summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--COPYRIGHT.txt568
-rw-r--r--SConstruct2
-rw-r--r--core/bind/core_bind.cpp42
-rw-r--r--core/io/stream_peer_tcp.cpp5
-rw-r--r--core/io/tcp_server.cpp7
-rw-r--r--core/io/tcp_server.h1
-rw-r--r--core/math/crypto_core.cpp11
-rw-r--r--core/math/crypto_core.h1
-rw-r--r--core/register_core_types.cpp2
-rw-r--r--core/script_language.h31
-rw-r--r--core/ustring.cpp21
-rw-r--r--core/ustring.h2
-rw-r--r--core/variant_call.cpp4
-rw-r--r--doc/classes/BakedLightmap.xml2
-rw-r--r--doc/classes/Spatial.xml1
-rw-r--r--doc/classes/TCP_Server.xml7
-rw-r--r--doc/classes/TileMap.xml12
-rw-r--r--doc/classes/Transform.xml4
-rw-r--r--doc/classes/Transform2D.xml3
-rw-r--r--drivers/gles2/shader_compiler_gles2.cpp2
-rw-r--r--drivers/pulseaudio/audio_driver_pulseaudio.cpp8
-rw-r--r--editor/animation_track_editor.cpp6
-rw-r--r--editor/animation_track_editor.h6
-rw-r--r--editor/code_editor.cpp60
-rw-r--r--editor/code_editor.h5
-rw-r--r--editor/editor_node.cpp9
-rw-r--r--editor/editor_node.h2
-rw-r--r--editor/filesystem_dock.cpp10
-rw-r--r--editor/plugins/path_editor_plugin.cpp8
-rw-r--r--editor/plugins/script_text_editor.cpp4
-rw-r--r--editor/plugins/script_text_editor.h6
-rw-r--r--editor/rename_dialog.cpp6
-rw-r--r--editor/rename_dialog.h7
-rw-r--r--editor/scene_tree_dock.cpp22
-rw-r--r--editor/script_create_dialog.cpp4
-rw-r--r--editor/script_create_dialog.h4
-rw-r--r--editor/spatial_editor_gizmos.cpp68
-rw-r--r--modules/gdnative/pluginscript/pluginscript_language.cpp5
-rw-r--r--modules/gdnative/pluginscript/pluginscript_language.h2
-rw-r--r--modules/gdscript/gdscript.h2
-rw-r--r--modules/gdscript/gdscript_editor.cpp219
-rw-r--r--modules/websocket/SCsub105
-rw-r--r--modules/websocket/doc_classes/WebSocketClient.xml2
-rw-r--r--modules/websocket/doc_classes/WebSocketServer.xml2
-rw-r--r--modules/websocket/lws_client.cpp248
-rw-r--r--modules/websocket/lws_helper.cpp157
-rw-r--r--modules/websocket/lws_helper.h111
-rw-r--r--modules/websocket/lws_peer.cpp270
-rw-r--r--modules/websocket/lws_server.cpp225
-rw-r--r--modules/websocket/register_types.cpp11
-rw-r--r--modules/websocket/wsl_client.cpp362
-rw-r--r--modules/websocket/wsl_client.h (renamed from modules/websocket/lws_client.h)44
-rw-r--r--modules/websocket/wsl_peer.cpp339
-rw-r--r--modules/websocket/wsl_peer.h (renamed from modules/websocket/lws_peer.h)72
-rw-r--r--modules/websocket/wsl_server.cpp281
-rw-r--r--modules/websocket/wsl_server.h (renamed from modules/websocket/lws_server.h)52
-rw-r--r--platform/haiku/detect.py4
-rw-r--r--platform/server/detect.py4
-rw-r--r--platform/windows/os_windows.cpp2
-rw-r--r--platform/x11/detect.py4
-rw-r--r--scene/gui/text_edit.cpp72
-rw-r--r--scene/gui/text_edit.h8
-rw-r--r--scene/resources/default_theme/background.pngbin854 -> 0 bytes
-rw-r--r--scene/resources/default_theme/base_green.pngbin86 -> 0 bytes
-rw-r--r--scene/resources/default_theme/default_theme.cpp2
-rw-r--r--scene/resources/default_theme/dosfont.pngbin683 -> 0 bytes
-rw-r--r--scene/resources/default_theme/frame_focus.pngbin200 -> 0 bytes
-rw-r--r--scene/resources/default_theme/full_panel_bg.pngbin207 -> 0 bytes
-rw-r--r--scene/resources/default_theme/icon_play.pngbin122 -> 0 bytes
-rw-r--r--scene/resources/default_theme/icon_stop.pngbin87 -> 0 bytes
-rw-r--r--scene/resources/default_theme/line_edit_focus.pngbin365 -> 0 bytes
-rw-r--r--scene/resources/default_theme/logo.pngbin6676 -> 0 bytes
-rw-r--r--scene/resources/default_theme/option_button_focus.pngbin416 -> 0 bytes
-rw-r--r--scene/resources/default_theme/popup_checked.pngbin143 -> 0 bytes
-rw-r--r--scene/resources/default_theme/popup_hover.pngbin145 -> 0 bytes
-rw-r--r--scene/resources/default_theme/popup_unchecked.pngbin98 -> 0 bytes
-rw-r--r--scene/resources/default_theme/reference_border.pngbin132 -> 0 bytes
-rw-r--r--scene/resources/default_theme/scroll_button_down.pngbin170 -> 0 bytes
-rw-r--r--scene/resources/default_theme/scroll_button_down_hl.pngbin170 -> 0 bytes
-rw-r--r--scene/resources/default_theme/scroll_button_up.pngbin173 -> 0 bytes
-rw-r--r--scene/resources/default_theme/scroll_button_up_hl.pngbin173 -> 0 bytes
-rw-r--r--scene/resources/default_theme/theme_data.h88
-rw-r--r--scene/resources/default_theme/tool_button_pressed.pngbin864 -> 0 bytes
-rw-r--r--scene/resources/default_theme/tree_bg_focus.pngbin696 -> 0 bytes
-rw-r--r--scene/resources/default_theme/tree_cursor.pngbin434 -> 0 bytes
-rw-r--r--scene/resources/default_theme/tree_cursor_unfocus.pngbin369 -> 0 bytes
-rw-r--r--servers/visual/visual_server_canvas.cpp17
-rw-r--r--servers/visual/visual_server_canvas.h1
-rw-r--r--thirdparty/README.md35
-rw-r--r--thirdparty/libwebsockets/LICENSE556
-rw-r--r--thirdparty/libwebsockets/core/alloc.c92
-rw-r--r--thirdparty/libwebsockets/core/context.c1962
-rw-r--r--thirdparty/libwebsockets/core/libwebsockets.c3479
-rw-r--r--thirdparty/libwebsockets/core/output.c320
-rw-r--r--thirdparty/libwebsockets/core/pollfd.c616
-rw-r--r--thirdparty/libwebsockets/core/private.h1770
-rw-r--r--thirdparty/libwebsockets/core/service.c987
-rw-r--r--thirdparty/libwebsockets/event-libs/poll/poll.c43
-rw-r--r--thirdparty/libwebsockets/event-libs/poll/private.h23
-rw-r--r--thirdparty/libwebsockets/event-libs/private.h74
-rw-r--r--thirdparty/libwebsockets/ipv6_fixes.diff32
-rw-r--r--thirdparty/libwebsockets/libwebsockets.h7346
-rw-r--r--thirdparty/libwebsockets/lws_config.h195
-rw-r--r--thirdparty/libwebsockets/lws_config_private.h145
-rw-r--r--thirdparty/libwebsockets/misc/base64-decode.c242
-rw-r--r--thirdparty/libwebsockets/misc/getifaddrs.c270
-rw-r--r--thirdparty/libwebsockets/misc/getifaddrs.h80
-rw-r--r--thirdparty/libwebsockets/misc/lejp.c753
-rw-r--r--thirdparty/libwebsockets/misc/sha-1.c300
-rw-r--r--thirdparty/libwebsockets/plat/lws-plat-unix.c982
-rw-r--r--thirdparty/libwebsockets/plat/lws-plat-win.c852
-rw-r--r--thirdparty/libwebsockets/roles/h1/ops-h1.c701
-rw-r--r--thirdparty/libwebsockets/roles/h1/private.h27
-rw-r--r--thirdparty/libwebsockets/roles/http/client/client-handshake.c1284
-rw-r--r--thirdparty/libwebsockets/roles/http/client/client.c1243
-rw-r--r--thirdparty/libwebsockets/roles/http/header.c421
-rw-r--r--thirdparty/libwebsockets/roles/http/lextable-strings.h108
-rw-r--r--thirdparty/libwebsockets/roles/http/lextable.h838
-rw-r--r--thirdparty/libwebsockets/roles/http/private.h258
-rw-r--r--thirdparty/libwebsockets/roles/http/server/access-log.c182
-rw-r--r--thirdparty/libwebsockets/roles/http/server/fops-zip.c668
-rw-r--r--thirdparty/libwebsockets/roles/http/server/lejp-conf.c993
-rw-r--r--thirdparty/libwebsockets/roles/http/server/parsers.c1137
-rw-r--r--thirdparty/libwebsockets/roles/http/server/server.c2765
-rw-r--r--thirdparty/libwebsockets/roles/listen/ops-listen.c177
-rw-r--r--thirdparty/libwebsockets/roles/pipe/ops-pipe.c81
-rw-r--r--thirdparty/libwebsockets/roles/private.h282
-rw-r--r--thirdparty/libwebsockets/roles/raw/ops-raw.c223
-rw-r--r--thirdparty/libwebsockets/roles/ws/client-parser-ws.c605
-rw-r--r--thirdparty/libwebsockets/roles/ws/client-ws.c629
-rw-r--r--thirdparty/libwebsockets/roles/ws/ops-ws.c1994
-rw-r--r--thirdparty/libwebsockets/roles/ws/private.h164
-rw-r--r--thirdparty/libwebsockets/roles/ws/server-ws.c836
-rw-r--r--thirdparty/libwebsockets/tls/mbedtls/lws-genhash.c202
-rw-r--r--thirdparty/libwebsockets/tls/mbedtls/lws-genrsa.c329
-rw-r--r--thirdparty/libwebsockets/tls/mbedtls/mbedtls-client.c240
-rw-r--r--thirdparty/libwebsockets/tls/mbedtls/mbedtls-server.c694
-rw-r--r--thirdparty/libwebsockets/tls/mbedtls/ssl.c518
-rw-r--r--thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl3.h44
-rw-r--r--thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_cert.h55
-rw-r--r--thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_code.h124
-rw-r--r--thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_dbg.h190
-rw-r--r--thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_lib.h30
-rw-r--r--thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_methods.h121
-rw-r--r--thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_pkey.h86
-rw-r--r--thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_stack.h52
-rw-r--r--thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_types.h303
-rw-r--r--thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_x509.h110
-rw-r--r--thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/tls1.h58
-rw-r--r--thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/x509_vfy.h116
-rwxr-xr-xthirdparty/libwebsockets/tls/mbedtls/wrapper/include/openssl/ssl.h1833
-rw-r--r--thirdparty/libwebsockets/tls/mbedtls/wrapper/include/platform/ssl_pm.h61
-rw-r--r--thirdparty/libwebsockets/tls/mbedtls/wrapper/include/platform/ssl_port.h46
-rw-r--r--thirdparty/libwebsockets/tls/mbedtls/wrapper/library/ssl_cert.c87
-rw-r--r--thirdparty/libwebsockets/tls/mbedtls/wrapper/library/ssl_lib.c1736
-rw-r--r--thirdparty/libwebsockets/tls/mbedtls/wrapper/library/ssl_methods.c81
-rw-r--r--thirdparty/libwebsockets/tls/mbedtls/wrapper/library/ssl_pkey.c239
-rw-r--r--thirdparty/libwebsockets/tls/mbedtls/wrapper/library/ssl_stack.c74
-rw-r--r--thirdparty/libwebsockets/tls/mbedtls/wrapper/library/ssl_x509.c354
-rwxr-xr-xthirdparty/libwebsockets/tls/mbedtls/wrapper/platform/ssl_pm.c907
-rw-r--r--thirdparty/libwebsockets/tls/mbedtls/wrapper/platform/ssl_port.c29
-rw-r--r--thirdparty/libwebsockets/tls/private.h281
-rw-r--r--thirdparty/libwebsockets/tls/tls-client.c150
-rw-r--r--thirdparty/libwebsockets/tls/tls-server.c382
-rw-r--r--thirdparty/libwebsockets/tls/tls.c522
-rw-r--r--thirdparty/libwebsockets/uwp_fixes.diff47
-rw-r--r--thirdparty/libwebsockets/win32helpers/getopt.c153
-rw-r--r--thirdparty/libwebsockets/win32helpers/getopt.h33
-rw-r--r--thirdparty/libwebsockets/win32helpers/getopt_long.c240
-rw-r--r--thirdparty/libwebsockets/win32helpers/gettimeofday.c36
-rw-r--r--thirdparty/libwebsockets/win32helpers/gettimeofday.h27
-rw-r--r--thirdparty/wslay/COPYING22
-rw-r--r--thirdparty/wslay/includes/config.h8
-rw-r--r--thirdparty/wslay/includes/wslay/wslay.h778
-rw-r--r--thirdparty/wslay/includes/wslay/wslayver.h31
-rw-r--r--thirdparty/wslay/msvcfix.diff17
-rw-r--r--thirdparty/wslay/wslay_event.c1027
-rw-r--r--thirdparty/wslay/wslay_event.h142
-rw-r--r--thirdparty/wslay/wslay_frame.c340
-rw-r--r--thirdparty/wslay/wslay_frame.h76
-rw-r--r--thirdparty/wslay/wslay_net.c36
-rw-r--r--thirdparty/wslay/wslay_net.h54
-rw-r--r--thirdparty/wslay/wslay_queue.c117
-rw-r--r--thirdparty/wslay/wslay_queue.h53
-rw-r--r--thirdparty/wslay/wslay_stack.c86
-rw-r--r--thirdparty/wslay/wslay_stack.h50
186 files changed, 4493 insertions, 49378 deletions
diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt
index 1759c935b8..326581a492 100644
--- a/COPYRIGHT.txt
+++ b/COPYRIGHT.txt
@@ -228,11 +228,6 @@ Comment: WebP codec
Copyright: 2010, Google Inc.
License: BSD-3-clause
-Files: ./thirdparty/libwebsockets/
-Comment: libwebsockets
-Copyright: 2010-2018, Andy Green
-License: LGPL-2.1+SLE (libwebsockets)
-
Files: ./thirdparty/mbedtls/
Comment: Mbed TLS
Copyright: 2006-2018, Arm Limited (or its affiliates)
@@ -366,6 +361,11 @@ Copyright: 2011, Khaled Mamou
2003-2009, Erwin Coumans
License: BSD-3-clause
+Files: ./thirdparty/wslay/
+Comment: Wslay
+Copyright: 2011-2015, Tatsuhiro Tsujikawa
+License: Expat
+
Files: ./thirdparty/xatlas/
Comment: xatlas
Copyright: 2018, Jonathan Young
@@ -1052,564 +1052,6 @@ License: FTL
Robert Wilhelm <robert.wilhelm@freetype.org>
Werner Lemberg <werner.lemberg@freetype.org>
-License: LGPL-2.1+SLE (libwebsockets)
- Libwebsockets and included programs are provided under the terms of the GNU
- Library General Public License (LGPL) 2.1, with the following exceptions:
- .
- 1) Any reference, whether in these modifications or in the GNU
- Library General Public License 2.1, to this License, these terms, the
- GNU Lesser Public License, GNU Library General Public License, LGPL, or
- any similar reference shall refer to the GNU Library General Public
- License 2.1 as modified by these paragraphs 1) through 4).
- .
- 2) Static linking of programs with the libwebsockets library does not
- constitute a derivative work and does not require the author to provide
- source code for the program, use the shared libwebsockets libraries, or
- link their program against a user-supplied version of libwebsockets.
- .
- If you link the program to a modified version of libwebsockets, then the
- changes to libwebsockets must be provided under the terms of the LGPL in
- sections 1, 2, and 4.
- .
- 3) You do not have to provide a copy of the libwebsockets license with
- programs that are linked to the libwebsockets library, nor do you have to
- identify the libwebsockets license in your program or documentation as
- required by section 6 of the LGPL.
- .
- However, programs must still identify their use of libwebsockets. The
- following example statement can be included in user documentation to
- satisfy this requirement:
- .
- "[program] is based in part on the work of the libwebsockets project
- (https://libwebsockets.org)"
- .
- 4) Some sources included have their own, more liberal licenses, or options
- to get original sources with the liberal terms.
- .
- Original liberal license retained
- .
- - lib/misc/sha-1.c - 3-clause BSD license retained, link to original
- - win32port/zlib - ZLIB license (see zlib.h)
- - lib/tls/mbedtls/wrapper - Apache 2.0 (only built if linked against mbedtls)
- .
- Relicensed to libwebsocket license
- .
- - lib/misc/base64-decode.c - relicensed to LGPL2.1+SLE, link to original
- - lib/misc/daemonize.c - relicensed from Public Domain to LGPL2.1+SLE,
- link to original Public Domain version
- .
- Public Domain (CC-zero) to simplify reuse
- .
- - test-apps/*.c
- - test-apps/*.h
- - minimal-examples/*
- - lwsws/*
- .
- ------ end of exceptions
- .
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 2.1, February 1999
- .
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
- .
- [This is the first released version of the Lesser GPL. It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
- .
- Preamble
- .
- The licenses for most software are designed to take away your
- freedom to share and change it. By contrast, the GNU General Public
- Licenses are intended to guarantee your freedom to share and change
- free software--to make sure the software is free for all its users.
- .
- This license, the Lesser General Public License, applies to some
- specially designated software packages--typically libraries--of the
- Free Software Foundation and other authors who decide to use it. You
- can use it too, but we suggest you first think carefully about whether
- this license or the ordinary General Public License is the better
- strategy to use in any particular case, based on the explanations below.
- .
- When we speak of free software, we are referring to freedom of use,
- not price. Our General Public Licenses are designed to make sure that
- you have the freedom to distribute copies of free software (and charge
- for this service if you wish); that you receive source code or can get
- it if you want it; that you can change the software and use pieces of
- it in new free programs; and that you are informed that you can do
- these things.
- .
- To protect your rights, we need to make restrictions that forbid
- distributors to deny you these rights or to ask you to surrender these
- rights. These restrictions translate to certain responsibilities for
- you if you distribute copies of the library or if you modify it.
- .
- For example, if you distribute copies of the library, whether gratis
- or for a fee, you must give the recipients all the rights that we gave
- you. You must make sure that they, too, receive or can get the source
- code. If you link other code with the library, you must provide
- complete object files to the recipients, so that they can relink them
- with the library after making changes to the library and recompiling
- it. And you must show them these terms so they know their rights.
- .
- We protect your rights with a two-step method: (1) we copyright the
- library, and (2) we offer you this license, which gives you legal
- permission to copy, distribute and/or modify the library.
- .
- To protect each distributor, we want to make it very clear that
- there is no warranty for the free library. Also, if the library is
- modified by someone else and passed on, the recipients should know
- that what they have is not the original version, so that the original
- author's reputation will not be affected by problems that might be
- introduced by others.
- .
- Finally, software patents pose a constant threat to the existence of
- any free program. We wish to make sure that a company cannot
- effectively restrict the users of a free program by obtaining a
- restrictive license from a patent holder. Therefore, we insist that
- any patent license obtained for a version of the library must be
- consistent with the full freedom of use specified in this license.
- .
- Most GNU software, including some libraries, is covered by the
- ordinary GNU General Public License. This license, the GNU Lesser
- General Public License, applies to certain designated libraries, and
- is quite different from the ordinary General Public License. We use
- this license for certain libraries in order to permit linking those
- libraries into non-free programs.
- .
- When a program is linked with a library, whether statically or using
- a shared library, the combination of the two is legally speaking a
- combined work, a derivative of the original library. The ordinary
- General Public License therefore permits such linking only if the
- entire combination fits its criteria of freedom. The Lesser General
- Public License permits more lax criteria for linking other code with
- the library.
- .
- We call this license the "Lesser" General Public License because it
- does Less to protect the user's freedom than the ordinary General
- Public License. It also provides other free software developers Less
- of an advantage over competing non-free programs. These disadvantages
- are the reason we use the ordinary General Public License for many
- libraries. However, the Lesser license provides advantages in certain
- special circumstances.
- .
- For example, on rare occasions, there may be a special need to
- encourage the widest possible use of a certain library, so that it becomes
- a de-facto standard. To achieve this, non-free programs must be
- allowed to use the library. A more frequent case is that a free
- library does the same job as widely used non-free libraries. In this
- case, there is little to gain by limiting the free library to free
- software only, so we use the Lesser General Public License.
- .
- In other cases, permission to use a particular library in non-free
- programs enables a greater number of people to use a large body of
- free software. For example, permission to use the GNU C Library in
- non-free programs enables many more people to use the whole GNU
- operating system, as well as its variant, the GNU/Linux operating
- system.
- .
- Although the Lesser General Public License is Less protective of the
- users' freedom, it does ensure that the user of a program that is
- linked with the Library has the freedom and the wherewithal to run
- that program using a modified version of the Library.
- .
- The precise terms and conditions for copying, distribution and
- modification follow. Pay close attention to the difference between a
- "work based on the library" and a "work that uses the library". The
- former contains code derived from the library, whereas the latter must
- be combined with the library in order to run.
- .
- GNU LESSER GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
- .
- 0. This License Agreement applies to any software library or other
- program which contains a notice placed by the copyright holder or
- other authorized party saying it may be distributed under the terms of
- this Lesser General Public License (also called "this License").
- Each licensee is addressed as "you".
- .
- A "library" means a collection of software functions and/or data
- prepared so as to be conveniently linked with application programs
- (which use some of those functions and data) to form executables.
- .
- The "Library", below, refers to any such software library or work
- which has been distributed under these terms. A "work based on the
- Library" means either the Library or any derivative work under
- copyright law: that is to say, a work containing the Library or a
- portion of it, either verbatim or with modifications and/or translated
- straightforwardly into another language. (Hereinafter, translation is
- included without limitation in the term "modification".)
- .
- "Source code" for a work means the preferred form of the work for
- making modifications to it. For a library, complete source code means
- all the source code for all modules it contains, plus any associated
- interface definition files, plus the scripts used to control compilation
- and installation of the library.
- .
- Activities other than copying, distribution and modification are not
- covered by this License; they are outside its scope. The act of
- running a program using the Library is not restricted, and output from
- such a program is covered only if its contents constitute a work based
- on the Library (independent of the use of the Library in a tool for
- writing it). Whether that is true depends on what the Library does
- and what the program that uses the Library does.
- .
- 1. You may copy and distribute verbatim copies of the Library's
- complete source code as you receive it, in any medium, provided that
- you conspicuously and appropriately publish on each copy an
- appropriate copyright notice and disclaimer of warranty; keep intact
- all the notices that refer to this License and to the absence of any
- warranty; and distribute a copy of this License along with the
- Library.
- .
- You may charge a fee for the physical act of transferring a copy,
- and you may at your option offer warranty protection in exchange for a
- fee.
- .
- 2. You may modify your copy or copies of the Library or any portion
- of it, thus forming a work based on the Library, and copy and
- distribute such modifications or work under the terms of Section 1
- above, provided that you also meet all of these conditions:
- .
- a) The modified work must itself be a software library.
- .
- b) You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
- .
- c) You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
- .
- d) If a facility in the modified Library refers to a function or a
- table of data to be supplied by an application program that uses
- the facility, other than as an argument passed when the facility
- is invoked, then you must make a good faith effort to ensure that,
- in the event an application does not supply such function or
- table, the facility still operates, and performs whatever part of
- its purpose remains meaningful.
- .
- (For example, a function in a library to compute square roots has
- a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function must
- be optional: if the application does not supply it, the square
- root function must still compute square roots.)
- .
- These requirements apply to the modified work as a whole. If
- identifiable sections of that work are not derived from the Library,
- and can be reasonably considered independent and separate works in
- themselves, then this License, and its terms, do not apply to those
- sections when you distribute them as separate works. But when you
- distribute the same sections as part of a whole which is a work based
- on the Library, the distribution of the whole must be on the terms of
- this License, whose permissions for other licensees extend to the
- entire whole, and thus to each and every part regardless of who wrote
- it.
- .
- Thus, it is not the intent of this section to claim rights or contest
- your rights to work written entirely by you; rather, the intent is to
- exercise the right to control the distribution of derivative or
- collective works based on the Library.
- .
- In addition, mere aggregation of another work not based on the Library
- with the Library (or with a work based on the Library) on a volume of
- a storage or distribution medium does not bring the other work under
- the scope of this License.
- .
- 3. You may opt to apply the terms of the ordinary GNU General Public
- License instead of this License to a given copy of the Library. To do
- this, you must alter all the notices that refer to this License, so
- that they refer to the ordinary GNU General Public License, version 2,
- instead of to this License. (If a newer version than version 2 of the
- ordinary GNU General Public License has appeared, then you can specify
- that version instead if you wish.) Do not make any other change in
- these notices.
- .
- Once this change is made in a given copy, it is irreversible for
- that copy, so the ordinary GNU General Public License applies to all
- subsequent copies and derivative works made from that copy.
- .
- This option is useful when you wish to copy part of the code of
- the Library into a program that is not a library.
- .
- 4. You may copy and distribute the Library (or a portion or
- derivative of it, under Section 2) in object code or executable form
- under the terms of Sections 1 and 2 above provided that you accompany
- it with the complete corresponding machine-readable source code, which
- must be distributed under the terms of Sections 1 and 2 above on a
- medium customarily used for software interchange.
- .
- If distribution of object code is made by offering access to copy
- from a designated place, then offering equivalent access to copy the
- source code from the same place satisfies the requirement to
- distribute the source code, even though third parties are not
- compelled to copy the source along with the object code.
- .
- 5. A program that contains no derivative of any portion of the
- Library, but is designed to work with the Library by being compiled or
- linked with it, is called a "work that uses the Library". Such a
- work, in isolation, is not a derivative work of the Library, and
- therefore falls outside the scope of this License.
- .
- However, linking a "work that uses the Library" with the Library
- creates an executable that is a derivative of the Library (because it
- contains portions of the Library), rather than a "work that uses the
- library". The executable is therefore covered by this License.
- Section 6 states terms for distribution of such executables.
- .
- When a "work that uses the Library" uses material from a header file
- that is part of the Library, the object code for the work may be a
- derivative work of the Library even though the source code is not.
- Whether this is true is especially significant if the work can be
- linked without the Library, or if the work is itself a library. The
- threshold for this to be true is not precisely defined by law.
- .
- If such an object file uses only numerical parameters, data
- structure layouts and accessors, and small macros and small inline
- functions (ten lines or less in length), then the use of the object
- file is unrestricted, regardless of whether it is legally a derivative
- work. (Executables containing this object code plus portions of the
- Library will still fall under Section 6.)
- .
- Otherwise, if the work is a derivative of the Library, you may
- distribute the object code for the work under the terms of Section 6.
- Any executables containing that work also fall under Section 6,
- whether or not they are linked directly with the Library itself.
- .
- 6. As an exception to the Sections above, you may also combine or
- link a "work that uses the Library" with the Library to produce a
- work containing portions of the Library, and distribute that work
- under terms of your choice, provided that the terms permit
- modification of the work for the customer's own use and reverse
- engineering for debugging such modifications.
- .
- You must give prominent notice with each copy of the work that the
- Library is used in it and that the Library and its use are covered by
- this License. You must supply a copy of this License. If the work
- during execution displays copyright notices, you must include the
- copyright notice for the Library among them, as well as a reference
- directing the user to the copy of this License. Also, you must do one
- of these things:
- .
- a) Accompany the work with the complete corresponding
- machine-readable source code for the Library including whatever
- changes were used in the work (which must be distributed under
- Sections 1 and 2 above); and, if the work is an executable linked
- with the Library, with the complete machine-readable "work that
- uses the Library", as object code and/or source code, so that the
- user can modify the Library and then relink to produce a modified
- executable containing the modified Library. (It is understood
- that the user who changes the contents of definitions files in the
- Library will not necessarily be able to recompile the application
- to use the modified definitions.)
- .
- b) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (1) uses at run time a
- copy of the library already present on the user's computer system,
- rather than copying library functions into the executable, and (2)
- will operate properly with a modified version of the library, if
- the user installs one, as long as the modified version is
- interface-compatible with the version that the work was made with.
- .
- c) Accompany the work with a written offer, valid for at
- least three years, to give the same user the materials
- specified in Subsection 6a, above, for a charge no more
- than the cost of performing this distribution.
- .
- d) If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the above
- specified materials from the same place.
- .
- e) Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
- .
- For an executable, the required form of the "work that uses the
- Library" must include any data and utility programs needed for
- reproducing the executable from it. However, as a special exception,
- the materials to be distributed need not include anything that is
- normally distributed (in either source or binary form) with the major
- components (compiler, kernel, and so on) of the operating system on
- which the executable runs, unless that component itself accompanies
- the executable.
- .
- It may happen that this requirement contradicts the license
- restrictions of other proprietary libraries that do not normally
- accompany the operating system. Such a contradiction means you cannot
- use both them and the Library together in an executable that you
- distribute.
- .
- 7. You may place library facilities that are a work based on the
- Library side-by-side in a single library together with other library
- facilities not covered by this License, and distribute such a combined
- library, provided that the separate distribution of the work based on
- the Library and of the other library facilities is otherwise
- permitted, and provided that you do these two things:
- .
- a) Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- Sections above.
- .
- b) Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same work.
- .
- 8. You may not copy, modify, sublicense, link with, or distribute
- the Library except as expressly provided under this License. Any
- attempt otherwise to copy, modify, sublicense, link with, or
- distribute the Library is void, and will automatically terminate your
- rights under this License. However, parties who have received copies,
- or rights, from you under this License will not have their licenses
- terminated so long as such parties remain in full compliance.
- .
- 9. You are not required to accept this License, since you have not
- signed it. However, nothing else grants you permission to modify or
- distribute the Library or its derivative works. These actions are
- prohibited by law if you do not accept this License. Therefore, by
- modifying or distributing the Library (or any work based on the
- Library), you indicate your acceptance of this License to do so, and
- all its terms and conditions for copying, distributing or modifying
- the Library or works based on it.
- .
- 10. Each time you redistribute the Library (or any work based on the
- Library), the recipient automatically receives a license from the
- original licensor to copy, distribute, link with or modify the Library
- subject to these terms and conditions. You may not impose any further
- restrictions on the recipients' exercise of the rights granted herein.
- You are not responsible for enforcing compliance by third parties with
- this License.
- .
- 11. If, as a consequence of a court judgment or allegation of patent
- infringement or for any other reason (not limited to patent issues),
- conditions are imposed on you (whether by court order, agreement or
- otherwise) that contradict the conditions of this License, they do not
- excuse you from the conditions of this License. If you cannot
- distribute so as to satisfy simultaneously your obligations under this
- License and any other pertinent obligations, then as a consequence you
- may not distribute the Library at all. For example, if a patent
- license would not permit royalty-free redistribution of the Library by
- all those who receive copies directly or indirectly through you, then
- the only way you could satisfy both it and this License would be to
- refrain entirely from distribution of the Library.
- .
- If any portion of this section is held invalid or unenforceable under any
- particular circumstance, the balance of the section is intended to apply,
- and the section as a whole is intended to apply in other circumstances.
- .
- It is not the purpose of this section to induce you to infringe any
- patents or other property right claims or to contest validity of any
- such claims; this section has the sole purpose of protecting the
- integrity of the free software distribution system which is
- implemented by public license practices. Many people have made
- generous contributions to the wide range of software distributed
- through that system in reliance on consistent application of that
- system; it is up to the author/donor to decide if he or she is willing
- to distribute software through any other system and a licensee cannot
- impose that choice.
- .
- This section is intended to make thoroughly clear what is believed to
- be a consequence of the rest of this License.
- .
- 12. If the distribution and/or use of the Library is restricted in
- certain countries either by patents or by copyrighted interfaces, the
- original copyright holder who places the Library under this License may add
- an explicit geographical distribution limitation excluding those countries,
- so that distribution is permitted only in or among countries not thus
- excluded. In such case, this License incorporates the limitation as if
- written in the body of this License.
- .
- 13. The Free Software Foundation may publish revised and/or new
- versions of the Lesser General Public License from time to time.
- Such new versions will be similar in spirit to the present version,
- but may differ in detail to address new problems or concerns.
- .
- Each version is given a distinguishing version number. If the Library
- specifies a version number of this License which applies to it and
- "any later version", you have the option of following the terms and
- conditions either of that version or of any later version published by
- the Free Software Foundation. If the Library does not specify a
- license version number, you may choose any version ever published by
- the Free Software Foundation.
- .
- 14. If you wish to incorporate parts of the Library into other free
- programs whose distribution conditions are incompatible with these,
- write to the author to ask for permission. For software which is
- copyrighted by the Free Software Foundation, write to the Free
- Software Foundation; we sometimes make exceptions for this. Our
- decision will be guided by the two goals of preserving the free status
- of all derivatives of our free software and of promoting the sharing
- and reuse of software generally.
- .
- NO WARRANTY
- .
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
- WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
- EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
- OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
- KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
- LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
- THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
- .
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
- WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
- AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
- FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
- CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
- LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
- RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
- FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
- SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- DAMAGES.
- .
- END OF TERMS AND CONDITIONS
- .
- How to Apply These Terms to Your New Libraries
- .
- If you develop a new library, and you want it to be of the greatest
- possible use to the public, we recommend making it free software that
- everyone can redistribute and change. You can do so by permitting
- redistribution under these terms (or, alternatively, under the terms of the
- ordinary General Public License).
- .
- To apply these terms, attach the following notices to the library. It is
- safest to attach them to the start of each source file to most effectively
- convey the exclusion of warranty; and each file should have at least the
- "copyright" line and a pointer to where the full notice is found.
- .
- <one line to give the library's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
- .
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
- .
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
- .
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- .
- Also add information on how to contact you by electronic and paper mail.
- .
- You should also get your employer (if you work as a programmer) or your
- school, if any, to sign a "copyright disclaimer" for the library, if
- necessary. Here is a sample; alter the names:
- .
- Yoyodyne, Inc., hereby disclaims all copyright interest in the
- library `Frob' (a library for tweaking knobs) written by James Random Hacker.
- .
- <signature of Ty Coon>, 1 April 1990
- Ty Coon, President of Vice
- .
- That's all there is to it!
-
License: MPL-2.0
Mozilla Public License Version 2.0
==================================
diff --git a/SConstruct b/SConstruct
index c2524a4a4d..7b0c644aea 100644
--- a/SConstruct
+++ b/SConstruct
@@ -145,7 +145,7 @@ opts.Add(BoolVariable('builtin_libtheora', "Use the built-in libtheora library",
opts.Add(BoolVariable('builtin_libvorbis', "Use the built-in libvorbis library", True))
opts.Add(BoolVariable('builtin_libvpx', "Use the built-in libvpx library", True))
opts.Add(BoolVariable('builtin_libwebp', "Use the built-in libwebp library", True))
-opts.Add(BoolVariable('builtin_libwebsockets', "Use the built-in libwebsockets library", True))
+opts.Add(BoolVariable('builtin_wslay', "Use the built-in wslay library", True))
opts.Add(BoolVariable('builtin_mbedtls', "Use the built-in mbedTLS library", True))
opts.Add(BoolVariable('builtin_miniupnpc', "Use the built-in miniupnpc library", True))
opts.Add(BoolVariable('builtin_opus', "Use the built-in Opus library", True))
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index 382ab31f6d..1bf3425d50 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -2432,16 +2432,8 @@ String _Marshalls::variant_to_base64(const Variant &p_var, bool p_full_objects)
err = encode_variant(p_var, &w[0], len, p_full_objects);
ERR_FAIL_COND_V(err != OK, "");
- int b64len = len / 3 * 4 + 4 + 1;
- PoolVector<uint8_t> b64buff;
- b64buff.resize(b64len);
- PoolVector<uint8_t>::Write w64 = b64buff.write();
-
- size_t strlen = 0;
- ERR_FAIL_COND_V(CryptoCore::b64_encode(&w64[0], b64len, &strlen, &w[0], len) != OK, String());
- //OS::get_singleton()->print("len is %i, vector size is %i\n", b64len, strlen);
- w64[strlen] = 0;
- String ret = (char *)&w64[0];
+ String ret = CryptoCore::b64_encode_str(&w[0], len);
+ ERR_FAIL_COND_V(ret == "", ret);
return ret;
};
@@ -2467,19 +2459,8 @@ Variant _Marshalls::base64_to_variant(const String &p_str, bool p_allow_objects)
String _Marshalls::raw_to_base64(const PoolVector<uint8_t> &p_arr) {
- int len = p_arr.size();
- PoolVector<uint8_t>::Read r = p_arr.read();
-
- int b64len = len / 3 * 4 + 4 + 1;
- PoolVector<uint8_t> b64buff;
- b64buff.resize(b64len);
- PoolVector<uint8_t>::Write w64 = b64buff.write();
-
- size_t strlen = 0;
- ERR_FAIL_COND_V(CryptoCore::b64_encode(&w64[0], b64len, &strlen, &r[0], len) != OK, String());
- w64[strlen] = 0;
- String ret = (char *)&w64[0];
-
+ String ret = CryptoCore::b64_encode_str(p_arr.read().ptr(), p_arr.size());
+ ERR_FAIL_COND_V(ret == "", ret);
return ret;
};
@@ -2504,19 +2485,8 @@ PoolVector<uint8_t> _Marshalls::base64_to_raw(const String &p_str) {
String _Marshalls::utf8_to_base64(const String &p_str) {
CharString cstr = p_str.utf8();
- int len = cstr.length();
-
- int b64len = len / 3 * 4 + 4 + 1;
- PoolVector<uint8_t> b64buff;
- b64buff.resize(b64len);
- PoolVector<uint8_t>::Write w64 = b64buff.write();
-
- size_t strlen = 0;
- ERR_FAIL_COND_V(CryptoCore::b64_encode(&w64[0], b64len, &strlen, (unsigned char *)cstr.get_data(), len) != OK, String());
-
- w64[strlen] = 0;
- String ret = (char *)&w64[0];
-
+ String ret = CryptoCore::b64_encode_str((unsigned char *)cstr.get_data(), cstr.length());
+ ERR_FAIL_COND_V(ret == "", ret);
return ret;
};
diff --git a/core/io/stream_peer_tcp.cpp b/core/io/stream_peer_tcp.cpp
index bcdae343b8..a8dd263484 100644
--- a/core/io/stream_peer_tcp.cpp
+++ b/core/io/stream_peer_tcp.cpp
@@ -217,6 +217,11 @@ Error StreamPeerTCP::read(uint8_t *p_buffer, int p_bytes, int &r_received, bool
to_read -= read;
total_read += read;
+
+ if (!p_block) {
+ r_received = total_read;
+ return OK;
+ }
}
}
diff --git a/core/io/tcp_server.cpp b/core/io/tcp_server.cpp
index be87f47d50..a2756164bc 100644
--- a/core/io/tcp_server.cpp
+++ b/core/io/tcp_server.cpp
@@ -34,6 +34,7 @@ void TCP_Server::_bind_methods() {
ClassDB::bind_method(D_METHOD("listen", "port", "bind_address"), &TCP_Server::listen, DEFVAL("*"));
ClassDB::bind_method(D_METHOD("is_connection_available"), &TCP_Server::is_connection_available);
+ ClassDB::bind_method(D_METHOD("is_listening"), &TCP_Server::is_listening);
ClassDB::bind_method(D_METHOD("take_connection"), &TCP_Server::take_connection);
ClassDB::bind_method(D_METHOD("stop"), &TCP_Server::stop);
}
@@ -75,6 +76,12 @@ Error TCP_Server::listen(uint16_t p_port, const IP_Address &p_bind_address) {
return OK;
}
+bool TCP_Server::is_listening() const {
+ ERR_FAIL_COND_V(!_sock.is_valid(), false);
+
+ return _sock->is_open();
+}
+
bool TCP_Server::is_connection_available() const {
ERR_FAIL_COND_V(!_sock.is_valid(), false);
diff --git a/core/io/tcp_server.h b/core/io/tcp_server.h
index 538db175ad..ef64044599 100644
--- a/core/io/tcp_server.h
+++ b/core/io/tcp_server.h
@@ -50,6 +50,7 @@ protected:
public:
Error listen(uint16_t p_port, const IP_Address &p_bind_address = IP_Address("*"));
+ bool is_listening() const;
bool is_connection_available() const;
Ref<StreamPeerTCP> take_connection();
diff --git a/core/math/crypto_core.cpp b/core/math/crypto_core.cpp
index 6449d94db8..d7ba54e469 100644
--- a/core/math/crypto_core.cpp
+++ b/core/math/crypto_core.cpp
@@ -120,6 +120,17 @@ Error CryptoCore::AESContext::decrypt_ecb(const uint8_t p_src[16], uint8_t r_dst
}
// CryptoCore
+String CryptoCore::b64_encode_str(const uint8_t *p_src, int p_src_len) {
+ int b64len = p_src_len / 3 * 4 + 4 + 1;
+ PoolVector<uint8_t> b64buff;
+ b64buff.resize(b64len);
+ PoolVector<uint8_t>::Write w64 = b64buff.write();
+ size_t strlen = 0;
+ int ret = b64_encode(&w64[0], b64len, &strlen, p_src, p_src_len);
+ w64[strlen] = 0;
+ return ret ? String() : (const char *)&w64[0];
+}
+
Error CryptoCore::b64_encode(uint8_t *r_dst, int p_dst_len, size_t *r_len, const uint8_t *p_src, int p_src_len) {
int ret = mbedtls_base64_encode(r_dst, p_dst_len, r_len, p_src, p_src_len);
return ret ? FAILED : OK;
diff --git a/core/math/crypto_core.h b/core/math/crypto_core.h
index 1cb3c86e18..e28cb5a792 100644
--- a/core/math/crypto_core.h
+++ b/core/math/crypto_core.h
@@ -79,6 +79,7 @@ public:
Error decrypt_ecb(const uint8_t p_src[16], uint8_t r_dst[16]);
};
+ static String b64_encode_str(const uint8_t *p_src, int p_src_len);
static Error b64_encode(uint8_t *r_dst, int p_dst_len, size_t *r_len, const uint8_t *p_src, int p_src_len);
static Error b64_decode(uint8_t *r_dst, int p_dst_len, size_t *r_len, const uint8_t *p_src, int p_src_len);
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index af863dd385..11cd07042f 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -190,6 +190,8 @@ void register_core_types() {
ClassDB::register_class<JSONParseResult>();
+ ClassDB::register_virtual_class<ResourceImporter>();
+
ip = IP::create();
_geometry = memnew(_Geometry);
diff --git a/core/script_language.h b/core/script_language.h
index b0c60b4e90..87f103bb33 100644
--- a/core/script_language.h
+++ b/core/script_language.h
@@ -200,6 +200,35 @@ public:
virtual ~ScriptInstance();
};
+struct ScriptCodeCompletionOption {
+ enum Kind {
+ KIND_CLASS,
+ KIND_FUNCTION,
+ KIND_SIGNAL,
+ KIND_VARIABLE,
+ KIND_MEMBER,
+ KIND_ENUM,
+ KIND_CONSTANT,
+ KIND_NODE_PATH,
+ KIND_FILE_PATH,
+ KIND_PLAIN_TEXT,
+ };
+ Kind kind;
+ String display;
+ String insert_text;
+ RES icon;
+
+ ScriptCodeCompletionOption() {
+ kind = KIND_PLAIN_TEXT;
+ }
+
+ ScriptCodeCompletionOption(const String &p_text, Kind p_kind) {
+ display = p_text;
+ insert_text = p_text;
+ kind = p_kind;
+ }
+};
+
class ScriptCodeCompletionCache {
static ScriptCodeCompletionCache *singleton;
@@ -250,7 +279,7 @@ public:
virtual Error open_in_external_editor(const Ref<Script> &p_script, int p_line, int p_col) { return ERR_UNAVAILABLE; }
virtual bool overrides_external_editor() { return false; }
- virtual Error complete_code(const String &p_code, const String &p_path, Object *p_owner, List<String> *r_options, bool &r_force, String &r_call_hint) { return ERR_UNAVAILABLE; }
+ virtual Error complete_code(const String &p_code, const String &p_path, Object *p_owner, List<ScriptCodeCompletionOption> *r_options, bool &r_force, String &r_call_hint) { return ERR_UNAVAILABLE; }
struct LookupResult {
enum Type {
diff --git a/core/ustring.cpp b/core/ustring.cpp
index 2b312191e2..21ac304a1b 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -2257,6 +2257,13 @@ String String::md5_text() const {
return String::hex_encode_buffer(hash, 16);
}
+String String::sha1_text() const {
+ CharString cs = utf8();
+ unsigned char hash[20];
+ CryptoCore::sha1((unsigned char *)cs.ptr(), cs.length(), hash);
+ return String::hex_encode_buffer(hash, 20);
+}
+
String String::sha256_text() const {
CharString cs = utf8();
unsigned char hash[32];
@@ -2278,6 +2285,20 @@ Vector<uint8_t> String::md5_buffer() const {
return ret;
};
+Vector<uint8_t> String::sha1_buffer() const {
+ CharString cs = utf8();
+ unsigned char hash[20];
+ CryptoCore::sha1((unsigned char *)cs.ptr(), cs.length(), hash);
+
+ Vector<uint8_t> ret;
+ ret.resize(20);
+ for (int i = 0; i < 20; i++) {
+ ret.write[i] = hash[i];
+ }
+
+ return ret;
+}
+
Vector<uint8_t> String::sha256_buffer() const {
CharString cs = utf8();
unsigned char hash[32];
diff --git a/core/ustring.h b/core/ustring.h
index a32daabb91..8a52c53238 100644
--- a/core/ustring.h
+++ b/core/ustring.h
@@ -305,8 +305,10 @@ public:
uint32_t hash() const; /* hash the string */
uint64_t hash64() const; /* hash the string */
String md5_text() const;
+ String sha1_text() const;
String sha256_text() const;
Vector<uint8_t> md5_buffer() const;
+ Vector<uint8_t> sha1_buffer() const;
Vector<uint8_t> sha256_buffer() const;
_FORCE_INLINE_ bool empty() const { return length() == 0; }
diff --git a/core/variant_call.cpp b/core/variant_call.cpp
index 811008e7c8..4c3cbfa484 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -275,8 +275,10 @@ struct _VariantCall {
VCALL_LOCALMEM2(String, erase);
VCALL_LOCALMEM0R(String, hash);
VCALL_LOCALMEM0R(String, md5_text);
+ VCALL_LOCALMEM0R(String, sha1_text);
VCALL_LOCALMEM0R(String, sha256_text);
VCALL_LOCALMEM0R(String, md5_buffer);
+ VCALL_LOCALMEM0R(String, sha1_buffer);
VCALL_LOCALMEM0R(String, sha256_buffer);
VCALL_LOCALMEM0R(String, empty);
VCALL_LOCALMEM0R(String, is_abs_path);
@@ -1539,8 +1541,10 @@ void register_variant_methods() {
ADDFUNC2(STRING, NIL, String, erase, INT, "position", INT, "chars", varray());
ADDFUNC0R(STRING, INT, String, hash, varray());
ADDFUNC0R(STRING, STRING, String, md5_text, varray());
+ ADDFUNC0R(STRING, STRING, String, sha1_text, varray());
ADDFUNC0R(STRING, STRING, String, sha256_text, varray());
ADDFUNC0R(STRING, POOL_BYTE_ARRAY, String, md5_buffer, varray());
+ ADDFUNC0R(STRING, POOL_BYTE_ARRAY, String, sha1_buffer, varray());
ADDFUNC0R(STRING, POOL_BYTE_ARRAY, String, sha256_buffer, varray());
ADDFUNC0R(STRING, BOOL, String, empty, varray());
ADDFUNC0R(STRING, BOOL, String, is_abs_path, varray());
diff --git a/doc/classes/BakedLightmap.xml b/doc/classes/BakedLightmap.xml
index 571a6fde80..4baf3a6bb2 100644
--- a/doc/classes/BakedLightmap.xml
+++ b/doc/classes/BakedLightmap.xml
@@ -31,6 +31,8 @@
<member name="bake_cell_size" type="float" setter="set_bake_cell_size" getter="get_bake_cell_size" default="0.25">
Grid subdivision size for lightmapper calculation. The default value will work for most cases. Increase for better lighting on small details or if your scene is very large.
</member>
+ <member name="bake_default_texels_per_unit" type="float" setter="set_bake_default_texels_per_unit" getter="get_bake_default_texels_per_unit" default="20.0">
+ </member>
<member name="bake_energy" type="float" setter="set_energy" getter="get_energy" default="1.0">
</member>
<member name="bake_extents" type="Vector3" setter="set_extents" getter="get_extents" default="Vector3( 10, 10, 10 )">
diff --git a/doc/classes/Spatial.xml b/doc/classes/Spatial.xml
index 9f4118aa7b..09a5bf3b8f 100644
--- a/doc/classes/Spatial.xml
+++ b/doc/classes/Spatial.xml
@@ -274,6 +274,7 @@
</argument>
<description>
Changes the node's position by given offset [Vector3].
+ Note that the translation [code]offset[/code] is affected by the node's scale, so if scaled by e.g. [code](10, 1, 1)[/code], a translation by an offset of [code](2, 0, 0)[/code] would actually add 20 ([code]2 * 10[/code]) to the X coordinate.
</description>
</method>
<method name="translate_object_local">
diff --git a/doc/classes/TCP_Server.xml b/doc/classes/TCP_Server.xml
index 432d83f25b..cac3a0b082 100644
--- a/doc/classes/TCP_Server.xml
+++ b/doc/classes/TCP_Server.xml
@@ -16,6 +16,13 @@
Returns [code]true[/code] if a connection is available for taking.
</description>
</method>
+ <method name="is_listening" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ Returns [code]true[/code] if the server is currently listening for connections.
+ </description>
+ </method>
<method name="listen">
<return type="int" enum="Error">
</return>
diff --git a/doc/classes/TileMap.xml b/doc/classes/TileMap.xml
index a0111d3262..3f9c2e8647 100644
--- a/doc/classes/TileMap.xml
+++ b/doc/classes/TileMap.xml
@@ -274,12 +274,7 @@
<member name="cell_y_sort" type="bool" setter="set_y_sort_mode" getter="is_y_sort_mode_enabled" default="false">
If [code]true[/code], the TileMap's children will be drawn in order of their Y coordinate.
</member>
- <member name="compatibility_mode" type="bool" setter="set_compatibility_mode" getter="is_compatibility_mode_enabled">
- If [code]true[/code], the compatibility with the tilemaps made in Godot 3.1 or earlier is maintained (textures move when the tile origin changes and rotate if the texture size is not homogeneous). This mode presents problems when doing [code]flip_h[/code], [code]flip_v[/code] and [code]transpose[/code] tile operations on non-homogeneous isometric tiles (e.g. 2:1), in which the texture could not coincide with the collision, thus it is not recommended for isometric or non-square tiles.
- If [code]false[/code], the textures do not move when doing [code]flip_h[/code], [code]flip_v[/code] operations if no offset is used, nor when changing the tile origin.
- The compatibility mode doesn't work with the [member centered_textures] option, because displacing textures with the [member cell_tile_origin] option or in irregular tiles is not relevant when centering those textures.
- </member>
- <member name="centered_textures" type="bool" setter="set_centered_textures" getter="is_centered_textures_enabled">
+ <member name="centered_textures" type="bool" setter="set_centered_textures" getter="is_centered_textures_enabled" default="false">
If [code]true[/code], the textures will be centered in the middle of each tile. This is useful for certain isometric or top-down modes when textures are made larger or smaller than the tiles (e.g. to avoid flickering on tile edges). The offset is still applied, but from the center of the tile. If used, [member compatibility_mode] is ignored.
If [code]false[/code], the texture position start in the top-left corner unless [member compatibility_mode] is enabled.
</member>
@@ -300,6 +295,11 @@
</member>
<member name="collision_use_parent" type="bool" setter="set_collision_use_parent" getter="get_collision_use_parent" default="false">
</member>
+ <member name="compatibility_mode" type="bool" setter="set_compatibility_mode" getter="is_compatibility_mode_enabled" default="false">
+ If [code]true[/code], the compatibility with the tilemaps made in Godot 3.1 or earlier is maintained (textures move when the tile origin changes and rotate if the texture size is not homogeneous). This mode presents problems when doing [code]flip_h[/code], [code]flip_v[/code] and [code]transpose[/code] tile operations on non-homogeneous isometric tiles (e.g. 2:1), in which the texture could not coincide with the collision, thus it is not recommended for isometric or non-square tiles.
+ If [code]false[/code], the textures do not move when doing [code]flip_h[/code], [code]flip_v[/code] operations if no offset is used, nor when changing the tile origin.
+ The compatibility mode doesn't work with the [member centered_textures] option, because displacing textures with the [member cell_tile_origin] option or in irregular tiles is not relevant when centering those textures.
+ </member>
<member name="mode" type="int" setter="set_mode" getter="get_mode" enum="TileMap.Mode" default="0">
The TileMap orientation mode. See [enum Mode] for possible values.
</member>
diff --git a/doc/classes/Transform.xml b/doc/classes/Transform.xml
index 80a393dcee..9916d25af5 100644
--- a/doc/classes/Transform.xml
+++ b/doc/classes/Transform.xml
@@ -167,12 +167,16 @@
</members>
<constants>
<constant name="IDENTITY" value="Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )">
+ [Transform] with no translation, rotation or scaling applied. When applied to other data structures, [constant IDENTITY] performs no transformation.
</constant>
<constant name="FLIP_X" value="Transform( -1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )">
+ [Transform] with mirroring applied perpendicular to the YZ plane.
</constant>
<constant name="FLIP_Y" value="Transform( 1, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0 )">
+ [Transform] with mirroring applied perpendicular to the XZ plane.
</constant>
<constant name="FLIP_Z" value="Transform( 1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0 )">
+ [Transform] with mirroring applied perpendicular to the XY plane.
</constant>
</constants>
</class>
diff --git a/doc/classes/Transform2D.xml b/doc/classes/Transform2D.xml
index c5ae88d050..f6fce1aaa1 100644
--- a/doc/classes/Transform2D.xml
+++ b/doc/classes/Transform2D.xml
@@ -172,10 +172,13 @@
</members>
<constants>
<constant name="IDENTITY" value="Transform2D( 1, 0, 0, 1, 0, 0 )">
+ [Transform2D] with no translation, rotation or scaling applied. When applied to other data structures, [constant IDENTITY] performs no transformation.
</constant>
<constant name="FLIP_X" value="Transform2D( -1, 0, 0, 1, 0, 0 )">
+ [Transform2D] with mirroring applied parallel to the X axis.
</constant>
<constant name="FLIP_Y" value="Transform2D( 1, 0, 0, -1, 0, 0 )">
+ [Transform2D] with mirroring applied parallel to the Y axis.
</constant>
</constants>
</class>
diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp
index b48b93944c..ee34a478b1 100644
--- a/drivers/gles2/shader_compiler_gles2.cpp
+++ b/drivers/gles2/shader_compiler_gles2.cpp
@@ -318,7 +318,7 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
// use highp if no precision is specified to prevent different default values in fragment and vertex shader
SL::DataPrecision precision = E->get().precision;
- if (precision == SL::PRECISION_DEFAULT) {
+ if (precision == SL::PRECISION_DEFAULT && E->get().type != SL::TYPE_BOOL) {
precision = SL::PRECISION_HIGHP;
}
diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
index aec3d27d69..a61fa449f1 100644
--- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp
+++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
@@ -191,6 +191,14 @@ Error AudioDriverPulseAudio::init_device() {
spec.format = PA_SAMPLE_S16LE;
spec.channels = pa_map.channels;
spec.rate = mix_rate;
+ pa_map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
+ pa_map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
+ pa_map.map[2] = PA_CHANNEL_POSITION_FRONT_CENTER;
+ pa_map.map[3] = PA_CHANNEL_POSITION_LFE;
+ pa_map.map[4] = PA_CHANNEL_POSITION_REAR_LEFT;
+ pa_map.map[5] = PA_CHANNEL_POSITION_REAR_RIGHT;
+ pa_map.map[6] = PA_CHANNEL_POSITION_SIDE_LEFT;
+ pa_map.map[7] = PA_CHANNEL_POSITION_SIDE_RIGHT;
pa_str = pa_stream_new(pa_ctx, "Sound", &spec, &pa_map);
if (pa_str == NULL) {
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index c835dda1b9..f5b5cfa848 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -5273,17 +5273,17 @@ AnimationTrackEditor::AnimationTrackEditor() {
VBoxContainer *cleanup_vb = memnew(VBoxContainer);
cleanup_dialog->add_child(cleanup_vb);
- cleanup_keys = memnew(CheckButton);
+ cleanup_keys = memnew(CheckBox);
cleanup_keys->set_text(TTR("Remove invalid keys"));
cleanup_keys->set_pressed(true);
cleanup_vb->add_child(cleanup_keys);
- cleanup_tracks = memnew(CheckButton);
+ cleanup_tracks = memnew(CheckBox);
cleanup_tracks->set_text(TTR("Remove unresolved and empty tracks"));
cleanup_tracks->set_pressed(true);
cleanup_vb->add_child(cleanup_tracks);
- cleanup_all = memnew(CheckButton);
+ cleanup_all = memnew(CheckBox);
cleanup_all->set_text(TTR("Clean-up all animations"));
cleanup_vb->add_child(cleanup_all);
diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h
index 0d5a621e07..8dc2304a95 100644
--- a/editor/animation_track_editor.h
+++ b/editor/animation_track_editor.h
@@ -439,9 +439,9 @@ class AnimationTrackEditor : public VBoxContainer {
SpinBox *optimize_max_angle;
ConfirmationDialog *cleanup_dialog;
- CheckButton *cleanup_keys;
- CheckButton *cleanup_tracks;
- CheckButton *cleanup_all;
+ CheckBox *cleanup_keys;
+ CheckBox *cleanup_tracks;
+ CheckBox *cleanup_all;
ConfirmationDialog *scale_dialog;
SpinBox *scale;
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index ed50c7914e..7c396e1da3 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -341,7 +341,11 @@ bool FindReplaceBar::search_prev() {
bool FindReplaceBar::search_next() {
uint32_t flags = 0;
- String text = get_search_text();
+ String text;
+ if (replace_all_mode)
+ text = get_replace_text();
+ else
+ text = get_search_text();
if (is_whole_words())
flags |= TextEdit::SEARCH_WHOLE_WORDS;
@@ -724,7 +728,7 @@ void CodeTextEditor::_code_complete_timer_timeout() {
void CodeTextEditor::_complete_request() {
- List<String> entries;
+ List<ScriptCodeCompletionOption> entries;
String ctext = text_editor->get_text_for_completion();
_code_complete_script(ctext, &entries);
bool forced = false;
@@ -733,15 +737,55 @@ void CodeTextEditor::_complete_request() {
}
if (entries.size() == 0)
return;
- Vector<String> strs;
- strs.resize(entries.size());
- int i = 0;
- for (List<String>::Element *E = entries.front(); E; E = E->next()) {
- strs.write[i++] = E->get();
+ for (List<ScriptCodeCompletionOption>::Element *E = entries.front(); E; E = E->next()) {
+ E->get().icon = _get_completion_icon(E->get());
}
+ text_editor->code_complete(entries, forced);
+}
- text_editor->code_complete(strs, forced);
+Ref<Texture> CodeTextEditor::_get_completion_icon(const ScriptCodeCompletionOption &p_option) {
+ Ref<Texture> tex;
+ switch (p_option.kind) {
+ case ScriptCodeCompletionOption::KIND_CLASS: {
+ if (has_icon(p_option.display, "EditorIcons")) {
+ tex = get_icon(p_option.display, "EditorIcons");
+ } else {
+ tex = get_icon("Object", "EditorIcons");
+ }
+ } break;
+ case ScriptCodeCompletionOption::KIND_ENUM:
+ tex = get_icon("Enum", "EditorIcons");
+ break;
+ case ScriptCodeCompletionOption::KIND_FILE_PATH:
+ tex = get_icon("File", "EditorIcons");
+ break;
+ case ScriptCodeCompletionOption::KIND_NODE_PATH:
+ tex = get_icon("NodePath", "EditorIcons");
+ break;
+ case ScriptCodeCompletionOption::KIND_VARIABLE:
+ tex = get_icon("Variant", "EditorIcons");
+ break;
+ case ScriptCodeCompletionOption::KIND_CONSTANT:
+ tex = get_icon("MemberConstant", "EditorIcons");
+ break;
+ case ScriptCodeCompletionOption::KIND_MEMBER:
+ tex = get_icon("MemberProperty", "EditorIcons");
+ break;
+ case ScriptCodeCompletionOption::KIND_SIGNAL:
+ tex = get_icon("MemberSignal", "EditorIcons");
+ break;
+ case ScriptCodeCompletionOption::KIND_FUNCTION:
+ tex = get_icon("MemberMethod", "EditorIcons");
+ break;
+ case ScriptCodeCompletionOption::KIND_PLAIN_TEXT:
+ tex = get_icon("CubeMesh", "EditorIcons");
+ break;
+ default:
+ tex = get_icon("String", "EditorIcons");
+ break;
+ }
+ return tex;
}
void CodeTextEditor::_font_resize_timeout() {
diff --git a/editor/code_editor.h b/editor/code_editor.h
index c0989f9704..5af1f531a9 100644
--- a/editor/code_editor.h
+++ b/editor/code_editor.h
@@ -131,7 +131,7 @@ public:
FindReplaceBar();
};
-typedef void (*CodeTextEditorCodeCompleteFunc)(void *p_ud, const String &p_code, List<String> *r_options, bool &r_forced);
+typedef void (*CodeTextEditorCodeCompleteFunc)(void *p_ud, const String &p_code, List<ScriptCodeCompletionOption> *r_options, bool &r_forced);
class CodeTextEditor : public VBoxContainer {
@@ -162,6 +162,7 @@ class CodeTextEditor : public VBoxContainer {
void _update_font();
void _complete_request();
+ Ref<Texture> _get_completion_icon(const ScriptCodeCompletionOption &p_option);
void _font_resize_timeout();
bool _add_font_size(int p_delta);
@@ -183,7 +184,7 @@ class CodeTextEditor : public VBoxContainer {
protected:
virtual void _load_theme_settings() {}
virtual void _validate_script() {}
- virtual void _code_complete_script(const String &p_code, List<String> *r_options) {}
+ virtual void _code_complete_script(const String &p_code, List<ScriptCodeCompletionOption> *r_options) {}
void _text_changed_idle_timeout();
void _code_complete_timer_timeout();
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index d9600172d7..9d3be1ab9e 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -2622,6 +2622,13 @@ void EditorNode::_exit_editor() {
exiting = true;
resource_preview->stop(); //stop early to avoid crashes
_save_docks();
+
+ // Dim the editor window while it's quitting to make it clearer that it's busy.
+ // No transition is applied, as the effect needs to be visible immediately
+ float c = 1.0f - float(EDITOR_GET("interface/editor/dim_amount"));
+ Color dim_color = Color(c, c, c);
+ gui_base->set_modulate(dim_color);
+
get_tree()->quit();
}
@@ -6258,7 +6265,7 @@ EditorNode::EditorNode() {
file_export_lib->set_title(TTR("Export Library"));
file_export_lib->set_mode(EditorFileDialog::MODE_SAVE_FILE);
file_export_lib->connect("file_selected", this, "_dialog_action");
- file_export_lib_merge = memnew(CheckButton);
+ file_export_lib_merge = memnew(CheckBox);
file_export_lib_merge->set_text(TTR("Merge With Existing"));
file_export_lib_merge->set_pressed(true);
file_export_lib->get_vbox()->add_child(file_export_lib_merge);
diff --git a/editor/editor_node.h b/editor/editor_node.h
index ca64126c60..733f29c8ff 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -330,7 +330,7 @@ private:
EditorFileDialog *file_export;
EditorFileDialog *file_export_lib;
EditorFileDialog *file_script;
- CheckButton *file_export_lib_merge;
+ CheckBox *file_export_lib_merge;
LineEdit *file_export_password;
String current_path;
MenuButton *update_spinner;
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index 9301d8c1a4..b74350c98b 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -1324,14 +1324,14 @@ void FileSystemDock::_duplicate_operation_confirm() {
return;
}
- String new_path;
String base_dir = to_duplicate.path.get_base_dir();
- if (to_duplicate.is_file) {
- new_path = base_dir.plus_file(new_name);
- } else {
- new_path = base_dir.substr(0, base_dir.find_last("/")).plus_file(new_name);
+ // get_base_dir() returns "some/path" if the original path was "some/path/", so work it around.
+ if (to_duplicate.path.ends_with("/")) {
+ base_dir = base_dir.get_base_dir();
}
+ String new_path = base_dir.plus_file(new_name);
+
//Present a more user friendly warning for name conflict
DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
if (da->file_exists(new_path) || da->dir_exists(new_path)) {
diff --git a/editor/plugins/path_editor_plugin.cpp b/editor/plugins/path_editor_plugin.cpp
index 88dc258c5f..1ae5acc5ff 100644
--- a/editor/plugins/path_editor_plugin.cpp
+++ b/editor/plugins/path_editor_plugin.cpp
@@ -95,6 +95,7 @@ void PathSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_p
Vector3 ray_from = p_camera->project_ray_origin(p_point);
Vector3 ray_dir = p_camera->project_ray_normal(p_point);
+ // Setting curve point positions
if (p_idx < c->get_point_count()) {
Plane p(gt.xform(original), p_camera->get_transform().basis.get_axis(2));
@@ -126,6 +127,7 @@ void PathSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_p
Vector3 inters;
+ // Setting curve in/out positions
if (p.intersects_ray(ray_from, ray_dir, &inters)) {
if (!PathEditorPlugin::singleton->is_handle_clicked()) {
@@ -135,9 +137,13 @@ void PathSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_p
}
Vector3 local = gi.xform(inters) - base;
+ if (SpatialEditor::get_singleton()->is_snap_enabled()) {
+ float snap = SpatialEditor::get_singleton()->get_translate_snap();
+ local.snap(Vector3(snap, snap, snap));
+ }
+
if (t == 0) {
c->set_point_in(idx, local);
-
if (PathEditorPlugin::singleton->mirror_angle_enabled())
c->set_point_out(idx, PathEditorPlugin::singleton->mirror_length_enabled() ? -local : (-local.normalized() * orig_out_length));
} else {
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index 2cfa759e3b..438621115b 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -773,13 +773,13 @@ void ScriptEditor::_update_modified_scripts_for_external_editor(Ref<Script> p_fo
}
}
-void ScriptTextEditor::_code_complete_scripts(void *p_ud, const String &p_code, List<String> *r_options, bool &r_force) {
+void ScriptTextEditor::_code_complete_scripts(void *p_ud, const String &p_code, List<ScriptCodeCompletionOption> *r_options, bool &r_force) {
ScriptTextEditor *ste = (ScriptTextEditor *)p_ud;
ste->_code_complete_script(p_code, r_options, r_force);
}
-void ScriptTextEditor::_code_complete_script(const String &p_code, List<String> *r_options, bool &r_force) {
+void ScriptTextEditor::_code_complete_script(const String &p_code, List<ScriptCodeCompletionOption> *r_options, bool &r_force) {
if (color_panel->is_visible_in_tree()) return;
Node *base = get_tree()->get_edited_scene_root();
diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h
index b53383b117..9a2a514a6e 100644
--- a/editor/plugins/script_text_editor.h
+++ b/editor/plugins/script_text_editor.h
@@ -143,7 +143,6 @@ class ScriptTextEditor : public ScriptEditorBase {
};
protected:
- static void _code_complete_scripts(void *p_ud, const String &p_code, List<String> *r_options, bool &r_force);
void _update_breakpoint_list();
void _breakpoint_item_pressed(int p_idx);
void _breakpoint_toggled(int p_row);
@@ -151,7 +150,10 @@ protected:
void _validate_script(); // No longer virtual.
void _update_bookmark_list();
void _bookmark_item_pressed(int p_idx);
- void _code_complete_script(const String &p_code, List<String> *r_options, bool &r_force);
+
+ static void _code_complete_scripts(void *p_ud, const String &p_code, List<ScriptCodeCompletionOption> *r_options, bool &r_force);
+ void _code_complete_script(const String &p_code, List<ScriptCodeCompletionOption> *r_options, bool &r_force);
+
void _load_theme_settings();
void _set_theme_for_script();
void _show_warnings_panel(bool p_show);
diff --git a/editor/rename_dialog.cpp b/editor/rename_dialog.cpp
index 40343cf908..cc9e14975f 100644
--- a/editor/rename_dialog.cpp
+++ b/editor/rename_dialog.cpp
@@ -131,7 +131,7 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und
vbc_substitute->set_name(TTR("Substitute"));
tabc_features->add_child(vbc_substitute);
- cbut_substitute = memnew(CheckButton);
+ cbut_substitute = memnew(CheckBox);
cbut_substitute->set_text(TTR("Substitute"));
vbc_substitute->add_child(cbut_substitute);
@@ -246,7 +246,7 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und
vbc_regex->set_custom_minimum_size(Size2(0, feature_min_height));
tabc_features->add_child(vbc_regex);
- cbut_regex = memnew(CheckButton);
+ cbut_regex = memnew(CheckBox);
cbut_regex->set_text(TTR("Regular Expressions"));
vbc_regex->add_child(cbut_regex);
@@ -258,7 +258,7 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und
vbc_process->set_custom_minimum_size(Size2(0, feature_min_height));
tabc_features->add_child(vbc_process);
- cbut_process = memnew(CheckButton);
+ cbut_process = memnew(CheckBox);
cbut_process->set_text(TTR("Post-Process"));
vbc_process->add_child(cbut_process);
diff --git a/editor/rename_dialog.h b/editor/rename_dialog.h
index 4e0fab6a9f..9f0fbf66a1 100644
--- a/editor/rename_dialog.h
+++ b/editor/rename_dialog.h
@@ -32,7 +32,6 @@
#define RENAME_DIALOG_H
#include "scene/gui/check_box.h"
-#include "scene/gui/check_button.h"
#include "scene/gui/dialogs.h"
#include "scene/gui/option_button.h"
#include "scene/gui/spin_box.h"
@@ -75,9 +74,9 @@ class RenameDialog : public ConfirmationDialog {
TabContainer *tabc_features;
- CheckButton *cbut_substitute;
- CheckButton *cbut_regex;
- CheckButton *cbut_process;
+ CheckBox *cbut_substitute;
+ CheckBox *cbut_regex;
+ CheckBox *cbut_process;
CheckBox *chk_per_level_counter;
Button *but_insert_name;
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index f6ef8f5716..5f62ed0702 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -439,6 +439,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
}
script_create_dialog->connect("script_created", this, "_script_created");
script_create_dialog->connect("popup_hide", this, "_script_creation_closed");
+ script_create_dialog->set_inheritance_base_type("Node");
script_create_dialog->config(inherits, path);
script_create_dialog->popup_centered();
@@ -2243,23 +2244,20 @@ void SceneTreeDock::_script_dropped(String p_file, NodePath p_to) {
void SceneTreeDock::_nodes_dragged(Array p_nodes, NodePath p_to, int p_type) {
- Vector<Node *> nodes;
- Node *to_node;
-
- for (int i = 0; i < p_nodes.size(); i++) {
- Node *n = get_node((p_nodes[i]));
- if (n) {
- nodes.push_back(n);
- }
- }
+ List<Node *> selection = editor_selection->get_selected_node_list();
- if (nodes.size() == 0)
- return;
+ if (selection.empty())
+ return; //nothing to reparent
- to_node = get_node(p_to);
+ Node *to_node = get_node(p_to);
if (!to_node)
return;
+ Vector<Node *> nodes;
+ for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
+ nodes.push_back(E->get());
+ }
+
int to_pos = -1;
_normalize_drop(to_node, to_pos, p_type);
diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp
index 8916f4d8c4..bebfe6d3a1 100644
--- a/editor/script_create_dialog.cpp
+++ b/editor/script_create_dialog.cpp
@@ -742,8 +742,8 @@ ScriptCreateDialog::ScriptCreateDialog() {
/* Built-in Script */
- internal = memnew(CheckButton);
- internal->set_h_size_flags(0);
+ internal = memnew(CheckBox);
+ internal->set_text(TTR("On"));
internal->connect("pressed", this, "_built_in_pressed");
internal_label = memnew(Label(TTR("Built-in Script")));
internal_label->set_align(Label::ALIGN_RIGHT);
diff --git a/editor/script_create_dialog.h b/editor/script_create_dialog.h
index 61f87f5732..288b8f604b 100644
--- a/editor/script_create_dialog.h
+++ b/editor/script_create_dialog.h
@@ -33,7 +33,7 @@
#include "editor/editor_file_dialog.h"
#include "editor/editor_settings.h"
-#include "scene/gui/check_button.h"
+#include "scene/gui/check_box.h"
#include "scene/gui/dialogs.h"
#include "scene/gui/grid_container.h"
#include "scene/gui/line_edit.h"
@@ -57,7 +57,7 @@ class ScriptCreateDialog : public ConfirmationDialog {
LineEdit *file_path;
Button *path_button;
EditorFileDialog *file_browse;
- CheckButton *internal;
+ CheckBox *internal;
Label *internal_label;
VBoxContainer *path_vb;
AcceptDialog *alert;
diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp
index fe6d9dd8c7..cbfd0f3742 100644
--- a/editor/spatial_editor_gizmos.cpp
+++ b/editor/spatial_editor_gizmos.cpp
@@ -873,6 +873,10 @@ void LightSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx,
Geometry::get_closest_points_between_segments(Vector3(), Vector3(0, 0, -4096), s[0], s[1], ra, rb);
float d = -ra.z;
+ if (SpatialEditor::get_singleton()->is_snap_enabled()) {
+ d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap());
+ }
+
if (d < 0)
d = 0;
@@ -885,6 +889,10 @@ void LightSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx,
if (cp.intersects_ray(ray_from, ray_dir, &inters)) {
float r = inters.distance_to(gt.origin);
+ if (SpatialEditor::get_singleton()->is_snap_enabled()) {
+ r = Math::stepify(r, SpatialEditor::get_singleton()->get_translate_snap());
+ }
+
light->set_param(Light::PARAM_RANGE, r);
}
}
@@ -1257,6 +1265,10 @@ void CameraSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx
Vector3 ra, rb;
Geometry::get_closest_points_between_segments(Vector3(0, 0, -1), Vector3(4096, 0, -1), s[0], s[1], ra, rb);
float d = ra.x * 2.0;
+ if (SpatialEditor::get_singleton()->is_snap_enabled()) {
+ d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap());
+ }
+
if (d < 0)
d = 0;
@@ -2310,6 +2322,9 @@ void VisibilityNotifierGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int
Geometry::get_closest_points_between_segments(ofs - axis * 4096, ofs + axis * 4096, sg[0], sg[1], ra, rb);
float d = ra[p_idx];
+ if (SpatialEditor::get_singleton()->is_snap_enabled()) {
+ d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap());
+ }
aabb.position[p_idx] = d - 1.0 - aabb.size[p_idx] * 0.5;
notifier->set_aabb(aabb);
@@ -2319,6 +2334,10 @@ void VisibilityNotifierGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int
Geometry::get_closest_points_between_segments(ofs, ofs + axis * 4096, sg[0], sg[1], ra, rb);
float d = ra[p_idx] - ofs[p_idx];
+ if (SpatialEditor::get_singleton()->is_snap_enabled()) {
+ d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap());
+ }
+
if (d < 0.001)
d = 0.001;
//resize
@@ -2444,7 +2463,6 @@ void ParticlesGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Ca
Particles *particles = Object::cast_to<Particles>(p_gizmo->get_spatial_node());
Transform gt = particles->get_global_transform();
- //gt.orthonormalize();
Transform gi = gt.affine_inverse();
bool move = p_idx >= 3;
@@ -2467,6 +2485,9 @@ void ParticlesGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Ca
Geometry::get_closest_points_between_segments(ofs - axis * 4096, ofs + axis * 4096, sg[0], sg[1], ra, rb);
float d = ra[p_idx];
+ if (SpatialEditor::get_singleton()->is_snap_enabled()) {
+ d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap());
+ }
aabb.position[p_idx] = d - 1.0 - aabb.size[p_idx] * 0.5;
particles->set_visibility_aabb(aabb);
@@ -2476,6 +2497,10 @@ void ParticlesGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Ca
Geometry::get_closest_points_between_segments(ofs, ofs + axis * 4096, sg[0], sg[1], ra, rb);
float d = ra[p_idx] - ofs[p_idx];
+ if (SpatialEditor::get_singleton()->is_snap_enabled()) {
+ d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap());
+ }
+
if (d < 0.001)
d = 0.001;
//resize
@@ -2619,6 +2644,10 @@ void ReflectionProbeGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_i
Vector3 ra, rb;
Geometry::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb);
float d = ra[p_idx];
+ if (SpatialEditor::get_singleton()->is_snap_enabled()) {
+ d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap());
+ }
+
if (d < 0.001)
d = 0.001;
@@ -2641,8 +2670,11 @@ void ReflectionProbeGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_i
Vector3 ra, rb;
Geometry::get_closest_points_between_segments(origin - axis * 16384, origin + axis * 16384, sg[0], sg[1], ra, rb);
- float d = ra[p_idx];
- d += 0.25;
+ // Adjust the actual position to account for the gizmo handle position
+ float d = ra[p_idx] + 0.25;
+ if (SpatialEditor::get_singleton()->is_snap_enabled()) {
+ d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap());
+ }
origin[p_idx] = d;
probe->set_origin_offset(origin);
@@ -2780,7 +2812,6 @@ void GIProbeGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Came
GIProbe *probe = Object::cast_to<GIProbe>(p_gizmo->get_spatial_node());
Transform gt = probe->get_global_transform();
- //gt.orthonormalize();
Transform gi = gt.affine_inverse();
Vector3 extents = probe->get_extents();
@@ -2796,6 +2827,10 @@ void GIProbeGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Came
Vector3 ra, rb;
Geometry::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb);
float d = ra[p_idx];
+ if (SpatialEditor::get_singleton()->is_snap_enabled()) {
+ d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap());
+ }
+
if (d < 0.001)
d = 0.001;
@@ -2945,7 +2980,6 @@ void BakedIndirectLightGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int
BakedLightmap *baker = Object::cast_to<BakedLightmap>(p_gizmo->get_spatial_node());
Transform gt = baker->get_global_transform();
- //gt.orthonormalize();
Transform gi = gt.affine_inverse();
Vector3 extents = baker->get_extents();
@@ -2961,6 +2995,10 @@ void BakedIndirectLightGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int
Vector3 ra, rb;
Geometry::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb);
float d = ra[p_idx];
+ if (SpatialEditor::get_singleton()->is_snap_enabled()) {
+ d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap());
+ }
+
if (d < 0.001)
d = 0.001;
@@ -3158,6 +3196,10 @@ void CollisionShapeSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, i
Vector3 ra, rb;
Geometry::get_closest_points_between_segments(Vector3(), Vector3(4096, 0, 0), sg[0], sg[1], ra, rb);
float d = ra.x;
+ if (SpatialEditor::get_singleton()->is_snap_enabled()) {
+ d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap());
+ }
+
if (d < 0.001)
d = 0.001;
@@ -3170,6 +3212,10 @@ void CollisionShapeSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, i
Vector3 ra, rb;
Geometry::get_closest_points_between_segments(Vector3(), Vector3(0, 0, 4096), sg[0], sg[1], ra, rb);
float d = ra.z;
+ if (SpatialEditor::get_singleton()->is_snap_enabled()) {
+ d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap());
+ }
+
if (d < 0.001)
d = 0.001;
@@ -3184,6 +3230,10 @@ void CollisionShapeSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, i
Vector3 ra, rb;
Geometry::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb);
float d = ra[p_idx];
+ if (SpatialEditor::get_singleton()->is_snap_enabled()) {
+ d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap());
+ }
+
if (d < 0.001)
d = 0.001;
@@ -3202,6 +3252,11 @@ void CollisionShapeSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, i
float d = axis.dot(ra);
if (p_idx == 1)
d -= cs2->get_radius();
+
+ if (SpatialEditor::get_singleton()->is_snap_enabled()) {
+ d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap());
+ }
+
if (d < 0.001)
d = 0.001;
@@ -3219,6 +3274,9 @@ void CollisionShapeSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, i
Vector3 ra, rb;
Geometry::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb);
float d = axis.dot(ra);
+ if (SpatialEditor::get_singleton()->is_snap_enabled()) {
+ d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap());
+ }
if (d < 0.001)
d = 0.001;
diff --git a/modules/gdnative/pluginscript/pluginscript_language.cpp b/modules/gdnative/pluginscript/pluginscript_language.cpp
index 4bbadc62e7..9de073fc8e 100644
--- a/modules/gdnative/pluginscript/pluginscript_language.cpp
+++ b/modules/gdnative/pluginscript/pluginscript_language.cpp
@@ -159,7 +159,7 @@ String PluginScriptLanguage::make_function(const String &p_class, const String &
return String();
}
-Error PluginScriptLanguage::complete_code(const String &p_code, const String &p_path, Object *p_owner, List<String> *r_options, bool &r_force, String &r_call_hint) {
+Error PluginScriptLanguage::complete_code(const String &p_code, const String &p_path, Object *p_owner, List<ScriptCodeCompletionOption> *r_options, bool &r_force, String &r_call_hint) {
if (_desc.complete_code) {
Array options;
godot_error tmp = _desc.complete_code(
@@ -171,7 +171,8 @@ Error PluginScriptLanguage::complete_code(const String &p_code, const String &p_
&r_force,
(godot_string *)&r_call_hint);
for (int i = 0; i < options.size(); i++) {
- r_options->push_back(String(options[i]));
+ ScriptCodeCompletionOption option(options[i], ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
+ r_options->push_back(option);
}
return (Error)tmp;
}
diff --git a/modules/gdnative/pluginscript/pluginscript_language.h b/modules/gdnative/pluginscript/pluginscript_language.h
index a11e916975..7b3844d0b0 100644
--- a/modules/gdnative/pluginscript/pluginscript_language.h
+++ b/modules/gdnative/pluginscript/pluginscript_language.h
@@ -81,7 +81,7 @@ public:
virtual bool can_inherit_from_file() { return true; }
virtual int find_function(const String &p_function, const String &p_code) const;
virtual String make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const;
- virtual Error complete_code(const String &p_code, const String &p_path, Object *p_owner, List<String> *r_options, bool &r_force, String &r_call_hint);
+ virtual Error complete_code(const String &p_code, const String &p_path, Object *p_owner, List<ScriptCodeCompletionOption> *r_options, bool &r_force, String &r_call_hint);
virtual void auto_indent_code(String &p_code, int p_from_line, int p_to_line) const;
virtual void add_global_constant(const StringName &p_variable, const Variant &p_value);
diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h
index 1756f6eabc..a5ad23c75d 100644
--- a/modules/gdscript/gdscript.h
+++ b/modules/gdscript/gdscript.h
@@ -458,7 +458,7 @@ public:
virtual bool can_inherit_from_file() { return true; }
virtual int find_function(const String &p_function, const String &p_code) const;
virtual String make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const;
- virtual Error complete_code(const String &p_code, const String &p_path, Object *p_owner, List<String> *r_options, bool &r_forced, String &r_call_hint);
+ virtual Error complete_code(const String &p_code, const String &p_path, Object *p_owner, List<ScriptCodeCompletionOption> *r_options, bool &r_forced, String &r_call_hint);
#ifdef TOOLS_ENABLED
virtual Error lookup_code(const String &p_code, const String &p_symbol, const String &p_path, Object *p_owner, LookupResult &r_result);
#endif
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index 26b14a6148..78a1bfc99b 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -509,12 +509,14 @@ struct GDScriptCompletionIdentifier {
assigned_expression(NULL) {}
};
-static void _get_directory_contents(EditorFileSystemDirectory *p_dir, Set<String> &r_list) {
+static void _get_directory_contents(EditorFileSystemDirectory *p_dir, Map<String, ScriptCodeCompletionOption> &r_list) {
const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", false) ? "'" : "\"";
for (int i = 0; i < p_dir->get_file_count(); i++) {
- r_list.insert(quote_style + p_dir->get_file_path(i) + quote_style);
+ ScriptCodeCompletionOption option(p_dir->get_file_path(i), ScriptCodeCompletionOption::KIND_FILE_PATH);
+ option.insert_text = quote_style + option.display + quote_style;
+ r_list.insert(option.display, option);
}
for (int i = 0; i < p_dir->get_subdir_count(); i++) {
@@ -1807,14 +1809,15 @@ static String _make_arguments_hint(const GDScriptParser::FunctionNode *p_functio
return arghint;
}
-static void _find_enumeration_candidates(const String p_enum_hint, Set<String> &r_result) {
+static void _find_enumeration_candidates(const String p_enum_hint, Map<String, ScriptCodeCompletionOption> &r_result) {
if (p_enum_hint.find(".") == -1) {
// Global constant
StringName current_enum = p_enum_hint;
for (int i = 0; i < GlobalConstants::get_global_constant_count(); i++) {
if (GlobalConstants::get_global_constant_enum(i) == current_enum) {
- r_result.insert(GlobalConstants::get_global_constant_name(i));
+ ScriptCodeCompletionOption option(GlobalConstants::get_global_constant_name(i), ScriptCodeCompletionOption::KIND_ENUM);
+ r_result.insert(option.display, option);
}
}
} else {
@@ -1829,15 +1832,17 @@ static void _find_enumeration_candidates(const String p_enum_hint, Set<String> &
ClassDB::get_enum_constants(class_name, enum_name, &enum_constants);
for (List<StringName>::Element *E = enum_constants.front(); E; E = E->next()) {
String candidate = class_name + "." + E->get();
- r_result.insert(candidate);
+ ScriptCodeCompletionOption option(candidate, ScriptCodeCompletionOption::KIND_ENUM);
+ r_result.insert(option.display, option);
}
}
}
-static void _find_identifiers_in_block(const GDScriptCompletionContext &p_context, Set<String> &r_result) {
+static void _find_identifiers_in_block(const GDScriptCompletionContext &p_context, Map<String, ScriptCodeCompletionOption> &r_result) {
for (Map<StringName, GDScriptParser::LocalVarNode *>::Element *E = p_context.block->variables.front(); E; E = E->next()) {
if (E->get()->line < p_context.line) {
- r_result.insert(E->key().operator String());
+ ScriptCodeCompletionOption option(E->key().operator String(), ScriptCodeCompletionOption::KIND_VARIABLE);
+ r_result.insert(option.display, option);
}
}
if (p_context.block->parent_block) {
@@ -1847,40 +1852,47 @@ static void _find_identifiers_in_block(const GDScriptCompletionContext &p_contex
}
}
-static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, bool p_only_functions, Set<String> &r_result);
+static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, bool p_only_functions, Map<String, ScriptCodeCompletionOption> &r_result);
-static void _find_identifiers_in_class(const GDScriptCompletionContext &p_context, bool p_static, bool p_only_functions, bool p_parent_only, Set<String> &r_result) {
+static void _find_identifiers_in_class(const GDScriptCompletionContext &p_context, bool p_static, bool p_only_functions, bool p_parent_only, Map<String, ScriptCodeCompletionOption> &r_result) {
if (!p_parent_only) {
if (!p_static && !p_only_functions) {
for (int i = 0; i < p_context._class->variables.size(); i++) {
- r_result.insert(p_context._class->variables[i].identifier);
+ ScriptCodeCompletionOption option(p_context._class->variables[i].identifier, ScriptCodeCompletionOption::KIND_MEMBER);
+ r_result.insert(option.display, option);
}
}
if (!p_only_functions) {
for (Map<StringName, GDScriptParser::ClassNode::Constant>::Element *E = p_context._class->constant_expressions.front(); E; E = E->next()) {
- r_result.insert(E->key());
+ ScriptCodeCompletionOption option(E->key(), ScriptCodeCompletionOption::KIND_CONSTANT);
+ r_result.insert(option.display, option);
}
for (int i = 0; i < p_context._class->subclasses.size(); i++) {
- r_result.insert(p_context._class->subclasses[i]->name);
+ ScriptCodeCompletionOption option(p_context._class->subclasses[i]->name, ScriptCodeCompletionOption::KIND_CLASS);
+ r_result.insert(option.display, option);
}
}
for (int i = 0; i < p_context._class->static_functions.size(); i++) {
+ ScriptCodeCompletionOption option(p_context._class->static_functions[i]->name.operator String(), ScriptCodeCompletionOption::KIND_FUNCTION);
if (p_context._class->static_functions[i]->arguments.size()) {
- r_result.insert(p_context._class->static_functions[i]->name.operator String() + "(");
+ option.insert_text += "(";
} else {
- r_result.insert(p_context._class->static_functions[i]->name.operator String() + "()");
+ option.insert_text += "()";
}
+ r_result.insert(option.display, option);
}
if (!p_static) {
for (int i = 0; i < p_context._class->functions.size(); i++) {
+ ScriptCodeCompletionOption option(p_context._class->functions[i]->name.operator String(), ScriptCodeCompletionOption::KIND_FUNCTION);
if (p_context._class->functions[i]->arguments.size()) {
- r_result.insert(p_context._class->functions[i]->name.operator String() + "(");
+ option.insert_text += "(";
} else {
- r_result.insert(p_context._class->functions[i]->name.operator String() + "()");
+ option.insert_text += "()";
}
+ r_result.insert(option.display, option);
}
}
}
@@ -1898,12 +1910,14 @@ static void _find_identifiers_in_class(const GDScriptCompletionContext &p_contex
_find_identifiers_in_base(c, base_type, p_only_functions, r_result);
}
-static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, bool p_only_functions, Set<String> &r_result) {
+static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, bool p_only_functions, Map<String, ScriptCodeCompletionOption> &r_result) {
GDScriptParser::DataType base_type = p_base.type;
bool _static = base_type.is_meta_type;
if (_static && base_type.kind != GDScriptParser::DataType::BUILTIN) {
- r_result.insert("new(");
+ ScriptCodeCompletionOption option("new", ScriptCodeCompletionOption::KIND_FUNCTION);
+ option.insert_text += "(";
+ r_result.insert(option.display, option);
}
while (base_type.has_type) {
@@ -1921,26 +1935,31 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context
if (script.is_valid()) {
if (!_static && !p_only_functions) {
for (const Set<StringName>::Element *E = script->get_members().front(); E; E = E->next()) {
- r_result.insert(E->get().operator String());
+ ScriptCodeCompletionOption option(E->get().operator String(), ScriptCodeCompletionOption::KIND_MEMBER);
+ r_result.insert(option.display, option);
}
}
if (!p_only_functions) {
for (const Map<StringName, Variant>::Element *E = script->get_constants().front(); E; E = E->next()) {
- r_result.insert(E->key().operator String());
+ ScriptCodeCompletionOption option(E->key().operator String(), ScriptCodeCompletionOption::KIND_CONSTANT);
+ r_result.insert(option.display, option);
}
}
for (const Map<StringName, GDScriptFunction *>::Element *E = script->get_member_functions().front(); E; E = E->next()) {
if (!_static || E->get()->is_static()) {
+ ScriptCodeCompletionOption option(E->key().operator String(), ScriptCodeCompletionOption::KIND_FUNCTION);
if (E->get()->get_argument_count()) {
- r_result.insert(E->key().operator String() + "(");
+ option.insert_text += "(";
} else {
- r_result.insert(E->key().operator String() + "()");
+ option.insert_text += "()";
}
+ r_result.insert(option.display, option);
}
}
if (!p_only_functions) {
for (const Map<StringName, Ref<GDScript> >::Element *E = script->get_subclasses().front(); E; E = E->next()) {
- r_result.insert(E->key().operator String());
+ ScriptCodeCompletionOption option(E->key().operator String(), ScriptCodeCompletionOption::KIND_CLASS);
+ r_result.insert(option.display, option);
}
}
base_type = GDScriptParser::DataType();
@@ -1964,25 +1983,29 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context
List<PropertyInfo> members;
scr->get_script_property_list(&members);
for (List<PropertyInfo>::Element *E = members.front(); E; E = E->next()) {
- r_result.insert(E->get().name);
+ ScriptCodeCompletionOption option(E->get().name, ScriptCodeCompletionOption::KIND_MEMBER);
+ r_result.insert(option.display, option);
}
}
if (!p_only_functions) {
Map<StringName, Variant> constants;
scr->get_constants(&constants);
for (Map<StringName, Variant>::Element *E = constants.front(); E; E = E->next()) {
- r_result.insert(E->key().operator String());
+ ScriptCodeCompletionOption option(E->key().operator String(), ScriptCodeCompletionOption::KIND_CONSTANT);
+ r_result.insert(option.display, option);
}
}
List<MethodInfo> methods;
scr->get_script_method_list(&methods);
for (List<MethodInfo>::Element *E = methods.front(); E; E = E->next()) {
+ ScriptCodeCompletionOption option(E->get().name, ScriptCodeCompletionOption::KIND_FUNCTION);
if (E->get().arguments.size()) {
- r_result.insert(E->get().name + "(");
+ option.insert_text += "(";
} else {
- r_result.insert(E->get().name + "()");
+ option.insert_text += "()";
}
+ r_result.insert(option.display, option);
}
Ref<Script> base_script = scr->get_base_script();
@@ -2009,7 +2032,8 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context
List<String> constants;
ClassDB::get_integer_constant_list(type, &constants);
for (List<String>::Element *E = constants.front(); E; E = E->next()) {
- r_result.insert(E->get());
+ ScriptCodeCompletionOption option(E->get(), ScriptCodeCompletionOption::KIND_CONSTANT);
+ r_result.insert(option.display, option);
}
if (!_static) {
@@ -2022,7 +2046,8 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context
if (E->get().name.find("/") != -1) {
continue;
}
- r_result.insert(E->get().name);
+ ScriptCodeCompletionOption option(E->get().name, ScriptCodeCompletionOption::KIND_MEMBER);
+ r_result.insert(option.display, option);
}
}
}
@@ -2035,11 +2060,13 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context
if (E->get().name.begins_with("_")) {
continue;
}
+ ScriptCodeCompletionOption option(E->get().name, ScriptCodeCompletionOption::KIND_FUNCTION);
if (E->get().arguments.size()) {
- r_result.insert(E->get().name + "(");
+ option.insert_text += "(";
} else {
- r_result.insert(E->get().name + "()");
+ option.insert_text += "()";
}
+ r_result.insert(option.display, option);
}
}
@@ -2058,7 +2085,8 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context
for (List<PropertyInfo>::Element *E = members.front(); E; E = E->next()) {
if (String(E->get().name).find("/") == -1) {
- r_result.insert(E->get().name);
+ ScriptCodeCompletionOption option(E->get().name, ScriptCodeCompletionOption::KIND_MEMBER);
+ r_result.insert(option.display, option);
}
}
}
@@ -2066,11 +2094,13 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context
List<MethodInfo> methods;
tmp.get_method_list(&methods);
for (List<MethodInfo>::Element *E = methods.front(); E; E = E->next()) {
+ ScriptCodeCompletionOption option(E->get().name, ScriptCodeCompletionOption::KIND_FUNCTION);
if (E->get().arguments.size()) {
- r_result.insert(E->get().name + "(");
+ option.insert_text += "(";
} else {
- r_result.insert(E->get().name + "()");
+ option.insert_text += "()";
}
+ r_result.insert(option.display, option);
}
return;
@@ -2082,7 +2112,7 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context
}
}
-static void _find_identifiers(const GDScriptCompletionContext &p_context, bool p_only_functions, Set<String> &r_result) {
+static void _find_identifiers(const GDScriptCompletionContext &p_context, bool p_only_functions, Map<String, ScriptCodeCompletionOption> &r_result) {
const GDScriptParser::BlockNode *block = p_context.block;
@@ -2091,7 +2121,8 @@ static void _find_identifiers(const GDScriptCompletionContext &p_context, bool p
const GDScriptParser::FunctionNode *f = p_context.function;
for (int i = 0; i < f->arguments.size(); i++) {
- r_result.insert(f->arguments[i].operator String());
+ ScriptCodeCompletionOption option(f->arguments[i].operator String(), ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
+ r_result.insert(option.display, option);
}
}
@@ -2116,11 +2147,13 @@ static void _find_identifiers(const GDScriptCompletionContext &p_context, bool p
for (int i = 0; i < GDScriptFunctions::FUNC_MAX; i++) {
MethodInfo mi = GDScriptFunctions::get_info(GDScriptFunctions::Function(i));
+ ScriptCodeCompletionOption option(String(GDScriptFunctions::get_func_name(GDScriptFunctions::Function(i))), ScriptCodeCompletionOption::KIND_FUNCTION);
if (mi.arguments.size() || (mi.flags & METHOD_FLAG_VARARG)) {
- r_result.insert(String(GDScriptFunctions::get_func_name(GDScriptFunctions::Function(i))) + "(");
+ option.insert_text += "(";
} else {
- r_result.insert(String(GDScriptFunctions::get_func_name(GDScriptFunctions::Function(i))) + "()");
+ option.insert_text += "()";
}
+ r_result.insert(option.display, option);
}
static const char *_type_names[Variant::VARIANT_MAX] = {
@@ -2130,7 +2163,8 @@ static void _find_identifiers(const GDScriptCompletionContext &p_context, bool p
};
for (int i = 0; i < Variant::VARIANT_MAX; i++) {
- r_result.insert(_type_names[i]);
+ ScriptCodeCompletionOption option(_type_names[i], ScriptCodeCompletionOption::KIND_CLASS);
+ r_result.insert(option.display, option);
}
static const char *_keywords[] = {
@@ -2144,7 +2178,8 @@ static void _find_identifiers(const GDScriptCompletionContext &p_context, bool p
const char **kw = _keywords;
while (*kw) {
- r_result.insert(*kw);
+ ScriptCodeCompletionOption option(*kw, ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
+ r_result.insert(option.display, option);
kw++;
}
@@ -2158,7 +2193,8 @@ static void _find_identifiers(const GDScriptCompletionContext &p_context, bool p
}
String path = ProjectSettings::get_singleton()->get(s);
if (path.begins_with("*")) {
- r_result.insert(s.get_slice("/", 1));
+ ScriptCodeCompletionOption option(s.get_slice("/", 1), ScriptCodeCompletionOption::KIND_CONSTANT);
+ r_result.insert(option.display, option);
}
}
@@ -2166,16 +2202,18 @@ static void _find_identifiers(const GDScriptCompletionContext &p_context, bool p
List<StringName> named_scripts;
ScriptServer::get_global_class_list(&named_scripts);
for (List<StringName>::Element *E = named_scripts.front(); E; E = E->next()) {
- r_result.insert(E->get().operator String());
+ ScriptCodeCompletionOption option(E->get().operator String(), ScriptCodeCompletionOption::KIND_CLASS);
+ r_result.insert(option.display, option);
}
// Native classes
for (const Map<StringName, int>::Element *E = GDScriptLanguage::get_singleton()->get_global_map().front(); E; E = E->next()) {
- r_result.insert(E->key().operator String());
+ ScriptCodeCompletionOption option(E->key().operator String(), ScriptCodeCompletionOption::KIND_CLASS);
+ r_result.insert(option.display, option);
}
}
-static void _find_call_arguments(const GDScriptCompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, const StringName &p_method, int p_argidx, bool p_static, Set<String> &r_result, String &r_arghint) {
+static void _find_call_arguments(const GDScriptCompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, const StringName &p_method, int p_argidx, bool p_static, Map<String, ScriptCodeCompletionOption> &r_result, String &r_arghint) {
Variant base = p_base.value;
GDScriptParser::DataType base_type = p_base.type;
@@ -2199,7 +2237,9 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con
if ((p_method == "connect" || p_method == "emit_signal") && p_argidx == 0) {
for (int i = 0; i < base_type.class_type->_signals.size(); i++) {
- r_result.insert(quote_style + base_type.class_type->_signals[i].name.operator String() + quote_style);
+ ScriptCodeCompletionOption option(base_type.class_type->_signals[i].name.operator String(), ScriptCodeCompletionOption::KIND_SIGNAL);
+ option.insert_text = quote_style + option.display + quote_style;
+ r_result.insert(option.display, option);
}
}
@@ -2212,7 +2252,9 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con
List<MethodInfo> signals;
gds->get_script_signal_list(&signals);
for (List<MethodInfo>::Element *E = signals.front(); E; E = E->next()) {
- r_result.insert(quote_style + E->get().name + quote_style);
+ ScriptCodeCompletionOption option(E->get().name, ScriptCodeCompletionOption::KIND_SIGNAL);
+ option.insert_text = quote_style + option.display + quote_style;
+ r_result.insert(option.display, option);
}
}
Ref<GDScript> base_script = gds->get_base_script();
@@ -2250,7 +2292,8 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con
List<String> options;
obj->get_argument_options(p_method, p_argidx, &options);
for (List<String>::Element *F = options.front(); F; F = F->next()) {
- r_result.insert(F->get());
+ ScriptCodeCompletionOption option(F->get(), ScriptCodeCompletionOption::KIND_FUNCTION);
+ r_result.insert(option.display, option);
}
}
}
@@ -2271,7 +2314,9 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con
List<MethodInfo> signals;
ClassDB::get_signal_list(class_name, &signals);
for (List<MethodInfo>::Element *E = signals.front(); E; E = E->next()) {
- r_result.insert(quote_style + E->get().name + quote_style);
+ ScriptCodeCompletionOption option(E->get().name, ScriptCodeCompletionOption::KIND_SIGNAL);
+ option.insert_text = quote_style + option.display + quote_style;
+ r_result.insert(option.display, option);
}
}
@@ -2286,7 +2331,9 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con
continue;
}
String name = s.get_slice("/", 1);
- r_result.insert(quote_style + "/root/" + name + quote_style);
+ ScriptCodeCompletionOption option("/root/" + name, ScriptCodeCompletionOption::KIND_NODE_PATH);
+ option.insert_text = quote_style + option.display + quote_style;
+ r_result.insert(option.display, option);
}
}
@@ -2300,7 +2347,9 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con
continue;
}
String name = s.get_slice("/", 1);
- r_result.insert(quote_style + name + quote_style);
+ ScriptCodeCompletionOption option(name, ScriptCodeCompletionOption::KIND_CONSTANT);
+ option.insert_text = quote_style + option.display + quote_style;
+ r_result.insert(option.display, option);
}
}
@@ -2333,7 +2382,7 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con
}
}
-static void _find_call_arguments(GDScriptCompletionContext &p_context, const GDScriptParser::Node *p_node, int p_argidx, Set<String> &r_result, bool &r_forced, String &r_arghint) {
+static void _find_call_arguments(GDScriptCompletionContext &p_context, const GDScriptParser::Node *p_node, int p_argidx, Map<String, ScriptCodeCompletionOption> &r_result, bool &r_forced, String &r_arghint) {
const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", false) ? "'" : "\"";
@@ -2451,17 +2500,19 @@ static void _find_call_arguments(GDScriptCompletionContext &p_context, const GDS
_find_call_arguments(p_context, ci, function, p_argidx, _static, r_result, r_arghint);
if (function == "connect" && p_argidx == 2) {
- Set<String> methods;
+ Map<String, ScriptCodeCompletionOption> methods;
_find_identifiers_in_base(p_context, connect_base, true, methods);
- for (Set<String>::Element *E = methods.front(); E; E = E->next()) {
- r_result.insert(quote_style + E->get().replace("(", "").replace(")", "") + quote_style);
+ for (Map<String, ScriptCodeCompletionOption>::Element *E = methods.front(); E; E = E->next()) {
+ ScriptCodeCompletionOption &option = E->value();
+ option.insert_text = quote_style + option.display + quote_style;
+ r_result.insert(option.display, option);
}
}
r_forced = r_result.size() > 0;
}
-Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path, Object *p_owner, List<String> *r_options, bool &r_forced, String &r_call_hint) {
+Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path, Object *p_owner, List<ScriptCodeCompletionOption> *r_options, bool &r_forced, String &r_call_hint) {
const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", false) ? "'" : "\"";
@@ -2469,7 +2520,7 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
parser.parse(p_code, p_path.get_base_dir(), false, p_path, true);
r_forced = false;
- Set<String> options;
+ Map<String, ScriptCodeCompletionOption> options;
GDScriptCompletionContext context;
context._class = parser.get_completion_class();
context.block = parser.get_completion_block();
@@ -2490,7 +2541,8 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
List<StringName> constants;
Variant::get_constants_for_type(parser.get_completion_built_in_constant(), &constants);
for (List<StringName>::Element *E = constants.front(); E; E = E->next()) {
- options.insert(E->get().operator String());
+ ScriptCodeCompletionOption option(E->get().operator String(), ScriptCodeCompletionOption::KIND_CONSTANT);
+ options.insert(option.display, option);
}
} break;
case GDScriptParser::COMPLETION_PARENT_FUNCTION: {
@@ -2515,9 +2567,11 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
r_forced = true;
String idopt = opt.unquote();
if (idopt.replace("/", "_").is_valid_identifier()) {
- options.insert(idopt);
+ ScriptCodeCompletionOption option(idopt, ScriptCodeCompletionOption::KIND_NODE_PATH);
+ options.insert(option.display, option);
} else {
- options.insert(opt);
+ ScriptCodeCompletionOption option(opt, ScriptCodeCompletionOption::KIND_NODE_PATH);
+ options.insert(option.display, option);
}
}
}
@@ -2532,7 +2586,8 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
continue;
}
String name = s.get_slice("/", 1);
- options.insert(quote_style + "/root/" + name + quote_style);
+ ScriptCodeCompletionOption option(quote_style + "/root/" + name + quote_style, ScriptCodeCompletionOption::KIND_NODE_PATH);
+ options.insert(option.display, option);
}
}
} break;
@@ -2655,7 +2710,8 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
}
method_hint += ":";
- options.insert(method_hint);
+ ScriptCodeCompletionOption option(method_hint, ScriptCodeCompletionOption::KIND_FUNCTION);
+ options.insert(option.display, option);
}
} break;
case GDScriptParser::COMPLETION_YIELD: {
@@ -2673,7 +2729,9 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
switch (base_type.kind) {
case GDScriptParser::DataType::CLASS: {
for (int i = 0; i < base_type.class_type->_signals.size(); i++) {
- options.insert(quote_style + base_type.class_type->_signals[i].name.operator String() + quote_style);
+ ScriptCodeCompletionOption option(base_type.class_type->_signals[i].name.operator String(), ScriptCodeCompletionOption::KIND_SIGNAL);
+ option.insert_text = quote_style + option.display + quote_style;
+ options.insert(option.display, option);
}
base_type = base_type.class_type->base_type;
} break;
@@ -2684,7 +2742,8 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
List<MethodInfo> signals;
scr->get_script_signal_list(&signals);
for (List<MethodInfo>::Element *E = signals.front(); E; E = E->next()) {
- options.insert(quote_style + E->get().name + quote_style);
+ ScriptCodeCompletionOption option(quote_style + E->get().name + quote_style, ScriptCodeCompletionOption::KIND_SIGNAL);
+ options.insert(option.display, option);
}
Ref<Script> base_script = scr->get_base_script();
if (base_script.is_valid()) {
@@ -2711,7 +2770,8 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
List<MethodInfo> signals;
ClassDB::get_signal_list(class_name, &signals);
for (List<MethodInfo>::Element *E = signals.front(); E; E = E->next()) {
- options.insert(quote_style + E->get().name + quote_style);
+ ScriptCodeCompletionOption option(quote_style + E->get().name + quote_style, ScriptCodeCompletionOption::KIND_SIGNAL);
+ options.insert(option.display, option);
}
} break;
default: {
@@ -2748,18 +2808,21 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
c.line = E->value().expression->line;
if (_guess_expression_type(c, E->value().expression, constant)) {
if (constant.type.has_type && constant.type.is_meta_type) {
- options.insert(E->key().operator String());
+ ScriptCodeCompletionOption option(E->key().operator String(), ScriptCodeCompletionOption::KIND_CLASS);
+ options.insert(option.display, option);
}
}
}
for (int i = 0; i < clss->subclasses.size(); i++) {
if (clss->subclasses[i]->name != StringName()) {
- options.insert(clss->subclasses[i]->name.operator String());
+ ScriptCodeCompletionOption option(clss->subclasses[i]->name.operator String(), ScriptCodeCompletionOption::KIND_CLASS);
+ options.insert(option.display, option);
}
}
clss = clss->owner;
for (int i = 0; i < Variant::VARIANT_MAX; i++) {
- options.insert(Variant::get_type_name((Variant::Type)i));
+ ScriptCodeCompletionOption option(Variant::get_type_name((Variant::Type)i), ScriptCodeCompletionOption::KIND_CLASS);
+ options.insert(option.display, option);
}
}
@@ -2773,18 +2836,21 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
if (Engine::get_singleton()->has_singleton(class_name)) {
continue;
}
- options.insert(class_name);
+ ScriptCodeCompletionOption option(class_name, ScriptCodeCompletionOption::KIND_CLASS);
+ options.insert(option.display, option);
}
// Named scripts
List<StringName> named_scripts;
ScriptServer::get_global_class_list(&named_scripts);
for (List<StringName>::Element *E = named_scripts.front(); E; E = E->next()) {
- options.insert(E->get().operator String());
+ ScriptCodeCompletionOption option(E->get().operator String(), ScriptCodeCompletionOption::KIND_CLASS);
+ options.insert(option.display, option);
}
if (parser.get_completion_identifier_is_function()) {
- options.insert("void");
+ ScriptCodeCompletionOption option("void", ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
+ options.insert(option.display, option);
}
r_forced = true;
} break;
@@ -2831,13 +2897,15 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
c2.line = E->value().expression->line;
if (_guess_expression_type(c2, E->value().expression, constant)) {
if (constant.type.has_type && constant.type.is_meta_type) {
- options.insert(E->key().operator String());
+ ScriptCodeCompletionOption option(E->key().operator String(), ScriptCodeCompletionOption::KIND_CLASS);
+ options.insert(option.display, option);
}
}
}
for (int i = 0; i < base_type.class_type->subclasses.size(); i++) {
if (base_type.class_type->subclasses[i]->name != StringName()) {
- options.insert(base_type.class_type->subclasses[i]->name.operator String());
+ ScriptCodeCompletionOption option(base_type.class_type->subclasses[i]->name.operator String(), ScriptCodeCompletionOption::KIND_CLASS);
+ options.insert(option.display, option);
}
}
@@ -2855,7 +2923,8 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
for (Map<StringName, Variant>::Element *E = constants.front(); E; E = E->next()) {
Ref<Script> const_scr = E->value();
if (const_scr.is_valid()) {
- options.insert(E->key().operator String());
+ ScriptCodeCompletionOption option(E->key().operator String(), ScriptCodeCompletionOption::KIND_CLASS);
+ options.insert(option.display, option);
}
}
Ref<Script> base_script = scr->get_base_script();
@@ -2877,7 +2946,7 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
} break;
}
- for (Set<String>::Element *E = options.front(); E; E = E->next()) {
+ for (Map<String, ScriptCodeCompletionOption>::Element *E = options.front(); E; E = E->next()) {
r_options->push_back(E->get());
}
@@ -2886,7 +2955,7 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
#else
-Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path, Object *p_owner, List<String> *r_options, bool &r_forced, String &r_call_hint) {
+Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path, Object *p_owner, List<ScriptCodeCompletionOption> *r_options, bool &r_forced, String &r_call_hint) {
return OK;
}
diff --git a/modules/websocket/SCsub b/modules/websocket/SCsub
index be26b08a60..033169411f 100644
--- a/modules/websocket/SCsub
+++ b/modules/websocket/SCsub
@@ -5,89 +5,26 @@ Import('env_modules')
# Thirdparty source files
-env_lws = env_modules.Clone()
-
-if env['builtin_libwebsockets'] and not env["platform"] == "javascript": # already builtin for javascript
- thirdparty_dir = "#thirdparty/libwebsockets/"
- helper_dir = "win32helpers/"
- thirdparty_sources = [
-
- "core/alloc.c",
- "core/context.c",
- "core/libwebsockets.c",
- "core/output.c",
- "core/pollfd.c",
- "core/service.c",
-
- "event-libs/poll/poll.c",
-
- "misc/base64-decode.c",
- "misc/lejp.c",
- "misc/sha-1.c",
-
- "roles/h1/ops-h1.c",
- "roles/http/header.c",
- "roles/http/client/client.c",
- "roles/http/client/client-handshake.c",
- "roles/http/server/fops-zip.c",
- "roles/http/server/lejp-conf.c",
- "roles/http/server/parsers.c",
- "roles/http/server/server.c",
- "roles/listen/ops-listen.c",
- "roles/pipe/ops-pipe.c",
- "roles/raw/ops-raw.c",
-
- "roles/ws/client-ws.c",
- "roles/ws/client-parser-ws.c",
- "roles/ws/ops-ws.c",
- "roles/ws/server-ws.c",
-
- "tls/tls.c",
- "tls/tls-client.c",
- "tls/tls-server.c",
-
- "tls/mbedtls/wrapper/library/ssl_cert.c",
- "tls/mbedtls/wrapper/library/ssl_pkey.c",
- "tls/mbedtls/wrapper/library/ssl_stack.c",
- "tls/mbedtls/wrapper/library/ssl_methods.c",
- "tls/mbedtls/wrapper/library/ssl_lib.c",
- "tls/mbedtls/wrapper/library/ssl_x509.c",
- "tls/mbedtls/wrapper/platform/ssl_port.c",
- "tls/mbedtls/wrapper/platform/ssl_pm.c",
- "tls/mbedtls/lws-genhash.c",
- "tls/mbedtls/mbedtls-client.c",
- "tls/mbedtls/lws-genrsa.c",
- "tls/mbedtls/ssl.c",
- "tls/mbedtls/mbedtls-server.c"
+env_ws = env_modules.Clone()
+
+if env['builtin_wslay'] and not env["platform"] == "javascript": # already builtin for javascript
+ wslay_dir = "#thirdparty/wslay/"
+ wslay_sources = [
+ "wslay_net.c",
+ "wslay_event.c",
+ "wslay_queue.c",
+ "wslay_stack.c",
+ "wslay_frame.c",
]
-
- if env["platform"] == "android": # Builtin getifaddrs
- thirdparty_sources += ["misc/getifaddrs.c"]
-
- if env["platform"] == "windows" or env["platform"] == "uwp": # Winsock
- thirdparty_sources += ["plat/lws-plat-win.c", helper_dir + "getopt.c", helper_dir + "getopt_long.c", helper_dir + "gettimeofday.c"]
- else: # Unix socket
- thirdparty_sources += ["plat/lws-plat-unix.c"]
-
- thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
-
- env_lws.Prepend(CPPPATH=[thirdparty_dir])
-
- if env['builtin_mbedtls']:
- mbedtls_includes = "#thirdparty/mbedtls/include"
- env_lws.Prepend(CPPPATH=[mbedtls_includes])
-
- wrapper_includes = ["#thirdparty/libwebsockets/tls/mbedtls/wrapper/include/" + inc for inc in ["internal", "openssl", "platform", ""]]
- env_lws.Prepend(CPPPATH=wrapper_includes)
-
+ wslay_sources = [wslay_dir + s for s in wslay_sources]
+ env_ws.Prepend(CPPPATH=[wslay_dir + "includes/"])
+ env_ws.Append(CPPDEFINES=["HAVE_CONFIG_H"])
if env["platform"] == "windows" or env["platform"] == "uwp":
- env_lws.Prepend(CPPPATH=[thirdparty_dir + helper_dir])
-
- if env["platform"] == "uwp":
- env_lws.Append(CPPDEFINES=["LWS_MINGW_SUPPORT"])
-
- env_thirdparty = env_lws.Clone()
- env_thirdparty.disable_warnings()
- env_thirdparty.add_source_files(env.modules_sources, thirdparty_sources)
-
-env_lws.add_source_files(env.modules_sources, "*.cpp")
+ env_ws.Append(CPPDEFINES=["HAVE_WINSOCK2_H"])
+ else:
+ env_ws.Append(CPPDEFINES=["HAVE_NETINET_IN_H"])
+ env_wslay = env_ws.Clone()
+ env_wslay.disable_warnings()
+ env_wslay.add_source_files(env.modules_sources, wslay_sources)
+
+env_ws.add_source_files(env.modules_sources, "*.cpp")
diff --git a/modules/websocket/doc_classes/WebSocketClient.xml b/modules/websocket/doc_classes/WebSocketClient.xml
index 0d425ad1dd..c3baf9de83 100644
--- a/modules/websocket/doc_classes/WebSocketClient.xml
+++ b/modules/websocket/doc_classes/WebSocketClient.xml
@@ -22,7 +22,7 @@
<argument index="2" name="gd_mp_api" type="bool" default="false">
</argument>
<description>
- Connects to the given URL requesting one of the given [code]protocols[/code] as sub-protocol.
+ Connects to the given URL requesting one of the given [code]protocols[/code] as sub-protocol. If the list empty (default), no sub-protocol will be requested.
If [code]true[/code] is passed as [code]gd_mp_api[/code], the client will behave like a network peer for the [MultiplayerAPI], connections to non-Godot servers will not work, and [signal data_received] will not be emitted.
If [code]false[/code] is passed instead (default), you must call [PacketPeer] functions ([code]put_packet[/code], [code]get_packet[/code], etc.) on the [WebSocketPeer] returned via [code]get_peer(1)[/code] and not on this object directly (e.g. [code]get_peer(1).put_packet(data)[/code]).
</description>
diff --git a/modules/websocket/doc_classes/WebSocketServer.xml b/modules/websocket/doc_classes/WebSocketServer.xml
index 1af5e403e6..63318e5874 100644
--- a/modules/websocket/doc_classes/WebSocketServer.xml
+++ b/modules/websocket/doc_classes/WebSocketServer.xml
@@ -69,7 +69,7 @@
</argument>
<description>
Starts listening on the given port.
- You can specify the desired subprotocols via the "protocols" array. If the list empty (default), "binary" will be used.
+ You can specify the desired subprotocols via the "protocols" array. If the list empty (default), no sub-protocol will be requested.
If [code]true[/code] is passed as [code]gd_mp_api[/code], the server will behave like a network peer for the [MultiplayerAPI], connections from non-Godot clients will not work, and [signal data_received] will not be emitted.
If [code]false[/code] is passed instead (default), you must call [PacketPeer] functions ([code]put_packet[/code], [code]get_packet[/code], etc.), on the [WebSocketPeer] returned via [code]get_peer(id)[/code] to communicate with the peer with given [code]id[/code] (e.g. [code]get_peer(id).get_available_packet_count[/code]).
</description>
diff --git a/modules/websocket/lws_client.cpp b/modules/websocket/lws_client.cpp
deleted file mode 100644
index f139a4ef66..0000000000
--- a/modules/websocket/lws_client.cpp
+++ /dev/null
@@ -1,248 +0,0 @@
-/*************************************************************************/
-/* lws_client.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef JAVASCRIPT_ENABLED
-
-#include "lws_client.h"
-#include "core/io/ip.h"
-#include "core/project_settings.h"
-#if defined(LWS_OPENSSL_SUPPORT)
-#include "core/io/stream_peer_ssl.h"
-#include "tls/mbedtls/wrapper/include/openssl/ssl.h"
-#endif
-
-Error LWSClient::connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, PoolVector<String> p_protocols) {
-
- ERR_FAIL_COND_V(context != NULL, FAILED);
-
- IP_Address addr;
-
- if (!p_host.is_valid_ip_address()) {
- addr = IP::get_singleton()->resolve_hostname(p_host);
- } else {
- addr = p_host;
- }
-
- ERR_FAIL_COND_V(!addr.is_valid(), ERR_INVALID_PARAMETER);
-
- // Prepare protocols
- _lws_make_protocols(this, &LWSClient::_lws_gd_callback, p_protocols, &_lws_ref);
-
- // Init lws client
- struct lws_context_creation_info info;
- struct lws_client_connect_info i;
-
- memset(&i, 0, sizeof i);
- memset(&info, 0, sizeof info);
-
- info.port = CONTEXT_PORT_NO_LISTEN;
- info.protocols = _lws_ref->lws_structs;
- info.gid = -1;
- info.uid = -1;
- //info.ws_ping_pong_interval = 5;
- info.user = _lws_ref;
-#if defined(LWS_OPENSSL_SUPPORT)
- info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
-#endif
- context = lws_create_context(&info);
-
- if (context == NULL) {
- _lws_free_ref(_lws_ref);
- _lws_ref = NULL;
- ERR_EXPLAIN("Unable to create lws context");
- ERR_FAIL_V(FAILED);
- }
-
- i.context = context;
- if (p_protocols.size() > 0)
- i.protocol = _lws_ref->lws_names;
- else
- i.protocol = NULL;
-
- if (p_ssl) {
- i.ssl_connection = LCCSCF_USE_SSL;
- if (!verify_ssl)
- i.ssl_connection |= LCCSCF_ALLOW_SELFSIGNED;
- } else {
- i.ssl_connection = 0;
- }
-
- // These CharStrings needs to survive till we call lws_client_connect_via_info
- CharString addr_ch = ((String)addr).ascii();
- CharString host_ch = p_host.utf8();
- CharString path_ch = p_path.utf8();
- i.address = addr_ch.get_data();
- i.host = host_ch.get_data();
- i.path = path_ch.get_data();
- i.port = p_port;
-
- lws_client_connect_via_info(&i);
-
- return OK;
-};
-
-int LWSClient::get_max_packet_size() const {
- return (1 << _out_buf_size) - PROTO_SIZE;
-}
-
-void LWSClient::poll() {
-
- _lws_poll();
-}
-
-int LWSClient::_handle_cb(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) {
-
- Ref<LWSPeer> peer = static_cast<Ref<LWSPeer> >(_peer);
- LWSPeer::PeerData *peer_data = (LWSPeer::PeerData *)user;
-
- switch (reason) {
-#if defined(LWS_OPENSSL_SUPPORT)
- case LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS: {
- PoolByteArray arr = StreamPeerSSL::get_project_cert_array();
- if (arr.size() > 0)
- SSL_CTX_add_client_CA((SSL_CTX *)user, d2i_X509(NULL, &arr.read()[0], arr.size()));
- else if (verify_ssl)
- WARN_PRINTS("No CA cert specified in project settings, SSL will not work");
- } break;
-#endif
- case LWS_CALLBACK_CLIENT_ESTABLISHED:
- peer->set_wsi(wsi, _in_buf_size, _in_pkt_size, _out_buf_size, _out_pkt_size);
- peer_data->peer_id = 0;
- peer_data->force_close = false;
- peer_data->clean_close = false;
- _on_connect(lws_get_protocol(wsi)->name);
- break;
-
- case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
- _on_error();
- destroy_context();
- return -1; // We should close the connection (would probably happen anyway)
-
- case LWS_CALLBACK_WS_PEER_INITIATED_CLOSE: {
- int code;
- String reason2 = peer->get_close_reason(in, len, code);
- peer_data->clean_close = true;
- _on_close_request(code, reason2);
- return 0;
- }
-
- case LWS_CALLBACK_CLIENT_CLOSED:
- peer->close();
- destroy_context();
- _on_disconnect(peer_data->clean_close);
- return 0; // We can end here
-
- case LWS_CALLBACK_CLIENT_RECEIVE:
- peer->read_wsi(in, len);
- if (peer->get_available_packet_count() > 0)
- _on_peer_packet();
- break;
-
- case LWS_CALLBACK_CLIENT_WRITEABLE:
- if (peer_data->force_close) {
- peer->send_close_status(wsi);
- return -1;
- }
-
- peer->write_wsi();
- break;
-
- default:
- break;
- }
-
- return 0;
-}
-
-Ref<WebSocketPeer> LWSClient::get_peer(int p_peer_id) const {
-
- return _peer;
-}
-
-NetworkedMultiplayerPeer::ConnectionStatus LWSClient::get_connection_status() const {
-
- if (context == NULL)
- return CONNECTION_DISCONNECTED;
-
- if (_peer->is_connected_to_host())
- return CONNECTION_CONNECTED;
-
- return CONNECTION_CONNECTING;
-}
-
-void LWSClient::disconnect_from_host(int p_code, String p_reason) {
-
- if (context == NULL)
- return;
-
- _peer->close(p_code, p_reason);
-};
-
-IP_Address LWSClient::get_connected_host() const {
-
- return IP_Address();
-};
-
-uint16_t LWSClient::get_connected_port() const {
-
- return 1025;
-};
-
-Error LWSClient::set_buffers(int p_in_buffer, int p_in_packets, int p_out_buffer, int p_out_packets) {
- ERR_EXPLAIN("Buffers sizes can only be set before listening or connecting");
- ERR_FAIL_COND_V(context != NULL, FAILED);
-
- _in_buf_size = nearest_shift(p_in_buffer - 1) + 10;
- _in_pkt_size = nearest_shift(p_in_packets - 1);
- _out_buf_size = nearest_shift(p_out_buffer - 1) + 10;
- _out_pkt_size = nearest_shift(p_out_packets - 1);
- return OK;
-}
-
-LWSClient::LWSClient() {
- _in_buf_size = nearest_shift((int)GLOBAL_GET(WSC_IN_BUF) - 1) + 10;
- _in_pkt_size = nearest_shift((int)GLOBAL_GET(WSC_IN_PKT) - 1);
- _out_buf_size = nearest_shift((int)GLOBAL_GET(WSC_OUT_BUF) - 1) + 10;
- _out_pkt_size = nearest_shift((int)GLOBAL_GET(WSC_OUT_PKT) - 1);
-
- context = NULL;
- _lws_ref = NULL;
- _peer = Ref<LWSPeer>(memnew(LWSPeer));
-};
-
-LWSClient::~LWSClient() {
-
- invalidate_lws_ref(); // We do not want any more callback
- disconnect_from_host();
- destroy_context();
- _peer = Ref<LWSPeer>();
-};
-
-#endif // JAVASCRIPT_ENABLED
diff --git a/modules/websocket/lws_helper.cpp b/modules/websocket/lws_helper.cpp
deleted file mode 100644
index a652779960..0000000000
--- a/modules/websocket/lws_helper.cpp
+++ /dev/null
@@ -1,157 +0,0 @@
-/*************************************************************************/
-/* lws_helper.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#if !defined(JAVASCRIPT_ENABLED)
-
-#include "lws_helper.h"
-
-_LWSRef *_lws_create_ref(void *obj) {
-
- _LWSRef *out = (_LWSRef *)memalloc(sizeof(_LWSRef));
- out->is_destroying = false;
- out->free_context = false;
- out->is_polling = false;
- out->obj = obj;
- out->is_valid = true;
- out->lws_structs = NULL;
- out->lws_names = NULL;
- return out;
-}
-
-void _lws_free_ref(_LWSRef *ref) {
- // Free strings and structs
- memfree(ref->lws_structs);
- memfree(ref->lws_names);
- // Free ref
- memfree(ref);
-}
-
-bool _lws_destroy(struct lws_context *context, _LWSRef *ref) {
- if (context == NULL || ref->is_destroying)
- return false;
-
- if (ref->is_polling) {
- ref->free_context = true;
- return false;
- }
-
- ref->is_destroying = true;
- lws_context_destroy(context);
- _lws_free_ref(ref);
- return true;
-}
-
-bool _lws_poll(struct lws_context *context, _LWSRef *ref) {
-
- ERR_FAIL_COND_V(context == NULL, false);
- ERR_FAIL_COND_V(ref == NULL, false);
-
- ref->is_polling = true;
- lws_service(context, 0);
- ref->is_polling = false;
-
- if (!ref->free_context)
- return false; // Nothing to do
-
- bool is_valid = ref->is_valid; // Might have been destroyed by poll
-
- _lws_destroy(context, ref); // Will destroy context and ref
-
- return is_valid; // If the object should NULL its context and ref
-}
-
-/*
- * Prepare the protocol_structs to be fed to context.
- * Also prepare the protocol string used by the client.
- */
-void _lws_make_protocols(void *p_obj, lws_callback_function *p_callback, PoolVector<String> p_names, _LWSRef **r_lws_ref) {
- // The input strings might go away after this call, we need to copy them.
- // We will clear them when destroying the context.
- int i;
- int len = p_names.size();
- size_t data_size = sizeof(struct LWSPeer::PeerData);
- PoolVector<String>::Read pnr = p_names.read();
-
- // This is a reference connecting the object with lws keep track of status, mallocs, etc.
- // Must survive as long the context.
- // Must be freed manually when context creation fails.
- _LWSRef *ref = _lws_create_ref(p_obj);
-
- // LWS protocol structs.
- ref->lws_structs = (struct lws_protocols *)memalloc(sizeof(struct lws_protocols) * (len + 2));
- memset(ref->lws_structs, 0, sizeof(struct lws_protocols) * (len + 2));
-
- CharString strings = p_names.join(",").ascii();
- int str_len = strings.length();
-
- // Joined string of protocols, double the size: comma separated first, NULL separated last
- ref->lws_names = (char *)memalloc((str_len + 1) * 2); // Plus the terminator
-
- char *names_ptr = ref->lws_names;
- struct lws_protocols *structs_ptr = ref->lws_structs;
-
- // Comma separated protocols string to be used in client Sec-WebSocket-Protocol header
- if (str_len > 0)
- copymem(names_ptr, strings.get_data(), str_len);
- names_ptr[str_len] = '\0'; // NULL terminator
-
- // NULL terminated protocol strings to be used in protocol structs
- if (str_len > 0)
- copymem(&names_ptr[str_len + 1], strings.get_data(), str_len);
- names_ptr[(str_len * 2) + 1] = '\0'; // NULL terminator
- int pos = str_len + 1;
-
- // The first protocol is the default for any http request (before upgrade).
- // It is also used as the websocket protocol when no subprotocol is specified.
- structs_ptr[0].name = "default";
- structs_ptr[0].callback = p_callback;
- structs_ptr[0].per_session_data_size = data_size;
- structs_ptr[0].rx_buffer_size = LWS_BUF_SIZE;
- structs_ptr[0].tx_packet_size = LWS_PACKET_SIZE;
- // Add user defined protocols
- for (i = 0; i < len; i++) {
- structs_ptr[i + 1].name = (const char *)&names_ptr[pos];
- structs_ptr[i + 1].callback = p_callback;
- structs_ptr[i + 1].per_session_data_size = data_size;
- structs_ptr[i + 1].rx_buffer_size = LWS_BUF_SIZE;
- structs_ptr[i + 1].tx_packet_size = LWS_PACKET_SIZE;
- pos += pnr[i].ascii().length() + 1;
- names_ptr[pos - 1] = '\0';
- }
- // Add protocols terminator
- structs_ptr[len + 1].name = NULL;
- structs_ptr[len + 1].callback = NULL;
- structs_ptr[len + 1].per_session_data_size = 0;
- structs_ptr[len + 1].rx_buffer_size = 0;
-
- *r_lws_ref = ref;
-}
-
-#endif
diff --git a/modules/websocket/lws_helper.h b/modules/websocket/lws_helper.h
deleted file mode 100644
index 265dc4e6ad..0000000000
--- a/modules/websocket/lws_helper.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*************************************************************************/
-/* lws_helper.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef LWS_HELPER_H
-#define LWS_HELPER_H
-
-#define LWS_BUF_SIZE 65536
-#define LWS_PACKET_SIZE LWS_BUF_SIZE
-
-#include "core/io/stream_peer.h"
-#include "core/os/os.h"
-#include "core/reference.h"
-#include "core/ring_buffer.h"
-#include "lws_peer.h"
-
-struct _LWSRef {
- bool free_context;
- bool is_polling;
- bool is_valid;
- bool is_destroying;
- void *obj;
- struct lws_protocols *lws_structs;
- char *lws_names;
-};
-
-_LWSRef *_lws_create_ref(void *obj);
-void _lws_free_ref(_LWSRef *ref);
-bool _lws_destroy(struct lws_context *context, _LWSRef *ref);
-bool _lws_poll(struct lws_context *context, _LWSRef *ref);
-void _lws_make_protocols(void *p_obj, lws_callback_function *p_callback, PoolVector<String> p_names, _LWSRef **r_lws_ref);
-
-/* clang-format off */
-#define LWS_HELPER(CNAME) \
-protected: \
- struct _LWSRef *_lws_ref; \
- struct lws_context *context; \
- bool _keep_servicing; \
- \
- static int _lws_gd_callback(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { \
- \
- if (wsi == NULL) { \
- return 0; \
- } \
- \
- struct _LWSRef *ref = (struct _LWSRef *)lws_context_user(lws_get_context(wsi)); \
- if (!ref->is_valid) \
- return 0; \
- CNAME *helper = (CNAME *)ref->obj; \
- helper->_keep_servicing = true; \
- return helper->_handle_cb(wsi, reason, user, in, len); \
- } \
- \
- void invalidate_lws_ref() { \
- if (_lws_ref != NULL) \
- _lws_ref->is_valid = false; \
- } \
- \
- void destroy_context() { \
- if (_lws_destroy(context, _lws_ref)) { \
- context = NULL; \
- _lws_ref = NULL; \
- } \
- } \
- \
-public: \
- virtual int _handle_cb(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); \
- \
- void _lws_poll() { \
- ERR_FAIL_COND(context == NULL); \
- do { \
- _keep_servicing = false; \
- if (::_lws_poll(context, _lws_ref)) { \
- context = NULL; \
- _lws_ref = NULL; \
- break; \
- } \
- } while (_keep_servicing); \
- } \
- \
-protected:
-
-/* clang-format on */
-
-#endif // LWS_HELPER_H
diff --git a/modules/websocket/lws_peer.cpp b/modules/websocket/lws_peer.cpp
deleted file mode 100644
index a7c85450fa..0000000000
--- a/modules/websocket/lws_peer.cpp
+++ /dev/null
@@ -1,270 +0,0 @@
-/*************************************************************************/
-/* lws_peer.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef JAVASCRIPT_ENABLED
-
-#include "lws_peer.h"
-
-#include "core/io/ip.h"
-
-// Needed for socket_helpers on Android at least. UNIXes has it, just include if not windows
-#if !defined(WINDOWS_ENABLED)
-#include <netinet/in.h>
-#include <sys/socket.h>
-#endif
-
-#include "drivers/unix/net_socket_posix.h"
-
-void LWSPeer::set_wsi(struct lws *p_wsi, unsigned int p_in_buf_size, unsigned int p_in_pkt_size, unsigned int p_out_buf_size, unsigned int p_out_pkt_size) {
- ERR_FAIL_COND(wsi != NULL);
-
- _in_buffer.resize(p_in_pkt_size, p_in_buf_size);
- _out_buffer.resize(p_out_pkt_size, p_out_buf_size);
- _packet_buffer.resize((1 << MAX(p_in_buf_size, p_out_buf_size)) + LWS_PRE);
- wsi = p_wsi;
-};
-
-void LWSPeer::set_write_mode(WriteMode p_mode) {
- write_mode = p_mode;
-}
-
-LWSPeer::WriteMode LWSPeer::get_write_mode() const {
- return write_mode;
-}
-
-Error LWSPeer::read_wsi(void *in, size_t len) {
-
- ERR_FAIL_COND_V(!is_connected_to_host(), FAILED);
-
- if (lws_is_first_fragment(wsi))
- _in_size = 0;
- else if (_in_size == -1) // Trash this frame
- return ERR_FILE_CORRUPT;
-
- Error err = _in_buffer.write_packet((const uint8_t *)in, len, NULL);
-
- if (err != OK) {
- _in_buffer.discard_payload(_in_size);
- _in_size = -1;
- ERR_FAIL_V(err);
- }
-
- _in_size += len;
-
- if (lws_is_final_fragment(wsi)) {
- uint8_t is_string = lws_frame_is_binary(wsi) ? 0 : 1;
- err = _in_buffer.write_packet(NULL, _in_size, &is_string);
- if (err != OK) {
- _in_buffer.discard_payload(_in_size);
- _in_size = -1;
- ERR_FAIL_V(err);
- }
- }
-
- return OK;
-}
-
-Error LWSPeer::write_wsi() {
-
- ERR_FAIL_COND_V(!is_connected_to_host(), FAILED);
-
- PoolVector<uint8_t> tmp;
- int count = _out_buffer.packets_left();
-
- if (count == 0)
- return OK;
-
- int read = 0;
- uint8_t is_string = 0;
- PoolVector<uint8_t>::Write rw = _packet_buffer.write();
- _out_buffer.read_packet(&(rw[LWS_PRE]), _packet_buffer.size() - LWS_PRE, &is_string, read);
-
- enum lws_write_protocol mode = is_string ? LWS_WRITE_TEXT : LWS_WRITE_BINARY;
- lws_write(wsi, &(rw[LWS_PRE]), read, mode);
-
- if (count > 1)
- lws_callback_on_writable(wsi); // we want to write more!
-
- return OK;
-}
-
-Error LWSPeer::put_packet(const uint8_t *p_buffer, int p_buffer_size) {
-
- ERR_FAIL_COND_V(!is_connected_to_host(), FAILED);
-
- uint8_t is_string = write_mode == WRITE_MODE_TEXT;
- _out_buffer.write_packet(p_buffer, p_buffer_size, &is_string);
- lws_callback_on_writable(wsi); // notify that we want to write
- return OK;
-};
-
-Error LWSPeer::get_packet(const uint8_t **r_buffer, int &r_buffer_size) {
-
- r_buffer_size = 0;
-
- ERR_FAIL_COND_V(!is_connected_to_host(), FAILED);
-
- if (_in_buffer.packets_left() == 0)
- return ERR_UNAVAILABLE;
-
- int read = 0;
- PoolVector<uint8_t>::Write rw = _packet_buffer.write();
- _in_buffer.read_packet(rw.ptr(), _packet_buffer.size(), &_is_string, read);
-
- *r_buffer = rw.ptr();
- r_buffer_size = read;
-
- return OK;
-};
-
-int LWSPeer::get_available_packet_count() const {
-
- if (!is_connected_to_host())
- return 0;
-
- return _in_buffer.packets_left();
-};
-
-bool LWSPeer::was_string_packet() const {
-
- return _is_string;
-};
-
-bool LWSPeer::is_connected_to_host() const {
-
- return wsi != NULL;
-};
-
-String LWSPeer::get_close_reason(void *in, size_t len, int &r_code) {
- String s;
- r_code = 0;
- if (len < 2) // From docs this should not happen
- return s;
-
- const uint8_t *b = (const uint8_t *)in;
- r_code = b[0] << 8 | b[1];
-
- if (len > 2) {
- const char *utf8 = (const char *)&b[2];
- s.parse_utf8(utf8, len - 2);
- }
- return s;
-}
-
-void LWSPeer::send_close_status(struct lws *p_wsi) {
- if (close_code == -1)
- return;
-
- int len = close_reason.size();
- ERR_FAIL_COND(len > 123); // Maximum allowed reason size in bytes
-
- lws_close_status code = (lws_close_status)close_code;
- unsigned char *reason = len > 0 ? (unsigned char *)close_reason.utf8().ptrw() : NULL;
-
- lws_close_reason(p_wsi, code, reason, len);
-
- close_code = -1;
- close_reason = "";
-}
-
-void LWSPeer::close(int p_code, String p_reason) {
- if (wsi != NULL) {
- close_code = p_code;
- close_reason = p_reason;
- PeerData *data = ((PeerData *)lws_wsi_user(wsi));
- data->force_close = true;
- data->clean_close = true;
- lws_callback_on_writable(wsi); // Notify that we want to disconnect
- } else {
- close_code = -1;
- close_reason = "";
- }
- wsi = NULL;
- _in_buffer.clear();
- _out_buffer.clear();
- _in_size = 0;
- _is_string = 0;
- _packet_buffer.resize(0);
-};
-
-IP_Address LWSPeer::get_connected_host() const {
-
- ERR_FAIL_COND_V(!is_connected_to_host(), IP_Address());
-
- IP_Address ip;
- uint16_t port = 0;
-
- struct sockaddr_storage addr;
- socklen_t len = sizeof(addr);
-
- int fd = lws_get_socket_fd(wsi);
- ERR_FAIL_COND_V(fd == -1, IP_Address());
-
- int ret = getpeername(fd, (struct sockaddr *)&addr, &len);
- ERR_FAIL_COND_V(ret != 0, IP_Address());
-
- NetSocketPosix::_set_ip_port(&addr, ip, port);
-
- return ip;
-};
-
-uint16_t LWSPeer::get_connected_port() const {
-
- ERR_FAIL_COND_V(!is_connected_to_host(), 0);
-
- IP_Address ip;
- uint16_t port = 0;
-
- struct sockaddr_storage addr;
- socklen_t len = sizeof(addr);
-
- int fd = lws_get_socket_fd(wsi);
- ERR_FAIL_COND_V(fd == -1, 0);
-
- int ret = getpeername(fd, (struct sockaddr *)&addr, &len);
- ERR_FAIL_COND_V(ret != 0, 0);
-
- NetSocketPosix::_set_ip_port(&addr, ip, port);
-
- return port;
-};
-
-LWSPeer::LWSPeer() {
- wsi = NULL;
- write_mode = WRITE_MODE_BINARY;
- close();
-};
-
-LWSPeer::~LWSPeer() {
-
- close();
-};
-
-#endif // JAVASCRIPT_ENABLED
diff --git a/modules/websocket/lws_server.cpp b/modules/websocket/lws_server.cpp
deleted file mode 100644
index 482c02dc60..0000000000
--- a/modules/websocket/lws_server.cpp
+++ /dev/null
@@ -1,225 +0,0 @@
-/*************************************************************************/
-/* lws_server.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef JAVASCRIPT_ENABLED
-
-#include "lws_server.h"
-#include "core/os/os.h"
-#include "core/project_settings.h"
-
-Error LWSServer::listen(int p_port, PoolVector<String> p_protocols, bool gd_mp_api) {
-
- ERR_FAIL_COND_V(context != NULL, FAILED);
-
- _is_multiplayer = gd_mp_api;
-
- struct lws_context_creation_info info;
- memset(&info, 0, sizeof info);
-
- // Prepare lws protocol structs
- _lws_make_protocols(this, &LWSServer::_lws_gd_callback, p_protocols, &_lws_ref);
-
- info.port = p_port;
- info.user = _lws_ref;
- info.protocols = _lws_ref->lws_structs;
- info.gid = -1;
- info.uid = -1;
- //info.ws_ping_pong_interval = 5;
-
- context = lws_create_context(&info);
-
- if (context == NULL) {
- _lws_free_ref(_lws_ref);
- _lws_ref = NULL;
- ERR_EXPLAIN("Unable to create LWS context");
- ERR_FAIL_V(FAILED);
- }
-
- return OK;
-}
-
-bool LWSServer::is_listening() const {
- return context != NULL;
-}
-
-int LWSServer::get_max_packet_size() const {
- return (1 << _out_buf_size) - PROTO_SIZE;
-}
-
-int LWSServer::_handle_cb(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) {
-
- LWSPeer::PeerData *peer_data = (LWSPeer::PeerData *)user;
-
- switch (reason) {
- case LWS_CALLBACK_HTTP:
- // no http for now
- // closing immediately returning -1;
- return -1;
-
- case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
- // check header here?
- break;
-
- case LWS_CALLBACK_ESTABLISHED: {
- int32_t id = _gen_unique_id();
-
- Ref<LWSPeer> peer = Ref<LWSPeer>(memnew(LWSPeer));
- peer->set_wsi(wsi, _in_buf_size, _in_pkt_size, _out_buf_size, _out_pkt_size);
- _peer_map[id] = peer;
-
- peer_data->peer_id = id;
- peer_data->force_close = false;
- peer_data->clean_close = false;
- _on_connect(id, lws_get_protocol(wsi)->name);
- break;
- }
-
- case LWS_CALLBACK_WS_PEER_INITIATED_CLOSE: {
- if (peer_data == NULL)
- return 0;
-
- int32_t id = peer_data->peer_id;
- if (_peer_map.has(id)) {
- int code;
- Ref<LWSPeer> peer = _peer_map[id];
- String reason2 = peer->get_close_reason(in, len, code);
- peer_data->clean_close = true;
- _on_close_request(id, code, reason2);
- }
- return 0;
- }
-
- case LWS_CALLBACK_CLOSED: {
- if (peer_data == NULL)
- return 0;
- int32_t id = peer_data->peer_id;
- bool clean = peer_data->clean_close;
- if (_peer_map.has(id)) {
- _peer_map[id]->close();
- _peer_map.erase(id);
- }
- _on_disconnect(id, clean);
- return 0; // we can end here
- }
-
- case LWS_CALLBACK_RECEIVE: {
- int32_t id = peer_data->peer_id;
- if (_peer_map.has(id)) {
- static_cast<Ref<LWSPeer> >(_peer_map[id])->read_wsi(in, len);
- if (_peer_map[id]->get_available_packet_count() > 0)
- _on_peer_packet(id);
- }
- break;
- }
-
- case LWS_CALLBACK_SERVER_WRITEABLE: {
- int id = peer_data->peer_id;
- if (peer_data->force_close) {
- if (_peer_map.has(id)) {
- Ref<LWSPeer> peer = _peer_map[id];
- peer->send_close_status(wsi);
- }
- return -1;
- }
-
- if (_peer_map.has(id))
- static_cast<Ref<LWSPeer> >(_peer_map[id])->write_wsi();
- break;
- }
-
- default:
- break;
- }
-
- return 0;
-}
-
-void LWSServer::stop() {
- if (context == NULL)
- return;
-
- _peer_map.clear();
- destroy_context();
- context = NULL;
-}
-
-bool LWSServer::has_peer(int p_id) const {
- return _peer_map.has(p_id);
-}
-
-Ref<WebSocketPeer> LWSServer::get_peer(int p_id) const {
- ERR_FAIL_COND_V(!has_peer(p_id), NULL);
- return _peer_map[p_id];
-}
-
-IP_Address LWSServer::get_peer_address(int p_peer_id) const {
- ERR_FAIL_COND_V(!has_peer(p_peer_id), IP_Address());
-
- return _peer_map[p_peer_id]->get_connected_host();
-}
-
-int LWSServer::get_peer_port(int p_peer_id) const {
- ERR_FAIL_COND_V(!has_peer(p_peer_id), 0);
-
- return _peer_map[p_peer_id]->get_connected_port();
-}
-
-void LWSServer::disconnect_peer(int p_peer_id, int p_code, String p_reason) {
- ERR_FAIL_COND(!has_peer(p_peer_id));
-
- get_peer(p_peer_id)->close(p_code, p_reason);
-}
-
-Error LWSServer::set_buffers(int p_in_buffer, int p_in_packets, int p_out_buffer, int p_out_packets) {
- ERR_EXPLAIN("Buffers sizes can only be set before listening or connecting");
- ERR_FAIL_COND_V(context != NULL, FAILED);
-
- _in_buf_size = nearest_shift(p_in_buffer - 1) + 10;
- _in_pkt_size = nearest_shift(p_in_packets - 1);
- _out_buf_size = nearest_shift(p_out_buffer - 1) + 10;
- _out_pkt_size = nearest_shift(p_out_packets - 1);
- return OK;
-}
-
-LWSServer::LWSServer() {
- _in_buf_size = nearest_shift((int)GLOBAL_GET(WSS_IN_BUF) - 1) + 10;
- _in_pkt_size = nearest_shift((int)GLOBAL_GET(WSS_IN_PKT) - 1);
- _out_buf_size = nearest_shift((int)GLOBAL_GET(WSS_OUT_BUF) - 1) + 10;
- _out_pkt_size = nearest_shift((int)GLOBAL_GET(WSS_OUT_PKT) - 1);
- context = NULL;
- _lws_ref = NULL;
-}
-
-LWSServer::~LWSServer() {
- invalidate_lws_ref(); // we do not want any more callbacks
- stop();
-}
-
-#endif // JAVASCRIPT_ENABLED
diff --git a/modules/websocket/register_types.cpp b/modules/websocket/register_types.cpp
index 39bf3de982..1c808f0d5c 100644
--- a/modules/websocket/register_types.cpp
+++ b/modules/websocket/register_types.cpp
@@ -37,9 +37,8 @@
#include "emws_peer.h"
#include "emws_server.h"
#else
-#include "lws_client.h"
-#include "lws_peer.h"
-#include "lws_server.h"
+#include "wsl_client.h"
+#include "wsl_server.h"
#endif
void register_websocket_types() {
@@ -64,9 +63,9 @@ void register_websocket_types() {
EMWSClient::make_default();
EMWSServer::make_default();
#else
- LWSPeer::make_default();
- LWSClient::make_default();
- LWSServer::make_default();
+ WSLPeer::make_default();
+ WSLClient::make_default();
+ WSLServer::make_default();
#endif
ClassDB::register_virtual_class<WebSocketMultiplayerPeer>();
diff --git a/modules/websocket/wsl_client.cpp b/modules/websocket/wsl_client.cpp
new file mode 100644
index 0000000000..b2d865a58f
--- /dev/null
+++ b/modules/websocket/wsl_client.cpp
@@ -0,0 +1,362 @@
+/*************************************************************************/
+/* wsl_client.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef JAVASCRIPT_ENABLED
+
+#include "wsl_client.h"
+#include "core/io/ip.h"
+#include "core/project_settings.h"
+
+void WSLClient::_do_handshake() {
+ if (_requested < _request.size() - 1) {
+ int sent = 0;
+ Error err = _connection->put_partial_data(((const uint8_t *)_request.get_data() + _requested), _request.size() - _requested - 1, sent);
+ // Sending handshake failed
+ if (err != OK) {
+ disconnect_from_host();
+ _on_error();
+ return;
+ }
+ _requested += sent;
+
+ } else {
+ int read = 0;
+ while (true) {
+ if (_resp_pos >= WSL_MAX_HEADER_SIZE) {
+ // Header is too big
+ disconnect_from_host();
+ _on_error();
+ ERR_EXPLAIN("Response headers too big");
+ ERR_FAIL();
+ }
+ Error err = _connection->get_partial_data(&_resp_buf[_resp_pos], 1, read);
+ if (err == ERR_FILE_EOF) {
+ // We got a disconnect.
+ disconnect_from_host();
+ _on_error();
+ return;
+ } else if (err != OK) {
+ // Got some error.
+ disconnect_from_host();
+ _on_error();
+ return;
+ } else if (read != 1) {
+ // Busy, wait next poll.
+ break;
+ }
+ // Check "\r\n\r\n" header terminator
+ char *r = (char *)_resp_buf;
+ int l = _resp_pos;
+ if (l > 3 && r[l] == '\n' && r[l - 1] == '\r' && r[l - 2] == '\n' && r[l - 3] == '\r') {
+ r[l - 3] = '\0';
+ String protocol;
+ // Response is over, verify headers and create peer.
+ if (!_verify_headers(protocol)) {
+ disconnect_from_host();
+ _on_error();
+ ERR_EXPLAIN("Invalid response headers");
+ ERR_FAIL();
+ }
+ // Create peer.
+ WSLPeer::PeerData *data = memnew(struct WSLPeer::PeerData);
+ data->obj = this;
+ data->conn = _connection;
+ data->is_server = false;
+ data->id = 1;
+ _peer->make_context(data, _in_buf_size, _in_pkt_size, _out_buf_size, _out_pkt_size);
+ _on_connect(protocol);
+ }
+ _resp_pos += 1;
+ }
+ }
+}
+
+bool WSLClient::_verify_headers(String &r_protocol) {
+ String s = (char *)_resp_buf;
+ Vector<String> psa = s.split("\r\n");
+ int len = psa.size();
+ if (len < 4) {
+ ERR_EXPLAIN("Not enough response headers.");
+ ERR_FAIL_V(false);
+ }
+
+ Vector<String> req = psa[0].split(" ", false);
+ if (req.size() < 2) {
+ ERR_EXPLAIN("Invalid protocol or status code.");
+ ERR_FAIL_V(false);
+ }
+ // Wrong protocol
+ if (req[0] != "HTTP/1.1" || req[1] != "101") {
+ ERR_EXPLAIN("Invalid protocol or status code.");
+ ERR_FAIL_V(false);
+ }
+
+ Map<String, String> headers;
+ for (int i = 1; i < len; i++) {
+ Vector<String> header = psa[i].split(":", false, 1);
+ if (header.size() != 2) {
+ ERR_EXPLAIN("Invalid header -> " + psa[i]);
+ ERR_FAIL_V(false);
+ }
+ String name = header[0].to_lower();
+ String value = header[1].strip_edges();
+ if (headers.has(name))
+ headers[name] += "," + value;
+ else
+ headers[name] = value;
+ }
+
+#define _WLS_EXPLAIN(NAME, VALUE) \
+ ERR_EXPLAIN("Missing or invalid header '" + String(NAME) + "'. Expected value '" + VALUE + "'");
+#define _WLS_CHECK(NAME, VALUE) \
+ _WLS_EXPLAIN(NAME, VALUE); \
+ ERR_FAIL_COND_V(!headers.has(NAME) || headers[NAME].to_lower() != VALUE, false);
+#define _WLS_CHECK_NC(NAME, VALUE) \
+ _WLS_EXPLAIN(NAME, VALUE); \
+ ERR_FAIL_COND_V(!headers.has(NAME) || headers[NAME] != VALUE, false);
+ _WLS_CHECK("connection", "upgrade");
+ _WLS_CHECK("upgrade", "websocket");
+ _WLS_CHECK_NC("sec-websocket-accept", WSLPeer::compute_key_response(_key));
+ if (_protocols.size() == 0) {
+ // We didn't request a custom protocol
+ ERR_FAIL_COND_V(headers.has("sec-websocket-protocol"), false);
+ } else {
+ ERR_FAIL_COND_V(!headers.has("sec-websocket-protocol"), false);
+ r_protocol = headers["sec-websocket-protocol"];
+ bool valid = false;
+ for (int i = 0; i < _protocols.size(); i++) {
+ if (_protocols[i] != r_protocol)
+ continue;
+ valid = true;
+ break;
+ }
+ if (!valid)
+ return false;
+ }
+#undef _WLS_CHECK_NC
+#undef _WLS_CHECK
+#undef _WLS_EXPLAIN
+
+ return true;
+}
+
+Error WSLClient::connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, PoolVector<String> p_protocols) {
+
+ ERR_FAIL_COND_V(_connection.is_valid(), ERR_ALREADY_IN_USE);
+
+ _peer = Ref<WSLPeer>(memnew(WSLPeer));
+ IP_Address addr;
+
+ if (!p_host.is_valid_ip_address()) {
+ addr = IP::get_singleton()->resolve_hostname(p_host);
+ } else {
+ addr = p_host;
+ }
+
+ ERR_FAIL_COND_V(!addr.is_valid(), ERR_INVALID_PARAMETER);
+
+ String port = "";
+ if ((p_port != 80 && !p_ssl) || (p_port != 443 && p_ssl)) {
+ port = ":" + itos(p_port);
+ }
+
+ Error err = _tcp->connect_to_host(addr, p_port);
+ if (err != OK) {
+ _on_error();
+ _tcp->disconnect_from_host();
+ return err;
+ }
+ _connection = _tcp;
+ _use_ssl = p_ssl;
+ _host = p_host;
+ _protocols = p_protocols;
+
+ _key = WSLPeer::generate_key();
+ // TODO custom extra headers (allow overriding this too?)
+ String request = "GET " + p_path + " HTTP/1.1\r\n";
+ request += "Host: " + p_host + port + "\r\n";
+ request += "Upgrade: websocket\r\n";
+ request += "Connection: Upgrade\r\n";
+ request += "Sec-WebSocket-Key: " + _key + "\r\n";
+ request += "Sec-WebSocket-Version: 13\r\n";
+ if (p_protocols.size() > 0) {
+ request += "Sec-WebSocket-Protocol: ";
+ for (int i = 0; i < p_protocols.size(); i++) {
+ if (i != 0)
+ request += ",";
+ request += p_protocols[i];
+ }
+ request += "\r\n";
+ }
+ request += "\r\n";
+ _request = request.utf8();
+
+ return OK;
+}
+
+int WSLClient::get_max_packet_size() const {
+ return (1 << _out_buf_size) - PROTO_SIZE;
+}
+
+void WSLClient::poll() {
+ if (_peer->is_connected_to_host()) {
+ _peer->poll();
+ if (!_peer->is_connected_to_host()) {
+ _on_disconnect(_peer->close_code != -1);
+ disconnect_from_host();
+ }
+ return;
+ }
+
+ if (_connection.is_null())
+ return; // Not connected.
+
+ switch (_tcp->get_status()) {
+ case StreamPeerTCP::STATUS_NONE:
+ // Clean close
+ _on_error();
+ disconnect_from_host();
+ break;
+ case StreamPeerTCP::STATUS_CONNECTED: {
+ Ref<StreamPeerSSL> ssl;
+ if (_use_ssl) {
+ if (_connection == _tcp) {
+ // Start SSL handshake
+ ssl = Ref<StreamPeerSSL>(StreamPeerSSL::create());
+ ERR_EXPLAIN("SSL is not available in this build");
+ ERR_FAIL_COND(ssl.is_null());
+ ssl->set_blocking_handshake_enabled(false);
+ if (ssl->connect_to_stream(_tcp, verify_ssl, _host) != OK) {
+ _on_error();
+ disconnect_from_host();
+ return;
+ }
+ _connection = ssl;
+ } else {
+ ssl = static_cast<Ref<StreamPeerSSL> >(_connection);
+ ERR_FAIL_COND(ssl.is_null()); // Bug?
+ ssl->poll();
+ }
+ if (ssl->get_status() == StreamPeerSSL::STATUS_HANDSHAKING)
+ return; // Need more polling.
+ else if (ssl->get_status() != StreamPeerSSL::STATUS_CONNECTED) {
+ _on_error();
+ disconnect_from_host();
+ return; // Error.
+ }
+ }
+ // Do websocket handshake.
+ _do_handshake();
+ } break;
+ case StreamPeerTCP::STATUS_ERROR:
+ _on_error();
+ disconnect_from_host();
+ break;
+ case StreamPeerTCP::STATUS_CONNECTING:
+ break; // Wait for connection
+ }
+}
+
+Ref<WebSocketPeer> WSLClient::get_peer(int p_peer_id) const {
+
+ ERR_FAIL_COND_V(p_peer_id != 1, NULL);
+
+ return _peer;
+}
+
+NetworkedMultiplayerPeer::ConnectionStatus WSLClient::get_connection_status() const {
+
+ if (_peer->is_connected_to_host())
+ return CONNECTION_CONNECTED;
+
+ if (_tcp->is_connected_to_host())
+ return CONNECTION_CONNECTING;
+
+ return CONNECTION_DISCONNECTED;
+}
+
+void WSLClient::disconnect_from_host(int p_code, String p_reason) {
+
+ _peer->close(p_code, p_reason);
+ _connection = Ref<StreamPeer>(NULL);
+ _tcp = Ref<StreamPeerTCP>(memnew(StreamPeerTCP));
+
+ _key = "";
+ _host = "";
+ _protocols.resize(0);
+ _use_ssl = false;
+
+ _request = "";
+ _requested = 0;
+
+ memset(_resp_buf, 0, sizeof(_resp_buf));
+ _resp_pos = 0;
+}
+
+IP_Address WSLClient::get_connected_host() const {
+
+ return IP_Address();
+}
+
+uint16_t WSLClient::get_connected_port() const {
+
+ return 1025;
+}
+
+Error WSLClient::set_buffers(int p_in_buffer, int p_in_packets, int p_out_buffer, int p_out_packets) {
+ ERR_EXPLAIN("Buffers sizes can only be set before listening or connecting");
+ ERR_FAIL_COND_V(_connection.is_valid(), FAILED);
+
+ _in_buf_size = nearest_shift(p_in_buffer - 1) + 10;
+ _in_pkt_size = nearest_shift(p_in_packets - 1);
+ _out_buf_size = nearest_shift(p_out_buffer - 1) + 10;
+ _out_pkt_size = nearest_shift(p_out_packets - 1);
+ return OK;
+}
+
+WSLClient::WSLClient() {
+ _in_buf_size = nearest_shift((int)GLOBAL_GET(WSC_IN_BUF) - 1) + 10;
+ _in_pkt_size = nearest_shift((int)GLOBAL_GET(WSC_IN_PKT) - 1);
+ _out_buf_size = nearest_shift((int)GLOBAL_GET(WSC_OUT_BUF) - 1) + 10;
+ _out_pkt_size = nearest_shift((int)GLOBAL_GET(WSC_OUT_PKT) - 1);
+
+ _peer.instance();
+ _tcp.instance();
+ disconnect_from_host();
+}
+
+WSLClient::~WSLClient() {
+
+ _peer->close_now();
+ _peer->invalidate();
+ disconnect_from_host();
+}
+
+#endif // JAVASCRIPT_ENABLED
diff --git a/modules/websocket/lws_client.h b/modules/websocket/wsl_client.h
index df4aabec7f..57dfd635b7 100644
--- a/modules/websocket/lws_client.h
+++ b/modules/websocket/wsl_client.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* lws_client.h */
+/* wsl_client.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,21 +28,21 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef LWSCLIENT_H
-#define LWSCLIENT_H
+#ifndef WSLCLIENT_H
+#define WSLCLIENT_H
#ifndef JAVASCRIPT_ENABLED
#include "core/error_list.h"
-#include "lws_helper.h"
-#include "lws_peer.h"
+#include "core/io/stream_peer_ssl.h"
+#include "core/io/stream_peer_tcp.h"
#include "websocket_client.h"
+#include "wsl_peer.h"
+#include "wslay/wslay.h"
-class LWSClient : public WebSocketClient {
+class WSLClient : public WebSocketClient {
- GDCIIMPL(LWSClient, WebSocketClient);
-
- LWS_HELPER(LWSClient);
+ GDCIIMPL(WSLClient, WebSocketClient);
private:
int _in_buf_size;
@@ -50,6 +50,26 @@ private:
int _out_buf_size;
int _out_pkt_size;
+ Ref<WSLPeer> _peer;
+ Ref<StreamPeerTCP> _tcp;
+ Ref<StreamPeer> _connection;
+
+ CharString _request;
+ int _requested;
+
+ uint8_t _resp_buf[WSL_MAX_HEADER_SIZE];
+ int _resp_pos;
+
+ String _response;
+
+ String _key;
+ String _host;
+ PoolVector<String> _protocols;
+ bool _use_ssl;
+
+ void _do_handshake();
+ bool _verify_headers(String &r_protocol);
+
public:
Error set_buffers(int p_in_buffer, int p_in_packets, int p_out_buffer, int p_out_packets);
Error connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, PoolVector<String> p_protocol = PoolVector<String>());
@@ -61,10 +81,10 @@ public:
virtual ConnectionStatus get_connection_status() const;
virtual void poll();
- LWSClient();
- ~LWSClient();
+ WSLClient();
+ ~WSLClient();
};
#endif // JAVASCRIPT_ENABLED
-#endif // LWSCLIENT_H
+#endif // WSLCLIENT_H
diff --git a/modules/websocket/wsl_peer.cpp b/modules/websocket/wsl_peer.cpp
new file mode 100644
index 0000000000..b11bd2b70f
--- /dev/null
+++ b/modules/websocket/wsl_peer.cpp
@@ -0,0 +1,339 @@
+/*************************************************************************/
+/* lws_peer.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef JAVASCRIPT_ENABLED
+
+#include "wsl_peer.h"
+
+#include "wsl_client.h"
+#include "wsl_server.h"
+
+#include "core/math/crypto_core.h"
+#include "core/math/random_number_generator.h"
+#include "core/os/os.h"
+
+String WSLPeer::generate_key() {
+ // Random key
+ RandomNumberGenerator rng;
+ rng.set_seed(OS::get_singleton()->get_unix_time());
+ PoolVector<uint8_t> bkey;
+ int len = 16; // 16 bytes, as per RFC
+ bkey.resize(len);
+ PoolVector<uint8_t>::Write w = bkey.write();
+ for (int i = 0; i < len; i++) {
+ w[i] = (uint8_t)rng.randi_range(0, 255);
+ }
+ return CryptoCore::b64_encode_str(&w[0], len);
+}
+
+String WSLPeer::compute_key_response(String p_key) {
+ String key = p_key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; // Magic UUID as per RFC
+ Vector<uint8_t> sha = key.sha1_buffer();
+ return CryptoCore::b64_encode_str(sha.ptr(), sha.size());
+}
+
+void WSLPeer::_wsl_destroy(struct PeerData **p_data) {
+ if (!p_data || !(*p_data))
+ return;
+ struct PeerData *data = *p_data;
+ if (data->polling) {
+ data->destroy = true;
+ return;
+ }
+ wslay_event_context_free(data->ctx);
+ memdelete(data);
+ *p_data = NULL;
+}
+
+bool WSLPeer::_wsl_poll(struct PeerData *p_data) {
+ p_data->polling = true;
+ int err = 0;
+ if ((err = wslay_event_recv(p_data->ctx)) != 0 || (err = wslay_event_send(p_data->ctx)) != 0) {
+ print_verbose("Websocket (wslay) poll error: " + itos(err));
+ p_data->destroy = true;
+ }
+ p_data->polling = false;
+
+ if (p_data->destroy || (wslay_event_get_close_sent(p_data->ctx) && wslay_event_get_close_received(p_data->ctx))) {
+ bool valid = p_data->valid;
+ _wsl_destroy(&p_data);
+ return valid;
+ }
+ return false;
+}
+
+ssize_t wsl_recv_callback(wslay_event_context_ptr ctx, uint8_t *data, size_t len, int flags, void *user_data) {
+ struct WSLPeer::PeerData *peer_data = (struct WSLPeer::PeerData *)user_data;
+ if (!peer_data->valid) {
+ wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE);
+ return -1;
+ }
+ Ref<StreamPeer> conn = peer_data->conn;
+ int read = 0;
+ Error err = conn->get_partial_data(data, len, read);
+ if (err != OK) {
+ print_verbose("Websocket get data error: " + itos(err) + ", read (should be 0!): " + itos(read));
+ wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE);
+ return -1;
+ }
+ if (read == 0) {
+ wslay_event_set_error(ctx, WSLAY_ERR_WOULDBLOCK);
+ return -1;
+ }
+ return read;
+}
+
+ssize_t wsl_send_callback(wslay_event_context_ptr ctx, const uint8_t *data, size_t len, int flags, void *user_data) {
+ struct WSLPeer::PeerData *peer_data = (struct WSLPeer::PeerData *)user_data;
+ if (!peer_data->valid) {
+ wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE);
+ return -1;
+ }
+ Ref<StreamPeer> conn = peer_data->conn;
+ int sent = 0;
+ Error err = conn->put_partial_data(data, len, sent);
+ if (err != OK) {
+ wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE);
+ return -1;
+ }
+ if (sent == 0) {
+ wslay_event_set_error(ctx, WSLAY_ERR_WOULDBLOCK);
+ return -1;
+ }
+ return sent;
+}
+
+int wsl_genmask_callback(wslay_event_context_ptr ctx, uint8_t *buf, size_t len, void *user_data) {
+ RandomNumberGenerator rng;
+ // TODO maybe use crypto in the future?
+ rng.set_seed(OS::get_singleton()->get_unix_time());
+ for (unsigned int i = 0; i < len; i++) {
+ buf[i] = (uint8_t)rng.randi_range(0, 255);
+ }
+ return 0;
+}
+
+void wsl_msg_recv_callback(wslay_event_context_ptr ctx, const struct wslay_event_on_msg_recv_arg *arg, void *user_data) {
+ struct WSLPeer::PeerData *peer_data = (struct WSLPeer::PeerData *)user_data;
+ if (!peer_data->valid) {
+ return;
+ }
+ WSLPeer *peer = (WSLPeer *)peer_data->peer;
+
+ if (peer->parse_message(arg) != OK)
+ return;
+
+ if (peer_data->is_server) {
+ WSLServer *helper = (WSLServer *)peer_data->obj;
+ helper->_on_peer_packet(peer_data->id);
+ } else {
+ WSLClient *helper = (WSLClient *)peer_data->obj;
+ helper->_on_peer_packet();
+ }
+}
+
+wslay_event_callbacks wsl_callbacks = {
+ wsl_recv_callback,
+ wsl_send_callback,
+ wsl_genmask_callback,
+ NULL, /* on_frame_recv_start_callback */
+ NULL, /* on_frame_recv_callback */
+ NULL, /* on_frame_recv_end_callback */
+ wsl_msg_recv_callback
+};
+
+Error WSLPeer::parse_message(const wslay_event_on_msg_recv_arg *arg) {
+ uint8_t is_string = 0;
+ if (arg->opcode == WSLAY_TEXT_FRAME) {
+ is_string = 1;
+ } else if (arg->opcode == WSLAY_CONNECTION_CLOSE) {
+ close_code = arg->status_code;
+ size_t len = arg->msg_length;
+ close_reason = "";
+ if (len > 2 /* first 2 bytes = close code */) {
+ close_reason.parse_utf8((char *)arg->msg + 2, len - 2);
+ }
+ if (!wslay_event_get_close_sent(_data->ctx)) {
+ if (_data->is_server) {
+ WSLServer *helper = (WSLServer *)_data->obj;
+ helper->_on_close_request(_data->id, close_code, close_reason);
+ } else {
+ WSLClient *helper = (WSLClient *)_data->obj;
+ helper->_on_close_request(close_code, close_reason);
+ }
+ }
+ return ERR_FILE_EOF;
+ } else if (arg->opcode != WSLAY_BINARY_FRAME) {
+ // Ping or pong
+ return ERR_SKIP;
+ }
+ _in_buffer.write_packet(arg->msg, arg->msg_length, &is_string);
+ return OK;
+}
+
+void WSLPeer::make_context(PeerData *p_data, unsigned int p_in_buf_size, unsigned int p_in_pkt_size, unsigned int p_out_buf_size, unsigned int p_out_pkt_size) {
+ ERR_FAIL_COND(_data != NULL);
+ ERR_FAIL_COND(p_data == NULL);
+
+ _in_buffer.resize(p_in_pkt_size, p_in_buf_size);
+ _packet_buffer.resize((1 << MAX(p_in_buf_size, p_out_buf_size)));
+
+ _data = p_data;
+ _data->peer = this;
+ _data->valid = true;
+ _connection = Ref<StreamPeer>(_data->conn);
+
+ if (_data->is_server)
+ wslay_event_context_server_init(&(_data->ctx), &wsl_callbacks, _data);
+ else
+ wslay_event_context_client_init(&(_data->ctx), &wsl_callbacks, _data);
+ wslay_event_config_set_max_recv_msg_length(_data->ctx, (1 << p_in_buf_size));
+}
+
+void WSLPeer::set_write_mode(WriteMode p_mode) {
+ write_mode = p_mode;
+}
+
+WSLPeer::WriteMode WSLPeer::get_write_mode() const {
+ return write_mode;
+}
+
+void WSLPeer::poll() {
+ if (!_data)
+ return;
+
+ if (_wsl_poll(_data)) {
+ _data = NULL;
+ }
+}
+
+Error WSLPeer::put_packet(const uint8_t *p_buffer, int p_buffer_size) {
+
+ ERR_FAIL_COND_V(!is_connected_to_host(), FAILED);
+
+ struct wslay_event_msg msg; // Should I use fragmented?
+ msg.opcode = write_mode == WRITE_MODE_TEXT ? WSLAY_TEXT_FRAME : WSLAY_BINARY_FRAME;
+ msg.msg = p_buffer;
+ msg.msg_length = p_buffer_size;
+
+ wslay_event_queue_msg(_data->ctx, &msg);
+ return OK;
+}
+
+Error WSLPeer::get_packet(const uint8_t **r_buffer, int &r_buffer_size) {
+
+ r_buffer_size = 0;
+
+ ERR_FAIL_COND_V(!is_connected_to_host(), FAILED);
+
+ if (_in_buffer.packets_left() == 0)
+ return ERR_UNAVAILABLE;
+
+ int read = 0;
+ PoolVector<uint8_t>::Write rw = _packet_buffer.write();
+ _in_buffer.read_packet(rw.ptr(), _packet_buffer.size(), &_is_string, read);
+
+ *r_buffer = rw.ptr();
+ r_buffer_size = read;
+
+ return OK;
+}
+
+int WSLPeer::get_available_packet_count() const {
+
+ if (!is_connected_to_host())
+ return 0;
+
+ return _in_buffer.packets_left();
+}
+
+bool WSLPeer::was_string_packet() const {
+
+ return _is_string;
+}
+
+bool WSLPeer::is_connected_to_host() const {
+
+ return _data != NULL;
+}
+
+void WSLPeer::close_now() {
+ close(1000, "");
+ _wsl_destroy(&_data);
+}
+
+void WSLPeer::close(int p_code, String p_reason) {
+ if (_data && !wslay_event_get_close_sent(_data->ctx)) {
+ CharString cs = p_reason.utf8();
+ wslay_event_queue_close(_data->ctx, p_code, (uint8_t *)cs.ptr(), cs.size());
+ wslay_event_send(_data->ctx);
+ }
+
+ _in_buffer.clear();
+ _packet_buffer.resize(0);
+}
+
+IP_Address WSLPeer::get_connected_host() const {
+
+ ERR_FAIL_COND_V(!is_connected_to_host(), IP_Address());
+
+ IP_Address ip;
+ return ip;
+}
+
+uint16_t WSLPeer::get_connected_port() const {
+
+ ERR_FAIL_COND_V(!is_connected_to_host(), 0);
+
+ uint16_t port = 0;
+ return port;
+}
+
+void WSLPeer::invalidate() {
+ if (_data)
+ _data->valid = false;
+}
+
+WSLPeer::WSLPeer() {
+ _data = NULL;
+ _is_string = 0;
+ close_code = -1;
+ write_mode = WRITE_MODE_BINARY;
+}
+
+WSLPeer::~WSLPeer() {
+
+ close();
+ invalidate();
+ _wsl_destroy(&_data);
+ _data = NULL;
+}
+
+#endif // JAVASCRIPT_ENABLED
diff --git a/modules/websocket/lws_peer.h b/modules/websocket/wsl_peer.h
index 6771c13094..d51b304fe1 100644
--- a/modules/websocket/lws_peer.h
+++ b/modules/websocket/wsl_peer.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* lws_peer.h */
+/* wsl_peer.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,50 +28,76 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef LWSPEER_H
-#define LWSPEER_H
+#ifndef WSLPEER_H
+#define WSLPEER_H
#ifndef JAVASCRIPT_ENABLED
#include "core/error_list.h"
#include "core/io/packet_peer.h"
#include "core/ring_buffer.h"
-#include "libwebsockets.h"
-#include "lws_config.h"
#include "packet_buffer.h"
#include "websocket_peer.h"
+#include "wslay/wslay.h"
-class LWSPeer : public WebSocketPeer {
+#define WSL_MAX_HEADER_SIZE 4096
- GDCIIMPL(LWSPeer, WebSocketPeer);
+class WSLPeer : public WebSocketPeer {
+
+ GDCIIMPL(WSLPeer, WebSocketPeer);
+
+public:
+ struct PeerData {
+ bool polling;
+ bool destroy;
+ bool valid;
+ bool is_server;
+ void *obj;
+ void *peer;
+ Ref<StreamPeer> conn;
+ int id;
+ wslay_event_context_ptr ctx;
+
+ PeerData() {
+ polling = false;
+ destroy = false;
+ valid = false;
+ is_server = false;
+ id = 1;
+ ctx = NULL;
+ obj = NULL;
+ peer = NULL;
+ }
+ };
+
+ static String compute_key_response(String p_key);
+ static String generate_key();
private:
- int _in_size;
+ static bool _wsl_poll(struct PeerData *p_data);
+ static void _wsl_destroy(struct PeerData **p_data);
+
+ Ref<StreamPeer> _connection;
+ struct PeerData *_data;
uint8_t _is_string;
// Our packet info is just a boolean (is_string), using uint8_t for it.
PacketBuffer<uint8_t> _in_buffer;
- PacketBuffer<uint8_t> _out_buffer;
PoolVector<uint8_t> _packet_buffer;
- struct lws *wsi;
WriteMode write_mode;
+public:
int close_code;
String close_reason;
-
-public:
- struct PeerData {
- uint32_t peer_id;
- bool force_close;
- bool clean_close;
- };
+ void poll(); // Used by client and server.
virtual int get_available_packet_count() const;
virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size);
virtual Error put_packet(const uint8_t *p_buffer, int p_buffer_size);
virtual int get_max_packet_size() const { return _packet_buffer.size(); };
+ virtual void close_now();
virtual void close(int p_code = 1000, String p_reason = "");
virtual bool is_connected_to_host() const;
virtual IP_Address get_connected_host() const;
@@ -81,14 +107,12 @@ public:
virtual void set_write_mode(WriteMode p_mode);
virtual bool was_string_packet() const;
- void set_wsi(struct lws *wsi, unsigned int _in_buf_size, unsigned int _in_pkt_size, unsigned int _out_buf_size, unsigned int _out_pkt_size);
- Error read_wsi(void *in, size_t len);
- Error write_wsi();
- void send_close_status(struct lws *wsi);
- String get_close_reason(void *in, size_t len, int &r_code);
+ void make_context(PeerData *p_data, unsigned int p_in_buf_size, unsigned int p_in_pkt_size, unsigned int p_out_buf_size, unsigned int p_out_pkt_size);
+ Error parse_message(const wslay_event_on_msg_recv_arg *arg);
+ void invalidate();
- LWSPeer();
- ~LWSPeer();
+ WSLPeer();
+ ~WSLPeer();
};
#endif // JAVASCRIPT_ENABLED
diff --git a/modules/websocket/wsl_server.cpp b/modules/websocket/wsl_server.cpp
new file mode 100644
index 0000000000..1e140a716f
--- /dev/null
+++ b/modules/websocket/wsl_server.cpp
@@ -0,0 +1,281 @@
+/*************************************************************************/
+/* lws_server.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef JAVASCRIPT_ENABLED
+
+#include "wsl_server.h"
+#include "core/os/os.h"
+#include "core/project_settings.h"
+
+WSLServer::PendingPeer::PendingPeer() {
+ time = 0;
+ has_request = false;
+ response_sent = 0;
+ req_pos = 0;
+ memset(req_buf, 0, sizeof(req_buf));
+}
+
+bool WSLServer::PendingPeer::_parse_request(String &r_key) {
+ Vector<String> psa = String((char *)req_buf).split("\r\n");
+ int len = psa.size();
+ if (len < 4) {
+ ERR_EXPLAIN("Not enough response headers.");
+ ERR_FAIL_V(false);
+ }
+
+ Vector<String> req = psa[0].split(" ", false);
+ if (req.size() < 2) {
+ ERR_EXPLAIN("Invalid protocol or status code.");
+ ERR_FAIL_V(false);
+ }
+ // Wrong protocol
+ if (req[0] != "GET" || req[2] != "HTTP/1.1") {
+ ERR_EXPLAIN("Invalid method or HTTP version.");
+ ERR_FAIL_V(false);
+ }
+
+ Map<String, String> headers;
+ for (int i = 1; i < len; i++) {
+ Vector<String> header = psa[i].split(":", false, 1);
+ if (header.size() != 2) {
+ ERR_EXPLAIN("Invalid header -> " + psa[i]);
+ ERR_FAIL_V(false);
+ }
+ String name = header[0].to_lower();
+ String value = header[1].strip_edges();
+ if (headers.has(name))
+ headers[name] += "," + value;
+ else
+ headers[name] = value;
+ }
+#define _WLS_CHECK(NAME, VALUE) \
+ ERR_EXPLAIN("Missing or invalid header '" + String(NAME) + "'. Expected value '" + VALUE + "'"); \
+ ERR_FAIL_COND_V(!headers.has(NAME) || headers[NAME].to_lower() != VALUE, false);
+#define _WLS_CHECK_EX(NAME) \
+ ERR_EXPLAIN("Missing header '" + String(NAME) + "'."); \
+ ERR_FAIL_COND_V(!headers.has(NAME), false);
+ _WLS_CHECK("upgrade", "websocket");
+ _WLS_CHECK("sec-websocket-version", "13");
+ _WLS_CHECK_EX("sec-websocket-key");
+ _WLS_CHECK_EX("connection");
+#undef _WLS_CHECK_EX
+#undef _WLS_CHECK
+ r_key = headers["sec-websocket-key"];
+ return true;
+}
+
+Error WSLServer::PendingPeer::do_handshake() {
+ if (OS::get_singleton()->get_ticks_msec() - time > WSL_SERVER_TIMEOUT)
+ return ERR_TIMEOUT;
+ if (!has_request) {
+ int read = 0;
+ while (true) {
+ if (req_pos >= WSL_MAX_HEADER_SIZE) {
+ // Header is too big
+ ERR_EXPLAIN("Response headers too big");
+ ERR_FAIL_V(ERR_OUT_OF_MEMORY);
+ }
+ Error err = connection->get_partial_data(&req_buf[req_pos], 1, read);
+ if (err != OK) // Got an error
+ return FAILED;
+ else if (read != 1) // Busy, wait next poll
+ return ERR_BUSY;
+ char *r = (char *)req_buf;
+ int l = req_pos;
+ if (l > 3 && r[l] == '\n' && r[l - 1] == '\r' && r[l - 2] == '\n' && r[l - 3] == '\r') {
+ r[l - 3] = '\0';
+ if (!_parse_request(key)) {
+ return FAILED;
+ }
+ String s = "HTTP/1.1 101 Switching Protocols\r\n";
+ s += "Upgrade: websocket\r\n";
+ s += "Connection: Upgrade\r\n";
+ s += "Sec-WebSocket-Accept: " + WSLPeer::compute_key_response(key) + "\r\n";
+ s += "\r\n";
+ response = s.utf8();
+ has_request = true;
+ break;
+ }
+ req_pos += 1;
+ }
+ }
+ if (has_request && response_sent < response.size() - 1) {
+ int sent = 0;
+ Error err = connection->put_partial_data((const uint8_t *)response.get_data() + response_sent, response.size() - response_sent - 1, sent);
+ if (err != OK) {
+ return err;
+ }
+ response_sent += sent;
+ }
+ if (response_sent < response.size() - 1)
+ return ERR_BUSY;
+ return OK;
+}
+
+Error WSLServer::listen(int p_port, PoolVector<String> p_protocols, bool gd_mp_api) {
+ ERR_FAIL_COND_V(is_listening(), ERR_ALREADY_IN_USE);
+
+ _is_multiplayer = gd_mp_api;
+ _server->listen(p_port);
+
+ return OK;
+}
+
+void WSLServer::poll() {
+
+ List<int> remove_ids;
+ for (Map<int, Ref<WebSocketPeer> >::Element *E = _peer_map.front(); E; E = E->next()) {
+ Ref<WSLPeer> peer = (WSLPeer *)E->get().ptr();
+ peer->poll();
+ if (!peer->is_connected_to_host()) {
+ _on_disconnect(E->key(), peer->close_code != -1);
+ remove_ids.push_back(E->key());
+ }
+ }
+ for (List<int>::Element *E = remove_ids.front(); E; E = E->next()) {
+ _peer_map.erase(E->get());
+ }
+ remove_ids.clear();
+
+ List<Ref<PendingPeer> > remove_peers;
+ for (List<Ref<PendingPeer> >::Element *E = _pending.front(); E; E = E->next()) {
+ Ref<PendingPeer> ppeer = E->get();
+ Error err = ppeer->do_handshake();
+ if (err == ERR_BUSY) {
+ continue;
+ } else if (err != OK) {
+ remove_peers.push_back(ppeer);
+ continue;
+ }
+ // Creating new peer
+ int32_t id = _gen_unique_id();
+
+ WSLPeer::PeerData *data = memnew(struct WSLPeer::PeerData);
+ data->obj = this;
+ data->conn = ppeer->connection;
+ data->is_server = true;
+ data->id = id;
+
+ Ref<WSLPeer> ws_peer = memnew(WSLPeer);
+ ws_peer->make_context(data, _in_buf_size, _in_pkt_size, _out_buf_size, _out_pkt_size);
+
+ _peer_map[id] = ws_peer;
+ remove_peers.push_back(ppeer);
+ _on_connect(id, "");
+ }
+ for (List<Ref<PendingPeer> >::Element *E = remove_peers.front(); E; E = E->next()) {
+ _pending.erase(E->get());
+ }
+ remove_peers.clear();
+
+ if (!_server->is_listening())
+ return;
+
+ while (_server->is_connection_available()) {
+ Ref<StreamPeer> conn = _server->take_connection();
+ if (is_refusing_new_connections())
+ continue; // Conn will go out-of-scope and be closed.
+
+ Ref<PendingPeer> peer = memnew(PendingPeer);
+ peer->connection = conn;
+ peer->time = OS::get_singleton()->get_ticks_msec();
+ _pending.push_back(peer);
+ }
+}
+
+bool WSLServer::is_listening() const {
+ return _server->is_listening();
+}
+
+int WSLServer::get_max_packet_size() const {
+ return (1 << _out_buf_size) - PROTO_SIZE;
+}
+
+void WSLServer::stop() {
+ _server->stop();
+ for (Map<int, Ref<WebSocketPeer> >::Element *E = _peer_map.front(); E; E = E->next()) {
+ Ref<WSLPeer> peer = (WSLPeer *)E->get().ptr();
+ peer->close_now();
+ }
+ _pending.clear();
+ _peer_map.clear();
+}
+
+bool WSLServer::has_peer(int p_id) const {
+ return _peer_map.has(p_id);
+}
+
+Ref<WebSocketPeer> WSLServer::get_peer(int p_id) const {
+ ERR_FAIL_COND_V(!has_peer(p_id), NULL);
+ return _peer_map[p_id];
+}
+
+IP_Address WSLServer::get_peer_address(int p_peer_id) const {
+ ERR_FAIL_COND_V(!has_peer(p_peer_id), IP_Address());
+
+ return _peer_map[p_peer_id]->get_connected_host();
+}
+
+int WSLServer::get_peer_port(int p_peer_id) const {
+ ERR_FAIL_COND_V(!has_peer(p_peer_id), 0);
+
+ return _peer_map[p_peer_id]->get_connected_port();
+}
+
+void WSLServer::disconnect_peer(int p_peer_id, int p_code, String p_reason) {
+ ERR_FAIL_COND(!has_peer(p_peer_id));
+
+ get_peer(p_peer_id)->close(p_code, p_reason);
+}
+
+Error WSLServer::set_buffers(int p_in_buffer, int p_in_packets, int p_out_buffer, int p_out_packets) {
+ ERR_EXPLAIN("Buffers sizes can only be set before listening or connecting");
+ ERR_FAIL_COND_V(_server->is_listening(), FAILED);
+
+ _in_buf_size = nearest_shift(p_in_buffer - 1) + 10;
+ _in_pkt_size = nearest_shift(p_in_packets - 1);
+ _out_buf_size = nearest_shift(p_out_buffer - 1) + 10;
+ _out_pkt_size = nearest_shift(p_out_packets - 1);
+ return OK;
+}
+
+WSLServer::WSLServer() {
+ _in_buf_size = nearest_shift((int)GLOBAL_GET(WSS_IN_BUF) - 1) + 10;
+ _in_pkt_size = nearest_shift((int)GLOBAL_GET(WSS_IN_PKT) - 1);
+ _out_buf_size = nearest_shift((int)GLOBAL_GET(WSS_OUT_BUF) - 1) + 10;
+ _out_pkt_size = nearest_shift((int)GLOBAL_GET(WSS_OUT_PKT) - 1);
+ _server.instance();
+}
+
+WSLServer::~WSLServer() {
+ stop();
+}
+
+#endif // JAVASCRIPT_ENABLED
diff --git a/modules/websocket/lws_server.h b/modules/websocket/wsl_server.h
index b331852d26..b0520bd731 100644
--- a/modules/websocket/lws_server.h
+++ b/modules/websocket/wsl_server.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* lws_server.h */
+/* wsl_server.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,29 +28,53 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef LWSSERVER_H
-#define LWSSERVER_H
+#ifndef WSLSERVER_H
+#define WSLSERVER_H
#ifndef JAVASCRIPT_ENABLED
-#include "core/reference.h"
-#include "lws_helper.h"
-#include "lws_peer.h"
#include "websocket_server.h"
+#include "wsl_peer.h"
-class LWSServer : public WebSocketServer {
+#include "core/io/stream_peer_tcp.h"
+#include "core/io/tcp_server.h"
- GDCIIMPL(LWSServer, WebSocketServer);
+#define WSL_SERVER_TIMEOUT 1000
- LWS_HELPER(LWSServer);
+class WSLServer : public WebSocketServer {
+
+ GDCIIMPL(WSLServer, WebSocketServer);
private:
- Map<int, Ref<LWSPeer> > peer_map;
+ class PendingPeer : public Reference {
+
+ private:
+ bool _parse_request(String &r_key);
+
+ public:
+ Ref<StreamPeer> connection;
+
+ int time;
+ uint8_t req_buf[WSL_MAX_HEADER_SIZE];
+ int req_pos;
+ String key;
+ bool has_request;
+ CharString response;
+ int response_sent;
+
+ PendingPeer();
+
+ Error do_handshake();
+ };
+
int _in_buf_size;
int _in_pkt_size;
int _out_buf_size;
int _out_pkt_size;
+ List<Ref<PendingPeer> > _pending;
+ Ref<TCP_Server> _server;
+
public:
Error set_buffers(int p_in_buffer, int p_in_packets, int p_out_buffer, int p_out_packets);
Error listen(int p_port, PoolVector<String> p_protocols = PoolVector<String>(), bool gd_mp_api = false);
@@ -62,12 +86,12 @@ public:
IP_Address get_peer_address(int p_peer_id) const;
int get_peer_port(int p_peer_id) const;
void disconnect_peer(int p_peer_id, int p_code = 1000, String p_reason = "");
- virtual void poll() { _lws_poll(); }
+ virtual void poll();
- LWSServer();
- ~LWSServer();
+ WSLServer();
+ ~WSLServer();
};
#endif // JAVASCRIPT_ENABLED
-#endif // LWSSERVER_H
+#endif // WSLSERVER_H
diff --git a/platform/haiku/detect.py b/platform/haiku/detect.py
index 28d52e79a2..2a3e165069 100644
--- a/platform/haiku/detect.py
+++ b/platform/haiku/detect.py
@@ -128,8 +128,8 @@ def configure(env):
if any(platform.machine() in s for s in list_of_x86):
env["x86_libtheora_opt_gcc"] = True
- if not env['builtin_libwebsockets']:
- env.ParseConfig('pkg-config libwebsockets --cflags --libs')
+ if not env['builtin_wslay']:
+ env.ParseConfig('pkg-config libwslay --cflags --libs')
if not env['builtin_mbedtls']:
# mbedTLS does not provide a pkgconfig config yet. See https://github.com/ARMmbed/mbedtls/issues/228
diff --git a/platform/server/detect.py b/platform/server/detect.py
index 2b13edee1e..185dce8128 100644
--- a/platform/server/detect.py
+++ b/platform/server/detect.py
@@ -196,8 +196,8 @@ def configure(env):
# mbedTLS does not provide a pkgconfig config yet. See https://github.com/ARMmbed/mbedtls/issues/228
env.Append(LIBS=['mbedtls', 'mbedcrypto', 'mbedx509'])
- if not env['builtin_libwebsockets']:
- env.ParseConfig('pkg-config libwebsockets --cflags --libs')
+ if not env['builtin_wslay']:
+ env.ParseConfig('pkg-config libwslay --cflags --libs')
if not env['builtin_miniupnpc']:
# No pkgconfig file so far, hardcode default paths.
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index e535f6a148..0a9cfc0214 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -2586,7 +2586,7 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments,
modstr.resize(cmdline.size());
for (int i = 0; i < cmdline.size(); i++)
modstr.write[i] = cmdline[i];
- int ret = CreateProcessW(NULL, modstr.ptrw(), NULL, NULL, 0, NORMAL_PRIORITY_CLASS, NULL, NULL, si_w, &pi.pi);
+ int ret = CreateProcessW(NULL, modstr.ptrw(), NULL, NULL, 0, NORMAL_PRIORITY_CLASS & CREATE_NO_WINDOW, NULL, NULL, si_w, &pi.pi);
ERR_FAIL_COND_V(ret == 0, ERR_CANT_FORK);
if (p_blocking) {
diff --git a/platform/x11/detect.py b/platform/x11/detect.py
index 789dcf7851..58dea615cb 100644
--- a/platform/x11/detect.py
+++ b/platform/x11/detect.py
@@ -266,8 +266,8 @@ def configure(env):
# mbedTLS does not provide a pkgconfig config yet. See https://github.com/ARMmbed/mbedtls/issues/228
env.Append(LIBS=['mbedtls', 'mbedcrypto', 'mbedx509'])
- if not env['builtin_libwebsockets']:
- env.ParseConfig('pkg-config libwebsockets --cflags --libs')
+ if not env['builtin_wslay']:
+ env.ParseConfig('pkg-config libwslay --cflags --libs')
if not env['builtin_miniupnpc']:
# No pkgconfig file so far, hardcode default paths.
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index a6e3d644f6..9242e7997a 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -35,6 +35,7 @@
#include "core/os/keyboard.h"
#include "core/os/os.h"
#include "core/project_settings.h"
+#include "core/script_language.h"
#include "scene/main/viewport.h"
#ifdef TOOLS_ENABLED
@@ -1362,7 +1363,7 @@ void TextEdit::_notification(int p_what) {
if (completion_options.size() < 50) {
for (int i = 0; i < completion_options.size(); i++) {
- int w2 = MIN(cache.font->get_string_size(completion_options[i]).x, cmax_width);
+ int w2 = MIN(cache.font->get_string_size(completion_options[i].display).x, cmax_width);
if (w2 > w)
w = w2;
}
@@ -1370,6 +1371,11 @@ void TextEdit::_notification(int p_what) {
w = cmax_width;
}
+ // Add space for completion icons
+ const int icon_hsep = get_constant("hseparation", "ItemList");
+ Size2 icon_area_size(get_row_height(), get_row_height());
+ w += icon_area_size.width + icon_hsep;
+
int th = h + csb->get_minimum_size().y;
if (cursor_pos.y + get_row_height() + th > get_size().height) {
@@ -1405,12 +1411,26 @@ void TextEdit::_notification(int p_what) {
ERR_CONTINUE(l < 0 || l >= completion_options.size());
Color text_color = cache.completion_font_color;
for (int j = 0; j < color_regions.size(); j++) {
- if (completion_options[l].begins_with(color_regions[j].begin_key)) {
+ if (completion_options[l].insert_text.begins_with(color_regions[j].begin_key)) {
text_color = color_regions[j].color;
}
}
int yofs = (get_row_height() - cache.font->get_height()) / 2;
- draw_string(cache.font, Point2(completion_rect.position.x, completion_rect.position.y + i * get_row_height() + cache.font->get_ascent() + yofs), completion_options[l], text_color, completion_rect.size.width);
+ Point2 title_pos(completion_rect.position.x, completion_rect.position.y + i * get_row_height() + cache.font->get_ascent() + yofs);
+
+ //draw completion icon if it is valid
+ Ref<Texture> icon = completion_options[l].icon;
+ Rect2 icon_area(completion_rect.position.x, completion_rect.position.y + i * get_row_height(), icon_area_size.width, icon_area_size.height);
+ if (icon.is_valid()) {
+ const real_t max_scale = 0.7f;
+ const real_t side = max_scale * icon_area.size.width;
+ real_t scale = MIN(side / icon->get_width(), side / icon->get_height());
+ Size2 icon_size = icon->get_size() * scale;
+ draw_texture_rect(icon, Rect2(icon_area.position + (icon_area.size - icon_size) / 2, icon_size));
+ }
+
+ title_pos.x = icon_area.position.x + icon_area.size.width + icon_hsep;
+ draw_string(cache.font, title_pos, completion_options[l].display, text_color, completion_rect.size.width);
}
if (scrollw) {
@@ -5925,12 +5945,12 @@ void TextEdit::_confirm_completion() {
_remove_text(cursor.line, cursor.column - completion_base.length(), cursor.line, cursor.column);
cursor_set_column(cursor.column - completion_base.length(), false);
- insert_text_at_cursor(completion_current);
+ insert_text_at_cursor(completion_current.insert_text);
// When inserted into the middle of an existing string/method, don't add an unnecessary quote/bracket.
String line = text[cursor.line];
CharType next_char = line[cursor.column];
- CharType last_completion_char = completion_current[completion_current.length() - 1];
+ CharType last_completion_char = completion_current.insert_text[completion_current.insert_text.length() - 1];
if ((last_completion_char == '"' || last_completion_char == '\'') && last_completion_char == next_char) {
_base_remove_text(cursor.line, cursor.column, cursor.line, cursor.column + 1);
@@ -6066,39 +6086,41 @@ void TextEdit::_update_completion_candidates() {
completion_base = s;
Vector<float> sim_cache;
bool single_quote = s.begins_with("'");
- Vector<String> completion_options_casei;
+ Vector<ScriptCodeCompletionOption> completion_options_casei;
+
+ for (List<ScriptCodeCompletionOption>::Element *E = completion_sources.front(); E; E = E->next()) {
+ ScriptCodeCompletionOption &option = E->get();
- for (int i = 0; i < completion_strings.size(); i++) {
- if (single_quote && completion_strings[i].is_quoted()) {
- completion_strings.write[i] = completion_strings[i].unquote().quote("'");
+ if (single_quote && option.display.is_quoted()) {
+ option.display = option.display.unquote().quote("'");
}
- if (inquote && restore_quotes == 1 && !completion_strings[i].is_quoted()) {
+ if (inquote && restore_quotes == 1 && !option.display.is_quoted()) {
String quote = single_quote ? "'" : "\"";
- completion_strings.write[i] = completion_strings[i].quote(quote);
+ option.display = option.display.quote(quote);
}
- if (completion_strings[i].begins_with(s)) {
- completion_options.push_back(completion_strings[i]);
- } else if (completion_strings[i].to_lower().begins_with(s.to_lower())) {
- completion_options_casei.push_back(completion_strings[i]);
+ if (option.display.begins_with(s)) {
+ completion_options.push_back(option);
+ } else if (option.display.to_lower().begins_with(s.to_lower())) {
+ completion_options_casei.push_back(option);
}
}
completion_options.append_array(completion_options_casei);
if (completion_options.size() == 0) {
- for (int i = 0; i < completion_strings.size(); i++) {
- if (s.is_subsequence_of(completion_strings[i])) {
- completion_options.push_back(completion_strings[i]);
+ for (int i = 0; i < completion_sources.size(); i++) {
+ if (s.is_subsequence_of(completion_sources[i].display)) {
+ completion_options.push_back(completion_sources[i]);
}
}
}
if (completion_options.size() == 0) {
- for (int i = 0; i < completion_strings.size(); i++) {
- if (s.is_subsequence_ofi(completion_strings[i])) {
- completion_options.push_back(completion_strings[i]);
+ for (int i = 0; i < completion_sources.size(); i++) {
+ if (s.is_subsequence_ofi(completion_sources[i].display)) {
+ completion_options.push_back(completion_sources[i]);
}
}
}
@@ -6109,7 +6131,7 @@ void TextEdit::_update_completion_candidates() {
return;
}
- if (completion_options.size() == 1 && s == completion_options[0]) {
+ if (completion_options.size() == 1 && s == completion_options[0].display) {
// A perfect match, stop completion
_cancel_completion();
return;
@@ -6147,12 +6169,12 @@ void TextEdit::set_code_hint(const String &p_hint) {
update();
}
-void TextEdit::code_complete(const Vector<String> &p_strings, bool p_forced) {
+void TextEdit::code_complete(const List<ScriptCodeCompletionOption> &p_strings, bool p_forced) {
- completion_strings = p_strings;
+ completion_sources = p_strings;
completion_active = true;
completion_forced = p_forced;
- completion_current = "";
+ completion_current = ScriptCodeCompletionOption();
completion_index = 0;
_update_completion_candidates();
}
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index 30956ccb23..9fb8e03288 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -255,11 +255,11 @@ private:
Set<String> completion_prefixes;
bool completion_enabled;
- Vector<String> completion_strings;
- Vector<String> completion_options;
+ List<ScriptCodeCompletionOption> completion_sources;
+ Vector<ScriptCodeCompletionOption> completion_options;
bool completion_active;
bool completion_forced;
- String completion_current;
+ ScriptCodeCompletionOption completion_current;
String completion_base;
int completion_index;
Rect2i completion_rect;
@@ -704,7 +704,7 @@ public:
void set_tooltip_request_func(Object *p_obj, const StringName &p_function, const Variant &p_udata);
void set_completion(bool p_enabled, const Vector<String> &p_prefixes);
- void code_complete(const Vector<String> &p_strings, bool p_forced = false);
+ void code_complete(const List<ScriptCodeCompletionOption> &p_strings, bool p_forced = false);
void set_code_hint(const String &p_hint);
void query_code_comple();
diff --git a/scene/resources/default_theme/background.png b/scene/resources/default_theme/background.png
deleted file mode 100644
index 6c5f43e3ce..0000000000
--- a/scene/resources/default_theme/background.png
+++ /dev/null
Binary files differ
diff --git a/scene/resources/default_theme/base_green.png b/scene/resources/default_theme/base_green.png
deleted file mode 100644
index 03a5b313d7..0000000000
--- a/scene/resources/default_theme/base_green.png
+++ /dev/null
Binary files differ
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 4e2fe1f9b2..cf6ce3a5ef 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -854,8 +854,6 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_constant("bezier_len_pos", "GraphEdit", 80 * scale);
theme->set_constant("bezier_len_neg", "GraphEdit", 160 * scale);
- theme->set_icon("logo", "Icons", make_icon(logo_png));
-
// Visual Node Ports
theme->set_constant("port_grab_distance_horizontal", "GraphEdit", 48 * scale);
theme->set_constant("port_grab_distance_vertical", "GraphEdit", 6 * scale);
diff --git a/scene/resources/default_theme/dosfont.png b/scene/resources/default_theme/dosfont.png
deleted file mode 100644
index e2739b94ea..0000000000
--- a/scene/resources/default_theme/dosfont.png
+++ /dev/null
Binary files differ
diff --git a/scene/resources/default_theme/frame_focus.png b/scene/resources/default_theme/frame_focus.png
deleted file mode 100644
index 1b24ba47d8..0000000000
--- a/scene/resources/default_theme/frame_focus.png
+++ /dev/null
Binary files differ
diff --git a/scene/resources/default_theme/full_panel_bg.png b/scene/resources/default_theme/full_panel_bg.png
deleted file mode 100644
index 85f753cc13..0000000000
--- a/scene/resources/default_theme/full_panel_bg.png
+++ /dev/null
Binary files differ
diff --git a/scene/resources/default_theme/icon_play.png b/scene/resources/default_theme/icon_play.png
deleted file mode 100644
index b9ed6e6d5b..0000000000
--- a/scene/resources/default_theme/icon_play.png
+++ /dev/null
Binary files differ
diff --git a/scene/resources/default_theme/icon_stop.png b/scene/resources/default_theme/icon_stop.png
deleted file mode 100644
index 0c1371ceb9..0000000000
--- a/scene/resources/default_theme/icon_stop.png
+++ /dev/null
Binary files differ
diff --git a/scene/resources/default_theme/line_edit_focus.png b/scene/resources/default_theme/line_edit_focus.png
deleted file mode 100644
index 1d74b74068..0000000000
--- a/scene/resources/default_theme/line_edit_focus.png
+++ /dev/null
Binary files differ
diff --git a/scene/resources/default_theme/logo.png b/scene/resources/default_theme/logo.png
deleted file mode 100644
index d0ef9d8aa7..0000000000
--- a/scene/resources/default_theme/logo.png
+++ /dev/null
Binary files differ
diff --git a/scene/resources/default_theme/option_button_focus.png b/scene/resources/default_theme/option_button_focus.png
deleted file mode 100644
index 402670f9a2..0000000000
--- a/scene/resources/default_theme/option_button_focus.png
+++ /dev/null
Binary files differ
diff --git a/scene/resources/default_theme/popup_checked.png b/scene/resources/default_theme/popup_checked.png
deleted file mode 100644
index b7b05640e1..0000000000
--- a/scene/resources/default_theme/popup_checked.png
+++ /dev/null
Binary files differ
diff --git a/scene/resources/default_theme/popup_hover.png b/scene/resources/default_theme/popup_hover.png
deleted file mode 100644
index bdb6ae8bd0..0000000000
--- a/scene/resources/default_theme/popup_hover.png
+++ /dev/null
Binary files differ
diff --git a/scene/resources/default_theme/popup_unchecked.png b/scene/resources/default_theme/popup_unchecked.png
deleted file mode 100644
index ff922335c3..0000000000
--- a/scene/resources/default_theme/popup_unchecked.png
+++ /dev/null
Binary files differ
diff --git a/scene/resources/default_theme/reference_border.png b/scene/resources/default_theme/reference_border.png
deleted file mode 100644
index 6a680f393c..0000000000
--- a/scene/resources/default_theme/reference_border.png
+++ /dev/null
Binary files differ
diff --git a/scene/resources/default_theme/scroll_button_down.png b/scene/resources/default_theme/scroll_button_down.png
deleted file mode 100644
index 1df4ef5b6b..0000000000
--- a/scene/resources/default_theme/scroll_button_down.png
+++ /dev/null
Binary files differ
diff --git a/scene/resources/default_theme/scroll_button_down_hl.png b/scene/resources/default_theme/scroll_button_down_hl.png
deleted file mode 100644
index ba79087393..0000000000
--- a/scene/resources/default_theme/scroll_button_down_hl.png
+++ /dev/null
Binary files differ
diff --git a/scene/resources/default_theme/scroll_button_up.png b/scene/resources/default_theme/scroll_button_up.png
deleted file mode 100644
index f425412f50..0000000000
--- a/scene/resources/default_theme/scroll_button_up.png
+++ /dev/null
Binary files differ
diff --git a/scene/resources/default_theme/scroll_button_up_hl.png b/scene/resources/default_theme/scroll_button_up_hl.png
deleted file mode 100644
index 615a236c52..0000000000
--- a/scene/resources/default_theme/scroll_button_up_hl.png
+++ /dev/null
Binary files differ
diff --git a/scene/resources/default_theme/theme_data.h b/scene/resources/default_theme/theme_data.h
index 5e13a6625a..cf37c57407 100644
--- a/scene/resources/default_theme/theme_data.h
+++ b/scene/resources/default_theme/theme_data.h
@@ -10,14 +10,6 @@ static const unsigned char arrow_right_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x8, 0x4, 0x0, 0x0, 0x0, 0xfc, 0x7c, 0x94, 0x6c, 0x0, 0x0, 0x0, 0x2e, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x20, 0x17, 0x3c, 0xf8, 0xf, 0x82, 0xf7, 0x13, 0x70, 0x48, 0x3c, 0xf8, 0xf2, 0x50, 0x1b, 0x43, 0x2, 0xa, 0xaf, 0xbe, 0xe0, 0xc6, 0x2e, 0xf1, 0xff, 0xe1, 0x7c, 0x12, 0x24, 0x10, 0x46, 0x11, 0xb6, 0x1c, 0xe1, 0x5c, 0xa, 0x0, 0x0, 0xe0, 0x14, 0x48, 0xb1, 0x3d, 0x1b, 0x7a, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
-static const unsigned char background_png[] = {
- 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x20, 0x8, 0x3, 0x0, 0x0, 0x0, 0x44, 0xa4, 0x8a, 0xc6, 0x0, 0x0, 0x1, 0xe, 0x50, 0x4c, 0x54, 0x45, 0x91, 0xc9, 0xab, 0x90, 0xc9, 0xab, 0x90, 0xc9, 0xaa, 0x90, 0xc8, 0xab, 0x91, 0xc9, 0xaa, 0x91, 0xc8, 0xab, 0x90, 0xc8, 0xaa, 0x8f, 0xc8, 0xab, 0x8f, 0xc9, 0xab, 0x8f, 0xc8, 0xaa, 0x90, 0xc7, 0xaa, 0x90, 0xc7, 0xab, 0x8f, 0xc7, 0xaa, 0x8f, 0xc7, 0xab, 0x8e, 0xc7, 0xab, 0x8e, 0xc6, 0xab, 0x8f, 0xc6, 0xab, 0x8e, 0xc6, 0xaa, 0x8f, 0xc6, 0xaa, 0x8e, 0xc7, 0xaa, 0x8e, 0xc5, 0xaa, 0x8e, 0xc5, 0xab, 0x8d, 0xc5, 0xaa, 0x8d, 0xc5, 0xab, 0x8d, 0xc6, 0xaa, 0x8d, 0xc6, 0xab, 0x8d, 0xc4, 0xaa, 0x8e, 0xc4, 0xab, 0x8d, 0xc4, 0xab, 0x8e, 0xc4, 0xaa, 0x8c, 0xc4, 0xaa, 0x8c, 0xc5, 0xaa, 0x8d, 0xc3, 0xab, 0x8d, 0xc3, 0xaa, 0x8c, 0xc3, 0xaa, 0x8c, 0xc4, 0xab, 0x8c, 0xc3, 0xab, 0x8c, 0xc2, 0xab, 0x8b, 0xc2, 0xaa, 0x8b, 0xc3, 0xaa, 0x8b, 0xc3, 0xab, 0x8c, 0xc2, 0xaa, 0x8b, 0xc2, 0xab, 0x8b, 0xc1, 0xaa, 0x8b, 0xc1, 0xab, 0x8a, 0xc2, 0xaa, 0x8a, 0xc1, 0xaa, 0x8a, 0xc0, 0xaa, 0x8b, 0xc0, 0xaa, 0x8a, 0xc1, 0xa9, 0x8a, 0xc0, 0xa9, 0x89, 0xc0, 0xaa, 0x8a, 0xbf, 0xaa, 0x89, 0xbf, 0xaa, 0x89, 0xbf, 0xa9, 0x8a, 0xbf, 0xa9, 0x88, 0xbf, 0xaa, 0x89, 0xbe, 0xaa, 0x89, 0xbe, 0xa9, 0x88, 0xbf, 0xa9, 0x88, 0xbe, 0xa9, 0x88, 0xbe, 0xaa, 0x88, 0xbd, 0xaa, 0x88, 0xbd, 0xa9, 0x89, 0xbd, 0xaa, 0x89, 0xbd, 0xa9, 0x87, 0xbe, 0xa9, 0x87, 0xbd, 0xaa, 0x87, 0xbe, 0xaa, 0x87, 0xbd, 0xa9, 0x87, 0xbc, 0xaa, 0x88, 0xbc, 0xa9, 0x88, 0xbc, 0xaa, 0x87, 0xbc, 0xa9, 0x86, 0xbc, 0xa9, 0x87, 0xbb, 0xaa, 0x87, 0xbb, 0xa9, 0x86, 0xbb, 0xa9, 0x86, 0xbc, 0xaa, 0x86, 0xbb, 0xaa, 0x86, 0xba, 0xaa, 0x86, 0xba, 0xa9, 0x85, 0xba, 0xa9, 0x85, 0xbb, 0xaa, 0x85, 0xbb, 0xa9, 0x85, 0xba, 0xaa, 0x85, 0xb9, 0xa9, 0x86, 0xb9, 0xa9, 0x86, 0xb9, 0xaa, 0x85, 0xb9, 0xaa, 0x3e, 0xa0, 0x4f, 0x4f, 0x0, 0x0, 0x2, 0x3, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x2d, 0x4a, 0x7, 0x82, 0x4, 0x37, 0x12, 0x2, 0xa, 0x4a, 0xea, 0x9e, 0xbd, 0xff, 0x3f, 0xf5, 0x6c, 0x4f, 0x4b, 0xda, 0x58, 0x91, 0x24, 0x10, 0x20, 0xf8, 0x5d, 0x20, 0x81, 0x1f, 0xa8, 0x1f, 0xf6, 0x7, 0xf5, 0x7d, 0x0, 0x0, 0x3c, 0x0, 0x8, 0x14, 0x28, 0xb8, 0x41, 0x0, 0x50, 0x7b, 0x70, 0x63, 0xc, 0x9, 0x1c, 0xaa, 0x52, 0xeb, 0x4, 0x5b, 0xfb, 0x1d, 0x89, 0x68, 0xe1, 0x39, 0x9c, 0x7d, 0x68, 0x77, 0x60, 0x8c, 0x7a, 0x80, 0xe5, 0x6e, 0xdc, 0x41, 0x47, 0x51, 0x5f, 0xb8, 0xdd, 0xed, 0xa0, 0x9f, 0xc6, 0xad, 0xba, 0xee, 0xfb, 0xee, 0xde, 0x97, 0x74, 0x6f, 0x98, 0x82, 0x26, 0x51, 0x30, 0xa6, 0x3f, 0x10, 0xc8, 0xad, 0x13, 0xe4, 0x83, 0x0, 0x7a, 0x4, 0x4a, 0xd9, 0x5c, 0xde, 0xd2, 0x16, 0x15, 0xf2, 0xac, 0xac, 0x3e, 0x8f, 0x5a, 0x15, 0x3a, 0x5a, 0xe0, 0x6a, 0x1, 0xdc, 0xbd, 0x9b, 0x47, 0x44, 0xb6, 0x1e, 0x44, 0x5b, 0xe7, 0x84, 0x4b, 0xc3, 0xc, 0x1b, 0x51, 0xeb, 0xaa, 0x54, 0xc7, 0xb3, 0xeb, 0xca, 0x1a, 0x36, 0xbc, 0x76, 0x64, 0x4a, 0x62, 0x54, 0x3c, 0xe7, 0xf4, 0xc0, 0xd4, 0x1b, 0xda, 0x48, 0xa4, 0xc1, 0xd7, 0x98, 0xc2, 0xac, 0x19, 0x76, 0xd7, 0x44, 0x80, 0x33, 0xfe, 0xcb, 0x2b, 0x97, 0x6d, 0x8e, 0x2, 0x36, 0x4a, 0xfd, 0xc, 0xef, 0xb1, 0x35, 0x76, 0x63, 0x62, 0xc6, 0x5b, 0x38, 0xd3, 0x7e, 0x0, 0x7b, 0xfe, 0xef, 0x48, 0x93, 0xff, 0xdc, 0x3d, 0xed, 0xf4, 0xc4, 0xc4, 0x99, 0x93, 0xd3, 0x68, 0x5c, 0x9e, 0xee, 0x87, 0x16, 0xca, 0x1f, 0xbb, 0x80, 0x9e, 0xa0, 0x5, 0x47, 0x0, 0xbc, 0x5f, 0x7, 0x79, 0xa9, 0x3, 0x99, 0x80, 0x8f, 0xa7, 0x16, 0x68, 0xcd, 0x3a, 0x3d, 0x32, 0x60, 0xc0, 0x6f, 0xd8, 0x2b, 0x8a, 0xe1, 0x20, 0xf, 0xe3, 0x4, 0xcf, 0xfa, 0x1a, 0xb, 0x90, 0xfb, 0x2a, 0x57, 0x4a, 0xa8, 0xc9, 0xb7, 0x91, 0x37, 0x82, 0xf7, 0x4c, 0xd2, 0xa9, 0x9a, 0x78, 0x8f, 0x53, 0x22, 0x40, 0xfd, 0x44, 0x5c, 0xdf, 0xeb, 0x89, 0x4a, 0xc9, 0x0, 0xe7, 0x74, 0x1, 0x28, 0xff, 0xa6, 0x7e, 0xa, 0x4, 0xe9, 0x43, 0xe2, 0x7, 0x7d, 0xaf, 0x9, 0xca, 0x61, 0x3, 0x88, 0x13, 0x20, 0xab, 0x50, 0x1e, 0x41, 0xbc, 0x68, 0x3, 0xd5, 0xc2, 0x69, 0xa4, 0x5b, 0x22, 0xbb, 0x35, 0xdc, 0x45, 0x72, 0x94, 0xba, 0x85, 0xee, 0x82, 0x54, 0x0, 0xcb, 0x45, 0xa4, 0x78, 0xa, 0xc0, 0x28, 0x1c, 0x91, 0x46, 0x50, 0xa3, 0x34, 0xcb, 0x63, 0xfa, 0xeb, 0xb8, 0xd8, 0x5e, 0x9e, 0xde, 0x2b, 0xa3, 0xda, 0x35, 0xd3, 0x62, 0xc4, 0x8e, 0xca, 0x39, 0xf0, 0xb1, 0x7a, 0xd6, 0x69, 0x5f, 0x5, 0xa1, 0xa4, 0xa3, 0x3a, 0xdf, 0x8, 0xd8, 0xcf, 0x62, 0xf7, 0x14, 0x4f, 0x5a, 0x87, 0xa5, 0xc1, 0x22, 0x51, 0xe2, 0xd5, 0x9a, 0xc1, 0x1c, 0x37, 0x5e, 0xd6, 0x7f, 0xed, 0xfb, 0x41, 0x5e, 0xb7, 0xf, 0x7c, 0xe3, 0xba, 0x7b, 0xd0, 0xa5, 0x3a, 0xb3, 0x8c, 0xd7, 0x2e, 0x4e, 0xd7, 0xba, 0xbb, 0xd7, 0xc6, 0xb, 0x8d, 0x17, 0x1f, 0xe3, 0x46, 0x9, 0x49, 0xa1, 0x8c, 0x13, 0x63, 0x4c, 0xa6, 0xfa, 0x2a, 0x8c, 0x38, 0x88, 0x6a, 0xc9, 0x32, 0x4c, 0x1b, 0xa3, 0x44, 0x43, 0xd9, 0x55, 0xdb, 0xce, 0xc1, 0xe9, 0x92, 0x2f, 0x4a, 0x25, 0x59, 0x36, 0x52, 0x52, 0x41, 0xc4, 0x16, 0x2, 0x41, 0x32, 0x7a, 0x73, 0x4b, 0x21, 0xb, 0x8, 0x57, 0x89, 0xc2, 0x90, 0x65, 0xa8, 0xdc, 0x46, 0x56, 0x14, 0x15, 0x8e, 0xc1, 0x20, 0xd7, 0xcc, 0x40, 0x76, 0x42, 0x3a, 0x83, 0xf, 0x83, 0x46, 0xf5, 0x27, 0xa7, 0x80, 0x7e, 0xcf, 0xd2, 0x74, 0xd0, 0x78, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
-};
-
-static const unsigned char base_green_png[] = {
- 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x20, 0x1, 0x3, 0x0, 0x0, 0x0, 0x49, 0xb4, 0xe8, 0xb7, 0x0, 0x0, 0x0, 0x6, 0x50, 0x4c, 0x54, 0x45, 0x90, 0xc9, 0xab, 0xff, 0xff, 0xff, 0xc6, 0xd0, 0x9d, 0x30, 0x0, 0x0, 0x0, 0xb, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x18, 0xe4, 0x0, 0x0, 0x0, 0xa0, 0x0, 0x1, 0xf3, 0xdb, 0xea, 0x79, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
-};
-
static const unsigned char button_disabled_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0xc7, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x6c, 0xd0, 0x81, 0x66, 0x43, 0x31, 0x14, 0x87, 0xf1, 0xf, 0x5, 0x17, 0xb8, 0x28, 0x2e, 0x8, 0x71, 0xf3, 0x6, 0x19, 0xb6, 0xb9, 0xcb, 0xac, 0x95, 0xa4, 0xb7, 0xad, 0x6a, 0xd5, 0x68, 0x5f, 0xe4, 0x3e, 0x76, 0x1e, 0xe1, 0xbf, 0x21, 0xa6, 0xab, 0xf8, 0x1, 0x7c, 0x9c, 0x73, 0xe, 0xac, 0xe8, 0xe8, 0x19, 0x30, 0x58, 0xc6, 0xca, 0x62, 0x18, 0xe8, 0xe9, 0x58, 0x41, 0xc7, 0x1a, 0x87, 0x27, 0x10, 0x49, 0xe4, 0x5f, 0x89, 0x48, 0xc0, 0xe3, 0x58, 0xd3, 0x41, 0x8f, 0xb, 0xcb, 0xbd, 0x7c, 0xeb, 0xbf, 0x7b, 0x9, 0xb, 0x8e, 0x1e, 0x6, 0xfc, 0xad, 0x64, 0x6d, 0xb5, 0x79, 0xb0, 0x55, 0xd6, 0xad, 0xe0, 0x19, 0xc0, 0x10, 0xae, 0xda, 0x34, 0x5c, 0x45, 0xc0, 0x80, 0x25, 0x5e, 0xf4, 0xd5, 0x70, 0x11, 0x11, 0xb, 0x23, 0xe9, 0xac, 0xcf, 0x86, 0xb3, 0x48, 0x8c, 0x30, 0x92, 0x4f, 0xa, 0xd, 0x27, 0x91, 0x6b, 0x70, 0xd4, 0x47, 0xc3, 0xf1, 0x2f, 0x48, 0x7, 0x4d, 0xd, 0x87, 0x3a, 0xc2, 0x12, 0x67, 0xbd, 0x37, 0xcc, 0x75, 0x49, 0x43, 0xd8, 0xe9, 0xad, 0x61, 0x57, 0xcf, 0x1c, 0xf0, 0xfb, 0x32, 0xe9, 0xf5, 0xc9, 0xa4, 0x7d, 0x7d, 0x54, 0x8f, 0x7b, 0x59, 0xe6, 0x92, 0x14, 0x1f, 0x24, 0xcd, 0x3f, 0x7b, 0x6b, 0xa, 0xe, 0x6a, 0x82, 0x91, 0x45, 0x30, 0xba, 0x1, 0x4a, 0x51, 0xc4, 0x35, 0x1f, 0xe5, 0xa1, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
@@ -62,10 +54,6 @@ static const unsigned char color_picker_sample_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x14, 0x8, 0x0, 0x0, 0x0, 0x0, 0x47, 0x29, 0xbc, 0x83, 0x0, 0x0, 0x0, 0x3c, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xed, 0xd5, 0x21, 0x11, 0x0, 0x30, 0xc, 0x4, 0xc1, 0xfa, 0x57, 0x53, 0x87, 0xed, 0x4, 0x45, 0xc4, 0xed, 0xa3, 0xc3, 0x4b, 0xfe, 0xbc, 0xd9, 0x9d, 0x35, 0x2b, 0xe, 0x0, 0x0, 0x0, 0x80, 0xed, 0x66, 0xc5, 0x1, 0x0, 0x0, 0x0, 0xe0, 0x6, 0x1, 0x0, 0x0, 0x90, 0x6, 0x70, 0x83, 0x0, 0x0, 0x0, 0x28, 0x3, 0x7c, 0x54, 0x93, 0xd6, 0xf1, 0xd1, 0x16, 0x8a, 0x17, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
-static const unsigned char dosfont_png[] = {
- 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x80, 0x1, 0x0, 0x0, 0x0, 0x0, 0xeb, 0x45, 0x5c, 0x66, 0x0, 0x0, 0x0, 0x2, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x0, 0x76, 0x93, 0xcd, 0x38, 0x0, 0x0, 0x2, 0x64, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xbc, 0xd4, 0x81, 0x86, 0x2c, 0x47, 0x14, 0xc6, 0xf1, 0xcf, 0x45, 0x81, 0x32, 0x2, 0x38, 0x58, 0x17, 0xe4, 0x1, 0xa, 0x44, 0x8b, 0x7a, 0x98, 0xb2, 0xe2, 0xb8, 0x28, 0x2c, 0x68, 0x8d, 0x63, 0x5c, 0xb0, 0xef, 0x90, 0xb7, 0xe9, 0x6c, 0x71, 0x40, 0x9, 0x20, 0xd0, 0x63, 0x2d, 0x98, 0x0, 0xc, 0x88, 0x60, 0x54, 0xa7, 0xaa, 0xba, 0xef, 0x66, 0x67, 0x5d, 0x10, 0x37, 0xf7, 0xf, 0xc3, 0x4f, 0x39, 0x53, 0x87, 0xd2, 0xf8, 0x5a, 0x84, 0x9b, 0xb8, 0x81, 0xc3, 0x6b, 0xc4, 0x90, 0x1, 0xce, 0xee, 0xe4, 0xe1, 0x39, 0x6a, 0x84, 0x23, 0xda, 0x80, 0xe1, 0x7f, 0x8c, 0x4f, 0xf1, 0x29, 0x38, 0x8b, 0xd6, 0x87, 0x4, 0x8f, 0x32, 0xf, 0xa, 0x67, 0x99, 0x2a, 0x98, 0x4, 0x42, 0x94, 0xd1, 0x56, 0xf0, 0xd, 0xec, 0xd2, 0xc0, 0x9c, 0xa8, 0xc2, 0x7a, 0x44, 0x1, 0x6d, 0x90, 0xdd, 0x97, 0x13, 0x2e, 0x1, 0x28, 0x8f, 0x39, 0xf4, 0x19, 0x55, 0x42, 0x9f, 0xa1, 0x59, 0x41, 0x4, 0x10, 0x68, 0xe6, 0x6d, 0xe8, 0x23, 0xac, 0xeb, 0xf0, 0xd9, 0xbf, 0xdd, 0xc5, 0xdd, 0x2c, 0xf7, 0x4d, 0x23, 0x11, 0x5b, 0x86, 0x22, 0x82, 0x96, 0x0, 0x83, 0xea, 0xdd, 0x1c, 0x54, 0x15, 0x30, 0x8, 0x2a, 0x98, 0x8c, 0xf1, 0xf3, 0x6c, 0x54, 0x89, 0x2c, 0x5c, 0x75, 0xb2, 0x26, 0xee, 0x40, 0x47, 0xb2, 0x15, 0xc8, 0xe7, 0xeb, 0xd5, 0xca, 0x11, 0x70, 0xb0, 0xf4, 0xc, 0x72, 0xa6, 0x18, 0x25, 0x35, 0x40, 0x80, 0x69, 0x10, 0x8c, 0x35, 0xea, 0x1a, 0xb8, 0xa3, 0x6d, 0x30, 0xef, 0x40, 0x44, 0x20, 0x9c, 0x40, 0xaa, 0x56, 0x2b, 0xd8, 0xfe, 0x2f, 0x34, 0xe3, 0x58, 0xe4, 0xa3, 0x88, 0x93, 0x9, 0xce, 0x20, 0x90, 0xe0, 0xfb, 0xf4, 0xc3, 0xd5, 0xff, 0x5d, 0x8a, 0x57, 0xff, 0xf1, 0x7c, 0x49, 0x2a, 0x57, 0xc, 0xcc, 0x91, 0x99, 0x95, 0x2c, 0x87, 0x3f, 0xcf, 0xca, 0x88, 0xfc, 0xc4, 0xf7, 0xf7, 0x4f, 0x1d, 0xd6, 0xbf, 0x2a, 0x28, 0xcf, 0xfc, 0xe9, 0xd3, 0x5c, 0x21, 0x86, 0xb5, 0x34, 0x90, 0x99, 0xa7, 0x69, 0x2e, 0x64, 0xa7, 0xb0, 0x3c, 0xab, 0xa0, 0xf4, 0x13, 0xcf, 0xda, 0x20, 0xfd, 0xae, 0x1, 0x5a, 0x21, 0x4, 0x55, 0xca, 0x31, 0x24, 0x6d, 0xd0, 0x86, 0x76, 0xe0, 0xfb, 0x1d, 0x38, 0x72, 0xe0, 0x6, 0xbc, 0x41, 0xbb, 0xd8, 0xe5, 0x67, 0xf5, 0xd3, 0xb9, 0x24, 0x95, 0xcb, 0xff, 0xb0, 0x3a, 0xdc, 0x2d, 0xc, 0x15, 0xe4, 0x2a, 0xab, 0xa6, 0xda, 0xea, 0xe1, 0x23, 0x8, 0xca, 0xba, 0x74, 0x48, 0xee, 0xb3, 0x55, 0xa0, 0xc1, 0xaf, 0x15, 0x38, 0x3d, 0xba, 0xd9, 0xa2, 0x43, 0xa0, 0xa, 0x9e, 0xad, 0x7b, 0xd9, 0x40, 0x86, 0x6, 0xe4, 0xc9, 0x3d, 0x6c, 0x10, 0x6d, 0x85, 0x85, 0xc8, 0xb9, 0x61, 0x3, 0x36, 0xd, 0x3c, 0x5, 0x77, 0xd7, 0xe1, 0xf, 0x56, 0x52, 0x5e, 0x99, 0x7e, 0x73, 0x87, 0xe, 0xcf, 0xd, 0x3c, 0x27, 0x4a, 0xce, 0x74, 0x90, 0xb3, 0x78, 0x21, 0x4e, 0x7e, 0xf5, 0x1f, 0x7c, 0x83, 0xaa, 0xb7, 0x1d, 0xf0, 0xb6, 0x15, 0xdf, 0xa6, 0x17, 0xdc, 0x61, 0xc0, 0xb, 0x99, 0x97, 0x61, 0x83, 0x0, 0x8b, 0x88, 0x40, 0x26, 0xd0, 0xbf, 0xf0, 0xb, 0x2, 0xb0, 0xc3, 0x34, 0x89, 0x97, 0x30, 0xc6, 0xe1, 0xc0, 0x74, 0x3e, 0xc9, 0x9, 0x36, 0x6a, 0xd4, 0x4b, 0x1e, 0xc9, 0x44, 0x5a, 0x59, 0x19, 0xc2, 0x73, 0x2e, 0x21, 0x33, 0x99, 0x89, 0x96, 0x6, 0xb9, 0xc2, 0xfc, 0x75, 0x88, 0x5f, 0x40, 0xb3, 0x76, 0xe0, 0xd, 0x46, 0x91, 0x51, 0x2e, 0x72, 0xf6, 0xe6, 0xec, 0x17, 0x16, 0xc1, 0x96, 0x5, 0x18, 0xad, 0xb0, 0x43, 0x7e, 0xf, 0x13, 0xe0, 0xd1, 0xba, 0xfc, 0xe7, 0x77, 0xd3, 0x3b, 0xd0, 0xc3, 0x78, 0xf3, 0xb9, 0x22, 0xa2, 0xd3, 0x7b, 0x40, 0x6d, 0x3c, 0xc9, 0x35, 0xa7, 0x94, 0xb4, 0xec, 0x90, 0x47, 0x75, 0x15, 0x58, 0xf3, 0x3, 0xe, 0x1d, 0x38, 0x34, 0xf0, 0x4a, 0xb5, 0xe, 0x61, 0xa8, 0xb0, 0x90, 0xba, 0x57, 0xb0, 0x2e, 0xf3, 0xe2, 0x35, 0xbc, 0x82, 0xfe, 0x94, 0xfd, 0xca, 0xaa, 0x3b, 0xc8, 0x45, 0xee, 0x46, 0xe2, 0x74, 0x2c, 0xf5, 0x62, 0x6f, 0xdf, 0x87, 0xc1, 0x9e, 0x7d, 0xf7, 0xfb, 0xcf, 0x18, 0xe4, 0xa0, 0xf4, 0xf, 0x22, 0x3c, 0x3d, 0xa, 0x46, 0x1, 0x0, 0x24, 0x3a, 0x65, 0x42, 0x42, 0xc7, 0x4f, 0x7c, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
-};
-
static const unsigned char dropdown_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x8, 0x8, 0x4, 0x0, 0x0, 0x0, 0x6e, 0x6, 0x76, 0x0, 0x0, 0x0, 0x0, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x60, 0x60, 0xf8, 0xc0, 0xcc, 0x0, 0x2, 0x60, 0x16, 0x98, 0x78, 0x67, 0x8, 0x81, 0x6f, 0x4d, 0xde, 0x9a, 0x0, 0x5, 0xde, 0x3a, 0x3d, 0xfc, 0x8f, 0x80, 0xaf, 0xba, 0x18, 0xde, 0x29, 0x2, 0x19, 0xbf, 0x61, 0x2, 0x6f, 0x62, 0x18, 0x3e, 0xb0, 0xbd, 0x97, 0x4, 0x32, 0xff, 0x80, 0xb9, 0xb1, 0x20, 0x93, 0xc0, 0x42, 0x8, 0x2e, 0x54, 0xe8, 0x9d, 0xdc, 0x9b, 0x54, 0x10, 0xb, 0x21, 0xc4, 0x4, 0x63, 0x1, 0x0, 0x86, 0x1f, 0x3b, 0x1e, 0x92, 0x22, 0x3f, 0x40, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
@@ -78,14 +66,6 @@ static const unsigned char focus_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x4, 0x3, 0x0, 0x0, 0x0, 0xa4, 0x5b, 0x41, 0xd4, 0x0, 0x0, 0x0, 0x30, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0xff, 0xff, 0xff, 0xb9, 0xa2, 0x9b, 0xc9, 0x0, 0x0, 0x0, 0xf, 0x74, 0x52, 0x4e, 0x53, 0x0, 0xe, 0x39, 0x68, 0x7a, 0x7b, 0x3a, 0x74, 0x10, 0x8, 0x69, 0xf, 0x6, 0x75, 0x11, 0xb8, 0x16, 0x0, 0x1, 0x0, 0x0, 0x0, 0x38, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x10, 0x32, 0x9, 0xd, 0x75, 0x56, 0x64, 0x48, 0xef, 0x9c, 0x39, 0x73, 0x46, 0x19, 0xc3, 0x6a, 0x6, 0x20, 0xd8, 0xc5, 0x10, 0x3, 0xa2, 0x8e, 0x32, 0x44, 0x82, 0xa8, 0xa9, 0xd8, 0x29, 0xa8, 0x12, 0xb0, 0x6, 0x29, 0x86, 0xdc, 0x9d, 0x33, 0x67, 0xce, 0x2b, 0x63, 0x10, 0x3, 0x1b, 0x6, 0x0, 0xdf, 0xc6, 0x11, 0x6d, 0xb8, 0xf4, 0x9c, 0xac, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
-static const unsigned char frame_focus_png[] = {
- 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x4, 0x3, 0x0, 0x0, 0x0, 0xa4, 0x5b, 0x41, 0xd4, 0x0, 0x0, 0x0, 0x30, 0x50, 0x4c, 0x54, 0x45, 0xff, 0xff, 0xff, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0x47, 0x8c, 0xbf, 0xff, 0xff, 0xff, 0xcc, 0x40, 0x27, 0xb9, 0x0, 0x0, 0x0, 0xf, 0x74, 0x52, 0x4e, 0x53, 0x0, 0xe, 0x39, 0x68, 0x7a, 0x7b, 0x3a, 0x74, 0x10, 0x8, 0x69, 0xf, 0x6, 0x75, 0x11, 0xb8, 0x16, 0x0, 0x1, 0x0, 0x0, 0x0, 0x38, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x10, 0x32, 0x9, 0xd, 0x75, 0x56, 0x64, 0x48, 0xef, 0x9c, 0x39, 0x73, 0x46, 0x19, 0xc3, 0x6a, 0x6, 0x20, 0xd8, 0xc5, 0x10, 0x3, 0xa2, 0x8e, 0x32, 0x44, 0x82, 0xa8, 0xa9, 0xd8, 0x29, 0xa8, 0x12, 0xb0, 0x6, 0x29, 0x86, 0xdc, 0x9d, 0x33, 0x67, 0xce, 0x2b, 0x63, 0x10, 0x3, 0x1b, 0x6, 0x0, 0xdf, 0xc6, 0x11, 0x6d, 0xb8, 0xf4, 0x9c, 0xac, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
-};
-
-static const unsigned char full_panel_bg_png[] = {
- 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x20, 0x4, 0x3, 0x0, 0x0, 0x0, 0x81, 0x54, 0x67, 0xc7, 0x0, 0x0, 0x0, 0x30, 0x50, 0x4c, 0x54, 0x45, 0x27, 0x27, 0x29, 0x26, 0x26, 0x28, 0x25, 0x25, 0x27, 0x24, 0x24, 0x26, 0x23, 0x23, 0x25, 0x22, 0x22, 0x24, 0x21, 0x21, 0x23, 0x1e, 0x1e, 0x20, 0x1d, 0x1d, 0x1f, 0x1c, 0x1c, 0x1e, 0x31, 0x30, 0x32, 0x50, 0x4e, 0x54, 0x4e, 0x4c, 0x50, 0x4c, 0x4a, 0x4e, 0x3d, 0x3b, 0x3f, 0x38, 0x36, 0x3a, 0xb3, 0xde, 0x6f, 0x4d, 0x0, 0x0, 0x0, 0x5a, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x60, 0x60, 0x14, 0x52, 0x82, 0x3, 0x45, 0x1, 0x20, 0x5f, 0xd9, 0x35, 0xd, 0xe, 0x42, 0x8c, 0x4, 0x18, 0x98, 0xcc, 0x2a, 0x66, 0xc2, 0x41, 0x7b, 0xb2, 0x2, 0x83, 0x70, 0xd6, 0x9e, 0xbb, 0x70, 0x70, 0x7a, 0x99, 0x21, 0x83, 0x48, 0xf5, 0xfb, 0xff, 0x70, 0xf0, 0x6f, 0xbb, 0x23, 0x83, 0x6a, 0xcf, 0x7f, 0x24, 0x70, 0x22, 0x88, 0x41, 0x6d, 0x2e, 0xb2, 0xc0, 0xcd, 0x24, 0x8a, 0x5, 0x46, 0x5, 0x30, 0x2, 0x19, 0x23, 0x1a, 0x30, 0x22, 0xa, 0x23, 0x2a, 0x31, 0x22, 0x1b, 0x23, 0x39, 0x0, 0x0, 0x8c, 0xb1, 0x80, 0xd2, 0x41, 0x59, 0x8c, 0x74, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
-};
-
static const unsigned char graph_node_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x40, 0x8, 0x6, 0x0, 0x0, 0x0, 0x13, 0x7d, 0xf7, 0x96, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xe0, 0x8, 0x17, 0xd, 0x5, 0x12, 0xa1, 0x38, 0x83, 0x9b, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x0, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0xe, 0x17, 0x0, 0x0, 0x2, 0x74, 0x49, 0x44, 0x41, 0x54, 0x58, 0xc3, 0xed, 0x97, 0x3d, 0x6f, 0xd3, 0x60, 0x10, 0xc7, 0x7f, 0x17, 0x9b, 0x26, 0x25, 0x22, 0xad, 0xa, 0x8, 0xf1, 0x52, 0x75, 0x0, 0x16, 0x24, 0x90, 0x2a, 0x96, 0x7c, 0x1, 0x6, 0xc4, 0xce, 0xc4, 0x17, 0x0, 0x31, 0xb0, 0x30, 0x0, 0x23, 0x82, 0x85, 0x5, 0x9, 0x4, 0x5f, 0x80, 0x89, 0x1d, 0x31, 0xf0, 0x5, 0x58, 0x50, 0x25, 0x50, 0x59, 0x80, 0xa1, 0xe2, 0xad, 0x28, 0x34, 0x4a, 0x3, 0x25, 0x76, 0xea, 0xe7, 0x39, 0x6, 0x3f, 0x76, 0x6d, 0xc7, 0x49, 0x5f, 0xd8, 0x90, 0x6f, 0xb1, 0xf5, 0xe4, 0xb9, 0xdf, 0xdd, 0xfd, 0xef, 0x22, 0xf9, 0x84, 0x2d, 0x13, 0xa0, 0x6, 0x78, 0xee, 0x29, 0xe4, 0x4d, 0x1, 0xb, 0x18, 0xf7, 0x54, 0x32, 0x97, 0x6a, 0xc0, 0x7e, 0x60, 0xe, 0x38, 0xc, 0xb4, 0x80, 0x7d, 0x5, 0xc0, 0x26, 0xd0, 0x7, 0x3a, 0x40, 0x17, 0xf8, 0x3, 0xd8, 0x24, 0x6a, 0x13, 0x38, 0x35, 0x73, 0x60, 0xf6, 0x6a, 0xa3, 0xde, 0xb8, 0x38, 0x35, 0x55, 0x3f, 0x41, 0x89, 0xd, 0x87, 0xe1, 0x97, 0x20, 0xc, 0x5e, 0xae, 0xff, 0xea, 0x3d, 0x5, 0x3e, 0x2, 0x1b, 0xe2, 0x22, 0x2d, 0xcc, 0xcd, 0x1e, 0x7c, 0x78, 0x72, 0xe1, 0xf4, 0xa5, 0x7b, 0xb7, 0x1f, 0x7c, 0x9e, 0x6e, 0x35, 0xca, 0xfc, 0x19, 0xf4, 0x3, 0xee, 0xdc, 0xbf, 0x39, 0xff, 0x69, 0xe5, 0xc3, 0x8b, 0x6e, 0x6f, 0xed, 0x6, 0xb0, 0x22, 0x40, 0x3, 0x58, 0x3c, 0x7a, 0xe4, 0xf8, 0xab, 0x67, 0x4f, 0x9e, 0x77, 0xa3, 0xc8, 0x12, 0xd, 0xa3, 0x52, 0x80, 0x3f, 0xe5, 0xe3, 0xfb, 0x35, 0xae, 0x5c, 0xbb, 0x3c, 0xf7, 0xfd, 0xc7, 0xd7, 0xb, 0xc0, 0x92, 0xef, 0x74, 0x68, 0xfa, 0x9e, 0xdf, 0x1c, 0xfc, 0xe, 0xbb, 0x88, 0xc6, 0x47, 0xa, 0x2a, 0x59, 0x85, 0x95, 0x61, 0xb8, 0xc9, 0x30, 0x4, 0xdf, 0xf3, 0x9b, 0xae, 0x6c, 0x49, 0x0, 0x1e, 0x80, 0x51, 0x1b, 0xfb, 0xc7, 0x2, 0xc7, 0x5a, 0x3b, 0x88, 0x66, 0xcf, 0x63, 0xf3, 0x12, 0x80, 0x26, 0xbf, 0xa8, 0xb5, 0xa8, 0xa, 0x88, 0x22, 0x8, 0x8a, 0x22, 0x2a, 0x19, 0x37, 0x1d, 0xe9, 0xad, 0x9f, 0x6b, 0xb4, 0x55, 0x14, 0x5, 0x55, 0x44, 0xe2, 0x32, 0x6c, 0xe2, 0x24, 0x71, 0x18, 0x9d, 0x4, 0xb0, 0x6a, 0xd3, 0x1b, 0x2a, 0xe9, 0x4b, 0xfc, 0xae, 0xe4, 0x45, 0x19, 0x9f, 0x81, 0x2b, 0xdb, 0x15, 0xa6, 0xa2, 0x19, 0x2d, 0xec, 0x8, 0x24, 0x7, 0x30, 0xd6, 0x16, 0xf8, 0x82, 0xa8, 0xc6, 0x45, 0x68, 0x52, 0xbf, 0x4e, 0xce, 0x60, 0xeb, 0x42, 0x5c, 0xb4, 0x66, 0x9c, 0x6c, 0xc9, 0x1f, 0xa4, 0x0, 0xb0, 0x39, 0xc5, 0xc9, 0xa1, 0x28, 0x89, 0x5f, 0x14, 0xd1, 0x5a, 0x37, 0x32, 0x89, 0xf2, 0x82, 0xc6, 0x3, 0xe0, 0xda, 0xa, 0x22, 0x3a, 0xa9, 0xb, 0x9a, 0x26, 0xaa, 0xf1, 0x41, 0x9a, 0x42, 0x2, 0xb2, 0xb2, 0x6d, 0x6, 0x5b, 0xa3, 0xab, 0x23, 0xd5, 0x48, 0x32, 0x92, 0xe3, 0x33, 0x10, 0x37, 0xb7, 0x2a, 0xea, 0xee, 0x4a, 0x2a, 0x42, 0xe, 0x5a, 0x2a, 0xa2, 0x51, 0x37, 0x40, 0x85, 0x48, 0x96, 0xb4, 0x23, 0xdb, 0x88, 0x68, 0x5c, 0xc4, 0xcc, 0x3c, 0x14, 0xa7, 0x6f, 0xa2, 0x6, 0xaa, 0xb1, 0x7c, 0xd9, 0x30, 0xaa, 0x79, 0xc7, 0x49, 0x93, 0x78, 0xf7, 0xd1, 0xad, 0x79, 0x76, 0x69, 0x29, 0x20, 0xda, 0x34, 0x2c, 0x9e, 0x3d, 0xff, 0x7a, 0x27, 0x4e, 0x4b, 0xef, 0xde, 0xb4, 0x4b, 0x33, 0x58, 0xef, 0xf7, 0x76, 0x9b, 0x0, 0x35, 0xfe, 0xd1, 0x2a, 0x40, 0x5, 0xa8, 0x0, 0x15, 0xa0, 0x2, 0x54, 0x80, 0xa, 0xf0, 0x5f, 0x2, 0xa4, 0xe4, 0x13, 0x78, 0xd7, 0x19, 0xd8, 0x3d, 0xf8, 0xda, 0x4, 0x60, 0x81, 0xc0, 0x18, 0x13, 0xda, 0x68, 0x7, 0x5e, 0x11, 0x18, 0x63, 0x42, 0x20, 0x0, 0x6c, 0xcd, 0xad, 0xb2, 0x6b, 0x41, 0x38, 0x58, 0xee, 0x74, 0x57, 0xdb, 0x93, 0x20, 0x36, 0x82, 0x4e, 0x77, 0xb5, 0x1d, 0x84, 0x83, 0x65, 0x60, 0xd, 0x30, 0xc9, 0xe6, 0x3a, 0x3, 0x9c, 0x6b, 0x35, 0x67, 0x1f, 0x37, 0xea, 0xd3, 0x67, 0x3c, 0xcf, 0x2b, 0x15, 0xd7, 0x18, 0x63, 0x83, 0x70, 0xf0, 0xbe, 0xbf, 0xd1, 0xbb, 0xe, 0xbc, 0x5, 0xd6, 0x25, 0xb3, 0xc2, 0xb5, 0x80, 0x63, 0xc0, 0x21, 0xa0, 0x3e, 0x66, 0xf9, 0xe, 0x81, 0x9f, 0xc0, 0x37, 0xb7, 0x47, 0x1b, 0x29, 0x8, 0xea, 0x27, 0xfb, 0xe0, 0x98, 0x2a, 0xd4, 0x95, 0x1c, 0xed, 0x51, 0xf8, 0x51, 0xfb, 0xb, 0x1, 0xbe, 0x20, 0x9f, 0x90, 0x81, 0x17, 0xaa, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
@@ -178,10 +158,6 @@ static const unsigned char icon_parent_folder_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x68, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0xa0, 0x33, 0xb8, 0x27, 0xfe, 0xe0, 0xfc, 0x83, 0x73, 0xf7, 0xc4, 0x71, 0x48, 0xdf, 0x11, 0x7b, 0x78, 0xe9, 0xc1, 0x3f, 0x20, 0xbc, 0xfe, 0x40, 0x12, 0x8f, 0x34, 0x4c, 0x9, 0xa6, 0xe1, 0x57, 0x80, 0x12, 0x17, 0x81, 0xf8, 0x2f, 0x58, 0xe1, 0x15, 0x34, 0x8b, 0x1e, 0x9c, 0x5, 0xa, 0x5e, 0xb8, 0x23, 0x6, 0x52, 0x70, 0x5b, 0x14, 0xac, 0xf0, 0xc, 0xaa, 0x82, 0x7d, 0xf, 0x8e, 0xde, 0x14, 0xf9, 0xcf, 0x8, 0x52, 0xc0, 0xc0, 0x70, 0x5b, 0xf4, 0xe1, 0xc9, 0x7, 0x47, 0xb1, 0xb8, 0x3, 0xaa, 0x0, 0xa, 0x48, 0x52, 0x80, 0xb0, 0xea, 0xc8, 0xc3, 0x83, 0xc, 0x83, 0xe, 0x0, 0x0, 0xb8, 0x27, 0x55, 0x4c, 0xbe, 0xc0, 0xd2, 0xac, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
-static const unsigned char icon_play_png[] = {
- 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x41, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0xa0, 0x1b, 0x78, 0x70, 0xf8, 0xc1, 0xb5, 0x7, 0xde, 0xf8, 0x14, 0xfc, 0x7, 0xc1, 0x87, 0x3b, 0x1e, 0x6a, 0xe1, 0x54, 0x0, 0x85, 0xbf, 0x1f, 0x4c, 0x79, 0x22, 0x8c, 0x5d, 0x1, 0x2, 0xbe, 0x7f, 0x58, 0x7e, 0x9b, 0x1d, 0x43, 0x1, 0x1a, 0x3c, 0x4c, 0x91, 0x82, 0x77, 0x8, 0x2b, 0x8, 0x3b, 0x12, 0xd3, 0x9b, 0x84, 0x3, 0x8a, 0xfe, 0x0, 0x0, 0xa4, 0x15, 0x70, 0xca, 0x48, 0x40, 0x6f, 0xa6, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
-};
-
static const unsigned char icon_reload_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0xb1, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xad, 0x50, 0x35, 0xba, 0xc2, 0x40, 0x10, 0x7e, 0xcd, 0x33, 0x5c, 0xca, 0x1c, 0x21, 0x87, 0xc1, 0xa9, 0xd3, 0x23, 0x47, 0xca, 0x69, 0xb0, 0x6, 0x77, 0xdb, 0xfd, 0x17, 0x2f, 0x91, 0x3e, 0xee, 0xd2, 0xc1, 0x4e, 0xb5, 0xdf, 0xcc, 0xaf, 0x5f, 0x9f, 0x7c, 0xdb, 0x5f, 0xda, 0x44, 0x17, 0x2f, 0x75, 0xba, 0xa4, 0xb1, 0xfd, 0xf5, 0xad, 0x8f, 0x1c, 0x86, 0x90, 0x5c, 0x33, 0x38, 0x72, 0x1e, 0xb4, 0xbe, 0x66, 0x28, 0xad, 0xe2, 0xab, 0x38, 0xcd, 0x63, 0xa9, 0x9d, 0xb8, 0x58, 0x68, 0x53, 0x5b, 0x1f, 0x33, 0xd6, 0x9f, 0xa5, 0xc1, 0x20, 0x91, 0xba, 0x7d, 0x80, 0x1e, 0x24, 0x94, 0xdc, 0x92, 0xa4, 0x2, 0x9, 0x1d, 0xe7, 0xe0, 0x9, 0x69, 0x15, 0xf7, 0x58, 0x4e, 0x40, 0xc2, 0xc3, 0x58, 0x8a, 0xb6, 0x31, 0xd1, 0x39, 0xd8, 0x27, 0xed, 0x83, 0x5b, 0x14, 0x33, 0x7d, 0x3d, 0xbb, 0x45, 0x5d, 0x12, 0x55, 0x97, 0x4, 0xe3, 0xb5, 0xf4, 0x8c, 0x77, 0xd6, 0xa7, 0x2c, 0x3b, 0x78, 0x4c, 0x52, 0x81, 0xa, 0x8e, 0x3a, 0xa9, 0x6a, 0x6b, 0xc, 0xe6, 0x3f, 0xa1, 0x8d, 0x86, 0x16, 0xe5, 0x39, 0x78, 0xa2, 0x4d, 0xea, 0xe, 0xfa, 0xdd, 0xa7, 0x0, 0x90, 0x4f, 0x8b, 0xd0, 0xe1, 0x9e, 0x1b, 0xc2, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
@@ -190,10 +166,6 @@ static const unsigned char icon_snap_grid_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x33, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0xf3, 0xf3, 0xf3, 0xff, 0x84, 0x84, 0xff, 0x84, 0x84, 0xff, 0x84, 0x84, 0xff, 0x85, 0x85, 0xff, 0x83, 0x83, 0xff, 0x84, 0x84, 0xff, 0x84, 0x84, 0xff, 0x84, 0x84, 0xff, 0x84, 0x84, 0xff, 0x84, 0x84, 0xff, 0x80, 0x80, 0xff, 0x84, 0x84, 0xff, 0x84, 0x84, 0xff, 0x84, 0x84, 0xff, 0xff, 0xff, 0xa, 0xa5, 0x43, 0x1, 0x0, 0x0, 0x0, 0x10, 0x74, 0x52, 0x4e, 0x53, 0x0, 0xff, 0x1d, 0xac, 0xf2, 0xaf, 0x27, 0xed, 0xff, 0xee, 0xb4, 0x1b, 0x1c, 0xb6, 0xaa, 0xf1, 0x50, 0xa6, 0xdd, 0x5f, 0x0, 0x0, 0x0, 0x4e, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x62, 0x0, 0x2, 0x40, 0x23, 0xd3, 0x60, 0x0, 0x40, 0xc, 0x3, 0xaf, 0x76, 0x93, 0xfd, 0x97, 0x7d, 0x9b, 0x55, 0x70, 0x12, 0x62, 0xaf, 0x68, 0x0, 0xc4, 0xe9, 0x3c, 0x1, 0x67, 0xf7, 0x17, 0x20, 0x95, 0xd6, 0xc6, 0xee, 0x80, 0x74, 0xde, 0x7b, 0x1f, 0x24, 0xb0, 0x64, 0x29, 0x1f, 0x53, 0x2e, 0xbe, 0x6e, 0x80, 0xf6, 0x19, 0x90, 0x9e, 0x36, 0x8b, 0xf7, 0xc0, 0x5c, 0xdf, 0x0, 0x66, 0x60, 0xae, 0xf3, 0xb9, 0x1, 0xfb, 0xe9, 0x1, 0xa6, 0x26, 0x1, 0xcd, 0x30, 0x66, 0x63, 0x6, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
-static const unsigned char icon_stop_png[] = {
- 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x1e, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x20, 0x2, 0x7c, 0x60, 0x26, 0x28, 0xf3, 0xf0, 0x3f, 0x76, 0x8, 0x94, 0xa2, 0x97, 0x82, 0x51, 0x5, 0x84, 0x23, 0x8b, 0x30, 0x0, 0x0, 0x66, 0x60, 0x11, 0xdc, 0x92, 0xb3, 0xb7, 0xe7, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
-};
-
static const unsigned char icon_visibility_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x3, 0x73, 0x42, 0x49, 0x54, 0x8, 0x8, 0x8, 0xdb, 0xe1, 0x4f, 0xe0, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xe, 0xc4, 0x0, 0x0, 0xe, 0xc4, 0x1, 0x95, 0x2b, 0xe, 0x1b, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x0, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x6e, 0x6b, 0x73, 0x63, 0x61, 0x70, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x9b, 0xee, 0x3c, 0x1a, 0x0, 0x0, 0x0, 0x96, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0xdf, 0xdf, 0xdf, 0xe3, 0xe3, 0xe3, 0xe6, 0xe6, 0xe6, 0xd5, 0xd5, 0xd5, 0xd8, 0xd8, 0xd8, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xe1, 0xe1, 0xe1, 0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xde, 0xde, 0xde, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xb7, 0x7e, 0xd, 0xb6, 0x0, 0x0, 0x0, 0x32, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x8, 0x9, 0xa, 0xc, 0xd, 0xe, 0xf, 0x11, 0x12, 0x13, 0x2e, 0x2f, 0x32, 0x33, 0x36, 0x37, 0x38, 0x48, 0x49, 0x4b, 0x50, 0x53, 0x55, 0x56, 0x6c, 0x6d, 0x6e, 0x70, 0x77, 0x79, 0x7b, 0x7c, 0xc5, 0xd7, 0xd8, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1, 0xe2, 0xe3, 0xf0, 0xf2, 0xf3, 0xf4, 0xfe, 0x5e, 0x62, 0x1a, 0x26, 0x0, 0x0, 0x0, 0x86, 0x49, 0x44, 0x41, 0x54, 0x18, 0x19, 0x8d, 0xc1, 0xb, 0x16, 0x42, 0x40, 0x0, 0x86, 0xd1, 0x2f, 0xa2, 0x77, 0x2a, 0x85, 0xde, 0x91, 0x5e, 0x33, 0x8a, 0x7f, 0xff, 0x9b, 0xcb, 0x99, 0x63, 0x1, 0xee, 0xa5, 0x9f, 0xc1, 0x3e, 0x6f, 0xea, 0xfc, 0xe0, 0xd1, 0x99, 0xdd, 0xe5, 0x94, 0xb, 0x9c, 0xf9, 0x57, 0x26, 0x9, 0x82, 0x5d, 0xa1, 0xdf, 0x92, 0x96, 0xf7, 0x94, 0x99, 0xd0, 0x1a, 0x1b, 0x7d, 0x7c, 0xe0, 0x2c, 0x25, 0x6c, 0x2b, 0x1b, 0x93, 0x4a, 0x17, 0xa0, 0x94, 0x2, 0xac, 0x64, 0x8, 0xa5, 0x12, 0x78, 0x48, 0x1, 0x56, 0x32, 0x8c, 0xa4, 0x7, 0x70, 0x93, 0x76, 0xc4, 0xd6, 0x6c, 0xc8, 0xa4, 0x2b, 0x30, 0xac, 0x54, 0x8c, 0x69, 0x4d, 0xad, 0xcc, 0x90, 0xd6, 0xba, 0x91, 0x49, 0xc3, 0x30, 0xb3, 0x6a, 0x22, 0x9c, 0xd5, 0x5b, 0xce, 0x2b, 0xa2, 0xe3, 0x9f, 0xf2, 0xba, 0xce, 0x8f, 0x3e, 0xbd, 0xfc, 0x1, 0xdb, 0xf3, 0x10, 0xc5, 0x78, 0x85, 0x14, 0x89, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
@@ -222,14 +194,6 @@ static const unsigned char line_edit_disabled_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0xa, 0x8, 0x4, 0x0, 0x0, 0x0, 0x27, 0x3b, 0x7, 0x36, 0x0, 0x0, 0x0, 0x4e, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x94, 0xc8, 0x67, 0x6b, 0x60, 0xe6, 0x60, 0x64, 0x80, 0x80, 0xff, 0xc, 0x7f, 0x7f, 0xfc, 0x6a, 0x60, 0x94, 0xfb, 0xc0, 0xce, 0xcf, 0xc2, 0x80, 0x10, 0xfc, 0xc3, 0xf0, 0xf3, 0x23, 0xa3, 0xe2, 0x4f, 0xe, 0x36, 0x54, 0xc1, 0x1f, 0xbf, 0x18, 0x95, 0xbe, 0x73, 0x70, 0xb0, 0x30, 0xc0, 0x1, 0x48, 0xf0, 0x7, 0x85, 0x82, 0x58, 0x2d, 0xc2, 0xe6, 0xa4, 0x4f, 0x20, 0xc7, 0x37, 0x32, 0xb3, 0x23, 0x39, 0xfe, 0xfb, 0xaf, 0x46, 0x0, 0xee, 0x2a, 0x2f, 0xce, 0x4c, 0x47, 0x66, 0xf6, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
-static const unsigned char line_edit_focus_png[] = {
- 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0xa8, 0x50, 0x4c, 0x54, 0x45, 0x1b, 0x17, 0x18, 0x1b, 0x17, 0x18, 0x1b, 0x17, 0x18, 0xc8, 0x68, 0x12, 0xef, 0xed, 0xe7, 0xef, 0xed, 0xe8, 0xf0, 0xed, 0xe8, 0xf0, 0xee, 0xe8, 0xf0, 0xed, 0xe7, 0xed, 0xeb, 0xe5, 0xee, 0xeb, 0xe5, 0xee, 0xeb, 0xe6, 0xec, 0xe9, 0xe3, 0xeb, 0xe9, 0xe3, 0xeb, 0xe9, 0xe2, 0xec, 0xe9, 0xe2, 0xe9, 0xe6, 0xe0, 0xea, 0xe7, 0xe0, 0xea, 0xe7, 0xe1, 0xe8, 0xe4, 0xdd, 0xe8, 0xe5, 0xde, 0xe8, 0xe5, 0xdd, 0xe8, 0xe4, 0xde, 0xe6, 0xe2, 0xdb, 0xe6, 0xe3, 0xdb, 0xe6, 0xe3, 0xdc, 0xe7, 0xe2, 0xdb, 0xe7, 0xe3, 0xdb, 0xe4, 0xe0, 0xd8, 0xe5, 0xe0, 0xd8, 0xe5, 0xe1, 0xd9, 0xe5, 0xe0, 0xd9, 0xe4, 0xe1, 0xd9, 0xe5, 0xe1, 0xd8, 0xe4, 0xe0, 0xd9, 0xe2, 0xdf, 0xd6, 0xe3, 0xdf, 0xd6, 0xe3, 0xde, 0xd6, 0xe2, 0xde, 0xd6, 0xe1, 0xdc, 0xd4, 0xe1, 0xdc, 0xd3, 0xe0, 0xdc, 0xd3, 0xe1, 0xdd, 0xd3, 0xe1, 0xdd, 0xd4, 0xdf, 0xda, 0xd0, 0xdf, 0xda, 0xd1, 0xdf, 0xdb, 0xd1, 0xe0, 0xda, 0xd1, 0xdd, 0xd8, 0xcf, 0xdd, 0xd8, 0xce, 0xde, 0xd9, 0xce, 0xde, 0xd8, 0xce, 0xdd, 0xd9, 0xce, 0xdc, 0xd6, 0xcc, 0xdb, 0xd6, 0xcc, 0xdc, 0xd6, 0xcb, 0xbd, 0x92, 0xbc, 0xa2, 0x0, 0x0, 0x0, 0x2, 0x74, 0x52, 0x4e, 0x53, 0x36, 0x61, 0xc5, 0x3a, 0xd, 0x83, 0x0, 0x0, 0x0, 0x72, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x4c, 0x8c, 0x55, 0x2, 0x4, 0x1, 0x8, 0x85, 0xc0, 0xc9, 0xfb, 0x1f, 0x76, 0x7b, 0x75, 0x3a, 0xf0, 0xc7, 0xc0, 0x27, 0xc1, 0x9d, 0x34, 0xe4, 0x4e, 0xb5, 0xa0, 0x68, 0x95, 0xf1, 0x93, 0xc4, 0xb0, 0xb7, 0xd6, 0x2, 0x7c, 0x2d, 0x46, 0xc3, 0x82, 0x45, 0xf8, 0x87, 0x16, 0x5a, 0xd7, 0x71, 0x21, 0x9e, 0x2c, 0x86, 0x52, 0x10, 0x89, 0xee, 0x86, 0x15, 0xd9, 0xf0, 0x6b, 0x7f, 0xac, 0x8b, 0xce, 0x85, 0xb4, 0x8b, 0xe1, 0xb7, 0x2e, 0x6, 0xd9, 0x53, 0x6a, 0x3c, 0x43, 0xa9, 0xd0, 0xcc, 0xd8, 0x5f, 0xd0, 0x4, 0xa2, 0xf6, 0x50, 0xac, 0x68, 0xff, 0x6d, 0xf9, 0x3f, 0xc, 0x93, 0x88, 0x59, 0x68, 0x81, 0x69, 0x18, 0x9e, 0x3, 0xba, 0x1b, 0x55, 0x0, 0x0, 0x0, 0x69, 0x26, 0x8d, 0xeb, 0x4b, 0xad, 0xe7, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
-};
-
-static const unsigned char logo_png[] = {
- 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x80, 0x8, 0x6, 0x0, 0x0, 0x0, 0xc3, 0x3e, 0x61, 0xcb, 0x0, 0x0, 0x19, 0xdb, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xec, 0x99, 0x3, 0x94, 0x7b, 0x39, 0x14, 0xc6, 0xd7, 0xb6, 0xed, 0x87, 0x62, 0x6d, 0xdb, 0x33, 0xe5, 0x6b, 0xc7, 0x6b, 0xdb, 0xb6, 0x77, 0x5c, 0xb7, 0x6b, 0xdb, 0xb6, 0x6d, 0xdb, 0xb6, 0xbd, 0xdb, 0x74, 0xbf, 0xde, 0xe6, 0x35, 0xff, 0xe6, 0xcc, 0xdb, 0x1d, 0x9f, 0x37, 0xd3, 0xe4, 0x9c, 0xdf, 0x49, 0x5e, 0x9c, 0x7c, 0x37, 0x37, 0x39, 0xed, 0x54, 0x2a, 0xa8, 0xa0, 0x82, 0xa, 0x2a, 0xa8, 0xa0, 0x82, 0xa, 0x2a, 0xa8, 0xa0, 0x82, 0xa, 0xf5, 0x17, 0x8c, 0x48, 0x6a, 0xe, 0x23, 0xd4, 0x73, 0xa5, 0x16, 0xe8, 0xba, 0x5f, 0xb, 0x74, 0xdf, 0xac, 0x87, 0x7a, 0x2f, 0x34, 0xc3, 0xfd, 0x9d, 0x66, 0x24, 0x71, 0x0, 0xca, 0xa2, 0x66, 0x34, 0xb3, 0xba, 0x37, 0x9e, 0x5f, 0x78, 0x92, 0x2e, 0x5f, 0x5, 0x3d, 0xd4, 0x77, 0xe6, 0x72, 0xd, 0xa7, 0x33, 0x50, 0x2a, 0xa3, 0x35, 0x9c, 0x5e, 0xd4, 0x1a, 0xcf, 0xfc, 0x19, 0x7c, 0xae, 0x35, 0x76, 0xbe, 0xa5, 0x5, 0x3a, 0x9f, 0xd5, 0x1a, 0xbb, 0x1e, 0xd4, 0x83, 0x3d, 0xb7, 0x1b, 0xe1, 0xbe, 0x4b, 0xcd, 0x48, 0xf2, 0x0, 0x4f, 0x2c, 0xe7, 0x9f, 0x4, 0x4b, 0x57, 0xc1, 0x13, 0x3f, 0x6b, 0x16, 0x8, 0xfc, 0xe9, 0x72, 0xd, 0x67, 0x94, 0xb4, 0xc6, 0x32, 0x67, 0x56, 0x41, 0x9e, 0xc, 0x2f, 0xeb, 0xfc, 0xa, 0xc6, 0x70, 0x97, 0xc7, 0xca, 0x2c, 0x3e, 0x8e, 0x53, 0x55, 0xc1, 0xb4, 0xb2, 0x1b, 0xeb, 0x70, 0xcd, 0x38, 0xb1, 0x29, 0x23, 0x92, 0x38, 0x79, 0xa4, 0xfd, 0xad, 0xbe, 0xff, 0x63, 0x53, 0x1b, 0xd1, 0xf4, 0x36, 0x7a, 0xa0, 0xf3, 0x77, 0x12, 0xb6, 0xe1, 0xc, 0x46, 0xb1, 0x94, 0x6, 0xac, 0x36, 0x26, 0x63, 0x28, 0xc2, 0x0, 0x1a, 0xd6, 0x3c, 0xf0, 0x89, 0xa9, 0x95, 0x32, 0x63, 0x18, 0x8c, 0x68, 0x66, 0x29, 0x23, 0x92, 0xdc, 0x5, 0xc2, 0x77, 0xe1, 0x7e, 0x7e, 0xaa, 0x2a, 0x4a, 0xa0, 0xf3, 0xf, 0xe4, 0xef, 0x30, 0x62, 0xf7, 0x1f, 0xec, 0x7d, 0x0, 0xfd, 0xfd, 0x83, 0xfe, 0x4a, 0x2, 0xea, 0xdf, 0x11, 0xee, 0x5, 0x7e, 0xc7, 0x55, 0x70, 0x4, 0xd2, 0xd3, 0x28, 0x95, 0xc6, 0xe6, 0xb4, 0xaf, 0x60, 0x46, 0x53, 0xbb, 0x18, 0xa1, 0xbe, 0xab, 0xb0, 0xd9, 0x3f, 0x83, 0xaa, 0x6b, 0xd6, 0x85, 0x8, 0xdf, 0x98, 0x56, 0x66, 0xbd, 0x61, 0x8f, 0x11, 0xcb, 0x2d, 0x36, 0x45, 0x9f, 0xc, 0x94, 0x6, 0x3, 0x1f, 0xfb, 0x2f, 0x23, 0xdc, 0x7f, 0x99, 0x1e, 0x18, 0x5d, 0x3, 0x50, 0xc2, 0x47, 0xb3, 0xcb, 0x43, 0xf8, 0x3d, 0xe1, 0xe6, 0xef, 0xc4, 0x26, 0x33, 0x50, 0x2, 0xd8, 0xf8, 0xae, 0x32, 0x8c, 0xc7, 0x94, 0xbf, 0x1c, 0x84, 0xc0, 0x9, 0x7e, 0xdc, 0x13, 0xcb, 0xcf, 0x3f, 0xf4, 0x97, 0x7f, 0x72, 0x7a, 0x33, 0x9a, 0xde, 0x1b, 0xfd, 0xd0, 0xe9, 0x47, 0x9f, 0x83, 0x86, 0xe6, 0x14, 0xe8, 0x2a, 0xe2, 0x1d, 0xf0, 0xa2, 0x27, 0x5e, 0x98, 0x56, 0xa9, 0x36, 0xa, 0x1, 0xaf, 0xea, 0xc5, 0x3d, 0xb1, 0x6c, 0xb, 0x4e, 0xfc, 0xdd, 0xd8, 0xdc, 0x12, 0x87, 0x8b, 0xce, 0xd3, 0x41, 0x21, 0x2, 0x44, 0x63, 0x4, 0xd2, 0x30, 0x98, 0x33, 0xe1, 0x9, 0x66, 0x1a, 0xd2, 0x78, 0x10, 0xe, 0x2f, 0xfa, 0x47, 0xf4, 0x60, 0x37, 0x84, 0xa4, 0xfe, 0x2a, 0xfd, 0xcb, 0x4, 0x44, 0x9a, 0x8b, 0xcf, 0xec, 0x34, 0xc6, 0xfe, 0xc1, 0xd7, 0x7a, 0xe1, 0x74, 0x4a, 0xbd, 0x51, 0x8, 0x10, 0x31, 0x3, 0x31, 0x4a, 0x53, 0xc0, 0x0, 0x17, 0x5e, 0xe4, 0xf3, 0x3c, 0x2a, 0xe3, 0x14, 0xc9, 0x8, 0xac, 0xac, 0x5, 0x61, 0x1c, 0xdd, 0xb1, 0xaf, 0xf5, 0xa2, 0xe9, 0x4c, 0x2b, 0x37, 0xbf, 0x27, 0x56, 0x58, 0x6, 0xc6, 0x66, 0x80, 0xd, 0xd1, 0xf6, 0x1f, 0xd1, 0x8f, 0xe8, 0xd3, 0x19, 0x31, 0x3e, 0x28, 0x95, 0xbd, 0x7, 0xfa, 0x55, 0x6, 0x30, 0x1a, 0x1, 0xae, 0xfc, 0xb, 0x3d, 0x20, 0x84, 0x1f, 0x4, 0x4c, 0x8, 0x82, 0x38, 0xd4, 0xfb, 0x11, 0xae, 0x82, 0xd5, 0x21, 0xec, 0xac, 0x38, 0xdd, 0xcb, 0x80, 0x55, 0xbc, 0xf1, 0xc2, 0x9a, 0xde, 0xa6, 0xc2, 0x5a, 0x65, 0xb1, 0xe1, 0x21, 0x3a, 0x60, 0x64, 0xdd, 0x78, 0x4c, 0x5e, 0x8b, 0xbb, 0xfb, 0x1, 0x78, 0x9a, 0x77, 0xe5, 0xbe, 0x6, 0xd, 0x79, 0x25, 0x1a, 0xf7, 0xaf, 0xd1, 0xb8, 0x2, 0x3c, 0x4d, 0xe7, 0xcc, 0xa2, 0x5e, 0xfb, 0xe1, 0xc4, 0xc3, 0xb8, 0x53, 0x8b, 0xa0, 0x4, 0x18, 0xc5, 0x32, 0x21, 0xe9, 0x3b, 0x0, 0xe1, 0x0, 0xd2, 0x24, 0x20, 0xee, 0xf5, 0xcb, 0x71, 0xaf, 0x1f, 0xd, 0x91, 0xef, 0x45, 0xde, 0xaf, 0xbc, 0x9e, 0x83, 0x90, 0x7c, 0x1c, 0xe0, 0x3c, 0x8e, 0x9c, 0xcf, 0xc7, 0x14, 0x75, 0xfe, 0x42, 0x5f, 0x23, 0x7a, 0x4, 0x7a, 0x9b, 0xce, 0x5a, 0x1a, 0xde, 0x6b, 0x6f, 0x18, 0xef, 0xf2, 0x75, 0xfe, 0x6, 0xc8, 0x9e, 0x82, 0x53, 0xf9, 0x43, 0x79, 0x73, 0x8d, 0x50, 0x6f, 0x15, 0x5d, 0x66, 0xa0, 0x7c, 0xb4, 0x41, 0x5c, 0xe4, 0x69, 0x81, 0x28, 0x23, 0xb1, 0x45, 0x1b, 0xa4, 0xed, 0x7c, 0xb9, 0x4c, 0x8c, 0xed, 0x38, 0x9e, 0x21, 0xc6, 0xf9, 0x1b, 0x1e, 0x60, 0x35, 0x33, 0x96, 0x5b, 0xc4, 0xdb, 0x7c, 0xee, 0xec, 0x43, 0x59, 0x2f, 0xea, 0xcf, 0xe2, 0x8d, 0x9f, 0x65, 0xea, 0xe1, 0xbe, 0x77, 0x78, 0xbf, 0x5f, 0x9a, 0xb1, 0xfc, 0x46, 0xde, 0xa6, 0xb3, 0x67, 0xa8, 0x4b, 0x3, 0xc0, 0xe2, 0xb7, 0x81, 0x1, 0x7c, 0x62, 0x88, 0xd, 0x66, 0x94, 0x1e, 0x1c, 0x8c, 0xb7, 0xb1, 0xd3, 0xf2, 0x77, 0x69, 0x94, 0xa9, 0xf1, 0x1e, 0xb8, 0x52, 0xde, 0xc1, 0x15, 0x73, 0x3a, 0xae, 0x1c, 0x1d, 0xcc, 0x8a, 0xbc, 0xff, 0xf4, 0xa, 0x38, 0xed, 0xb, 0xa2, 0xfe, 0xa1, 0x7a, 0x10, 0xfd, 0x10, 0x3d, 0xd5, 0xf9, 0x22, 0xff, 0x8, 0xfc, 0xef, 0x30, 0x5f, 0xfd, 0x79, 0x80, 0xa6, 0xb3, 0x97, 0xc1, 0x46, 0xbe, 0x5b, 0x39, 0x91, 0x10, 0x2d, 0xdc, 0x87, 0x8d, 0x96, 0x8, 0x3b, 0xe0, 0x58, 0x26, 0xb5, 0x1d, 0x29, 0x21, 0x82, 0xe6, 0x27, 0xf2, 0x78, 0x9a, 0x83, 0x77, 0xc6, 0x75, 0xf0, 0xa, 0x1b, 0x7a, 0x5b, 0xce, 0x9b, 0x7d, 0xa0, 0x5f, 0x9, 0x51, 0xa6, 0xe3, 0xaa, 0xba, 0x8f, 0xd7, 0x2f, 0xf2, 0xd8, 0xf6, 0x2c, 0xd4, 0x97, 0xc7, 0xca, 0xe4, 0x51, 0x6f, 0xa9, 0xfa, 0xf3, 0x2, 0x91, 0xe4, 0x6b, 0x7a, 0x79, 0x83, 0xab, 0x9b, 0xda, 0xcf, 0x41, 0xda, 0x19, 0x51, 0x67, 0xbc, 0x9, 0xf5, 0x31, 0xc2, 0x9e, 0x27, 0xd2, 0x95, 0xf9, 0x93, 0x21, 0x3c, 0xf, 0x11, 0x1b, 0xa4, 0xfb, 0x7e, 0x53, 0x94, 0x15, 0x1, 0xd5, 0x95, 0xfb, 0xe1, 0x6b, 0x29, 0x52, 0x1c, 0x49, 0x3d, 0x8c, 0xff, 0x29, 0xd6, 0xad, 0x2f, 0x3, 0x88, 0xa6, 0x1f, 0xe2, 0x1b, 0xc8, 0x45, 0x75, 0x3b, 0x10, 0x8d, 0x10, 0x79, 0x7c, 0xfe, 0x94, 0xaf, 0x93, 0xa0, 0xc9, 0x67, 0x60, 0x8, 0xdb, 0xe2, 0x6a, 0x68, 0xa5, 0xb2, 0x8a, 0xc8, 0x4c, 0xea, 0x8b, 0x11, 0xa2, 0xf, 0x6, 0x60, 0x4, 0x89, 0xf, 0xcc, 0x58, 0xa1, 0xa5, 0x8e, 0x1e, 0x82, 0xf9, 0x5d, 0xe1, 0x1e, 0x3f, 0xb5, 0x4f, 0x13, 0xc5, 0x13, 0x9, 0x31, 0x67, 0x56, 0xf5, 0x8, 0x38, 0xd1, 0xe0, 0x4f, 0x23, 0x9c, 0x0, 0x55, 0x8f, 0xc5, 0x78, 0x2c, 0x90, 0xda, 0x89, 0xba, 0x89, 0x6f, 0x60, 0x3c, 0x7, 0xd4, 0xcb, 0x3b, 0xc0, 0x84, 0x1, 0xbc, 0x42, 0x9b, 0x10, 0x49, 0x4c, 0x48, 0x20, 0x18, 0xab, 0xc4, 0xfd, 0x22, 0x3d, 0xe5, 0x37, 0x21, 0xca, 0x64, 0x50, 0xc6, 0xe4, 0x7e, 0xf4, 0x70, 0xe2, 0x73, 0x3c, 0x92, 0xf, 0x98, 0xec, 0xff, 0xcb, 0xc7, 0x70, 0xef, 0xbd, 0x86, 0x85, 0x17, 0xcb, 0x8b, 0x36, 0xb1, 0xf8, 0x9, 0xe, 0x93, 0xd3, 0xc3, 0xc0, 0xf6, 0x28, 0x48, 0x27, 0x3f, 0x81, 0x27, 0x38, 0x74, 0x92, 0x8a, 0x5f, 0xc8, 0xe0, 0xe4, 0x7f, 0x66, 0x9f, 0x2, 0x2c, 0x96, 0xf1, 0xb8, 0x9e, 0x21, 0x2f, 0x60, 0xef, 0x5, 0xe, 0xc7, 0x77, 0x78, 0x44, 0x9e, 0x30, 0x19, 0xff, 0xef, 0xbf, 0xdf, 0x8c, 0xa4, 0x7e, 0x31, 0xb0, 0x60, 0xc0, 0xc5, 0x47, 0x1c, 0x55, 0x88, 0xfd, 0xc0, 0x61, 0xb0, 0xb2, 0xf7, 0xfb, 0x5b, 0xcf, 0x77, 0xef, 0x8f, 0x44, 0xb0, 0xce, 0x6e, 0xb8, 0xf1, 0x13, 0xf0, 0xb, 0xd7, 0xdc, 0x83, 0xa9, 0xef, 0x6f, 0xbd, 0x60, 0x66, 0x2c, 0xea, 0xc1, 0xaa, 0xf0, 0xd1, 0x54, 0x19, 0x26, 0xd2, 0xa, 0xc0, 0xf7, 0x26, 0xfd, 0x15, 0x7e, 0x21, 0x3c, 0xd8, 0xb5, 0xe2, 0x43, 0xf4, 0xd5, 0x30, 0x49, 0xb8, 0xf0, 0xd4, 0xf, 0x10, 0xf5, 0x21, 0x3c, 0x58, 0x2e, 0x87, 0x31, 0x9c, 0x8c, 0xfc, 0xe5, 0x1c, 0xfe, 0xfc, 0x58, 0x16, 0xf5, 0x1e, 0xe6, 0x8b, 0x23, 0xd0, 0x96, 0x21, 0x6, 0x3, 0x6d, 0x44, 0x5a, 0xa4, 0x1d, 0xcb, 0x44, 0x1d, 0xc7, 0x6f, 0x30, 0xf8, 0xbe, 0xd3, 0x36, 0xe, 0x79, 0xce, 0xed, 0x6, 0x3f, 0x5f, 0xe7, 0x36, 0x6, 0x3f, 0x10, 0xa0, 0x7c, 0xfa, 0x6f, 0x5d, 0xbe, 0xfd, 0xa2, 0x99, 0xdd, 0x29, 0x7e, 0xcb, 0x85, 0xb3, 0xe3, 0xdf, 0xb6, 0x87, 0xb0, 0x80, 0x62, 0xed, 0x42, 0x33, 0x3f, 0x22, 0xff, 0x61, 0x18, 0x42, 0x2, 0x86, 0xd0, 0xe2, 0x6f, 0xbf, 0x68, 0xae, 0x4a, 0xfd, 0xf3, 0x56, 0xc2, 0x82, 0x9e, 0x94, 0x36, 0x85, 0x99, 0x56, 0xba, 0xc4, 0x51, 0x60, 0x3f, 0x80, 0x2d, 0xfe, 0xfb, 0xde, 0xe6, 0x73, 0xda, 0xdc, 0xfc, 0x7a, 0x3f, 0xdb, 0xb6, 0x60, 0x8f, 0x95, 0x61, 0x9c, 0xda, 0x93, 0x62, 0xe5, 0xde, 0x41, 0xbd, 0x2b, 0x40, 0x17, 0x8c, 0xe2, 0xbe, 0x4a, 0xdd, 0x34, 0xd5, 0x3, 0x76, 0x5b, 0x90, 0x16, 0x38, 0x7e, 0x67, 0xfe, 0x87, 0xb4, 0x8c, 0x63, 0x19, 0xcf, 0x77, 0x48, 0x3b, 0xd7, 0x1d, 0xfc, 0x5c, 0x9d, 0xe7, 0x3b, 0xe0, 0xba, 0xb8, 0xf8, 0xbc, 0xe, 0xa3, 0x7d, 0x89, 0x17, 0xce, 0x5d, 0x79, 0xa7, 0xab, 0xa7, 0x73, 0xa5, 0xf8, 0xbe, 0x96, 0xf3, 0x22, 0x34, 0x51, 0x12, 0x31, 0x23, 0x26, 0x2e, 0x16, 0x4e, 0x65, 0x44, 0x94, 0xc7, 0x94, 0x9f, 0x2d, 0xe2, 0xbb, 0xc6, 0x60, 0x14, 0x2, 0x3a, 0xfd, 0xd8, 0x1f, 0x6f, 0xbc, 0xf0, 0xa4, 0xaf, 0xe5, 0xfc, 0xd, 0x5c, 0x29, 0x3e, 0x1e, 0x71, 0x8b, 0xe3, 0x34, 0xbf, 0xc5, 0x5, 0x2d, 0x3, 0xb1, 0x21, 0x66, 0xc, 0x69, 0xe, 0xff, 0xa6, 0x32, 0x29, 0x5f, 0xe4, 0x59, 0x20, 0x36, 0x78, 0x44, 0x9b, 0x11, 0x62, 0x11, 0xa3, 0xd7, 0xc6, 0x12, 0xf1, 0xb0, 0xd6, 0x21, 0xd2, 0xd5, 0x83, 0x2, 0xd7, 0x7f, 0x90, 0x3b, 0x4f, 0x7e, 0xeb, 0x85, 0x33, 0x60, 0x72, 0xbd, 0x74, 0xaa, 0x69, 0xe2, 0x5c, 0x4c, 0x97, 0x62, 0xd6, 0x1a, 0x20, 0xe3, 0x79, 0x55, 0x44, 0x3d, 0xd7, 0xcc, 0x97, 0xf0, 0x36, 0xb9, 0xd0, 0x0, 0xfc, 0xed, 0x17, 0x4f, 0xb, 0xb7, 0xb4, 0x79, 0xed, 0x6, 0xe6, 0xdc, 0x2, 0x89, 0x2d, 0xa5, 0x1, 0xa5, 0x6b, 0x90, 0xda, 0x38, 0xaf, 0x43, 0xb4, 0xa7, 0xf4, 0x78, 0xad, 0x1, 0x94, 0xef, 0xff, 0x47, 0x7c, 0xad, 0x17, 0xac, 0xef, 0x2a, 0x3, 0x58, 0xbe, 0xfd, 0xe2, 0x85, 0xf1, 0x98, 0x7b, 0xca, 0x63, 0xfd, 0xcb, 0xbd, 0x39, 0x0, 0x3b, 0x8f, 0x45, 0x71, 0xbc, 0x9f, 0x6d, 0xd, 0xd6, 0xae, 0xd7, 0xb6, 0xed, 0xdd, 0x87, 0x6a, 0x6d, 0xdb, 0xb6, 0x8d, 0xc7, 0xba, 0xfd, 0xb4, 0xb6, 0x6d, 0xdb, 0xb6, 0xed, 0xde, 0xee, 0x2f, 0xed, 0x49, 0x5e, 0xa6, 0x93, 0x4f, 0x2f, 0x49, 0x1f, 0x32, 0xf3, 0x9f, 0x73, 0x73, 0x93, 0x1e, 0xfe, 0xef, 0xe9, 0x4d, 0xa6, 0xd5, 0x93, 0x73, 0x9d, 0xcd, 0xa4, 0x5c, 0x37, 0xd7, 0x6b, 0x60, 0x7e, 0xef, 0x37, 0xfc, 0xc0, 0x37, 0x5, 0x6a, 0x3f, 0xf7, 0x23, 0x9, 0xfd, 0x0, 0xbc, 0x2, 0x9e, 0xe6, 0xbd, 0xc5, 0xc3, 0xbe, 0xc6, 0xd6, 0x7, 0x79, 0xbe, 0xbe, 0x9f, 0x78, 0x90, 0x2d, 0x8f, 0x82, 0x67, 0x19, 0xbf, 0xce, 0xbd, 0x5f, 0xf0, 0x99, 0xff, 0x2a, 0x3a, 0x80, 0xb5, 0xd, 0xfb, 0x64, 0xb0, 0x88, 0x4f, 0xf4, 0x32, 0xb7, 0xeb, 0x75, 0x25, 0xed, 0x1c, 0x9f, 0xee, 0xd, 0x44, 0x52, 0xbd, 0xe3, 0xb7, 0x1, 0xe1, 0xfd, 0x1f, 0x1a, 0x0, 0x23, 0xb7, 0x16, 0x67, 0x4b, 0x38, 0x59, 0xd6, 0xe1, 0xab, 0x82, 0x79, 0xa4, 0x35, 0x4c, 0xd7, 0xe4, 0x73, 0x48, 0x81, 0xa1, 0xc3, 0x7c, 0xaf, 0xa1, 0x5f, 0xe6, 0x2c, 0xee, 0x17, 0x2, 0x32, 0xd6, 0x24, 0x30, 0x25, 0xf4, 0x6f, 0x92, 0xf7, 0x31, 0x5, 0x7d, 0x96, 0x56, 0x7a, 0x23, 0x8f, 0x9f, 0x67, 0xfa, 0x9a, 0x3a, 0x23, 0xf8, 0xbf, 0x26, 0x5f, 0x61, 0x4b, 0xfb, 0x23, 0xe9, 0x89, 0x24, 0x76, 0x94, 0xb7, 0x29, 0x39, 0x34, 0x14, 0xcf, 0x8f, 0x61, 0x3c, 0xd, 0x78, 0xb9, 0x67, 0x43, 0x5f, 0x63, 0xc7, 0xc1, 0xbc, 0xab, 0x48, 0x43, 0x8e, 0x7, 0xf9, 0xfc, 0xab, 0x10, 0xe6, 0xfb, 0x5a, 0xb2, 0x55, 0xfc, 0xec, 0xf2, 0x4f, 0x89, 0xaf, 0x96, 0xf1, 0xc8, 0x9c, 0x39, 0x6e, 0xa4, 0xc5, 0xbc, 0x71, 0x4d, 0xf4, 0x49, 0x9e, 0x79, 0x8c, 0xbe, 0x7a, 0xc9, 0xed, 0xae, 0x18, 0xd8, 0xf3, 0xed, 0x3f, 0x92, 0xe, 0x91, 0xd4, 0xd7, 0x2a, 0x4e, 0xeb, 0x81, 0x3, 0x76, 0xab, 0x95, 0x73, 0x43, 0x2, 0x39, 0x9f, 0xcb, 0x9c, 0x71, 0xcd, 0xfa, 0x7c, 0xee, 0x73, 0xaa, 0x66, 0x5e, 0x19, 0xfa, 0x1b, 0xae, 0xff, 0xe, 0x1f, 0x5f, 0xa2, 0x80, 0x19, 0x8a, 0xdd, 0x10, 0x8e, 0xe7, 0x47, 0xd8, 0xdb, 0xef, 0xa4, 0x97, 0xa3, 0x0, 0xa7, 0xb0, 0xe7, 0xb9, 0x1b, 0xbd, 0xef, 0x51, 0x98, 0xbf, 0x88, 0xd9, 0xec, 0x7, 0xe8, 0xca, 0x47, 0x4d, 0xcc, 0xf3, 0x8c, 0x4b, 0xe6, 0x6b, 0xa5, 0xe8, 0x12, 0x42, 0x37, 0xb4, 0x7c, 0x42, 0x2c, 0xbb, 0xf7, 0x6, 0x2, 0x6c, 0xc2, 0x6a, 0x28, 0xf1, 0xa6, 0xcf, 0x8, 0xb6, 0xce, 0x30, 0xdb, 0x55, 0x66, 0x1f, 0x58, 0xa9, 0x3f, 0xb0, 0x62, 0xdf, 0x64, 0x7f, 0x72, 0x4, 0x6f, 0xcd, 0x86, 0xbb, 0xb4, 0xf9, 0x5d, 0x92, 0x47, 0xdf, 0x2c, 0x64, 0x78, 0x9b, 0x3c, 0xfc, 0x29, 0x44, 0x30, 0x16, 0x82, 0xb, 0xb1, 0x1a, 0x64, 0xa7, 0x8b, 0x3d, 0xe2, 0x8f, 0xe4, 0x86, 0xf5, 0x2c, 0x1, 0x62, 0x85, 0x61, 0xbe, 0xa6, 0x64, 0x33, 0xc9, 0xfe, 0xcf, 0x5b, 0x71, 0xaa, 0x45, 0x69, 0x90, 0xb1, 0xeb, 0xc0, 0x8e, 0xd2, 0x65, 0xd7, 0xb8, 0xe5, 0xf, 0x7e, 0x5d, 0xfb, 0x1d, 0xed, 0x7b, 0xff, 0xba, 0x3d, 0x5, 0xc5, 0x8a, 0x83, 0xe9, 0xa, 0x1d, 0xd8, 0xfe, 0x52, 0xf3, 0x43, 0x5b, 0x10, 0xc8, 0x5a, 0x3f, 0x9d, 0x8e, 0xfd, 0x3f, 0x6c, 0xe6, 0x7a, 0x7e, 0x13, 0x18, 0xcb, 0x8d, 0x60, 0x25, 0x1c, 0x42, 0xf0, 0xa, 0x48, 0xe0, 0xad, 0xba, 0xa3, 0xf3, 0x8, 0xbc, 0xd5, 0x12, 0xe6, 0x7b, 0xac, 0xe7, 0xc, 0x3b, 0xa, 0x30, 0xd6, 0x93, 0xdc, 0xf6, 0x33, 0xdf, 0xd9, 0x97, 0xfa, 0x23, 0x99, 0xa1, 0x3d, 0xb3, 0x20, 0xf2, 0x23, 0xf9, 0x11, 0xcb, 0xeb, 0xf8, 0xf2, 0x87, 0x9e, 0xb, 0xa4, 0x4e, 0xd2, 0xda, 0x58, 0xe6, 0x12, 0xab, 0xc0, 0xf2, 0x1e, 0x20, 0x8b, 0xc, 0x5b, 0x2f, 0xd1, 0x85, 0xa7, 0x59, 0xfd, 0xcd, 0x3d, 0x10, 0xcd, 0xe, 0xa, 0x26, 0x66, 0xc, 0xf6, 0x37, 0x77, 0xe, 0x61, 0x3c, 0x34, 0x10, 0xcd, 0xd, 0x72, 0x91, 0x4, 0x79, 0x48, 0x90, 0x3c, 0x87, 0x60, 0x4b, 0xac, 0xbe, 0x4a, 0x61, 0x4, 0x65, 0xce, 0x2b, 0xd2, 0x29, 0x78, 0xbb, 0xf4, 0x29, 0xfd, 0x5c, 0x83, 0xbf, 0xb1, 0xed, 0x3b, 0x1e, 0x49, 0xd7, 0xec, 0x25, 0xef, 0x45, 0x8e, 0xc6, 0xa7, 0xef, 0x29, 0x52, 0x6d, 0xfc, 0x4e, 0xe4, 0xc2, 0x4c, 0xfa, 0x32, 0x5d, 0xe0, 0xd1, 0x4a, 0xd, 0xe2, 0xc5, 0x61, 0xd8, 0x1d, 0x1e, 0x8c, 0x15, 0xc6, 0x53, 0xf0, 0x15, 0x2, 0x91, 0xcc, 0x26, 0x6c, 0x6c, 0x77, 0x86, 0x20, 0xbb, 0x33, 0x7f, 0x12, 0x73, 0x1b, 0xd0, 0x15, 0x87, 0xb8, 0x16, 0x34, 0xc, 0x1b, 0x8a, 0xa1, 0x33, 0x70, 0x8e, 0xd6, 0xd4, 0x66, 0x10, 0x80, 0xb1, 0xf3, 0x40, 0x37, 0x52, 0x27, 0xc4, 0xbf, 0x7c, 0xf, 0x3f, 0x18, 0x4a, 0x14, 0xc7, 0x7b, 0x7a, 0xd1, 0xa1, 0x25, 0x1c, 0x1f, 0x3f, 0xd1, 0xa, 0x25, 0x79, 0x50, 0x86, 0xef, 0xf6, 0xe3, 0x37, 0x24, 0x5d, 0xe0, 0x4f, 0x48, 0xf0, 0x16, 0xdd, 0xef, 0x27, 0xce, 0x4d, 0xd7, 0x6a, 0xc7, 0x6d, 0xcf, 0x43, 0x8a, 0xd, 0x5d, 0xd, 0x3a, 0xb4, 0xfb, 0xac, 0xc1, 0x30, 0xee, 0x70, 0x56, 0xe3, 0x3f, 0x3a, 0x5b, 0x19, 0x97, 0x9d, 0x86, 0x4e, 0x2e, 0xc6, 0x14, 0xbf, 0xf3, 0x26, 0x4f, 0x2f, 0x3d, 0xe8, 0x48, 0xcb, 0xf8, 0x1a, 0xda, 0x5f, 0x17, 0x5f, 0x55, 0xd5, 0x77, 0xa4, 0xfd, 0xf8, 0xd, 0x9, 0x94, 0x9, 0xc6, 0x35, 0x8b, 0x71, 0x89, 0x8e, 0xb0, 0x8f, 0xfb, 0xef, 0x6, 0x76, 0x9f, 0x3d, 0x38, 0x18, 0xcd, 0x36, 0xf2, 0xd8, 0xc5, 0x2e, 0x5c, 0x73, 0xb8, 0x7d, 0xde, 0x30, 0x7, 0x38, 0x97, 0x39, 0xa0, 0x27, 0x11, 0xe6, 0x13, 0x5c, 0x73, 0xf2, 0x4e, 0x4f, 0x2f, 0x3f, 0x2, 0xb1, 0xdc, 0x12, 0x74, 0x28, 0xde, 0x3d, 0x48, 0xf1, 0xcd, 0xf1, 0x21, 0xad, 0xcf, 0xe7, 0x7d, 0x8f, 0xe8, 0x2, 0xe6, 0xeb, 0xd5, 0x39, 0x73, 0xde, 0xb5, 0xb1, 0x7e, 0xce, 0xe2, 0x3c, 0x67, 0x89, 0xe8, 0xad, 0x3, 0x5c, 0xf, 0x3a, 0xb4, 0xdb, 0x8c, 0x61, 0xb4, 0xa5, 0xcf, 0xb4, 0xf6, 0xa3, 0x3b, 0x69, 0x17, 0xe8, 0xd2, 0xf5, 0x28, 0xc6, 0x5a, 0xf1, 0xef, 0x5d, 0x3a, 0x71, 0x87, 0xb, 0xc1, 0xb8, 0xb2, 0x51, 0xf6, 0xd2, 0xa9, 0x1e, 0xd1, 0xf3, 0x21, 0xb2, 0x5e, 0x50, 0xba, 0x4d, 0x5e, 0x7e, 0x7d, 0x10, 0x8c, 0x65, 0x1b, 0xea, 0xd0, 0xfa, 0x72, 0x61, 0x8, 0xf0, 0x35, 0x28, 0xc3, 0x7e, 0xc7, 0x80, 0xbe, 0x12, 0x80, 0xc9, 0xa9, 0x3b, 0xf8, 0xce, 0x1f, 0xe7, 0xe9, 0x43, 0x7, 0x4f, 0x26, 0xd, 0x90, 0xe0, 0x1d, 0xc9, 0x89, 0x42, 0x2a, 0x89, 0xab, 0x2e, 0xc0, 0x5e, 0x5, 0xec, 0x3, 0xdc, 0xff, 0x21, 0x29, 0xef, 0x6, 0x1e, 0xe4, 0xf5, 0xe9, 0xbf, 0xe, 0x13, 0x80, 0xa4, 0x21, 0x9b, 0x93, 0xaf, 0xf0, 0xd4, 0xb1, 0xb9, 0xa7, 0xf, 0x1e, 0x90, 0xe0, 0x78, 0x56, 0xe1, 0xaf, 0x5a, 0x1c, 0x75, 0x2e, 0xbe, 0xe4, 0xf, 0x19, 0x49, 0x5f, 0xec, 0x6e, 0xfb, 0x8f, 0x17, 0xc6, 0x12, 0xe4, 0x4f, 0x55, 0xe3, 0x9d, 0x40, 0xa4, 0x2d, 0x18, 0x3a, 0x7e, 0x66, 0x77, 0x7d, 0x8c, 0xa7, 0x8f, 0x1e, 0x10, 0x77, 0x2c, 0x5, 0x68, 0x97, 0x78, 0x94, 0xc4, 0x26, 0xd2, 0x45, 0x60, 0x43, 0x0, 0x1, 0x52, 0xf7, 0xb2, 0x2f, 0x59, 0xde, 0x95, 0x0, 0xb5, 0x7f, 0xbf, 0xd2, 0x9a, 0x37, 0x80, 0x0, 0xbf, 0x6b, 0xc6, 0x2, 0xcd, 0x4, 0xd9, 0xdc, 0x89, 0xec, 0x3e, 0x8, 0xa0, 0xaa, 0x7, 0xc9, 0xae, 0x3a, 0xcd, 0xcb, 0x96, 0x29, 0x9e, 0x3e, 0x7c, 0x4, 0xe3, 0x85, 0xb5, 0x28, 0xc2, 0xe3, 0x46, 0x61, 0x9a, 0x91, 0xb, 0x9a, 0x13, 0x8b, 0x31, 0xd2, 0x72, 0xde, 0x9c, 0x47, 0x91, 0x7f, 0xb3, 0x88, 0x4e, 0x77, 0x25, 0x38, 0x94, 0xf, 0x44, 0xf9, 0x75, 0xb4, 0xe9, 0xbf, 0xab, 0x6, 0x93, 0x8e, 0x0, 0x5d, 0x4, 0x94, 0xfa, 0x90, 0xbd, 0xc5, 0xe, 0x9e, 0x7e, 0x70, 0xb0, 0x2, 0x8f, 0xaf, 0xc6, 0x94, 0x2c, 0x49, 0x8c, 0x75, 0x1, 0x36, 0x95, 0x26, 0xd9, 0x8, 0xa6, 0x5d, 0xfc, 0x5d, 0x60, 0xf2, 0xb, 0xd8, 0x87, 0xa1, 0x94, 0x16, 0x60, 0x19, 0xd9, 0x3d, 0x44, 0xb4, 0xcf, 0x57, 0x1c, 0x56, 0x9a, 0x1e, 0x88, 0x75, 0x1, 0xab, 0x67, 0x54, 0x7f, 0x20, 0x0, 0x71, 0x4, 0xd9, 0x8c, 0xdd, 0x6b, 0xe4, 0x87, 0x18, 0xe7, 0x92, 0x7, 0xa4, 0x13, 0x90, 0x7c, 0xa2, 0xf, 0x2, 0x4c, 0x5f, 0x7a, 0xe7, 0x96, 0x81, 0xce, 0x7, 0x96, 0x98, 0xbe, 0xb8, 0x5f, 0xa, 0x86, 0xa1, 0x8a, 0x31, 0xbb, 0xa8, 0xea, 0x4a, 0x7f, 0x45, 0xd2, 0x8c, 0x8d, 0x5f, 0x3f, 0x21, 0x41, 0xdc, 0x66, 0x9e, 0xba, 0x91, 0x47, 0x91, 0xd1, 0xcc, 0x5d, 0x81, 0x78, 0x61, 0x61, 0x67, 0x5f, 0x0, 0xed, 0x71, 0xe3, 0xe0, 0x40, 0xac, 0x10, 0xa3, 0x55, 0xff, 0x7, 0x24, 0xb0, 0x74, 0xb9, 0xbb, 0x40, 0x87, 0x21, 0x79, 0x8e, 0xbe, 0x90, 0x77, 0xb, 0x53, 0xfa, 0x13, 0x1, 0x58, 0x2c, 0xeb, 0x10, 0xdf, 0xb7, 0xa0, 0xec, 0x26, 0xc8, 0x9f, 0xd4, 0x21, 0xa5, 0x18, 0x4b, 0x5e, 0x33, 0xaf, 0x53, 0xab, 0xd, 0xdd, 0xd8, 0xe5, 0x5e, 0xd, 0xc3, 0x84, 0x0, 0x69, 0xfb, 0x68, 0xc6, 0x69, 0x58, 0x1b, 0x4a, 0x4c, 0xdf, 0xd5, 0xd3, 0xcf, 0x8e, 0xf0, 0xee, 0x33, 0x27, 0xb2, 0x61, 0x3e, 0x5d, 0x62, 0x55, 0x5a, 0xac, 0xee, 0x14, 0x5e, 0x8a, 0x8f, 0xd4, 0xc0, 0xea, 0x7f, 0x9f, 0xee, 0x73, 0x56, 0x30, 0x3e, 0x7d, 0x39, 0x9b, 0xc, 0x2e, 0xe, 0xf, 0xed, 0x36, 0x73, 0x51, 0x14, 0xad, 0x1f, 0x88, 0x17, 0x23, 0xc1, 0x78, 0xf1, 0x40, 0x56, 0xea, 0x1b, 0x18, 0x2c, 0x1, 0xcd, 0x90, 0x6d, 0x88, 0x9e, 0x4f, 0x43, 0x89, 0x19, 0x6b, 0x7a, 0xfa, 0xe1, 0x11, 0xde, 0x6d, 0xe6, 0xca, 0x5a, 0x8c, 0x8e, 0xe6, 0xcb, 0xac, 0x8b, 0xc2, 0x9b, 0xe6, 0xbe, 0xd, 0xc6, 0xf3, 0xb3, 0x58, 0x4c, 0xdb, 0xfb, 0xe2, 0x33, 0x7, 0x77, 0xa3, 0xe0, 0x33, 0xc6, 0x51, 0xec, 0x55, 0x29, 0xf4, 0xe, 0xb4, 0xaf, 0x4, 0xf2, 0x68, 0x98, 0xd4, 0xc9, 0xe6, 0xec, 0x9d, 0x40, 0x4, 0x63, 0x20, 0x18, 0x35, 0xa0, 0x19, 0x56, 0xda, 0xd8, 0x6, 0xaa, 0xce, 0xc7, 0xa, 0x47, 0x62, 0x7b, 0x74, 0x7f, 0x24, 0x0, 0xb, 0x68, 0x45, 0xf2, 0xf7, 0x83, 0xe4, 0xce, 0x9, 0x28, 0x73, 0xee, 0x91, 0xac, 0xfa, 0xcc, 0xf7, 0xd8, 0xb8, 0x8f, 0x7a, 0x1d, 0x1a, 0xde, 0x7d, 0xd6, 0xc4, 0xee, 0x32, 0x75, 0x1a, 0x2b, 0xfe, 0x30, 0x1e, 0xc3, 0xde, 0x92, 0x62, 0xeb, 0xc0, 0x68, 0x56, 0x87, 0x32, 0xcf, 0xd9, 0x84, 0x2, 0x15, 0x5d, 0x7c, 0xf7, 0xaf, 0xe6, 0xe9, 0xa7, 0x7, 0xc4, 0x5e, 0x96, 0xe2, 0x3c, 0x23, 0x39, 0x53, 0x8e, 0xe4, 0x4d, 0xea, 0x80, 0xde, 0x2f, 0x59, 0xf1, 0x4f, 0x51, 0xf8, 0x13, 0x58, 0xb0, 0xa3, 0x6c, 0xb6, 0xaa, 0x19, 0xff, 0x73, 0x77, 0xce, 0x51, 0x96, 0x2b, 0x69, 0x0, 0x3f, 0xe7, 0xd9, 0xb6, 0xed, 0x77, 0xb5, 0xb6, 0x6d, 0x7b, 0xdb, 0x5a, 0xdb, 0xb6, 0x6d, 0x7b, 0x9b, 0xd7, 0xcd, 0x35, 0x9f, 0xcd, 0xb1, 0x6d, 0xab, 0xbb, 0xb2, 0xbf, 0x4a, 0xbe, 0x4c, 0x32, 0x75, 0x36, 0xe7, 0x4e, 0xcf, 0xad, 0x34, 0xf2, 0xc7, 0xef, 0x54, 0xa5, 0x92, 0xfb, 0xb9, 0xaa, 0x82, 0xc1, 0x5b, 0x49, 0xfe, 0x3a, 0x84, 0x22, 0x98, 0xa, 0x3, 0x1e, 0x25, 0x1c, 0x4d, 0xa8, 0x2f, 0xfc, 0x1e, 0x22, 0x8e, 0x27, 0x89, 0xd6, 0xc7, 0x2c, 0x79, 0x6c, 0x52, 0xb, 0x0, 0xdf, 0x4e, 0x25, 0x41, 0x9f, 0xc2, 0xcf, 0x88, 0x18, 0xfc, 0x5e, 0x30, 0x8e, 0x5, 0xf3, 0x5c, 0x38, 0x6e, 0x24, 0xfd, 0xbd, 0xd7, 0xbd, 0xb1, 0xfb, 0x70, 0x5b, 0x5f, 0xf7, 0x3e, 0x4d, 0x1, 0xf0, 0x1a, 0x36, 0x30, 0x82, 0xbe, 0x92, 0x7e, 0x6c, 0xf0, 0xc2, 0x64, 0xd7, 0x8d, 0x8d, 0x7d, 0x8f, 0x12, 0x33, 0x92, 0x5a, 0x4, 0x4f, 0x94, 0xb8, 0x5a, 0x8b, 0x27, 0xb9, 0xda, 0x74, 0x63, 0x43, 0xdf, 0xa9, 0x16, 0x97, 0xaa, 0xee, 0x9f, 0x22, 0x14, 0xe1, 0x7f, 0x70, 0xa4, 0xd, 0x61, 0x1c, 0xd7, 0x42, 0x8c, 0xac, 0x71, 0x5e, 0xc9, 0xf1, 0xd2, 0x54, 0x63, 0x7f, 0x3a, 0xc9, 0x5, 0xc0, 0xbe, 0x7c, 0x6d, 0x10, 0x57, 0x30, 0xe2, 0x74, 0x70, 0xf1, 0xa2, 0x15, 0x19, 0x1a, 0x96, 0xfe, 0xed, 0x99, 0xe6, 0xfc, 0xb9, 0x16, 0x5f, 0x5a, 0x74, 0xf7, 0x6a, 0x45, 0x8, 0xd6, 0x28, 0x69, 0xa7, 0x80, 0x3f, 0xde, 0x94, 0x6a, 0xea, 0xbf, 0x3a, 0xd1, 0x5, 0xd0, 0x9c, 0xbf, 0x6, 0x5f, 0x27, 0x2c, 0xc7, 0x6e, 0x77, 0xba, 0x69, 0xe0, 0x3c, 0x8b, 0xcb, 0x54, 0x6f, 0x51, 0xaa, 0x4c, 0xf1, 0xb5, 0xcf, 0x89, 0x1b, 0xf4, 0x78, 0x6d, 0x43, 0xcf, 0x40, 0xaa, 0x69, 0xe0, 0xe2, 0x24, 0x17, 0x0, 0x33, 0xf5, 0x4a, 0x7c, 0x5d, 0x2f, 0x3e, 0xdb, 0x62, 0x3c, 0xdd, 0x3c, 0xad, 0x5, 0xd0, 0x1d, 0x3d, 0x2e, 0x44, 0x9f, 0xb, 0x40, 0xef, 0xf7, 0xd8, 0x2, 0xce, 0x4e, 0xf8, 0xa, 0x70, 0x19, 0x2b, 0xec, 0x82, 0x20, 0x6, 0xd2, 0x46, 0xc7, 0x25, 0x32, 0xd6, 0x37, 0xa, 0x29, 0xa0, 0xb0, 0xce, 0xb7, 0x79, 0xa3, 0x52, 0x14, 0xe1, 0xea, 0x0, 0x43, 0x1a, 0xa4, 0x8d, 0xa2, 0x21, 0x7a, 0xac, 0xd6, 0xef, 0x5d, 0x7d, 0xd, 0xc9, 0x2f, 0x80, 0x54, 0x93, 0x14, 0x0, 0x3e, 0xd7, 0x4b, 0x50, 0x0, 0xdd, 0x14, 0x40, 0xc1, 0x5e, 0x1, 0xa4, 0x75, 0x1, 0x78, 0xa, 0x94, 0x4e, 0x9a, 0x1, 0xf4, 0x84, 0xe8, 0x3e, 0x34, 0x8c, 0xdf, 0x6a, 0x7d, 0x14, 0x40, 0x9e, 0x0, 0x5d, 0x9c, 0xec, 0x15, 0xa0, 0x70, 0x25, 0xbe, 0x6e, 0xa8, 0x15, 0x1b, 0xa8, 0xd1, 0x7, 0xe9, 0x23, 0x6f, 0x3c, 0xd5, 0x68, 0x75, 0xb, 0xe8, 0xeb, 0xe5, 0x8d, 0x1c, 0x82, 0x5d, 0x25, 0xa, 0x9c, 0x98, 0x11, 0x5d, 0xbd, 0x37, 0x11, 0xa0, 0x44, 0xdf, 0x4, 0x66, 0x5a, 0x8a, 0xd7, 0xe8, 0x98, 0xe2, 0xaf, 0xcd, 0xd8, 0xed, 0x4e, 0x59, 0xbd, 0x9, 0x6c, 0xea, 0xff, 0xe9, 0x8d, 0x5a, 0x30, 0xb0, 0x2f, 0x7, 0xec, 0x3f, 0xa6, 0x5, 0x12, 0x6, 0x72, 0x2c, 0xd7, 0x4, 0x63, 0x26, 0xe6, 0xb5, 0xe1, 0xeb, 0x9, 0x8, 0xb2, 0xe9, 0x2f, 0xa5, 0x0, 0x52, 0xc9, 0x2e, 0x80, 0xc2, 0xb5, 0x7e, 0xc, 0x25, 0x1e, 0x26, 0x46, 0xbc, 0x8c, 0x6b, 0x18, 0xf3, 0x5a, 0x81, 0x3e, 0xb1, 0xdb, 0x4e, 0xdc, 0xce, 0xb5, 0xf8, 0xac, 0x9a, 0xff, 0x34, 0x8a, 0xb6, 0x84, 0x92, 0x1e, 0x37, 0x52, 0xc9, 0x3d, 0xbb, 0x52, 0xcd, 0x85, 0x47, 0x25, 0x7c, 0x5, 0x78, 0x8a, 0xf8, 0xab, 0xec, 0xc5, 0xae, 0x77, 0x13, 0x5, 0x70, 0xb2, 0xc5, 0x15, 0x60, 0xe0, 0x2d, 0x6c, 0x3, 0xeb, 0x74, 0xb5, 0x71, 0x3f, 0x0, 0xbd, 0xca, 0x6d, 0x41, 0xc6, 0xac, 0xe3, 0xaf, 0x1c, 0x38, 0xf2, 0xd8, 0xc4, 0xee, 0xff, 0x2d, 0xc5, 0xd3, 0x88, 0xed, 0x67, 0x6d, 0xc7, 0x90, 0x89, 0x43, 0xdc, 0xf2, 0x5f, 0xe6, 0x25, 0xd3, 0x61, 0x76, 0xaa, 0xb4, 0xb5, 0x74, 0x1, 0x37, 0x63, 0x9d, 0xbc, 0x5c, 0xf8, 0x7b, 0xa, 0x5, 0x1, 0x18, 0x2e, 0x7d, 0xbe, 0x6f, 0xab, 0xb4, 0xd7, 0x42, 0xbf, 0x10, 0x36, 0xac, 0x5f, 0xda, 0x10, 0xe6, 0xf5, 0x72, 0xd, 0x72, 0x15, 0xc7, 0x9e, 0xdc, 0xe6, 0x62, 0x52, 0xb, 0x80, 0xb8, 0x96, 0xaf, 0x61, 0x7b, 0xbd, 0xfd, 0x46, 0xb7, 0x0, 0x24, 0x5e, 0x12, 0xb3, 0x50, 0x1f, 0xcc, 0x78, 0x1a, 0xc8, 0x78, 0x28, 0x7e, 0xd0, 0xb7, 0x89, 0x7c, 0xfd, 0x83, 0x42, 0xf8, 0x6c, 0xba, 0xa5, 0x74, 0x8a, 0x8d, 0x6a, 0x3d, 0x1e, 0x41, 0x37, 0x30, 0x23, 0x9f, 0x9b, 0x6e, 0x29, 0x34, 0xd2, 0x7e, 0x12, 0xe1, 0xbf, 0xc4, 0x81, 0x3b, 0x30, 0x6e, 0xf, 0x38, 0x3e, 0x28, 0x57, 0xb4, 0x1a, 0xa7, 0xe, 0x94, 0x57, 0x0, 0x85, 0xf, 0x64, 0xdb, 0xaa, 0x27, 0x26, 0xb3, 0x0, 0x4a, 0x39, 0x9d, 0x28, 0x10, 0x9f, 0xeb, 0x23, 0x15, 0x9e, 0x8c, 0xc1, 0xd8, 0x16, 0xa, 0xe1, 0x6f, 0x4c, 0xe0, 0xf7, 0x90, 0xc3, 0x33, 0xac, 0x19, 0x9f, 0x6b, 0x1f, 0x3c, 0x91, 0xa, 0xbe, 0x98, 0x19, 0xfa, 0x38, 0xda, 0x97, 0xd2, 0xb6, 0xa3, 0xe8, 0x7e, 0x14, 0x4e, 0xa0, 0xd8, 0x9a, 0x43, 0x14, 0xd8, 0xca, 0x6c, 0x6b, 0xf9, 0x9, 0x9, 0xdd, 0x2, 0x1e, 0xe5, 0x27, 0xdf, 0x52, 0x11, 0x28, 0x21, 0x98, 0x88, 0x22, 0x9b, 0x8f, 0x6a, 0x1b, 0xd8, 0x6e, 0xca, 0xe8, 0x7c, 0x4d, 0xae, 0xad, 0x7c, 0x64, 0x5c, 0xe, 0x7d, 0x87, 0x22, 0x18, 0x7, 0x9d, 0x38, 0x87, 0xb6, 0x2e, 0x90, 0xa1, 0xc0, 0x61, 0xe5, 0x79, 0x4d, 0xd2, 0x92, 0xcf, 0xaa, 0x76, 0x3a, 0xf1, 0xfa, 0x9c, 0xc4, 0x49, 0x4d, 0x3e, 0x3e, 0x35, 0xe3, 0xab, 0xcc, 0x38, 0x8a, 0xae, 0x25, 0xe8, 0xfd, 0x52, 0xba, 0xa5, 0x7c, 0x83, 0x55, 0x87, 0x72, 0x9d, 0x23, 0x47, 0x30, 0x53, 0xdf, 0x80, 0x61, 0xe3, 0xae, 0xa2, 0xe6, 0x1, 0x5, 0xce, 0xc1, 0x93, 0x17, 0xa4, 0xef, 0xc9, 0x70, 0xc1, 0xe0, 0x6f, 0x66, 0xdb, 0xca, 0x67, 0x27, 0xab, 0x0, 0x2a, 0x4f, 0x26, 0x19, 0xeb, 0x3, 0x3f, 0xf3, 0x66, 0x1c, 0x26, 0x43, 0xf4, 0x6f, 0x49, 0xbe, 0xf4, 0x69, 0xc1, 0xd5, 0x97, 0x7f, 0x88, 0xed, 0xe7, 0x59, 0x71, 0xdc, 0xd4, 0x5c, 0xe2, 0x57, 0x1e, 0xef, 0xa2, 0x15, 0x38, 0x36, 0xc0, 0xe0, 0xb5, 0xc8, 0x7e, 0x41, 0xc2, 0xf6, 0xff, 0x26, 0x99, 0xa1, 0x76, 0xe2, 0x24, 0xa4, 0xa3, 0xcf, 0x29, 0xf0, 0x56, 0x84, 0xe6, 0xfc, 0x70, 0xb6, 0xbd, 0x7a, 0x41, 0x5c, 0x2f, 0x36, 0x56, 0x84, 0x95, 0xd1, 0x1a, 0x14, 0x4, 0xfa, 0x46, 0xb, 0xe6, 0xb8, 0xd2, 0x20, 0x7, 0xc7, 0x8a, 0xdf, 0xc8, 0xb4, 0x55, 0x4f, 0x4e, 0xc4, 0xde, 0xdf, 0x5a, 0x4e, 0xe3, 0xcf, 0x5f, 0xd3, 0x4d, 0x92, 0x34, 0x29, 0x82, 0x38, 0x11, 0x5d, 0x12, 0xcb, 0x42, 0x8f, 0xfc, 0x27, 0x96, 0xd6, 0xbf, 0x6c, 0x1d, 0x96, 0x69, 0x29, 0xfd, 0x80, 0x76, 0xf, 0x38, 0x14, 0x83, 0x15, 0x90, 0x5, 0x85, 0xa5, 0xec, 0x5b, 0xaf, 0x4c, 0xc8, 0xe3, 0xdf, 0x47, 0x24, 0x3e, 0x4a, 0xda, 0x29, 0x1, 0x5d, 0xa2, 0xaf, 0xf4, 0xeb, 0x58, 0x1c, 0xd3, 0xff, 0x3a, 0x55, 0xa6, 0xb5, 0xf2, 0x54, 0x1e, 0x39, 0x76, 0x90, 0x30, 0x14, 0x15, 0x95, 0x28, 0x17, 0x8a, 0x61, 0x6a, 0x18, 0x5c, 0xf4, 0x8d, 0x76, 0xe5, 0x68, 0x79, 0x2c, 0x9b, 0xbf, 0x47, 0xfe, 0x39, 0xb3, 0x3b, 0xf9, 0x95, 0x27, 0xe3, 0xcf, 0xcd, 0x7e, 0x42, 0x82, 0x38, 0xd0, 0xd6, 0x8e, 0x55, 0x8d, 0x31, 0xe3, 0xd8, 0x40, 0x26, 0xd2, 0x2e, 0xee, 0x3f, 0x3e, 0x19, 0xdf, 0xcd, 0x4d, 0xfb, 0xd0, 0x89, 0xbc, 0xbe, 0xdd, 0x24, 0x5, 0xe0, 0x48, 0x5b, 0x17, 0xfb, 0x65, 0xb5, 0x14, 0xb7, 0x13, 0xc0, 0x8f, 0xcc, 0xd6, 0xe4, 0xe7, 0x3a, 0x86, 0x4e, 0x66, 0xf6, 0xff, 0x42, 0xfc, 0x91, 0xe4, 0x4f, 0x9, 0xca, 0x9f, 0x44, 0xc4, 0x70, 0x8c, 0x18, 0xa6, 0xe2, 0x5e, 0xe2, 0x46, 0x51, 0xb4, 0x17, 0xf4, 0xac, 0xb5, 0x81, 0xd2, 0xa4, 0x5d, 0x67, 0x4a, 0xf, 0xe2, 0xc0, 0x8b, 0x67, 0xe9, 0xa3, 0xdf, 0xc7, 0xf0, 0x61, 0x47, 0xfd, 0x71, 0x29, 0x4e, 0xfe, 0x3a, 0x89, 0x1f, 0xf7, 0x1f, 0x5f, 0x9d, 0x8a, 0x4a, 0xbf, 0x6, 0x65, 0xab, 0x33, 0x35, 0x1c, 0xcd, 0xa, 0xc6, 0x58, 0xe4, 0x31, 0xc9, 0x9f, 0xf0, 0xb6, 0x82, 0xf2, 0xf0, 0x23, 0x3a, 0x87, 0x4f, 0x9a, 0x55, 0xc9, 0x6f, 0x1f, 0x6c, 0xc0, 0xfe, 0x85, 0xe2, 0x8b, 0x3b, 0x23, 0xa3, 0x7c, 0xae, 0x35, 0x6e, 0x9e, 0x97, 0x36, 0x1a, 0x3f, 0xf, 0x5e, 0x1, 0x7c, 0x32, 0x76, 0x67, 0x1f, 0xd9, 0x35, 0x76, 0x34, 0x2f, 0x6f, 0x96, 0x7b, 0xc6, 0x95, 0xad, 0x40, 0xf0, 0x94, 0xb4, 0x1e, 0x6d, 0x95, 0xa1, 0x59, 0xb4, 0xf4, 0x3f, 0x86, 0x7d, 0xf7, 0x56, 0x89, 0x87, 0x2, 0x67, 0xa, 0x51, 0x1a, 0x1d, 0x33, 0x26, 0xce, 0x5c, 0x9e, 0xa4, 0x5e, 0x11, 0xab, 0xb3, 0x8f, 0xe8, 0xfa, 0xd3, 0x11, 0x54, 0x7b, 0x27, 0xca, 0x36, 0x83, 0x93, 0x6d, 0xb3, 0x87, 0xe, 0x20, 0x2d, 0x33, 0x47, 0xfa, 0xed, 0xd5, 0xea, 0xcc, 0x4f, 0xfe, 0x70, 0x8e, 0x2d, 0xeb, 0x1e, 0xdf, 0x76, 0x90, 0xb6, 0xae, 0x38, 0x44, 0xca, 0x89, 0x1a, 0xf7, 0x72, 0x31, 0xf8, 0xb9, 0x78, 0x9d, 0xed, 0x1a, 0x3b, 0x82, 0x6a, 0xff, 0x30, 0xca, 0xf6, 0x7a, 0xa, 0x2b, 0x4a, 0x5a, 0x6b, 0x84, 0xe5, 0xa6, 0x5b, 0xd0, 0xd3, 0x56, 0x2d, 0xcc, 0xdc, 0x65, 0x7f, 0x38, 0x4b, 0x91, 0xce, 0xd1, 0xb6, 0x82, 0x12, 0x1f, 0x94, 0xa5, 0x38, 0x28, 0x5f, 0xae, 0x81, 0x13, 0xc1, 0x38, 0xb9, 0x69, 0x8f, 0xd3, 0xd9, 0xa3, 0x98, 0xf9, 0x5f, 0xa2, 0xda, 0xc7, 0x41, 0x12, 0x55, 0x55, 0xf4, 0x75, 0x2b, 0x84, 0xfb, 0xe1, 0x31, 0xf3, 0x9a, 0xe8, 0xeb, 0x90, 0x17, 0xc8, 0xe5, 0x58, 0xf4, 0xdd, 0xc4, 0xd3, 0xc7, 0x69, 0x33, 0x6b, 0xe6, 0x8f, 0x3c, 0x83, 0xfd, 0x76, 0x19, 0xb6, 0x19, 0x13, 0xa1, 0xaa, 0x20, 0xc2, 0x3f, 0x21, 0x7a, 0x4c, 0xc0, 0x6f, 0x66, 0x39, 0x68, 0xff, 0x77, 0x72, 0x7c, 0x3f, 0x13, 0x61, 0x5, 0x13, 0x62, 0x27, 0x5b, 0xaf, 0x1e, 0x73, 0xf1, 0xfa, 0x65, 0xb7, 0xcf, 0xf9, 0x3b, 0xb2, 0x1d, 0xc3, 0x4f, 0x8f, 0x69, 0xd9, 0x1f, 0x3b, 0x8e, 0x4, 0x7c, 0x27, 0xdd, 0x5a, 0x99, 0xc8, 0x60, 0x1c, 0x55, 0xef, 0x3a, 0x2a, 0xfd, 0x43, 0xa3, 0xcd, 0xe8, 0xb, 0xa6, 0x5c, 0xfa, 0x8a, 0x40, 0x43, 0x65, 0x43, 0xa6, 0x7d, 0x68, 0x46, 0x7c, 0x35, 0xcc, 0xb4, 0xd, 0x7e, 0x8a, 0x80, 0x6f, 0xd4, 0x76, 0x82, 0x97, 0x74, 0xb1, 0xb5, 0xb6, 0xcf, 0xb5, 0x10, 0x59, 0x81, 0xec, 0x7f, 0x7b, 0xdf, 0x62, 0x46, 0x8f, 0xce, 0x76, 0x78, 0xf0, 0x5d, 0xe6, 0x1c, 0xa, 0xf0, 0x6, 0xe2, 0xf1, 0x64, 0x92, 0xfe, 0x12, 0x72, 0xf3, 0x56, 0xda, 0xc7, 0x30, 0x76, 0x78, 0xc, 0xc9, 0x1f, 0x3d, 0x81, 0x7d, 0xee, 0x93, 0xcc, 0xfe, 0xa0, 0xb2, 0xe9, 0x83, 0x73, 0xf0, 0x54, 0xa5, 0x9d, 0x14, 0x4a, 0x74, 0x86, 0x67, 0xd6, 0x16, 0x9c, 0xed, 0x79, 0xf4, 0xbb, 0x6e, 0x8a, 0x7e, 0xcd, 0x19, 0xef, 0xfd, 0xcf, 0xd1, 0xe8, 0x9f, 0xeb, 0xcd, 0xca, 0xfd, 0x3e, 0x29, 0xeb, 0x31, 0xc1, 0x57, 0xdd, 0xb2, 0xa4, 0xdf, 0x49, 0xe2, 0x4f, 0xfd, 0x7f, 0xb6, 0xe8, 0x18, 0x60, 0xc7, 0x61, 0xe4, 0xe7, 0x70, 0xf2, 0x73, 0x24, 0xd7, 0x1f, 0x66, 0xdd, 0x61, 0xaa, 0xea, 0x78, 0xe8, 0xe4, 0xe6, 0x62, 0x42, 0x3b, 0x99, 0xc3, 0x49, 0x8d, 0xf4, 0xe3, 0x45, 0x2, 0x21, 0x7d, 0x25, 0x38, 0xb0, 0x87, 0xc0, 0x2c, 0xcd, 0x52, 0x94, 0xa9, 0x96, 0xca, 0x91, 0x53, 0x91, 0x78, 0x66, 0x1a, 0x1, 0x1e, 0x2a, 0xa2, 0x77, 0x65, 0x78, 0xb5, 0xf2, 0x6d, 0xb2, 0x85, 0x11, 0xdb, 0x7d, 0xe8, 0xfc, 0xcd, 0x74, 0xef, 0x73, 0x4f, 0xcf, 0xba, 0xc6, 0xc, 0xb9, 0x15, 0xae, 0xdb, 0x30, 0x4, 0xc4, 0x3c, 0x6, 0xa3, 0xf, 0x91, 0xbf, 0x33, 0xae, 0x8d, 0xb8, 0x46, 0x85, 0xce, 0x2b, 0x19, 0xd3, 0xf6, 0x6c, 0xa5, 0xf2, 0xef, 0x63, 0x39, 0xfc, 0x44, 0xae, 0x73, 0xec, 0xc4, 0x98, 0xb6, 0xbe, 0x2c, 0x85, 0xf6, 0x1b, 0x96, 0xfc, 0x85, 0x2c, 0xf9, 0x7b, 0xfd, 0x19, 0xea, 0xdb, 0x22, 0x31, 0x89, 0xf0, 0x25, 0x2a, 0x46, 0x35, 0xe3, 0x25, 0x2b, 0xc9, 0xd0, 0xdf, 0x1f, 0xf5, 0xb6, 0xbf, 0x1e, 0x3d, 0xbd, 0x77, 0xb9, 0x1d, 0x23, 0xd7, 0x63, 0xc8, 0x9d, 0xbe, 0x71, 0xfe, 0xb2, 0x2c, 0xc7, 0x53, 0xc9, 0x1, 0x3a, 0x7d, 0x1b, 0x24, 0x50, 0x9b, 0x28, 0x84, 0xb9, 0x24, 0xea, 0x57, 0xd8, 0xfb, 0x4a, 0xf6, 0xc8, 0x93, 0xeb, 0xf4, 0x39, 0x45, 0xe1, 0x7f, 0x94, 0xc2, 0xfa, 0x1b, 0xb2, 0x17, 0xc1, 0x2e, 0x3f, 0xf1, 0xa2, 0xd7, 0xd7, 0x6d, 0xdd, 0xc7, 0xc0, 0xaf, 0xa1, 0xc5, 0xe8, 0x7f, 0xf3, 0xcc, 0xb8, 0xdb, 0xed, 0x1c, 0x7d, 0x3e, 0x6, 0x39, 0x30, 0x41, 0xa0, 0x9d, 0x69, 0x46, 0xb9, 0x48, 0x5f, 0xec, 0xd2, 0x7d, 0xdd, 0xee, 0xa6, 0x8, 0x16, 0xc3, 0xed, 0x30, 0x44, 0x22, 0xbf, 0xc9, 0xc, 0x7e, 0x1d, 0xab, 0x43, 0x9a, 0xfe, 0x85, 0xf4, 0x4f, 0xcd, 0x75, 0xfd, 0xe9, 0x44, 0x38, 0xee, 0x91, 0x6f, 0xfd, 0xcb, 0x89, 0x8c, 0x9d, 0x41, 0xb1, 0x5c, 0xc4, 0xf8, 0xe3, 0xd8, 0x47, 0xdf, 0xc3, 0xf1, 0x0, 0xbf, 0xbb, 0x9, 0xee, 0x67, 0xc6, 0xaf, 0xf7, 0x65, 0x83, 0xa9, 0x57, 0x8f, 0x49, 0xbf, 0x7e, 0x4c, 0x79, 0xf4, 0x27, 0xb0, 0xe5, 0x7f, 0xed, 0x9c, 0x3, 0x90, 0x2c, 0x49, 0x13, 0x80, 0xfb, 0xff, 0xcf, 0xb6, 0x6d, 0x6b, 0x7a, 0xe6, 0x6c, 0xdb, 0xb6, 0x6f, 0x7d, 0xb6, 0x6d, 0xdb, 0x76, 0xe0, 0x7c, 0xb7, 0xec, 0x99, 0xd5, 0xd9, 0xb6, 0x6d, 0x63, 0xdf, 0x54, 0xdd, 0x57, 0xbd, 0x39, 0x13, 0xf5, 0x2a, 0x5e, 0x5f, 0xaf, 0x63, 0xd0, 0x19, 0xf1, 0x45, 0x66, 0x55, 0x67, 0xd6, 0x54, 0x67, 0x66, 0xf5, 0xcc, 0xf2, 0x8a, 0xb5, 0x8f, 0x7b, 0xf9, 0x7f, 0x5e, 0x29, 0x8, 0x49, 0x9a, 0x8d, 0xd, 0x75, 0x93, 0x18, 0x4d, 0x57, 0x2, 0x9b, 0x24, 0x19, 0x46, 0x8f, 0xd, 0x4f, 0x58, 0xc8, 0x9c, 0xec, 0xc1, 0xb5, 0xd1, 0x36, 0xbf, 0x11, 0xf3, 0x1, 0x7b, 0x7f, 0x9e, 0x2f, 0x61, 0x7b, 0xfd, 0x9a, 0x27, 0x72, 0x7e, 0x4d, 0x73, 0x0, 0x1d, 0x8c, 0x3, 0x4e, 0x79, 0x27, 0xf4, 0x72, 0xfd, 0x65, 0x7c, 0xbf, 0x2, 0xed, 0xc2, 0x9a, 0xb2, 0xee, 0xf0, 0xef, 0x1, 0xed, 0xe2, 0xee, 0x3d, 0xf, 0x9a, 0x3d, 0x35, 0xaf, 0x50, 0xd3, 0x3c, 0xaf, 0x57, 0x2a, 0xc2, 0x9, 0x9a, 0x88, 0x6f, 0x0, 0xad, 0x27, 0x49, 0x51, 0x6, 0x29, 0x48, 0x29, 0x61, 0xf6, 0x55, 0xb4, 0xad, 0xf9, 0x62, 0x31, 0xa3, 0xe6, 0x42, 0x6d, 0xc7, 0x5a, 0xf1, 0x63, 0x75, 0xaf, 0x92, 0x57, 0x63, 0x77, 0xfa, 0x75, 0xad, 0xa5, 0xf7, 0xb, 0xb2, 0x3c, 0x5, 0x26, 0x81, 0x73, 0xe9, 0x4e, 0x1d, 0x52, 0xd3, 0xac, 0x38, 0x49, 0x46, 0x6b, 0xdf, 0x82, 0x31, 0xd8, 0x63, 0x57, 0x8b, 0x1d, 0xed, 0x67, 0x13, 0xbd, 0x66, 0xc4, 0x7a, 0xae, 0x2f, 0x7b, 0xb5, 0xed, 0x22, 0xe2, 0x8f, 0x4d, 0xb1, 0x5d, 0x3b, 0x6a, 0xad, 0x8, 0x7c, 0x8b, 0xb8, 0x78, 0xd7, 0x76, 0xf7, 0xc6, 0x41, 0x3b, 0xdc, 0x2b, 0x55, 0xf1, 0xeb, 0xda, 0xe6, 0xe0, 0xfd, 0xf2, 0x2d, 0xbf, 0xb6, 0x7f, 0xd3, 0xe8, 0xf0, 0xb4, 0x98, 0xb1, 0x20, 0x36, 0x14, 0x1b, 0x84, 0x64, 0xcb, 0x1c, 0x36, 0x73, 0x85, 0x58, 0x87, 0x1a, 0xc7, 0x76, 0xfd, 0xa2, 0xfd, 0x21, 0xde, 0xdf, 0xf2, 0x8b, 0x88, 0x8f, 0xb0, 0x23, 0xe7, 0x6c, 0x86, 0xb5, 0x17, 0xb0, 0x1b, 0xa0, 0xf5, 0x68, 0xaf, 0x94, 0xc5, 0xaf, 0x6d, 0xdb, 0x9a, 0xee, 0xcd, 0x83, 0xa6, 0x19, 0x14, 0x68, 0x6c, 0x25, 0xe3, 0xe2, 0x9c, 0xcc, 0x17, 0x35, 0x28, 0xeb, 0x7a, 0xc1, 0x4e, 0x0, 0x2b, 0x87, 0xe8, 0x96, 0xe7, 0x68, 0x82, 0x75, 0xbc, 0x52, 0x96, 0x15, 0x6a, 0x5a, 0xae, 0x5e, 0x81, 0x6e, 0x75, 0xb, 0x2b, 0x63, 0x80, 0xda, 0x96, 0xf7, 0x79, 0x62, 0xdc, 0x2, 0xa7, 0x63, 0x37, 0x33, 0x37, 0xc1, 0xe6, 0x18, 0x3e, 0xad, 0x15, 0x51, 0x7c, 0x3b, 0x87, 0x34, 0xc0, 0xcd, 0x2b, 0x36, 0x6, 0x93, 0x78, 0xa5, 0x2a, 0xa9, 0xba, 0xf6, 0x29, 0xd9, 0x64, 0x1b, 0xdd, 0x3a, 0xe, 0xb4, 0xc5, 0x8f, 0x34, 0x47, 0x3b, 0xfa, 0x4a, 0xa, 0xbf, 0x1b, 0xdf, 0xc4, 0x98, 0x3c, 0xf4, 0xaf, 0x6d, 0x5b, 0x6, 0xff, 0x5e, 0x8a, 0x55, 0xf4, 0x35, 0x36, 0x28, 0x40, 0x27, 0x80, 0x22, 0x2f, 0xa, 0x6d, 0xe, 0xcf, 0x47, 0x3c, 0x69, 0xf7, 0xf0, 0x4a, 0x59, 0xd2, 0xf5, 0x1d, 0x4b, 0x52, 0xe4, 0x4f, 0x29, 0xec, 0x57, 0x14, 0xbd, 0x83, 0x8d, 0x3f, 0xc8, 0xd7, 0xd6, 0x27, 0x31, 0x3f, 0x47, 0x84, 0xff, 0xbc, 0xf8, 0xe6, 0xf0, 0xd5, 0x7c, 0xca, 0xd, 0xe1, 0x46, 0x8d, 0x56, 0xa0, 0xa3, 0x69, 0xb3, 0xec, 0x61, 0xfb, 0x45, 0xf8, 0xb6, 0xb9, 0xf6, 0x28, 0xd2, 0x16, 0xf7, 0x1a, 0xca, 0xe4, 0x65, 0x85, 0x9a, 0xd6, 0x47, 0x39, 0x68, 0x53, 0x94, 0x7a, 0x13, 0x9c, 0xe5, 0xd7, 0xb5, 0xd7, 0xfb, 0xf5, 0x1d, 0x53, 0xf, 0xec, 0x43, 0x64, 0xc7, 0x64, 0x74, 0x76, 0x6f, 0x4a, 0xba, 0x5e, 0x92, 0xa1, 0x52, 0x62, 0xa7, 0x1d, 0x7c, 0x87, 0xb4, 0xad, 0x23, 0x89, 0x8f, 0x77, 0x7d, 0x5c, 0xff, 0x74, 0xd4, 0x5e, 0x22, 0xec, 0x91, 0xc6, 0xe4, 0x3, 0xbe, 0x25, 0xb7, 0x47, 0x7a, 0x15, 0x25, 0xf2, 0x6b, 0xe5, 0xdc, 0x5c, 0x2b, 0x9d, 0xfe, 0xb, 0xd0, 0x8, 0x61, 0x22, 0x55, 0x7f, 0x42, 0xdb, 0x1d, 0xda, 0x22, 0xc6, 0x68, 0x21, 0xca, 0xd7, 0xf5, 0x89, 0x5f, 0xc7, 0x9d, 0x8b, 0x7e, 0xd, 0x77, 0x7e, 0xf0, 0x7b, 0x8a, 0x88, 0x91, 0x27, 0x3, 0x5a, 0xc9, 0x1, 0x9, 0x56, 0xa8, 0x6d, 0x9b, 0xcc, 0xab, 0x44, 0x49, 0xd7, 0x7, 0x17, 0xf3, 0xd9, 0xe0, 0xf3, 0xe2, 0x69, 0xaa, 0x6f, 0x57, 0xa0, 0xab, 0x1d, 0x72, 0xa1, 0xd0, 0xa, 0xad, 0xe1, 0x47, 0xde, 0x6, 0x4e, 0xf3, 0x2a, 0x55, 0x52, 0x75, 0x1d, 0x3b, 0xd2, 0x4, 0xaf, 0xf1, 0xa8, 0xcb, 0xf3, 0x76, 0xa2, 0xcb, 0x1d, 0xee, 0x43, 0xc5, 0xce, 0xc5, 0xc7, 0x2a, 0x6c, 0x2d, 0x7c, 0x4a, 0x3, 0x1c, 0xe6, 0x55, 0xb2, 0xf8, 0x75, 0xc1, 0xec, 0x7c, 0x86, 0x78, 0x51, 0x6e, 0x1e, 0x2, 0xd1, 0x36, 0x81, 0x35, 0x3f, 0x78, 0xe2, 0xd7, 0x8, 0xe2, 0x63, 0x6d, 0x1b, 0xdc, 0x79, 0x50, 0x85, 0x42, 0x82, 0xf6, 0x43, 0x3b, 0xf4, 0x51, 0xc0, 0xb8, 0x5d, 0x45, 0xad, 0x6b, 0x62, 0xb0, 0x8d, 0xbf, 0x2, 0x6d, 0x48, 0xd5, 0xb6, 0x7f, 0x86, 0x6e, 0xf4, 0x2a, 0x5d, 0x32, 0xd, 0xd9, 0x9a, 0x74, 0x43, 0xf0, 0x85, 0x49, 0x18, 0x5a, 0x81, 0x2e, 0x17, 0xd8, 0xb3, 0xbd, 0x5f, 0x55, 0x98, 0x83, 0x71, 0xf0, 0x97, 0xc1, 0xf2, 0x53, 0x72, 0x8f, 0x2e, 0xca, 0x5e, 0x8f, 0x13, 0x6f, 0xf4, 0x97, 0xe4, 0xa5, 0xce, 0xab, 0x6, 0xf1, 0xeb, 0x83, 0xde, 0x74, 0x43, 0x56, 0xa3, 0x35, 0xda, 0x5, 0x2, 0x21, 0x1b, 0x47, 0x7c, 0xbc, 0xd8, 0xf1, 0xd7, 0x5d, 0xb2, 0x36, 0x4a, 0xd0, 0xb2, 0xef, 0xb0, 0xb0, 0x42, 0x61, 0x3e, 0xc8, 0x34, 0xe6, 0x56, 0x46, 0xef, 0xce, 0x29, 0x2e, 0x36, 0x8a, 0x1b, 0x67, 0x8f, 0xa5, 0x71, 0xcc, 0xfc, 0xab, 0xb0, 0xb9, 0x57, 0x2d, 0x42, 0xa7, 0xbf, 0x1, 0xe1, 0xa3, 0xd2, 0xe8, 0x92, 0xa4, 0x71, 0xbc, 0xb1, 0x12, 0x74, 0x61, 0xdf, 0xf2, 0xa8, 0x37, 0xcd, 0x92, 0xa3, 0x78, 0x1b, 0x52, 0xd0, 0x49, 0x3c, 0x11, 0x1a, 0x61, 0x43, 0xae, 0xfd, 0xa, 0xda, 0x8d, 0xb3, 0xc6, 0xf9, 0xfe, 0xf8, 0x6c, 0x2b, 0xfe, 0x19, 0xaf, 0x5a, 0xc4, 0xaf, 0xcf, 0x2e, 0x44, 0xc2, 0xde, 0x4f, 0x87, 0x49, 0xce, 0x29, 0xd0, 0x0, 0xe1, 0xd8, 0x21, 0x5b, 0x20, 0x62, 0xce, 0xbd, 0x1e, 0x45, 0xd6, 0xd6, 0x11, 0x36, 0x38, 0x31, 0xec, 0x51, 0x59, 0xb1, 0x8a, 0x62, 0xcb, 0x7c, 0x0, 0xd9, 0x7, 0x33, 0x8d, 0x9d, 0xab, 0xa5, 0x1b, 0x73, 0x53, 0xa4, 0x9b, 0x7a, 0xfe, 0xe7, 0x39, 0x92, 0x6e, 0xc8, 0x2d, 0xcc, 0x7d, 0x3e, 0x81, 0x9f, 0xac, 0x93, 0x1b, 0x6f, 0x2d, 0x59, 0xff, 0x46, 0xbf, 0x21, 0xbb, 0xa0, 0x57, 0x4d, 0xc2, 0xd, 0x6f, 0xc6, 0x8d, 0x7f, 0x26, 0xd, 0x60, 0x35, 0x41, 0x3c, 0xc4, 0x28, 0xdb, 0x6, 0xfb, 0x9a, 0xd1, 0x23, 0x8e, 0xfd, 0xf8, 0x67, 0xfc, 0x1, 0x45, 0x3f, 0x97, 0xa2, 0x2f, 0xa, 0x53, 0x31, 0xfe, 0xcf, 0xdf, 0xc8, 0xc5, 0x67, 0x16, 0x1a, 0xe1, 0x60, 0xeb, 0xad, 0x4e, 0x89, 0x86, 0xdc, 0xe1, 0xe9, 0xc6, 0xce, 0x99, 0xbc, 0x6a, 0x13, 0x1a, 0xe0, 0x4c, 0x6e, 0xfe, 0x67, 0x93, 0x5c, 0xb4, 0x26, 0xa1, 0x83, 0x82, 0x98, 0x3c, 0xd8, 0x63, 0x83, 0x72, 0xfc, 0x54, 0x41, 0x8b, 0xaf, 0x3b, 0x1f, 0x8b, 0xb3, 0x7e, 0x1f, 0xc5, 0x5a, 0x3c, 0xd3, 0xd4, 0x35, 0x27, 0x7a, 0x1a, 0x6f, 0x10, 0x42, 0xcc, 0x14, 0xc4, 0x2c, 0xc4, 0x1a, 0x9f, 0x81, 0xe6, 0x9, 0xf8, 0x8d, 0xdf, 0x90, 0x5b, 0xdb, 0x97, 0xb7, 0x8c, 0xaa, 0x13, 0x6e, 0xbe, 0x9b, 0x93, 0x91, 0xcf, 0x34, 0x75, 0x6a, 0x50, 0xa2, 0xe3, 0x50, 0x5, 0x88, 0xd5, 0x24, 0xf4, 0x26, 0xd8, 0x1f, 0xee, 0x66, 0xfc, 0x17, 0xe8, 0x28, 0xec, 0x78, 0x6b, 0x1c, 0xb, 0xbe, 0xca, 0xb2, 0xff, 0xf1, 0x86, 0x29, 0x34, 0xc2, 0x42, 0xec, 0x77, 0x7, 0x58, 0xd2, 0xab, 0x66, 0x21, 0x1, 0x5f, 0x83, 0x26, 0x21, 0xa, 0xb4, 0xd8, 0x91, 0x70, 0xdd, 0x1d, 0xbf, 0x97, 0x6e, 0xec, 0x4a, 0xc1, 0xc4, 0x8c, 0xe7, 0xce, 0x34, 0x75, 0xa7, 0x60, 0x4d, 0xc6, 0xeb, 0xc3, 0x26, 0xb0, 0x23, 0x1c, 0x83, 0xdf, 0xb5, 0x70, 0x3f, 0x3c, 0xb, 0xda, 0x7e, 0xcd, 0x81, 0x42, 0x8c, 0x2, 0x4d, 0xd3, 0xfe, 0x63, 0x5e, 0xcf, 0x1b, 0xa6, 0xac, 0x74, 0x48, 0x2f, 0x6b, 0x54, 0xb9, 0x64, 0x1a, 0xbb, 0x2e, 0xee, 0x2f, 0x8, 0x49, 0x86, 0x15, 0xad, 0xa2, 0x60, 0xbb, 0x28, 0x8, 0xfd, 0xf0, 0x57, 0x60, 0xfc, 0xb6, 0x49, 0xd5, 0x65, 0x23, 0xdf, 0x7b, 0xcd, 0x7, 0x32, 0x7c, 0xa6, 0x85, 0x39, 0x61, 0x3e, 0xe0, 0x4b, 0xb3, 0xce, 0x3e, 0x7b, 0x2d, 0x74, 0x2c, 0xe2, 0xab, 0x88, 0xd5, 0xd0, 0x37, 0x12, 0xd, 0x90, 0x8, 0x42, 0x22, 0xe7, 0xe2, 0xc4, 0x6e, 0x4b, 0x13, 0x3c, 0x16, 0x16, 0xfd, 0xe0, 0xee, 0x2, 0xca, 0x1a, 0x2b, 0x6b, 0xac, 0xc, 0x72, 0x8a, 0xcf, 0x26, 0x7e, 0xf2, 0x41, 0xbe, 0xde, 0xc4, 0x14, 0xb2, 0x93, 0xb5, 0xf2, 0xb2, 0x5e, 0x34, 0x4d, 0xe0, 0xec, 0x47, 0xf8, 0x91, 0x3d, 0x27, 0xd, 0x30, 0xc2, 0x8d, 0xb0, 0x14, 0x49, 0xdd, 0x1b, 0x9e, 0x0, 0xd, 0x24, 0xbd, 0xc7, 0xa0, 0x84, 0xd0, 0x66, 0xde, 0xa0, 0xe1, 0x29, 0x62, 0x66, 0xf6, 0x6, 0x29, 0xac, 0x31, 0x9, 0xd4, 0x12, 0x3b, 0x4e, 0x5e, 0x43, 0xd6, 0x8e, 0xc7, 0xf8, 0x13, 0x97, 0x47, 0xbf, 0x4, 0x13, 0x79, 0xa3, 0x22, 0x49, 0x23, 0x2c, 0xb, 0xfb, 0x92, 0xe0, 0xdb, 0xe0, 0x67, 0xd0, 0x16, 0x4a, 0x8a, 0xf0, 0x3d, 0xac, 0x31, 0xf4, 0xf, 0x60, 0x3d, 0x73, 0x11, 0xaf, 0xad, 0x6, 0x80, 0x81, 0x35, 0x0, 0xfc, 0x43, 0xec, 0x9d, 0xf0, 0x7f, 0x6f, 0xf4, 0x24, 0x91, 0x74, 0x53, 0xf7, 0x1c, 0xb0, 0x3f, 0x9c, 0x43, 0xc1, 0x3a, 0x40, 0x67, 0x28, 0x2, 0xfa, 0x77, 0xe6, 0xf6, 0x1e, 0x81, 0xf5, 0x3b, 0x56, 0x3c, 0xb8, 0xb7, 0xf, 0x58, 0x93, 0x2, 0x1f, 0xd2, 0x4b, 0x91, 0x5, 0x6c, 0x1b, 0xae, 0x2b, 0x33, 0x2f, 0xfc, 0x49, 0xec, 0xd1, 0x90, 0x34, 0xc0, 0x58, 0x9, 0x45, 0xf0, 0xe1, 0x42, 0xb8, 0x1e, 0x4e, 0x1e, 0x89, 0x5f, 0x48, 0xa1, 0x80, 0x1b, 0xd2, 0x50, 0x7f, 0x80, 0x29, 0xb2, 0x12, 0xb4, 0x8c, 0x6d, 0x94, 0xc1, 0xcc, 0xb, 0x79, 0xd8, 0x4c, 0xfe, 0x34, 0xbd, 0x5c, 0x25, 0x11, 0x9a, 0xc0, 0x7c, 0xcb, 0xf6, 0x33, 0xb4, 0xa6, 0x98, 0xe3, 0xc1, 0xdc, 0x4, 0xc1, 0xff, 0x53, 0x74, 0x2b, 0x3e, 0x73, 0x7b, 0xe5, 0x2f, 0x89, 0xf0, 0x68, 0x3f, 0x8b, 0xd3, 0xdd, 0x27, 0x8f, 0x7f, 0x85, 0xfe, 0x1b, 0x7e, 0xc6, 0xfe, 0x1a, 0xfd, 0x21, 0xbc, 0xcc, 0x69, 0xf, 0xd0, 0xf, 0x33, 0x77, 0x2b, 0xf6, 0xfe, 0x2b, 0x1d, 0xfa, 0xe4, 0xd2, 0x5e, 0x65, 0x48, 0x22, 0x9c, 0xe4, 0xa9, 0x38, 0xd1, 0x77, 0xc2, 0x43, 0xd8, 0x77, 0xc0, 0x35, 0x70, 0x16, 0xff, 0x60, 0xf9, 0x70, 0xd8, 0x3, 0x7b, 0xd, 0xae, 0xcd, 0xe2, 0x95, 0xbd, 0x24, 0x92, 0x48, 0x22, 0x89, 0x24, 0x92, 0x48, 0x22, 0x89, 0x24, 0x92, 0x48, 0x22, 0x89, 0xfc, 0xb, 0x31, 0x1b, 0x93, 0xfa, 0xac, 0xe1, 0x98, 0xc3, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
-};
-
static const unsigned char mini_checkerboard_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x0, 0x0, 0x0, 0x0, 0x3a, 0x98, 0xa0, 0xbd, 0x0, 0x0, 0x0, 0x17, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x78, 0x0, 0x5, 0xff, 0xa1, 0x60, 0xa0, 0x4, 0x60, 0xc, 0x98, 0xc4, 0x0, 0x9, 0x0, 0x0, 0x44, 0x81, 0xef, 0x81, 0xc1, 0x26, 0x8e, 0x8, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
@@ -242,10 +206,6 @@ static const unsigned char option_button_disabled_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x40, 0xde, 0x8d, 0x6b, 0x0, 0x0, 0x1, 0x2f, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0x3f, 0x3f, 0x5a, 0x5a, 0x5a, 0x2b, 0x2b, 0x31, 0x2e, 0x2e, 0x34, 0x59, 0x59, 0x59, 0x2a, 0x2a, 0x30, 0x4b, 0x4b, 0x4b, 0x22, 0x22, 0x27, 0x35, 0x35, 0x35, 0x4a, 0x4a, 0x4a, 0x24, 0x24, 0x28, 0x24, 0x24, 0x29, 0x56, 0x56, 0x56, 0x62, 0x62, 0x62, 0x2a, 0x2a, 0x31, 0x2a, 0x2a, 0x30, 0x2d, 0x2d, 0x34, 0x2f, 0x2f, 0x36, 0x2e, 0x2e, 0x35, 0x2c, 0x2c, 0x32, 0x48, 0x48, 0x48, 0x44, 0x44, 0x44, 0x43, 0x43, 0x43, 0x54, 0x54, 0x54, 0x26, 0x26, 0x2b, 0x24, 0x24, 0x28, 0x27, 0x27, 0x2d, 0x29, 0x29, 0x2f, 0x28, 0x28, 0x2e, 0x25, 0x25, 0x2b, 0x23, 0x23, 0x28, 0x26, 0x26, 0x2c, 0x25, 0x25, 0x2a, 0x2a, 0x2a, 0x2f, 0x2b, 0x2b, 0x31, 0x22, 0x22, 0x26, 0x52, 0x52, 0x52, 0x42, 0x42, 0x42, 0x2d, 0x2d, 0x33, 0x22, 0x22, 0x27, 0x51, 0x51, 0x51, 0x40, 0x40, 0x40, 0x27, 0x27, 0x2b, 0x2e, 0x2e, 0x34, 0x2c, 0x2c, 0x31, 0x29, 0x29, 0x2e, 0x4f, 0x4f, 0x4f, 0x3f, 0x3f, 0x3f, 0x4d, 0x4d, 0x4d, 0x3e, 0x3e, 0x3e, 0x24, 0x24, 0x2a, 0x24, 0x24, 0x29, 0x20, 0x20, 0x25, 0x4c, 0x4c, 0x4c, 0x3d, 0x3d, 0x3d, 0x28, 0x28, 0x2d, 0x2b, 0x2b, 0x30, 0x29, 0x29, 0x2d, 0x20, 0x20, 0x23, 0x4a, 0x4a, 0x4a, 0x3b, 0x3b, 0x3b, 0x22, 0x22, 0x28, 0x27, 0x27, 0x2c, 0x1e, 0x1e, 0x22, 0x49, 0x49, 0x49, 0x3a, 0x3a, 0x3a, 0x21, 0x21, 0x26, 0x21, 0x21, 0x25, 0x23, 0x23, 0x27, 0x20, 0x20, 0x24, 0x1d, 0x1d, 0x21, 0x39, 0x39, 0x39, 0x47, 0x47, 0x47, 0x1f, 0x1f, 0x24, 0x1f, 0x1f, 0x23, 0x1e, 0x1e, 0x21, 0x46, 0x46, 0x46, 0xd3, 0xa7, 0xd4, 0x88, 0x0, 0x0, 0x0, 0x24, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x4, 0xa, 0x11, 0x19, 0x1f, 0x22, 0x24, 0x1d, 0x16, 0xd, 0x7, 0x2, 0x15, 0x25, 0x34, 0x3f, 0x46, 0x47, 0x48, 0x43, 0x3a, 0x2d, 0x1b, 0x77, 0xef, 0xe6, 0x49, 0xef, 0xe6, 0xef, 0xe7, 0x77, 0xef, 0xe4, 0x4a, 0xba, 0xea, 0xc1, 0xeb, 0x0, 0x0, 0x0, 0xec, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x6c, 0x8e, 0x5, 0x4e, 0x0, 0x31, 0x10, 0x45, 0xff, 0xef, 0x56, 0xc2, 0xe2, 0xee, 0x4e, 0x3c, 0xc8, 0xd, 0xb8, 0x38, 0xa7, 0xc0, 0xdd, 0xdd, 0x5d, 0xbb, 0x94, 0x4c, 0xd2, 0xc1, 0xdf, 0x4a, 0x47, 0x5e, 0x27, 0xc3, 0xc, 0x80, 0x64, 0x24, 0xb8, 0xc7, 0x4f, 0x2c, 0x6b, 0xd5, 0x90, 0xff, 0xdd, 0x23, 0x7e, 0xc1, 0xa2, 0xb6, 0x64, 0xad, 0x26, 0x82, 0xc6, 0xef, 0x45, 0xbc, 0xe3, 0x1, 0x2c, 0x69, 0x9b, 0xc8, 0x7f, 0x5, 0x36, 0x1e, 0x41, 0x84, 0xd6, 0x4, 0x25, 0x90, 0xb7, 0x39, 0x6c, 0x4c, 0x2f, 0xbe, 0x68, 0xdf, 0x13, 0xa1, 0x9e, 0xc8, 0xa4, 0xb7, 0xe7, 0x47, 0x93, 0x63, 0x1b, 0xf9, 0xdc, 0x8, 0x88, 0x60, 0xbf, 0x4, 0xff, 0xd2, 0x56, 0x93, 0xe3, 0xb7, 0xb2, 0xf6, 0x2c, 0x36, 0x1, 0x16, 0xf4, 0x5f, 0x42, 0xc4, 0x17, 0x8f, 0xb5, 0xc0, 0xa5, 0x8, 0x30, 0x5f, 0xc2, 0x5d, 0xcf, 0xc9, 0xd, 0x74, 0x87, 0x8b, 0x5e, 0x56, 0x22, 0x24, 0xf7, 0x6d, 0xc2, 0xd1, 0x80, 0x26, 0x27, 0x5d, 0x5b, 0x67, 0x7d, 0x2f, 0x80, 0x4d, 0xc9, 0x7f, 0x9, 0x63, 0xa7, 0x61, 0x23, 0xc7, 0x74, 0x3d, 0xf, 0xae, 0x41, 0x84, 0x6f, 0x13, 0xe6, 0x26, 0xfa, 0x36, 0x46, 0x73, 0xbc, 0xba, 0x3b, 0xd6, 0xca, 0x8, 0xd0, 0xd6, 0x36, 0x4e, 0x35, 0xeb, 0xad, 0xd7, 0xb0, 0x60, 0x72, 0xdc, 0xda, 0x9c, 0x2, 0x67, 0x76, 0x64, 0x82, 0x99, 0x9b, 0xb6, 0x80, 0xb0, 0x7e, 0x8d, 0xf6, 0x5a, 0xdd, 0xe1, 0xb5, 0xba, 0xba, 0xb1, 0x0, 0xcd, 0xc7, 0x50, 0x23, 0xeb, 0xfb, 0x7f, 0xb4, 0xc8, 0x22, 0x18, 0xdd, 0x0, 0xd5, 0xec, 0x4e, 0x53, 0xc6, 0x18, 0x44, 0x3f, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
-static const unsigned char option_button_focus_png[] = {
- 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0xb1, 0x50, 0x4c, 0x54, 0x45, 0x95, 0xa9, 0xb0, 0x92, 0xa7, 0xae, 0x8e, 0xa2, 0xa9, 0x8a, 0x9d, 0xa4, 0x85, 0x98, 0x9f, 0x80, 0x93, 0x9b, 0x7b, 0x8f, 0x96, 0x77, 0x8a, 0x92, 0x72, 0x86, 0x8c, 0x6e, 0x80, 0x88, 0x69, 0x7c, 0x84, 0x64, 0x77, 0x7f, 0x60, 0x72, 0x7a, 0x5b, 0x6e, 0x75, 0x56, 0x69, 0x71, 0xc8, 0xe3, 0xe7, 0xc8, 0xe2, 0xe7, 0xca, 0xe3, 0xe7, 0xce, 0xe6, 0xe9, 0xce, 0xe6, 0xea, 0xd0, 0xe6, 0xe9, 0xce, 0xe5, 0xea, 0xd0, 0xe6, 0xea, 0xce, 0xe5, 0xe9, 0xd0, 0xe5, 0xe9, 0xd3, 0xe7, 0xeb, 0xd4, 0xe7, 0xeb, 0xd9, 0xea, 0xed, 0xd7, 0xe9, 0xed, 0xd7, 0xea, 0xed, 0xdc, 0xec, 0xef, 0xdc, 0xeb, 0xef, 0xe0, 0xed, 0xf1, 0xdf, 0xee, 0xf1, 0xdf, 0xed, 0xf1, 0xe0, 0xee, 0xf1, 0xe3, 0xf0, 0xf2, 0xe2, 0xef, 0xf2, 0xe3, 0xef, 0xf2, 0xe6, 0xf1, 0xf3, 0xe8, 0xf2, 0xf5, 0xe8, 0xf3, 0xf4, 0xe8, 0xf2, 0xf4, 0xe8, 0xf3, 0xf5, 0xd6, 0x5a, 0x5b, 0xd4, 0x57, 0x58, 0xe5, 0x89, 0x89, 0xd5, 0x57, 0x59, 0xd5, 0x58, 0x59, 0xd5, 0x59, 0x5a, 0xd6, 0x59, 0x5a, 0xd6, 0x5a, 0x5c, 0xd7, 0x5b, 0x5c, 0xd7, 0x5b, 0x5d, 0xd8, 0x5c, 0x5d, 0xd8, 0x5c, 0x5e, 0xd8, 0x5d, 0x5f, 0xd9, 0x5d, 0x5f, 0xe8, 0x6c, 0x6e, 0x20, 0x6, 0x32, 0x78, 0x0, 0x0, 0x0, 0x2c, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0xac, 0x80, 0x68, 0x47, 0x0, 0x0, 0x0, 0x72, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x55, 0xc8, 0xc1, 0x8d, 0xc2, 0x30, 0x18, 0x6, 0xd1, 0x99, 0xdf, 0x8e, 0x7c, 0x59, 0x6d, 0xb, 0x14, 0x40, 0xff, 0xa5, 0x50, 0x0, 0x6d, 0x4, 0xe4, 0xf, 0x59, 0x8, 0x42, 0xde, 0xf1, 0x35, 0xce, 0xd0, 0x2b, 0xbf, 0x6e, 0x5d, 0xe5, 0x10, 0xbb, 0x95, 0x3b, 0x48, 0x2a, 0xe4, 0xd2, 0xec, 0x9a, 0xe6, 0x2, 0xcf, 0xd, 0x56, 0x30, 0x24, 0x48, 0x6, 0xb8, 0x82, 0xc2, 0x0, 0xd6, 0x3b, 0xf6, 0x6a, 0x12, 0xc0, 0xc8, 0x6e, 0x77, 0x3c, 0xa, 0xa3, 0xb3, 0x4d, 0x19, 0x76, 0xa5, 0xb, 0x12, 0x1b, 0xb8, 0x82, 0xc6, 0x22, 0x7c, 0x42, 0xc4, 0x40, 0x41, 0x59, 0x8a, 0x42, 0x80, 0x39, 0xc1, 0xae, 0x6c, 0x7c, 0xb9, 0xe2, 0x8f, 0x43, 0xf4, 0x9f, 0xb3, 0x17, 0x98, 0xa8, 0x1a, 0xb6, 0xa7, 0xd9, 0xa6, 0x4e, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
-};
-
static const unsigned char option_button_hover_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x40, 0xde, 0x8d, 0x6b, 0x0, 0x0, 0x1, 0x41, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x42, 0x40, 0x4b, 0x5f, 0x5a, 0x6c, 0x2b, 0x2b, 0x31, 0x2e, 0x2e, 0x34, 0x5f, 0x5a, 0x6b, 0x2a, 0x2a, 0x30, 0x56, 0x53, 0x64, 0x22, 0x22, 0x27, 0x3e, 0x3b, 0x46, 0x57, 0x53, 0x63, 0x24, 0x24, 0x28, 0x24, 0x24, 0x29, 0x5b, 0x57, 0x68, 0x5a, 0x56, 0x67, 0x67, 0x63, 0x76, 0x2a, 0x2a, 0x31, 0x2a, 0x2a, 0x30, 0x2d, 0x2d, 0x34, 0x2f, 0x2f, 0x36, 0x2e, 0x2e, 0x35, 0x2c, 0x2c, 0x32, 0x4d, 0x4a, 0x57, 0x49, 0x46, 0x52, 0x48, 0x45, 0x51, 0x5a, 0x56, 0x65, 0x26, 0x26, 0x2b, 0x24, 0x24, 0x28, 0x27, 0x27, 0x2d, 0x29, 0x29, 0x2f, 0x28, 0x28, 0x2e, 0x25, 0x25, 0x2b, 0x23, 0x23, 0x28, 0x5b, 0x57, 0x66, 0x26, 0x26, 0x2c, 0x25, 0x25, 0x2a, 0x2a, 0x2a, 0x2f, 0x2b, 0x2b, 0x31, 0x22, 0x22, 0x26, 0x59, 0x55, 0x64, 0x47, 0x44, 0x50, 0x2d, 0x2d, 0x33, 0x22, 0x22, 0x27, 0x58, 0x54, 0x64, 0x46, 0x43, 0x50, 0x27, 0x27, 0x2b, 0x2e, 0x2e, 0x34, 0x2c, 0x2c, 0x31, 0x29, 0x29, 0x2e, 0x56, 0x53, 0x63, 0x45, 0x42, 0x4f, 0x56, 0x53, 0x62, 0x45, 0x42, 0x4e, 0x24, 0x24, 0x2a, 0x24, 0x24, 0x29, 0x20, 0x20, 0x25, 0x55, 0x51, 0x62, 0x44, 0x41, 0x4e, 0x28, 0x28, 0x2d, 0x2b, 0x2b, 0x30, 0x29, 0x29, 0x2d, 0x20, 0x20, 0x23, 0x55, 0x51, 0x60, 0x44, 0x41, 0x4d, 0x22, 0x22, 0x28, 0x27, 0x27, 0x2c, 0x1e, 0x1e, 0x22, 0x43, 0x40, 0x4c, 0x54, 0x50, 0x5f, 0x21, 0x21, 0x26, 0x21, 0x21, 0x25, 0x23, 0x23, 0x27, 0x20, 0x20, 0x24, 0x1d, 0x1d, 0x21, 0x47, 0x43, 0x51, 0x43, 0x3f, 0x4d, 0x42, 0x3f, 0x4c, 0x53, 0x4f, 0x5f, 0x1f, 0x1f, 0x24, 0x1f, 0x1f, 0x23, 0x1e, 0x1e, 0x21, 0x53, 0x50, 0x5f, 0x53, 0x4f, 0x5e, 0x5f, 0x5a, 0x6c, 0xd3, 0x26, 0x54, 0x35, 0x0, 0x0, 0x0, 0x24, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x4, 0xa, 0x11, 0x19, 0x1f, 0x22, 0x24, 0x1d, 0x16, 0xd, 0x7, 0x2, 0x15, 0x25, 0x34, 0x3f, 0x46, 0x47, 0x48, 0x43, 0x3a, 0x2d, 0x1b, 0x77, 0xef, 0xe6, 0x49, 0xef, 0xe6, 0xef, 0xe7, 0x77, 0xef, 0xe4, 0x4a, 0xba, 0xea, 0xc1, 0xeb, 0x0, 0x0, 0x0, 0xe5, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x85, 0x91, 0x43, 0x62, 0xc5, 0x60, 0x18, 0x45, 0xef, 0x8d, 0x51, 0xdb, 0xee, 0x46, 0xca, 0x6d, 0x77, 0x58, 0xce, 0x6b, 0xdb, 0x7c, 0x8a, 0xad, 0xea, 0x44, 0x1f, 0x4e, 0x92, 0x1f, 0x4c, 0x0, 0xe0, 0x9, 0x61, 0xf0, 0x89, 0x32, 0x12, 0xcd, 0xd4, 0x8, 0xef, 0x1f, 0x35, 0x54, 0xa0, 0x68, 0x1a, 0x34, 0x89, 0x8, 0x86, 0xa4, 0xd, 0x57, 0xb4, 0xdf, 0x79, 0x5, 0x89, 0x94, 0xba, 0xf9, 0xb3, 0xc0, 0xce, 0xeb, 0xf0, 0x17, 0x1c, 0xab, 0x11, 0x9, 0x1a, 0xf9, 0x96, 0x84, 0x5d, 0x5e, 0x43, 0x15, 0x7, 0x2e, 0x42, 0x41, 0x51, 0xd3, 0xbe, 0x67, 0xd5, 0x6b, 0x42, 0x3a, 0x38, 0x9b, 0xf5, 0x2e, 0x20, 0xfa, 0x5, 0x33, 0x41, 0x69, 0xf4, 0xeb, 0x49, 0x6c, 0x19, 0xe6, 0xbd, 0xdd, 0xd, 0x48, 0xa0, 0x92, 0xb, 0x36, 0x72, 0x6a, 0x26, 0xf0, 0x14, 0xa, 0x10, 0x72, 0xe1, 0x7d, 0xf4, 0xf6, 0x35, 0x1b, 0xc3, 0xe3, 0x18, 0x9d, 0x50, 0xf0, 0xe4, 0xc2, 0x17, 0xae, 0x27, 0xd3, 0xe4, 0x6e, 0xe8, 0xf8, 0x7e, 0xbc, 0x1, 0x48, 0x9e, 0x57, 0xf8, 0xc5, 0xfc, 0xbd, 0x7a, 0x98, 0xc4, 0x94, 0x47, 0xbf, 0xe4, 0xce, 0x48, 0x8, 0x6e, 0x69, 0x91, 0x63, 0x47, 0x73, 0x49, 0xbc, 0x77, 0x3e, 0xd7, 0x4b, 0x3b, 0x12, 0x36, 0x16, 0xb3, 0x85, 0x6a, 0x68, 0xce, 0x39, 0x62, 0xc6, 0xba, 0x3d, 0x8d, 0xe7, 0x91, 0x20, 0xac, 0xad, 0xa6, 0xc2, 0xe, 0x6, 0xcc, 0x74, 0xc, 0x2d, 0xe7, 0xf9, 0x55, 0x2, 0x28, 0x94, 0x37, 0xab, 0xee, 0xa1, 0xcc, 0xbf, 0xdb, 0xed, 0x3, 0x70, 0xe6, 0x4f, 0x4a, 0xc3, 0xed, 0xed, 0xf3, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
@@ -270,18 +230,6 @@ static const unsigned char popup_bg_disabled_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x78, 0x50, 0x4c, 0x54, 0x45, 0xff, 0x0, 0xff, 0x67, 0x7a, 0x85, 0x66, 0x7a, 0x86, 0x68, 0x7b, 0x86, 0x57, 0x51, 0x51, 0x4c, 0x42, 0x40, 0x4d, 0x43, 0x41, 0x56, 0x4c, 0x4b, 0x4d, 0x44, 0x41, 0x4e, 0x44, 0x42, 0x4f, 0x45, 0x43, 0x67, 0x7b, 0x87, 0x4f, 0x44, 0x43, 0x50, 0x45, 0x44, 0x52, 0x46, 0x44, 0x51, 0x46, 0x45, 0x4b, 0x40, 0x3f, 0x51, 0x47, 0x45, 0x52, 0x48, 0x46, 0x53, 0x48, 0x47, 0x4b, 0x41, 0x3f, 0x54, 0x49, 0x46, 0x55, 0x4a, 0x47, 0x55, 0x49, 0x47, 0x68, 0x7c, 0x88, 0x4a, 0x40, 0x3e, 0x55, 0x4b, 0x49, 0x56, 0x4d, 0x4b, 0x53, 0x49, 0x47, 0x50, 0x46, 0x44, 0x4a, 0x41, 0x3e, 0x48, 0x3e, 0x3c, 0x4b, 0x42, 0x3f, 0x49, 0x3f, 0x3d, 0x46, 0x3d, 0x3c, 0x47, 0x3d, 0x3b, 0x47, 0x3e, 0x3b, 0x49, 0x40, 0x3d, 0x45, 0x3c, 0x3b, 0x46, 0x3c, 0x3a, 0xdd, 0x63, 0x56, 0x8d, 0x0, 0x0, 0x0, 0xad, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x2d, 0x88, 0x35, 0x42, 0x4, 0x0, 0xc, 0x4, 0x77, 0x93, 0x9c, 0xbb, 0xf4, 0xc8, 0xff, 0xdf, 0x84, 0xb5, 0xb8, 0x5b, 0x84, 0x0, 0x37, 0xc5, 0xca, 0x10, 0xd, 0xc9, 0xce, 0xaa, 0xea, 0x24, 0x40, 0xca, 0x41, 0x64, 0x2b, 0x5, 0x87, 0x34, 0xa8, 0x88, 0x54, 0xef, 0x82, 0x80, 0x89, 0x34, 0x36, 0x96, 0xe0, 0x14, 0xa4, 0x12, 0xa6, 0x24, 0x18, 0xe1, 0xa8, 0x50, 0x59, 0x7c, 0x73, 0x30, 0x50, 0x55, 0x4a, 0x31, 0xd7, 0xb4, 0x89, 0xa1, 0x51, 0xb2, 0x9c, 0x1, 0x2c, 0x4, 0x83, 0x15, 0x12, 0x30, 0xab, 0xe9, 0x5a, 0x1, 0xb4, 0x40, 0xa1, 0x29, 0xbe, 0x75, 0xe, 0x5a, 0x70, 0xbe, 0x2a, 0xff, 0x12, 0xf1, 0xef, 0x1b, 0x5f, 0x8d, 0x5b, 0x68, 0xd, 0xdc, 0xe3, 0xf1, 0x71, 0x16, 0x3e, 0x5b, 0xc8, 0x33, 0xa9, 0xc7, 0xbc, 0x7f, 0xa4, 0x22, 0x6a, 0xb5, 0x90, 0xcb, 0xb2, 0x1a, 0x25, 0x67, 0x8b, 0x8f, 0x6f, 0xf8, 0x64, 0xa8, 0x35, 0x7a, 0x25, 0xa8, 0xa7, 0x1, 0x38, 0xc, 0xcc, 0xab, 0x4c, 0x5, 0xea, 0xe3, 0x76, 0x2f, 0x54, 0x93, 0xf3, 0xf, 0x4f, 0x10, 0x8d, 0x4c, 0x16, 0x9d, 0xcf, 0x1f, 0xd1, 0xf9, 0x3, 0x34, 0xc8, 0x4a, 0xb4, 0x1d, 0xb, 0xcd, 0x83, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
-static const unsigned char popup_checked_png[] = {
- 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x8, 0x8, 0x4, 0x0, 0x0, 0x0, 0x6e, 0x6, 0x76, 0x0, 0x0, 0x0, 0x0, 0x56, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0xc0, 0x3, 0x6e, 0xf0, 0xde, 0x3f, 0xf5, 0xe0, 0x30, 0x9c, 0xfb, 0x9f, 0xf1, 0xc1, 0xda, 0x7, 0xff, 0x1f, 0x9c, 0x85, 0xb, 0x3c, 0xa8, 0x1, 0x72, 0xdf, 0x3d, 0x56, 0x61, 0x78, 0x70, 0xf8, 0xc1, 0x99, 0x3b, 0x62, 0xf, 0xbc, 0x1e, 0xfc, 0x5, 0x42, 0x2f, 0xa0, 0xcc, 0xfd, 0x53, 0x40, 0x99, 0x6b, 0xf, 0xde, 0x3, 0xc9, 0x6a, 0xb0, 0x52, 0xa0, 0xec, 0xe5, 0x7, 0xff, 0x81, 0x70, 0xed, 0x7f, 0x46, 0x20, 0x17, 0x2a, 0x74, 0xfa, 0xc1, 0xb1, 0x1b, 0xbc, 0x10, 0x1e, 0x0, 0xfd, 0x1f, 0x33, 0x9, 0xf7, 0x50, 0x16, 0x2f, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
-};
-
-static const unsigned char popup_hover_png[] = {
- 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xed, 0xdd, 0xe2, 0x52, 0x0, 0x0, 0x0, 0x2d, 0x50, 0x4c, 0x54, 0x45, 0xff, 0x0, 0xff, 0x20, 0x2e, 0x31, 0x83, 0xae, 0xb7, 0xb3, 0xd8, 0xe1, 0xaf, 0xd5, 0xde, 0xac, 0xd2, 0xdb, 0xa9, 0xcf, 0xd8, 0xa5, 0xcc, 0xd5, 0xa2, 0xc9, 0xd2, 0x9e, 0xc6, 0xcf, 0x9b, 0xc3, 0xcc, 0x97, 0xc0, 0xc9, 0x94, 0xbd, 0xc6, 0x91, 0xba, 0xc3, 0x8d, 0xb7, 0xc0, 0x9c, 0x2c, 0x91, 0xa9, 0x0, 0x0, 0x0, 0x1f, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x62, 0x14, 0x4, 0x3, 0x1, 0x26, 0x41, 0x28, 0x60, 0x62, 0x80, 0xd0, 0xc, 0x74, 0x61, 0x98, 0x80, 0x1, 0x3, 0xd3, 0x7b, 0x28, 0x0, 0x0, 0x1a, 0x86, 0xe, 0x98, 0x2c, 0x61, 0xda, 0x2e, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
-};
-
-static const unsigned char popup_unchecked_png[] = {
- 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x8, 0x1, 0x3, 0x0, 0x0, 0x0, 0xfe, 0xc1, 0x2c, 0xc8, 0x0, 0x0, 0x0, 0x6, 0x50, 0x4c, 0x54, 0x45, 0xff, 0x0, 0xff, 0xff, 0xff, 0xff, 0x9f, 0x18, 0x32, 0xe0, 0x0, 0x0, 0x0, 0x1, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x40, 0xe6, 0xd8, 0x66, 0x0, 0x0, 0x0, 0xa, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x40, 0x3, 0x0, 0x0, 0x10, 0x0, 0x1, 0xb3, 0xac, 0xe2, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
-};
-
static const unsigned char popup_window_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x2a, 0x0, 0x0, 0x0, 0x46, 0x8, 0x3, 0x0, 0x0, 0x0, 0x8d, 0x2b, 0xf6, 0x48, 0x0, 0x0, 0x1, 0x6b, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0xe8, 0xe5, 0xf1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0x1d, 0x22, 0x0, 0x0, 0x0, 0x1a, 0x19, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x1e, 0x23, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0x1d, 0x21, 0x17, 0x16, 0x19, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x21, 0x1f, 0x24, 0x1b, 0x1a, 0x1d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x21, 0x1f, 0x24, 0x1e, 0x1c, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x22, 0x20, 0x25, 0x20, 0x1e, 0x23, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x21, 0x1f, 0x24, 0x0, 0x0, 0x0, 0x21, 0x1f, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x22, 0x20, 0x25, 0x0, 0x0, 0x0, 0x20, 0x20, 0x25, 0x20, 0x1d, 0x25, 0x20, 0x1d, 0x22, 0x1d, 0x1d, 0x22, 0x1d, 0x1d, 0x20, 0x1d, 0x1a, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x32, 0x30, 0x38, 0xe8, 0xe5, 0xf1, 0xe5, 0xe2, 0xeb, 0xe3, 0xe1, 0xe8, 0xe1, 0xdf, 0xe7, 0xe0, 0xde, 0xe6, 0xdf, 0xdd, 0xe5, 0xde, 0xdc, 0xe4, 0xdd, 0xdb, 0xe3, 0xdc, 0xda, 0xe2, 0xda, 0xd8, 0xe0, 0xd9, 0xd7, 0xdf, 0xd7, 0xd6, 0xdf, 0xd6, 0xd4, 0xdd, 0xd5, 0xd3, 0xdc, 0xd4, 0xd1, 0xdb, 0xd3, 0xd0, 0xda, 0xd1, 0xce, 0xd8, 0xd0, 0xcd, 0xd7, 0xcf, 0xcd, 0xd7, 0xe2, 0xdf, 0xeb, 0x48, 0x46, 0x51, 0x42, 0x40, 0x4b, 0x40, 0x3e, 0x48, 0x40, 0x3d, 0x48, 0x48, 0x45, 0x50, 0x42, 0x3f, 0x4a, 0x3f, 0x3d, 0x48, 0x47, 0x44, 0x50, 0x41, 0x3f, 0x4a, 0x3f, 0x3d, 0x47, 0x41, 0x3e, 0x49, 0x3f, 0x3c, 0x47, 0x46, 0x43, 0x4f, 0x3e, 0x3c, 0x46, 0x40, 0x3e, 0x49, 0x3d, 0x3b, 0x46, 0x45, 0x43, 0x4e, 0x3d, 0x3b, 0x45, 0x44, 0x42, 0x4d, 0x3d, 0x3a, 0x45, 0x3e, 0x3c, 0x47, 0x3c, 0x3a, 0x44, 0x43, 0x42, 0x4c, 0x43, 0x40, 0x4c, 0x3e, 0x3b, 0x46, 0x3b, 0x39, 0x43, 0x43, 0x3f, 0x4c, 0x43, 0x3f, 0x4b, 0x3a, 0x38, 0x42, 0x42, 0x3e, 0x4b, 0x42, 0x3e, 0x49, 0x3a, 0x37, 0x41, 0x39, 0x37, 0x41, 0x3f, 0x3e, 0x48, 0x39, 0x37, 0x40, 0x38, 0x36, 0x40, 0x3e, 0x3d, 0x48, 0x38, 0x36, 0x3f, 0x3e, 0x3d, 0x47, 0x3a, 0x38, 0x41, 0x38, 0x35, 0x3f, 0x37, 0x35, 0x3e, 0x39, 0x36, 0x40, 0x37, 0x34, 0x3e, 0x3d, 0x3a, 0x46, 0x36, 0x34, 0x3d, 0x3d, 0x3a, 0x44, 0x37, 0x35, 0x3f, 0x35, 0x33, 0x3c, 0x46, 0x44, 0x4f, 0xac, 0xa5, 0x1, 0x25, 0x0, 0x0, 0x0, 0x33, 0x74, 0x52, 0x4e, 0x53, 0x0, 0xa2, 0x3, 0x9, 0x17, 0xc, 0x20, 0xf, 0x2a, 0x5e, 0x12, 0x30, 0x68, 0x46, 0x20, 0x4e, 0xa2, 0x7d, 0x3a, 0x4f, 0xa4, 0x7d, 0x3f, 0x25, 0x60, 0xc0, 0xb8, 0x57, 0x1d, 0xba, 0x59, 0xbd, 0x5b, 0x22, 0xbf, 0x5e, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xa1, 0x9f, 0x9e, 0x52, 0x92, 0x15, 0x44, 0x7e, 0xd8, 0x5, 0xc7, 0xf4, 0xac, 0x0, 0x0, 0x1, 0x98, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xed, 0xd6, 0x55, 0x9e, 0x14, 0x31, 0x10, 0x80, 0xf1, 0xb2, 0x20, 0x1d, 0xdc, 0x9d, 0x3b, 0x2c, 0xa7, 0x87, 0x4b, 0xe0, 0xee, 0xd0, 0x82, 0xcb, 0xea, 0xb4, 0x86, 0x79, 0x23, 0x93, 0xaa, 0xcc, 0xf, 0xd7, 0xfd, 0x9e, 0xff, 0xed, 0x1d, 0x21, 0xf8, 0xe2, 0xfe, 0x1c, 0x8a, 0x17, 0x32, 0xa1, 0xa2, 0x2b, 0x48, 0x66, 0xb8, 0xa2, 0x28, 0x10, 0x9a, 0xd1, 0xf7, 0x3d, 0x16, 0x66, 0xfa, 0x45, 0x74, 0x9b, 0xd2, 0x97, 0x52, 0xe2, 0x2f, 0xa6, 0x40, 0x5f, 0x4c, 0x1d, 0xf3, 0x97, 0x52, 0x5e, 0x46, 0xf7, 0xee, 0xe3, 0x88, 0x8a, 0x48, 0x9e, 0x8a, 0xec, 0x8c, 0x28, 0x2c, 0xa7, 0xf0, 0x99, 0xd2, 0x6e, 0xe7, 0x8e, 0x10, 0x9b, 0xd1, 0x11, 0xe7, 0xe, 0xd1, 0x17, 0x8e, 0x2, 0xe6, 0x55, 0xf8, 0x42, 0x4a, 0x74, 0x18, 0xbe, 0xf8, 0xac, 0x9b, 0x5f, 0x4a, 0xb7, 0x36, 0x20, 0xa5, 0xf9, 0x2f, 0x90, 0x50, 0x11, 0x36, 0x13, 0x49, 0xa9, 0xe7, 0x6c, 0x5e, 0xcf, 0x2e, 0x99, 0xf4, 0xd, 0xb8, 0x8c, 0x5, 0xa7, 0x28, 0x8, 0x98, 0x9, 0x68, 0xba, 0x41, 0x66, 0x1b, 0x8a, 0xa2, 0xb0, 0x4d, 0x59, 0x30, 0xa5, 0x94, 0xa3, 0x94, 0x52, 0x0, 0x6f, 0x53, 0x6f, 0x7c, 0x82, 0x16, 0xcc, 0x5a, 0x51, 0x14, 0xbd, 0x98, 0x79, 0x4c, 0x29, 0x72, 0xee, 0xac, 0x8c, 0xea, 0xac, 0xb9, 0x51, 0xa0, 0xce, 0xa, 0x44, 0x60, 0x46, 0xa4, 0x28, 0x2, 0x9b, 0x1, 0x2a, 0x5a, 0xa, 0x9a, 0x49, 0xa9, 0xe8, 0x79, 0x20, 0x33, 0x38, 0xaf, 0x68, 0xc5, 0x68, 0xc6, 0x95, 0xa2, 0xe7, 0x72, 0x67, 0x3d, 0x97, 0x52, 0x24, 0xcf, 0x66, 0x9e, 0x30, 0xa5, 0xef, 0x5a, 0x34, 0x6b, 0xdf, 0xa5, 0x14, 0xa4, 0x0, 0xb3, 0x42, 0x8c, 0xe5, 0x38, 0x37, 0xb4, 0x14, 0x3d, 0xd2, 0xda, 0xb4, 0x3d, 0xa2, 0x68, 0xe3, 0xc0, 0xcc, 0x35, 0x8a, 0x9e, 0x86, 0x4c, 0xa7, 0x15, 0x85, 0x9d, 0x6c, 0xb6, 0x13, 0x16, 0xe8, 0x54, 0x78, 0xbc, 0x8e, 0x60, 0x86, 0xd7, 0xd1, 0x17, 0xd3, 0x37, 0x6e, 0x48, 0x30, 0x4f, 0x70, 0x81, 0xbe, 0xed, 0x97, 0xd1, 0xfe, 0x6d, 0x44, 0xf7, 0xed, 0xa7, 0x63, 0x39, 0x79, 0x8c, 0xf6, 0xef, 0x8b, 0xe8, 0x61, 0xe6, 0x8d, 0x55, 0x5b, 0xae, 0x9e, 0x62, 0x3e, 0x1c, 0xd1, 0x3b, 0xf7, 0x9b, 0xc7, 0xfb, 0x9b, 0xab, 0x46, 0xcd, 0xab, 0x4b, 0xcd, 0xfd, 0x3b, 0x11, 0x1d, 0xe, 0x76, 0xf5, 0xc5, 0x2b, 0xe5, 0xf3, 0x67, 0x49, 0xcf, 0xcb, 0x2b, 0x8f, 0xea, 0xee, 0xe0, 0x10, 0xd1, 0xf0, 0xb2, 0x58, 0xb, 0x61, 0x75, 0xd6, 0x26, 0xcd, 0x56, 0x43, 0x58, 0x2b, 0x5e, 0x86, 0x88, 0x4e, 0x63, 0x33, 0x84, 0xf7, 0x1f, 0x26, 0xd5, 0x87, 0xf7, 0x61, 0x68, 0xc6, 0x29, 0xa2, 0x73, 0xdb, 0x5e, 0x2d, 0x57, 0x1f, 0xab, 0x56, 0xcb, 0xab, 0xed, 0x5c, 0xfe, 0xc4, 0x5d, 0xf1, 0x27, 0x1a, 0x8f, 0xba, 0x8d, 0xd7, 0xa0, 0x9a, 0x40, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
@@ -302,22 +250,10 @@ static const unsigned char radio_unchecked_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xed, 0xdd, 0xe2, 0x52, 0x0, 0x0, 0x0, 0x2a, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x4, 0x3, 0x4, 0x9, 0x9, 0x9, 0x6, 0x6, 0x6, 0xa, 0xa, 0xb, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x7f, 0x7f, 0x82, 0xd9, 0xd9, 0xd9, 0x47, 0x47, 0x48, 0x2b, 0x6e, 0xf2, 0xbf, 0x0, 0x0, 0x0, 0xb, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x88, 0xd1, 0xf7, 0x64, 0xf6, 0x2, 0xb3, 0xed, 0xd7, 0x0, 0x0, 0x0, 0x49, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x40, 0x2, 0x61, 0x15, 0xed, 0xa9, 0x20, 0x5a, 0x72, 0xf5, 0x99, 0x33, 0xbb, 0x26, 0x1, 0x19, 0x73, 0xcf, 0x0, 0xc1, 0x4d, 0x6, 0x6, 0xd6, 0x35, 0x20, 0xc6, 0xa9, 0x0, 0x6, 0xb6, 0x3d, 0x20, 0xc6, 0xe9, 0x4, 0x6, 0xf6, 0x33, 0x60, 0x50, 0xc0, 0xc0, 0x1, 0x61, 0x34, 0xc0, 0x19, 0x70, 0x29, 0xb8, 0x62, 0xb8, 0x76, 0x84, 0x81, 0xc, 0x96, 0x20, 0x2b, 0xa6, 0xc0, 0x2d, 0x45, 0x0, 0x0, 0x37, 0xca, 0x3d, 0x81, 0xb4, 0x84, 0xb6, 0x80, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
-static const unsigned char reference_border_png[] = {
- 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x2, 0x3, 0x0, 0x0, 0x0, 0x62, 0x9d, 0x17, 0xf2, 0x0, 0x0, 0x0, 0xc, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0xff, 0xd1, 0xd1, 0xff, 0xb7, 0xb7, 0xff, 0x41, 0x41, 0x2b, 0x2, 0x77, 0xea, 0x0, 0x0, 0x0, 0x2, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x0, 0x76, 0x93, 0xcd, 0x38, 0x0, 0x0, 0x0, 0x25, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x58, 0xff, 0xff, 0xff, 0x2f, 0x86, 0x6, 0x6, 0x6, 0x26, 0x86, 0xa3, 0xa1, 0xa1, 0xc1, 0xc, 0x47, 0x18, 0x18, 0x84, 0x49, 0x22, 0xc0, 0xda, 0xc0, 0x6, 0x80, 0x8d, 0x2, 0x0, 0x36, 0x2b, 0x14, 0x3d, 0x85, 0x39, 0x85, 0x31, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
-};
-
static const unsigned char scroll_bg_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x8, 0x3, 0x0, 0x0, 0x0, 0x61, 0xab, 0xac, 0xd5, 0x0, 0x0, 0x0, 0x45, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x40, 0x3e, 0x4a, 0x2a, 0x29, 0x2f, 0x20, 0x20, 0x24, 0x3f, 0x3e, 0x49, 0x1f, 0x1f, 0x24, 0x20, 0x20, 0x24, 0x4d, 0x4b, 0x59, 0x4d, 0x4b, 0x59, 0x3f, 0x3e, 0x49, 0x3f, 0x3e, 0x49, 0x1e, 0x1e, 0x23, 0x20, 0x20, 0x25, 0x22, 0x22, 0x27, 0x23, 0x23, 0x27, 0x23, 0x23, 0x28, 0x25, 0x25, 0x2a, 0x14, 0xee, 0x69, 0x20, 0x0, 0x0, 0x0, 0x11, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x4, 0x19, 0x40, 0x5d, 0x66, 0x28, 0x93, 0xf0, 0xfc, 0x94, 0xfc, 0xfd, 0x67, 0x1a, 0x96, 0x95, 0x1c, 0xf0, 0x43, 0x52, 0x0, 0x0, 0x0, 0x55, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x55, 0x8e, 0x45, 0x2, 0x80, 0x50, 0x10, 0x42, 0xc1, 0xee, 0xfb, 0x5f, 0xd4, 0xd6, 0xdf, 0xfd, 0x36, 0xd3, 0x3, 0x4, 0xd, 0x90, 0x6, 0xb2, 0x25, 0x39, 0xe0, 0xd2, 0xf9, 0xcb, 0x6a, 0x60, 0x6f, 0x27, 0xb7, 0xbc, 0x58, 0xb7, 0x53, 0x4d, 0x0, 0xf2, 0x3f, 0x5e, 0x36, 0x43, 0x5f, 0xc3, 0xf0, 0xdf, 0x17, 0xd7, 0xa6, 0xae, 0x60, 0x10, 0xff, 0x57, 0x16, 0xc5, 0x5a, 0xf1, 0x60, 0xe3, 0xe7, 0x5f, 0x37, 0x46, 0x74, 0xba, 0x9a, 0x16, 0xef, 0x37, 0x1c, 0x6f, 0x61, 0x47, 0x1, 0xa5, 0xc7, 0x32, 0x47, 0x38, 0x12, 0x92, 0xb1, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
-static const unsigned char scroll_button_down_png[] = {
- 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xed, 0xdd, 0xe2, 0x52, 0x0, 0x0, 0x0, 0x21, 0x50, 0x4c, 0x54, 0x45, 0x2d, 0x2c, 0x2f, 0x48, 0x46, 0x4a, 0x2d, 0x2c, 0x2f, 0x2d, 0x2c, 0x2f, 0x2d, 0x2c, 0x2f, 0x4c, 0x4a, 0x4e, 0x48, 0x46, 0x4a, 0x40, 0x3e, 0x42, 0x38, 0x36, 0x3a, 0xc3, 0xc3, 0xc3, 0x59, 0x59, 0x59, 0xb3, 0x52, 0xf2, 0x5, 0x0, 0x0, 0x0, 0x5, 0x74, 0x52, 0x4e, 0x53, 0x8, 0xfe, 0x9, 0xd, 0x19, 0x4a, 0xb6, 0xc1, 0xe6, 0x0, 0x0, 0x0, 0x33, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0xc, 0x5, 0x3, 0x21, 0x86, 0xf4, 0xe, 0x30, 0x28, 0x63, 0x88, 0x80, 0x30, 0x5a, 0xf1, 0x33, 0x66, 0x2, 0x1, 0x2a, 0xa3, 0x73, 0xe6, 0xcc, 0x19, 0x10, 0x35, 0x40, 0x1, 0x8, 0xa3, 0x73, 0x6, 0x1, 0x73, 0xe0, 0x96, 0x1a, 0x42, 0x9c, 0x21, 0x2, 0x0, 0x5a, 0xfa, 0x3d, 0xf9, 0xfa, 0xe2, 0x64, 0xe2, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
-};
-
-static const unsigned char scroll_button_down_hl_png[] = {
- 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xed, 0xdd, 0xe2, 0x52, 0x0, 0x0, 0x0, 0x21, 0x50, 0x4c, 0x54, 0x45, 0x3d, 0x3b, 0x3f, 0x60, 0x5d, 0x62, 0x3d, 0x3b, 0x3f, 0x3d, 0x3b, 0x3f, 0x3d, 0x3b, 0x3f, 0x65, 0x62, 0x67, 0x60, 0x5d, 0x62, 0x56, 0x53, 0x58, 0x4b, 0x49, 0x4e, 0xce, 0xce, 0xce, 0x59, 0x59, 0x59, 0xb8, 0xf5, 0x6d, 0x48, 0x0, 0x0, 0x0, 0x5, 0x74, 0x52, 0x4e, 0x53, 0x7, 0xfe, 0xc, 0x9, 0x1c, 0xda, 0x2b, 0xa5, 0x57, 0x0, 0x0, 0x0, 0x33, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0xc, 0x5, 0x3, 0x21, 0x86, 0xf4, 0xe, 0x30, 0x28, 0x63, 0x88, 0x80, 0x30, 0x5a, 0xf1, 0x33, 0x66, 0x2, 0x1, 0x2a, 0xa3, 0x73, 0xe6, 0xcc, 0x19, 0x10, 0x35, 0x40, 0x1, 0x8, 0xa3, 0x73, 0x6, 0x1, 0x73, 0xe0, 0x96, 0x1a, 0x42, 0x9c, 0x21, 0x2, 0x0, 0x5a, 0xfa, 0x3d, 0xf9, 0xfa, 0xe2, 0x64, 0xe2, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
-};
-
static const unsigned char scroll_button_left_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xed, 0xdd, 0xe2, 0x52, 0x0, 0x0, 0x0, 0x30, 0x50, 0x4c, 0x54, 0x45, 0x2d, 0x2c, 0x2f, 0x48, 0x46, 0x4a, 0x2d, 0x2c, 0x2f, 0x2d, 0x2c, 0x2f, 0x2d, 0x2c, 0x2f, 0x4c, 0x4a, 0x4e, 0x48, 0x46, 0x4a, 0x40, 0x3e, 0x42, 0x38, 0x36, 0x3a, 0xc3, 0xc3, 0xc3, 0xc2, 0xc2, 0xc2, 0xc1, 0xc1, 0xc1, 0xc0, 0xc0, 0xc0, 0xbf, 0xbf, 0xbf, 0xbe, 0xbe, 0xbe, 0x59, 0x59, 0x59, 0x8e, 0x47, 0x76, 0xf1, 0x0, 0x0, 0x0, 0x5, 0x74, 0x52, 0x4e, 0x53, 0x8, 0xfe, 0x9, 0xd, 0x19, 0x4a, 0xb6, 0xc1, 0xe6, 0x0, 0x0, 0x0, 0x3e, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0xc, 0x5, 0x3, 0x21, 0x86, 0xf4, 0xe, 0x30, 0x28, 0x63, 0x88, 0x80, 0x30, 0x5a, 0x51, 0x19, 0x33, 0xa1, 0x8c, 0xae, 0x55, 0x50, 0xc6, 0x2e, 0x28, 0xa3, 0x7b, 0xf7, 0x6e, 0x8, 0xa3, 0xe7, 0xcc, 0x19, 0xa8, 0x14, 0x9c, 0xd1, 0x7b, 0x17, 0xa6, 0xfd, 0x1d, 0x86, 0x81, 0x60, 0x6, 0xdc, 0x52, 0x43, 0x88, 0x33, 0x44, 0x0, 0xcc, 0x4e, 0x3f, 0xd1, 0x4, 0x90, 0xbf, 0x60, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
@@ -334,14 +270,6 @@ static const unsigned char scroll_button_right_hl_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x33, 0x50, 0x4c, 0x54, 0x45, 0x3d, 0x3b, 0x3f, 0x60, 0x5d, 0x62, 0x3d, 0x3b, 0x3f, 0x3d, 0x3b, 0x3f, 0x3d, 0x3b, 0x3f, 0x65, 0x62, 0x67, 0x60, 0x5d, 0x62, 0x56, 0x53, 0x58, 0x4b, 0x49, 0x4e, 0xc9, 0xc9, 0xc9, 0xc8, 0xc8, 0xc8, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc5, 0xc5, 0xc5, 0xc4, 0xc4, 0xc4, 0xc3, 0xc3, 0xc3, 0xc2, 0xc2, 0xc2, 0x2e, 0x3d, 0xb1, 0x1e, 0x0, 0x0, 0x0, 0x5, 0x74, 0x52, 0x4e, 0x53, 0x7, 0xfe, 0xc, 0x9, 0x1c, 0xda, 0x2b, 0xa5, 0x57, 0x0, 0x0, 0x0, 0x49, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x65, 0xc8, 0x31, 0x16, 0x2, 0x20, 0x10, 0x43, 0xc1, 0xe4, 0x83, 0xdc, 0xff, 0xb8, 0x88, 0xf, 0x57, 0xb, 0x8b, 0x80, 0x53, 0xe, 0xf2, 0x23, 0x18, 0xc6, 0x68, 0x61, 0x74, 0xca, 0xa, 0x2e, 0x74, 0xf9, 0x85, 0xfd, 0x17, 0x5c, 0x81, 0xfb, 0x11, 0x2a, 0xaa, 0x65, 0x80, 0x20, 0xc3, 0x5f, 0xaf, 0x2b, 0x96, 0xce, 0x78, 0xea, 0x88, 0x39, 0x95, 0x91, 0x70, 0x29, 0x94, 0xd9, 0x6b, 0x87, 0xf5, 0xfe, 0x0, 0xc6, 0xa7, 0x1b, 0x66, 0x7b, 0x42, 0xf1, 0x14, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
-static const unsigned char scroll_button_up_png[] = {
- 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xed, 0xdd, 0xe2, 0x52, 0x0, 0x0, 0x0, 0x21, 0x50, 0x4c, 0x54, 0x45, 0x2d, 0x2c, 0x2f, 0x48, 0x46, 0x4a, 0x2d, 0x2c, 0x2f, 0x2d, 0x2c, 0x2f, 0x2d, 0x2c, 0x2f, 0x4c, 0x4a, 0x4e, 0x48, 0x46, 0x4a, 0x40, 0x3e, 0x42, 0x38, 0x36, 0x3a, 0xc3, 0xc3, 0xc3, 0x59, 0x59, 0x59, 0xb3, 0x52, 0xf2, 0x5, 0x0, 0x0, 0x0, 0x5, 0x74, 0x52, 0x4e, 0x53, 0x8, 0xfe, 0x9, 0xd, 0x19, 0x4a, 0xb6, 0xc1, 0xe6, 0x0, 0x0, 0x0, 0x36, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0xc, 0x5, 0x3, 0x21, 0x86, 0xf4, 0xe, 0x30, 0x28, 0x63, 0x88, 0x80, 0x30, 0x5a, 0xb1, 0x33, 0x3a, 0x67, 0x40, 0x19, 0x33, 0x67, 0x42, 0x18, 0x9d, 0x33, 0x67, 0xce, 0x0, 0x33, 0x66, 0x2, 0x1, 0x2a, 0x3, 0x9f, 0x39, 0x10, 0x6, 0xdc, 0x52, 0x43, 0x88, 0x33, 0x44, 0x0, 0x59, 0xc8, 0x3d, 0xf9, 0xf, 0x68, 0xc5, 0xa9, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
-};
-
-static const unsigned char scroll_button_up_hl_png[] = {
- 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xed, 0xdd, 0xe2, 0x52, 0x0, 0x0, 0x0, 0x21, 0x50, 0x4c, 0x54, 0x45, 0x3d, 0x3b, 0x3f, 0x60, 0x5d, 0x62, 0x3d, 0x3b, 0x3f, 0x3d, 0x3b, 0x3f, 0x3d, 0x3b, 0x3f, 0x65, 0x62, 0x67, 0x60, 0x5d, 0x62, 0x56, 0x53, 0x58, 0x4b, 0x49, 0x4e, 0xce, 0xce, 0xce, 0x59, 0x59, 0x59, 0xb8, 0xf5, 0x6d, 0x48, 0x0, 0x0, 0x0, 0x5, 0x74, 0x52, 0x4e, 0x53, 0x7, 0xfe, 0xc, 0x9, 0x1c, 0xda, 0x2b, 0xa5, 0x57, 0x0, 0x0, 0x0, 0x36, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0xc, 0x5, 0x3, 0x21, 0x86, 0xf4, 0xe, 0x30, 0x28, 0x63, 0x88, 0x80, 0x30, 0x5a, 0xb1, 0x33, 0x3a, 0x67, 0x40, 0x19, 0x33, 0x67, 0x42, 0x18, 0x9d, 0x33, 0x67, 0xce, 0x0, 0x33, 0x66, 0x2, 0x1, 0x2a, 0x3, 0x9f, 0x39, 0x10, 0x6, 0xdc, 0x52, 0x43, 0x88, 0x33, 0x44, 0x0, 0x59, 0xc8, 0x3d, 0xf9, 0xf, 0x68, 0xc5, 0xa9, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
-};
-
static const unsigned char scroll_grabber_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x8, 0x3, 0x0, 0x0, 0x0, 0x61, 0xab, 0xac, 0xd5, 0x0, 0x0, 0x0, 0x5d, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x5b, 0x59, 0x61, 0x5b, 0x59, 0x61, 0x5a, 0x58, 0x60, 0x59, 0x57, 0x5f, 0x5a, 0x58, 0x60, 0x5a, 0x58, 0x60, 0x57, 0x56, 0x5e, 0x58, 0x56, 0x5e, 0x56, 0x55, 0x5d, 0x57, 0x55, 0x5d, 0x57, 0x55, 0x5d, 0x55, 0x53, 0x5b, 0x55, 0x53, 0x5b, 0x54, 0x53, 0x5b, 0x55, 0x54, 0x5c, 0x54, 0x52, 0x5a, 0x55, 0x53, 0x5b, 0x5a, 0x58, 0x60, 0x56, 0x54, 0x5c, 0x54, 0x53, 0x5a, 0x55, 0x53, 0x5b, 0x53, 0x51, 0x59, 0x52, 0x51, 0x59, 0x52, 0x50, 0x58, 0x51, 0x50, 0x58, 0x51, 0x4f, 0x57, 0x50, 0x4e, 0x56, 0x4f, 0x4d, 0x55, 0x50, 0x4f, 0x57, 0x54, 0x52, 0x5a, 0xae, 0x55, 0xff, 0xf7, 0x0, 0x0, 0x0, 0x12, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x2c, 0xb8, 0xf4, 0x2e, 0xf2, 0xb8, 0xf4, 0xf5, 0xf4, 0xf5, 0xb8, 0x2f, 0xf2, 0x2e, 0xb8, 0xf4, 0xb8, 0x66, 0xf6, 0xf7, 0x12, 0x0, 0x0, 0x0, 0x48, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x64, 0xc7, 0xb1, 0x11, 0x80, 0x40, 0x8, 0x45, 0x41, 0xff, 0x83, 0x2, 0xe, 0xfb, 0x2f, 0x13, 0xe2, 0xf3, 0x6, 0x12, 0x1d, 0x37, 0x5b, 0xae, 0x97, 0x5f, 0x84, 0xdd, 0x68, 0xe2, 0x1e, 0x41, 0xb8, 0x77, 0x58, 0x6, 0xb6, 0xe8, 0x88, 0xd1, 0xe1, 0x93, 0xad, 0x63, 0xab, 0xa3, 0x3a, 0xa3, 0x26, 0xa9, 0x4a, 0x52, 0xf9, 0xc, 0x62, 0xcf, 0xa7, 0x8f, 0x1f, 0x1e, 0xbd, 0xff, 0x84, 0xee, 0x2, 0x0, 0x54, 0x76, 0x10, 0x19, 0x1e, 0xd7, 0x1d, 0x9b, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
@@ -422,10 +350,6 @@ static const unsigned char toggle_on_disabled_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x20, 0x8, 0x6, 0x0, 0x0, 0x0, 0xa2, 0x9d, 0x7e, 0x84, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x12, 0x0, 0x0, 0xb, 0x12, 0x1, 0xd2, 0xdd, 0x7e, 0xfc, 0x0, 0x0, 0x6, 0x54, 0x49, 0x44, 0x41, 0x54, 0x68, 0x43, 0xed, 0x59, 0x4b, 0x6f, 0x1b, 0x55, 0x14, 0x3e, 0x71, 0xfc, 0x9a, 0xd8, 0x4e, 0x9c, 0x38, 0x6e, 0x62, 0xe7, 0x21, 0xb5, 0x6e, 0x51, 0xd5, 0x5, 0xa8, 0xac, 0x93, 0x14, 0x89, 0x22, 0x84, 0xba, 0x60, 0x53, 0xb1, 0x29, 0x12, 0x42, 0xa0, 0xfe, 0x1, 0x7e, 0x1, 0x7b, 0xb6, 0x6c, 0xaa, 0x82, 0xa8, 0xc4, 0x96, 0x5f, 0x50, 0x21, 0x55, 0x34, 0x1b, 0x4a, 0x17, 0x65, 0x51, 0x9, 0x85, 0x3c, 0x9b, 0xb4, 0x4d, 0xfd, 0x76, 0xfc, 0x7e, 0xf3, 0x7d, 0x37, 0x33, 0xc6, 0x76, 0xed, 0xcc, 0x38, 0x4e, 0x52, 0x21, 0x7a, 0xa4, 0xa3, 0xc9, 0x4c, 0xee, 0x3d, 0xf7, 0xbc, 0xee, 0xb9, 0xdf, 0x3d, 0x16, 0x79, 0x4b, 0x6f, 0x3d, 0xf0, 0xbf, 0xf6, 0xc0, 0xc8, 0x80, 0xd6, 0x73, 0xbc, 0xc1, 0x9c, 0x3a, 0xe8, 0xfc, 0x1, 0x97, 0xb3, 0x3c, 0xbc, 0xa9, 0x8f, 0xe4, 0xd3, 0x60, 0x4b, 0x93, 0xad, 0x1a, 0x60, 0x83, 0x34, 0xb2, 0xa3, 0x8d, 0x47, 0xf5, 0x6f, 0x56, 0x65, 0x58, 0x52, 0xe8, 0x18, 0x83, 0x68, 0x70, 0x3, 0x5c, 0x7, 0x57, 0xdb, 0x98, 0xdf, 0xc8, 0x47, 0x92, 0x99, 0xf2, 0xfc, 0x3f, 0xd, 0x75, 0x82, 0xbd, 0x60, 0xbf, 0xce, 0xe3, 0x78, 0x6a, 0xba, 0x33, 0xe8, 0x18, 0x33, 0x39, 0x66, 0x7a, 0x1c, 0xf7, 0xff, 0x86, 0xf1, 0x34, 0xbc, 0x8, 0x3e, 0x0, 0xa7, 0x75, 0xce, 0xe1, 0x59, 0xd1, 0x1d, 0x63, 0x64, 0xc8, 0x6b, 0xeb, 0x1c, 0xa5, 0x38, 0xd, 0xb3, 0xeb, 0x86, 0x7, 0xf1, 0x9c, 0xf7, 0xf9, 0x26, 0x96, 0xc1, 0x1f, 0x39, 0x9d, 0xce, 0xb, 0x36, 0xdb, 0xe8, 0xb8, 0xcd, 0x66, 0xd3, 0x46, 0x40, 0xc7, 0xd5, 0xfe, 0x24, 0xe6, 0x35, 0x41, 0x8d, 0x46, 0xa3, 0xd8, 0x68, 0xd4, 0xf, 0x2a, 0x95, 0xca, 0x66, 0x36, 0x9b, 0xb9, 0xf, 0x7e, 0x8, 0xd9, 0x7b, 0xe0, 0x18, 0x98, 0x8e, 0xa8, 0xf5, 0xcb, 0x86, 0x7e, 0xca, 0xd3, 0x78, 0x46, 0x7d, 0x2, 0xbc, 0x38, 0x36, 0xe6, 0x5d, 0x9, 0x4, 0x82, 0xb7, 0x5d, 0x2e, 0xf7, 0x3b, 0x6f, 0xd8, 0x5e, 0x53, 0x9f, 0xc1, 0x1f, 0x52, 0x2e, 0x97, 0xd6, 0x12, 0x89, 0xd8, 0x9d, 0x42, 0x21, 0xf7, 0x1b, 0x26, 0x3c, 0x3, 0x67, 0xf4, 0x6c, 0x78, 0x6d, 0x4b, 0xf4, 0x72, 0x0, 0xbf, 0xd1, 0xf8, 0x49, 0xf0, 0x85, 0xc9, 0xc9, 0xe9, 0xcf, 0xa7, 0xa6, 0xa6, 0xbf, 0x42, 0xb4, 0xf9, 0xed, 0x4c, 0x49, 0xd3, 0xec, 0x32, 0x3b, 0x3b, 0x2b, 0x93, 0x93, 0x93, 0xa2, 0x69, 0x9a, 0x40, 0x87, 0xbe, 0xeb, 0xd7, 0x6a, 0x35, 0x89, 0xc7, 0xe3, 0xb2, 0xb7, 0xb7, 0x27, 0xc5, 0x62, 0x4d, 0x90, 0x15, 0x95, 0x64, 0x32, 0xfe, 0x43, 0x2a, 0x15, 0xff, 0x19, 0x93, 0x36, 0xc1, 0x29, 0xdd, 0x9, 0x1d, 0xdb, 0xa1, 0xdb, 0x1, 0xc6, 0x9e, 0x67, 0xe4, 0x23, 0x53, 0x53, 0xc1, 0xaf, 0x61, 0xfc, 0xd7, 0x67, 0x9e, 0xe6, 0xb6, 0x51, 0x59, 0x98, 0xb, 0xca, 0xcc, 0xcc, 0x8c, 0x24, 0x12, 0x9, 0x65, 0x58, 0x36, 0x87, 0x6d, 0xde, 0xec, 0x51, 0xd3, 0xb0, 0x3, 0x35, 0xb7, 0x4d, 0x3c, 0x1e, 0x8f, 0xf8, 0xfd, 0x7e, 0xe5, 0xac, 0xfd, 0xfd, 0x7d, 0xd9, 0x7d, 0x1e, 0x93, 0x66, 0xbd, 0xd6, 0x84, 0x13, 0xee, 0x26, 0x93, 0xb1, 0xbb, 0xb0, 0x67, 0x43, 0xcf, 0x4, 0x16, 0xcb, 0x96, 0x13, 0x58, 0xe0, 0xda, 0x89, 0x2e, 0x76, 0x83, 0x43, 0x1e, 0x8f, 0xef, 0xe3, 0x60, 0x70, 0xe6, 0x1b, 0x78, 0xbd, 0x7b, 0xcc, 0xe9, 0x66, 0x1, 0x96, 0x8b, 0x9c, 0x9f, 0x93, 0x89, 0x89, 0x9, 0xd9, 0xdc, 0xdc, 0x84, 0x31, 0x9, 0xa9, 0x54, 0xb8, 0x85, 0xfb, 0xd5, 0xb1, 0xa6, 0xd4, 0x6a, 0xd, 0x29, 0x14, 0xca, 0x92, 0x4c, 0x66, 0xf0, 0xcc, 0x4a, 0x28, 0x14, 0x12, 0xaf, 0xc7, 0x2d, 0xa9, 0x4c, 0x7e, 0xc4, 0xed, 0x72, 0xbd, 0x57, 0xa9, 0x94, 0xb7, 0xaa, 0xd5, 0xca, 0x2e, 0x84, 0xe4, 0xc1, 0x1d, 0xc2, 0xba, 0x8d, 0xe3, 0x3b, 0x2b, 0xfd, 0xa5, 0x50, 0x68, 0xfe, 0x5b, 0x87, 0xc3, 0x11, 0x38, 0x5d, 0x6b, 0xbb, 0xa4, 0x23, 0x9a, 0xe1, 0x50, 0x40, 0x45, 0x71, 0x6d, 0x6d, 0x4d, 0x72, 0xb9, 0xf2, 0xc0, 0xcb, 0x97, 0x4a, 0x55, 0x39, 0x38, 0x48, 0x29, 0x27, 0x8c, 0xda, 0x9a, 0x92, 0xcb, 0x97, 0x6c, 0x28, 0xda, 0x91, 0x4c, 0x26, 0xc5, 0x7a, 0xc0, 0x6d, 0x40, 0xa1, 0x2d, 0x6f, 0xb6, 0x6f, 0x2a, 0xa6, 0x3f, 0xcf, 0xf9, 0x89, 0xf1, 0x71, 0xff, 0xa, 0xa, 0xde, 0xf9, 0x81, 0x57, 0x1f, 0x72, 0x82, 0xcb, 0x39, 0xa2, 0x14, 0xdf, 0xd9, 0xd9, 0x51, 0xfb, 0xf8, 0xb8, 0xc4, 0xb9, 0x94, 0x11, 0xe, 0x87, 0x85, 0x32, 0x69, 0xb, 0x6c, 0x5a, 0xa6, 0x6d, 0x60, 0x9e, 0x6c, 0x2d, 0xea, 0xe5, 0x0, 0xbf, 0xd7, 0x3b, 0x7e, 0xdd, 0xea, 0xe2, 0x73, 0x73, 0x61, 0xb9, 0x7a, 0xf5, 0x5d, 0xb9, 0x75, 0xeb, 0x33, 0xb9, 0x79, 0xf3, 0x53, 0xec, 0xdb, 0xc3, 0xa4, 0xd1, 0x34, 0xa7, 0xfa, 0x66, 0x43, 0x14, 0x8c, 0xf7, 0x6b, 0xd7, 0x96, 0x8e, 0x14, 0x1b, 0xc, 0x6, 0x11, 0xbd, 0x3, 0x49, 0xa7, 0x99, 0xa9, 0xc3, 0x11, 0x65, 0x64, 0x32, 0x19, 0xa1, 0x4c, 0x92, 0xd7, 0xeb, 0xa3, 0x4d, 0x2c, 0xec, 0x2c, 0xe6, 0xad, 0xda, 0xd7, 0xcb, 0x1, 0xe3, 0x48, 0x19, 0xcb, 0xd1, 0xbf, 0x78, 0xf1, 0x2, 0x3c, 0xec, 0x92, 0x7, 0xf, 0x56, 0xe5, 0xfe, 0xfd, 0x5f, 0xe5, 0xfa, 0xf5, 0xf, 0x85, 0x4e, 0x31, 0x68, 0x79, 0x99, 0x8e, 0xb7, 0x46, 0x4c, 0xfd, 0x74, 0x9a, 0x38, 0xe6, 0x64, 0x88, 0xb2, 0x28, 0x93, 0xe4, 0x74, 0xba, 0x22, 0x78, 0x10, 0xc0, 0x31, 0x3, 0x7a, 0x3a, 0x80, 0xe3, 0x58, 0x3, 0xdc, 0x4, 0x39, 0x56, 0x54, 0xa0, 0xa1, 0xf3, 0xf3, 0x61, 0x79, 0xfa, 0xf4, 0x2f, 0x79, 0xfe, 0xfc, 0x5, 0x3c, 0x9e, 0x93, 0x8d, 0x8d, 0x2d, 0x44, 0xfd, 0x70, 0x76, 0x34, 0x9a, 0x40, 0x4, 0x2, 0x2a, 0x1b, 0xac, 0x10, 0x8f, 0xba, 0x7c, 0x7e, 0xf8, 0xe8, 0x1b, 0x6b, 0x51, 0x16, 0x65, 0x2a, 0xc3, 0x46, 0xed, 0xac, 0x6d, 0x7c, 0xa1, 0x8d, 0x7d, 0x1d, 0xa0, 0x8e, 0x41, 0x22, 0x3c, 0x2b, 0xa, 0xe3, 0x88, 0x51, 0x46, 0x66, 0xb3, 0xd9, 0xd6, 0xf0, 0x78, 0x3c, 0x26, 0xd3, 0xd3, 0xd3, 0xea, 0x1d, 0xd5, 0x57, 0x9e, 0x3c, 0xf9, 0x53, 0x96, 0x96, 0xac, 0x65, 0x1, 0x8a, 0xae, 0x14, 0x8a, 0xa6, 0xf0, 0xdd, 0x8a, 0x6a, 0x6a, 0xc, 0x65, 0x51, 0x26, 0x49, 0xc7, 0x31, 0xaf, 0xc1, 0xf6, 0x6e, 0x64, 0xa1, 0xb0, 0x35, 0xd0, 0x14, 0xb1, 0xb5, 0x29, 0xd9, 0xed, 0x2e, 0x39, 0x77, 0x2e, 0x20, 0x3e, 0x9f, 0xaf, 0x35, 0xd6, 0xe7, 0x1b, 0x57, 0x86, 0x1b, 0xb4, 0xbe, 0xbe, 0xcd, 0xf4, 0x93, 0xcb, 0x97, 0x2f, 0x9b, 0xca, 0xab, 0x56, 0xab, 0x32, 0xa6, 0xf5, 0x7, 0x3b, 0xa6, 0x2, 0xba, 0x6, 0x50, 0x16, 0x65, 0x92, 0x8, 0x8c, 0xf8, 0x0, 0x77, 0x9c, 0xa7, 0xdd, 0xab, 0x11, 0x24, 0x14, 0xeb, 0xf5, 0x9a, 0xa5, 0x8d, 0xc8, 0xc8, 0x33, 0x3, 0xfc, 0xfe, 0x43, 0x7, 0xd0, 0x11, 0x91, 0xc8, 0x79, 0x5, 0x5c, 0xda, 0xe9, 0xf1, 0xe3, 0xdf, 0xe5, 0xca, 0x15, 0x73, 0x7, 0x14, 0x8b, 0x45, 0x5, 0x68, 0x4e, 0x8a, 0x28, 0x8b, 0x32, 0x49, 0xba, 0x4d, 0x7c, 0xe9, 0x0, 0x42, 0xed, 0x47, 0x2, 0x3d, 0x43, 0x77, 0x65, 0x71, 0xa9, 0xd8, 0x70, 0x38, 0x9c, 0xe7, 0xac, 0x28, 0xb2, 0xba, 0xfa, 0x50, 0x6e, 0xdc, 0xf8, 0x4, 0x11, 0xce, 0x1, 0xbc, 0x78, 0x55, 0xd, 0x78, 0xf5, 0x2a, 0xd1, 0xb1, 0xef, 0xf9, 0x4e, 0x47, 0x99, 0x51, 0x2a, 0x95, 0x52, 0x68, 0x2e, 0x16, 0xb3, 0xe4, 0x7f, 0x33, 0x71, 0x4a, 0x16, 0x65, 0x92, 0x90, 0x95, 0x44, 0x82, 0xbc, 0x2d, 0x1e, 0x9, 0x84, 0xd4, 0x25, 0x8, 0xd0, 0xd7, 0x87, 0x63, 0x63, 0xc5, 0x74, 0x5, 0x4a, 0xab, 0xd5, 0x65, 0x77, 0xf7, 0x5, 0x40, 0xcb, 0x81, 0x3c, 0x7a, 0xf4, 0x87, 0xbc, 0x7c, 0x19, 0x55, 0xd3, 0x8, 0x63, 0xa3, 0xd1, 0x7d, 0x14, 0xb5, 0xc3, 0x8, 0x6c, 0x6f, 0x6f, 0x22, 0x1a, 0x85, 0xd6, 0x7b, 0x2f, 0xd9, 0xe5, 0x72, 0x51, 0x16, 0x16, 0x16, 0x30, 0x2e, 0x27, 0x4, 0x34, 0xc3, 0x90, 0xdf, 0xef, 0x51, 0x38, 0x60, 0x6b, 0x6b, 0xb, 0xd1, 0x6f, 0xc2, 0x11, 0x89, 0x7b, 0xb8, 0x24, 0x3d, 0x82, 0xcc, 0xa4, 0xee, 0x4, 0x25, 0xbe, 0x17, 0xcc, 0xb5, 0x61, 0x60, 0x11, 0xe, 0x58, 0xb6, 0xdb, 0xed, 0x87, 0x67, 0x88, 0x9, 0x21, 0x63, 0x70, 0x7e, 0x67, 0xa5, 0xd9, 0xfc, 0xf7, 0x6a, 0xc1, 0xed, 0x61, 0x18, 0xcf, 0xe9, 0xfc, 0x5f, 0xfb, 0x7b, 0x2f, 0x91, 0x75, 0xec, 0xd0, 0x11, 0x6c, 0x53, 0x2a, 0x4e, 0x34, 0x47, 0x88, 0x7b, 0x1c, 0xe2, 0x25, 0x2a, 0x12, 0x89, 0x20, 0x13, 0x5f, 0x49, 0x3a, 0x53, 0xe0, 0xed, 0x70, 0x2b, 0x1a, 0x7d, 0xf9, 0x3d, 0x64, 0xed, 0x80, 0x79, 0xcc, 0xb4, 0x4, 0xf7, 0x72, 0x0, 0xb7, 0xc2, 0x8, 0x6e, 0x57, 0x39, 0xdc, 0x7, 0x3e, 0x40, 0x36, 0x9c, 0x5c, 0x55, 0xb2, 0x60, 0x4d, 0x36, 0x5f, 0x56, 0x38, 0x9e, 0x88, 0xb0, 0x54, 0xca, 0x43, 0xf9, 0xc1, 0x32, 0x81, 0x91, 0xa7, 0xf1, 0xb9, 0x5c, 0x4e, 0x9e, 0xed, 0x45, 0xa5, 0x51, 0xaf, 0xd5, 0x62, 0xb1, 0xfd, 0xef, 0x70, 0x17, 0x60, 0xf4, 0x59, 0x9c, 0x58, 0xc, 0xfb, 0x5e, 0x86, 0xa8, 0xa2, 0x6a, 0x2f, 0x61, 0x42, 0x86, 0xc6, 0x6b, 0xda, 0xd8, 0xfb, 0x67, 0x7a, 0x1b, 0xc4, 0x7d, 0x3e, 0x5, 0x3c, 0xe1, 0x74, 0xd8, 0x64, 0x71, 0x71, 0x11, 0x20, 0xcb, 0x81, 0x14, 0xae, 0x48, 0xa5, 0x6a, 0xe8, 0xdc, 0xde, 0x96, 0xc4, 0xdf, 0x88, 0x8f, 0xa6, 0x8d, 0xaa, 0x42, 0x1c, 0xe, 0xcf, 0x2, 0x84, 0xcd, 0xa1, 0x86, 0xc4, 0x64, 0xfb, 0xd9, 0xbe, 0xba, 0xd, 0x22, 0xf5, 0x7f, 0x44, 0x36, 0xfd, 0x2, 0x9b, 0xd8, 0x20, 0xe9, 0x88, 0x3e, 0x8d, 0x35, 0xeb, 0x7, 0x44, 0xd0, 0x8, 0xf9, 0xd2, 0xef, 0xf, 0x7c, 0x81, 0x73, 0xb4, 0x3, 0x43, 0x5b, 0x8, 0xe6, 0xd0, 0x43, 0x86, 0xec, 0x7, 0xd4, 0xd2, 0xe9, 0xc4, 0x3d, 0x34, 0x46, 0x7e, 0x82, 0x22, 0xeb, 0x60, 0x4b, 0xfd, 0x0, 0x43, 0x69, 0xa3, 0x23, 0x44, 0xf4, 0xb4, 0xe8, 0xf1, 0x78, 0x57, 0xd0, 0x1b, 0xb8, 0xed, 0x76, 0x6b, 0x97, 0x86, 0xb6, 0xea, 0xc, 0x4, 0x94, 0x4a, 0xc5, 0xbf, 0xd1, 0x3, 0xb8, 0x93, 0xcf, 0xb7, 0x3a, 0x42, 0x3c, 0x56, 0xc, 0x1c, 0xd0, 0xa1, 0x81, 0x59, 0x4f, 0x90, 0x30, 0x8a, 0xcd, 0x50, 0x42, 0xbb, 0x5, 0xf4, 0x3, 0x97, 0xf4, 0x9e, 0xe0, 0x45, 0x42, 0xcb, 0x37, 0xd1, 0x25, 0xea, 0xe5, 0x3f, 0x82, 0x1c, 0x9e, 0xf3, 0x28, 0xc6, 0xeb, 0x7a, 0x4f, 0x70, 0x15, 0xe3, 0x78, 0xff, 0xe7, 0x9e, 0x67, 0x4f, 0x90, 0x85, 0xa4, 0x67, 0x45, 0x35, 0x6b, 0x68, 0x1a, 0x1d, 0x22, 0x17, 0x4, 0x10, 0xa1, 0x30, 0x23, 0x78, 0x32, 0x74, 0x77, 0x85, 0xcf, 0x20, 0xae, 0x7d, 0x97, 0xa0, 0x61, 0xed, 0x5d, 0x61, 0xa6, 0x3a, 0x23, 0xce, 0xfd, 0x4e, 0x48, 0xda, 0x1, 0x7c, 0xba, 0xa5, 0x98, 0x39, 0x80, 0xe3, 0x8d, 0xaa, 0xc3, 0x13, 0x83, 0x75, 0x80, 0x37, 0x1b, 0x66, 0x86, 0x71, 0xa9, 0xb0, 0x22, 0xe3, 0x34, 0x1d, 0x64, 0xfc, 0x10, 0x62, 0xfc, 0x2e, 0xc0, 0x54, 0x27, 0xd8, 0x31, 0xc, 0xef, 0xdb, 0x12, 0x37, 0x8c, 0x1b, 0x44, 0xb9, 0xae, 0x12, 0x3c, 0xc8, 0xd4, 0x53, 0x1f, 0xdb, 0xfe, 0xab, 0xd0, 0x91, 0x46, 0x9f, 0xba, 0x26, 0x6f, 0x17, 0xf8, 0xf, 0x79, 0xe0, 0x1f, 0xd, 0x80, 0x80, 0xb4, 0xad, 0xe9, 0x2a, 0x4d, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
-static const unsigned char tool_button_pressed_png[] = {
- 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x1, 0xfe, 0x50, 0x4c, 0x54, 0x45, 0x29, 0x3a, 0x40, 0x2d, 0x3e, 0x44, 0x26, 0x34, 0x3b, 0x24, 0x34, 0x39, 0x23, 0x31, 0x38, 0x22, 0x31, 0x37, 0x22, 0x31, 0x37, 0x22, 0x30, 0x36, 0x22, 0x31, 0x36, 0x26, 0x34, 0x3c, 0x32, 0x44, 0x4c, 0x26, 0x34, 0x39, 0x23, 0x31, 0x36, 0x21, 0x2e, 0x34, 0x1f, 0x2c, 0x30, 0x1f, 0x2b, 0x2f, 0x1f, 0x2a, 0x2e, 0x1e, 0x2b, 0x2f, 0x1f, 0x2b, 0x2e, 0x36, 0x4b, 0x52, 0x25, 0x33, 0x38, 0x20, 0x2f, 0x32, 0x1c, 0x29, 0x2e, 0x1b, 0x26, 0x2a, 0x1a, 0x23, 0x26, 0x18, 0x22, 0x26, 0x19, 0x22, 0x26, 0x19, 0x23, 0x26, 0x19, 0x26, 0x29, 0x20, 0x2d, 0x32, 0x25, 0x31, 0x38, 0x3c, 0x51, 0x59, 0x23, 0x31, 0x37, 0x1f, 0x2b, 0x31, 0x1a, 0x25, 0x2b, 0x17, 0x20, 0x24, 0x15, 0x1c, 0x21, 0x14, 0x1b, 0x21, 0x14, 0x1c, 0x21, 0x13, 0x1b, 0x21, 0x15, 0x1d, 0x21, 0x1a, 0x25, 0x2a, 0x40, 0x57, 0x60, 0x23, 0x31, 0x36, 0x1f, 0x2b, 0x31, 0x1b, 0x25, 0x29, 0x16, 0x1e, 0x23, 0x14, 0x1b, 0x1d, 0x12, 0x19, 0x1d, 0x12, 0x1b, 0x1d, 0x14, 0x1a, 0x1d, 0x45, 0x5e, 0x67, 0x22, 0x32, 0x37, 0x20, 0x2d, 0x31, 0x1a, 0x26, 0x2a, 0x15, 0x1f, 0x25, 0x14, 0x1c, 0x1f, 0x12, 0x1b, 0x1f, 0x12, 0x1b, 0x20, 0x14, 0x1b, 0x1f, 0x15, 0x1e, 0x24, 0x1a, 0x25, 0x29, 0x4b, 0x64, 0x6d, 0x23, 0x32, 0x38, 0x20, 0x2e, 0x32, 0x1b, 0x27, 0x2b, 0x17, 0x22, 0x27, 0x16, 0x1e, 0x23, 0x14, 0x1e, 0x23, 0x16, 0x20, 0x24, 0x14, 0x1e, 0x22, 0x15, 0x1e, 0x22, 0x17, 0x21, 0x27, 0x1c, 0x27, 0x2c, 0x4f, 0x6a, 0x75, 0x21, 0x2f, 0x33, 0x1d, 0x29, 0x2d, 0x19, 0x23, 0x2a, 0x18, 0x22, 0x27, 0x16, 0x21, 0x27, 0x18, 0x23, 0x29, 0x17, 0x21, 0x26, 0x19, 0x23, 0x29, 0x1c, 0x28, 0x2d, 0x21, 0x2e, 0x33, 0x54, 0x70, 0x7c, 0x23, 0x33, 0x38, 0x22, 0x30, 0x34, 0x1e, 0x2a, 0x2f, 0x1a, 0x26, 0x2d, 0x1a, 0x25, 0x2b, 0x19, 0x25, 0x2b, 0x1a, 0x26, 0x2d, 0x1a, 0x26, 0x2c, 0x18, 0x25, 0x2a, 0x1a, 0x24, 0x2a, 0x1a, 0x25, 0x2c, 0x1d, 0x2a, 0x2f, 0x22, 0x2f, 0x34, 0x59, 0x77, 0x82, 0x23, 0x33, 0x39, 0x22, 0x30, 0x35, 0x1f, 0x2c, 0x31, 0x1c, 0x28, 0x30, 0x1c, 0x28, 0x2e, 0x1b, 0x29, 0x2f, 0x1c, 0x2a, 0x31, 0x1b, 0x28, 0x2f, 0x1c, 0x28, 0x2d, 0x1b, 0x27, 0x2f, 0x1f, 0x2b, 0x31, 0x5e, 0x7d, 0x8a, 0x24, 0x34, 0x39, 0x21, 0x2f, 0x37, 0x20, 0x2d, 0x34, 0x1d, 0x2b, 0x33, 0x1d, 0x2b, 0x32, 0x1d, 0x2d, 0x35, 0x1e, 0x2e, 0x36, 0x1f, 0x2e, 0x36, 0x1d, 0x2b, 0x34, 0x1d, 0x2b, 0x31, 0x1d, 0x2b, 0x32, 0x20, 0x2d, 0x32, 0x21, 0x2f, 0x36, 0x63, 0x83, 0x90, 0x25, 0x34, 0x39, 0x21, 0x31, 0x36, 0x1f, 0x2e, 0x34, 0x1f, 0x2e, 0x34, 0x1f, 0x2e, 0x36, 0x20, 0x31, 0x39, 0x21, 0x33, 0x3b, 0x21, 0x32, 0x3b, 0x1f, 0x30, 0x37, 0x1f, 0x2e, 0x35, 0x1e, 0x2d, 0x33, 0x1f, 0x2d, 0x33, 0x21, 0x30, 0x36, 0x67, 0x8a, 0x97, 0x24, 0x33, 0x39, 0x20, 0x30, 0x36, 0x1f, 0x2f, 0x35, 0x21, 0x30, 0x37, 0x22, 0x32, 0x39, 0x21, 0x35, 0x3e, 0x24, 0x37, 0x41, 0x24, 0x36, 0x41, 0x21, 0x33, 0x3c, 0x21, 0x31, 0x38, 0x1e, 0x2f, 0x35, 0x1e, 0x2e, 0x35, 0x20, 0x2e, 0x35, 0x24, 0x31, 0x39, 0x6c, 0x90, 0x9e, 0x22, 0x30, 0x36, 0x1f, 0x2e, 0x36, 0x20, 0x30, 0x36, 0x20, 0x31, 0x39, 0x23, 0x34, 0x3d, 0x23, 0x37, 0x41, 0x26, 0x3c, 0x47, 0x26, 0x3b, 0x46, 0x22, 0x35, 0x3f, 0x22, 0x32, 0x3b, 0x1f, 0x30, 0x37, 0x1f, 0x2e, 0x35, 0x1f, 0x2d, 0x35, 0x21, 0x30, 0x36, 0x72, 0x96, 0xa5, 0x7e, 0x8c, 0xc3, 0xb0, 0x0, 0x0, 0x0, 0xaa, 0x74, 0x52, 0x4e, 0x53, 0xc3, 0xc3, 0xe6, 0xd7, 0xcb, 0xc3, 0xbf, 0xbe, 0xbd, 0xe5, 0xc3, 0xd7, 0xc0, 0xac, 0xa0, 0x9a, 0x98, 0x98, 0x98, 0xc3, 0xcb, 0xac, 0x92, 0x82, 0x7b, 0x78, 0x78, 0x7b, 0x82, 0xac, 0xcb, 0xc3, 0xc3, 0xa0, 0x82, 0x6f, 0x67, 0x64, 0x63, 0x64, 0x67, 0x82, 0xc3, 0xbf, 0x9a, 0x7a, 0x67, 0x5e, 0x5b, 0x5a, 0x5e, 0xc3, 0xbd, 0x98, 0x78, 0x64, 0x5b, 0x57, 0x57, 0x5b, 0x64, 0x78, 0xc3, 0xbd, 0x98, 0x78, 0x63, 0x5a, 0x57, 0x56, 0x57, 0x5a, 0x63, 0x77, 0xc3, 0x98, 0x78, 0x63, 0x5a, 0x57, 0x56, 0x5a, 0x63, 0x77, 0x98, 0xc3, 0xbd, 0x98, 0x78, 0x63, 0x5a, 0x57, 0x56, 0x56, 0x57, 0x5a, 0x63, 0x77, 0x98, 0xc3, 0xbd, 0x98, 0x77, 0x63, 0x5a, 0x57, 0x56, 0x57, 0x5a, 0x63, 0x77, 0xc3, 0xbb, 0x96, 0x76, 0x63, 0x5a, 0x57, 0x56, 0x56, 0x57, 0x5a, 0x63, 0x76, 0x96, 0xc3, 0xb5, 0x92, 0x75, 0x62, 0x5a, 0x57, 0x56, 0x56, 0x57, 0x59, 0x62, 0x74, 0x92, 0xc3, 0xa9, 0x8b, 0x71, 0x61, 0x59, 0x57, 0x56, 0x56, 0x57, 0x59, 0x61, 0x71, 0x8b, 0xa9, 0xc3, 0x95, 0x7e, 0x6b, 0x5e, 0x59, 0x57, 0x56, 0x56, 0x57, 0x59, 0x5e, 0x6b, 0x7e, 0x95, 0xc3, 0x4f, 0x78, 0x99, 0x30, 0x0, 0x0, 0x0, 0x67, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x5c, 0x8b, 0x5, 0x2, 0xc3, 0x30, 0xc, 0xc4, 0x72, 0x5d, 0x39, 0xf4, 0xff, 0x67, 0x8e, 0x79, 0x1a, 0x37, 0xa0, 0xa0, 0x6d, 0x5d, 0x6b, 0x2a, 0x5a, 0xfd, 0x30, 0xe6, 0x1, 0xf4, 0xa7, 0x76, 0xfa, 0x37, 0x74, 0x7, 0x98, 0x52, 0x83, 0x46, 0x97, 0x41, 0xfb, 0xd6, 0x2d, 0x86, 0xae, 0xfe, 0x84, 0x6b, 0x6d, 0x32, 0x6e, 0x58, 0x28, 0x22, 0x3a, 0x41, 0x32, 0xde, 0xd7, 0x6a, 0x67, 0x5b, 0xb7, 0xb7, 0xc9, 0xb0, 0xd8, 0xd6, 0x3a, 0x65, 0x34, 0xb4, 0x21, 0x8f, 0x1c, 0x3, 0x6d, 0x21, 0x84, 0x5d, 0x32, 0x8a, 0x48, 0x22, 0x6e, 0xda, 0xa8, 0x92, 0x36, 0x3e, 0x87, 0xea, 0x7b, 0x7e, 0x0, 0x62, 0xa8, 0x25, 0xad, 0x68, 0x1d, 0x7d, 0x1a, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
-};
-
static const unsigned char tooltip_bg_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x4, 0x3, 0x0, 0x0, 0x0, 0xed, 0xdd, 0xe2, 0x52, 0x0, 0x0, 0x0, 0x30, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2d, 0x2c, 0x2f, 0x48, 0x46, 0x4a, 0xdd, 0xdd, 0xdd, 0x4c, 0x4a, 0x4e, 0x48, 0x46, 0x4a, 0x40, 0x3e, 0x42, 0xbc, 0x3, 0x4f, 0xe9, 0x0, 0x0, 0x0, 0xd, 0x74, 0x52, 0x4e, 0x53, 0xa, 0x1a, 0x26, 0x29, 0x2a, 0x48, 0x65, 0x6d, 0x6e, 0x66, 0xf5, 0xfe, 0xcc, 0xff, 0xb7, 0x4a, 0xbe, 0x0, 0x0, 0x0, 0x38, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x60, 0x54, 0x76, 0x1, 0x2, 0x23, 0x1, 0x6, 0xd1, 0xf4, 0xe, 0x20, 0x28, 0xb, 0x64, 0xd0, 0x5c, 0x7d, 0x17, 0x8, 0x76, 0x4d, 0x62, 0x70, 0x7f, 0x7f, 0x6, 0x8, 0xfe, 0x95, 0x30, 0x78, 0xdc, 0x1, 0x31, 0xce, 0xb6, 0x50, 0xc8, 0x80, 0x1b, 0x8, 0xb7, 0x2, 0x6e, 0x29, 0xdc, 0x19, 0x0, 0xcf, 0x24, 0x4d, 0xb3, 0xd0, 0x4d, 0xb9, 0x40, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
@@ -438,18 +362,6 @@ static const unsigned char tree_bg_disabled_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0xa, 0x8, 0x4, 0x0, 0x0, 0x0, 0x27, 0x3b, 0x7, 0x36, 0x0, 0x0, 0x0, 0x4e, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x94, 0xc8, 0x67, 0x6b, 0x60, 0xe6, 0x60, 0x64, 0x80, 0x80, 0xff, 0xc, 0x7f, 0x7f, 0xfc, 0x6a, 0x60, 0x94, 0xfb, 0xc0, 0xce, 0xcf, 0xc2, 0x80, 0x10, 0xfc, 0xc3, 0xf0, 0xf3, 0x23, 0xa3, 0xe2, 0x4f, 0xe, 0x36, 0x54, 0xc1, 0x1f, 0xbf, 0x18, 0x95, 0xbe, 0x73, 0x70, 0xb0, 0x30, 0xc0, 0x1, 0x48, 0xf0, 0x7, 0x85, 0x82, 0x58, 0x2d, 0xc2, 0xe6, 0xa4, 0x4f, 0x20, 0xc7, 0x37, 0x32, 0xb3, 0x23, 0x39, 0xfe, 0xfb, 0xaf, 0x46, 0x0, 0xee, 0x2a, 0x2f, 0xce, 0x4c, 0x47, 0x66, 0xf6, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
-static const unsigned char tree_bg_focus_png[] = {
- 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x20, 0x8, 0x6, 0x0, 0x0, 0x0, 0x73, 0x7a, 0x7a, 0xf4, 0x0, 0x0, 0x2, 0x7f, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x62, 0x91, 0x16, 0x97, 0x30, 0x63, 0x60, 0x60, 0x38, 0xc9, 0x30, 0x30, 0xc0, 0x9c, 0x11, 0xe8, 0x80, 0xff, 0x6b, 0x3, 0x7f, 0xd, 0x88, 0xed, 0xc1, 0xeb, 0xd9, 0x18, 0x58, 0x60, 0x1c, 0x9e, 0xac, 0xdd, 0x0, 0x5a, 0xcb, 0x6, 0xc5, 0x99, 0x23, 0x6, 0xa2, 0xaf, 0xe4, 0xb3, 0xe5, 0x8a, 0x39, 0x69, 0xf8, 0xcf, 0xa8, 0x82, 0x2d, 0x52, 0xe0, 0x1e, 0x61, 0x63, 0xe0, 0x93, 0x29, 0x7a, 0x66, 0xdb, 0xdb, 0x7a, 0x5d, 0x92, 0x96, 0x45, 0x12, 0x55, 0xf, 0x24, 0xbd, 0x4, 0x50, 0x22, 0x81, 0x98, 0x70, 0x96, 0x63, 0x2b, 0x91, 0x3d, 0xdb, 0x80, 0xb0, 0xfd, 0x52, 0xf7, 0x85, 0x6d, 0xfe, 0xf9, 0xfb, 0x2f, 0x0, 0x2, 0x80, 0x18, 0x80, 0xa7, 0x4a, 0xa8, 0x6a, 0x40, 0xf8, 0x15, 0xc0, 0x9c, 0x61, 0x43, 0x77, 0xd3, 0xd, 0x48, 0x34, 0xce, 0x5e, 0x0, 0x84, 0xd0, 0x24, 0xe7, 0xf1, 0xa8, 0x17, 0x0, 0x3, 0x94, 0x7d, 0xef, 0x1c, 0xec, 0xe, 0x98, 0x38, 0x60, 0x33, 0xc7, 0x34, 0xb6, 0x90, 0xb5, 0x1, 0xf0, 0x76, 0xfb, 0x47, 0x3d, 0xe6, 0x59, 0x62, 0x89, 0x5, 0x60, 0x8f, 0xb1, 0x7d, 0x70, 0x6a, 0x9c, 0x20, 0xf1, 0x5e, 0x82, 0x49, 0x5c, 0xff, 0x27, 0x7f, 0xcc, 0x73, 0x1c, 0xd0, 0x6f, 0xe, 0xb4, 0x3b, 0x0, 0x52, 0x3, 0x35, 0x4e, 0x94, 0xa0, 0x37, 0x0, 0x9b, 0xa4, 0x18, 0x37, 0x5e, 0xd2, 0xe8, 0xd3, 0x2d, 0xd7, 0xbd, 0x52, 0x61, 0x3b, 0x97, 0x3b, 0x5c, 0xb9, 0x3, 0x98, 0xb1, 0xa, 0x8c, 0x34, 0xeb, 0x68, 0xef, 0xc2, 0x9f, 0x22, 0xc, 0x4e, 0xf2, 0x80, 0x42, 0xa8, 0x4e, 0xdd, 0x89, 0x8f, 0x50, 0xb4, 0x84, 0x9d, 0xbd, 0xb7, 0x33, 0x6d, 0xc0, 0x7b, 0x9, 0xc8, 0x17, 0xdf, 0x13, 0x4b, 0xca, 0xf3, 0x2f, 0xe, 0x24, 0x69, 0x8e, 0xf7, 0x68, 0x2d, 0x81, 0xfb, 0xa9, 0xfc, 0xe2, 0xbc, 0x73, 0xdc, 0x51, 0x7c, 0x1d, 0x9, 0xdd, 0x1, 0x72, 0xb6, 0x59, 0x1, 0x26, 0xe, 0xc2, 0xb8, 0x85, 0xf7, 0xe, 0xd8, 0x71, 0xe2, 0x9e, 0x6e, 0xae, 0x8e, 0x18, 0x2d, 0x0, 0x9, 0x1f, 0xd2, 0xbd, 0x17, 0xb4, 0x14, 0xc2, 0xc7, 0x29, 0x2, 0x33, 0x9f, 0x1c, 0xc5, 0xbc, 0x3, 0x5b, 0x9, 0x8c, 0xf9, 0xe2, 0x80, 0xff, 0xa0, 0x3, 0x53, 0x27, 0xe1, 0x6e, 0xac, 0x26, 0x3d, 0x60, 0x2d, 0x37, 0x36, 0xb9, 0x26, 0xc7, 0xa3, 0xd9, 0x9a, 0x2e, 0xea, 0xa7, 0x7a, 0x3, 0x38, 0x8, 0x23, 0xb8, 0x25, 0x51, 0x3a, 0xfb, 0xc3, 0x5c, 0x2c, 0x0, 0xf0, 0x69, 0xa, 0xce, 0x8f, 0x47, 0x5b, 0x18, 0x7f, 0x9f, 0x46, 0x3, 0x6f, 0x73, 0xff, 0xb5, 0x4, 0x26, 0xf5, 0x62, 0x1f, 0x43, 0xbc, 0x81, 0xa4, 0x3f, 0x12, 0xeb, 0x18, 0xd2, 0x74, 0x37, 0xf6, 0xe8, 0xcb, 0x1f, 0xa2, 0x88, 0x3d, 0x16, 0x1e, 0xed, 0x25, 0x38, 0xc5, 0x5e, 0x82, 0xd3, 0x2d, 0x13, 0x89, 0x25, 0x74, 0x47, 0xf0, 0xfb, 0x9e, 0xf1, 0x32, 0x86, 0x29, 0xc6, 0xe2, 0x0, 0xd, 0xae, 0x1f, 0x1d, 0x30, 0x9, 0x2d, 0xf6, 0x47, 0xcd, 0xc8, 0x23, 0x3e, 0x4c, 0x41, 0x77, 0x53, 0xae, 0x2f, 0x0, 0xbe, 0x97, 0xc0, 0xb7, 0xbd, 0xfb, 0x8, 0x76, 0x20, 0x56, 0x80, 0x50, 0x32, 0x5f, 0x46, 0x12, 0x68, 0xf6, 0x24, 0xa1, 0xb5, 0xf9, 0xd7, 0x9f, 0x25, 0xc9, 0x9c, 0x75, 0x81, 0x1b, 0x3e, 0x4f, 0xc1, 0xe8, 0x24, 0x16, 0x42, 0xd2, 0x40, 0x1c, 0xd9, 0xb6, 0x26, 0xc, 0xa4, 0x58, 0x1b, 0x70, 0x3e, 0x2c, 0x0, 0xdd, 0xb8, 0x8a, 0x76, 0x73, 0x5d, 0x57, 0x32, 0xc9, 0x45, 0xfe, 0x23, 0x3a, 0x2c, 0x8, 0x52, 0x32, 0xef, 0x0, 0xdd, 0x7e, 0x9d, 0xd9, 0xbe, 0xc6, 0xe5, 0xbe, 0xd6, 0x31, 0x1c, 0x88, 0x16, 0xad, 0xa2, 0x74, 0xd1, 0xae, 0x24, 0x95, 0xc4, 0xad, 0x6, 0xb, 0x0, 0x59, 0x1c, 0x67, 0xe7, 0x5c, 0x33, 0x6b, 0xef, 0x25, 0x68, 0x37, 0x58, 0xa8, 0x5, 0xfa, 0x17, 0x28, 0xaa, 0x1a, 0xa9, 0x96, 0x46, 0x77, 0x1c, 0xf8, 0x16, 0x71, 0xa0, 0x2f, 0xfc, 0x5a, 0xe7, 0x5d, 0x6b, 0x13, 0x76, 0x73, 0x89, 0x38, 0x72, 0x35, 0x1, 0x10, 0xfa, 0x9, 0x20, 0xe, 0xa4, 0xa9, 0x9f, 0xba, 0xc6, 0x5, 0x2f, 0x0, 0x6d, 0x43, 0x77, 0x6c, 0xab, 0x66, 0x6c, 0xa7, 0x7f, 0x73, 0x60, 0x77, 0x21, 0xe7, 0xf7, 0x53, 0x36, 0x75, 0x2, 0xfc, 0x37, 0x96, 0x15, 0xd1, 0x28, 0xc6, 0xff, 0x65, 0xa0, 0xd, 0x60, 0x2, 0x63, 0x4, 0x0, 0xf5, 0x8e, 0x13, 0x81, 0xf4, 0x3c, 0x86, 0x81, 0x1, 0x49, 0x0, 0x33, 0xd4, 0x35, 0xaa, 0x8d, 0x7e, 0xfe, 0xa5, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
-};
-
-static const unsigned char tree_cursor_png[] = {
- 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0xe, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x96, 0xdd, 0xe3, 0x0, 0x0, 0x0, 0xc3, 0x50, 0x4c, 0x54, 0x45, 0xd4, 0xab, 0x9e, 0xd3, 0xaa, 0x9d, 0xd4, 0xab, 0x9e, 0xd3, 0xaa, 0x9d, 0xd4, 0xab, 0x9c, 0xd4, 0xac, 0x9e, 0xd5, 0xaf, 0xa3, 0xd5, 0xb0, 0xa3, 0xd5, 0xaf, 0xa3, 0xd5, 0xad, 0xa1, 0xd5, 0xaf, 0xa3, 0xd5, 0xad, 0xa1, 0xd5, 0xb0, 0xa3, 0xd6, 0xad, 0xa0, 0xd6, 0xad, 0xa0, 0xd5, 0xb0, 0xa3, 0xd7, 0xb1, 0xa5, 0xd7, 0xb1, 0xa7, 0xd7, 0xb1, 0xa7, 0xd7, 0xb1, 0xa7, 0xd7, 0xb1, 0xa7, 0xd7, 0xb1, 0xa5, 0xd7, 0xb1, 0xa5, 0xd8, 0xb3, 0xa8, 0xd8, 0xb5, 0xaa, 0xda, 0xb3, 0xa8, 0xda, 0xb3, 0xa8, 0xd8, 0xb3, 0xa8, 0xd8, 0xb5, 0xaa, 0xda, 0xb3, 0xa8, 0xd8, 0xb3, 0xa8, 0xdb, 0xb7, 0xad, 0xda, 0xb8, 0xae, 0xdb, 0xb9, 0xad, 0xdb, 0xb9, 0xad, 0xdb, 0xb7, 0xad, 0xdd, 0xba, 0xb1, 0xdd, 0xbb, 0xb1, 0xdd, 0xbd, 0xb1, 0xdd, 0xbf, 0xb3, 0xdd, 0xbd, 0xb3, 0xdf, 0xc1, 0xb7, 0xdf, 0xc0, 0xb5, 0xdf, 0xbf, 0xb5, 0xe1, 0xc3, 0xb9, 0xe1, 0xc3, 0xbb, 0xe1, 0xc5, 0xbb, 0xe2, 0xc7, 0xbe, 0xe1, 0xc5, 0xbd, 0xe4, 0xcb, 0xc2, 0xe3, 0xca, 0xc1, 0xe3, 0xcb, 0xc3, 0xe6, 0xce, 0xc6, 0xe6, 0xd0, 0xc6, 0xe8, 0xd1, 0xca, 0xe8, 0xd1, 0xca, 0xe8, 0xd0, 0xca, 0xe8, 0xcf, 0xca, 0xb7, 0x7d, 0x69, 0xb1, 0x77, 0x63, 0xac, 0x73, 0x5c, 0xa6, 0x69, 0x56, 0x9c, 0x67, 0x54, 0x93, 0x62, 0x51, 0x88, 0x60, 0x50, 0x9e, 0xe4, 0xa3, 0x87, 0x0, 0x0, 0x0, 0x3a, 0x74, 0x52, 0x4e, 0x53, 0x32, 0x2f, 0x30, 0x33, 0x38, 0x40, 0x32, 0x2f, 0x2f, 0x2f, 0x31, 0x33, 0x33, 0x33, 0x36, 0x38, 0x31, 0x2f, 0x30, 0x31, 0x33, 0x33, 0x35, 0x2f, 0x2f, 0x2f, 0x30, 0x32, 0x33, 0x33, 0x33, 0x2f, 0x2f, 0x2f, 0x30, 0x30, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x32, 0x2f, 0x2f, 0x2f, 0xb8, 0xf, 0x95, 0x41, 0x0, 0x0, 0x0, 0x64, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x4d, 0xc9, 0x1, 0xa, 0x2, 0x31, 0xc, 0x44, 0xd1, 0xff, 0xdb, 0xec, 0x2a, 0x1e, 0x48, 0xc0, 0xfb, 0x7b, 0x2c, 0x3b, 0x96, 0x2c, 0x88, 0x3, 0x19, 0x78, 0x19, 0x5f, 0xfc, 0xa7, 0x7c, 0xb, 0x78, 0xd5, 0xb3, 0x3c, 0x45, 0xf5, 0xea, 0xf2, 0x21, 0xb4, 0xc2, 0xd8, 0xbc, 0x19, 0xcd, 0xb0, 0xab, 0xbc, 0x83, 0xa4, 0x1f, 0x6c, 0x1e, 0x82, 0xca, 0x67, 0x2c, 0x2d, 0xe, 0x25, 0x31, 0x67, 0x6a, 0x51, 0x99, 0xc0, 0xc8, 0xbe, 0x35, 0xcc, 0x45, 0xc, 0xca, 0xdc, 0x1c, 0x6, 0x70, 0x8f, 0xa1, 0xd7, 0x36, 0x13, 0xe8, 0xb5, 0x6d, 0x18, 0x6b, 0xb3, 0xf8, 0x65, 0xe6, 0xb, 0x36, 0x5c, 0x24, 0xde, 0x86, 0x96, 0x3a, 0xaf, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
-};
-
-static const unsigned char tree_cursor_unfocus_png[] = {
- 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0xe, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x96, 0xdd, 0xe3, 0x0, 0x0, 0x0, 0x96, 0x50, 0x4c, 0x54, 0x45, 0xc0, 0xb5, 0xb2, 0xbf, 0xb4, 0xb1, 0xc0, 0xb5, 0xb2, 0xbf, 0xb4, 0xb1, 0xbf, 0xb5, 0xb1, 0xc0, 0xb5, 0xb2, 0xc3, 0xb8, 0xb5, 0xc3, 0xb8, 0xb5, 0xc2, 0xb7, 0xb4, 0xc3, 0xb8, 0xb5, 0xc2, 0xb7, 0xb4, 0xc3, 0xb8, 0xb5, 0xc2, 0xb7, 0xb4, 0xc3, 0xb8, 0xb5, 0xc5, 0xba, 0xb7, 0xc5, 0xbc, 0xb9, 0xc5, 0xbc, 0xb9, 0xc5, 0xbc, 0xb9, 0xc5, 0xbc, 0xb9, 0xc5, 0xba, 0xb7, 0xc5, 0xba, 0xb7, 0xc6, 0xbd, 0xba, 0xc7, 0xbe, 0xbb, 0xc7, 0xbe, 0xbb, 0xc6, 0xbd, 0xba, 0xc7, 0xbe, 0xbb, 0xc6, 0xbd, 0xba, 0xca, 0xc1, 0xbe, 0xca, 0xc1, 0xbe, 0xcd, 0xc4, 0xc1, 0xcd, 0xc6, 0xc3, 0xd0, 0xc9, 0xc6, 0xcf, 0xc8, 0xc5, 0xd2, 0xcb, 0xc8, 0xd3, 0xcb, 0xc9, 0xd3, 0xcc, 0xc9, 0xd5, 0xcd, 0xcb, 0xd4, 0xcc, 0xca, 0xd7, 0xd1, 0xcf, 0xd6, 0xd0, 0xce, 0xda, 0xd4, 0xd2, 0xdd, 0xd7, 0xd5, 0xdd, 0xd7, 0xd5, 0x9a, 0x8b, 0x86, 0x94, 0x85, 0x80, 0x8e, 0x80, 0x7a, 0x88, 0x79, 0x74, 0x81, 0x75, 0x6f, 0x7a, 0x6f, 0x6a, 0x73, 0x69, 0x65, 0x9a, 0x51, 0xd2, 0xe3, 0x0, 0x0, 0x0, 0x2b, 0x74, 0x52, 0x4e, 0x53, 0x32, 0x2f, 0x30, 0x33, 0x38, 0x40, 0x32, 0x2f, 0x2f, 0x31, 0x33, 0x33, 0x36, 0x38, 0x31, 0x2f, 0x30, 0x31, 0x33, 0x33, 0x35, 0x2f, 0x2f, 0x30, 0x32, 0x33, 0x33, 0x2f, 0x30, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x32, 0x2f, 0x82, 0xd8, 0x8a, 0x2f, 0x0, 0x0, 0x0, 0x5f, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x62, 0xd1, 0x66, 0x40, 0x6, 0x2c, 0x8c, 0x57, 0x0, 0x2d, 0xc9, 0x87, 0x15, 0x4, 0x51, 0x8, 0x42, 0xd1, 0x7, 0x13, 0x3b, 0xd9, 0xfe, 0x1b, 0x1c, 0x16, 0xcf, 0xf, 0xa6, 0xab, 0x6a, 0xd3, 0x2a, 0xbf, 0x53, 0xb7, 0x66, 0xa8, 0x63, 0xe9, 0xd4, 0xbb, 0x88, 0x82, 0xcb, 0x47, 0xd9, 0xb, 0x54, 0xde, 0xec, 0x57, 0x97, 0xde, 0x63, 0x94, 0x12, 0xab, 0xec, 0xec, 0x56, 0xce, 0x69, 0x28, 0xc8, 0x9f, 0xbf, 0x9c, 0x39, 0xd8, 0x16, 0x47, 0x69, 0x65, 0xc, 0xe, 0xc3, 0x8e, 0xeb, 0x69, 0x28, 0x1, 0x0, 0xb0, 0xae, 0x0, 0x0, 0x90, 0x3f, 0xa6, 0x5b, 0x1b, 0xad, 0x12, 0x69, 0xd7, 0x5c, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
-};
-
static const unsigned char tree_title_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x1, 0x3, 0x0, 0x0, 0x0, 0x25, 0x3d, 0x6d, 0x22, 0x0, 0x0, 0x0, 0x6, 0x50, 0x4c, 0x54, 0x45, 0x25, 0x23, 0x25, 0x4c, 0x4a, 0x4e, 0x1, 0xf9, 0x98, 0x2e, 0x0, 0x0, 0x0, 0xb, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x20, 0x11, 0x0, 0x0, 0x0, 0x30, 0x0, 0x1, 0x6e, 0xa6, 0xf, 0x3f, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
diff --git a/scene/resources/default_theme/tool_button_pressed.png b/scene/resources/default_theme/tool_button_pressed.png
deleted file mode 100644
index 5494475792..0000000000
--- a/scene/resources/default_theme/tool_button_pressed.png
+++ /dev/null
Binary files differ
diff --git a/scene/resources/default_theme/tree_bg_focus.png b/scene/resources/default_theme/tree_bg_focus.png
deleted file mode 100644
index aadc6b0db4..0000000000
--- a/scene/resources/default_theme/tree_bg_focus.png
+++ /dev/null
Binary files differ
diff --git a/scene/resources/default_theme/tree_cursor.png b/scene/resources/default_theme/tree_cursor.png
deleted file mode 100644
index 2b8722d066..0000000000
--- a/scene/resources/default_theme/tree_cursor.png
+++ /dev/null
Binary files differ
diff --git a/scene/resources/default_theme/tree_cursor_unfocus.png b/scene/resources/default_theme/tree_cursor_unfocus.png
deleted file mode 100644
index bfaebbea85..0000000000
--- a/scene/resources/default_theme/tree_cursor_unfocus.png
+++ /dev/null
Binary files differ
diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp
index 66e2429bd0..fc75fda583 100644
--- a/servers/visual/visual_server_canvas.cpp
+++ b/servers/visual/visual_server_canvas.cpp
@@ -49,13 +49,14 @@ void VisualServerCanvas::_render_canvas_item_tree(Item *p_canvas_item, const Tra
}
}
-void _collect_ysort_children(VisualServerCanvas::Item *p_canvas_item, Transform2D p_transform, VisualServerCanvas::Item *p_material_owner, VisualServerCanvas::Item **r_items, int &r_index) {
+void _collect_ysort_children(VisualServerCanvas::Item *p_canvas_item, Transform2D p_transform, VisualServerCanvas::Item *p_material_owner, const Color p_modulate, VisualServerCanvas::Item **r_items, int &r_index) {
int child_item_count = p_canvas_item->child_items.size();
VisualServerCanvas::Item **child_items = p_canvas_item->child_items.ptrw();
for (int i = 0; i < child_item_count; i++) {
if (child_items[i]->visible) {
if (r_items) {
r_items[r_index] = child_items[i];
+ child_items[i]->ysort_modulate = p_modulate;
child_items[i]->ysort_xform = p_transform;
child_items[i]->ysort_pos = p_transform.xform(child_items[i]->xform.elements[2]);
child_items[i]->material_owner = child_items[i]->use_parent_material ? p_material_owner : NULL;
@@ -64,7 +65,11 @@ void _collect_ysort_children(VisualServerCanvas::Item *p_canvas_item, Transform2
r_index++;
if (child_items[i]->sort_y)
- _collect_ysort_children(child_items[i], p_transform * child_items[i]->xform, child_items[i]->use_parent_material ? p_material_owner : child_items[i], r_items, r_index);
+ _collect_ysort_children(child_items[i],
+ p_transform * child_items[i]->xform,
+ child_items[i]->use_parent_material ? p_material_owner : child_items[i],
+ p_modulate * child_items[i]->modulate,
+ r_items, r_index);
}
}
}
@@ -125,14 +130,14 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor
if (ci->ysort_children_count == -1) {
ci->ysort_children_count = 0;
- _collect_ysort_children(ci, Transform2D(), p_material_owner, NULL, ci->ysort_children_count);
+ _collect_ysort_children(ci, Transform2D(), p_material_owner, Color(1, 1, 1, 1), NULL, ci->ysort_children_count);
}
child_item_count = ci->ysort_children_count;
child_items = (Item **)alloca(child_item_count * sizeof(Item *));
int i = 0;
- _collect_ysort_children(ci, Transform2D(), p_material_owner, child_items, i);
+ _collect_ysort_children(ci, Transform2D(), p_material_owner, Color(1, 1, 1, 1), child_items, i);
SortArray<Item *, ItemPtrSort> sorter;
sorter.sort(child_items, child_item_count);
@@ -148,7 +153,7 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor
if (!child_items[i]->behind || (ci->sort_y && child_items[i]->sort_y))
continue;
if (ci->sort_y) {
- _render_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner);
+ _render_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate * child_items[i]->ysort_modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner);
} else {
_render_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner);
}
@@ -190,7 +195,7 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor
if (child_items[i]->behind || (ci->sort_y && child_items[i]->sort_y))
continue;
if (ci->sort_y) {
- _render_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner);
+ _render_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate * child_items[i]->ysort_modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner);
} else {
_render_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner);
}
diff --git a/servers/visual/visual_server_canvas.h b/servers/visual/visual_server_canvas.h
index 28a8770c90..822e3f8ce3 100644
--- a/servers/visual/visual_server_canvas.h
+++ b/servers/visual/visual_server_canvas.h
@@ -49,6 +49,7 @@ public:
int index;
bool children_order_dirty;
int ysort_children_count;
+ Color ysort_modulate;
Transform2D ysort_xform;
Vector2 ysort_pos;
diff --git a/thirdparty/README.md b/thirdparty/README.md
index 9738716221..dbdf9bbf4f 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -262,32 +262,17 @@ changes to ensure they build for Javascript/HTML5. Those
changes are marked with `// -- GODOT --` comments.
-## libwebsockets
-
-- Upstream: https://github.com/warmcat/libwebsockets
-- Version: 3.0.1
-- License: LGPLv2.1 + static linking exception
-
-File extracted from upstream source:
-- From `lib/` into `thirdparty/libwebsockets`:
- - Everything from `core`
- - From `event-libs` only the `poll` subfolder
- - From `misc` only `base64-decode.c`, `getifaddrs.c`, `getifaddrs.h`, `lejp.c`, and `sha-1.c`
- - From `plat` only `lws-plat-unix.c` and `lws-plat-win.c`
- - From `roles` only `private.h`, `h1`, `http`, `listen`, `pipe`, `raw`, `ws`
- - From `roles/http` exclude `minilex.c`
- - From `roles/http/server` exclude `access-log.c`, `lws-spa.c`, `ranges.c`, and `rewrite.c`
- - From `roles/ws` exclude `ext` folder.
- - From `tls` exclude `openssl` folder.
-- Also copy `win32helpers/` from `win32port/` inside `thirdparty/libwebsockets`
-- A fix has been added to allow building for 32-bits UWP, replacing `GetFileSize[Ex]` and `CreateFileW` with supported functions.
- There is a diff for this change in `thirdparty/libwebsockets/uwp_fixes.diff`
-- A fix to disable V6ONLY flag from IPv6 sockets (on by default on some systems) has been also applied.
- The diff for this change can be found in `thirdparty/libwebsockets/ipv6_fixes.diff`
-
-Important: `lws_config.h` and `lws_config_private.h` contains custom
-Godot build configurations, check them out when updating.
+## wslay
+- Upstream: https://github.com/tatsuhiro-t/wslay
+- Version: 1.1.0
+- License: MIT
+
+File extracted from upstream releaze tarball:
+
+- All `*.c` and `*.h` in `lib/` and `lib/includes/`
+- `wslay.h` has a small Godot addition to fix MSVC build.
+ See `thirdparty/wslay/msvcfix.diff`
## mbedtls
diff --git a/thirdparty/libwebsockets/LICENSE b/thirdparty/libwebsockets/LICENSE
deleted file mode 100644
index 6c7cd90cdc..0000000000
--- a/thirdparty/libwebsockets/LICENSE
+++ /dev/null
@@ -1,556 +0,0 @@
-Libwebsockets and included programs are provided under the terms of the GNU
-Library General Public License (LGPL) 2.1, with the following exceptions:
-
-1) Any reference, whether in these modifications or in the GNU
-Library General Public License 2.1, to this License, these terms, the
-GNU Lesser Public License, GNU Library General Public License, LGPL, or
-any similar reference shall refer to the GNU Library General Public
-License 2.1 as modified by these paragraphs 1) through 4).
-
-2) Static linking of programs with the libwebsockets library does not
-constitute a derivative work and does not require the author to provide
-source code for the program, use the shared libwebsockets libraries, or
-link their program against a user-supplied version of libwebsockets.
-
-If you link the program to a modified version of libwebsockets, then the
-changes to libwebsockets must be provided under the terms of the LGPL in
-sections 1, 2, and 4.
-
-3) You do not have to provide a copy of the libwebsockets license with
-programs that are linked to the libwebsockets library, nor do you have to
-identify the libwebsockets license in your program or documentation as
-required by section 6 of the LGPL.
-
-However, programs must still identify their use of libwebsockets. The
-following example statement can be included in user documentation to
-satisfy this requirement:
-
-"[program] is based in part on the work of the libwebsockets project
-(https://libwebsockets.org)"
-
-4) Some sources included have their own, more liberal licenses, or options
-to get original sources with the liberal terms.
-
-Original liberal license retained
-
- - lib/misc/sha-1.c - 3-clause BSD license retained, link to original
- - win32port/zlib - ZLIB license (see zlib.h)
- - lib/tls/mbedtls/wrapper - Apache 2.0 (only built if linked against mbedtls)
-
-Relicensed to libwebsocket license
-
- - lib/misc/base64-decode.c - relicensed to LGPL2.1+SLE, link to original
- - lib/misc/daemonize.c - relicensed from Public Domain to LGPL2.1+SLE,
- link to original Public Domain version
-
-Public Domain (CC-zero) to simplify reuse
-
- - test-apps/*.c
- - test-apps/*.h
- - minimal-examples/*
- - lwsws/*
-
------- end of exceptions
-
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 2.1, February 1999
-
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the Lesser GPL. It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
- This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it. You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations below.
-
- When we speak of free software, we are referring to freedom of use,
-not price. Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
-
- To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights. These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
- For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you. You must make sure that they, too, receive or can get the source
-code. If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it. And you must show them these terms so they know their rights.
-
- We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
- To protect each distributor, we want to make it very clear that
-there is no warranty for the free library. Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-
- Finally, software patents pose a constant threat to the existence of
-any free program. We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder. Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
-
- Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License. This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License. We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
-
- When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library. The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom. The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
-
- We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License. It also provides other free software developers Less
-of an advantage over competing non-free programs. These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries. However, the Lesser license provides advantages in certain
-special circumstances.
-
- For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it becomes
-a de-facto standard. To achieve this, non-free programs must be
-allowed to use the library. A more frequent case is that a free
-library does the same job as widely used non-free libraries. In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
-
- In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software. For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
-
- Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
-
- The precise terms and conditions for copying, distribution and
-modification follow. Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library". The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-
- GNU LESSER GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
-
- A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
- The "Library", below, refers to any such software library or work
-which has been distributed under these terms. A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language. (Hereinafter, translation is
-included without limitation in the term "modification".)
-
- "Source code" for a work means the preferred form of the work for
-making modifications to it. For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
- Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it). Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
- 1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
- You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
- 2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) The modified work must itself be a software library.
-
- b) You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
-
- c) You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
-
- d) If a facility in the modified Library refers to a function or a
- table of data to be supplied by an application program that uses
- the facility, other than as an argument passed when the facility
- is invoked, then you must make a good faith effort to ensure that,
- in the event an application does not supply such function or
- table, the facility still operates, and performs whatever part of
- its purpose remains meaningful.
-
- (For example, a function in a library to compute square roots has
- a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function must
- be optional: if the application does not supply it, the square
- root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library. To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License. (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.) Do not make any other change in
-these notices.
-
- Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
- This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
- 4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
- If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library". Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
- However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library". The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
- When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library. The
-threshold for this to be true is not precisely defined by law.
-
- If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work. (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
- Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
- 6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
- You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License. You must supply a copy of this License. If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License. Also, you must do one
-of these things:
-
- a) Accompany the work with the complete corresponding
- machine-readable source code for the Library including whatever
- changes were used in the work (which must be distributed under
- Sections 1 and 2 above); and, if the work is an executable linked
- with the Library, with the complete machine-readable "work that
- uses the Library", as object code and/or source code, so that the
- user can modify the Library and then relink to produce a modified
- executable containing the modified Library. (It is understood
- that the user who changes the contents of definitions files in the
- Library will not necessarily be able to recompile the application
- to use the modified definitions.)
-
- b) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (1) uses at run time a
- copy of the library already present on the user's computer system,
- rather than copying library functions into the executable, and (2)
- will operate properly with a modified version of the library, if
- the user installs one, as long as the modified version is
- interface-compatible with the version that the work was made with.
-
- c) Accompany the work with a written offer, valid for at
- least three years, to give the same user the materials
- specified in Subsection 6a, above, for a charge no more
- than the cost of performing this distribution.
-
- d) If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the above
- specified materials from the same place.
-
- e) Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
-
- For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it. However, as a special exception,
-the materials to be distributed need not include anything that is
-normally distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
- It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system. Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
- 7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
- a) Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- Sections above.
-
- b) Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same work.
-
- 8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License. Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License. However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
- 9. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Library or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
- 10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties with
-this License.
-
- 11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all. For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded. In such case, this License incorporates the limitation as if
-written in the body of this License.
-
- 13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation. If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
- 14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission. For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this. Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
- NO WARRANTY
-
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Libraries
-
- If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change. You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
- To apply these terms, attach the following notices to the library. It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
- <one line to give the library's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the
- library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
- <signature of Ty Coon>, 1 April 1990
- Ty Coon, President of Vice
-
-That's all there is to it!
diff --git a/thirdparty/libwebsockets/core/alloc.c b/thirdparty/libwebsockets/core/alloc.c
deleted file mode 100644
index f169fc3767..0000000000
--- a/thirdparty/libwebsockets/core/alloc.c
+++ /dev/null
@@ -1,92 +0,0 @@
-#include "core/private.h"
-
-#if defined(LWS_PLAT_OPTEE)
-
-#define TEE_USER_MEM_HINT_NO_FILL_ZERO 0x80000000
-
-void *__attribute__((weak))
- TEE_Malloc(uint32_t size, uint32_t hint)
-{
- return NULL;
-}
-void *__attribute__((weak))
- TEE_Realloc(void *buffer, uint32_t newSize)
-{
- return NULL;
-}
-void __attribute__((weak))
- TEE_Free(void *buffer)
-{
-}
-
-void *lws_realloc(void *ptr, size_t size, const char *reason)
-{
- return TEE_Realloc(ptr, size);
-}
-
-void *lws_malloc(size_t size, const char *reason)
-{
- return TEE_Malloc(size, TEE_USER_MEM_HINT_NO_FILL_ZERO);
-}
-
-void lws_free(void *p)
-{
- TEE_Free(p);
-}
-
-void *lws_zalloc(size_t size, const char *reason)
-{
- void *ptr = TEE_Malloc(size, TEE_USER_MEM_HINT_NO_FILL_ZERO);
- if (ptr)
- memset(ptr, 0, size);
- return ptr;
-}
-
-void lws_set_allocator(void *(*cb)(void *ptr, size_t size, const char *reason))
-{
- (void)cb;
-}
-#else
-
-static void *_realloc(void *ptr, size_t size, const char *reason)
-{
- if (size) {
-#if defined(LWS_WITH_ESP32)
- lwsl_notice("%s: size %lu: %s (free heap %d)\n", __func__,
- (unsigned long)size, reason, (unsigned int)esp_get_free_heap_size() - (int)size);
-#else
- lwsl_debug("%s: size %lu: %s\n", __func__,
- (unsigned long)size, reason);
-#endif
-#if defined(LWS_PLAT_OPTEE)
- return (void *)TEE_Realloc(ptr, size);
-#else
- return (void *)realloc(ptr, size);
-#endif
- }
- if (ptr)
- free(ptr);
-
- return NULL;
-}
-
-void *(*_lws_realloc)(void *ptr, size_t size, const char *reason) = _realloc;
-
-void *lws_realloc(void *ptr, size_t size, const char *reason)
-{
- return _lws_realloc(ptr, size, reason);
-}
-
-void *lws_zalloc(size_t size, const char *reason)
-{
- void *ptr = _lws_realloc(NULL, size, reason);
- if (ptr)
- memset(ptr, 0, size);
- return ptr;
-}
-
-void lws_set_allocator(void *(*cb)(void *ptr, size_t size, const char *reason))
-{
- _lws_realloc = cb;
-}
-#endif
diff --git a/thirdparty/libwebsockets/core/context.c b/thirdparty/libwebsockets/core/context.c
deleted file mode 100644
index 7be004df33..0000000000
--- a/thirdparty/libwebsockets/core/context.c
+++ /dev/null
@@ -1,1962 +0,0 @@
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010-2018 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- */
-
-#include "core/private.h"
-
-#ifndef LWS_BUILD_HASH
-#define LWS_BUILD_HASH "unknown-build-hash"
-#endif
-
-const struct lws_role_ops *available_roles[] = {
-#if defined(LWS_ROLE_H2)
- &role_ops_h2,
-#endif
-#if defined(LWS_ROLE_H1)
- &role_ops_h1,
-#endif
-#if defined(LWS_ROLE_WS)
- &role_ops_ws,
-#endif
- NULL
-};
-
-const struct lws_event_loop_ops *available_event_libs[] = {
-#if defined(LWS_WITH_POLL)
- &event_loop_ops_poll,
-#endif
-#if defined(LWS_WITH_LIBUV)
- &event_loop_ops_uv,
-#endif
-#if defined(LWS_WITH_LIBEVENT)
- &event_loop_ops_event,
-#endif
-#if defined(LWS_WITH_LIBEV)
- &event_loop_ops_ev,
-#endif
- NULL
-};
-
-static const char *library_version = LWS_LIBRARY_VERSION " " LWS_BUILD_HASH;
-
-/**
- * lws_get_library_version: get version and git hash library built from
- *
- * returns a const char * to a string like "1.1 178d78c"
- * representing the library version followed by the git head hash it
- * was built from
- */
-LWS_VISIBLE const char *
-lws_get_library_version(void)
-{
- return library_version;
-}
-
-int
-lws_role_call_alpn_negotiated(struct lws *wsi, const char *alpn)
-{
-#if defined(LWS_WITH_TLS)
- if (!alpn)
- return 0;
-
- lwsl_info("%s: '%s'\n", __func__, alpn);
-
- LWS_FOR_EVERY_AVAILABLE_ROLE_START(ar)
- if (ar->alpn && !strcmp(ar->alpn, alpn) && ar->alpn_negotiated)
- return ar->alpn_negotiated(wsi, alpn);
- LWS_FOR_EVERY_AVAILABLE_ROLE_END;
-#endif
- return 0;
-}
-
-static const char * const mount_protocols[] = {
- "http://",
- "https://",
- "file://",
- "cgi://",
- ">http://",
- ">https://",
- "callback://"
-};
-
-LWS_VISIBLE void *
-lws_protocol_vh_priv_zalloc(struct lws_vhost *vhost,
- const struct lws_protocols *prot, int size)
-{
- int n = 0;
-
- /* allocate the vh priv array only on demand */
- if (!vhost->protocol_vh_privs) {
- vhost->protocol_vh_privs = (void **)lws_zalloc(
- vhost->count_protocols * sizeof(void *),
- "protocol_vh_privs");
- if (!vhost->protocol_vh_privs)
- return NULL;
- }
-
- while (n < vhost->count_protocols && &vhost->protocols[n] != prot)
- n++;
-
- if (n == vhost->count_protocols) {
- n = 0;
- while (n < vhost->count_protocols &&
- strcmp(vhost->protocols[n].name, prot->name))
- n++;
-
- if (n == vhost->count_protocols)
- return NULL;
- }
-
- vhost->protocol_vh_privs[n] = lws_zalloc(size, "vh priv");
- return vhost->protocol_vh_privs[n];
-}
-
-LWS_VISIBLE void *
-lws_protocol_vh_priv_get(struct lws_vhost *vhost,
- const struct lws_protocols *prot)
-{
- int n = 0;
-
- if (!vhost || !vhost->protocol_vh_privs || !prot)
- return NULL;
-
- while (n < vhost->count_protocols && &vhost->protocols[n] != prot)
- n++;
-
- if (n == vhost->count_protocols) {
- n = 0;
- while (n < vhost->count_protocols &&
- strcmp(vhost->protocols[n].name, prot->name))
- n++;
-
- if (n == vhost->count_protocols) {
- lwsl_err("%s: unknown protocol %p\n", __func__, prot);
- return NULL;
- }
- }
-
- return vhost->protocol_vh_privs[n];
-}
-
-static const struct lws_protocol_vhost_options *
-lws_vhost_protocol_options(struct lws_vhost *vh, const char *name)
-{
- const struct lws_protocol_vhost_options *pvo = vh->pvo;
-
- if (!name)
- return NULL;
-
- while (pvo) {
- if (!strcmp(pvo->name, name))
- return pvo;
- pvo = pvo->next;
- }
-
- return NULL;
-}
-
-/*
- * inform every vhost that hasn't already done it, that
- * his protocols are initializing
- */
-LWS_VISIBLE int
-lws_protocol_init(struct lws_context *context)
-{
- struct lws_vhost *vh = context->vhost_list;
- const struct lws_protocol_vhost_options *pvo, *pvo1;
- struct lws wsi;
- int n, any = 0;
-
- if (context->doing_protocol_init)
- return 0;
-
- context->doing_protocol_init = 1;
-
- memset(&wsi, 0, sizeof(wsi));
- wsi.context = context;
-
- lwsl_info("%s\n", __func__);
-
- while (vh) {
- wsi.vhost = vh;
-
- /* only do the protocol init once for a given vhost */
- if (vh->created_vhost_protocols ||
- (vh->options & LWS_SERVER_OPTION_SKIP_PROTOCOL_INIT))
- goto next;
-
- /* initialize supported protocols on this vhost */
-
- for (n = 0; n < vh->count_protocols; n++) {
- wsi.protocol = &vh->protocols[n];
- if (!vh->protocols[n].name)
- continue;
- pvo = lws_vhost_protocol_options(vh,
- vh->protocols[n].name);
- if (pvo) {
- /*
- * linked list of options specific to
- * vh + protocol
- */
- pvo1 = pvo;
- pvo = pvo1->options;
-
- while (pvo) {
- lwsl_debug(
- " vhost \"%s\", "
- "protocol \"%s\", "
- "option \"%s\"\n",
- vh->name,
- vh->protocols[n].name,
- pvo->name);
-
- if (!strcmp(pvo->name, "default")) {
- lwsl_info("Setting default "
- "protocol for vh %s to %s\n",
- vh->name,
- vh->protocols[n].name);
- vh->default_protocol_index = n;
- }
- if (!strcmp(pvo->name, "raw")) {
- lwsl_info("Setting raw "
- "protocol for vh %s to %s\n",
- vh->name,
- vh->protocols[n].name);
- vh->raw_protocol_index = n;
- }
- pvo = pvo->next;
- }
-
- pvo = pvo1->options;
- }
-
-#if defined(LWS_WITH_TLS)
- any |= !!vh->tls.ssl_ctx;
-#endif
-
- /*
- * inform all the protocols that they are doing their
- * one-time initialization if they want to.
- *
- * NOTE the wsi is all zeros except for the context, vh
- * + protocol ptrs so lws_get_context(wsi) etc can work
- */
- if (vh->protocols[n].callback(&wsi,
- LWS_CALLBACK_PROTOCOL_INIT, NULL,
- (void *)pvo, 0)) {
- lws_free(vh->protocol_vh_privs[n]);
- vh->protocol_vh_privs[n] = NULL;
- lwsl_err("%s: protocol %s failed init\n", __func__,
- vh->protocols[n].name);
- }
- }
-
- vh->created_vhost_protocols = 1;
-next:
- vh = vh->vhost_next;
- }
-
- context->doing_protocol_init = 0;
-
- if (!context->protocol_init_done)
- lws_finalize_startup(context);
-
- context->protocol_init_done = 1;
-
- if (any)
- lws_tls_check_all_cert_lifetimes(context);
-
- return 0;
-}
-
-LWS_VISIBLE int
-lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
- void *user, void *in, size_t len)
-{
- struct lws_ssl_info *si;
-#ifdef LWS_WITH_CGI
- struct lws_cgi_args *args;
-#endif
-#if defined(LWS_WITH_CGI) || defined(LWS_WITH_HTTP_PROXY)
- char buf[512];
- int n;
-#endif
-
- switch (reason) {
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- case LWS_CALLBACK_HTTP:
-#ifndef LWS_NO_SERVER
- if (lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL))
- return -1;
-
- if (lws_http_transaction_completed(wsi))
-#endif
- return -1;
- break;
-#if !defined(LWS_NO_SERVER)
- case LWS_CALLBACK_HTTP_FILE_COMPLETION:
- if (lws_http_transaction_completed(wsi))
- return -1;
- break;
-#endif
-
- case LWS_CALLBACK_HTTP_WRITEABLE:
-#ifdef LWS_WITH_CGI
- if (wsi->reason_bf & (LWS_CB_REASON_AUX_BF__CGI_HEADERS |
- LWS_CB_REASON_AUX_BF__CGI)) {
- n = lws_cgi_write_split_stdout_headers(wsi);
- if (n < 0) {
- lwsl_debug("AUX_BF__CGI forcing close\n");
- return -1;
- }
- if (!n)
- lws_rx_flow_control(
- wsi->http.cgi->stdwsi[LWS_STDOUT], 1);
-
- if (wsi->reason_bf & LWS_CB_REASON_AUX_BF__CGI_HEADERS)
- wsi->reason_bf &=
- ~LWS_CB_REASON_AUX_BF__CGI_HEADERS;
- else
- wsi->reason_bf &= ~LWS_CB_REASON_AUX_BF__CGI;
- break;
- }
-
- if (wsi->reason_bf & LWS_CB_REASON_AUX_BF__CGI_CHUNK_END) {
- if (!wsi->http2_substream) {
- memcpy(buf + LWS_PRE, "0\x0d\x0a\x0d\x0a", 5);
- lwsl_debug("writing chunk term and exiting\n");
- n = lws_write(wsi, (unsigned char *)buf +
- LWS_PRE, 5, LWS_WRITE_HTTP);
- } else
- n = lws_write(wsi, (unsigned char *)buf +
- LWS_PRE, 0,
- LWS_WRITE_HTTP_FINAL);
-
- /* always close after sending it */
- return -1;
- }
-#endif
-#if defined(LWS_WITH_HTTP_PROXY)
- if (wsi->reason_bf & LWS_CB_REASON_AUX_BF__PROXY) {
- char *px = buf + LWS_PRE;
- int lenx = sizeof(buf) - LWS_PRE;
-
- /*
- * our sink is writeable and our source has something
- * to read. So read a lump of source material of
- * suitable size to send or what's available, whichever
- * is the smaller.
- */
- wsi->reason_bf &= ~LWS_CB_REASON_AUX_BF__PROXY;
- if (!lws_get_child(wsi))
- break;
- if (lws_http_client_read(lws_get_child(wsi), &px,
- &lenx) < 0)
- return -1;
- break;
- }
-#endif
- break;
-
-#if defined(LWS_WITH_HTTP_PROXY)
- case LWS_CALLBACK_RECEIVE_CLIENT_HTTP:
- assert(lws_get_parent(wsi));
- if (!lws_get_parent(wsi))
- break;
- lws_get_parent(wsi)->reason_bf |= LWS_CB_REASON_AUX_BF__PROXY;
- lws_callback_on_writable(lws_get_parent(wsi));
- break;
-
- case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ:
- assert(lws_get_parent(wsi));
- n = lws_write(lws_get_parent(wsi), (unsigned char *)in,
- len, LWS_WRITE_HTTP);
- if (n < 0)
- return -1;
- break;
-
- case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: {
- unsigned char *p, *end;
- char ctype[64], ctlen = 0;
-
- p = (unsigned char *)buf + LWS_PRE;
- end = p + sizeof(buf) - LWS_PRE;
-
- if (lws_add_http_header_status(lws_get_parent(wsi),
- HTTP_STATUS_OK, &p, end))
- return 1;
- if (lws_add_http_header_by_token(lws_get_parent(wsi),
- WSI_TOKEN_HTTP_SERVER,
- (unsigned char *)"libwebsockets",
- 13, &p, end))
- return 1;
-
- ctlen = lws_hdr_copy(wsi, ctype, sizeof(ctype),
- WSI_TOKEN_HTTP_CONTENT_TYPE);
- if (ctlen > 0) {
- if (lws_add_http_header_by_token(lws_get_parent(wsi),
- WSI_TOKEN_HTTP_CONTENT_TYPE,
- (unsigned char *)ctype, ctlen, &p, end))
- return 1;
- }
-
- if (lws_finalize_http_header(lws_get_parent(wsi), &p, end))
- return 1;
-
- *p = '\0';
- n = lws_write(lws_get_parent(wsi),
- (unsigned char *)buf + LWS_PRE,
- p - ((unsigned char *)buf + LWS_PRE),
- LWS_WRITE_HTTP_HEADERS);
- if (n < 0)
- return -1;
-
- break; }
-
-#endif
-
-#ifdef LWS_WITH_CGI
- /* CGI IO events (POLLIN/OUT) appear here, our default policy is:
- *
- * - POST data goes on subprocess stdin
- * - subprocess stdout goes on http via writeable callback
- * - subprocess stderr goes to the logs
- */
- case LWS_CALLBACK_CGI:
- args = (struct lws_cgi_args *)in;
- switch (args->ch) { /* which of stdin/out/err ? */
- case LWS_STDIN:
- /* TBD stdin rx flow control */
- break;
- case LWS_STDOUT:
- /* quench POLLIN on STDOUT until MASTER got writeable */
- lws_rx_flow_control(args->stdwsi[LWS_STDOUT], 0);
- wsi->reason_bf |= LWS_CB_REASON_AUX_BF__CGI;
- /* when writing to MASTER would not block */
- lws_callback_on_writable(wsi);
- break;
- case LWS_STDERR:
- n = lws_get_socket_fd(args->stdwsi[LWS_STDERR]);
- if (n < 0)
- break;
- n = read(n, buf, sizeof(buf) - 2);
- if (n > 0) {
- if (buf[n - 1] != '\n')
- buf[n++] = '\n';
- buf[n] = '\0';
- lwsl_notice("CGI-stderr: %s\n", buf);
- }
- break;
- }
- break;
-
- case LWS_CALLBACK_CGI_TERMINATED:
- lwsl_debug("LWS_CALLBACK_CGI_TERMINATED: %d %" PRIu64 "\n",
- wsi->http.cgi->explicitly_chunked,
- (uint64_t)wsi->http.cgi->content_length);
- if (!wsi->http.cgi->explicitly_chunked &&
- !wsi->http.cgi->content_length) {
- /* send terminating chunk */
- lwsl_debug("LWS_CALLBACK_CGI_TERMINATED: ending\n");
- wsi->reason_bf |= LWS_CB_REASON_AUX_BF__CGI_CHUNK_END;
- lws_callback_on_writable(wsi);
- lws_set_timeout(wsi, PENDING_TIMEOUT_CGI, 3);
- break;
- }
- return -1;
-
- case LWS_CALLBACK_CGI_STDIN_DATA: /* POST body for stdin */
- args = (struct lws_cgi_args *)in;
- args->data[args->len] = '\0';
- n = lws_get_socket_fd(args->stdwsi[LWS_STDIN]);
- if (n < 0)
- return -1;
- n = write(n, args->data, args->len);
- if (n < args->len)
- lwsl_notice("LWS_CALLBACK_CGI_STDIN_DATA: "
- "sent %d only %d went", n, args->len);
- return n;
-#endif
-#endif
- case LWS_CALLBACK_SSL_INFO:
- si = in;
-
- (void)si;
- lwsl_notice("LWS_CALLBACK_SSL_INFO: where: 0x%x, ret: 0x%x\n",
- si->where, si->ret);
- break;
-
- default:
- break;
- }
-
- return 0;
-}
-
-/* list of supported protocols and callbacks */
-
-static const struct lws_protocols protocols_dummy[] = {
- /* first protocol must always be HTTP handler */
-
- {
- "http-only", /* name */
- lws_callback_http_dummy, /* callback */
- 0, /* per_session_data_size */
- 0, /* rx_buffer_size */
- 0, /* id */
- NULL, /* user */
- 0 /* tx_packet_size */
- },
- /*
- * the other protocols are provided by lws plugins
- */
- { NULL, NULL, 0, 0, 0, NULL, 0} /* terminator */
-};
-
-#ifdef LWS_PLAT_OPTEE
-#undef LWS_HAVE_GETENV
-#endif
-
-static void
-lws_vhost_destroy2(struct lws_vhost *vh);
-
-LWS_VISIBLE struct lws_vhost *
-lws_create_vhost(struct lws_context *context,
- const struct lws_context_creation_info *info)
-{
- struct lws_vhost *vh = lws_zalloc(sizeof(*vh), "create vhost"),
- **vh1 = &context->vhost_list;
- const struct lws_http_mount *mounts;
- const struct lws_protocols *pcols = info->protocols;
- 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;
- char buf[20];
-#if !defined(LWS_WITHOUT_CLIENT) && defined(LWS_HAVE_GETENV)
- char *p;
-#endif
- int n;
-
- if (!vh)
- return NULL;
-
-#if LWS_MAX_SMP > 1
- pthread_mutex_init(&vh->lock, NULL);
-#endif
-
- if (!pcols)
- pcols = &protocols_dummy[0];
-
- vh->context = context;
- if (!info->vhost_name)
- vh->name = "default";
- else
- vh->name = info->vhost_name;
-
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- vh->http.error_document_404 = info->error_document_404;
-#endif
-
- if (info->options & LWS_SERVER_OPTION_ONLY_RAW)
- lwsl_info("%s set to only support RAW\n", vh->name);
-
- vh->iface = info->iface;
-#if !defined(LWS_WITH_ESP32) && \
- !defined(OPTEE_TA) && !defined(WIN32)
- vh->bind_iface = info->bind_iface;
-#endif
-
- for (vh->count_protocols = 0;
- pcols[vh->count_protocols].callback;
- vh->count_protocols++)
- ;
-
- vh->options = info->options;
- vh->pvo = info->pvo;
- vh->headers = info->headers;
- vh->user = info->user;
-
- LWS_FOR_EVERY_AVAILABLE_ROLE_START(ar)
- if (ar->init_vhost)
- if (ar->init_vhost(vh, info))
- return NULL;
- LWS_FOR_EVERY_AVAILABLE_ROLE_END;
-
-
- if (info->keepalive_timeout)
- vh->keepalive_timeout = info->keepalive_timeout;
- else
- vh->keepalive_timeout = 5;
-
- if (info->timeout_secs_ah_idle)
- vh->timeout_secs_ah_idle = info->timeout_secs_ah_idle;
- else
- vh->timeout_secs_ah_idle = 10;
-
-#if defined(LWS_WITH_TLS)
-
- vh->tls.alpn = info->alpn;
- vh->tls.ssl_info_event_mask = info->ssl_info_event_mask;
-
- if (info->ecdh_curve)
- lws_strncpy(vh->tls.ecdh_curve, info->ecdh_curve,
- sizeof(vh->tls.ecdh_curve));
-
- /* carefully allocate and take a copy of cert + key paths if present */
- n = 0;
- if (info->ssl_cert_filepath)
- n += (int)strlen(info->ssl_cert_filepath) + 1;
- if (info->ssl_private_key_filepath)
- n += (int)strlen(info->ssl_private_key_filepath) + 1;
-
- if (n) {
- vh->tls.key_path = vh->tls.alloc_cert_path = lws_malloc(n, "vh paths");
- if (info->ssl_cert_filepath) {
- n = (int)strlen(info->ssl_cert_filepath) + 1;
- memcpy(vh->tls.alloc_cert_path, info->ssl_cert_filepath, n);
- vh->tls.key_path += n;
- }
- if (info->ssl_private_key_filepath)
- memcpy(vh->tls.key_path, info->ssl_private_key_filepath,
- strlen(info->ssl_private_key_filepath) + 1);
- }
-#endif
-
- /*
- * 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),
- "vhost-specific plugin table");
- if (!lwsp) {
- lwsl_err("OOM\n");
- return NULL;
- }
-
- m = vh->count_protocols;
- memcpy(lwsp, pcols, 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.
- */
-
- if (context->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++) {
- /*
- * for compatibility's sake, no pvo implies
- * allow all protocols
- */
- if (f || lws_vhost_protocol_options(vh,
- plugin->caps.protocols[n].name)) {
- memcpy(&lwsp[m],
- &plugin->caps.protocols[n],
- sizeof(struct lws_protocols));
- m++;
- vh->count_protocols++;
- }
- }
- plugin = plugin->list;
- }
- }
-#endif
-
- if (
-#ifdef LWS_WITH_PLUGINS
- (context->plugin_list) ||
-#endif
- context->options & LWS_SERVER_OPTION_EXPLICIT_VHOSTS)
- vh->protocols = lwsp;
- else {
- vh->protocols = pcols;
- lws_free(lwsp);
- }
-
- vh->same_vh_protocol_list = (struct lws **)
- lws_zalloc(sizeof(struct lws *) * vh->count_protocols,
- "same vh list");
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- vh->http.mount_list = info->mounts;
-#endif
-
-#ifdef LWS_WITH_UNIX_SOCK
- if (LWS_UNIX_SOCK_ENABLED(context)) {
- lwsl_notice("Creating Vhost '%s' path \"%s\", %d protocols\n",
- vh->name, vh->iface, vh->count_protocols);
- } else
-#endif
- {
- switch(info->port) {
- case CONTEXT_PORT_NO_LISTEN:
- strcpy(buf, "(serving disabled)");
- break;
- case CONTEXT_PORT_NO_LISTEN_SERVER:
- strcpy(buf, "(no listener)");
- break;
- default:
- lws_snprintf(buf, sizeof(buf), "port %u", info->port);
- break;
- }
- lwsl_notice("Creating Vhost '%s' %s, %d protocols, IPv6 %s\n",
- vh->name, buf, vh->count_protocols,
- LWS_IPV6_ENABLED(vh) ? "on" : "off");
- }
- mounts = info->mounts;
- while (mounts) {
- (void)mount_protocols[0];
- lwsl_info(" mounting %s%s to %s\n",
- mount_protocols[mounts->origin_protocol],
- mounts->origin, mounts->mountpoint);
-
- /* convert interpreter protocol names to pointers */
- pvo = mounts->interpret;
- while (pvo) {
- for (n = 0; n < vh->count_protocols; n++) {
- if (strcmp(pvo->value, vh->protocols[n].name))
- continue;
- ((struct lws_protocol_vhost_options *)pvo)->
- value = (const char *)(lws_intptr_t)n;
- break;
- }
- if (n == vh->count_protocols)
- lwsl_err("ignoring unknown interp pr %s\n",
- pvo->value);
- pvo = pvo->next;
- }
-
- mounts = mounts->mount_next;
- }
-
- vh->listen_port = info->port;
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- vh->http.http_proxy_port = 0;
- vh->http.http_proxy_address[0] = '\0';
-#endif
-#if defined(LWS_WITH_SOCKS5)
- vh->socks_proxy_port = 0;
- vh->socks_proxy_address[0] = '\0';
-#endif
-
-#if !defined(LWS_WITHOUT_CLIENT)
- /* either use proxy from info, or try get it from env var */
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- /* http proxy */
- if (info->http_proxy_address) {
- /* override for backwards compatibility */
- if (info->http_proxy_port)
- vh->http.http_proxy_port = info->http_proxy_port;
- lws_set_proxy(vh, info->http_proxy_address);
- } else
-#endif
- {
-#ifdef LWS_HAVE_GETENV
- p = getenv("http_proxy");
- if (p)
- lws_set_proxy(vh, p);
-#endif
- }
-#endif
-#if defined(LWS_WITH_SOCKS5)
- /* socks proxy */
- if (info->socks_proxy_address) {
- /* override for backwards compatibility */
- if (info->socks_proxy_port)
- vh->socks_proxy_port = info->socks_proxy_port;
- lws_set_socks(vh, info->socks_proxy_address);
- } else {
-#ifdef LWS_HAVE_GETENV
- p = getenv("socks_proxy");
- if (p)
- lws_set_socks(vh, p);
-#endif
- }
-#endif
-
- vh->ka_time = info->ka_time;
- vh->ka_interval = info->ka_interval;
- vh->ka_probes = info->ka_probes;
-
- if (vh->options & LWS_SERVER_OPTION_STS)
- lwsl_notice(" STS enabled\n");
-
-#ifdef LWS_WITH_ACCESS_LOG
- if (info->log_filepath) {
- vh->log_fd = lws_open(info->log_filepath,
- O_CREAT | O_APPEND | O_RDWR, 0600);
- if (vh->log_fd == (int)LWS_INVALID_FILE) {
- lwsl_err("unable to open log filepath %s\n",
- info->log_filepath);
- goto bail;
- }
-#ifndef WIN32
- if (context->uid != -1)
- if (chown(info->log_filepath, context->uid,
- context->gid) == -1)
- lwsl_err("unable to chown log file %s\n",
- info->log_filepath);
-#endif
- } else
- vh->log_fd = (int)LWS_INVALID_FILE;
-#endif
- if (lws_context_init_server_ssl(info, vh)) {
- lwsl_err("%s: lws_context_init_server_ssl failed\n", __func__);
- goto bail1;
- }
- if (lws_context_init_client_ssl(info, vh)) {
- lwsl_err("%s: lws_context_init_client_ssl failed\n", __func__);
- goto bail1;
- }
- lws_context_lock(context);
- n = _lws_vhost_init_server(info, vh);
- lws_context_unlock(context);
- if (n < 0) {
- lwsl_err("init server failed\n");
- goto bail1;
- }
-
-
- while (1) {
- if (!(*vh1)) {
- *vh1 = vh;
- break;
- }
- vh1 = &(*vh1)->vhost_next;
- };
-
- /* for the case we are adding a vhost much later, after server init */
-
- if (context->protocol_init_done)
- if (lws_protocol_init(context)) {
- lwsl_err("%s: lws_protocol_init failed\n", __func__);
- goto bail1;
- }
-
- return vh;
-
-bail1:
- lws_vhost_destroy(vh);
- lws_vhost_destroy2(vh);
-
- return NULL;
-
-#ifdef LWS_WITH_ACCESS_LOG
-bail:
- lws_free(vh);
-#endif
-
- return NULL;
-}
-
-LWS_VISIBLE int
-lws_init_vhost_client_ssl(const struct lws_context_creation_info *info,
- struct lws_vhost *vhost)
-{
- struct lws_context_creation_info i;
-
- memcpy(&i, info, sizeof(i));
- i.port = CONTEXT_PORT_NO_LISTEN;
-
- return lws_context_init_client_ssl(&i, vhost);
-}
-
-LWS_VISIBLE void
-lws_cancel_service_pt(struct lws *wsi)
-{
- lws_plat_pipe_signal(wsi);
-}
-
-LWS_VISIBLE void
-lws_cancel_service(struct lws_context *context)
-{
- struct lws_context_per_thread *pt = &context->pt[0];
- short m = context->count_threads;
-
- if (context->being_destroyed1)
- return;
-
- lwsl_info("%s\n", __func__);
-
- while (m--) {
- if (pt->pipe_wsi)
- lws_plat_pipe_signal(pt->pipe_wsi);
- pt++;
- }
-}
-
-int
-lws_create_event_pipes(struct lws_context *context)
-{
- struct lws *wsi;
- int n;
-
- /*
- * Create the pt event pipes... these are unique in that they are
- * not bound to a vhost or protocol (both are NULL)
- */
-
- for (n = 0; n < context->count_threads; n++) {
- if (context->pt[n].pipe_wsi)
- continue;
-
- wsi = lws_zalloc(sizeof(*wsi), "event pipe wsi");
- if (!wsi) {
- lwsl_err("Out of mem\n");
- return 1;
- }
- wsi->context = context;
- lws_role_transition(wsi, 0, LRS_UNCONNECTED, &role_ops_pipe);
- wsi->protocol = NULL;
- wsi->tsi = n;
- wsi->vhost = NULL;
- wsi->event_pipe = 1;
- wsi->desc.sockfd = LWS_SOCK_INVALID;
- context->pt[n].pipe_wsi = wsi;
- context->count_wsi_allocated++;
-
- if (lws_plat_pipe_create(wsi))
- /*
- * platform code returns 0 if it actually created pipes
- * and initialized pt->dummy_pipe_fds[]. If it used
- * some other mechanism outside of signaling in the
- * normal event loop, we skip treating the pipe as
- * related to dummy_pipe_fds[], adding it to the fds,
- * etc.
- */
- continue;
-
- wsi->desc.sockfd = context->pt[n].dummy_pipe_fds[0];
- lwsl_debug("event pipe fd %d\n", wsi->desc.sockfd);
-
- if (context->event_loop_ops->accept)
- context->event_loop_ops->accept(wsi);
-
- if (__insert_wsi_socket_into_fds(context, wsi))
- return 1;
- }
-
- return 0;
-}
-
-void
-lws_destroy_event_pipe(struct lws *wsi)
-{
- lwsl_info("%s\n", __func__);
- __remove_wsi_socket_from_fds(wsi);
-
- if (wsi->context->event_loop_ops->wsi_logical_close) {
- wsi->context->event_loop_ops->wsi_logical_close(wsi);
- lws_plat_pipe_close(wsi);
- return;
- }
-
- if (wsi->context->event_loop_ops->destroy_wsi)
- wsi->context->event_loop_ops->destroy_wsi(wsi);
- lws_plat_pipe_close(wsi);
- wsi->context->count_wsi_allocated--;
- lws_free(wsi);
-}
-
-LWS_VISIBLE struct lws_context *
-lws_create_context(const struct lws_context_creation_info *info)
-{
- struct lws_context *context = NULL;
- struct lws_plat_file_ops *prev;
-#ifndef LWS_NO_DAEMONIZE
- int pid_daemon = get_daemonize_pid();
-#endif
- int n;
-#if defined(__ANDROID__)
- struct rlimit rt;
-#endif
-
-
-
- lwsl_info("Initial logging level %d\n", log_level);
- lwsl_info("Libwebsockets version: %s\n", library_version);
-#if defined(GCC_VER)
- lwsl_info("Compiled with %s\n", GCC_VER);
-#endif
-
-#ifdef LWS_WITH_IPV6
- if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DISABLE_IPV6))
- lwsl_info("IPV6 compiled in and enabled\n");
- else
- lwsl_info("IPV6 compiled in but disabled\n");
-#else
- lwsl_info("IPV6 not compiled in\n");
-#endif
-
- lwsl_info(" LWS_DEF_HEADER_LEN : %u\n", LWS_DEF_HEADER_LEN);
- lwsl_info(" LWS_MAX_PROTOCOLS : %u\n", LWS_MAX_PROTOCOLS);
- lwsl_info(" LWS_MAX_SMP : %u\n", LWS_MAX_SMP);
- lwsl_info(" sizeof (*info) : %ld\n", (long)sizeof(*info));
-#if defined(LWS_WITH_STATS)
- lwsl_info(" LWS_WITH_STATS : on\n");
-#endif
- lwsl_info(" SYSTEM_RANDOM_FILEPATH: '%s'\n", SYSTEM_RANDOM_FILEPATH);
-#if defined(LWS_WITH_HTTP2)
- lwsl_info(" HTTP2 support : available\n");
-#else
- lwsl_info(" HTTP2 support : not configured\n");
-#endif
- if (lws_plat_context_early_init())
- return NULL;
-
- context = lws_zalloc(sizeof(struct lws_context), "context");
- if (!context) {
- lwsl_err("No memory for websocket context\n");
- return NULL;
- }
-
-#if defined(LWS_WITH_TLS)
-#if defined(LWS_WITH_MBEDTLS)
- context->tls_ops = &tls_ops_mbedtls;
-#else
- context->tls_ops = &tls_ops_openssl;
-#endif
-#endif
-
- if (info->pt_serv_buf_size)
- context->pt_serv_buf_size = info->pt_serv_buf_size;
- else
- context->pt_serv_buf_size = 4096;
-
-#if defined(LWS_ROLE_H2)
- role_ops_h2.init_context(context, info);
-#endif
-
-#if LWS_MAX_SMP > 1
- pthread_mutex_init(&context->lock, NULL);
-#endif
-
-#if defined(LWS_WITH_ESP32)
- context->last_free_heap = esp_get_free_heap_size();
-#endif
-
- /* default to just the platform fops implementation */
-
- context->fops_platform.LWS_FOP_OPEN = _lws_plat_file_open;
- context->fops_platform.LWS_FOP_CLOSE = _lws_plat_file_close;
- context->fops_platform.LWS_FOP_SEEK_CUR = _lws_plat_file_seek_cur;
- context->fops_platform.LWS_FOP_READ = _lws_plat_file_read;
- context->fops_platform.LWS_FOP_WRITE = _lws_plat_file_write;
- context->fops_platform.fi[0].sig = NULL;
-
- /*
- * arrange a linear linked-list of fops starting from context->fops
- *
- * platform fops
- * [ -> fops_zip (copied into context so .next settable) ]
- * [ -> info->fops ]
- */
-
- context->fops = &context->fops_platform;
- prev = (struct lws_plat_file_ops *)context->fops;
-
-#if defined(LWS_WITH_ZIP_FOPS)
- /* make a soft copy so we can set .next */
- context->fops_zip = fops_zip;
- prev->next = &context->fops_zip;
- prev = (struct lws_plat_file_ops *)prev->next;
-#endif
-
- /* if user provided fops, tack them on the end of the list */
- if (info->fops)
- prev->next = info->fops;
-
- context->reject_service_keywords = info->reject_service_keywords;
- if (info->external_baggage_free_on_destroy)
- context->external_baggage_free_on_destroy =
- info->external_baggage_free_on_destroy;
-
- context->time_up = time(NULL);
- context->pcontext_finalize = info->pcontext;
-
- context->simultaneous_ssl_restriction =
- info->simultaneous_ssl_restriction;
-
-#ifndef LWS_NO_DAEMONIZE
- if (pid_daemon) {
- context->started_with_parent = pid_daemon;
- lwsl_info(" Started with daemon pid %d\n", pid_daemon);
- }
-#endif
-#if defined(__ANDROID__)
- n = getrlimit ( RLIMIT_NOFILE,&rt);
- if (-1 == n) {
- lwsl_err("Get RLIMIT_NOFILE failed!\n");
- return NULL;
- }
- context->max_fds = rt.rlim_cur;
-#else
- context->max_fds = getdtablesize();
-#endif
-
- if (info->count_threads)
- context->count_threads = info->count_threads;
- else
- context->count_threads = 1;
-
- if (context->count_threads > LWS_MAX_SMP)
- context->count_threads = LWS_MAX_SMP;
-
- context->token_limits = info->token_limits;
-
- context->options = info->options;
-
- /*
- * set the context event loops ops struct
- *
- * after this, all event_loop actions use the generic ops
- */
-
-#if defined(LWS_WITH_POLL)
- context->event_loop_ops = &event_loop_ops_poll;
-#endif
-
- if (lws_check_opt(context->options, LWS_SERVER_OPTION_LIBUV))
-#if defined(LWS_WITH_LIBUV)
- context->event_loop_ops = &event_loop_ops_uv;
-#else
- goto fail_event_libs;
-#endif
-
- if (lws_check_opt(context->options, LWS_SERVER_OPTION_LIBEV))
-#if defined(LWS_WITH_LIBEV)
- context->event_loop_ops = &event_loop_ops_ev;
-#else
- goto fail_event_libs;
-#endif
-
- if (lws_check_opt(context->options, LWS_SERVER_OPTION_LIBEVENT))
-#if defined(LWS_WITH_LIBEVENT)
- context->event_loop_ops = &event_loop_ops_event;
-#else
- goto fail_event_libs;
-#endif
-
- if (!context->event_loop_ops)
- goto fail_event_libs;
-
- lwsl_info("Using event loop: %s\n", context->event_loop_ops->name);
-
-#if defined(LWS_WITH_TLS)
- time(&context->tls.last_cert_check_s);
- if (info->alpn)
- context->tls.alpn_default = info->alpn;
- else {
- char *p = context->tls.alpn_discovered, first = 1;
-
- LWS_FOR_EVERY_AVAILABLE_ROLE_START(ar) {
- if (ar->alpn) {
- if (!first)
- *p++ = ',';
- p += lws_snprintf(p,
- context->tls.alpn_discovered +
- sizeof(context->tls.alpn_discovered) -
- 2 - p, "%s", ar->alpn);
- first = 0;
- }
- } LWS_FOR_EVERY_AVAILABLE_ROLE_END;
-
- context->tls.alpn_default = context->tls.alpn_discovered;
- }
-
- lwsl_info("Default ALPN advertisment: %s\n", context->tls.alpn_default);
-#endif
-
- if (info->timeout_secs)
- context->timeout_secs = info->timeout_secs;
- else
- context->timeout_secs = AWAITING_TIMEOUT;
-
- context->ws_ping_pong_interval = info->ws_ping_pong_interval;
-
- lwsl_info(" default timeout (secs): %u\n", context->timeout_secs);
-
- if (info->max_http_header_data)
- context->max_http_header_data = info->max_http_header_data;
- else
- if (info->max_http_header_data2)
- context->max_http_header_data =
- info->max_http_header_data2;
- else
- context->max_http_header_data = LWS_DEF_HEADER_LEN;
-
- if (info->max_http_header_pool)
- context->max_http_header_pool = info->max_http_header_pool;
- else
- context->max_http_header_pool = context->max_fds;
-
- if (info->fd_limit_per_thread)
- context->fd_limit_per_thread = info->fd_limit_per_thread;
- else
- context->fd_limit_per_thread = context->max_fds /
- context->count_threads;
-
- /*
- * Allocate the per-thread storage for scratchpad buffers,
- * and header data pool
- */
- for (n = 0; n < context->count_threads; n++) {
- context->pt[n].serv_buf = lws_malloc(context->pt_serv_buf_size,
- "pt_serv_buf");
- if (!context->pt[n].serv_buf) {
- lwsl_err("OOM\n");
- return NULL;
- }
-
- context->pt[n].context = context;
- context->pt[n].tid = n;
-
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- context->pt[n].http.ah_list = NULL;
- context->pt[n].http.ah_pool_length = 0;
-#endif
- lws_pt_mutex_init(&context->pt[n]);
- }
-
- lwsl_info(" Threads: %d each %d fds\n", context->count_threads,
- context->fd_limit_per_thread);
-
- if (!info->ka_interval && info->ka_time > 0) {
- lwsl_err("info->ka_interval can't be 0 if ka_time used\n");
- return NULL;
- }
-
-
-#if defined(LWS_WITH_PEER_LIMITS)
- /* scale the peer hash table according to the max fds for the process,
- * so that the max list depth averages 16. Eg, 1024 fd -> 64,
- * 102400 fd -> 6400
- */
- context->pl_hash_elements =
- (context->count_threads * context->fd_limit_per_thread) / 16;
- context->pl_hash_table = lws_zalloc(sizeof(struct lws_peer *) *
- context->pl_hash_elements, "peer limits hash table");
- context->ip_limit_ah = info->ip_limit_ah;
- context->ip_limit_wsi = info->ip_limit_wsi;
-#endif
-
- lwsl_info(" mem: context: %5lu B (%ld ctx + (%ld thr x %d))\n",
- (long)sizeof(struct lws_context) +
- (context->count_threads * context->pt_serv_buf_size),
- (long)sizeof(struct lws_context),
- (long)context->count_threads,
- context->pt_serv_buf_size);
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- lwsl_info(" mem: http hdr rsvd: %5lu B (%u thr x (%u + %lu) x %u))\n",
- (long)(context->max_http_header_data +
- sizeof(struct allocated_headers)) *
- context->max_http_header_pool * context->count_threads,
- context->count_threads,
- context->max_http_header_data,
- (long)sizeof(struct allocated_headers),
- context->max_http_header_pool);
-#endif
- n = sizeof(struct lws_pollfd) * context->count_threads *
- context->fd_limit_per_thread;
- context->pt[0].fds = lws_zalloc(n, "fds table");
- if (context->pt[0].fds == NULL) {
- lwsl_err("OOM allocating %d fds\n", context->max_fds);
- goto bail;
- }
- lwsl_info(" mem: pollfd map: %5u\n", n);
-
- if (info->server_string) {
- context->server_string = info->server_string;
- context->server_string_len = (short)
- strlen(context->server_string);
- }
-
-#if LWS_MAX_SMP > 1
- /* each thread serves his own chunk of fds */
- for (n = 1; n < (int)info->count_threads; n++)
- context->pt[n].fds = context->pt[n - 1].fds +
- context->fd_limit_per_thread;
-#endif
-
- if (lws_plat_init(context, info))
- goto bail;
-
- if (context->event_loop_ops->init_context)
- if (context->event_loop_ops->init_context(context, info))
- goto bail;
-
-
- if (context->event_loop_ops->init_pt)
- for (n = 0; n < context->count_threads; n++) {
- void *lp = NULL;
-
- if (info->foreign_loops)
- lp = info->foreign_loops[n];
-
- if (context->event_loop_ops->init_pt(context, lp, n))
- goto bail;
- }
-
- if (lws_create_event_pipes(context))
- goto bail;
-
- lws_context_init_ssl_library(info);
-
- context->user_space = info->user;
-
- /*
- * if he's not saying he'll make his own vhosts later then act
- * compatibly and make a default vhost using the data in the info
- */
- if (!lws_check_opt(info->options, LWS_SERVER_OPTION_EXPLICIT_VHOSTS))
- if (!lws_create_vhost(context, info)) {
- lwsl_err("Failed to create default vhost\n");
- for (n = 0; n < context->count_threads; n++)
- lws_free_set_NULL(context->pt[n].serv_buf);
-#if defined(LWS_WITH_PEER_LIMITS)
- lws_free_set_NULL(context->pl_hash_table);
-#endif
- lws_free_set_NULL(context->pt[0].fds);
- lws_plat_context_late_destroy(context);
- lws_free_set_NULL(context);
- return NULL;
- }
-
- lws_context_init_extensions(info, context);
-
- lwsl_info(" mem: per-conn: %5lu bytes + protocol rx buf\n",
- (unsigned long)sizeof(struct lws));
-
- strcpy(context->canonical_hostname, "unknown");
- lws_server_get_canonical_hostname(context, info);
-
- context->uid = info->uid;
- context->gid = info->gid;
-
-#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
- memcpy(context->caps, info->caps, sizeof(context->caps));
- context->count_caps = info->count_caps;
-#endif
-
- /*
- * drop any root privs for this process
- * to listen on port < 1023 we would have needed root, but now we are
- * listening, we don't want the power for anything else
- */
- if (!lws_check_opt(info->options, LWS_SERVER_OPTION_EXPLICIT_VHOSTS))
- lws_plat_drop_app_privileges(info);
-
- /* expedite post-context init (eg, protocols) */
- lws_cancel_service(context);
-
-#if defined(LWS_WITH_SELFTESTS)
- lws_jws_selftest();
-#endif
-
- return context;
-
-bail:
- lws_context_destroy(context);
-
- return NULL;
-
-fail_event_libs:
- lwsl_err("Requested event library support not configured, available:\n");
- {
- const struct lws_event_loop_ops **elops = available_event_libs;
-
- while (*elops) {
- lwsl_err(" - %s\n", (*elops)->name);
- elops++;
- }
- }
- lws_free(context);
-
- return NULL;
-}
-
-LWS_VISIBLE LWS_EXTERN void
-lws_context_deprecate(struct lws_context *context, lws_reload_func cb)
-{
- struct lws_vhost *vh = context->vhost_list, *vh1;
- struct lws *wsi;
-
- /*
- * "deprecation" means disable the context from accepting any new
- * connections and free up listen sockets to be used by a replacement
- * context.
- *
- * Otherwise the deprecated context remains operational, until its
- * number of connected sockets falls to zero, when it is deleted.
- */
-
- /* for each vhost, close his listen socket */
-
- while (vh) {
- wsi = vh->lserv_wsi;
- if (wsi) {
- wsi->socket_is_permanently_unusable = 1;
- lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "ctx deprecate");
- wsi->context->deprecation_pending_listen_close_count++;
- /*
- * other vhosts can share the listen port, they
- * point to the same wsi. So zap those too.
- */
- vh1 = context->vhost_list;
- while (vh1) {
- if (vh1->lserv_wsi == wsi)
- vh1->lserv_wsi = NULL;
- vh1 = vh1->vhost_next;
- }
- }
- vh = vh->vhost_next;
- }
-
- context->deprecated = 1;
- context->deprecation_cb = cb;
-}
-
-LWS_VISIBLE LWS_EXTERN int
-lws_context_is_deprecated(struct lws_context *context)
-{
- return context->deprecated;
-}
-
-void
-lws_vhost_destroy1(struct lws_vhost *vh)
-{
- const struct lws_protocols *protocol = NULL;
- struct lws_context_per_thread *pt;
- int n, m = vh->context->count_threads;
- struct lws_context *context = vh->context;
- struct lws wsi;
-
- lwsl_info("%s\n", __func__);
-
- if (vh->being_destroyed)
- return;
-
- vh->being_destroyed = 1;
-
- /*
- * Are there other vhosts that are piggybacking on our listen socket?
- * If so we need to hand the listen socket off to one of the others
- * so it will remain open. If not, leave it attached to the closing
- * vhost and it will get closed.
- */
-
- if (vh->lserv_wsi)
- lws_start_foreach_ll(struct lws_vhost *, v,
- context->vhost_list) {
- if (v != vh &&
- !v->being_destroyed &&
- v->listen_port == vh->listen_port &&
- ((!v->iface && !vh->iface) ||
- (v->iface && vh->iface &&
- !strcmp(v->iface, vh->iface)))) {
- /*
- * this can only be a listen wsi, which is
- * restricted... it has no protocol or other
- * bindings or states. So we can simply
- * swap it to a vhost that has the same
- * iface + port, but is not closing.
- */
- assert(v->lserv_wsi == NULL);
- v->lserv_wsi = vh->lserv_wsi;
- vh->lserv_wsi = NULL;
- if (v->lserv_wsi)
- v->lserv_wsi->vhost = v;
-
- lwsl_notice("%s: listen skt from %s to %s\n",
- __func__, vh->name, v->name);
- break;
- }
- } lws_end_foreach_ll(v, vhost_next);
-
- /*
- * Forcibly close every wsi assoicated with this vhost. That will
- * include the listen socket if it is still associated with the closing
- * vhost.
- */
-
- while (m--) {
- pt = &context->pt[m];
-
- for (n = 0; (unsigned int)n < context->pt[m].fds_count; n++) {
- struct lws *wsi = wsi_from_fd(context, pt->fds[n].fd);
- if (!wsi)
- continue;
- if (wsi->vhost != vh)
- continue;
-
- lws_close_free_wsi(wsi,
- LWS_CLOSE_STATUS_NOSTATUS_CONTEXT_DESTROY,
- "vh destroy"
- /* no protocol close */);
- n--;
- }
- }
-
- /*
- * destroy any pending timed events
- */
-
- while (vh->timed_vh_protocol_list)
- lws_timed_callback_remove(vh, vh->timed_vh_protocol_list);
-
- /*
- * let the protocols destroy the per-vhost protocol objects
- */
-
- memset(&wsi, 0, sizeof(wsi));
- wsi.context = vh->context;
- wsi.vhost = vh;
- protocol = vh->protocols;
- if (protocol && vh->created_vhost_protocols) {
- n = 0;
- while (n < vh->count_protocols) {
- wsi.protocol = protocol;
- protocol->callback(&wsi, LWS_CALLBACK_PROTOCOL_DESTROY,
- NULL, NULL, 0);
- protocol++;
- n++;
- }
- }
-
- /*
- * remove vhost from context list of vhosts
- */
-
- lws_start_foreach_llp(struct lws_vhost **, pv, context->vhost_list) {
- if (*pv == vh) {
- *pv = vh->vhost_next;
- break;
- }
- } lws_end_foreach_llp(pv, vhost_next);
-
- /* add ourselves to the pending destruction list */
-
- vh->vhost_next = vh->context->vhost_pending_destruction_list;
- vh->context->vhost_pending_destruction_list = vh;
-}
-
-static void
-lws_vhost_destroy2(struct lws_vhost *vh)
-{
- const struct lws_protocols *protocol = NULL;
- struct lws_context *context = vh->context;
- struct lws_deferred_free *df;
- int n;
-
- lwsl_info("%s: %p\n", __func__, vh);
-
- /* if we are still on deferred free list, remove ourselves */
-
- lws_start_foreach_llp(struct lws_deferred_free **, pdf,
- context->deferred_free_list) {
- if ((*pdf)->payload == vh) {
- df = *pdf;
- *pdf = df->next;
- lws_free(df);
- break;
- }
- } lws_end_foreach_llp(pdf, next);
-
- /* remove ourselves from the pending destruction list */
-
- lws_start_foreach_llp(struct lws_vhost **, pv,
- context->vhost_pending_destruction_list) {
- if ((*pv) == vh) {
- *pv = (*pv)->vhost_next;
- break;
- }
- } lws_end_foreach_llp(pv, vhost_next);
-
- /*
- * Free all the allocations associated with the vhost
- */
-
- protocol = vh->protocols;
- if (protocol) {
- n = 0;
- while (n < vh->count_protocols) {
- if (vh->protocol_vh_privs &&
- vh->protocol_vh_privs[n]) {
- lws_free(vh->protocol_vh_privs[n]);
- vh->protocol_vh_privs[n] = NULL;
- }
- protocol++;
- n++;
- }
- }
- if (vh->protocol_vh_privs)
- lws_free(vh->protocol_vh_privs);
- lws_ssl_SSL_CTX_destroy(vh);
- lws_free(vh->same_vh_protocol_list);
-
- if (context->plugin_list ||
- (context->options & LWS_SERVER_OPTION_EXPLICIT_VHOSTS))
- lws_free((void *)vh->protocols);
-
- LWS_FOR_EVERY_AVAILABLE_ROLE_START(ar)
- if (ar->destroy_vhost)
- ar->destroy_vhost(vh);
- LWS_FOR_EVERY_AVAILABLE_ROLE_END;
-
-#ifdef LWS_WITH_ACCESS_LOG
- if (vh->log_fd != (int)LWS_INVALID_FILE)
- close(vh->log_fd);
-#endif
-
-#if defined (LWS_WITH_TLS)
- lws_free_set_NULL(vh->tls.alloc_cert_path);
-#endif
-
-#if LWS_MAX_SMP > 1
- pthread_mutex_destroy(&vh->lock);
-#endif
-
-#if defined(LWS_WITH_UNIX_SOCK)
- if (LWS_UNIX_SOCK_ENABLED(context)) {
- n = unlink(vh->iface);
- if (n)
- lwsl_info("Closing unix socket %s: errno %d\n",
- vh->iface, errno);
- }
-#endif
- /*
- * although async event callbacks may still come for wsi handles with
- * pending close in the case of asycn event library like libuv,
- * they do not refer to the vhost. So it's safe to free.
- */
-
- lwsl_info(" %s: Freeing vhost %p\n", __func__, vh);
-
- memset(vh, 0, sizeof(*vh));
- lws_free(vh);
-}
-
-int
-lws_check_deferred_free(struct lws_context *context, int force)
-{
- struct lws_deferred_free *df;
- time_t now = lws_now_secs();
-
- lws_start_foreach_llp(struct lws_deferred_free **, pdf,
- context->deferred_free_list) {
- if (force ||
- lws_compare_time_t(context, now, (*pdf)->deadline) > 5) {
- df = *pdf;
- *pdf = df->next;
- /* finalize vh destruction */
- lwsl_notice("deferred vh %p destroy\n", df->payload);
- lws_vhost_destroy2(df->payload);
- lws_free(df);
- continue; /* after deletion we already point to next */
- }
- } lws_end_foreach_llp(pdf, next);
-
- return 0;
-}
-
-LWS_VISIBLE void
-lws_vhost_destroy(struct lws_vhost *vh)
-{
- struct lws_deferred_free *df = lws_malloc(sizeof(*df), "deferred free");
-
- if (!df)
- return;
-
- lws_vhost_destroy1(vh);
-
- /* part 2 is deferred to allow all the handle closes to complete */
-
- df->next = vh->context->deferred_free_list;
- df->deadline = lws_now_secs();
- df->payload = vh;
- vh->context->deferred_free_list = df;
-}
-
-/*
- * When using an event loop, the context destruction is in three separate
- * parts. This is to cover both internal and foreign event loops cleanly.
- *
- * - lws_context_destroy() simply starts a soft close of all wsi and
- * related allocations. The event loop continues.
- *
- * As the closes complete in the event loop, reference counting is used
- * to determine when everything is closed. It then calls
- * lws_context_destroy2().
- *
- * - lws_context_destroy2() cleans up the rest of the higher-level logical
- * lws pieces like vhosts. If the loop was foreign, it then proceeds to
- * lws_context_destroy3(). If it the loop is internal, it stops the
- * internal loops and waits for lws_context_destroy() to be called again
- * outside the event loop (since we cannot destroy the loop from
- * within the loop). That will cause lws_context_destroy3() to run
- * directly.
- *
- * - lws_context_destroy3() destroys any internal event loops and then
- * destroys the context itself, setting what was info.pcontext to NULL.
- */
-
-/*
- * destroy the actual context itself
- */
-
-static void
-lws_context_destroy3(struct lws_context *context)
-{
- struct lws_context **pcontext_finalize = context->pcontext_finalize;
- struct lws_context_per_thread *pt;
- int n;
-
- for (n = 0; n < context->count_threads; n++) {
- pt = &context->pt[n];
-
- if (context->event_loop_ops->destroy_pt)
- context->event_loop_ops->destroy_pt(context, n);
-
- lws_free_set_NULL(context->pt[n].serv_buf);
-
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- while (pt->http.ah_list)
- _lws_destroy_ah(pt, pt->http.ah_list);
-#endif
- }
-
- lws_free(context);
- lwsl_info("%s: ctx %p freed\n", __func__, context);
-
- if (pcontext_finalize)
- *pcontext_finalize = NULL;
-}
-
-/*
- * really start destroying things
- */
-
-void
-lws_context_destroy2(struct lws_context *context)
-{
- struct lws_vhost *vh = NULL, *vh1;
-#if defined(LWS_WITH_PEER_LIMITS)
- uint32_t nu;
-#endif
- int n;
-
- lwsl_info("%s: ctx %p\n", __func__, context);
-
- context->being_destroyed2 = 1;
-
- if (context->pt[0].fds)
- lws_free_set_NULL(context->pt[0].fds);
-
- /*
- * free all the per-vhost allocations
- */
-
- vh = context->vhost_list;
- while (vh) {
- vh1 = vh->vhost_next;
- lws_vhost_destroy2(vh);
- vh = vh1;
- }
-
- /* remove ourselves from the pending destruction list */
-
- while (context->vhost_pending_destruction_list)
- /* removes itself from list */
- lws_vhost_destroy2(context->vhost_pending_destruction_list);
-
-
- lws_stats_log_dump(context);
-
- lws_ssl_context_destroy(context);
- lws_plat_context_late_destroy(context);
-
-#if defined(LWS_WITH_PEER_LIMITS)
- for (nu = 0; nu < context->pl_hash_elements; nu++) {
- lws_start_foreach_llp(struct lws_peer **, peer,
- context->pl_hash_table[nu]) {
- struct lws_peer *df = *peer;
- *peer = df->next;
- lws_free(df);
- continue;
- } lws_end_foreach_llp(peer, next);
- }
- lws_free(context->pl_hash_table);
-#endif
-
- if (context->external_baggage_free_on_destroy)
- free(context->external_baggage_free_on_destroy);
-
- lws_check_deferred_free(context, 1);
-
-#if LWS_MAX_SMP > 1
- pthread_mutex_destroy(&context->lock);
-#endif
-
- if (context->event_loop_ops->destroy_context2)
- if (context->event_loop_ops->destroy_context2(context)) {
- context->finalize_destroy_after_internal_loops_stopped = 1;
- return;
- }
-
- if (!context->pt[0].event_loop_foreign)
- for (n = 0; n < context->count_threads; n++)
- if (context->pt[n].inside_service)
- return;
-
- lws_context_destroy3(context);
-}
-
-/*
- * Begin the context takedown
- */
-
-LWS_VISIBLE void
-lws_context_destroy(struct lws_context *context)
-{
- volatile struct lws_foreign_thread_pollfd *ftp, *next;
- volatile struct lws_context_per_thread *vpt;
- struct lws_context_per_thread *pt;
- struct lws_vhost *vh = NULL;
- struct lws wsi;
- int n, m;
-
- if (!context)
- return;
-
- if (context->finalize_destroy_after_internal_loops_stopped) {
- if (context->event_loop_ops->destroy_context2)
- context->event_loop_ops->destroy_context2(context);
-
- lws_context_destroy3(context);
-
- return;
- }
-
- if (context->being_destroyed1) {
- if (!context->being_destroyed2) {
- lws_context_destroy2(context);
-
- return;
- }
- lwsl_info("%s: ctx %p: already being destroyed\n",
- __func__, context);
-
- lws_context_destroy3(context);
- return;
- }
-
- lwsl_info("%s: ctx %p\n", __func__, context);
-
- m = context->count_threads;
- context->being_destroyed = 1;
- context->being_destroyed1 = 1;
- context->requested_kill = 1;
-
- memset(&wsi, 0, sizeof(wsi));
- wsi.context = context;
-
-#ifdef LWS_LATENCY
- if (context->worst_latency_info[0])
- lwsl_notice("Worst latency: %s\n", context->worst_latency_info);
-#endif
-
- while (m--) {
- pt = &context->pt[m];
- vpt = (volatile struct lws_context_per_thread *)pt;
-
- ftp = vpt->foreign_pfd_list;
- while (ftp) {
- next = ftp->next;
- lws_free((void *)ftp);
- ftp = next;
- }
- vpt->foreign_pfd_list = NULL;
-
- for (n = 0; (unsigned int)n < context->pt[m].fds_count; n++) {
- struct lws *wsi = wsi_from_fd(context, pt->fds[n].fd);
- if (!wsi)
- continue;
-
- if (wsi->event_pipe)
- lws_destroy_event_pipe(wsi);
- else
- lws_close_free_wsi(wsi,
- LWS_CLOSE_STATUS_NOSTATUS_CONTEXT_DESTROY,
- "ctx destroy"
- /* no protocol close */);
- n--;
- }
- lws_pt_mutex_destroy(pt);
- }
-
- /*
- * inform all the protocols that they are done and will have no more
- * callbacks.
- *
- * We can't free things until after the event loop shuts down.
- */
- if (context->protocol_init_done)
- vh = context->vhost_list;
- while (vh) {
- struct lws_vhost *vhn = vh->vhost_next;
- lws_vhost_destroy1(vh);
- vh = vhn;
- }
-
- lws_plat_context_early_destroy(context);
-
- /*
- * We face two different needs depending if foreign loop or not.
- *
- * 1) If foreign loop, we really want to advance the destroy_context()
- * past here, and block only for libuv-style async close completion.
- *
- * 2a) If poll, and we exited by ourselves and are calling a final
- * destroy_context() outside of any service already, we want to
- * advance all the way in one step.
- *
- * 2b) If poll, and we are reacting to a SIGINT, service thread(s) may
- * be in poll wait or servicing. We can't advance the
- * destroy_context() to the point it's freeing things; we have to
- * leave that for the final destroy_context() after the service
- * thread(s) are finished calling for service.
- */
-
- if (context->event_loop_ops->destroy_context1) {
- context->event_loop_ops->destroy_context1(context);
-
- return;
- }
-
- lws_context_destroy2(context);
-}
diff --git a/thirdparty/libwebsockets/core/libwebsockets.c b/thirdparty/libwebsockets/core/libwebsockets.c
deleted file mode 100644
index 58f00226f6..0000000000
--- a/thirdparty/libwebsockets/core/libwebsockets.c
+++ /dev/null
@@ -1,3479 +0,0 @@
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010-2017 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- */
-
-#include "core/private.h"
-
-#ifdef LWS_HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#ifdef LWS_WITH_IPV6
-#if defined(WIN32) || defined(_WIN32)
-#include <wincrypt.h>
-#include <iphlpapi.h>
-#else
-#include <net/if.h>
-#endif
-#endif
-
-int log_level = LLL_ERR | LLL_WARN | LLL_NOTICE;
-static void (*lwsl_emit)(int level, const char *line)
-#ifndef LWS_PLAT_OPTEE
- = lwsl_emit_stderr
-#endif
- ;
-#ifndef LWS_PLAT_OPTEE
-static const char * const log_level_names[] = {
- "ERR",
- "WARN",
- "NOTICE",
- "INFO",
- "DEBUG",
- "PARSER",
- "HEADER",
- "EXTENSION",
- "CLIENT",
- "LATENCY",
- "USER",
- "?",
- "?"
-};
-#endif
-
-int lws_open(const char *__file, int __oflag, ...)
-{
- va_list ap;
- int n;
-
- va_start(ap, __oflag);
- if (((__oflag & O_CREAT) == O_CREAT)
-#if defined(O_TMPFILE)
- || ((__oflag & O_TMPFILE) == O_TMPFILE)
-#endif
- )
- /* last arg is really a mode_t. But windows... */
- n = open(__file, __oflag, va_arg(ap, uint32_t));
- else
- n = open(__file, __oflag);
- va_end(ap);
-
- lws_plat_apply_FD_CLOEXEC(n);
-
- return n;
-}
-
-#if defined (_DEBUG)
-void lwsi_set_role(struct lws *wsi, lws_wsi_state_t role)
-{
- wsi->wsistate = (wsi->wsistate & (~LWSI_ROLE_MASK)) | role;
-
- lwsl_debug("lwsi_set_role(%p, 0x%x)\n", wsi, wsi->wsistate);
-}
-
-void lwsi_set_state(struct lws *wsi, lws_wsi_state_t lrs)
-{
- wsi->wsistate = (wsi->wsistate & (~LRS_MASK)) | lrs;
-
- lwsl_debug("lwsi_set_state(%p, 0x%x)\n", wsi, wsi->wsistate);
-}
-#endif
-
-signed char char_to_hex(const char c)
-{
- if (c >= '0' && c <= '9')
- return c - '0';
-
- if (c >= 'a' && c <= 'f')
- return c - 'a' + 10;
-
- if (c >= 'A' && c <= 'F')
- return c - 'A' + 10;
-
- return -1;
-}
-
-void
-__lws_free_wsi(struct lws *wsi)
-{
- if (!wsi)
- return;
-
- /*
- * Protocol user data may be allocated either internally by lws
- * or by specified the user. We should only free what we allocated.
- */
- if (wsi->protocol && wsi->protocol->per_session_data_size &&
- wsi->user_space && !wsi->user_space_externally_allocated)
- lws_free(wsi->user_space);
-
- lws_buflist_destroy_all_segments(&wsi->buflist);
- lws_free_set_NULL(wsi->trunc_alloc);
- lws_free_set_NULL(wsi->udp);
-
- if (wsi->vhost && wsi->vhost->lserv_wsi == wsi)
- wsi->vhost->lserv_wsi = NULL;
-
- // lws_peer_dump_from_wsi(wsi);
-
- if (wsi->role_ops->destroy_role)
- wsi->role_ops->destroy_role(wsi);
-
-#if defined(LWS_WITH_PEER_LIMITS)
- lws_peer_track_wsi_close(wsi->context, wsi->peer);
- wsi->peer = NULL;
-#endif
-
- /* since we will destroy the wsi, make absolutely sure now */
-
-#if defined(LWS_WITH_OPENSSL)
- __lws_ssl_remove_wsi_from_buffered_list(wsi);
-#endif
- __lws_remove_from_timeout_list(wsi);
-
- if (wsi->context->event_loop_ops->destroy_wsi)
- wsi->context->event_loop_ops->destroy_wsi(wsi);
-
- wsi->context->count_wsi_allocated--;
- lwsl_debug("%s: %p, remaining wsi %d\n", __func__, wsi,
- wsi->context->count_wsi_allocated);
-
- lws_free(wsi);
-}
-
-void
-lws_dll_add_front(struct lws_dll *d, struct lws_dll *phead)
-{
- if (d->prev)
- return;
-
- /* our next guy is current first guy */
- d->next = phead->next;
- /* if there is a next guy, set his prev ptr to our next ptr */
- if (d->next)
- d->next->prev = d;
- /* our prev ptr is first ptr */
- d->prev = phead;
- /* set the first guy to be us */
- phead->next = d;
-}
-
-/* situation is:
- *
- * HEAD: struct lws_dll * = &entry1
- *
- * Entry 1: struct lws_dll .pprev = &HEAD , .next = Entry 2
- * Entry 2: struct lws_dll .pprev = &entry1 , .next = &entry2
- * Entry 3: struct lws_dll .pprev = &entry2 , .next = NULL
- *
- * Delete Entry1:
- *
- * - HEAD = &entry2
- * - Entry2: .pprev = &HEAD, .next = &entry3
- * - Entry3: .pprev = &entry2, .next = NULL
- *
- * Delete Entry2:
- *
- * - HEAD = &entry1
- * - Entry1: .pprev = &HEAD, .next = &entry3
- * - Entry3: .pprev = &entry1, .next = NULL
- *
- * Delete Entry3:
- *
- * - HEAD = &entry1
- * - Entry1: .pprev = &HEAD, .next = &entry2
- * - Entry2: .pprev = &entry1, .next = NULL
- *
- */
-
-void
-lws_dll_remove(struct lws_dll *d)
-{
- if (!d->prev) /* ie, not part of the list */
- return;
-
- /*
- * remove us
- *
- * USp <-> us <-> USn --> USp <-> USn
- */
-
- /* if we have a next guy, set his prev to our prev */
- if (d->next)
- d->next->prev = d->prev;
-
- /* set our prev guy to our next guy instead of us */
- if (d->prev)
- d->prev->next = d->next;
-
- /* we're out of the list, we should not point anywhere any more */
- d->prev = NULL;
- d->next = NULL;
-}
-
-void
-__lws_remove_from_timeout_list(struct lws *wsi)
-{
- lws_dll_lws_remove(&wsi->dll_timeout);
-}
-
-void
-lws_remove_from_timeout_list(struct lws *wsi)
-{
- struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
-
- lws_pt_lock(pt, __func__);
- __lws_remove_from_timeout_list(wsi);
- lws_pt_unlock(pt);
-}
-
-void
-lws_dll_dump(struct lws_dll_lws *head, const char *title)
-{
- int n = 0;
-
- (void)n;
- lwsl_notice("%s: %s (head.next %p)\n", __func__, title, head->next);
-
- lws_start_foreach_dll_safe(struct lws_dll_lws *, d, d1, head->next) {
- struct lws *wsi = lws_container_of(d, struct lws, dll_hrtimer);
-
- (void)wsi;
-
- lwsl_notice(" %d: wsi %p: %llu\n", n++, wsi,
- (unsigned long long)wsi->pending_timer);
- } lws_end_foreach_dll_safe(d, d1);
-}
-
-void
-__lws_set_timer_usecs(struct lws *wsi, lws_usec_t usecs)
-{
- struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
- struct lws_dll_lws *dd = &pt->dll_head_hrtimer;
- struct timeval now;
- struct lws *wsi1;
- int bef = 0;
-
- lws_dll_lws_remove(&wsi->dll_hrtimer);
-
- if (usecs == LWS_SET_TIMER_USEC_CANCEL)
- return;
-
- gettimeofday(&now, NULL);
- wsi->pending_timer = ((now.tv_sec * 1000000ll) + now.tv_usec) + usecs;
-
- /*
- * we sort the hrtimer list with the earliest timeout first
- */
-
- lws_start_foreach_dll_safe(struct lws_dll_lws *, d, d1,
- pt->dll_head_hrtimer.next) {
- dd = d;
- wsi1 = lws_container_of(d, struct lws, dll_hrtimer);
-
- if (wsi1->pending_timer >= wsi->pending_timer) {
- /* d, dprev's next, is >= our time */
- bef = 1;
- break;
- }
- } lws_end_foreach_dll_safe(d, d1);
-
- if (bef) {
- /*
- * we go before dd
- * DDp <-> DD <-> DDn --> DDp <-> us <-> DD <-> DDn
- */
- /* we point forward to dd */
- wsi->dll_hrtimer.next = dd;
- /* we point back to what dd used to point back to */
- wsi->dll_hrtimer.prev = dd->prev;
- /* DDp points forward to us now */
- dd->prev->next = &wsi->dll_hrtimer;
- /* DD points back to us now */
- dd->prev = &wsi->dll_hrtimer;
- } else {
- /*
- * we go after dd
- * DDp <-> DD <-> DDn --> DDp <-> DD <-> us <-> DDn
- */
- /* we point forward to what dd used to point forward to */
- wsi->dll_hrtimer.next = dd->next;
- /* we point back to dd */
- wsi->dll_hrtimer.prev = dd;
- /* DDn points back to us */
- if (dd->next)
- dd->next->prev = &wsi->dll_hrtimer;
- /* DD points forward to us */
- dd->next = &wsi->dll_hrtimer;
- }
-
-// lws_dll_dump(&pt->dll_head_hrtimer, "after set_timer_usec");
-}
-
-LWS_VISIBLE void
-lws_set_timer_usecs(struct lws *wsi, lws_usec_t usecs)
-{
- __lws_set_timer_usecs(wsi, usecs);
-}
-
-lws_usec_t
-__lws_hrtimer_service(struct lws_context_per_thread *pt)
-{
- struct timeval now;
- struct lws *wsi;
- lws_usec_t t;
-
- gettimeofday(&now, NULL);
- t = (now.tv_sec * 1000000ll) + now.tv_usec;
-
- lws_start_foreach_dll_safe(struct lws_dll_lws *, d, d1,
- pt->dll_head_hrtimer.next) {
- wsi = lws_container_of(d, struct lws, dll_hrtimer);
-
- /*
- * if we met one in the future, we are done, because the list
- * is sorted by time in the future.
- */
- if (wsi->pending_timer > t)
- break;
-
- lws_set_timer_usecs(wsi, LWS_SET_TIMER_USEC_CANCEL);
-
- /* it's time for the timer to be serviced */
-
- if (wsi->protocol &&
- wsi->protocol->callback(wsi, LWS_CALLBACK_TIMER,
- wsi->user_space, NULL, 0))
- __lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS,
- "timer cb errored");
- } lws_end_foreach_dll_safe(d, d1);
-
- /* return an estimate how many us until next timer hit */
-
- if (!pt->dll_head_hrtimer.next)
- return LWS_HRTIMER_NOWAIT;
-
- wsi = lws_container_of(pt->dll_head_hrtimer.next, struct lws, dll_hrtimer);
-
- gettimeofday(&now, NULL);
- t = (now.tv_sec * 1000000ll) + now.tv_usec;
-
- if (wsi->pending_timer < t)
- return 0;
-
- return wsi->pending_timer - t;
-}
-
-void
-__lws_set_timeout(struct lws *wsi, enum pending_timeout reason, int secs)
-{
- struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
- time_t now;
-
- time(&now);
-
- lwsl_debug("%s: %p: %d secs\n", __func__, wsi, secs);
- wsi->pending_timeout_limit = secs;
- wsi->pending_timeout_set = now;
- wsi->pending_timeout = reason;
-
- if (!reason)
- lws_dll_lws_remove(&wsi->dll_timeout);
- else
- lws_dll_lws_add_front(&wsi->dll_timeout, &pt->dll_head_timeout);
-}
-
-LWS_VISIBLE void
-lws_set_timeout(struct lws *wsi, enum pending_timeout reason, int secs)
-{
- struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
-
- if (secs == LWS_TO_KILL_SYNC) {
- lws_remove_from_timeout_list(wsi);
- lwsl_debug("synchronously killing %p\n", wsi);
- lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "to sync kill");
- return;
- }
-
- if (secs == LWS_TO_KILL_ASYNC)
- secs = 0;
-
- lws_pt_lock(pt, __func__);
- __lws_set_timeout(wsi, reason, secs);
- lws_pt_unlock(pt);
-}
-
-int
-lws_timed_callback_remove(struct lws_vhost *vh, struct lws_timed_vh_protocol *p)
-{
- lws_start_foreach_llp(struct lws_timed_vh_protocol **, pt,
- vh->timed_vh_protocol_list) {
- if (*pt == p) {
- *pt = p->next;
- lws_free(p);
-
- return 0;
- }
- } lws_end_foreach_llp(pt, next);
-
- return 1;
-}
-
-LWS_VISIBLE LWS_EXTERN int
-lws_timed_callback_vh_protocol(struct lws_vhost *vh, const struct lws_protocols *prot,
- int reason, int secs)
-{
- struct lws_timed_vh_protocol *p = (struct lws_timed_vh_protocol *)
- lws_malloc(sizeof(*p), "timed_vh");
-
- if (!p)
- return 1;
-
- p->protocol = prot;
- p->reason = reason;
- p->time = lws_now_secs() + secs;
- p->next = vh->timed_vh_protocol_list;
-
- vh->timed_vh_protocol_list = p;
-
- return 0;
-}
-
-static void
-lws_remove_child_from_any_parent(struct lws *wsi)
-{
- struct lws **pwsi;
- int seen = 0;
-
- if (!wsi->parent)
- return;
-
- /* detach ourselves from parent's child list */
- pwsi = &wsi->parent->child_list;
- while (*pwsi) {
- if (*pwsi == wsi) {
- lwsl_info("%s: detach %p from parent %p\n", __func__,
- wsi, wsi->parent);
-
- if (wsi->parent->protocol)
- wsi->parent->protocol->callback(wsi,
- LWS_CALLBACK_CHILD_CLOSING,
- wsi->parent->user_space, wsi, 0);
-
- *pwsi = wsi->sibling_list;
- seen = 1;
- break;
- }
- pwsi = &(*pwsi)->sibling_list;
- }
- if (!seen)
- lwsl_err("%s: failed to detach from parent\n", __func__);
-
- wsi->parent = NULL;
-}
-
-int
-lws_bind_protocol(struct lws *wsi, const struct lws_protocols *p)
-{
-// if (wsi->protocol == p)
-// return 0;
- const struct lws_protocols *vp = wsi->vhost->protocols, *vpo;
-
- if (wsi->protocol && wsi->protocol_bind_balance) {
- wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP_DROP_PROTOCOL,
- wsi->user_space, NULL, 0);
- wsi->protocol_bind_balance = 0;
- }
- if (!wsi->user_space_externally_allocated)
- lws_free_set_NULL(wsi->user_space);
-
- lws_same_vh_protocol_remove(wsi);
-
- wsi->protocol = p;
- if (!p)
- return 0;
-
- if (lws_ensure_user_space(wsi))
- return 1;
-
- if (p > vp && p < &vp[wsi->vhost->count_protocols])
- lws_same_vh_protocol_insert(wsi, (int)(p - vp));
- else {
- int n = wsi->vhost->count_protocols;
- int hit = 0;
-
- vpo = vp;
-
- while (n--) {
- if (p->name && vp->name && !strcmp(p->name, vp->name)) {
- hit = 1;
- lws_same_vh_protocol_insert(wsi, (int)(vp - vpo));
- break;
- }
- vp++;
- }
- if (!hit)
- lwsl_err("%s: %p is not in vhost '%s' protocols list\n",
- __func__, p, wsi->vhost->name);
- }
-
- if (wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP_BIND_PROTOCOL,
- wsi->user_space, NULL, 0))
- return 1;
-
- wsi->protocol_bind_balance = 1;
-
- return 0;
-}
-
-void
-__lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason, const char *caller)
-{
- struct lws_context_per_thread *pt;
- struct lws *wsi1, *wsi2;
- struct lws_context *context;
- int n;
-
- lwsl_info("%s: %p: caller: %s\n", __func__, wsi, caller);
-
- if (!wsi)
- return;
-
- lws_access_log(wsi);
-
- context = wsi->context;
- pt = &context->pt[(int)wsi->tsi];
- lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_C_API_CLOSE, 1);
-
-#if !defined(LWS_NO_CLIENT)
-
- lws_free_set_NULL(wsi->client_hostname_copy);
- /* we are no longer an active client connection that can piggyback */
- lws_dll_lws_remove(&wsi->dll_active_client_conns);
-
- /*
- * if we have wsi in our transaction queue, if we are closing we
- * must go through and close all those first
- */
- if (wsi->vhost) {
- if ((int)reason != -1)
- lws_vhost_lock(wsi->vhost);
- lws_start_foreach_dll_safe(struct lws_dll_lws *, d, d1,
- wsi->dll_client_transaction_queue_head.next) {
- struct lws *w = lws_container_of(d, struct lws,
- dll_client_transaction_queue);
-
- __lws_close_free_wsi(w, -1, "trans q leader closing");
- } lws_end_foreach_dll_safe(d, d1);
-
- /*
- * !!! If we are closing, but we have pending pipelined transaction
- * results we already sent headers for, that's going to destroy sync
- * for HTTP/1 and leave H2 stream with no live swsi.
- *
- * However this is normal if we are being closed because the transaction
- * queue leader is closing.
- */
- lws_dll_lws_remove(&wsi->dll_client_transaction_queue);
- if ((int)reason !=-1)
- lws_vhost_unlock(wsi->vhost);
- }
-#endif
-
- /* if we have children, close them first */
- if (wsi->child_list) {
- wsi2 = wsi->child_list;
- while (wsi2) {
- wsi1 = wsi2->sibling_list;
- wsi2->parent = NULL;
- /* stop it doing shutdown processing */
- wsi2->socket_is_permanently_unusable = 1;
- __lws_close_free_wsi(wsi2, reason, "general child recurse");
- wsi2 = wsi1;
- }
- wsi->child_list = NULL;
- }
-
- if (wsi->role_ops == &role_ops_raw_file) {
- lws_remove_child_from_any_parent(wsi);
- __remove_wsi_socket_from_fds(wsi);
- wsi->protocol->callback(wsi, wsi->role_ops->close_cb[0],
- wsi->user_space, NULL, 0);
- goto async_close;
- }
-
- wsi->wsistate_pre_close = wsi->wsistate;
-
-#ifdef LWS_WITH_CGI
- if (wsi->role_ops == &role_ops_cgi) {
- /* we are not a network connection, but a handler for CGI io */
- if (wsi->parent && wsi->parent->http.cgi) {
-
- if (wsi->cgi_channel == LWS_STDOUT)
- lws_cgi_remove_and_kill(wsi->parent);
-
- /* end the binding between us and master */
- wsi->parent->http.cgi->stdwsi[(int)wsi->cgi_channel] = NULL;
- }
- wsi->socket_is_permanently_unusable = 1;
-
- goto just_kill_connection;
- }
-
- if (wsi->http.cgi)
- lws_cgi_remove_and_kill(wsi);
-#endif
-
-#if !defined(LWS_NO_CLIENT)
- lws_client_stash_destroy(wsi);
-#endif
-
- if (wsi->role_ops == &role_ops_raw_skt) {
- wsi->socket_is_permanently_unusable = 1;
- goto just_kill_connection;
- }
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- if (lwsi_role_http(wsi) && lwsi_role_server(wsi) &&
- wsi->http.fop_fd != NULL)
- lws_vfs_file_close(&wsi->http.fop_fd);
-#endif
-
- if (lwsi_state(wsi) == LRS_DEAD_SOCKET)
- return;
-
- if (wsi->socket_is_permanently_unusable ||
- reason == LWS_CLOSE_STATUS_NOSTATUS_CONTEXT_DESTROY ||
- lwsi_state(wsi) == LRS_SHUTDOWN)
- goto just_kill_connection;
-
- switch (lwsi_state_PRE_CLOSE(wsi)) {
- case LRS_DEAD_SOCKET:
- return;
-
- /* we tried the polite way... */
- case LRS_WAITING_TO_SEND_CLOSE:
- case LRS_AWAITING_CLOSE_ACK:
- case LRS_RETURNED_CLOSE:
- goto just_kill_connection;
-
- case LRS_FLUSHING_BEFORE_CLOSE:
- if (wsi->trunc_len) {
- lws_callback_on_writable(wsi);
- return;
- }
- lwsl_info("%p: end LRS_FLUSHING_BEFORE_CLOSE\n", wsi);
- goto just_kill_connection;
- default:
- if (wsi->trunc_len) {
- lwsl_info("%p: LRS_FLUSHING_BEFORE_CLOSE\n", wsi);
- lwsi_set_state(wsi, LRS_FLUSHING_BEFORE_CLOSE);
- __lws_set_timeout(wsi,
- PENDING_FLUSH_STORED_SEND_BEFORE_CLOSE, 5);
- return;
- }
- break;
- }
-
- if (lwsi_state(wsi) == LRS_WAITING_CONNECT ||
- lwsi_state(wsi) == LRS_H1C_ISSUE_HANDSHAKE)
- goto just_kill_connection;
-
- if (!wsi->told_user_closed && lwsi_role_http(wsi) &&
- lwsi_role_server(wsi)) {
- if (wsi->user_space && wsi->protocol &&
- wsi->protocol_bind_balance) {
- wsi->protocol->callback(wsi,
- LWS_CALLBACK_HTTP_DROP_PROTOCOL,
- wsi->user_space, NULL, 0);
- wsi->protocol_bind_balance = 0;
- }
- }
-
- /*
- * signal we are closing, lws_write will
- * add any necessary version-specific stuff. If the write fails,
- * no worries we are closing anyway. If we didn't initiate this
- * close, then our state has been changed to
- * LRS_RETURNED_CLOSE and we will skip this.
- *
- * Likewise if it's a second call to close this connection after we
- * sent the close indication to the peer already, we are in state
- * LRS_AWAITING_CLOSE_ACK and will skip doing this a second time.
- */
-
- if (wsi->role_ops->close_via_role_protocol &&
- wsi->role_ops->close_via_role_protocol(wsi, reason))
- return;
-
-just_kill_connection:
-
- if (wsi->role_ops->close_kill_connection)
- wsi->role_ops->close_kill_connection(wsi, reason);
-
- lws_remove_child_from_any_parent(wsi);
- n = 0;
-
- if (!wsi->told_user_closed && wsi->user_space &&
- wsi->protocol_bind_balance) {
- lwsl_debug("%s: %p: DROP_PROTOCOL %s\n", __func__, wsi,
- wsi->protocol->name);
- wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP_DROP_PROTOCOL,
- wsi->user_space, NULL, 0);
- wsi->protocol_bind_balance = 0;
- }
-
- if ((lwsi_state(wsi) == LRS_WAITING_SERVER_REPLY ||
- lwsi_state(wsi) == LRS_WAITING_CONNECT) && !wsi->already_did_cce)
- wsi->protocol->callback(wsi,
- LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
- wsi->user_space, NULL, 0);
-
- /*
- * Testing with ab shows that we have to stage the socket close when
- * the system is under stress... shutdown any further TX, change the
- * state to one that won't emit anything more, and wait with a timeout
- * for the POLLIN to show a zero-size rx before coming back and doing
- * the actual close.
- */
- if (wsi->role_ops != &role_ops_raw_skt && !lwsi_role_client(wsi) &&
- lwsi_state(wsi) != LRS_SHUTDOWN &&
- lwsi_state(wsi) != LRS_UNCONNECTED &&
- reason != LWS_CLOSE_STATUS_NOSTATUS_CONTEXT_DESTROY &&
- !wsi->socket_is_permanently_unusable) {
-
-#if defined(LWS_WITH_TLS)
- if (lws_is_ssl(wsi) && wsi->tls.ssl) {
- n = 0;
- switch (__lws_tls_shutdown(wsi)) {
- case LWS_SSL_CAPABLE_DONE:
- case LWS_SSL_CAPABLE_ERROR:
- case LWS_SSL_CAPABLE_MORE_SERVICE_READ:
- case LWS_SSL_CAPABLE_MORE_SERVICE_WRITE:
- case LWS_SSL_CAPABLE_MORE_SERVICE:
- break;
- }
- } else
-#endif
- {
- lwsl_info("%s: shutdown conn: %p (sock %d, state 0x%x)\n",
- __func__, wsi, (int)(long)wsi->desc.sockfd,
- lwsi_state(wsi));
- if (!wsi->socket_is_permanently_unusable &&
- lws_socket_is_valid(wsi->desc.sockfd)) {
- wsi->socket_is_permanently_unusable = 1;
- n = shutdown(wsi->desc.sockfd, SHUT_WR);
- }
- }
- if (n)
- lwsl_debug("closing: shutdown (state 0x%x) ret %d\n",
- lwsi_state(wsi), LWS_ERRNO);
-
- /*
- * This causes problems on WINCE / ESP32 with disconnection
- * when the events are half closing connection
- */
-#if !defined(_WIN32_WCE) && !defined(LWS_WITH_ESP32)
- /* libuv: no event available to guarantee completion */
- if (!wsi->socket_is_permanently_unusable &&
- lws_socket_is_valid(wsi->desc.sockfd) &&
- lwsi_state(wsi) != LRS_SHUTDOWN &&
- context->event_loop_ops->periodic_events_available) {
- __lws_change_pollfd(wsi, LWS_POLLOUT, LWS_POLLIN);
- lwsi_set_state(wsi, LRS_SHUTDOWN);
- __lws_set_timeout(wsi, PENDING_TIMEOUT_SHUTDOWN_FLUSH,
- context->timeout_secs);
-
- return;
- }
-#endif
- }
-
- lwsl_debug("%s: real just_kill_connection: %p (sockfd %d)\n", __func__,
- wsi, wsi->desc.sockfd);
-
-#ifdef LWS_WITH_HTTP_PROXY
- if (wsi->http.rw) {
- lws_rewrite_destroy(wsi->http.rw);
- wsi->http.rw = NULL;
- }
-#endif
- /*
- * we won't be servicing or receiving anything further from this guy
- * delete socket from the internal poll list if still present
- */
- __lws_ssl_remove_wsi_from_buffered_list(wsi);
- __lws_remove_from_timeout_list(wsi);
- lws_dll_lws_remove(&wsi->dll_hrtimer);
-
- /* don't repeat event loop stuff */
- if (wsi->told_event_loop_closed)
- return;
-
- /* checking return redundant since we anyway close */
- if (wsi->desc.sockfd != LWS_SOCK_INVALID)
- __remove_wsi_socket_from_fds(wsi);
- else
- lws_same_vh_protocol_remove(wsi);
-
- lwsi_set_state(wsi, LRS_DEAD_SOCKET);
- lws_buflist_destroy_all_segments(&wsi->buflist);
- lws_dll_lws_remove(&wsi->dll_buflist);
-
- if (wsi->role_ops->close_role)
- wsi->role_ops->close_role(pt, wsi);
-
- /* tell the user it's all over for this guy */
-
- if (lwsi_state_est_PRE_CLOSE(wsi) && !wsi->told_user_closed &&
- wsi->role_ops->close_cb[lwsi_role_server(wsi)]) {
- const struct lws_protocols *pro = wsi->protocol;
-
- if (!wsi->protocol)
- pro = &wsi->vhost->protocols[0];
-
- if (!wsi->upgraded_to_http2 || !lwsi_role_client(wsi))
- /*
- * The network wsi for a client h2 connection shouldn't
- * call back for its role: the child stream connections
- * own the role. Otherwise h2 will call back closed
- * one too many times as the children do it and then
- * the closing network stream.
- */
- pro->callback(wsi,
- wsi->role_ops->close_cb[lwsi_role_server(wsi)],
- wsi->user_space, NULL, 0);
- wsi->told_user_closed = 1;
- }
-
-async_close:
- wsi->socket_is_permanently_unusable = 1;
-
- if (wsi->context->event_loop_ops->wsi_logical_close)
- if (wsi->context->event_loop_ops->wsi_logical_close(wsi))
- return;
-
- __lws_close_free_wsi_final(wsi);
-}
-
-void
-__lws_close_free_wsi_final(struct lws *wsi)
-{
- int n;
-
- if (lws_socket_is_valid(wsi->desc.sockfd) && !lws_ssl_close(wsi)) {
- n = compatible_close(wsi->desc.sockfd);
- if (n)
- lwsl_debug("closing: close ret %d\n", LWS_ERRNO);
-
- wsi->desc.sockfd = LWS_SOCK_INVALID;
- }
-
- /* outermost destroy notification for wsi (user_space still intact) */
- if (wsi->vhost)
- wsi->vhost->protocols[0].callback(wsi, LWS_CALLBACK_WSI_DESTROY,
- wsi->user_space, NULL, 0);
-
-#ifdef LWS_WITH_CGI
- if (wsi->http.cgi) {
-
- for (n = 0; n < 3; n++) {
- if (wsi->http.cgi->pipe_fds[n][!!(n == 0)] == 0)
- lwsl_err("ZERO FD IN CGI CLOSE");
-
- if (wsi->http.cgi->pipe_fds[n][!!(n == 0)] >= 0)
- close(wsi->http.cgi->pipe_fds[n][!!(n == 0)]);
- }
-
- lws_free(wsi->http.cgi);
- }
-#endif
-
- __lws_free_wsi(wsi);
-}
-
-
-void
-lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason, const char *caller)
-{
- struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
-
- lws_pt_lock(pt, __func__);
- __lws_close_free_wsi(wsi, reason, caller);
- lws_pt_unlock(pt);
-}
-
-/* lws_buflist */
-
-int
-lws_buflist_append_segment(struct lws_buflist **head, const uint8_t *buf,
- size_t len)
-{
- struct lws_buflist *nbuf;
- int first = !*head;
- void *p = *head;
- int sanity = 1024;
-
- assert(buf);
- assert(len);
-
- /* append at the tail */
- while (*head) {
- if (!--sanity || head == &((*head)->next)) {
- lwsl_err("%s: corrupt list points to self\n", __func__);
- return -1;
- }
- head = &((*head)->next);
- }
-
- lwsl_info("%s: len %u first %d %p\n", __func__, (uint32_t)len, first, p);
-
- nbuf = (struct lws_buflist *)
- lws_malloc(sizeof(**head) + len, __func__);
- if (!nbuf) {
- lwsl_err("%s: OOM\n", __func__);
- return -1;
- }
-
- nbuf->len = len;
- nbuf->pos = 0;
- nbuf->next = NULL;
-
- p = (void *)nbuf->buf;
- memcpy(p, buf, len);
-
- *head = nbuf;
-
- return first; /* returns 1 if first segment just created */
-}
-
-static int
-lws_buflist_destroy_segment(struct lws_buflist **head)
-{
- struct lws_buflist *old = *head;
-
- assert(*head);
- *head = (*head)->next;
- old->next = NULL;
- lws_free(old);
-
- return !*head; /* returns 1 if last segment just destroyed */
-}
-
-void
-lws_buflist_destroy_all_segments(struct lws_buflist **head)
-{
- struct lws_buflist *p = *head, *p1;
-
- while (p) {
- p1 = p->next;
- p->next = NULL;
- lws_free(p);
- p = p1;
- }
-
- *head = NULL;
-}
-
-size_t
-lws_buflist_next_segment_len(struct lws_buflist **head, uint8_t **buf)
-{
- if (!*head) {
- if (buf)
- *buf = NULL;
-
- return 0;
- }
-
- if (!(*head)->len && (*head)->next)
- lws_buflist_destroy_segment(head);
-
- if (!*head) {
- if (buf)
- *buf = NULL;
-
- return 0;
- }
-
- assert((*head)->pos < (*head)->len);
-
- if (buf)
- *buf = (*head)->buf + (*head)->pos;
-
- return (*head)->len - (*head)->pos;
-}
-
-int
-lws_buflist_use_segment(struct lws_buflist **head, size_t len)
-{
- assert(*head);
- assert(len);
- assert((*head)->pos + len <= (*head)->len);
-
- (*head)->pos += len;
- if ((*head)->pos == (*head)->len)
- lws_buflist_destroy_segment(head);
-
- if (!*head)
- return 0;
-
- return (int)((*head)->len - (*head)->pos);
-}
-
-void
-lws_buflist_describe(struct lws_buflist **head, void *id)
-{
- struct lws_buflist *old;
- int n = 0;
-
- if (*head == NULL)
- lwsl_notice("%p: buflist empty\n", id);
-
- while (*head) {
- lwsl_notice("%p: %d: %llu / %llu (%llu left)\n", id, n,
- (unsigned long long)(*head)->pos,
- (unsigned long long)(*head)->len,
- (unsigned long long)(*head)->len - (*head)->pos);
- old = *head;
- head = &((*head)->next);
- if (*head == old) {
- lwsl_err("%s: next points to self\n", __func__);
- break;
- }
- n++;
- }
-}
-
-/* ... */
-
-LWS_VISIBLE LWS_EXTERN const char *
-lws_get_urlarg_by_name(struct lws *wsi, const char *name, char *buf, int len)
-{
- int n = 0, sl = (int)strlen(name);
-
- while (lws_hdr_copy_fragment(wsi, buf, len,
- WSI_TOKEN_HTTP_URI_ARGS, n) >= 0) {
-
- if (!strncmp(buf, name, sl))
- return buf + sl;
-
- n++;
- }
-
- return NULL;
-}
-
-#if !defined(LWS_WITH_ESP32)
-LWS_VISIBLE int
-interface_to_sa(struct lws_vhost *vh, const char *ifname,
- struct sockaddr_in *addr, size_t addrlen)
-{
- int ipv6 = 0;
-#ifdef LWS_WITH_IPV6
- ipv6 = LWS_IPV6_ENABLED(vh);
-#endif
- (void)vh;
-
- return lws_interface_to_sa(ipv6, ifname, addr, addrlen);
-}
-#endif
-
-#ifndef LWS_PLAT_OPTEE
-static int
-lws_get_addresses(struct lws_vhost *vh, void *ads, char *name,
- int name_len, char *rip, int rip_len)
-{
- struct addrinfo ai, *res;
- struct sockaddr_in addr4;
-
- rip[0] = '\0';
- name[0] = '\0';
- addr4.sin_family = AF_UNSPEC;
-
-#ifdef LWS_WITH_IPV6
- if (LWS_IPV6_ENABLED(vh)) {
- if (!lws_plat_inet_ntop(AF_INET6,
- &((struct sockaddr_in6 *)ads)->sin6_addr,
- rip, rip_len)) {
- lwsl_err("inet_ntop: %s", strerror(LWS_ERRNO));
- return -1;
- }
-
- // Strip off the IPv4 to IPv6 header if one exists
- if (strncmp(rip, "::ffff:", 7) == 0)
- memmove(rip, rip + 7, strlen(rip) - 6);
-
- getnameinfo((struct sockaddr *)ads, sizeof(struct sockaddr_in6),
- name, name_len, NULL, 0, 0);
-
- return 0;
- } else
-#endif
- {
- struct addrinfo *result;
-
- memset(&ai, 0, sizeof ai);
- ai.ai_family = PF_UNSPEC;
- ai.ai_socktype = SOCK_STREAM;
-#if !defined(LWS_WITH_ESP32)
- if (getnameinfo((struct sockaddr *)ads,
- sizeof(struct sockaddr_in),
- name, name_len, NULL, 0, 0))
- return -1;
-#endif
-
- if (getaddrinfo(name, NULL, &ai, &result))
- return -1;
-
- res = result;
- while (addr4.sin_family == AF_UNSPEC && res) {
- switch (res->ai_family) {
- case AF_INET:
- addr4.sin_addr =
- ((struct sockaddr_in *)res->ai_addr)->sin_addr;
- addr4.sin_family = AF_INET;
- break;
- }
-
- res = res->ai_next;
- }
- freeaddrinfo(result);
- }
-
- if (addr4.sin_family == AF_UNSPEC)
- return -1;
-
- if (lws_plat_inet_ntop(AF_INET, &addr4.sin_addr, rip, rip_len) == NULL)
- return -1;
-
- return 0;
-}
-
-
-LWS_VISIBLE const char *
-lws_get_peer_simple(struct lws *wsi, char *name, int namelen)
-{
- socklen_t len, olen;
-#ifdef LWS_WITH_IPV6
- struct sockaddr_in6 sin6;
-#endif
- struct sockaddr_in sin4;
- int af = AF_INET;
- void *p, *q;
-
- wsi = lws_get_network_wsi(wsi);
-
- if (wsi->parent_carries_io)
- wsi = wsi->parent;
-
-#ifdef LWS_WITH_IPV6
- if (LWS_IPV6_ENABLED(wsi->vhost)) {
- len = sizeof(sin6);
- p = &sin6;
- af = AF_INET6;
- q = &sin6.sin6_addr;
- } else
-#endif
- {
- len = sizeof(sin4);
- p = &sin4;
- q = &sin4.sin_addr;
- }
-
- olen = len;
- if (getpeername(wsi->desc.sockfd, p, &len) < 0 || len > olen) {
- lwsl_warn("getpeername: %s\n", strerror(LWS_ERRNO));
- return NULL;
- }
-
- return lws_plat_inet_ntop(af, q, name, namelen);
-}
-#endif
-
-LWS_VISIBLE void
-lws_get_peer_addresses(struct lws *wsi, lws_sockfd_type fd, char *name,
- int name_len, char *rip, int rip_len)
-{
-#ifndef LWS_PLAT_OPTEE
- socklen_t len;
-#ifdef LWS_WITH_IPV6
- struct sockaddr_in6 sin6;
-#endif
- struct sockaddr_in sin4;
- struct lws_context *context = wsi->context;
- int ret = -1;
- void *p;
-
- rip[0] = '\0';
- name[0] = '\0';
-
- lws_latency_pre(context, wsi);
-
-#ifdef LWS_WITH_IPV6
- if (LWS_IPV6_ENABLED(wsi->vhost)) {
- len = sizeof(sin6);
- p = &sin6;
- } else
-#endif
- {
- len = sizeof(sin4);
- p = &sin4;
- }
-
- if (getpeername(fd, p, &len) < 0) {
- lwsl_warn("getpeername: %s\n", strerror(LWS_ERRNO));
- goto bail;
- }
-
- ret = lws_get_addresses(wsi->vhost, p, name, name_len, rip, rip_len);
-
-bail:
- lws_latency(context, wsi, "lws_get_peer_addresses", ret, 1);
-#endif
- (void)wsi;
- (void)fd;
- (void)name;
- (void)name_len;
- (void)rip;
- (void)rip_len;
-
-}
-
-LWS_EXTERN void *
-lws_vhost_user(struct lws_vhost *vhost)
-{
- return vhost->user;
-}
-
-LWS_EXTERN void *
-lws_context_user(struct lws_context *context)
-{
- return context->user_space;
-}
-
-LWS_VISIBLE struct lws_vhost *
-lws_vhost_get(struct lws *wsi)
-{
- return wsi->vhost;
-}
-
-LWS_VISIBLE struct lws_vhost *
-lws_get_vhost(struct lws *wsi)
-{
- return wsi->vhost;
-}
-
-LWS_VISIBLE const struct lws_protocols *
-lws_protocol_get(struct lws *wsi)
-{
- return wsi->protocol;
-}
-
-LWS_VISIBLE const struct lws_udp *
-lws_get_udp(const struct lws *wsi)
-{
- return wsi->udp;
-}
-
-LWS_VISIBLE struct lws *
-lws_get_network_wsi(struct lws *wsi)
-{
- if (!wsi)
- return NULL;
-
-#if defined(LWS_WITH_HTTP2)
- if (!wsi->http2_substream && !wsi->client_h2_substream)
- return wsi;
-
- while (wsi->h2.parent_wsi)
- wsi = wsi->h2.parent_wsi;
-#endif
-
- return wsi;
-}
-
-LWS_VISIBLE LWS_EXTERN const struct lws_protocols *
-lws_vhost_name_to_protocol(struct lws_vhost *vh, const char *name)
-{
- int n;
-
- for (n = 0; n < vh->count_protocols; n++)
- if (!strcmp(name, vh->protocols[n].name))
- return &vh->protocols[n];
-
- return NULL;
-}
-
-LWS_VISIBLE int
-lws_callback_all_protocol(struct lws_context *context,
- const struct lws_protocols *protocol, int reason)
-{
- struct lws_context_per_thread *pt = &context->pt[0];
- unsigned int n, m = context->count_threads;
- struct lws *wsi;
-
- while (m--) {
- for (n = 0; n < pt->fds_count; n++) {
- wsi = wsi_from_fd(context, pt->fds[n].fd);
- if (!wsi)
- continue;
- if (wsi->protocol == protocol)
- protocol->callback(wsi, reason, wsi->user_space,
- NULL, 0);
- }
- pt++;
- }
-
- return 0;
-}
-
-LWS_VISIBLE int
-lws_callback_all_protocol_vhost_args(struct lws_vhost *vh,
- const struct lws_protocols *protocol, int reason,
- void *argp, size_t len)
-{
- struct lws_context *context = vh->context;
- struct lws_context_per_thread *pt = &context->pt[0];
- unsigned int n, m = context->count_threads;
- struct lws *wsi;
-
- while (m--) {
- for (n = 0; n < pt->fds_count; n++) {
- wsi = wsi_from_fd(context, pt->fds[n].fd);
- if (!wsi)
- continue;
- if (wsi->vhost == vh && (wsi->protocol == protocol ||
- !protocol))
- wsi->protocol->callback(wsi, reason,
- wsi->user_space, argp, len);
- }
- pt++;
- }
-
- return 0;
-}
-
-LWS_VISIBLE int
-lws_callback_all_protocol_vhost(struct lws_vhost *vh,
- const struct lws_protocols *protocol, int reason)
-{
- return lws_callback_all_protocol_vhost_args(vh, protocol, reason, NULL, 0);
-}
-
-LWS_VISIBLE LWS_EXTERN int
-lws_callback_vhost_protocols(struct lws *wsi, int reason, void *in, int len)
-{
- int n;
-
- for (n = 0; n < wsi->vhost->count_protocols; n++)
- if (wsi->vhost->protocols[n].callback(wsi, reason, NULL, in, len))
- return 1;
-
- return 0;
-}
-
-LWS_VISIBLE LWS_EXTERN int
-lws_callback_vhost_protocols_vhost(struct lws_vhost *vh, int reason, void *in,
- size_t len)
-{
- int n;
- struct lws *wsi = lws_zalloc(sizeof(*wsi), "fake wsi");
-
- wsi->context = vh->context;
- wsi->vhost = vh;
-
- for (n = 0; n < wsi->vhost->count_protocols; n++) {
- wsi->protocol = &vh->protocols[n];
- if (wsi->protocol->callback(wsi, reason, NULL, in, len)) {
- lws_free(wsi);
- return 1;
- }
- }
-
- lws_free(wsi);
-
- return 0;
-}
-
-LWS_VISIBLE LWS_EXTERN void
-lws_set_fops(struct lws_context *context, const struct lws_plat_file_ops *fops)
-{
- context->fops = fops;
-}
-
-LWS_VISIBLE LWS_EXTERN lws_filepos_t
-lws_vfs_tell(lws_fop_fd_t fop_fd)
-{
- return fop_fd->pos;
-}
-
-LWS_VISIBLE LWS_EXTERN lws_filepos_t
-lws_vfs_get_length(lws_fop_fd_t fop_fd)
-{
- return fop_fd->len;
-}
-
-LWS_VISIBLE LWS_EXTERN uint32_t
-lws_vfs_get_mod_time(lws_fop_fd_t fop_fd)
-{
- return fop_fd->mod_time;
-}
-
-LWS_VISIBLE lws_fileofs_t
-lws_vfs_file_seek_set(lws_fop_fd_t fop_fd, lws_fileofs_t offset)
-{
- lws_fileofs_t ofs;
-
- ofs = fop_fd->fops->LWS_FOP_SEEK_CUR(fop_fd, offset - fop_fd->pos);
-
- return ofs;
-}
-
-
-LWS_VISIBLE lws_fileofs_t
-lws_vfs_file_seek_end(lws_fop_fd_t fop_fd, lws_fileofs_t offset)
-{
- return fop_fd->fops->LWS_FOP_SEEK_CUR(fop_fd, fop_fd->len +
- fop_fd->pos + offset);
-}
-
-
-const struct lws_plat_file_ops *
-lws_vfs_select_fops(const struct lws_plat_file_ops *fops, const char *vfs_path,
- const char **vpath)
-{
- const struct lws_plat_file_ops *pf;
- const char *p = vfs_path;
- int n;
-
- *vpath = NULL;
-
- /* no non-platform fops, just use that */
-
- if (!fops->next)
- return fops;
-
- /*
- * scan the vfs path looking for indications we are to be
- * handled by a specific fops
- */
-
- while (p && *p) {
- if (*p != '/') {
- p++;
- continue;
- }
- /* the first one is always platform fops, so skip */
- pf = fops->next;
- while (pf) {
- n = 0;
- while (n < (int)LWS_ARRAY_SIZE(pf->fi) && pf->fi[n].sig) {
- if (p >= vfs_path + pf->fi[n].len)
- if (!strncmp(p - (pf->fi[n].len - 1),
- pf->fi[n].sig,
- pf->fi[n].len - 1)) {
- *vpath = p + 1;
- return pf;
- }
-
- n++;
- }
- pf = pf->next;
- }
- p++;
- }
-
- return fops;
-}
-
-LWS_VISIBLE LWS_EXTERN lws_fop_fd_t LWS_WARN_UNUSED_RESULT
-lws_vfs_file_open(const struct lws_plat_file_ops *fops, const char *vfs_path,
- lws_fop_flags_t *flags)
-{
- const char *vpath = "";
- const struct lws_plat_file_ops *selected;
-
- selected = lws_vfs_select_fops(fops, vfs_path, &vpath);
-
- return selected->LWS_FOP_OPEN(fops, vfs_path, vpath, flags);
-}
-
-
-/**
- * lws_now_secs() - seconds since 1970-1-1
- *
- */
-LWS_VISIBLE LWS_EXTERN unsigned long
-lws_now_secs(void)
-{
- struct timeval tv;
-
- gettimeofday(&tv, NULL);
-
- return tv.tv_sec;
-}
-
-LWS_VISIBLE LWS_EXTERN int
-lws_compare_time_t(struct lws_context *context, time_t t1, time_t t2)
-{
- if (t1 < context->time_discontiguity)
- t1 += context->time_fixup;
-
- if (t2 < context->time_discontiguity)
- t2 += context->time_fixup;
-
- return (int)(t1 - t2);
-}
-
-LWS_VISIBLE lws_sockfd_type
-lws_get_socket_fd(struct lws *wsi)
-{
- if (!wsi)
- return -1;
- return wsi->desc.sockfd;
-}
-
-#ifdef LWS_LATENCY
-void
-lws_latency(struct lws_context *context, struct lws *wsi, const char *action,
- int ret, int completed)
-{
- unsigned long long u;
- char buf[256];
-
- u = time_in_microseconds();
-
- if (!action) {
- wsi->latency_start = u;
- if (!wsi->action_start)
- wsi->action_start = u;
- return;
- }
- if (completed) {
- if (wsi->action_start == wsi->latency_start)
- sprintf(buf,
- "Completion first try lat %lluus: %p: ret %d: %s\n",
- u - wsi->latency_start,
- (void *)wsi, ret, action);
- else
- sprintf(buf,
- "Completion %lluus: lat %lluus: %p: ret %d: %s\n",
- u - wsi->action_start,
- u - wsi->latency_start,
- (void *)wsi, ret, action);
- wsi->action_start = 0;
- } else
- sprintf(buf, "lat %lluus: %p: ret %d: %s\n",
- u - wsi->latency_start, (void *)wsi, ret, action);
-
- if (u - wsi->latency_start > context->worst_latency) {
- context->worst_latency = u - wsi->latency_start;
- strcpy(context->worst_latency_info, buf);
- }
- lwsl_latency("%s", buf);
-}
-#endif
-
-LWS_VISIBLE int
-lws_rx_flow_control(struct lws *wsi, int _enable)
-{
- struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
- int en = _enable;
-
- // h2 ignores rx flow control atm
- if (lwsi_role_h2(wsi) || wsi->http2_substream ||
- lwsi_role_h2_ENCAPSULATION(wsi))
- return 0; // !!!
-
- lwsl_info("%s: %p 0x%x\n", __func__, wsi, _enable);
-
- if (!(_enable & LWS_RXFLOW_REASON_APPLIES)) {
- /*
- * convert user bool style to bitmap style... in user simple
- * bool style _enable = 0 = flow control it, = 1 = allow rx
- */
- en = LWS_RXFLOW_REASON_APPLIES | LWS_RXFLOW_REASON_USER_BOOL;
- if (_enable & 1)
- en |= LWS_RXFLOW_REASON_APPLIES_ENABLE_BIT;
- }
-
- lws_pt_lock(pt, __func__);
-
- /* any bit set in rxflow_bitmap DISABLEs rxflow control */
- if (en & LWS_RXFLOW_REASON_APPLIES_ENABLE_BIT)
- wsi->rxflow_bitmap &= ~(en & 0xff);
- else
- wsi->rxflow_bitmap |= en & 0xff;
-
- if ((LWS_RXFLOW_PENDING_CHANGE | (!wsi->rxflow_bitmap)) ==
- wsi->rxflow_change_to)
- goto skip;
-
- wsi->rxflow_change_to = LWS_RXFLOW_PENDING_CHANGE | !wsi->rxflow_bitmap;
-
- lwsl_info("%s: %p: bitmap 0x%x: en 0x%x, ch 0x%x\n", __func__, wsi,
- wsi->rxflow_bitmap, en, wsi->rxflow_change_to);
-
- if (_enable & LWS_RXFLOW_REASON_FLAG_PROCESS_NOW ||
- !wsi->rxflow_will_be_applied) {
- en = __lws_rx_flow_control(wsi);
- lws_pt_unlock(pt);
-
- return en;
- }
-
-skip:
- lws_pt_unlock(pt);
-
- return 0;
-}
-
-LWS_VISIBLE void
-lws_rx_flow_allow_all_protocol(const struct lws_context *context,
- const struct lws_protocols *protocol)
-{
- const struct lws_context_per_thread *pt = &context->pt[0];
- struct lws *wsi;
- unsigned int n, m = context->count_threads;
-
- while (m--) {
- for (n = 0; n < pt->fds_count; n++) {
- wsi = wsi_from_fd(context, pt->fds[n].fd);
- if (!wsi)
- continue;
- if (wsi->protocol == protocol)
- lws_rx_flow_control(wsi, LWS_RXFLOW_ALLOW);
- }
- pt++;
- }
-}
-
-int
-lws_broadcast(struct lws_context *context, int reason, void *in, size_t len)
-{
- struct lws_vhost *v = context->vhost_list;
- struct lws wsi;
- int n, ret = 0;
-
- memset(&wsi, 0, sizeof(wsi));
- wsi.context = context;
-
- while (v) {
- const struct lws_protocols *p = v->protocols;
- wsi.vhost = v;
-
- for (n = 0; n < v->count_protocols; n++) {
- wsi.protocol = p;
- if (p->callback &&
- p->callback(&wsi, reason, NULL, in, len))
- ret |= 1;
- p++;
- }
- v = v->vhost_next;
- }
-
- return ret;
-}
-
-LWS_VISIBLE extern const char *
-lws_canonical_hostname(struct lws_context *context)
-{
- return (const char *)context->canonical_hostname;
-}
-
-LWS_VISIBLE LWS_EXTERN const char *
-lws_get_vhost_name(struct lws_vhost *vhost)
-{
- return vhost->name;
-}
-
-LWS_VISIBLE LWS_EXTERN int
-lws_get_vhost_port(struct lws_vhost *vhost)
-{
- return vhost->listen_port;
-}
-
-LWS_VISIBLE LWS_EXTERN void *
-lws_get_vhost_user(struct lws_vhost *vhost)
-{
- return vhost->user;
-}
-
-LWS_VISIBLE LWS_EXTERN const char *
-lws_get_vhost_iface(struct lws_vhost *vhost)
-{
- return vhost->iface;
-}
-
-int user_callback_handle_rxflow(lws_callback_function callback_function,
- struct lws *wsi,
- enum lws_callback_reasons reason, void *user,
- void *in, size_t len)
-{
- int n;
-
- wsi->rxflow_will_be_applied = 1;
- n = callback_function(wsi, reason, user, in, len);
- wsi->rxflow_will_be_applied = 0;
- if (!n)
- n = __lws_rx_flow_control(wsi);
-
- return n;
-}
-
-#if !defined(LWS_WITHOUT_CLIENT)
-LWS_VISIBLE int
-lws_set_proxy(struct lws_vhost *vhost, const char *proxy)
-{
- char *p;
- char authstring[96];
-
- if (!proxy)
- return -1;
-
- /* we have to deal with a possible redundant leading http:// */
- if (!strncmp(proxy, "http://", 7))
- proxy += 7;
-
- p = strrchr(proxy, '@');
- if (p) { /* auth is around */
-
- if ((unsigned int)(p - proxy) > sizeof(authstring) - 1)
- goto auth_too_long;
-
- lws_strncpy(authstring, proxy, p - proxy + 1);
- // null termination not needed on input
- if (lws_b64_encode_string(authstring, lws_ptr_diff(p, proxy),
- vhost->proxy_basic_auth_token,
- sizeof vhost->proxy_basic_auth_token) < 0)
- goto auth_too_long;
-
- lwsl_info(" Proxy auth in use\n");
-
- proxy = p + 1;
- } else
- vhost->proxy_basic_auth_token[0] = '\0';
-
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- lws_strncpy(vhost->http.http_proxy_address, proxy,
- sizeof(vhost->http.http_proxy_address));
-
- p = strchr(vhost->http.http_proxy_address, ':');
- if (!p && !vhost->http.http_proxy_port) {
- lwsl_err("http_proxy needs to be ads:port\n");
-
- return -1;
- } else {
- if (p) {
- *p = '\0';
- vhost->http.http_proxy_port = atoi(p + 1);
- }
- }
-
- lwsl_info(" Proxy %s:%u\n", vhost->http.http_proxy_address,
- vhost->http.http_proxy_port);
-#endif
- return 0;
-
-auth_too_long:
- lwsl_err("proxy auth too long\n");
-
- return -1;
-}
-#endif
-
-#if defined(LWS_WITH_SOCKS5)
-LWS_VISIBLE int
-lws_set_socks(struct lws_vhost *vhost, const char *socks)
-{
- char *p_at, *p_colon;
- char user[96];
- char password[96];
-
- if (!socks)
- return -1;
-
- vhost->socks_user[0] = '\0';
- vhost->socks_password[0] = '\0';
-
- p_at = strrchr(socks, '@');
- if (p_at) { /* auth is around */
- if ((unsigned int)(p_at - socks) > (sizeof(user)
- + sizeof(password) - 2)) {
- lwsl_err("Socks auth too long\n");
- goto bail;
- }
-
- p_colon = strchr(socks, ':');
- if (p_colon) {
- if ((unsigned int)(p_colon - socks) > (sizeof(user)
- - 1) ) {
- lwsl_err("Socks user too long\n");
- goto bail;
- }
- if ((unsigned int)(p_at - p_colon) > (sizeof(password)
- - 1) ) {
- lwsl_err("Socks password too long\n");
- goto bail;
- }
-
- lws_strncpy(vhost->socks_user, socks, p_colon - socks + 1);
- lws_strncpy(vhost->socks_password, p_colon + 1,
- p_at - (p_colon + 1) + 1);
- }
-
- lwsl_info(" Socks auth, user: %s, password: %s\n",
- vhost->socks_user, vhost->socks_password );
-
- socks = p_at + 1;
- }
-
- lws_strncpy(vhost->socks_proxy_address, socks,
- sizeof(vhost->socks_proxy_address));
-
- p_colon = strchr(vhost->socks_proxy_address, ':');
- if (!p_colon && !vhost->socks_proxy_port) {
- lwsl_err("socks_proxy needs to be address:port\n");
- return -1;
- } else {
- if (p_colon) {
- *p_colon = '\0';
- vhost->socks_proxy_port = atoi(p_colon + 1);
- }
- }
-
- lwsl_info(" Socks %s:%u\n", vhost->socks_proxy_address,
- vhost->socks_proxy_port);
-
- return 0;
-
-bail:
- return -1;
-}
-#endif
-
-LWS_VISIBLE const struct lws_protocols *
-lws_get_protocol(struct lws *wsi)
-{
- return wsi->protocol;
-}
-
-
-int
-lws_ensure_user_space(struct lws *wsi)
-{
- if (!wsi->protocol)
- return 0;
-
- /* allocate the per-connection user memory (if any) */
-
- if (wsi->protocol->per_session_data_size && !wsi->user_space) {
- wsi->user_space = lws_zalloc(
- wsi->protocol->per_session_data_size, "user space");
- if (wsi->user_space == NULL) {
- lwsl_err("%s: OOM\n", __func__);
- return 1;
- }
- } else
- lwsl_debug("%s: %p protocol pss %lu, user_space=%p\n", __func__,
- wsi, (long)wsi->protocol->per_session_data_size,
- wsi->user_space);
- return 0;
-}
-
-LWS_VISIBLE void *
-lws_adjust_protocol_psds(struct lws *wsi, size_t new_size)
-{
- ((struct lws_protocols *)lws_get_protocol(wsi))->per_session_data_size =
- new_size;
-
- if (lws_ensure_user_space(wsi))
- return NULL;
-
- return wsi->user_space;
-}
-
-LWS_VISIBLE int
-lwsl_timestamp(int level, char *p, int len)
-{
-#ifndef LWS_PLAT_OPTEE
- time_t o_now = time(NULL);
- unsigned long long now;
- struct tm *ptm = NULL;
-#ifndef WIN32
- struct tm tm;
-#endif
- int n;
-
-#ifndef _WIN32_WCE
-#ifdef WIN32
- ptm = localtime(&o_now);
-#else
- if (localtime_r(&o_now, &tm))
- ptm = &tm;
-#endif
-#endif
- p[0] = '\0';
- for (n = 0; n < LLL_COUNT; n++) {
- if (level != (1 << n))
- continue;
- now = time_in_microseconds() / 100;
- if (ptm)
- n = lws_snprintf(p, len,
- "[%04d/%02d/%02d %02d:%02d:%02d:%04d] %s: ",
- ptm->tm_year + 1900,
- ptm->tm_mon + 1,
- ptm->tm_mday,
- ptm->tm_hour,
- ptm->tm_min,
- ptm->tm_sec,
- (int)(now % 10000), log_level_names[n]);
- else
- n = lws_snprintf(p, len, "[%llu:%04d] %s: ",
- (unsigned long long) now / 10000,
- (int)(now % 10000), log_level_names[n]);
- return n;
- }
-#else
- p[0] = '\0';
-#endif
-
- return 0;
-}
-
-#ifndef LWS_PLAT_OPTEE
-static const char * const colours[] = {
- "[31;1m", /* LLL_ERR */
- "[36;1m", /* LLL_WARN */
- "[35;1m", /* LLL_NOTICE */
- "[32;1m", /* LLL_INFO */
- "[34;1m", /* LLL_DEBUG */
- "[33;1m", /* LLL_PARSER */
- "[33m", /* LLL_HEADER */
- "[33m", /* LLL_EXT */
- "[33m", /* LLL_CLIENT */
- "[33;1m", /* LLL_LATENCY */
- "[30;1m", /* LLL_USER */
-};
-
-LWS_VISIBLE void lwsl_emit_stderr(int level, const char *line)
-{
- char buf[50];
- static char tty = 3;
- int n, m = LWS_ARRAY_SIZE(colours) - 1;
-
- if (!tty)
- tty = isatty(2) | 2;
- lwsl_timestamp(level, buf, sizeof(buf));
-
- if (tty == 3) {
- n = 1 << (LWS_ARRAY_SIZE(colours) - 1);
- while (n) {
- if (level & n)
- break;
- m--;
- n >>= 1;
- }
- fprintf(stderr, "%c%s%s%s%c[0m", 27, colours[m], buf, line, 27);
- } else
- fprintf(stderr, "%s%s", buf, line);
-}
-#endif
-
-LWS_VISIBLE void _lws_logv(int filter, const char *format, va_list vl)
-{
- char buf[256];
- int n;
-
- if (!(log_level & filter))
- return;
-
- n = vsnprintf(buf, sizeof(buf) - 1, format, vl);
- (void)n;
- /* vnsprintf returns what it would have written, even if truncated */
- if (n > (int)sizeof(buf) - 1)
- n = sizeof(buf) - 1;
- if (n > 0)
- buf[n] = '\0';
-
- lwsl_emit(filter, buf);
-}
-
-LWS_VISIBLE void _lws_log(int filter, const char *format, ...)
-{
- va_list ap;
-
- va_start(ap, format);
- _lws_logv(filter, format, ap);
- va_end(ap);
-}
-
-LWS_VISIBLE void lws_set_log_level(int level,
- void (*func)(int level, const char *line))
-{
- log_level = level;
- if (func)
- lwsl_emit = func;
-}
-
-LWS_VISIBLE int lwsl_visible(int level)
-{
- return log_level & level;
-}
-
-LWS_VISIBLE void
-lwsl_hexdump_level(int hexdump_level, const void *vbuf, size_t len)
-{
- unsigned char *buf = (unsigned char *)vbuf;
- unsigned int n, m, start;
- char line[80];
- char *p;
-
- if (!lwsl_visible(hexdump_level))
- return;
-
- if (!len)
- return;
-
- if (!vbuf)
- return;
-
- _lws_log(hexdump_level, "\n");
-
- for (n = 0; n < len;) {
- start = n;
- p = line;
-
- p += sprintf(p, "%04X: ", start);
-
- for (m = 0; m < 16 && n < len; m++)
- p += sprintf(p, "%02X ", buf[n++]);
- while (m++ < 16)
- p += sprintf(p, " ");
-
- p += sprintf(p, " ");
-
- for (m = 0; m < 16 && (start + m) < len; m++) {
- if (buf[start + m] >= ' ' && buf[start + m] < 127)
- *p++ = buf[start + m];
- else
- *p++ = '.';
- }
- while (m++ < 16)
- *p++ = ' ';
-
- *p++ = '\n';
- *p = '\0';
- _lws_log(hexdump_level, "%s", line);
- (void)line;
- }
-
- _lws_log(hexdump_level, "\n");
-}
-
-LWS_VISIBLE void
-lwsl_hexdump(const void *vbuf, size_t len)
-{
-#if defined(_DEBUG)
- lwsl_hexdump_level(LLL_DEBUG, vbuf, len);
-#endif
-}
-
-LWS_VISIBLE int
-lws_is_ssl(struct lws *wsi)
-{
-#if defined(LWS_WITH_TLS)
- return wsi->tls.use_ssl & LCCSCF_USE_SSL;
-#else
- (void)wsi;
- return 0;
-#endif
-}
-
-#if defined(LWS_WITH_TLS) && !defined(LWS_WITH_MBEDTLS)
-LWS_VISIBLE lws_tls_conn*
-lws_get_ssl(struct lws *wsi)
-{
- return wsi->tls.ssl;
-}
-#endif
-
-LWS_VISIBLE int
-lws_partial_buffered(struct lws *wsi)
-{
- return !!wsi->trunc_len;
-}
-
-LWS_VISIBLE lws_fileofs_t
-lws_get_peer_write_allowance(struct lws *wsi)
-{
- if (!wsi->role_ops->tx_credit)
- return -1;
- return wsi->role_ops->tx_credit(wsi);
-}
-
-LWS_VISIBLE void
-lws_role_transition(struct lws *wsi, enum lwsi_role role, enum lwsi_state state,
- struct lws_role_ops *ops)
-{
-#if defined(_DEBUG)
- const char *name = "(unset)";
-#endif
- wsi->wsistate = role | state;
- if (ops)
- wsi->role_ops = ops;
-#if defined(_DEBUG)
- if (wsi->role_ops)
- name = wsi->role_ops->name;
- lwsl_debug("%s: %p: wsistate 0x%x, ops %s\n", __func__, wsi,
- wsi->wsistate, name);
-#endif
-}
-
-LWS_VISIBLE struct lws_plat_file_ops *
-lws_get_fops(struct lws_context *context)
-{
- return (struct lws_plat_file_ops *)context->fops;
-}
-
-LWS_VISIBLE LWS_EXTERN struct lws_context *
-lws_get_context(const struct lws *wsi)
-{
- return wsi->context;
-}
-
-LWS_VISIBLE LWS_EXTERN int
-lws_get_count_threads(struct lws_context *context)
-{
- return context->count_threads;
-}
-
-LWS_VISIBLE LWS_EXTERN void *
-lws_wsi_user(struct lws *wsi)
-{
- return wsi->user_space;
-}
-
-LWS_VISIBLE LWS_EXTERN void
-lws_set_wsi_user(struct lws *wsi, void *data)
-{
- if (wsi->user_space_externally_allocated)
- wsi->user_space = data;
- else
- lwsl_err("%s: Cannot set internally-allocated user_space\n",
- __func__);
-}
-
-LWS_VISIBLE LWS_EXTERN struct lws *
-lws_get_parent(const struct lws *wsi)
-{
- return wsi->parent;
-}
-
-LWS_VISIBLE LWS_EXTERN struct lws *
-lws_get_child(const struct lws *wsi)
-{
- return wsi->child_list;
-}
-
-LWS_VISIBLE LWS_EXTERN void
-lws_set_parent_carries_io(struct lws *wsi)
-{
- wsi->parent_carries_io = 1;
-}
-
-LWS_VISIBLE LWS_EXTERN void *
-lws_get_opaque_parent_data(const struct lws *wsi)
-{
- return wsi->opaque_parent_data;
-}
-
-LWS_VISIBLE LWS_EXTERN void
-lws_set_opaque_parent_data(struct lws *wsi, void *data)
-{
- wsi->opaque_parent_data = data;
-}
-
-LWS_VISIBLE LWS_EXTERN int
-lws_get_child_pending_on_writable(const struct lws *wsi)
-{
- return wsi->parent_pending_cb_on_writable;
-}
-
-LWS_VISIBLE LWS_EXTERN void
-lws_clear_child_pending_on_writable(struct lws *wsi)
-{
- wsi->parent_pending_cb_on_writable = 0;
-}
-
-
-LWS_EXTERN int
-__lws_rx_flow_control(struct lws *wsi)
-{
- struct lws *wsic = wsi->child_list;
-
- // h2 ignores rx flow control atm
- if (lwsi_role_h2(wsi) || wsi->http2_substream ||
- lwsi_role_h2_ENCAPSULATION(wsi))
- return 0; // !!!
-
- /* if he has children, do those if they were changed */
- while (wsic) {
- if (wsic->rxflow_change_to & LWS_RXFLOW_PENDING_CHANGE)
- __lws_rx_flow_control(wsic);
-
- wsic = wsic->sibling_list;
- }
-
- /* there is no pending change */
- if (!(wsi->rxflow_change_to & LWS_RXFLOW_PENDING_CHANGE))
- return 0;
-
- /* stuff is still buffered, not ready to really accept new input */
- if (lws_buflist_next_segment_len(&wsi->buflist, NULL)) {
- /* get ourselves called back to deal with stashed buffer */
- lws_callback_on_writable(wsi);
- return 0;
- }
-
- /* now the pending is cleared, we can change rxflow state */
-
- wsi->rxflow_change_to &= ~LWS_RXFLOW_PENDING_CHANGE;
-
- lwsl_info("rxflow: wsi %p change_to %d\n", wsi,
- wsi->rxflow_change_to & LWS_RXFLOW_ALLOW);
-
- /* adjust the pollfd for this wsi */
-
- if (wsi->rxflow_change_to & LWS_RXFLOW_ALLOW) {
- if (__lws_change_pollfd(wsi, 0, LWS_POLLIN)) {
- lwsl_info("%s: fail\n", __func__);
- return -1;
- }
- } else
- if (__lws_change_pollfd(wsi, LWS_POLLIN, 0))
- return -1;
-
- return 0;
-}
-
-LWS_EXTERN int
-lws_check_utf8(unsigned char *state, unsigned char *buf, size_t len)
-{
- static const unsigned char e0f4[] = {
- 0xa0 | ((2 - 1) << 2) | 1, /* e0 */
- 0x80 | ((4 - 1) << 2) | 1, /* e1 */
- 0x80 | ((4 - 1) << 2) | 1, /* e2 */
- 0x80 | ((4 - 1) << 2) | 1, /* e3 */
- 0x80 | ((4 - 1) << 2) | 1, /* e4 */
- 0x80 | ((4 - 1) << 2) | 1, /* e5 */
- 0x80 | ((4 - 1) << 2) | 1, /* e6 */
- 0x80 | ((4 - 1) << 2) | 1, /* e7 */
- 0x80 | ((4 - 1) << 2) | 1, /* e8 */
- 0x80 | ((4 - 1) << 2) | 1, /* e9 */
- 0x80 | ((4 - 1) << 2) | 1, /* ea */
- 0x80 | ((4 - 1) << 2) | 1, /* eb */
- 0x80 | ((4 - 1) << 2) | 1, /* ec */
- 0x80 | ((2 - 1) << 2) | 1, /* ed */
- 0x80 | ((4 - 1) << 2) | 1, /* ee */
- 0x80 | ((4 - 1) << 2) | 1, /* ef */
- 0x90 | ((3 - 1) << 2) | 2, /* f0 */
- 0x80 | ((4 - 1) << 2) | 2, /* f1 */
- 0x80 | ((4 - 1) << 2) | 2, /* f2 */
- 0x80 | ((4 - 1) << 2) | 2, /* f3 */
- 0x80 | ((1 - 1) << 2) | 2, /* f4 */
-
- 0, /* s0 */
- 0x80 | ((4 - 1) << 2) | 0, /* s2 */
- 0x80 | ((4 - 1) << 2) | 1, /* s3 */
- };
- unsigned char s = *state;
-
- while (len--) {
- unsigned char c = *buf++;
-
- if (!s) {
- if (c >= 0x80) {
- if (c < 0xc2 || c > 0xf4)
- return 1;
- if (c < 0xe0)
- s = 0x80 | ((4 - 1) << 2);
- else
- s = e0f4[c - 0xe0];
- }
- } else {
- if (c < (s & 0xf0) ||
- c >= (s & 0xf0) + 0x10 + ((s << 2) & 0x30))
- return 1;
- s = e0f4[21 + (s & 3)];
- }
- }
-
- *state = s;
-
- return 0;
-}
-
-LWS_VISIBLE LWS_EXTERN int
-lws_parse_uri(char *p, const char **prot, const char **ads, int *port,
- const char **path)
-{
- const char *end;
- static const char *slash = "/";
-
- /* cut up the location into address, port and path */
- *prot = p;
- while (*p && (*p != ':' || p[1] != '/' || p[2] != '/'))
- p++;
- if (!*p) {
- end = p;
- p = (char *)*prot;
- *prot = end;
- } else {
- *p = '\0';
- p += 3;
- }
- *ads = p;
- if (!strcmp(*prot, "http") || !strcmp(*prot, "ws"))
- *port = 80;
- else if (!strcmp(*prot, "https") || !strcmp(*prot, "wss"))
- *port = 443;
-
- if (*p == '[')
- {
- ++(*ads);
- while (*p && *p != ']')
- p++;
- if (*p)
- *p++ = '\0';
- }
- else
- {
- while (*p && *p != ':' && *p != '/')
- p++;
- }
- if (*p == ':') {
- *p++ = '\0';
- *port = atoi(p);
- while (*p && *p != '/')
- p++;
- }
- *path = slash;
- if (*p) {
- *p++ = '\0';
- if (*p)
- *path = p;
- }
-
- return 0;
-}
-
-#if defined(LWS_WITHOUT_EXTENSIONS)
-
-/* we need to provide dummy callbacks for internal exts
- * so user code runs when faced with a lib compiled with
- * extensions disabled.
- */
-
-LWS_VISIBLE int
-lws_extension_callback_pm_deflate(struct lws_context *context,
- const struct lws_extension *ext,
- struct lws *wsi,
- enum lws_extension_callback_reasons reason,
- void *user, void *in, size_t len)
-{
- (void)context;
- (void)ext;
- (void)wsi;
- (void)reason;
- (void)user;
- (void)in;
- (void)len;
-
- return 0;
-}
-
-LWS_EXTERN int
-lws_set_extension_option(struct lws *wsi, const char *ext_name,
- const char *opt_name, const char *opt_val)
-{
- return -1;
-}
-#endif
-
-LWS_EXTERN int
-lws_socket_bind(struct lws_vhost *vhost, lws_sockfd_type sockfd, int port,
- const char *iface)
-{
-#ifdef LWS_WITH_UNIX_SOCK
- struct sockaddr_un serv_unix;
-#endif
-#ifdef LWS_WITH_IPV6
- struct sockaddr_in6 serv_addr6;
-#endif
- struct sockaddr_in serv_addr4;
-#ifndef LWS_PLAT_OPTEE
- socklen_t len = sizeof(struct sockaddr_storage);
-#endif
- int n;
-#if !defined(LWS_WITH_ESP32)
- int m;
-#endif
- struct sockaddr_storage sin;
- struct sockaddr *v;
-
-#ifdef LWS_WITH_UNIX_SOCK
- if (LWS_UNIX_SOCK_ENABLED(vhost)) {
- v = (struct sockaddr *)&serv_unix;
- n = sizeof(struct sockaddr_un);
- bzero((char *) &serv_unix, sizeof(serv_unix));
- serv_unix.sun_family = AF_UNIX;
- if (!iface)
- return -1;
- if (sizeof(serv_unix.sun_path) <= strlen(iface)) {
- lwsl_err("\"%s\" too long for UNIX domain socket\n",
- iface);
- return -1;
- }
- strcpy(serv_unix.sun_path, iface);
- if (serv_unix.sun_path[0] == '@')
- serv_unix.sun_path[0] = '\0';
-
- } else
-#endif
-#if defined(LWS_WITH_IPV6) && !defined(LWS_WITH_ESP32)
- if (LWS_IPV6_ENABLED(vhost)) {
- v = (struct sockaddr *)&serv_addr6;
- n = sizeof(struct sockaddr_in6);
- bzero((char *) &serv_addr6, sizeof(serv_addr6));
- if (iface) {
- m = interface_to_sa(vhost, iface,
- (struct sockaddr_in *)v, n);
- if (m == LWS_ITOSA_NOT_USABLE) {
- lwsl_info("%s: netif %s: Not usable\n",
- __func__, iface);
- return m;
- }
- if (m == LWS_ITOSA_NOT_EXIST) {
- lwsl_info("%s: netif %s: Does not exist\n",
- __func__, iface);
- return m;
- }
- serv_addr6.sin6_scope_id = lws_get_addr_scope(iface);
- }
-
- serv_addr6.sin6_family = AF_INET6;
- serv_addr6.sin6_port = htons(port);
- } else
-#endif
- {
- v = (struct sockaddr *)&serv_addr4;
- n = sizeof(serv_addr4);
- 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) {
- m = interface_to_sa(vhost, iface,
- (struct sockaddr_in *)v, n);
- if (m == LWS_ITOSA_NOT_USABLE) {
- lwsl_info("%s: netif %s: Not usable\n",
- __func__, iface);
- return m;
- }
- if (m == LWS_ITOSA_NOT_EXIST) {
- lwsl_info("%s: netif %s: Does not exist\n",
- __func__, iface);
- return m;
- }
- }
-#endif
- serv_addr4.sin_port = htons(port);
- } /* ipv4 */
-
- /* just checking for the interface extant */
- if (sockfd == LWS_SOCK_INVALID)
- return 0;
-
- n = bind(sockfd, v, n);
-#ifdef LWS_WITH_UNIX_SOCK
- if (n < 0 && LWS_UNIX_SOCK_ENABLED(vhost)) {
- lwsl_err("ERROR on binding fd %d to \"%s\" (%d %d)\n",
- sockfd, iface, n, LWS_ERRNO);
- return -1;
- } else
-#endif
- if (n < 0) {
- lwsl_err("ERROR on binding fd %d to port %d (%d %d)\n",
- sockfd, port, n, LWS_ERRNO);
- return -1;
- }
-
-#ifndef LWS_PLAT_OPTEE
- if (getsockname(sockfd, (struct sockaddr *)&sin, &len) == -1)
- lwsl_warn("getsockname: %s\n", strerror(LWS_ERRNO));
- else
-#endif
-#if defined(LWS_WITH_IPV6)
- port = (sin.ss_family == AF_INET6) ?
- ntohs(((struct sockaddr_in6 *) &sin)->sin6_port) :
- ntohs(((struct sockaddr_in *) &sin)->sin_port);
-#else
- {
- struct sockaddr_in sain;
- memcpy(&sain, &sin, sizeof(sain));
- port = ntohs(sain.sin_port);
- }
-#endif
-
- return port;
-}
-
-LWS_VISIBLE LWS_EXTERN int
-lws_get_vhost_listen_port(struct lws_vhost *vhost)
-{
- return vhost->listen_port;
-}
-
-#if defined(LWS_WITH_IPV6)
-LWS_EXTERN unsigned long
-lws_get_addr_scope(const char *ipaddr)
-{
- unsigned long scope = 0;
-
-#ifndef WIN32
- struct ifaddrs *addrs, *addr;
- char ip[NI_MAXHOST];
- unsigned int i;
-
- getifaddrs(&addrs);
- for (addr = addrs; addr; addr = addr->ifa_next) {
- if (!addr->ifa_addr ||
- addr->ifa_addr->sa_family != AF_INET6)
- continue;
-
- getnameinfo(addr->ifa_addr,
- sizeof(struct sockaddr_in6),
- ip, sizeof(ip),
- NULL, 0, NI_NUMERICHOST);
-
- i = 0;
- while (ip[i])
- if (ip[i++] == '%') {
- ip[i - 1] = '\0';
- break;
- }
-
- if (!strcmp(ip, ipaddr)) {
- scope = if_nametoindex(addr->ifa_name);
- break;
- }
- }
- freeifaddrs(addrs);
-#else
- PIP_ADAPTER_ADDRESSES adapter, addrs = NULL;
- PIP_ADAPTER_UNICAST_ADDRESS addr;
- ULONG size = 0;
- DWORD ret;
- struct sockaddr_in6 *sockaddr;
- char ip[NI_MAXHOST];
- unsigned int i;
- int found = 0;
-
- for (i = 0; i < 5; i++)
- {
- ret = GetAdaptersAddresses(AF_INET6, GAA_FLAG_INCLUDE_PREFIX,
- NULL, addrs, &size);
- if ((ret == NO_ERROR) || (ret == ERROR_NO_DATA)) {
- break;
- } else if (ret == ERROR_BUFFER_OVERFLOW)
- {
- if (addrs)
- free(addrs);
- addrs = (IP_ADAPTER_ADDRESSES *)malloc(size);
- } else
- {
- if (addrs)
- {
- free(addrs);
- addrs = NULL;
- }
- lwsl_err("Failed to get IPv6 address table (%d)", ret);
- break;
- }
- }
-
- if ((ret == NO_ERROR) && (addrs)) {
- adapter = addrs;
- while (adapter && !found) {
- addr = adapter->FirstUnicastAddress;
- while (addr && !found) {
- if (addr->Address.lpSockaddr->sa_family ==
- AF_INET6) {
- sockaddr = (struct sockaddr_in6 *)
- (addr->Address.lpSockaddr);
-
- lws_plat_inet_ntop(sockaddr->sin6_family,
- &sockaddr->sin6_addr,
- ip, sizeof(ip));
-
- if (!strcmp(ip, ipaddr)) {
- scope = sockaddr->sin6_scope_id;
- found = 1;
- break;
- }
- }
- addr = addr->Next;
- }
- adapter = adapter->Next;
- }
- }
- if (addrs)
- free(addrs);
-#endif
-
- return scope;
-}
-#endif
-
-#if !defined(LWS_NO_SERVER)
-
-LWS_EXTERN struct lws *
-lws_create_adopt_udp(struct lws_vhost *vhost, int port, int flags,
- const char *protocol_name, struct lws *parent_wsi)
-{
- lws_sock_file_fd_type sock;
- struct addrinfo h, *r, *rp;
- struct lws *wsi = NULL;
- char buf[16];
- int n;
-
- memset(&h, 0, sizeof(h));
- h.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
- h.ai_socktype = SOCK_DGRAM;
- h.ai_protocol = IPPROTO_UDP;
- h.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
-
- lws_snprintf(buf, sizeof(buf), "%u", port);
- n = getaddrinfo(NULL, buf, &h, &r);
- if (n) {
- lwsl_info("%s: getaddrinfo error: %s\n", __func__,
- gai_strerror(n));
- goto bail;
- }
-
- for (rp = r; rp; rp = rp->ai_next) {
- sock.sockfd = socket(rp->ai_family, rp->ai_socktype,
- rp->ai_protocol);
- if (sock.sockfd >= 0)
- break;
- }
- if (!rp) {
- lwsl_err("%s: unable to create INET socket\n", __func__);
- goto bail1;
- }
-
- if ((flags & LWS_CAUDP_BIND) && bind(sock.sockfd, rp->ai_addr,
-#if defined(_WIN32)
- (int)rp->ai_addrlen
-#else
- rp->ai_addrlen
-#endif
- ) == -1) {
- lwsl_err("%s: bind failed\n", __func__);
- goto bail2;
- }
-
- wsi = lws_adopt_descriptor_vhost(vhost, LWS_ADOPT_RAW_SOCKET_UDP, sock,
- protocol_name, parent_wsi);
- if (!wsi)
- lwsl_err("%s: udp adoption failed\n", __func__);
-
-bail2:
- if (!wsi)
- close((int)sock.sockfd);
-bail1:
- freeaddrinfo(r);
-
-bail:
- return wsi;
-}
-
-#endif
-
-
-
-static const char *hex = "0123456789ABCDEF";
-
-LWS_VISIBLE LWS_EXTERN const char *
-lws_sql_purify(char *escaped, const char *string, int len)
-{
- const char *p = string;
- char *q = escaped;
-
- while (*p && len-- > 2) {
- if (*p == '\'') {
- *q++ = '\'';
- *q++ = '\'';
- len --;
- p++;
- } else
- *q++ = *p++;
- }
- *q = '\0';
-
- return escaped;
-}
-
-LWS_VISIBLE LWS_EXTERN const char *
-lws_json_purify(char *escaped, const char *string, int len)
-{
- const char *p = string;
- char *q = escaped;
-
- if (!p) {
- escaped[0] = '\0';
- return escaped;
- }
-
- while (*p && len-- > 6) {
- if (*p == '\"' || *p == '\\' || *p < 0x20) {
- *q++ = '\\';
- *q++ = 'u';
- *q++ = '0';
- *q++ = '0';
- *q++ = hex[((*p) >> 4) & 15];
- *q++ = hex[(*p) & 15];
- len -= 5;
- p++;
- } else
- *q++ = *p++;
- }
- *q = '\0';
-
- return escaped;
-}
-
-LWS_VISIBLE LWS_EXTERN void
-lws_filename_purify_inplace(char *filename)
-{
- while (*filename) {
-
- if (*filename == '.' && filename[1] == '.') {
- *filename = '_';
- filename[1] = '_';
- }
-
- if (*filename == ':' ||
- *filename == '/' ||
- *filename == '\\' ||
- *filename == '$' ||
- *filename == '%')
- *filename = '_';
-
- filename++;
- }
-}
-
-LWS_VISIBLE LWS_EXTERN const char *
-lws_urlencode(char *escaped, const char *string, int len)
-{
- const char *p = string;
- char *q = escaped;
-
- while (*p && len-- > 3) {
- if (*p == ' ') {
- *q++ = '+';
- p++;
- continue;
- }
- if ((*p >= '0' && *p <= '9') ||
- (*p >= 'A' && *p <= 'Z') ||
- (*p >= 'a' && *p <= 'z')) {
- *q++ = *p++;
- continue;
- }
- *q++ = '%';
- *q++ = hex[(*p >> 4) & 0xf];
- *q++ = hex[*p & 0xf];
-
- len -= 2;
- p++;
- }
- *q = '\0';
-
- return escaped;
-}
-
-LWS_VISIBLE LWS_EXTERN int
-lws_urldecode(char *string, const char *escaped, int len)
-{
- int state = 0, n;
- char sum = 0;
-
- while (*escaped && len) {
- switch (state) {
- case 0:
- if (*escaped == '%') {
- state++;
- escaped++;
- continue;
- }
- if (*escaped == '+') {
- escaped++;
- *string++ = ' ';
- len--;
- continue;
- }
- *string++ = *escaped++;
- len--;
- break;
- case 1:
- n = char_to_hex(*escaped);
- if (n < 0)
- return -1;
- escaped++;
- sum = n << 4;
- state++;
- break;
-
- case 2:
- n = char_to_hex(*escaped);
- if (n < 0)
- return -1;
- escaped++;
- *string++ = sum | n;
- len--;
- state = 0;
- break;
- }
-
- }
- *string = '\0';
-
- return 0;
-}
-
-LWS_VISIBLE LWS_EXTERN int
-lws_finalize_startup(struct lws_context *context)
-{
- struct lws_context_creation_info info;
-
- info.uid = context->uid;
- info.gid = context->gid;
-
-#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
- memcpy(info.caps, context->caps, sizeof(info.caps));
- info.count_caps = context->count_caps;
-#endif
-
- if (lws_check_opt(context->options, LWS_SERVER_OPTION_EXPLICIT_VHOSTS))
- lws_plat_drop_app_privileges(&info);
-
- return 0;
-}
-
-int
-lws_snprintf(char *str, size_t size, const char *format, ...)
-{
- va_list ap;
- int n;
-
- if (!size)
- return 0;
-
- va_start(ap, format);
- n = vsnprintf(str, size, format, ap);
- va_end(ap);
-
- if (n >= (int)size)
- return (int)size;
-
- return n;
-}
-
-char *
-lws_strncpy(char *dest, const char *src, size_t size)
-{
- strncpy(dest, src, size - 1);
- dest[size - 1] = '\0';
-
- return dest;
-}
-
-
-LWS_VISIBLE LWS_EXTERN int
-lws_is_cgi(struct lws *wsi) {
-#ifdef LWS_WITH_CGI
- return !!wsi->http.cgi;
-#else
- return 0;
-#endif
-}
-
-const struct lws_protocol_vhost_options *
-lws_pvo_search(const struct lws_protocol_vhost_options *pvo, const char *name)
-{
- while (pvo) {
- if (!strcmp(pvo->name, name))
- break;
-
- pvo = pvo->next;
- }
-
- return pvo;
-}
-
-void
-lws_sum_stats(const struct lws_context *ctx, struct lws_conn_stats *cs)
-{
- const struct lws_vhost *vh = ctx->vhost_list;
-
- while (vh) {
-
- cs->rx += vh->conn_stats.rx;
- cs->tx += vh->conn_stats.tx;
- cs->h1_conn += vh->conn_stats.h1_conn;
- cs->h1_trans += vh->conn_stats.h1_trans;
- cs->h2_trans += vh->conn_stats.h2_trans;
- cs->ws_upg += vh->conn_stats.ws_upg;
- cs->h2_upg += vh->conn_stats.h2_upg;
- cs->h2_alpn += vh->conn_stats.h2_alpn;
- cs->h2_subs += vh->conn_stats.h2_subs;
- cs->rejected += vh->conn_stats.rejected;
-
- vh = vh->vhost_next;
- }
-}
-
-const char *
-lws_cmdline_option(int argc, const char **argv, const char *val)
-{
- int n = (int)strlen(val), c = argc;
-
- while (--c > 0) {
-
- if (!strncmp(argv[c], val, n)) {
- if (!*(argv[c] + n) && c < argc - 1) {
- /* coverity treats unchecked argv as "tainted" */
- if (!argv[c + 1] || strlen(argv[c + 1]) > 1024)
- return NULL;
- return argv[c + 1];
- }
-
- return argv[c] + n;
- }
- }
-
- return NULL;
-}
-
-#ifdef LWS_WITH_SERVER_STATUS
-
-LWS_EXTERN int
-lws_json_dump_vhost(const struct lws_vhost *vh, char *buf, int len)
-{
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- static const char * const prots[] = {
- "http://",
- "https://",
- "file://",
- "cgi://",
- ">http://",
- ">https://",
- "callback://"
- };
-#endif
- char *orig = buf, *end = buf + len - 1, first = 1;
- int n = 0;
-
- if (len < 100)
- return 0;
-
- buf += lws_snprintf(buf, end - buf,
- "{\n \"name\":\"%s\",\n"
- " \"port\":\"%d\",\n"
- " \"use_ssl\":\"%d\",\n"
- " \"sts\":\"%d\",\n"
- " \"rx\":\"%llu\",\n"
- " \"tx\":\"%llu\",\n"
- " \"h1_conn\":\"%lu\",\n"
- " \"h1_trans\":\"%lu\",\n"
- " \"h2_trans\":\"%lu\",\n"
- " \"ws_upg\":\"%lu\",\n"
- " \"rejected\":\"%lu\",\n"
- " \"h2_upg\":\"%lu\",\n"
- " \"h2_alpn\":\"%lu\",\n"
- " \"h2_subs\":\"%lu\""
- ,
- vh->name, vh->listen_port,
-#if defined(LWS_WITH_TLS)
- vh->tls.use_ssl & LCCSCF_USE_SSL,
-#else
- 0,
-#endif
- !!(vh->options & LWS_SERVER_OPTION_STS),
- vh->conn_stats.rx, vh->conn_stats.tx,
- vh->conn_stats.h1_conn,
- vh->conn_stats.h1_trans,
- vh->conn_stats.h2_trans,
- vh->conn_stats.ws_upg,
- vh->conn_stats.rejected,
- vh->conn_stats.h2_upg,
- vh->conn_stats.h2_alpn,
- vh->conn_stats.h2_subs
- );
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- if (vh->http.mount_list) {
- const struct lws_http_mount *m = vh->http.mount_list;
-
- buf += lws_snprintf(buf, end - buf, ",\n \"mounts\":[");
- while (m) {
- if (!first)
- buf += lws_snprintf(buf, end - buf, ",");
- buf += lws_snprintf(buf, end - buf,
- "\n {\n \"mountpoint\":\"%s\",\n"
- " \"origin\":\"%s%s\",\n"
- " \"cache_max_age\":\"%d\",\n"
- " \"cache_reuse\":\"%d\",\n"
- " \"cache_revalidate\":\"%d\",\n"
- " \"cache_intermediaries\":\"%d\"\n"
- ,
- m->mountpoint,
- prots[m->origin_protocol],
- m->origin,
- m->cache_max_age,
- m->cache_reusable,
- m->cache_revalidate,
- m->cache_intermediaries);
- if (m->def)
- buf += lws_snprintf(buf, end - buf,
- ",\n \"default\":\"%s\"",
- m->def);
- buf += lws_snprintf(buf, end - buf, "\n }");
- first = 0;
- m = m->mount_next;
- }
- buf += lws_snprintf(buf, end - buf, "\n ]");
- }
-#endif
- if (vh->protocols) {
- n = 0;
- first = 1;
-
- buf += lws_snprintf(buf, end - buf, ",\n \"ws-protocols\":[");
- while (n < vh->count_protocols) {
- if (!first)
- buf += lws_snprintf(buf, end - buf, ",");
- buf += lws_snprintf(buf, end - buf,
- "\n {\n \"%s\":{\n"
- " \"status\":\"ok\"\n }\n }"
- ,
- vh->protocols[n].name);
- first = 0;
- n++;
- }
- buf += lws_snprintf(buf, end - buf, "\n ]");
- }
-
- buf += lws_snprintf(buf, end - buf, "\n}");
-
- return buf - orig;
-}
-
-
-LWS_EXTERN LWS_VISIBLE int
-lws_json_dump_context(const struct lws_context *context, char *buf, int len,
- int hide_vhosts)
-{
- char *orig = buf, *end = buf + len - 1, first = 1;
- const struct lws_vhost *vh = context->vhost_list;
- const struct lws_context_per_thread *pt;
- time_t t = time(NULL);
- int n, listening = 0, cgi_count = 0;
- struct lws_conn_stats cs;
- double d = 0;
-#ifdef LWS_WITH_CGI
- struct lws_cgi * const *pcgi;
-#endif
-
-#ifdef LWS_WITH_LIBUV
- uv_uptime(&d);
-#endif
-
- buf += lws_snprintf(buf, end - buf, "{ "
- "\"version\":\"%s\",\n"
- "\"uptime\":\"%ld\",\n",
- lws_get_library_version(),
- (long)d);
-
-#ifdef LWS_HAVE_GETLOADAVG
- {
- double d[3];
- int m;
-
- m = getloadavg(d, 3);
- for (n = 0; n < m; n++) {
- buf += lws_snprintf(buf, end - buf,
- "\"l%d\":\"%.2f\",\n",
- n + 1, d[n]);
- }
- }
-#endif
-
- buf += lws_snprintf(buf, end - buf, "\"contexts\":[\n");
-
- buf += lws_snprintf(buf, end - buf, "{ "
- "\"context_uptime\":\"%ld\",\n"
- "\"cgi_spawned\":\"%d\",\n"
- "\"pt_fd_max\":\"%d\",\n"
- "\"ah_pool_max\":\"%d\",\n"
- "\"deprecated\":\"%d\",\n"
- "\"wsi_alive\":\"%d\",\n",
- (unsigned long)(t - context->time_up),
- context->count_cgi_spawned,
- context->fd_limit_per_thread,
- context->max_http_header_pool,
- context->deprecated,
- context->count_wsi_allocated);
-
- buf += lws_snprintf(buf, end - buf, "\"pt\":[\n ");
- for (n = 0; n < context->count_threads; n++) {
- pt = &context->pt[n];
- if (n)
- buf += lws_snprintf(buf, end - buf, ",");
- buf += lws_snprintf(buf, end - buf,
- "\n {\n"
- " \"fds_count\":\"%d\",\n"
- " \"ah_pool_inuse\":\"%d\",\n"
- " \"ah_wait_list\":\"%d\"\n"
- " }",
- pt->fds_count,
- pt->http.ah_count_in_use,
- pt->http.ah_wait_list_length);
- }
-
- buf += lws_snprintf(buf, end - buf, "]");
-
- buf += lws_snprintf(buf, end - buf, ", \"vhosts\":[\n ");
-
- first = 1;
- vh = context->vhost_list;
- listening = 0;
- cs = context->conn_stats;
- lws_sum_stats(context, &cs);
- while (vh) {
-
- if (!hide_vhosts) {
- if (!first)
- if(buf != end)
- *buf++ = ',';
- buf += lws_json_dump_vhost(vh, buf, end - buf);
- first = 0;
- }
- if (vh->lserv_wsi)
- listening++;
- vh = vh->vhost_next;
- }
-
- buf += lws_snprintf(buf, end - buf,
- "],\n\"listen_wsi\":\"%d\",\n"
- " \"rx\":\"%llu\",\n"
- " \"tx\":\"%llu\",\n"
- " \"h1_conn\":\"%lu\",\n"
- " \"h1_trans\":\"%lu\",\n"
- " \"h2_trans\":\"%lu\",\n"
- " \"ws_upg\":\"%lu\",\n"
- " \"rejected\":\"%lu\",\n"
- " \"h2_alpn\":\"%lu\",\n"
- " \"h2_subs\":\"%lu\",\n"
- " \"h2_upg\":\"%lu\"",
- listening, cs.rx, cs.tx,
- cs.h1_conn,
- cs.h1_trans,
- cs.h2_trans,
- cs.ws_upg,
- cs.rejected,
- cs.h2_alpn,
- cs.h2_subs,
- cs.h2_upg);
-
-#ifdef LWS_WITH_CGI
- for (n = 0; n < context->count_threads; n++) {
- pt = &context->pt[n];
- pcgi = &pt->http.cgi_list;
-
- while (*pcgi) {
- pcgi = &(*pcgi)->cgi_list;
-
- cgi_count++;
- }
- }
-#endif
- buf += lws_snprintf(buf, end - buf, ",\n \"cgi_alive\":\"%d\"\n ",
- cgi_count);
-
- buf += lws_snprintf(buf, end - buf, "}");
-
-
- buf += lws_snprintf(buf, end - buf, "]}\n ");
-
- return buf - orig;
-}
-
-#endif
-
-#if defined(LWS_WITH_STATS)
-
-LWS_VISIBLE LWS_EXTERN uint64_t
-lws_stats_get(struct lws_context *context, int index)
-{
- if (index >= LWSSTATS_SIZE)
- return 0;
-
- return context->lws_stats[index];
-}
-
-LWS_VISIBLE LWS_EXTERN void
-lws_stats_log_dump(struct lws_context *context)
-{
- struct lws_vhost *v = context->vhost_list;
- int n, m;
-
- (void)m;
-
- if (!context->updated)
- return;
-
- context->updated = 0;
-
- lwsl_notice("\n");
- lwsl_notice("LWS internal statistics dump ----->\n");
- lwsl_notice("LWSSTATS_C_CONNECTIONS: %8llu\n",
- (unsigned long long)lws_stats_get(context,
- LWSSTATS_C_CONNECTIONS));
- lwsl_notice("LWSSTATS_C_API_CLOSE: %8llu\n",
- (unsigned long long)lws_stats_get(context,
- LWSSTATS_C_API_CLOSE));
- lwsl_notice("LWSSTATS_C_API_READ: %8llu\n",
- (unsigned long long)lws_stats_get(context,
- LWSSTATS_C_API_READ));
- lwsl_notice("LWSSTATS_C_API_LWS_WRITE: %8llu\n",
- (unsigned long long)lws_stats_get(context,
- LWSSTATS_C_API_LWS_WRITE));
- lwsl_notice("LWSSTATS_C_API_WRITE: %8llu\n",
- (unsigned long long)lws_stats_get(context,
- LWSSTATS_C_API_WRITE));
- lwsl_notice("LWSSTATS_C_WRITE_PARTIALS: %8llu\n",
- (unsigned long long)lws_stats_get(context,
- LWSSTATS_C_WRITE_PARTIALS));
- lwsl_notice("LWSSTATS_C_WRITEABLE_CB_REQ: %8llu\n",
- (unsigned long long)lws_stats_get(context,
- LWSSTATS_C_WRITEABLE_CB_REQ));
- lwsl_notice("LWSSTATS_C_WRITEABLE_CB_EFF_REQ: %8llu\n",
- (unsigned long long)lws_stats_get(context,
- LWSSTATS_C_WRITEABLE_CB_EFF_REQ));
- lwsl_notice("LWSSTATS_C_WRITEABLE_CB: %8llu\n",
- (unsigned long long)lws_stats_get(context,
- LWSSTATS_C_WRITEABLE_CB));
- lwsl_notice("LWSSTATS_C_SSL_CONNECTIONS_ACCEPT_SPIN: %8llu\n",
- (unsigned long long)lws_stats_get(context,
- LWSSTATS_C_SSL_CONNECTIONS_ACCEPT_SPIN));
- lwsl_notice("LWSSTATS_C_SSL_CONNECTIONS_FAILED: %8llu\n",
- (unsigned long long)lws_stats_get(context,
- LWSSTATS_C_SSL_CONNECTIONS_FAILED));
- lwsl_notice("LWSSTATS_C_SSL_CONNECTIONS_ACCEPTED: %8llu\n",
- (unsigned long long)lws_stats_get(context,
- LWSSTATS_C_SSL_CONNECTIONS_ACCEPTED));
- lwsl_notice("LWSSTATS_C_SSL_CONNS_HAD_RX: %8llu\n",
- (unsigned long long)lws_stats_get(context,
- LWSSTATS_C_SSL_CONNS_HAD_RX));
- lwsl_notice("LWSSTATS_C_PEER_LIMIT_AH_DENIED: %8llu\n",
- (unsigned long long)lws_stats_get(context,
- LWSSTATS_C_PEER_LIMIT_AH_DENIED));
- lwsl_notice("LWSSTATS_C_PEER_LIMIT_WSI_DENIED: %8llu\n",
- (unsigned long long)lws_stats_get(context,
- LWSSTATS_C_PEER_LIMIT_WSI_DENIED));
-
- lwsl_notice("LWSSTATS_C_TIMEOUTS: %8llu\n",
- (unsigned long long)lws_stats_get(context,
- LWSSTATS_C_TIMEOUTS));
- lwsl_notice("LWSSTATS_C_SERVICE_ENTRY: %8llu\n",
- (unsigned long long)lws_stats_get(context,
- LWSSTATS_C_SERVICE_ENTRY));
- lwsl_notice("LWSSTATS_B_READ: %8llu\n",
- (unsigned long long)lws_stats_get(context, LWSSTATS_B_READ));
- lwsl_notice("LWSSTATS_B_WRITE: %8llu\n",
- (unsigned long long)lws_stats_get(context, LWSSTATS_B_WRITE));
- lwsl_notice("LWSSTATS_B_PARTIALS_ACCEPTED_PARTS: %8llu\n",
- (unsigned long long)lws_stats_get(context,
- LWSSTATS_B_PARTIALS_ACCEPTED_PARTS));
- lwsl_notice("LWSSTATS_MS_SSL_CONNECTIONS_ACCEPTED_DELAY: %8llums\n",
- (unsigned long long)lws_stats_get(context,
- LWSSTATS_MS_SSL_CONNECTIONS_ACCEPTED_DELAY) / 1000);
- if (lws_stats_get(context, LWSSTATS_C_SSL_CONNECTIONS_ACCEPTED))
- lwsl_notice(" Avg accept delay: %8llums\n",
- (unsigned long long)(lws_stats_get(context,
- LWSSTATS_MS_SSL_CONNECTIONS_ACCEPTED_DELAY) /
- lws_stats_get(context,
- LWSSTATS_C_SSL_CONNECTIONS_ACCEPTED)) / 1000);
- lwsl_notice("LWSSTATS_MS_SSL_RX_DELAY: %8llums\n",
- (unsigned long long)lws_stats_get(context,
- LWSSTATS_MS_SSL_RX_DELAY) / 1000);
- if (lws_stats_get(context, LWSSTATS_C_SSL_CONNS_HAD_RX))
- lwsl_notice(" Avg accept-rx delay: %8llums\n",
- (unsigned long long)(lws_stats_get(context,
- LWSSTATS_MS_SSL_RX_DELAY) /
- lws_stats_get(context,
- LWSSTATS_C_SSL_CONNS_HAD_RX)) / 1000);
-
- lwsl_notice("LWSSTATS_MS_WRITABLE_DELAY: %8lluus\n",
- (unsigned long long)lws_stats_get(context,
- LWSSTATS_MS_WRITABLE_DELAY));
- lwsl_notice("LWSSTATS_MS_WORST_WRITABLE_DELAY: %8lluus\n",
- (unsigned long long)lws_stats_get(context,
- LWSSTATS_MS_WORST_WRITABLE_DELAY));
- if (lws_stats_get(context, LWSSTATS_C_WRITEABLE_CB))
- lwsl_notice(" Avg writable delay: %8lluus\n",
- (unsigned long long)(lws_stats_get(context,
- LWSSTATS_MS_WRITABLE_DELAY) /
- lws_stats_get(context, LWSSTATS_C_WRITEABLE_CB)));
- lwsl_notice("Simultaneous SSL restriction: %8d/%d\n",
- context->simultaneous_ssl,
- context->simultaneous_ssl_restriction);
-
- lwsl_notice("Live wsi: %8d\n",
- context->count_wsi_allocated);
-
- context->updated = 1;
-
- while (v) {
- if (v->lserv_wsi &&
- v->lserv_wsi->position_in_fds_table != LWS_NO_FDS_POS) {
-
- struct lws_context_per_thread *pt =
- &context->pt[(int)v->lserv_wsi->tsi];
- struct lws_pollfd *pfd;
-
- pfd = &pt->fds[v->lserv_wsi->position_in_fds_table];
-
- lwsl_notice(" Listen port %d actual POLLIN: %d\n",
- v->listen_port,
- (int)pfd->events & LWS_POLLIN);
- }
-
- v = v->vhost_next;
- }
-
- for (n = 0; n < context->count_threads; n++) {
- struct lws_context_per_thread *pt = &context->pt[n];
- struct lws *wl;
- int m = 0;
-
- lwsl_notice("PT %d\n", n + 1);
-
- lws_pt_lock(pt, __func__);
-
- lwsl_notice(" AH in use / max: %d / %d\n",
- pt->http.ah_count_in_use,
- context->max_http_header_pool);
-
- wl = pt->http.ah_wait_list;
- while (wl) {
- m++;
- wl = wl->http.ah_wait_list;
- }
-
- lwsl_notice(" AH wait list count / actual: %d / %d\n",
- pt->http.ah_wait_list_length, m);
-
- lws_pt_unlock(pt);
- }
-
-#if defined(LWS_WITH_PEER_LIMITS)
- m = 0;
- for (n = 0; n < (int)context->pl_hash_elements; n++) {
- lws_start_foreach_llp(struct lws_peer **, peer,
- context->pl_hash_table[n]) {
- m++;
- } lws_end_foreach_llp(peer, next);
- }
-
- lwsl_notice(" Peers: total active %d\n", m);
- if (m > 10) {
- m = 10;
- lwsl_notice(" (showing 10 peers only)\n");
- }
-
- if (m) {
- for (n = 0; n < (int)context->pl_hash_elements; n++) {
- char buf[72];
-
- lws_start_foreach_llp(struct lws_peer **, peer,
- context->pl_hash_table[n]) {
- struct lws_peer *df = *peer;
-
- if (!lws_plat_inet_ntop(df->af, df->addr, buf,
- sizeof(buf) - 1))
- strcpy(buf, "unknown");
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- lwsl_notice(" peer %s: count wsi: %d, count ah: %d\n",
- buf, df->count_wsi,
- df->http.count_ah);
-#else
- lwsl_notice(" peer %s: count wsi: %d\n",
- buf, df->count_wsi);
-#endif
-
- if (!--m)
- break;
- } lws_end_foreach_llp(peer, next);
- }
- }
-#endif
-
- lwsl_notice("\n");
-}
-
-void
-lws_stats_atomic_bump(struct lws_context * context,
- struct lws_context_per_thread *pt, int index, uint64_t bump)
-{
- lws_pt_stats_lock(pt);
- context->lws_stats[index] += bump;
- if (index != LWSSTATS_C_SERVICE_ENTRY)
- context->updated = 1;
- lws_pt_stats_unlock(pt);
-}
-
-void
-lws_stats_atomic_max(struct lws_context * context,
- struct lws_context_per_thread *pt, int index, uint64_t val)
-{
- lws_pt_stats_lock(pt);
- if (val > context->lws_stats[index]) {
- context->lws_stats[index] = val;
- context->updated = 1;
- }
- lws_pt_stats_unlock(pt);
-}
-
-#endif
-
diff --git a/thirdparty/libwebsockets/core/output.c b/thirdparty/libwebsockets/core/output.c
deleted file mode 100644
index 11965a06b9..0000000000
--- a/thirdparty/libwebsockets/core/output.c
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010-2017 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- */
-
-#include "core/private.h"
-
-/*
- * notice this returns number of bytes consumed, or -1
- */
-int lws_issue_raw(struct lws *wsi, unsigned char *buf, size_t len)
-{
- struct lws_context *context = lws_get_context(wsi);
- struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
- size_t real_len = len;
- unsigned int n;
-
- // lwsl_hexdump_err(buf, len);
-
- /*
- * Detect if we got called twice without going through the
- * event loop to handle pending. This would be caused by either
- * back-to-back writes in one WRITABLE (illegal) or calling lws_write()
- * from outside the WRITABLE callback (illegal).
- */
- if (wsi->could_have_pending) {
- lwsl_hexdump_level(LLL_ERR, buf, len);
- lwsl_err("** %p: vh: %s, prot: %s, role %s: "
- "Illegal back-to-back write of %lu detected...\n",
- wsi, wsi->vhost->name, wsi->protocol->name,
- wsi->role_ops->name,
- (unsigned long)len);
- // assert(0);
-
- return -1;
- }
-
- lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_C_API_WRITE, 1);
-
- if (!len)
- return 0;
- /* just ignore sends after we cleared the truncation buffer */
- if (lwsi_state(wsi) == LRS_FLUSHING_BEFORE_CLOSE && !wsi->trunc_len)
- return (int)len;
-
- if (wsi->trunc_len && (buf < wsi->trunc_alloc ||
- buf > (wsi->trunc_alloc + wsi->trunc_len + wsi->trunc_offset))) {
- lwsl_hexdump_level(LLL_ERR, buf, len);
- lwsl_err("** %p: vh: %s, prot: %s, Sending new %lu, pending truncated ...\n"
- " It's illegal to do an lws_write outside of\n"
- " the writable callback: fix your code\n",
- wsi, wsi->vhost->name, wsi->protocol->name,
- (unsigned long)len);
- assert(0);
-
- return -1;
- }
-
- if (!wsi->http2_substream && !lws_socket_is_valid(wsi->desc.sockfd))
- lwsl_warn("** error invalid sock but expected to send\n");
-
- /* limit sending */
- if (wsi->protocol->tx_packet_size)
- n = (int)wsi->protocol->tx_packet_size;
- else {
- n = (int)wsi->protocol->rx_buffer_size;
- if (!n)
- n = context->pt_serv_buf_size;
- }
- n += LWS_PRE + 4;
- if (n > len)
- n = (int)len;
-
- /* nope, send it on the socket directly */
- lws_latency_pre(context, wsi);
- n = lws_ssl_capable_write(wsi, buf, n);
- lws_latency(context, wsi, "send lws_issue_raw", n, n == len);
-
- /* something got written, it can have been truncated now */
- wsi->could_have_pending = 1;
-
- switch (n) {
- case LWS_SSL_CAPABLE_ERROR:
- /* we're going to close, let close know sends aren't possible */
- wsi->socket_is_permanently_unusable = 1;
- return -1;
- case LWS_SSL_CAPABLE_MORE_SERVICE:
- /*
- * nothing got sent, not fatal. Retry the whole thing later,
- * ie, implying treat it was a truncated send so it gets
- * retried
- */
- n = 0;
- break;
- }
-
- /*
- * we were already handling a truncated send?
- */
- if (wsi->trunc_len) {
- lwsl_info("%p partial adv %d (vs %ld)\n", wsi, n, (long)real_len);
- wsi->trunc_offset += n;
- wsi->trunc_len -= n;
-
- if (!wsi->trunc_len) {
- lwsl_info("** %p partial send completed\n", wsi);
- /* done with it, but don't free it */
- n = (int)real_len;
- if (lwsi_state(wsi) == LRS_FLUSHING_BEFORE_CLOSE) {
- lwsl_info("** %p signalling to close now\n", wsi);
- return -1; /* retry closing now */
- }
-
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
-#if !defined(LWS_WITHOUT_SERVER)
- if (wsi->http.deferred_transaction_completed) {
- lwsl_notice("%s: partial completed, doing "
- "deferred transaction completed\n",
- __func__);
- wsi->http.deferred_transaction_completed = 0;
- return lws_http_transaction_completed(wsi);
- }
-#endif
-#endif
- }
- /* always callback on writeable */
- lws_callback_on_writable(wsi);
-
- return n;
- }
-
- if ((unsigned int)n == real_len)
- /* what we just sent went out cleanly */
- return n;
-
- /*
- * Newly truncated send. Buffer the remainder (it will get
- * first priority next time the socket is writable).
- */
- lwsl_debug("%p new partial sent %d from %lu total\n", wsi, n,
- (unsigned long)real_len);
-
- lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_C_WRITE_PARTIALS, 1);
- lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_B_PARTIALS_ACCEPTED_PARTS, n);
-
- /*
- * - if we still have a suitable malloc lying around, use it
- * - or, if too small, reallocate it
- * - or, if no buffer, create it
- */
- if (!wsi->trunc_alloc || real_len - n > wsi->trunc_alloc_len) {
- lws_free(wsi->trunc_alloc);
-
- wsi->trunc_alloc_len = (unsigned int)(real_len - n);
- wsi->trunc_alloc = lws_malloc(real_len - n,
- "truncated send alloc");
- if (!wsi->trunc_alloc) {
- lwsl_err("truncated send: unable to malloc %lu\n",
- (unsigned long)(real_len - n));
- return -1;
- }
- }
- wsi->trunc_offset = 0;
- wsi->trunc_len = (unsigned int)(real_len - n);
- memcpy(wsi->trunc_alloc, buf + n, real_len - n);
-
-#if !defined(LWS_WITH_ESP32)
- if (lws_wsi_is_udp(wsi)) {
- /* stash original destination for fulfilling UDP partials */
- wsi->udp->sa_pending = wsi->udp->sa;
- wsi->udp->salen_pending = wsi->udp->salen;
- }
-#endif
-
- /* since something buffered, force it to get another chance to send */
- lws_callback_on_writable(wsi);
-
- return (int)real_len;
-}
-
-LWS_VISIBLE int lws_write(struct lws *wsi, unsigned char *buf, size_t len,
- enum lws_write_protocol wp)
-{
- struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
-
- if (wsi->parent_carries_io) {
- struct lws_write_passthru pas;
-
- pas.buf = buf;
- pas.len = len;
- pas.wp = wp;
- pas.wsi = wsi;
-
- if (wsi->parent->protocol->callback(wsi->parent,
- LWS_CALLBACK_CHILD_WRITE_VIA_PARENT,
- wsi->parent->user_space,
- (void *)&pas, 0))
- return 1;
-
- return (int)len;
- }
-
- lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_C_API_LWS_WRITE, 1);
-
- if ((int)len < 0) {
- lwsl_err("%s: suspicious len int %d, ulong %lu\n", __func__,
- (int)len, (unsigned long)len);
- return -1;
- }
-
- lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_B_WRITE, len);
-
-#ifdef LWS_WITH_ACCESS_LOG
- wsi->http.access_log.sent += len;
-#endif
- if (wsi->vhost)
- wsi->vhost->conn_stats.tx += len;
-
- assert(wsi->role_ops);
- if (!wsi->role_ops->write_role_protocol)
- return lws_issue_raw(wsi, buf, len);
-
- return wsi->role_ops->write_role_protocol(wsi, buf, len, &wp);
-}
-
-LWS_VISIBLE int
-lws_ssl_capable_read_no_ssl(struct lws *wsi, unsigned char *buf, int len)
-{
- struct lws_context *context = wsi->context;
- struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
- int n = 0;
-
- lws_stats_atomic_bump(context, pt, LWSSTATS_C_API_READ, 1);
-
- if (lws_wsi_is_udp(wsi)) {
-#if !defined(LWS_WITH_ESP32)
- wsi->udp->salen = sizeof(wsi->udp->sa);
- n = recvfrom(wsi->desc.sockfd, (char *)buf, len, 0,
- &wsi->udp->sa, &wsi->udp->salen);
-#endif
- } else
- n = recv(wsi->desc.sockfd, (char *)buf, len, 0);
-
- if (n >= 0) {
- if (wsi->vhost)
- wsi->vhost->conn_stats.rx += n;
- lws_stats_atomic_bump(context, pt, LWSSTATS_B_READ, n);
-
- return n;
- }
-
- if (LWS_ERRNO == LWS_EAGAIN ||
- LWS_ERRNO == LWS_EWOULDBLOCK ||
- LWS_ERRNO == LWS_EINTR)
- return LWS_SSL_CAPABLE_MORE_SERVICE;
-
- lwsl_notice("error on reading from skt : %d\n", LWS_ERRNO);
- return LWS_SSL_CAPABLE_ERROR;
-}
-
-LWS_VISIBLE int
-lws_ssl_capable_write_no_ssl(struct lws *wsi, unsigned char *buf, int len)
-{
- int n = 0;
-
- if (lws_wsi_is_udp(wsi)) {
-#if !defined(LWS_WITH_ESP32)
- if (wsi->trunc_len)
- n = sendto(wsi->desc.sockfd, buf, len, 0, &wsi->udp->sa_pending, wsi->udp->salen_pending);
- else
- n = sendto(wsi->desc.sockfd, buf, len, 0, &wsi->udp->sa, wsi->udp->salen);
-#endif
- } else
- n = send(wsi->desc.sockfd, (char *)buf, len, MSG_NOSIGNAL);
-// lwsl_info("%s: sent len %d result %d", __func__, len, n);
- if (n >= 0)
- return n;
-
- if (LWS_ERRNO == LWS_EAGAIN ||
- LWS_ERRNO == LWS_EWOULDBLOCK ||
- LWS_ERRNO == LWS_EINTR) {
- if (LWS_ERRNO == LWS_EWOULDBLOCK) {
- lws_set_blocking_send(wsi);
- }
-
- return LWS_SSL_CAPABLE_MORE_SERVICE;
- }
-
- lwsl_debug("ERROR writing len %d to skt fd %d err %d / errno %d\n",
- len, wsi->desc.sockfd, n, LWS_ERRNO);
-
- return LWS_SSL_CAPABLE_ERROR;
-}
-
-LWS_VISIBLE int
-lws_ssl_pending_no_ssl(struct lws *wsi)
-{
- (void)wsi;
-#if defined(LWS_WITH_ESP32)
- return 100;
-#else
- return 0;
-#endif
-}
diff --git a/thirdparty/libwebsockets/core/pollfd.c b/thirdparty/libwebsockets/core/pollfd.c
deleted file mode 100644
index 2a632ce8ec..0000000000
--- a/thirdparty/libwebsockets/core/pollfd.c
+++ /dev/null
@@ -1,616 +0,0 @@
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010-2017 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- */
-
-#include "core/private.h"
-
-int
-_lws_change_pollfd(struct lws *wsi, int _and, int _or, struct lws_pollargs *pa)
-{
-#if !defined(LWS_WITH_LIBUV) && !defined(LWS_WITH_LIBEV) && !defined(LWS_WITH_LIBEVENT)
- volatile struct lws_context_per_thread *vpt;
-#endif
- struct lws_context_per_thread *pt;
- struct lws_context *context;
- int ret = 0, pa_events = 1;
- struct lws_pollfd *pfd;
- int sampled_tid, tid;
-
- if (!wsi)
- return 0;
-
- assert(wsi->position_in_fds_table == LWS_NO_FDS_POS ||
- wsi->position_in_fds_table >= 0);
-
- if (wsi->position_in_fds_table == LWS_NO_FDS_POS)
- return 0;
-
- if (((volatile struct lws *)wsi)->handling_pollout &&
- !_and && _or == LWS_POLLOUT) {
- /*
- * Happening alongside service thread handling POLLOUT.
- * The danger is when he is finished, he will disable POLLOUT,
- * countermanding what we changed here.
- *
- * Instead of changing the fds, inform the service thread
- * what happened, and ask it to leave POLLOUT active on exit
- */
- ((volatile struct lws *)wsi)->leave_pollout_active = 1;
- /*
- * by definition service thread is not in poll wait, so no need
- * to cancel service
- */
-
- lwsl_debug("%s: using leave_pollout_active\n", __func__);
-
- return 0;
- }
-
- context = wsi->context;
- pt = &context->pt[(int)wsi->tsi];
-
- assert(wsi->position_in_fds_table < (int)pt->fds_count);
-
-#if !defined(LWS_WITH_LIBUV) && \
- !defined(LWS_WITH_LIBEV) && \
- !defined(LWS_WITH_LIBEVENT)
- /*
- * This only applies when we use the default poll() event loop.
- *
- * BSD can revert pa->events at any time, when the kernel decides to
- * exit from poll(). We can't protect against it using locking.
- *
- * Therefore we must check first if the service thread is in poll()
- * wait; if so, we know we must be being called from a foreign thread,
- * and we must keep a strictly ordered list of changes we made instead
- * of trying to apply them, since when poll() exits, which may happen
- * at any time it would revert our changes.
- *
- * The plat code will apply them when it leaves the poll() wait
- * before doing anything else.
- */
-
- vpt = (volatile struct lws_context_per_thread *)pt;
-
- vpt->foreign_spinlock = 1;
- lws_memory_barrier();
-
- if (vpt->inside_poll) {
- struct lws_foreign_thread_pollfd *ftp, **ftp1;
- /*
- * We are certainly a foreign thread trying to change events
- * while the service thread is in the poll() wait.
- *
- * Create a list of changes to be applied after poll() exit,
- * instead of trying to apply them now.
- */
- ftp = lws_malloc(sizeof(*ftp), "ftp");
- if (!ftp) {
- vpt->foreign_spinlock = 0;
- lws_memory_barrier();
- ret = -1;
- goto bail;
- }
-
- ftp->_and = _and;
- ftp->_or = _or;
- ftp->fd_index = wsi->position_in_fds_table;
- ftp->next = NULL;
-
- /* place at END of list to maintain order */
- ftp1 = (struct lws_foreign_thread_pollfd **)
- &vpt->foreign_pfd_list;
- while (*ftp1)
- ftp1 = &((*ftp1)->next);
-
- *ftp1 = ftp;
- vpt->foreign_spinlock = 0;
- lws_memory_barrier();
- lws_cancel_service_pt(wsi);
-
- return 0;
- }
-
- vpt->foreign_spinlock = 0;
- lws_memory_barrier();
-#endif
-
- pfd = &pt->fds[wsi->position_in_fds_table];
- pa->fd = wsi->desc.sockfd;
- lwsl_debug("%s: wsi %p: fd %d events %d -> %d\n", __func__, wsi, pa->fd, pfd->events, (pfd->events & ~_and) | _or);
- pa->prev_events = pfd->events;
- pa->events = pfd->events = (pfd->events & ~_and) | _or;
-
- if (wsi->http2_substream)
- return 0;
-
- if (wsi->vhost &&
- wsi->vhost->protocols[0].callback(wsi,
- LWS_CALLBACK_CHANGE_MODE_POLL_FD,
- wsi->user_space, (void *)pa, 0)) {
- ret = -1;
- goto bail;
- }
-
- if (context->event_loop_ops->io) {
- if (_and & LWS_POLLIN)
- context->event_loop_ops->io(wsi,
- LWS_EV_STOP | LWS_EV_READ);
-
- if (_or & LWS_POLLIN)
- context->event_loop_ops->io(wsi,
- LWS_EV_START | LWS_EV_READ);
-
- if (_and & LWS_POLLOUT)
- context->event_loop_ops->io(wsi,
- LWS_EV_STOP | LWS_EV_WRITE);
-
- if (_or & LWS_POLLOUT)
- context->event_loop_ops->io(wsi,
- LWS_EV_START | LWS_EV_WRITE);
- }
-
- /*
- * if we changed something in this pollfd...
- * ... and we're running in a different thread context
- * than the service thread...
- * ... and the service thread is waiting ...
- * then cancel it to force a restart with our changed events
- */
- pa_events = pa->prev_events != pa->events;
-
- if (pa_events) {
- if (lws_plat_change_pollfd(context, wsi, pfd)) {
- lwsl_info("%s failed\n", __func__);
- ret = -1;
- goto bail;
- }
- sampled_tid = context->service_tid;
- if (sampled_tid && wsi->vhost) {
- tid = wsi->vhost->protocols[0].callback(wsi,
- LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0);
- if (tid == -1) {
- ret = -1;
- goto bail;
- }
- if (tid != sampled_tid)
- lws_cancel_service_pt(wsi);
- }
- }
-
-bail:
- return ret;
-}
-
-#ifndef LWS_NO_SERVER
-/*
- * Enable or disable listen sockets on this pt globally...
- * it's modulated according to the pt having space for a new accept.
- */
-static void
-lws_accept_modulation(struct lws_context *context,
- struct lws_context_per_thread *pt, int allow)
-{
- struct lws_vhost *vh = context->vhost_list;
- struct lws_pollargs pa1;
-
- while (vh) {
- if (vh->lserv_wsi) {
- if (allow)
- _lws_change_pollfd(vh->lserv_wsi,
- 0, LWS_POLLIN, &pa1);
- else
- _lws_change_pollfd(vh->lserv_wsi,
- LWS_POLLIN, 0, &pa1);
- }
- vh = vh->vhost_next;
- }
-}
-#endif
-
-int
-__insert_wsi_socket_into_fds(struct lws_context *context, struct lws *wsi)
-{
- struct lws_pollargs pa = { wsi->desc.sockfd, LWS_POLLIN, 0 };
- struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
- int ret = 0;
-
-
- lwsl_debug("%s: %p: tsi=%d, sock=%d, pos-in-fds=%d\n",
- __func__, wsi, wsi->tsi, wsi->desc.sockfd, pt->fds_count);
-
- if ((unsigned int)pt->fds_count >= context->fd_limit_per_thread) {
- lwsl_err("Too many fds (%d vs %d)\n", context->max_fds,
- context->fd_limit_per_thread );
- return 1;
- }
-
-#if !defined(_WIN32)
- if (wsi->desc.sockfd - lws_plat_socket_offset() >= context->max_fds) {
- lwsl_err("Socket fd %d is too high (%d) offset %d\n",
- wsi->desc.sockfd, context->max_fds, lws_plat_socket_offset());
- return 1;
- }
-#endif
-
- assert(wsi);
- assert(wsi->event_pipe || wsi->vhost);
- assert(lws_socket_is_valid(wsi->desc.sockfd));
-
- if (wsi->vhost &&
- wsi->vhost->protocols[0].callback(wsi, LWS_CALLBACK_LOCK_POLL,
- wsi->user_space, (void *) &pa, 1))
- return -1;
-
- pt->count_conns++;
- insert_wsi(context, wsi);
- wsi->position_in_fds_table = pt->fds_count;
-
- pt->fds[wsi->position_in_fds_table].fd = wsi->desc.sockfd;
- pt->fds[wsi->position_in_fds_table].events = LWS_POLLIN;
- pa.events = pt->fds[pt->fds_count].events;
-
- lws_plat_insert_socket_into_fds(context, wsi);
-
- /* external POLL support via protocol 0 */
- if (wsi->vhost &&
- wsi->vhost->protocols[0].callback(wsi, LWS_CALLBACK_ADD_POLL_FD,
- wsi->user_space, (void *) &pa, 0))
- ret = -1;
-#ifndef LWS_NO_SERVER
- /* if no more room, defeat accepts on this thread */
- if ((unsigned int)pt->fds_count == context->fd_limit_per_thread - 1)
- lws_accept_modulation(context, pt, 0);
-#endif
-
- if (wsi->vhost &&
- wsi->vhost->protocols[0].callback(wsi, LWS_CALLBACK_UNLOCK_POLL,
- wsi->user_space, (void *)&pa, 1))
- ret = -1;
-
- return ret;
-}
-
-int
-__remove_wsi_socket_from_fds(struct lws *wsi)
-{
- struct lws_context *context = wsi->context;
- struct lws_pollargs pa = { wsi->desc.sockfd, 0, 0 };
- struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
- struct lws *end_wsi;
- int v;
- int m, ret = 0;
-
- if (wsi->parent_carries_io) {
- lws_same_vh_protocol_remove(wsi);
- return 0;
- }
-
-#if !defined(_WIN32)
- if (wsi->desc.sockfd - lws_plat_socket_offset() > context->max_fds) {
- lwsl_err("fd %d too high (%d)\n", wsi->desc.sockfd,
- context->max_fds);
- return 1;
- }
-#endif
-
- if (wsi->vhost &&
- wsi->vhost->protocols[0].callback(wsi, LWS_CALLBACK_LOCK_POLL,
- wsi->user_space, (void *)&pa, 1))
- return -1;
-
- lws_same_vh_protocol_remove(wsi);
-
- /* the guy who is to be deleted's slot index in pt->fds */
- m = wsi->position_in_fds_table;
-
- /* these are the only valid possibilities for position_in_fds_table */
- assert(m == LWS_NO_FDS_POS || (m >= 0 &&
- (unsigned int)m < pt->fds_count));
-
- if (context->event_loop_ops->io)
- context->event_loop_ops->io(wsi,
- LWS_EV_STOP | LWS_EV_READ | LWS_EV_WRITE |
- LWS_EV_PREPARE_DELETION);
-
- lwsl_debug("%s: wsi=%p, sock=%d, fds pos=%d, end guy pos=%d, endfd=%d\n",
- __func__, wsi, wsi->desc.sockfd, wsi->position_in_fds_table,
- pt->fds_count, pt->fds[pt->fds_count].fd);
-
- if (m != LWS_NO_FDS_POS) {
-
- /* have the last guy take up the now vacant slot */
- pt->fds[m] = pt->fds[pt->fds_count - 1];
- /* this decrements pt->fds_count */
- lws_plat_delete_socket_from_fds(context, wsi, m);
- v = (int) pt->fds[m].fd;
- /* end guy's "position in fds table" is now the deletion guy's old one */
- end_wsi = wsi_from_fd(context, v);
- if (!end_wsi) {
- lwsl_err("no wsi for fd %d at pos %d, pt->fds_count=%d\n",
- (int)pt->fds[m].fd, m, pt->fds_count);
- assert(0);
- } else
- end_wsi->position_in_fds_table = m;
-
- /* deletion guy's lws_lookup entry needs nuking */
- delete_from_fd(context, wsi->desc.sockfd);
-
- /* removed wsi has no position any more */
- wsi->position_in_fds_table = LWS_NO_FDS_POS;
- }
-
- /* remove also from external POLL support via protocol 0 */
- if (lws_socket_is_valid(wsi->desc.sockfd) && wsi->vhost &&
- wsi->vhost->protocols[0].callback(wsi, LWS_CALLBACK_DEL_POLL_FD,
- wsi->user_space, (void *) &pa, 0))
- ret = -1;
-
-#ifndef LWS_NO_SERVER
- if (!context->being_destroyed &&
- /* if this made some room, accept connects on this thread */
- (unsigned int)pt->fds_count < context->fd_limit_per_thread - 1)
- lws_accept_modulation(context, pt, 1);
-#endif
-
- if (wsi->vhost &&
- wsi->vhost->protocols[0].callback(wsi, LWS_CALLBACK_UNLOCK_POLL,
- wsi->user_space, (void *) &pa, 1))
- ret = -1;
-
- return ret;
-}
-
-int
-__lws_change_pollfd(struct lws *wsi, int _and, int _or)
-{
- struct lws_context *context;
- struct lws_pollargs pa;
- int ret = 0;
-
- if (!wsi || (!wsi->protocol && !wsi->event_pipe) ||
- wsi->position_in_fds_table == LWS_NO_FDS_POS)
- return 0;
-
- context = lws_get_context(wsi);
- if (!context)
- return 1;
-
- if (wsi->vhost &&
- wsi->vhost->protocols[0].callback(wsi, LWS_CALLBACK_LOCK_POLL,
- wsi->user_space, (void *) &pa, 0))
- return -1;
-
- ret = _lws_change_pollfd(wsi, _and, _or, &pa);
- if (wsi->vhost &&
- wsi->vhost->protocols[0].callback(wsi, LWS_CALLBACK_UNLOCK_POLL,
- wsi->user_space, (void *) &pa, 0))
- ret = -1;
-
- return ret;
-}
-
-int
-lws_change_pollfd(struct lws *wsi, int _and, int _or)
-{
- struct lws_context_per_thread *pt;
- int ret = 0;
-
- pt = &wsi->context->pt[(int)wsi->tsi];
-
- lws_pt_lock(pt, __func__);
- ret = __lws_change_pollfd(wsi, _and, _or);
- lws_pt_unlock(pt);
-
- return ret;
-}
-
-LWS_VISIBLE int
-lws_callback_on_writable(struct lws *wsi)
-{
- struct lws_context_per_thread *pt;
- int n;
-
- if (lwsi_state(wsi) == LRS_SHUTDOWN)
- return 0;
-
- if (wsi->socket_is_permanently_unusable)
- return 0;
-
- pt = &wsi->context->pt[(int)wsi->tsi];
-
- if (wsi->parent_carries_io) {
-#if defined(LWS_WITH_STATS)
- if (!wsi->active_writable_req_us) {
- wsi->active_writable_req_us = time_in_microseconds();
- lws_stats_atomic_bump(wsi->context, pt,
- LWSSTATS_C_WRITEABLE_CB_EFF_REQ, 1);
- }
-#endif
- n = lws_callback_on_writable(wsi->parent);
- if (n < 0)
- return n;
-
- wsi->parent_pending_cb_on_writable = 1;
- return 1;
- }
-
- lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_C_WRITEABLE_CB_REQ, 1);
-#if defined(LWS_WITH_STATS)
- if (!wsi->active_writable_req_us) {
- wsi->active_writable_req_us = time_in_microseconds();
- lws_stats_atomic_bump(wsi->context, pt,
- LWSSTATS_C_WRITEABLE_CB_EFF_REQ, 1);
- }
-#endif
-
-
- if (wsi->role_ops->callback_on_writable) {
- if (wsi->role_ops->callback_on_writable(wsi))
- return 1;
- wsi = lws_get_network_wsi(wsi);
- }
-
- if (wsi->position_in_fds_table == LWS_NO_FDS_POS) {
- lwsl_debug("%s: failed to find socket %d\n", __func__,
- wsi->desc.sockfd);
- return -1;
- }
-
- if (__lws_change_pollfd(wsi, 0, LWS_POLLOUT))
- return -1;
-
- return 1;
-}
-
-
-/*
- * stitch protocol choice into the vh protocol linked list
- * We always insert ourselves at the start of the list
- *
- * X <-> B
- * X <-> pAn <-> pB
- *
- * Illegal to attach more than once without detach inbetween
- */
-void
-lws_same_vh_protocol_insert(struct lws *wsi, int n)
-{
- if (wsi->same_vh_protocol_prev || wsi->same_vh_protocol_next) {
- lws_same_vh_protocol_remove(wsi);
- lwsl_notice("Attempted to attach wsi twice to same vh prot\n");
- }
-
- lws_vhost_lock(wsi->vhost);
-
- wsi->same_vh_protocol_prev = &wsi->vhost->same_vh_protocol_list[n];
- /* old first guy is our next */
- wsi->same_vh_protocol_next = wsi->vhost->same_vh_protocol_list[n];
- /* we become the new first guy */
- wsi->vhost->same_vh_protocol_list[n] = wsi;
-
- if (wsi->same_vh_protocol_next)
- /* old first guy points back to us now */
- wsi->same_vh_protocol_next->same_vh_protocol_prev =
- &wsi->same_vh_protocol_next;
-
- wsi->on_same_vh_list = 1;
-
- lws_vhost_unlock(wsi->vhost);
-}
-
-void
-lws_same_vh_protocol_remove(struct lws *wsi)
-{
- /*
- * detach ourselves from vh protocol list if we're on one
- * A -> B -> C
- * A -> C , or, B -> C, or A -> B
- *
- * OK to call on already-detached wsi
- */
- lwsl_info("%s: removing same prot wsi %p\n", __func__, wsi);
-
- if (!wsi->vhost || !wsi->on_same_vh_list)
- return;
-
- lws_vhost_lock(wsi->vhost);
-
- if (wsi->same_vh_protocol_prev) {
- assert (*(wsi->same_vh_protocol_prev) == wsi);
- lwsl_info("have prev %p, setting him to our next %p\n",
- wsi->same_vh_protocol_prev,
- wsi->same_vh_protocol_next);
-
- /* guy who pointed to us should point to our next */
- *(wsi->same_vh_protocol_prev) = wsi->same_vh_protocol_next;
- }
-
- /* our next should point back to our prev */
- if (wsi->same_vh_protocol_next)
- wsi->same_vh_protocol_next->same_vh_protocol_prev =
- wsi->same_vh_protocol_prev;
-
- wsi->same_vh_protocol_prev = NULL;
- wsi->same_vh_protocol_next = NULL;
- wsi->on_same_vh_list = 0;
-
- lws_vhost_unlock(wsi->vhost);
-}
-
-
-LWS_VISIBLE int
-lws_callback_on_writable_all_protocol_vhost(const struct lws_vhost *vhost,
- const struct lws_protocols *protocol)
-{
- struct lws *wsi;
-
- if (protocol < vhost->protocols ||
- protocol >= (vhost->protocols + vhost->count_protocols)) {
- 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;
- }
-
- wsi = vhost->same_vh_protocol_list[protocol - vhost->protocols];
- while (wsi) {
- assert(wsi->protocol == protocol);
- assert(*wsi->same_vh_protocol_prev == wsi);
- if (wsi->same_vh_protocol_next)
- assert(wsi->same_vh_protocol_next->
- same_vh_protocol_prev ==
- &wsi->same_vh_protocol_next);
-
- lws_callback_on_writable(wsi);
- wsi = wsi->same_vh_protocol_next;
- }
-
- return 0;
-}
-
-LWS_VISIBLE int
-lws_callback_on_writable_all_protocol(const struct lws_context *context,
- const struct lws_protocols *protocol)
-{
- struct lws_vhost *vhost;
- int n;
-
- if (!context)
- return 0;
-
- vhost = context->vhost_list;
-
- while (vhost) {
- for (n = 0; n < vhost->count_protocols; n++)
- if (protocol->callback ==
- vhost->protocols[n].callback &&
- !strcmp(protocol->name, vhost->protocols[n].name))
- break;
- if (n != vhost->count_protocols)
- lws_callback_on_writable_all_protocol_vhost(
- vhost, &vhost->protocols[n]);
-
- vhost = vhost->vhost_next;
- }
-
- return 0;
-}
diff --git a/thirdparty/libwebsockets/core/private.h b/thirdparty/libwebsockets/core/private.h
deleted file mode 100644
index 73748b0498..0000000000
--- a/thirdparty/libwebsockets/core/private.h
+++ /dev/null
@@ -1,1770 +0,0 @@
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010 - 2018 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- */
-
-#include "lws_config.h"
-#include "lws_config_private.h"
-
-#if defined(LWS_WITH_CGI) && defined(LWS_HAVE_VFORK)
- #define _GNU_SOURCE
-#endif
-
-#if defined(__COVERITY__) && !defined(LWS_COVERITY_WORKAROUND)
- #define LWS_COVERITY_WORKAROUND
- typedef float _Float32;
- typedef float _Float64;
- typedef float _Float128;
- typedef float _Float32x;
- typedef float _Float64x;
- typedef float _Float128x;
-#endif
-
-#ifdef LWS_HAVE_SYS_TYPES_H
- #include <sys/types.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <ctype.h>
-#include <limits.h>
-#include <stdarg.h>
-#include <inttypes.h>
-
-#if defined(LWS_WITH_ESP32)
- #define MSG_NOSIGNAL 0
- #define SOMAXCONN 3
-#endif
-
-#define STORE_IN_ROM
-#include <assert.h>
-#if LWS_MAX_SMP > 1
- #include <pthread.h>
-#endif
-
-#ifdef LWS_HAVE_SYS_STAT_H
- #include <sys/stat.h>
-#endif
-
-#if defined(WIN32) || defined(_WIN32)
-
- #ifndef WIN32_LEAN_AND_MEAN
- #define WIN32_LEAN_AND_MEAN
- #endif
-
- #if (WINVER < 0x0501)
- #undef WINVER
- #undef _WIN32_WINNT
- #define WINVER 0x0501
- #define _WIN32_WINNT WINVER
- #endif
-
- #define LWS_NO_DAEMONIZE
- #define LWS_ERRNO WSAGetLastError()
- #define LWS_EAGAIN WSAEWOULDBLOCK
- #define LWS_EALREADY WSAEALREADY
- #define LWS_EINPROGRESS WSAEINPROGRESS
- #define LWS_EINTR WSAEINTR
- #define LWS_EISCONN WSAEISCONN
- #define LWS_EWOULDBLOCK WSAEWOULDBLOCK
- #define MSG_NOSIGNAL 0
- #define SHUT_RDWR SD_BOTH
- #define SOL_TCP IPPROTO_TCP
- #define SHUT_WR SD_SEND
-
- #define compatible_close(fd) closesocket(fd)
- #define lws_set_blocking_send(wsi) wsi->sock_send_blocking = 1
- #define LWS_SOCK_INVALID (INVALID_SOCKET)
-
- #include <winsock2.h>
- #include <ws2tcpip.h>
- #include <windows.h>
- #include <tchar.h>
- #ifdef LWS_HAVE_IN6ADDR_H
- #include <in6addr.h>
- #endif
- #include <mstcpip.h>
- #include <io.h>
-
- #if !defined(LWS_HAVE_ATOLL)
- #if defined(LWS_HAVE__ATOI64)
- #define atoll _atoi64
- #else
- #warning No atoll or _atoi64 available, using atoi
- #define atoll atoi
- #endif
- #endif
-
- #ifndef __func__
- #define __func__ __FUNCTION__
- #endif
-
- #ifdef LWS_HAVE__VSNPRINTF
- #define vsnprintf _vsnprintf
- #endif
-
- /* we don't have an implementation for this on windows... */
- int kill(int pid, int sig);
- int fork(void);
- #ifndef SIGINT
- #define SIGINT 2
- #endif
-
-#else /* not windows --> */
-
- #include <fcntl.h>
- #include <strings.h>
- #include <unistd.h>
- #include <sys/types.h>
-
- #ifndef __cplusplus
- #include <errno.h>
- #endif
- #include <netdb.h>
- #include <signal.h>
- #include <sys/socket.h>
-
- #if defined(LWS_BUILTIN_GETIFADDRS)
- #include "./misc/getifaddrs.h"
- #else
- #if !defined(LWS_WITH_ESP32)
- #if defined(__HAIKU__)
- #define _BSD_SOURCE
- #endif
- #include <ifaddrs.h>
- #endif
- #endif
- #if defined (__ANDROID__)
- #include <syslog.h>
- #include <sys/resource.h>
- #elif defined (__sun) || defined(__HAIKU__) || defined(__QNX__)
- #include <syslog.h>
- #else
- #if !defined(LWS_WITH_ESP32)
- #include <sys/syslog.h>
- #endif
- #endif
- #include <netdb.h>
- #if !defined(LWS_WITH_ESP32)
- #include <sys/mman.h>
- #include <sys/un.h>
- #include <netinet/in.h>
- #include <netinet/tcp.h>
- #include <arpa/inet.h>
- #include <poll.h>
- #endif
- #ifndef LWS_NO_FORK
- #ifdef LWS_HAVE_SYS_PRCTL_H
- #include <sys/prctl.h>
- #endif
- #endif
-
- #include <sys/time.h>
-
- #define LWS_ERRNO errno
- #define LWS_EAGAIN EAGAIN
- #define LWS_EALREADY EALREADY
- #define LWS_EINPROGRESS EINPROGRESS
- #define LWS_EINTR EINTR
- #define LWS_EISCONN EISCONN
- #define LWS_EWOULDBLOCK EWOULDBLOCK
-
- #define lws_set_blocking_send(wsi)
-
- #define LWS_SOCK_INVALID (-1)
-#endif /* not windows */
-
-#ifndef LWS_HAVE_BZERO
- #ifndef bzero
- #define bzero(b, len) (memset((b), '\0', (len)), (void) 0)
- #endif
-#endif
-
-#ifndef LWS_HAVE_STRERROR
- #define strerror(x) ""
-#endif
-
-
-#define lws_socket_is_valid(x) (x != LWS_SOCK_INVALID)
-
-#include "libwebsockets.h"
-
-#include "tls/private.h"
-
-#if defined(WIN32) || defined(_WIN32)
- #include <gettimeofday.h>
-
- #ifndef BIG_ENDIAN
- #define BIG_ENDIAN 4321 /* to show byte order (taken from gcc) */
- #endif
- #ifndef LITTLE_ENDIAN
- #define LITTLE_ENDIAN 1234
- #endif
- #ifndef BYTE_ORDER
- #define BYTE_ORDER LITTLE_ENDIAN
- #endif
-
- #undef __P
- #ifndef __P
- #if __STDC__
- #define __P(protos) protos
- #else
- #define __P(protos) ()
- #endif
- #endif
-
-#else /* not windows */
- static LWS_INLINE int compatible_close(int fd) { return close(fd); }
-
- #include <sys/stat.h>
- #include <sys/time.h>
-
- #if defined(__APPLE__)
- #include <machine/endian.h>
- #elif defined(__FreeBSD__)
- #include <sys/endian.h>
- #elif defined(__linux__)
- #include <endian.h>
- #endif
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if defined(__QNX__)
- #include <gulliver.h>
- #if defined(__LITTLEENDIAN__)
- #define BYTE_ORDER __LITTLEENDIAN__
- #define LITTLE_ENDIAN __LITTLEENDIAN__
- #define BIG_ENDIAN 4321 /* to show byte order (taken from gcc); for suppres warning that BIG_ENDIAN is not defined. */
- #endif
- #if defined(__BIGENDIAN__)
- #define BYTE_ORDER __BIGENDIAN__
- #define LITTLE_ENDIAN 1234 /* to show byte order (taken from gcc); for suppres warning that LITTLE_ENDIAN is not defined. */
- #define BIG_ENDIAN __BIGENDIAN__
- #endif
-#endif
-
-#if defined(__sun) && defined(__GNUC__)
-
- #include <arpa/nameser_compat.h>
-
- #if !defined (BYTE_ORDER)
- #define BYTE_ORDER __BYTE_ORDER__
- #endif
-
- #if !defined(LITTLE_ENDIAN)
- #define LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__
- #endif
-
- #if !defined(BIG_ENDIAN)
- #define BIG_ENDIAN __ORDER_BIG_ENDIAN__
- #endif
-
-#endif /* sun + GNUC */
-
-#if !defined(BYTE_ORDER)
- #define BYTE_ORDER __BYTE_ORDER
-#endif
-#if !defined(LITTLE_ENDIAN)
- #define LITTLE_ENDIAN __LITTLE_ENDIAN
-#endif
-#if !defined(BIG_ENDIAN)
- #define BIG_ENDIAN __BIG_ENDIAN
-#endif
-
-
-/*
- * Mac OSX as well as iOS do not define the MSG_NOSIGNAL flag,
- * but happily have something equivalent in the SO_NOSIGPIPE flag.
- */
-#ifdef __APPLE__
-#define MSG_NOSIGNAL SO_NOSIGPIPE
-#endif
-
-/*
- * Solaris 11.X only supports POSIX 2001, MSG_NOSIGNAL appears in
- * POSIX 2008.
- */
-#ifdef __sun
- #define MSG_NOSIGNAL 0
-#endif
-
-#ifdef _WIN32
- #ifndef FD_HASHTABLE_MODULUS
- #define FD_HASHTABLE_MODULUS 32
- #endif
-#endif
-
-#ifndef LWS_DEF_HEADER_LEN
-#define LWS_DEF_HEADER_LEN 4096
-#endif
-#ifndef LWS_DEF_HEADER_POOL
-#define LWS_DEF_HEADER_POOL 4
-#endif
-#ifndef LWS_MAX_PROTOCOLS
-#define LWS_MAX_PROTOCOLS 5
-#endif
-#ifndef LWS_MAX_EXTENSIONS_ACTIVE
-#define LWS_MAX_EXTENSIONS_ACTIVE 1
-#endif
-#ifndef LWS_MAX_EXT_OFFERS
-#define LWS_MAX_EXT_OFFERS 8
-#endif
-#ifndef SPEC_LATEST_SUPPORTED
-#define SPEC_LATEST_SUPPORTED 13
-#endif
-#ifndef AWAITING_TIMEOUT
-#define AWAITING_TIMEOUT 20
-#endif
-#ifndef CIPHERS_LIST_STRING
-#define CIPHERS_LIST_STRING "DEFAULT"
-#endif
-#ifndef LWS_SOMAXCONN
-#define LWS_SOMAXCONN SOMAXCONN
-#endif
-
-#define MAX_WEBSOCKET_04_KEY_LEN 128
-
-#ifndef SYSTEM_RANDOM_FILEPATH
-#define SYSTEM_RANDOM_FILEPATH "/dev/urandom"
-#endif
-
-#define LWS_H2_RX_SCRATCH_SIZE 512
-
-#if defined(WIN32) || defined(_WIN32)
- // Visual studio older than 2015 and WIN_CE has only _stricmp
- #if (defined(_MSC_VER) && _MSC_VER < 1900) || defined(_WIN32_WCE)
- #define strcasecmp _stricmp
- #elif !defined(__MINGW32__)
- #define strcasecmp stricmp
- #endif
- #define getdtablesize() 30000
-#endif
-
-/*
- * All lws_tls...() functions must return this type, converting the
- * native backend result and doing the extra work to determine which one
- * as needed.
- *
- * Native TLS backend return codes are NOT ALLOWED outside the backend.
- *
- * Non-SSL mode also uses these types.
- */
-enum lws_ssl_capable_status {
- LWS_SSL_CAPABLE_ERROR = -1, /* it failed */
- LWS_SSL_CAPABLE_DONE = 0, /* it succeeded */
- LWS_SSL_CAPABLE_MORE_SERVICE_READ = -2, /* retry WANT_READ */
- LWS_SSL_CAPABLE_MORE_SERVICE_WRITE = -3, /* retry WANT_WRITE */
- LWS_SSL_CAPABLE_MORE_SERVICE = -4, /* general retry */
-};
-
-#if defined(__clang__)
-#define lws_memory_barrier() __sync_synchronize()
-#elif defined(__GNUC__)
-#define lws_memory_barrier() __sync_synchronize()
-#else
-#define lws_memory_barrier()
-#endif
-
-/*
- *
- * ------ roles ------
- *
- */
-
-#include "roles/private.h"
-
-/* null-terminated array of pointers to roles lws built with */
-extern const struct lws_role_ops *available_roles[];
-
-#define LWS_FOR_EVERY_AVAILABLE_ROLE_START(xx) { \
- const struct lws_role_ops **ppxx = available_roles; \
- while (*ppxx) { \
- const struct lws_role_ops *xx = *ppxx++;
-
-#define LWS_FOR_EVERY_AVAILABLE_ROLE_END }}
-
-/*
- *
- * ------ event_loop ops ------
- *
- */
-
-#include "event-libs/private.h"
-
-/* enums of socks version */
-enum socks_version {
- SOCKS_VERSION_4 = 4,
- SOCKS_VERSION_5 = 5
-};
-
-/* enums of subnegotiation version */
-enum socks_subnegotiation_version {
- SOCKS_SUBNEGOTIATION_VERSION_1 = 1,
-};
-
-/* enums of socks commands */
-enum socks_command {
- SOCKS_COMMAND_CONNECT = 1,
- SOCKS_COMMAND_BIND = 2,
- SOCKS_COMMAND_UDP_ASSOCIATE = 3
-};
-
-/* enums of socks address type */
-enum socks_atyp {
- SOCKS_ATYP_IPV4 = 1,
- SOCKS_ATYP_DOMAINNAME = 3,
- SOCKS_ATYP_IPV6 = 4
-};
-
-/* enums of socks authentication methods */
-enum socks_auth_method {
- SOCKS_AUTH_NO_AUTH = 0,
- SOCKS_AUTH_GSSAPI = 1,
- SOCKS_AUTH_USERNAME_PASSWORD = 2
-};
-
-/* enums of subnegotiation status */
-enum socks_subnegotiation_status {
- SOCKS_SUBNEGOTIATION_STATUS_SUCCESS = 0,
-};
-
-/* enums of socks request reply */
-enum socks_request_reply {
- SOCKS_REQUEST_REPLY_SUCCESS = 0,
- SOCKS_REQUEST_REPLY_FAILURE_GENERAL = 1,
- SOCKS_REQUEST_REPLY_CONNECTION_NOT_ALLOWED = 2,
- SOCKS_REQUEST_REPLY_NETWORK_UNREACHABLE = 3,
- SOCKS_REQUEST_REPLY_HOST_UNREACHABLE = 4,
- SOCKS_REQUEST_REPLY_CONNECTION_REFUSED = 5,
- SOCKS_REQUEST_REPLY_TTL_EXPIRED = 6,
- SOCKS_REQUEST_REPLY_COMMAND_NOT_SUPPORTED = 7,
- SOCKS_REQUEST_REPLY_ATYP_NOT_SUPPORTED = 8
-};
-
-/* enums used to generate socks messages */
-enum socks_msg_type {
- /* greeting */
- SOCKS_MSG_GREETING,
- /* credential, user name and password */
- SOCKS_MSG_USERNAME_PASSWORD,
- /* connect command */
- SOCKS_MSG_CONNECT
-};
-
-enum {
- LWS_RXFLOW_ALLOW = (1 << 0),
- LWS_RXFLOW_PENDING_CHANGE = (1 << 1),
-};
-
-struct lws_ring {
- void *buf;
- void (*destroy_element)(void *element);
- uint32_t buflen;
- uint32_t element_len;
- uint32_t head;
- uint32_t oldest_tail;
-};
-
-struct lws_protocols;
-struct lws;
-
-struct lws_io_watcher {
-#ifdef LWS_WITH_LIBEV
- struct lws_io_watcher_libev ev;
-#endif
-#ifdef LWS_WITH_LIBUV
- struct lws_io_watcher_libuv uv;
-#endif
-#ifdef LWS_WITH_LIBEVENT
- struct lws_io_watcher_libevent event;
-#endif
- struct lws_context *context;
-
- uint8_t actual_events;
-};
-
-struct lws_signal_watcher {
-#ifdef LWS_WITH_LIBEV
- struct lws_signal_watcher_libev ev;
-#endif
-#ifdef LWS_WITH_LIBUV
- struct lws_signal_watcher_libuv uv;
-#endif
-#ifdef LWS_WITH_LIBEVENT
- struct lws_signal_watcher_libevent event;
-#endif
- struct lws_context *context;
-};
-
-#ifdef _WIN32
-#define LWS_FD_HASH(fd) ((fd ^ (fd >> 8) ^ (fd >> 16)) % FD_HASHTABLE_MODULUS)
-struct lws_fd_hashtable {
- struct lws **wsi;
- int length;
-};
-#endif
-
-struct lws_foreign_thread_pollfd {
- struct lws_foreign_thread_pollfd *next;
- int fd_index;
- int _and;
- int _or;
-};
-
-
-#define LWS_HRTIMER_NOWAIT (0x7fffffffffffffffll)
-
-/*
- * so we can have n connections being serviced simultaneously,
- * these things need to be isolated per-thread.
- */
-
-struct lws_context_per_thread {
-#if LWS_MAX_SMP > 1
- pthread_mutex_t lock;
- pthread_mutex_t lock_stats;
- pthread_t lock_owner;
- const char *last_lock_reason;
-#endif
-
- struct lws_context *context;
-
- /*
- * usable by anything in the service code, but only if the scope
- * does not last longer than the service action (since next service
- * of any socket can likewise use it and overwrite)
- */
- unsigned char *serv_buf;
-
- struct lws_dll_lws dll_head_timeout;
- struct lws_dll_lws dll_head_hrtimer;
- struct lws_dll_lws dll_head_buflist; /* guys with pending rxflow */
-
-#if defined(LWS_WITH_TLS)
- struct lws_pt_tls tls;
-#endif
-
- struct lws_pollfd *fds;
- volatile struct lws_foreign_thread_pollfd * volatile foreign_pfd_list;
-#ifdef _WIN32
- WSAEVENT *events;
-#endif
- lws_sockfd_type dummy_pipe_fds[2];
- struct lws *pipe_wsi;
-
- /* --- role based members --- */
-
-#if defined(LWS_ROLE_WS) && !defined(LWS_WITHOUT_EXTENSIONS)
- struct lws_pt_role_ws ws;
-#endif
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- struct lws_pt_role_http http;
-#endif
-
- /* --- event library based members --- */
-
-#if defined(LWS_WITH_LIBEV)
- struct lws_pt_eventlibs_libev ev;
-#endif
-#if defined(LWS_WITH_LIBUV)
- struct lws_pt_eventlibs_libuv uv;
-#endif
-#if defined(LWS_WITH_LIBEVENT)
- struct lws_pt_eventlibs_libevent event;
-#endif
-
-#if defined(LWS_WITH_LIBEV) || defined(LWS_WITH_LIBUV) || defined(LWS_WITH_LIBEVENT)
- struct lws_signal_watcher w_sigint;
-#endif
-
- /* --- */
-
- unsigned long count_conns;
- unsigned int fds_count;
-
- volatile unsigned char inside_poll;
- volatile unsigned char foreign_spinlock;
-
- unsigned char tid;
-
- unsigned char lock_depth;
- unsigned char inside_service:1;
- unsigned char event_loop_foreign:1;
- unsigned char event_loop_destroy_processing_done:1;
-};
-
-struct lws_conn_stats {
- unsigned long long rx, tx;
- unsigned long h1_conn, h1_trans, h2_trans, ws_upg, h2_alpn, h2_subs,
- h2_upg, rejected;
-};
-
-void
-lws_sum_stats(const struct lws_context *ctx, struct lws_conn_stats *cs);
-
-struct lws_timed_vh_protocol {
- struct lws_timed_vh_protocol *next;
- const struct lws_protocols *protocol;
- time_t time;
- int reason;
-};
-
-/*
- * virtual host -related context information
- * vhostwide SSL context
- * vhostwide proxy
- *
- * hierarchy:
- *
- * context -> vhost -> wsi
- *
- * incoming connection non-SSL vhost binding:
- *
- * listen socket -> wsi -> select vhost after first headers
- *
- * incoming connection SSL vhost binding:
- *
- * SSL SNI -> wsi -> bind after SSL negotiation
- */
-
-
-struct lws_vhost {
-#if !defined(LWS_WITHOUT_CLIENT)
- char proxy_basic_auth_token[128];
-#endif
-#if LWS_MAX_SMP > 1
- pthread_mutex_t lock;
-#endif
-
-#if defined(LWS_ROLE_H2)
- struct lws_vhost_role_h2 h2;
-#endif
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- struct lws_vhost_role_http http;
-#endif
-#if defined(LWS_ROLE_WS) && !defined(LWS_WITHOUT_EXTENSIONS)
- struct lws_vhost_role_ws ws;
-#endif
-
-#if defined(LWS_WITH_SOCKS5)
- char socks_proxy_address[128];
- char socks_user[96];
- char socks_password[96];
-#endif
-#if defined(LWS_WITH_LIBEV)
- struct lws_io_watcher w_accept;
-#endif
- struct lws_conn_stats conn_stats;
- struct lws_context *context;
- struct lws_vhost *vhost_next;
-
- struct lws *lserv_wsi;
- const char *name;
- const char *iface;
-
-#if !defined(LWS_WITH_ESP32) && !defined(OPTEE_TA) && !defined(WIN32)
- int bind_iface;
-#endif
- const struct lws_protocols *protocols;
- void **protocol_vh_privs;
- const struct lws_protocol_vhost_options *pvo;
- const struct lws_protocol_vhost_options *headers;
- struct lws **same_vh_protocol_list;
- struct lws_vhost *no_listener_vhost_list;
-#if !defined(LWS_NO_CLIENT)
- struct lws_dll_lws dll_active_client_conns;
-#endif
-
-#if defined(LWS_WITH_TLS)
- struct lws_vhost_tls tls;
-#endif
-
- struct lws_timed_vh_protocol *timed_vh_protocol_list;
- void *user;
-
- int listen_port;
-
-#if defined(LWS_WITH_SOCKS5)
- unsigned int socks_proxy_port;
-#endif
- unsigned int options;
- int count_protocols;
- int ka_time;
- int ka_probes;
- int ka_interval;
- int keepalive_timeout;
- int timeout_secs_ah_idle;
-
-#ifdef LWS_WITH_ACCESS_LOG
- int log_fd;
-#endif
-
- unsigned int created_vhost_protocols:1;
- unsigned int being_destroyed:1;
-
- unsigned char default_protocol_index;
- unsigned char raw_protocol_index;
-};
-
-struct lws_deferred_free
-{
- struct lws_deferred_free *next;
- time_t deadline;
- void *payload;
-};
-
-typedef union {
-#ifdef LWS_WITH_IPV6
- struct sockaddr_in6 sa6;
-#endif
- struct sockaddr_in sa4;
-} sockaddr46;
-
-
-#if defined(LWS_WITH_PEER_LIMITS)
-struct lws_peer {
- struct lws_peer *next;
- struct lws_peer *peer_wait_list;
-
- time_t time_created;
- time_t time_closed_all;
-
- uint8_t addr[32];
- uint32_t hash;
- uint32_t count_wsi;
- uint32_t total_wsi;
-
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- struct lws_peer_role_http http;
-#endif
-
- uint8_t af;
-};
-#endif
-
-/*
- * the rest is managed per-context, that includes
- *
- * - processwide single fd -> wsi lookup
- * - contextwide headers pool
- */
-
-struct lws_context {
- time_t last_timeout_check_s;
- time_t last_ws_ping_pong_check_s;
- time_t time_up;
- time_t time_discontiguity;
- time_t time_fixup;
- const struct lws_plat_file_ops *fops;
- struct lws_plat_file_ops fops_platform;
- struct lws_context **pcontext_finalize;
-
- const struct lws_tls_ops *tls_ops;
-
-#if defined(LWS_WITH_HTTP2)
- struct http2_settings set;
-#endif
-#if defined(LWS_WITH_ZIP_FOPS)
- struct lws_plat_file_ops fops_zip;
-#endif
- struct lws_context_per_thread pt[LWS_MAX_SMP];
- struct lws_conn_stats conn_stats;
-#if LWS_MAX_SMP > 1
- pthread_mutex_t lock;
- int lock_depth;
-#endif
-#ifdef _WIN32
-/* different implementation between unix and windows */
- struct lws_fd_hashtable fd_hashtable[FD_HASHTABLE_MODULUS];
-#else
- struct lws **lws_lookup; /* fd to wsi */
-#endif
- struct lws_vhost *vhost_list;
- struct lws_vhost *no_listener_vhost_list;
- struct lws_vhost *vhost_pending_destruction_list;
- struct lws_plugin *plugin_list;
- struct lws_deferred_free *deferred_free_list;
-#if defined(LWS_WITH_PEER_LIMITS)
- struct lws_peer **pl_hash_table;
- struct lws_peer *peer_wait_list;
- time_t next_cull;
-#endif
-
- void *external_baggage_free_on_destroy;
- const struct lws_token_limits *token_limits;
- void *user_space;
- const struct lws_protocol_vhost_options *reject_service_keywords;
- lws_reload_func deprecation_cb;
- void (*eventlib_signal_cb)(void *event_lib_handle, int signum);
-
-#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
- cap_value_t caps[4];
- char count_caps;
-#endif
-
-#if defined(LWS_WITH_LIBEV)
- struct lws_context_eventlibs_libev ev;
-#endif
-#if defined(LWS_WITH_LIBUV)
- struct lws_context_eventlibs_libuv uv;
-#endif
-#if defined(LWS_WITH_LIBEVENT)
- struct lws_context_eventlibs_libevent event;
-#endif
- struct lws_event_loop_ops *event_loop_ops;
-
-
-#if defined(LWS_WITH_TLS)
- struct lws_context_tls tls;
-#endif
-
- char canonical_hostname[128];
- const char *server_string;
-
-#ifdef LWS_LATENCY
- unsigned long worst_latency;
- char worst_latency_info[256];
-#endif
-
-#if defined(LWS_WITH_STATS)
- uint64_t lws_stats[LWSSTATS_SIZE];
- uint64_t last_dump;
- int updated;
-#endif
-#if defined(LWS_WITH_ESP32)
- unsigned long time_last_state_dump;
- uint32_t last_free_heap;
-#endif
-
- int max_fds;
- int count_event_loop_static_asset_handles;
- int started_with_parent;
- int uid, gid;
-
- int fd_random;
-
- int count_wsi_allocated;
- int count_cgi_spawned;
- unsigned int options;
- unsigned int fd_limit_per_thread;
- unsigned int timeout_secs;
- unsigned int pt_serv_buf_size;
- int max_http_header_data;
- int max_http_header_pool;
- int simultaneous_ssl_restriction;
- int simultaneous_ssl;
-#if defined(LWS_WITH_PEER_LIMITS)
- uint32_t pl_hash_elements; /* protected by context->lock */
- uint32_t count_peers; /* protected by context->lock */
- unsigned short ip_limit_ah;
- unsigned short ip_limit_wsi;
-#endif
- unsigned int deprecated:1;
- unsigned int being_destroyed:1;
- unsigned int being_destroyed1:1;
- unsigned int being_destroyed2:1;
- unsigned int requested_kill:1;
- unsigned int protocol_init_done:1;
- unsigned int doing_protocol_init:1;
- unsigned int done_protocol_destroy_cb:1;
- unsigned int finalize_destroy_after_internal_loops_stopped:1;
- /*
- * set to the Thread ID that's doing the service loop just before entry
- * to poll indicates service thread likely idling in poll()
- * volatile because other threads may check it as part of processing
- * for pollfd event change.
- */
- volatile int service_tid;
- int service_tid_detected;
-
- short count_threads;
- short plugin_protocol_count;
- short plugin_extension_count;
- short server_string_len;
- unsigned short ws_ping_pong_interval;
- unsigned short deprecation_pending_listen_close_count;
-
- uint8_t max_fi;
-};
-
-int
-lws_check_deferred_free(struct lws_context *context, int force);
-
-#define lws_get_context_protocol(ctx, x) ctx->vhost_list->protocols[x]
-#define lws_get_vh_protocol(vh, x) vh->protocols[x]
-
-LWS_EXTERN void
-__lws_close_free_wsi_final(struct lws *wsi);
-LWS_EXTERN void
-lws_libuv_closehandle(struct lws *wsi);
-LWS_EXTERN int
-lws_libuv_check_watcher_active(struct lws *wsi);
-
-LWS_VISIBLE LWS_EXTERN int
-lws_plat_plugins_init(struct lws_context * context, const char * const *d);
-
-LWS_VISIBLE LWS_EXTERN int
-lws_plat_plugins_destroy(struct lws_context * context);
-
-LWS_EXTERN void
-lws_restart_ws_ping_pong_timer(struct lws *wsi);
-
-struct lws *
-lws_adopt_socket_vhost(struct lws_vhost *vh, lws_sockfd_type accept_fd);
-
-int
-lws_jws_base64_enc(const char *in, size_t in_len, char *out, size_t out_max);
-
-void
-lws_vhost_destroy1(struct lws_vhost *vh);
-
-enum {
- LWS_EV_READ = (1 << 0),
- LWS_EV_WRITE = (1 << 1),
- LWS_EV_START = (1 << 2),
- LWS_EV_STOP = (1 << 3),
-
- LWS_EV_PREPARE_DELETION = (1 << 31),
-};
-
-
-#if defined(LWS_WITH_ESP32)
-LWS_EXTERN int
-lws_find_string_in_file(const char *filename, const char *string, int stringlen);
-#endif
-
-#ifdef LWS_WITH_IPV6
-#define LWS_IPV6_ENABLED(vh) \
- (!lws_check_opt(vh->context->options, LWS_SERVER_OPTION_DISABLE_IPV6) && \
- !lws_check_opt(vh->options, LWS_SERVER_OPTION_DISABLE_IPV6))
-#else
-#define LWS_IPV6_ENABLED(context) (0)
-#endif
-
-#ifdef LWS_WITH_UNIX_SOCK
-#define LWS_UNIX_SOCK_ENABLED(vhost) \
- (vhost->options & LWS_SERVER_OPTION_UNIX_SOCK)
-#else
-#define LWS_UNIX_SOCK_ENABLED(vhost) (0)
-#endif
-
-enum uri_path_states {
- URIPS_IDLE,
- URIPS_SEEN_SLASH,
- URIPS_SEEN_SLASH_DOT,
- URIPS_SEEN_SLASH_DOT_DOT,
-};
-
-enum uri_esc_states {
- URIES_IDLE,
- URIES_SEEN_PERCENT,
- URIES_SEEN_PERCENT_H1,
-};
-
-
-#ifndef LWS_NO_CLIENT
-struct client_info_stash {
- char *address;
- char *path;
- char *host;
- char *origin;
- char *protocol;
- char *method;
- char *iface;
- char *alpn;
-};
-#endif
-
-
-signed char char_to_hex(const char c);
-
-
-struct lws_buflist {
- struct lws_buflist *next;
-
- size_t len;
- size_t pos;
-
- uint8_t buf[1]; /* true length of this is set by the oversize malloc */
-};
-
-#define lws_wsi_is_udp(___wsi) (!!___wsi->udp)
-
-#define LWS_H2_FRAME_HEADER_LENGTH 9
-
-
-struct lws {
- /* structs */
-
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- struct _lws_http_mode_related http;
-#endif
-#if defined(LWS_ROLE_H2)
- struct _lws_h2_related h2;
-#endif
-#if defined(LWS_ROLE_WS)
- struct _lws_websocket_related *ws; /* allocated if we upgrade to ws */
-#endif
-
- const struct lws_role_ops *role_ops;
- lws_wsi_state_t wsistate;
- lws_wsi_state_t wsistate_pre_close;
-
- /* lifetime members */
-
-#if defined(LWS_WITH_LIBEV) || defined(LWS_WITH_LIBUV) || defined(LWS_WITH_LIBEVENT)
- struct lws_io_watcher w_read;
-#endif
-#if defined(LWS_WITH_LIBEV) || defined(LWS_WITH_LIBEVENT)
- struct lws_io_watcher w_write;
-#endif
-
- /* pointers */
-
- struct lws_context *context;
- struct lws_vhost *vhost;
- struct lws *parent; /* points to parent, if any */
- struct lws *child_list; /* points to first child */
- struct lws *sibling_list; /* subsequent children at same level */
-
- const struct lws_protocols *protocol;
- struct lws **same_vh_protocol_prev, *same_vh_protocol_next;
-
- struct lws_dll_lws dll_timeout;
- struct lws_dll_lws dll_hrtimer;
- struct lws_dll_lws dll_buflist; /* guys with pending rxflow */
-
-#if defined(LWS_WITH_PEER_LIMITS)
- struct lws_peer *peer;
-#endif
-
- struct lws_udp *udp;
-#ifndef LWS_NO_CLIENT
- struct client_info_stash *stash;
- char *client_hostname_copy;
- struct lws_dll_lws dll_active_client_conns;
- struct lws_dll_lws dll_client_transaction_queue_head;
- struct lws_dll_lws dll_client_transaction_queue;
-#endif
- void *user_space;
- void *opaque_parent_data;
-
- struct lws_buflist *buflist;
-
- /* truncated send handling */
- unsigned char *trunc_alloc; /* non-NULL means buffering in progress */
-
-#if defined(LWS_WITH_TLS)
- struct lws_lws_tls tls;
-#endif
-
- lws_sock_file_fd_type desc; /* .filefd / .sockfd */
-#if defined(LWS_WITH_STATS)
- uint64_t active_writable_req_us;
-#if defined(LWS_WITH_TLS)
- uint64_t accept_start_us;
-#endif
-#endif
-
- lws_usec_t pending_timer; /* hrtimer fires */
- time_t pending_timeout_set; /* second-resolution timeout start */
-
-#ifdef LWS_LATENCY
- unsigned long action_start;
- unsigned long latency_start;
-#endif
-
- /* ints */
-#define LWS_NO_FDS_POS (-1)
- int position_in_fds_table;
- unsigned int trunc_alloc_len; /* size of malloc */
- unsigned int trunc_offset; /* where we are in terms of spilling */
- unsigned int trunc_len; /* how much is buffered */
-#ifndef LWS_NO_CLIENT
- int chunk_remaining;
-#endif
- unsigned int cache_secs;
-
- unsigned int hdr_parsing_completed:1;
- unsigned int http2_substream:1;
- unsigned int upgraded_to_http2:1;
- unsigned int h2_stream_carries_ws:1;
- unsigned int seen_nonpseudoheader:1;
- unsigned int listener:1;
- unsigned int user_space_externally_allocated:1;
- unsigned int socket_is_permanently_unusable:1;
- unsigned int rxflow_change_to:2;
- unsigned int conn_stat_done:1;
- unsigned int cache_reuse:1;
- unsigned int cache_revalidate:1;
- unsigned int cache_intermediaries:1;
- unsigned int favoured_pollin:1;
- unsigned int sending_chunked:1;
- unsigned int interpreting:1;
- unsigned int already_did_cce:1;
- unsigned int told_user_closed:1;
- unsigned int told_event_loop_closed:1;
- unsigned int waiting_to_send_close_frame:1;
- unsigned int close_needs_ack:1;
- unsigned int ipv6:1;
- unsigned int parent_carries_io:1;
- unsigned int parent_pending_cb_on_writable:1;
- unsigned int cgi_stdout_zero_length:1;
- unsigned int seen_zero_length_recv:1;
- unsigned int rxflow_will_be_applied:1;
- unsigned int event_pipe:1;
- unsigned int on_same_vh_list:1;
- unsigned int handling_404:1;
- unsigned int protocol_bind_balance:1;
-
- unsigned int could_have_pending:1; /* detect back-to-back writes */
- unsigned int outer_will_close:1;
-
-#ifdef LWS_WITH_ACCESS_LOG
- unsigned int access_log_pending:1;
-#endif
-#ifndef LWS_NO_CLIENT
- unsigned int do_ws:1; /* whether we are doing http or ws flow */
- unsigned int chunked:1; /* if the clientside connection is chunked */
- unsigned int client_rx_avail:1;
- unsigned int client_http_body_pending:1;
- unsigned int transaction_from_pipeline_queue:1;
- unsigned int keepalive_active:1;
- unsigned int keepalive_rejected:1;
- unsigned int client_pipeline:1;
- unsigned int client_h2_alpn:1;
- unsigned int client_h2_substream:1;
-#endif
-
-#ifdef _WIN32
- unsigned int sock_send_blocking:1;
-#endif
-
-#ifndef LWS_NO_CLIENT
- unsigned short c_port;
-#endif
- unsigned short pending_timeout_limit;
-
- /* chars */
-
- char lws_rx_parse_state; /* enum lws_rx_parse_state */
- char rx_frame_type; /* enum lws_write_protocol */
- char pending_timeout; /* enum pending_timeout */
- char tsi; /* thread service index we belong to */
- char protocol_interpret_idx;
- char redirects;
- uint8_t rxflow_bitmap;
-#ifdef LWS_WITH_CGI
- char cgi_channel; /* which of stdin/out/err */
- char hdr_state;
-#endif
-#ifndef LWS_NO_CLIENT
- char chunk_parser; /* enum lws_chunk_parser */
-#endif
-#if defined(LWS_WITH_CGI) || !defined(LWS_NO_CLIENT)
- char reason_bf; /* internal writeable callback reason bitfield */
-#endif
-#if defined(LWS_WITH_STATS) && defined(LWS_WITH_TLS)
- char seen_rx;
-#endif
- uint8_t ws_over_h2_count;
- /* volatile to make sure code is aware other thread can change */
- volatile char handling_pollout;
- volatile char leave_pollout_active;
-};
-
-#define lws_is_flowcontrolled(w) (!!(wsi->rxflow_bitmap))
-
-void
-lws_service_do_ripe_rxflow(struct lws_context_per_thread *pt);
-
-LWS_EXTERN int log_level;
-
-LWS_EXTERN int
-lws_socket_bind(struct lws_vhost *vhost, lws_sockfd_type sockfd, int port,
- const char *iface);
-
-#if defined(LWS_WITH_IPV6)
-LWS_EXTERN unsigned long
-lws_get_addr_scope(const char *ipaddr);
-#endif
-
-LWS_EXTERN void
-lws_close_free_wsi(struct lws *wsi, enum lws_close_status, const char *caller);
-LWS_EXTERN void
-__lws_close_free_wsi(struct lws *wsi, enum lws_close_status, const char *caller);
-
-LWS_EXTERN void
-__lws_free_wsi(struct lws *wsi);
-
-LWS_EXTERN int
-__remove_wsi_socket_from_fds(struct lws *wsi);
-LWS_EXTERN int
-lws_rxflow_cache(struct lws *wsi, unsigned char *buf, int n, int len);
-
-#ifndef LWS_LATENCY
-static LWS_INLINE void
-lws_latency(struct lws_context *context, struct lws *wsi, const char *action,
- int ret, int completion) {
- do {
- (void)context; (void)wsi; (void)action; (void)ret;
- (void)completion;
- } while (0);
-}
-static LWS_INLINE void
-lws_latency_pre(struct lws_context *context, struct lws *wsi) {
- do { (void)context; (void)wsi; } while (0);
-}
-#else
-#define lws_latency_pre(_context, _wsi) lws_latency(_context, _wsi, NULL, 0, 0)
-extern void
-lws_latency(struct lws_context *context, struct lws *wsi, const char *action,
- int ret, int completion);
-#endif
-
-LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_ws_client_rx_sm(struct lws *wsi, unsigned char c);
-
-LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_parse(struct lws *wsi, unsigned char *buf, int *len);
-
-LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_parse_urldecode(struct lws *wsi, uint8_t *_c);
-
-LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_http_action(struct lws *wsi);
-
-LWS_EXTERN int
-lws_b64_selftest(void);
-
-LWS_EXTERN int
-lws_service_flag_pending(struct lws_context *context, int tsi);
-
-LWS_EXTERN int
-lws_timed_callback_remove(struct lws_vhost *vh, struct lws_timed_vh_protocol *p);
-
-#if defined(_WIN32)
-LWS_EXTERN struct lws *
-wsi_from_fd(const struct lws_context *context, lws_sockfd_type fd);
-
-LWS_EXTERN int
-insert_wsi(struct lws_context *context, struct lws *wsi);
-
-LWS_EXTERN int
-delete_from_fd(struct lws_context *context, lws_sockfd_type fd);
-#else
-#define wsi_from_fd(A,B) A->lws_lookup[B - lws_plat_socket_offset()]
-#define insert_wsi(A,B) assert(A->lws_lookup[B->desc.sockfd - lws_plat_socket_offset()] == 0); A->lws_lookup[B->desc.sockfd - lws_plat_socket_offset()]=B
-#define delete_from_fd(A,B) A->lws_lookup[B - lws_plat_socket_offset()]=0
-#endif
-
-LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-__insert_wsi_socket_into_fds(struct lws_context *context, struct lws *wsi);
-
-LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_issue_raw(struct lws *wsi, unsigned char *buf, size_t len);
-
-LWS_EXTERN void
-lws_remove_from_timeout_list(struct lws *wsi);
-
-LWS_EXTERN struct lws * LWS_WARN_UNUSED_RESULT
-lws_client_connect_2(struct lws *wsi);
-
-LWS_VISIBLE struct lws * LWS_WARN_UNUSED_RESULT
-lws_client_reset(struct lws **wsi, int ssl, const char *address, int port,
- const char *path, const char *host);
-
-LWS_EXTERN struct lws * LWS_WARN_UNUSED_RESULT
-lws_create_new_server_wsi(struct lws_vhost *vhost, int fixed_tsi);
-
-LWS_EXTERN char * LWS_WARN_UNUSED_RESULT
-lws_generate_client_handshake(struct lws *wsi, char *pkt);
-
-LWS_EXTERN int
-lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd);
-
-LWS_EXTERN struct lws *
-lws_client_connect_via_info2(struct lws *wsi);
-
-
-
-LWS_EXTERN void
-lws_client_stash_destroy(struct lws *wsi);
-
-/*
- * EXTENSIONS
- */
-
-#if defined(LWS_WITHOUT_EXTENSIONS)
-#define lws_any_extension_handled(_a, _b, _c, _d) (0)
-#define lws_ext_cb_active(_a, _b, _c, _d) (0)
-#define lws_ext_cb_all_exts(_a, _b, _c, _d, _e) (0)
-#define lws_issue_raw_ext_access lws_issue_raw
-#define lws_context_init_extensions(_a, _b)
-#endif
-
-LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_client_interpret_server_handshake(struct lws *wsi);
-
-LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_ws_rx_sm(struct lws *wsi, char already_processed, unsigned char c);
-
-LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_issue_raw_ext_access(struct lws *wsi, unsigned char *buf, size_t len);
-
-LWS_EXTERN void
-lws_role_transition(struct lws *wsi, enum lwsi_role role, enum lwsi_state state,
- struct lws_role_ops *ops);
-
-LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-user_callback_handle_rxflow(lws_callback_function, struct lws *wsi,
- enum lws_callback_reasons reason, void *user,
- void *in, size_t len);
-
-LWS_EXTERN int
-lws_plat_socket_offset(void);
-
-LWS_EXTERN int
-lws_plat_set_socket_options(struct lws_vhost *vhost, lws_sockfd_type fd);
-
-LWS_EXTERN int
-lws_plat_check_connection_error(struct lws *wsi);
-
-LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_header_table_attach(struct lws *wsi, int autoservice);
-
-LWS_EXTERN int
-lws_header_table_detach(struct lws *wsi, int autoservice);
-LWS_EXTERN int
-__lws_header_table_detach(struct lws *wsi, int autoservice);
-
-LWS_EXTERN void
-lws_header_table_reset(struct lws *wsi, int autoservice);
-
-void
-__lws_header_table_reset(struct lws *wsi, int autoservice);
-
-LWS_EXTERN char * LWS_WARN_UNUSED_RESULT
-lws_hdr_simple_ptr(struct lws *wsi, enum lws_token_indexes h);
-
-LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_hdr_simple_create(struct lws *wsi, enum lws_token_indexes h, const char *s);
-
-LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_ensure_user_space(struct lws *wsi);
-
-LWS_EXTERN int
-lws_change_pollfd(struct lws *wsi, int _and, int _or);
-
-#ifndef LWS_NO_SERVER
- int _lws_vhost_init_server(const struct lws_context_creation_info *info,
- struct lws_vhost *vhost);
- LWS_EXTERN struct lws_vhost *
- lws_select_vhost(struct lws_context *context, int port, const char *servername);
- LWS_EXTERN int LWS_WARN_UNUSED_RESULT
- lws_parse_ws(struct lws *wsi, unsigned char **buf, size_t len);
- LWS_EXTERN void
- lws_server_get_canonical_hostname(struct lws_context *context,
- const struct lws_context_creation_info *info);
-#else
- #define _lws_vhost_init_server(_a, _b) (0)
- #define lws_parse_ws(_a, _b, _c) (0)
- #define lws_server_get_canonical_hostname(_a, _b)
-#endif
-
-#ifndef LWS_NO_DAEMONIZE
- LWS_EXTERN int get_daemonize_pid();
-#else
- #define get_daemonize_pid() (0)
-#endif
-
-LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-interface_to_sa(struct lws_vhost *vh, const char *ifname,
- struct sockaddr_in *addr, size_t addrlen);
-LWS_EXTERN void lwsl_emit_stderr(int level, const char *line);
-
-#if !defined(LWS_WITH_TLS)
- #define LWS_SSL_ENABLED(context) (0)
- #define lws_context_init_server_ssl(_a, _b) (0)
- #define lws_ssl_destroy(_a)
- #define lws_context_init_alpn(_a)
- #define lws_ssl_capable_read lws_ssl_capable_read_no_ssl
- #define lws_ssl_capable_write lws_ssl_capable_write_no_ssl
- #define lws_ssl_pending lws_ssl_pending_no_ssl
- #define lws_server_socket_service_ssl(_b, _c) (0)
- #define lws_ssl_close(_a) (0)
- #define lws_ssl_context_destroy(_a)
- #define lws_ssl_SSL_CTX_destroy(_a)
- #define lws_ssl_remove_wsi_from_buffered_list(_a)
- #define __lws_ssl_remove_wsi_from_buffered_list(_a)
- #define lws_context_init_ssl_library(_a)
- #define lws_tls_check_all_cert_lifetimes(_a)
- #define lws_tls_acme_sni_cert_destroy(_a)
-#endif
-
-
-#if LWS_MAX_SMP > 1
-
-static LWS_INLINE void
-lws_pt_mutex_init(struct lws_context_per_thread *pt)
-{
- pthread_mutex_init(&pt->lock, NULL);
- pthread_mutex_init(&pt->lock_stats, NULL);
-}
-
-static LWS_INLINE void
-lws_pt_mutex_destroy(struct lws_context_per_thread *pt)
-{
- pthread_mutex_destroy(&pt->lock_stats);
- pthread_mutex_destroy(&pt->lock);
-}
-
-static LWS_INLINE void
-lws_pt_lock(struct lws_context_per_thread *pt, const char *reason)
-{
- if (pt->lock_owner == pthread_self()) {
- pt->lock_depth++;
- return;
- }
- pthread_mutex_lock(&pt->lock);
- pt->last_lock_reason = reason;
- pt->lock_owner = pthread_self();
- //lwsl_notice("tid %d: lock %s\n", pt->tid, reason);
-}
-
-static LWS_INLINE void
-lws_pt_unlock(struct lws_context_per_thread *pt)
-{
- if (pt->lock_depth) {
- pt->lock_depth--;
- return;
- }
- pt->last_lock_reason = "free";
- pt->lock_owner = 0;
- //lwsl_notice("tid %d: unlock %s\n", pt->tid, pt->last_lock_reason);
- pthread_mutex_unlock(&pt->lock);
-}
-
-static LWS_INLINE void
-lws_pt_stats_lock(struct lws_context_per_thread *pt)
-{
- pthread_mutex_lock(&pt->lock_stats);
-}
-
-static LWS_INLINE void
-lws_pt_stats_unlock(struct lws_context_per_thread *pt)
-{
- pthread_mutex_unlock(&pt->lock_stats);
-}
-
-static LWS_INLINE void
-lws_context_lock(struct lws_context *context)
-{
- pthread_mutex_lock(&context->lock);
-}
-
-static LWS_INLINE void
-lws_context_unlock(struct lws_context *context)
-{
- pthread_mutex_unlock(&context->lock);
-}
-
-static LWS_INLINE void
-lws_vhost_lock(struct lws_vhost *vhost)
-{
- pthread_mutex_lock(&vhost->lock);
-}
-
-static LWS_INLINE void
-lws_vhost_unlock(struct lws_vhost *vhost)
-{
- pthread_mutex_unlock(&vhost->lock);
-}
-
-
-#else
-#define lws_pt_mutex_init(_a) (void)(_a)
-#define lws_pt_mutex_destroy(_a) (void)(_a)
-#define lws_pt_lock(_a, b) (void)(_a)
-#define lws_pt_unlock(_a) (void)(_a)
-#define lws_context_lock(_a) (void)(_a)
-#define lws_context_unlock(_a) (void)(_a)
-#define lws_vhost_lock(_a) (void)(_a)
-#define lws_vhost_unlock(_a) (void)(_a)
-#define lws_pt_stats_lock(_a) (void)(_a)
-#define lws_pt_stats_unlock(_a) (void)(_a)
-#endif
-
-LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_ssl_capable_read_no_ssl(struct lws *wsi, unsigned char *buf, int len);
-
-LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_ssl_capable_write_no_ssl(struct lws *wsi, unsigned char *buf, int len);
-
-LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_ssl_pending_no_ssl(struct lws *wsi);
-
-int
-lws_tls_check_cert_lifetime(struct lws_vhost *vhost);
-
-int lws_jws_selftest(void);
-
-
-#ifndef LWS_NO_CLIENT
-LWS_EXTERN int lws_client_socket_service(struct lws *wsi,
- struct lws_pollfd *pollfd,
- struct lws *wsi_conn);
-LWS_EXTERN struct lws *
-lws_client_wsi_effective(struct lws *wsi);
-LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_http_transaction_completed_client(struct lws *wsi);
-#if !defined(LWS_WITH_TLS)
- #define lws_context_init_client_ssl(_a, _b) (0)
-#endif
-LWS_EXTERN void
-lws_decode_ssl_error(void);
-#else
-#define lws_context_init_client_ssl(_a, _b) (0)
-#endif
-
-LWS_EXTERN int
-__lws_rx_flow_control(struct lws *wsi);
-
-LWS_EXTERN int
-_lws_change_pollfd(struct lws *wsi, int _and, int _or, struct lws_pollargs *pa);
-
-#ifndef LWS_NO_SERVER
-LWS_EXTERN int
-lws_handshake_server(struct lws *wsi, unsigned char **buf, size_t len);
-#else
-#define lws_server_socket_service(_b, _c) (0)
-#define lws_handshake_server(_a, _b, _c) (0)
-#endif
-
-#ifdef LWS_WITH_ACCESS_LOG
-LWS_EXTERN int
-lws_access_log(struct lws *wsi);
-LWS_EXTERN void
-lws_prepare_access_log_info(struct lws *wsi, char *uri_ptr, int meth);
-#else
-#define lws_access_log(_a)
-#endif
-
-LWS_EXTERN int
-lws_cgi_kill_terminated(struct lws_context_per_thread *pt);
-
-LWS_EXTERN void
-lws_cgi_remove_and_kill(struct lws *wsi);
-
-int
-lws_protocol_init(struct lws_context *context);
-
-int
-lws_bind_protocol(struct lws *wsi, const struct lws_protocols *p);
-
-const struct lws_http_mount *
-lws_find_mount(struct lws *wsi, const char *uri_ptr, int uri_len);
-
-/*
- * custom allocator
- */
-LWS_EXTERN void *
-lws_realloc(void *ptr, size_t size, const char *reason);
-
-LWS_EXTERN void * LWS_WARN_UNUSED_RESULT
-lws_zalloc(size_t size, const char *reason);
-
-#ifdef LWS_PLAT_OPTEE
-void *lws_malloc(size_t size, const char *reason);
-void lws_free(void *p);
-#define lws_free_set_NULL(P) do { lws_free(P); (P) = NULL; } while(0)
-#else
-#define lws_malloc(S, R) lws_realloc(NULL, S, R)
-#define lws_free(P) lws_realloc(P, 0, "lws_free")
-#define lws_free_set_NULL(P) do { lws_realloc(P, 0, "free"); (P) = NULL; } while(0)
-#endif
-
-char *
-lws_strdup(const char *s);
-
-int
-lws_plat_pipe_create(struct lws *wsi);
-int
-lws_plat_pipe_signal(struct lws *wsi);
-void
-lws_plat_pipe_close(struct lws *wsi);
-int
-lws_create_event_pipes(struct lws_context *context);
-
-int lws_open(const char *__file, int __oflag, ...);
-void lws_plat_apply_FD_CLOEXEC(int n);
-
-const struct lws_plat_file_ops *
-lws_vfs_select_fops(const struct lws_plat_file_ops *fops, const char *vfs_path,
- const char **vpath);
-
-/* lws_plat_ */
-LWS_EXTERN void
-lws_plat_delete_socket_from_fds(struct lws_context *context,
- struct lws *wsi, int m);
-LWS_EXTERN void
-lws_plat_insert_socket_into_fds(struct lws_context *context,
- struct lws *wsi);
-LWS_EXTERN void
-lws_plat_service_periodic(struct lws_context *context);
-
-LWS_EXTERN int
-lws_plat_change_pollfd(struct lws_context *context, struct lws *wsi,
- struct lws_pollfd *pfd);
-LWS_EXTERN void
-lws_add_wsi_to_draining_ext_list(struct lws *wsi);
-LWS_EXTERN void
-lws_remove_wsi_from_draining_ext_list(struct lws *wsi);
-LWS_EXTERN int
-lws_plat_context_early_init(void);
-LWS_EXTERN void
-lws_plat_context_early_destroy(struct lws_context *context);
-LWS_EXTERN void
-lws_plat_context_late_destroy(struct lws_context *context);
-LWS_EXTERN int
-lws_poll_listen_fd(struct lws_pollfd *fd);
-LWS_EXTERN int
-lws_plat_service(struct lws_context *context, int timeout_ms);
-LWS_EXTERN LWS_VISIBLE int
-_lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi);
-LWS_EXTERN int
-lws_plat_init(struct lws_context *context,
- const struct lws_context_creation_info *info);
-LWS_EXTERN void
-lws_plat_drop_app_privileges(const struct lws_context_creation_info *info);
-LWS_EXTERN unsigned long long
-time_in_microseconds(void);
-LWS_EXTERN const char * LWS_WARN_UNUSED_RESULT
-lws_plat_inet_ntop(int af, const void *src, char *dst, int cnt);
-LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_plat_inet_pton(int af, const char *src, void *dst);
-
-LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_check_utf8(unsigned char *state, unsigned char *buf, size_t len);
-LWS_EXTERN int alloc_file(struct lws_context *context, const char *filename, uint8_t **buf,
- lws_filepos_t *amount);
-
-
-LWS_EXTERN void
-lws_same_vh_protocol_remove(struct lws *wsi);
-LWS_EXTERN void
-lws_same_vh_protocol_insert(struct lws *wsi, int n);
-
-LWS_EXTERN int
-lws_broadcast(struct lws_context *context, int reason, void *in, size_t len);
-
-#if defined(LWS_WITH_STATS)
- void
- lws_stats_atomic_bump(struct lws_context * context,
- struct lws_context_per_thread *pt, int index, uint64_t bump);
- void
- lws_stats_atomic_max(struct lws_context * context,
- struct lws_context_per_thread *pt, int index, uint64_t val);
-#else
- static LWS_INLINE uint64_t lws_stats_atomic_bump(struct lws_context * context,
- struct lws_context_per_thread *pt, int index, uint64_t bump) {
- (void)context; (void)pt; (void)index; (void)bump; return 0; }
- static LWS_INLINE uint64_t lws_stats_atomic_max(struct lws_context * context,
- struct lws_context_per_thread *pt, int index, uint64_t val) {
- (void)context; (void)pt; (void)index; (void)val; return 0; }
-#endif
-
-/* socks */
-void socks_generate_msg(struct lws *wsi, enum socks_msg_type type,
- ssize_t *msg_len);
-
-#if defined(LWS_WITH_PEER_LIMITS)
-void
-lws_peer_track_wsi_close(struct lws_context *context, struct lws_peer *peer);
-int
-lws_peer_confirm_ah_attach_ok(struct lws_context *context, struct lws_peer *peer);
-void
-lws_peer_track_ah_detach(struct lws_context *context, struct lws_peer *peer);
-void
-lws_peer_cull_peer_wait_list(struct lws_context *context);
-struct lws_peer *
-lws_get_or_create_peer(struct lws_vhost *vhost, lws_sockfd_type sockfd);
-void
-lws_peer_add_wsi(struct lws_context *context, struct lws_peer *peer,
- struct lws *wsi);
-void
-lws_peer_dump_from_wsi(struct lws *wsi);
-#endif
-
-#ifdef LWS_WITH_HTTP_PROXY
-hubbub_error
-html_parser_cb(const hubbub_token *token, void *pw);
-#endif
-
-
-void
-__lws_remove_from_timeout_list(struct lws *wsi);
-
-lws_usec_t
-__lws_hrtimer_service(struct lws_context_per_thread *pt);
-
-void
-__lws_set_timeout(struct lws *wsi, enum pending_timeout reason, int secs);
-int
-__lws_change_pollfd(struct lws *wsi, int _and, int _or);
-
-
-int
-lws_callback_as_writeable(struct lws *wsi);
-int
-lws_buflist_aware_read(struct lws_context_per_thread *pt, struct lws *wsi,
- struct lws_tokens *ebuf);
-int
-lws_buflist_aware_consume(struct lws *wsi, struct lws_tokens *ebuf, int used,
- int buffered);
-
-
-char *
-lws_generate_client_ws_handshake(struct lws *wsi, char *p);
-int
-lws_client_ws_upgrade(struct lws *wsi, const char **cce);
-int
-lws_create_client_ws_object(struct lws_client_connect_info *i, struct lws *wsi);
-int
-lws_alpn_comma_to_openssl(const char *comma, uint8_t *os, int len);
-int
-lws_role_call_alpn_negotiated(struct lws *wsi, const char *alpn);
-int
-lws_tls_server_conn_alpn(struct lws *wsi);
-
-int
-lws_ws_client_rx_sm_block(struct lws *wsi, unsigned char **buf, size_t len);
-void
-lws_destroy_event_pipe(struct lws *wsi);
-void
-lws_context_destroy2(struct lws_context *context);
-
-#ifdef __cplusplus
-};
-#endif
diff --git a/thirdparty/libwebsockets/core/service.c b/thirdparty/libwebsockets/core/service.c
deleted file mode 100644
index 6523058814..0000000000
--- a/thirdparty/libwebsockets/core/service.c
+++ /dev/null
@@ -1,987 +0,0 @@
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010-2018 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- */
-
-#include "core/private.h"
-
-int
-lws_callback_as_writeable(struct lws *wsi)
-{
- struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
- int n, m;
-
- lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_C_WRITEABLE_CB, 1);
-#if defined(LWS_WITH_STATS)
- if (wsi->active_writable_req_us) {
- uint64_t ul = time_in_microseconds() -
- wsi->active_writable_req_us;
-
- lws_stats_atomic_bump(wsi->context, pt,
- LWSSTATS_MS_WRITABLE_DELAY, ul);
- lws_stats_atomic_max(wsi->context, pt,
- LWSSTATS_MS_WORST_WRITABLE_DELAY, ul);
- wsi->active_writable_req_us = 0;
- }
-#endif
-
- n = wsi->role_ops->writeable_cb[lwsi_role_server(wsi)];
-
- m = user_callback_handle_rxflow(wsi->protocol->callback,
- wsi, (enum lws_callback_reasons) n,
- wsi->user_space, NULL, 0);
-
- return m;
-}
-
-LWS_VISIBLE int
-lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd)
-{
- volatile struct lws *vwsi = (volatile struct lws *)wsi;
- int n;
-
- //lwsl_notice("%s: %p\n", __func__, wsi);
-
- vwsi->leave_pollout_active = 0;
- vwsi->handling_pollout = 1;
- /*
- * if another thread wants POLLOUT on us, from here on while
- * handling_pollout is set, he will only set leave_pollout_active.
- * If we are going to disable POLLOUT, we will check that first.
- */
- wsi->could_have_pending = 0; /* clear back-to-back write detection */
-
- /*
- * user callback is lowest priority to get these notifications
- * actually, since other pending things cannot be disordered
- *
- * Priority 1: pending truncated sends are incomplete ws fragments
- * If anything else sent first the protocol would be
- * corrupted.
- */
-
- if (wsi->trunc_len) {
- //lwsl_notice("%s: completing partial\n", __func__);
- if (lws_issue_raw(wsi, wsi->trunc_alloc + wsi->trunc_offset,
- wsi->trunc_len) < 0) {
- lwsl_info("%s signalling to close\n", __func__);
- goto bail_die;
- }
- /* leave POLLOUT active either way */
- goto bail_ok;
- } else
- if (lwsi_state(wsi) == LRS_FLUSHING_BEFORE_CLOSE) {
- wsi->socket_is_permanently_unusable = 1;
- goto bail_die; /* retry closing now */
- }
-
-#ifdef LWS_WITH_CGI
- /*
- * A cgi master's wire protocol remains h1 or h2. He is just getting
- * his data from his child cgis.
- */
- if (wsi->http.cgi) {
- /* also one shot */
- if (pollfd)
- if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) {
- lwsl_info("failed at set pollfd\n");
- return 1;
- }
- goto user_service_go_again;
- }
-#endif
-
- /* if we got here, we should have wire protocol ops set on the wsi */
- assert(wsi->role_ops);
-
- if (!wsi->role_ops->handle_POLLOUT)
- goto bail_ok;
-
- switch ((wsi->role_ops->handle_POLLOUT)(wsi)) {
- case LWS_HP_RET_BAIL_OK:
- goto bail_ok;
- case LWS_HP_RET_BAIL_DIE:
- goto bail_die;
- case LWS_HP_RET_USER_SERVICE:
- break;
- default:
- assert(0);
- }
-
- /* one shot */
-
- if (wsi->parent_carries_io) {
- vwsi->handling_pollout = 0;
- vwsi->leave_pollout_active = 0;
-
- return lws_callback_as_writeable(wsi);
- }
-
- if (pollfd) {
- int eff = vwsi->leave_pollout_active;
-
- if (!eff) {
- if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) {
- lwsl_info("failed at set pollfd\n");
- goto bail_die;
- }
- }
-
- vwsi->handling_pollout = 0;
-
- /* cannot get leave_pollout_active set after the above */
- if (!eff && wsi->leave_pollout_active) {
- /*
- * got set inbetween sampling eff and clearing
- * handling_pollout, force POLLOUT on
- */
- lwsl_debug("leave_pollout_active\n");
- if (lws_change_pollfd(wsi, 0, LWS_POLLOUT)) {
- lwsl_info("failed at set pollfd\n");
- goto bail_die;
- }
- }
-
- vwsi->leave_pollout_active = 0;
- }
-
- if (lwsi_role_client(wsi) &&
- !wsi->hdr_parsing_completed &&
- lwsi_state(wsi) != LRS_H2_WAITING_TO_SEND_HEADERS &&
- lwsi_state(wsi) != LRS_ISSUE_HTTP_BODY
- )
- goto bail_ok;
-
-
-#ifdef LWS_WITH_CGI
-user_service_go_again:
-#endif
-
- if (wsi->role_ops->perform_user_POLLOUT) {
- if (wsi->role_ops->perform_user_POLLOUT(wsi) == -1)
- goto bail_die;
- else
- goto bail_ok;
- }
-
- lwsl_debug("%s: %p: non mux: wsistate 0x%x, ops %s\n", __func__, wsi,
- wsi->wsistate, wsi->role_ops->name);
-
- vwsi = (volatile struct lws *)wsi;
- vwsi->leave_pollout_active = 0;
-
- n = lws_callback_as_writeable(wsi);
- vwsi->handling_pollout = 0;
-
- if (vwsi->leave_pollout_active)
- lws_change_pollfd(wsi, 0, LWS_POLLOUT);
-
- return n;
-
- /*
- * since these don't disable the POLLOUT, they are always doing the
- * right thing for leave_pollout_active whether it was set or not.
- */
-
-bail_ok:
- vwsi->handling_pollout = 0;
- vwsi->leave_pollout_active = 0;
-
- return 0;
-
-bail_die:
- vwsi->handling_pollout = 0;
- vwsi->leave_pollout_active = 0;
-
- return -1;
-}
-
-static int
-__lws_service_timeout_check(struct lws *wsi, time_t sec)
-{
- struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
- int n = 0;
-
- (void)n;
-
- /*
- * if we went beyond the allowed time, kill the
- * connection
- */
- if (wsi->dll_timeout.prev &&
- lws_compare_time_t(wsi->context, sec, wsi->pending_timeout_set) >
- wsi->pending_timeout_limit) {
-
- if (wsi->desc.sockfd != LWS_SOCK_INVALID &&
- wsi->position_in_fds_table >= 0)
- n = pt->fds[wsi->position_in_fds_table].events;
-
- lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_C_TIMEOUTS, 1);
-
- /* no need to log normal idle keepalive timeout */
- if (wsi->pending_timeout != PENDING_TIMEOUT_HTTP_KEEPALIVE_IDLE)
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- lwsl_info("wsi %p: TIMEDOUT WAITING on %d "
- "(did hdr %d, ah %p, wl %d, pfd "
- "events %d) %llu vs %llu\n",
- (void *)wsi, wsi->pending_timeout,
- wsi->hdr_parsing_completed, wsi->http.ah,
- pt->http.ah_wait_list_length, n,
- (unsigned long long)sec,
- (unsigned long long)wsi->pending_timeout_limit);
-#if defined(LWS_WITH_CGI)
- if (wsi->http.cgi)
- lwsl_notice("CGI timeout: %s\n", wsi->http.cgi->summary);
-#endif
-#else
- lwsl_info("wsi %p: TIMEDOUT WAITING on %d ", (void *)wsi,
- wsi->pending_timeout);
-#endif
-
- /*
- * Since he failed a timeout, he already had a chance to do
- * something and was unable to... that includes situations like
- * half closed connections. So process this "failed timeout"
- * close as a violent death and don't try to do protocol
- * cleanup like flush partials.
- */
- wsi->socket_is_permanently_unusable = 1;
- if (lwsi_state(wsi) == LRS_WAITING_SSL && wsi->protocol)
- wsi->protocol->callback(wsi,
- LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
- wsi->user_space,
- (void *)"Timed out waiting SSL", 21);
-
- __lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "timeout");
-
- return 1;
- }
-
- return 0;
-}
-
-int lws_rxflow_cache(struct lws *wsi, unsigned char *buf, int n, int len)
-{
- struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
- uint8_t *buffered;
- size_t blen;
- int ret = 0, m;
-
- /* his RX is flowcontrolled, don't send remaining now */
- blen = lws_buflist_next_segment_len(&wsi->buflist, &buffered);
- if (blen) {
- if (buf >= buffered && buf + len <= buffered + blen) {
- /* rxflow while we were spilling prev rxflow */
- lwsl_info("%s: staying in rxflow buf\n", __func__);
-
- return 1;
- }
- ret = 1;
- }
-
- /* a new rxflow, buffer it and warn caller */
-
- m = lws_buflist_append_segment(&wsi->buflist, buf + n, len - n);
-
- if (m < 0)
- return -1;
- if (m) {
- lwsl_debug("%s: added %p to rxflow list\n", __func__, wsi);
- lws_dll_lws_add_front(&wsi->dll_buflist, &pt->dll_head_buflist);
- }
-
- return ret;
-}
-
-/* this is used by the platform service code to stop us waiting for network
- * activity in poll() when we have something that already needs service
- */
-
-LWS_VISIBLE LWS_EXTERN int
-lws_service_adjust_timeout(struct lws_context *context, int timeout_ms, int tsi)
-{
- struct lws_context_per_thread *pt = &context->pt[tsi];
-
- /* Figure out if we really want to wait in poll()
- * We only need to wait if really nothing already to do and we have
- * to wait for something from network
- */
-#if defined(LWS_ROLE_WS) && !defined(LWS_WITHOUT_EXTENSIONS)
- /* 1) if we know we are draining rx ext, do not wait in poll */
- if (pt->ws.rx_draining_ext_list)
- return 0;
-#endif
-
- /* 2) if we know we have non-network pending data, do not wait in poll */
-
- if (pt->context->tls_ops &&
- pt->context->tls_ops->fake_POLLIN_for_buffered)
- if (pt->context->tls_ops->fake_POLLIN_for_buffered(pt))
- return 0;
-
- /* 3) If there is any wsi with rxflow buffered and in a state to process
- * it, we should not wait in poll
- */
-
- lws_start_foreach_dll(struct lws_dll_lws *, d, pt->dll_head_buflist.next) {
- struct lws *wsi = lws_container_of(d, struct lws, dll_buflist);
-
- if (lwsi_state(wsi) != LRS_DEFERRING_ACTION)
- return 0;
-
- } lws_end_foreach_dll(d);
-
- return timeout_ms;
-}
-
-/*
- * POLLIN said there is something... we must read it, and either use it; or
- * if other material already in the buflist append it and return the buflist
- * head material.
- */
-int
-lws_buflist_aware_read(struct lws_context_per_thread *pt, struct lws *wsi,
- struct lws_tokens *ebuf)
-{
- int n, prior = (int)lws_buflist_next_segment_len(&wsi->buflist, NULL);
-
- ebuf->token = (char *)pt->serv_buf;
- ebuf->len = lws_ssl_capable_read(wsi, pt->serv_buf,
- wsi->context->pt_serv_buf_size);
-
- if (ebuf->len == LWS_SSL_CAPABLE_MORE_SERVICE && prior)
- goto get_from_buflist;
-
- if (ebuf->len <= 0)
- return 0;
-
- /* nothing in buflist already? Then just use what we read */
-
- if (!prior)
- return 0;
-
- /* stash what we read */
-
- n = lws_buflist_append_segment(&wsi->buflist, (uint8_t *)ebuf->token,
- ebuf->len);
- if (n < 0)
- return -1;
- if (n) {
- lwsl_debug("%s: added %p to rxflow list\n", __func__, wsi);
- lws_dll_lws_add_front(&wsi->dll_buflist, &pt->dll_head_buflist);
- }
-
- /* get the first buflist guy in line */
-
-get_from_buflist:
-
- ebuf->len = (int)lws_buflist_next_segment_len(&wsi->buflist,
- (uint8_t **)&ebuf->token);
-
- return 1; /* came from buflist */
-}
-
-int
-lws_buflist_aware_consume(struct lws *wsi, struct lws_tokens *ebuf, int used,
- int buffered)
-{
- struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
- int m;
-
- /* it's in the buflist; we didn't use any */
-
- if (!used && buffered)
- return 0;
-
- if (used && buffered) {
- m = lws_buflist_use_segment(&wsi->buflist, used);
- lwsl_info("%s: draining rxflow: used %d, next %d\n",
- __func__, used, m);
- if (m)
- return 0;
-
- lwsl_info("%s: removed %p from dll_buflist\n", __func__, wsi);
- lws_dll_lws_remove(&wsi->dll_buflist);
-
- return 0;
- }
-
- /* any remainder goes on the buflist */
-
- if (used != ebuf->len) {
- m = lws_buflist_append_segment(&wsi->buflist,
- (uint8_t *)ebuf->token + used,
- ebuf->len - used);
- if (m < 0)
- return 1; /* OOM */
- if (m) {
- lwsl_debug("%s: added %p to rxflow list\n", __func__, wsi);
- lws_dll_lws_add_front(&wsi->dll_buflist, &pt->dll_head_buflist);
- }
- }
-
- return 0;
-}
-
-void
-lws_service_do_ripe_rxflow(struct lws_context_per_thread *pt)
-{
- struct lws_pollfd pfd;
-
- if (!pt->dll_head_buflist.next)
- return;
-
- /*
- * service all guys with pending rxflow that reached a state they can
- * accept the pending data
- */
-
- lws_pt_lock(pt, __func__);
-
- lws_start_foreach_dll_safe(struct lws_dll_lws *, d, d1,
- pt->dll_head_buflist.next) {
- struct lws *wsi = lws_container_of(d, struct lws, dll_buflist);
-
- pfd.events = LWS_POLLIN;
- pfd.revents = LWS_POLLIN;
- pfd.fd = -1;
-
- lwsl_debug("%s: rxflow processing: %p 0x%x\n", __func__, wsi,
- wsi->wsistate);
-
- if (!lws_is_flowcontrolled(wsi) &&
- lwsi_state(wsi) != LRS_DEFERRING_ACTION &&
- (wsi->role_ops->handle_POLLIN)(pt, wsi, &pfd) ==
- LWS_HPI_RET_PLEASE_CLOSE_ME)
- lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS,
- "close_and_handled");
-
- } lws_end_foreach_dll_safe(d, d1);
-
- lws_pt_unlock(pt);
-}
-
-/*
- * guys that need POLLIN service again without waiting for network action
- * can force POLLIN here if not flowcontrolled, so they will get service.
- *
- * Return nonzero if anybody got their POLLIN faked
- */
-int
-lws_service_flag_pending(struct lws_context *context, int tsi)
-{
- struct lws_context_per_thread *pt = &context->pt[tsi];
-
-#if defined(LWS_WITH_TLS)
- struct lws *wsi, *wsi_next;
-#endif
- int forced = 0;
-
- lws_pt_lock(pt, __func__);
-
- /*
- * 1) If there is any wsi with a buflist and in a state to process
- * it, we should not wait in poll
- */
-
- lws_start_foreach_dll(struct lws_dll_lws *, d, pt->dll_head_buflist.next) {
- struct lws *wsi = lws_container_of(d, struct lws, dll_buflist);
-
- if (lwsi_state(wsi) != LRS_DEFERRING_ACTION) {
- forced = 1;
- break;
- }
- } lws_end_foreach_dll(d);
-
-#if defined(LWS_ROLE_WS)
- forced |= role_ops_ws.service_flag_pending(context, tsi);
-#endif
-
-#if defined(LWS_WITH_TLS)
- /*
- * 2) For all guys with buffered SSL read data already saved up, if they
- * are not flowcontrolled, fake their POLLIN status so they'll get
- * service to use up the buffered incoming data, even though their
- * network socket may have nothing
- */
- wsi = pt->tls.pending_read_list;
- while (wsi) {
- wsi_next = wsi->tls.pending_read_list_next;
- pt->fds[wsi->position_in_fds_table].revents |=
- pt->fds[wsi->position_in_fds_table].events & LWS_POLLIN;
- if (pt->fds[wsi->position_in_fds_table].revents & LWS_POLLIN) {
- forced = 1;
- /*
- * he's going to get serviced now, take him off the
- * list of guys with buffered SSL. If he still has some
- * at the end of the service, he'll get put back on the
- * list then.
- */
- __lws_ssl_remove_wsi_from_buffered_list(wsi);
- }
-
- wsi = wsi_next;
- }
-#endif
-
- lws_pt_unlock(pt);
-
- return forced;
-}
-
-static int
-lws_service_periodic_checks(struct lws_context *context,
- struct lws_pollfd *pollfd, int tsi)
-{
- struct lws_context_per_thread *pt = &context->pt[tsi];
- lws_sockfd_type our_fd = 0, tmp_fd;
- struct lws *wsi;
- int timed_out = 0;
- time_t now;
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- struct allocated_headers *ah;
- int m;
-#endif
-
- if (!context->protocol_init_done)
- if (lws_protocol_init(context))
- return -1;
-
- time(&now);
-
- /*
- * handle case that system time was uninitialized when lws started
- * at boot, and got initialized a little later
- */
- if (context->time_up < 1464083026 && now > 1464083026)
- context->time_up = now;
-
- if (context->last_timeout_check_s &&
- now - context->last_timeout_check_s > 100) {
- /*
- * There has been a discontiguity. Any stored time that is
- * less than context->time_discontiguity should have context->
- * time_fixup added to it.
- *
- * Some platforms with no RTC will experience this as a normal
- * event when ntp sets their clock, but we can have started
- * long before that with a 0-based unix time.
- */
-
- context->time_discontiguity = now;
- context->time_fixup = now - context->last_timeout_check_s;
-
- lwsl_notice("time discontiguity: at old time %llus, "
- "new time %llus: +%llus\n",
- (unsigned long long)context->last_timeout_check_s,
- (unsigned long long)context->time_discontiguity,
- (unsigned long long)context->time_fixup);
-
- context->last_timeout_check_s = now - 1;
- }
-
- if (!lws_compare_time_t(context, context->last_timeout_check_s, now))
- return 0;
-
- context->last_timeout_check_s = now;
-
-#if defined(LWS_WITH_STATS)
- if (!tsi && now - context->last_dump > 10) {
- lws_stats_log_dump(context);
- context->last_dump = now;
- }
-#endif
-
- lws_plat_service_periodic(context);
- lws_check_deferred_free(context, 0);
-
-#if defined(LWS_WITH_PEER_LIMITS)
- lws_peer_cull_peer_wait_list(context);
-#endif
-
- /* retire unused deprecated context */
-#if !defined(LWS_PLAT_OPTEE) && !defined(LWS_WITH_ESP32)
-#if !defined(_WIN32)
- if (context->deprecated && !context->count_wsi_allocated) {
- lwsl_notice("%s: ending deprecated context\n", __func__);
- kill(getpid(), SIGINT);
- return 0;
- }
-#endif
-#endif
- /* global timeout check once per second */
-
- if (pollfd)
- our_fd = pollfd->fd;
-
- /*
- * Phase 1: check every wsi on the timeout check list
- */
-
- lws_pt_lock(pt, __func__);
-
- lws_start_foreach_dll_safe(struct lws_dll_lws *, d, d1,
- context->pt[tsi].dll_head_timeout.next) {
- wsi = lws_container_of(d, struct lws, dll_timeout);
- tmp_fd = wsi->desc.sockfd;
- if (__lws_service_timeout_check(wsi, now)) {
- /* he did time out... */
- if (tmp_fd == our_fd)
- /* it was the guy we came to service! */
- timed_out = 1;
- /* he's gone, no need to mark as handled */
- }
- } lws_end_foreach_dll_safe(d, d1);
-
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- /*
- * Phase 2: double-check active ah timeouts independent of wsi
- * timeout status
- */
-
- ah = pt->http.ah_list;
- while (ah) {
- int len;
- char buf[256];
- const unsigned char *c;
-
- if (!ah->in_use || !ah->wsi || !ah->assigned ||
- (ah->wsi->vhost &&
- lws_compare_time_t(context, now, ah->assigned) <
- ah->wsi->vhost->timeout_secs_ah_idle + 360)) {
- ah = ah->next;
- continue;
- }
-
- /*
- * a single ah session somehow got held for
- * an unreasonable amount of time.
- *
- * Dump info on the connection...
- */
- wsi = ah->wsi;
- buf[0] = '\0';
-#if !defined(LWS_PLAT_OPTEE)
- lws_get_peer_simple(wsi, buf, sizeof(buf));
-#else
- buf[0] = '\0';
-#endif
- lwsl_notice("ah excessive hold: wsi %p\n"
- " peer address: %s\n"
- " ah pos %u\n",
- wsi, buf, ah->pos);
- buf[0] = '\0';
- m = 0;
- do {
- c = lws_token_to_string(m);
- if (!c)
- break;
- if (!(*c))
- break;
-
- len = lws_hdr_total_length(wsi, m);
- if (!len || len > (int)sizeof(buf) - 1) {
- m++;
- continue;
- }
-
- if (lws_hdr_copy(wsi, buf,
- sizeof buf, m) > 0) {
- buf[sizeof(buf) - 1] = '\0';
-
- lwsl_notice(" %s = %s\n",
- (const char *)c, buf);
- }
- m++;
- } while (1);
-
- /* explicitly detach the ah */
- lws_header_table_detach(wsi, 0);
-
- /* ... and then drop the connection */
-
- m = 0;
- if (wsi->desc.sockfd == our_fd) {
- m = timed_out;
-
- /* it was the guy we came to service! */
- timed_out = 1;
- }
-
- if (!m) /* if he didn't already timeout */
- __lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS,
- "excessive ah");
-
- ah = pt->http.ah_list;
- }
-#endif
- lws_pt_unlock(pt);
-
-#if 0
- {
- char s[300], *p = s;
-
- for (n = 0; n < context->count_threads; n++)
- p += sprintf(p, " %7lu (%5d), ",
- context->pt[n].count_conns,
- context->pt[n].fds_count);
-
- lwsl_notice("load: %s\n", s);
- }
-#endif
- /*
- * Phase 3: vhost / protocol timer callbacks
- */
-
- wsi = NULL;
- lws_start_foreach_ll(struct lws_vhost *, v, context->vhost_list) {
- struct lws_timed_vh_protocol *nx;
- if (v->timed_vh_protocol_list) {
- lws_start_foreach_ll(struct lws_timed_vh_protocol *,
- q, v->timed_vh_protocol_list) {
- if (now >= q->time) {
- if (!wsi)
- wsi = lws_zalloc(sizeof(*wsi), "cbwsi");
- wsi->context = context;
- wsi->vhost = v;
- wsi->protocol = q->protocol;
- lwsl_debug("timed cb: vh %s, protocol %s, reason %d\n", v->name, q->protocol->name, q->reason);
- q->protocol->callback(wsi, q->reason, NULL, NULL, 0);
- nx = q->next;
- lws_timed_callback_remove(v, q);
- q = nx;
- continue; /* we pointed ourselves to the next from the now-deleted guy */
- }
- } lws_end_foreach_ll(q, next);
- }
- } lws_end_foreach_ll(v, vhost_next);
- if (wsi)
- lws_free(wsi);
-
- /*
- * Phase 4: check for unconfigured vhosts due to required
- * interface missing before
- */
-
- lws_context_lock(context);
- lws_start_foreach_llp(struct lws_vhost **, pv,
- context->no_listener_vhost_list) {
- struct lws_vhost *v = *pv;
- lwsl_debug("deferred iface: checking if on vh %s\n", (*pv)->name);
- if (_lws_vhost_init_server(NULL, *pv) == 0) {
- /* became happy */
- lwsl_notice("vh %s: became connected\n", v->name);
- *pv = v->no_listener_vhost_list;
- v->no_listener_vhost_list = NULL;
- break;
- }
- } lws_end_foreach_llp(pv, no_listener_vhost_list);
- lws_context_unlock(context);
-
- /*
- * Phase 5: role periodic checks
- */
-#if defined(LWS_ROLE_WS)
- role_ops_ws.periodic_checks(context, tsi, now);
-#endif
-#if defined(LWS_ROLE_CGI)
- role_ops_cgi.periodic_checks(context, tsi, now);
-#endif
-
- /*
- * Phase 6: check the remaining cert lifetime daily
- */
-
- if (context->tls_ops &&
- context->tls_ops->periodic_housekeeping)
- context->tls_ops->periodic_housekeeping(context, now);
-
- return timed_out;
-}
-
-LWS_VISIBLE int
-lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd,
- int tsi)
-{
- struct lws_context_per_thread *pt = &context->pt[tsi];
- struct lws *wsi;
-
- if (!context || context->being_destroyed1)
- return -1;
-
- /* the socket we came to service timed out, nothing to do */
- if (lws_service_periodic_checks(context, pollfd, tsi) || !pollfd)
- return 0;
-
- /* no, here to service a socket descriptor */
- wsi = wsi_from_fd(context, pollfd->fd);
- if (!wsi)
- /* not lws connection ... leave revents alone and return */
- return 0;
-
- /*
- * so that caller can tell we handled, past here we need to
- * zero down pollfd->revents after handling
- */
-
- /* handle session socket closed */
-
- if ((!(pollfd->revents & pollfd->events & LWS_POLLIN)) &&
- (pollfd->revents & LWS_POLLHUP)) {
- wsi->socket_is_permanently_unusable = 1;
- lwsl_debug("Session Socket %p (fd=%d) dead\n",
- (void *)wsi, pollfd->fd);
-
- goto close_and_handled;
- }
-
-#ifdef _WIN32
- if (pollfd->revents & LWS_POLLOUT)
- wsi->sock_send_blocking = FALSE;
-#endif
-
- if ((!(pollfd->revents & pollfd->events & LWS_POLLIN)) &&
- (pollfd->revents & LWS_POLLHUP)) {
- lwsl_debug("pollhup\n");
- wsi->socket_is_permanently_unusable = 1;
- goto close_and_handled;
- }
-
-#if defined(LWS_WITH_TLS)
- if (lwsi_state(wsi) == LRS_SHUTDOWN &&
- lws_is_ssl(wsi) && wsi->tls.ssl) {
- switch (__lws_tls_shutdown(wsi)) {
- case LWS_SSL_CAPABLE_DONE:
- case LWS_SSL_CAPABLE_ERROR:
- goto close_and_handled;
-
- case LWS_SSL_CAPABLE_MORE_SERVICE_READ:
- case LWS_SSL_CAPABLE_MORE_SERVICE_WRITE:
- case LWS_SSL_CAPABLE_MORE_SERVICE:
- goto handled;
- }
- }
-#endif
- wsi->could_have_pending = 0; /* clear back-to-back write detection */
-
- /* okay, what we came here to do... */
-
- /* if we got here, we should have wire protocol ops set on the wsi */
- assert(wsi->role_ops);
-
- // lwsl_notice("%s: %s: wsistate 0x%x\n", __func__, wsi->role_ops->name,
- // wsi->wsistate);
-
- switch ((wsi->role_ops->handle_POLLIN)(pt, wsi, pollfd)) {
- case LWS_HPI_RET_WSI_ALREADY_DIED:
- return 1;
- case LWS_HPI_RET_HANDLED:
- break;
- case LWS_HPI_RET_PLEASE_CLOSE_ME:
-close_and_handled:
- lwsl_debug("%p: Close and handled\n", wsi);
- lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS,
- "close_and_handled");
-#if defined(_DEBUG) && defined(LWS_WITH_LIBUV)
- /*
- * confirm close has no problem being called again while
- * it waits for libuv service to complete the first async
- * close
- */
- if (context->event_loop_ops == &event_loop_ops_uv)
- lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS,
- "close_and_handled uv repeat test");
-#endif
- /*
- * pollfd may point to something else after the close
- * due to pollfd swapping scheme on delete on some platforms
- * we can't clear revents now because it'd be the wrong guy's
- * revents
- */
- return 1;
- default:
- assert(0);
- }
-#if defined(LWS_WITH_TLS)
-handled:
-#endif
- pollfd->revents = 0;
-
- lws_pt_lock(pt, __func__);
- __lws_hrtimer_service(pt);
- lws_pt_unlock(pt);
-
- return 0;
-}
-
-LWS_VISIBLE int
-lws_service_fd(struct lws_context *context, struct lws_pollfd *pollfd)
-{
- return lws_service_fd_tsi(context, pollfd, 0);
-}
-
-LWS_VISIBLE int
-lws_service(struct lws_context *context, int timeout_ms)
-{
- struct lws_context_per_thread *pt = &context->pt[0];
- int n;
-
- if (!context)
- return 1;
-
- pt->inside_service = 1;
-
- if (context->event_loop_ops->run_pt) {
- /* we are configured for an event loop */
- context->event_loop_ops->run_pt(context, 0);
-
- pt->inside_service = 0;
-
- return 1;
- }
- n = lws_plat_service(context, timeout_ms);
-
- pt->inside_service = 0;
-
- return n;
-}
-
-LWS_VISIBLE int
-lws_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
-{
- struct lws_context_per_thread *pt = &context->pt[tsi];
- int n;
-
- pt->inside_service = 1;
-
- if (context->event_loop_ops->run_pt) {
- /* we are configured for an event loop */
- context->event_loop_ops->run_pt(context, tsi);
-
- pt->inside_service = 0;
-
- return 1;
- }
-
- n = _lws_plat_service_tsi(context, timeout_ms, tsi);
-
- pt->inside_service = 0;
-
- return n;
-}
diff --git a/thirdparty/libwebsockets/event-libs/poll/poll.c b/thirdparty/libwebsockets/event-libs/poll/poll.c
deleted file mode 100644
index 09af5b15d8..0000000000
--- a/thirdparty/libwebsockets/event-libs/poll/poll.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010 - 2018 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * This is included from core/private.h if LWS_ROLE_WS
- */
-
-#include <core/private.h>
-
-struct lws_event_loop_ops event_loop_ops_poll = {
- /* name */ "poll",
- /* init_context */ NULL,
- /* destroy_context1 */ NULL,
- /* destroy_context2 */ NULL,
- /* init_vhost_listen_wsi */ NULL,
- /* init_pt */ NULL,
- /* wsi_logical_close */ NULL,
- /* check_client_connect_ok */ NULL,
- /* close_handle_manually */ NULL,
- /* accept */ NULL,
- /* io */ NULL,
- /* run */ NULL,
- /* destroy_pt */ NULL,
- /* destroy wsi */ NULL,
-
- /* periodic_events_available */ 1,
-}; \ No newline at end of file
diff --git a/thirdparty/libwebsockets/event-libs/poll/private.h b/thirdparty/libwebsockets/event-libs/poll/private.h
deleted file mode 100644
index ca313ebfb0..0000000000
--- a/thirdparty/libwebsockets/event-libs/poll/private.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010 - 2018 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- */
-
-extern struct lws_event_loop_ops event_loop_ops_poll;
diff --git a/thirdparty/libwebsockets/event-libs/private.h b/thirdparty/libwebsockets/event-libs/private.h
deleted file mode 100644
index c36d39c8c2..0000000000
--- a/thirdparty/libwebsockets/event-libs/private.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010 - 2018 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * This is included from core/private.h
- */
-
-struct lws_event_loop_ops {
- const char *name;
- /* event loop-specific context init during context creation */
- int (*init_context)(struct lws_context *context,
- const struct lws_context_creation_info *info);
- /* called during lws_destroy_context */
- int (*destroy_context1)(struct lws_context *context);
- /* called during lws_destroy_context2 */
- int (*destroy_context2)(struct lws_context *context);
- /* init vhost listening wsi */
- int (*init_vhost_listen_wsi)(struct lws *wsi);
- /* init the event loop for a pt */
- int (*init_pt)(struct lws_context *context, void *_loop, int tsi);
- /* called at end of first phase of close_free_wsi() */
- int (*wsi_logical_close)(struct lws *wsi);
- /* return nonzero if client connect not allowed */
- int (*check_client_connect_ok)(struct lws *wsi);
- /* close handle manually */
- void (*close_handle_manually)(struct lws *wsi);
- /* event loop accept processing */
- void (*accept)(struct lws *wsi);
- /* control wsi active events */
- void (*io)(struct lws *wsi, int flags);
- /* run the event loop for a pt */
- void (*run_pt)(struct lws_context *context, int tsi);
- /* called before pt is destroyed */
- void (*destroy_pt)(struct lws_context *context, int tsi);
- /* called just before wsi is freed */
- void (*destroy_wsi)(struct lws *wsi);
-
- unsigned int periodic_events_available:1;
-};
-
-/* bring in event libs private declarations */
-
-#if defined(LWS_WITH_POLL)
-#include "event-libs/poll/private.h"
-#endif
-
-#if defined(LWS_WITH_LIBUV)
-#include "event-libs/libuv/private.h"
-#endif
-
-#if defined(LWS_WITH_LIBEVENT)
-#include "event-libs/libevent/private.h"
-#endif
-
-#if defined(LWS_WITH_LIBEV)
-#include "event-libs/libev/private.h"
-#endif
-
diff --git a/thirdparty/libwebsockets/ipv6_fixes.diff b/thirdparty/libwebsockets/ipv6_fixes.diff
deleted file mode 100644
index fe3e5e4b63..0000000000
--- a/thirdparty/libwebsockets/ipv6_fixes.diff
+++ /dev/null
@@ -1,32 +0,0 @@
-diff --git a/thirdparty/libwebsockets/plat/lws-plat-unix.c b/thirdparty/libwebsockets/plat/lws-plat-unix.c
-index 7dba3bd82..d1bca8b5d 100644
---- a/thirdparty/libwebsockets/plat/lws-plat-unix.c
-+++ b/thirdparty/libwebsockets/plat/lws-plat-unix.c
-@@ -328,6 +328,11 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, int fd)
- int optval = 1;
- socklen_t optlen = sizeof(optval);
-
-+#ifdef LWS_WITH_IPV6
-+ optval = 0;
-+ setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const void*)&optval, optlen);
-+#endif
-+
- #if defined(__APPLE__) || \
- defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
- defined(__NetBSD__) || \
-diff --git a/thirdparty/libwebsockets/plat/lws-plat-win.c b/thirdparty/libwebsockets/plat/lws-plat-win.c
-index 1850b6425..26caab2cd 100644
---- a/thirdparty/libwebsockets/plat/lws-plat-win.c
-+++ b/thirdparty/libwebsockets/plat/lws-plat-win.c
-@@ -348,6 +348,11 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, lws_sockfd_type fd)
- struct protoent *tcp_proto;
- #endif
-
-+#ifdef LWS_WITH_IPV6
-+ optval = 0;
-+ setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const void*)&optval, optlen);
-+#endif
-+
- if (vhost->ka_time) {
- /* enable keepalive on this socket */
- optval = 1;
diff --git a/thirdparty/libwebsockets/libwebsockets.h b/thirdparty/libwebsockets/libwebsockets.h
deleted file mode 100644
index 2c01696404..0000000000
--- a/thirdparty/libwebsockets/libwebsockets.h
+++ /dev/null
@@ -1,7346 +0,0 @@
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010-2018 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- */
-
-/** @file */
-
-#ifndef LIBWEBSOCKET_H_3060898B846849FF9F88F5DB59B5950C
-#define LIBWEBSOCKET_H_3060898B846849FF9F88F5DB59B5950C
-
-#ifdef __cplusplus
-#include <cstddef>
-#include <cstdarg>
-
-extern "C" {
-#else
-#include <stdarg.h>
-#endif
-
-#include <string.h>
-#include <stdlib.h>
-
-#include "lws_config.h"
-
-/*
- * CARE: everything using cmake defines needs to be below here
- */
-
-#if defined(LWS_HAS_INTPTR_T)
-#include <stdint.h>
-#define lws_intptr_t intptr_t
-#else
-typedef unsigned long long lws_intptr_t;
-#endif
-
-#if defined(WIN32) || defined(_WIN32)
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#include <stddef.h>
-#include <basetsd.h>
-#include <io.h>
-#ifndef _WIN32_WCE
-#include <fcntl.h>
-#else
-#define _O_RDONLY 0x0000
-#define O_RDONLY _O_RDONLY
-#endif
-
-#define LWS_INLINE __inline
-#define LWS_VISIBLE
-#define LWS_WARN_UNUSED_RESULT
-#define LWS_WARN_DEPRECATED
-#define LWS_FORMAT(string_index)
-
-#ifdef LWS_DLL
-#ifdef LWS_INTERNAL
-#define LWS_EXTERN extern __declspec(dllexport)
-#else
-#define LWS_EXTERN extern __declspec(dllimport)
-#endif
-#else
-#define LWS_EXTERN
-#endif
-
-#define LWS_INVALID_FILE INVALID_HANDLE_VALUE
-#define LWS_O_RDONLY _O_RDONLY
-#define LWS_O_WRONLY _O_WRONLY
-#define LWS_O_CREAT _O_CREAT
-#define LWS_O_TRUNC _O_TRUNC
-
-#ifndef __func__
-#define __func__ __FUNCTION__
-#endif
-
-#else /* NOT WIN32 */
-#include <unistd.h>
-#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
-#include <sys/capability.h>
-#endif
-
-#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__QNX__) || defined(__OpenBSD__)
-#include <sys/socket.h>
-#include <netinet/in.h>
-#endif
-
-#define LWS_INLINE inline
-#define LWS_O_RDONLY O_RDONLY
-#define LWS_O_WRONLY O_WRONLY
-#define LWS_O_CREAT O_CREAT
-#define LWS_O_TRUNC O_TRUNC
-
-#if !defined(LWS_PLAT_OPTEE) && !defined(OPTEE_TA) && !defined(LWS_WITH_ESP32)
-#include <poll.h>
-#include <netdb.h>
-#define LWS_INVALID_FILE -1
-#else
-#define getdtablesize() (30)
-#if defined(LWS_WITH_ESP32)
-#define LWS_INVALID_FILE NULL
-#else
-#define LWS_INVALID_FILE NULL
-#endif
-#endif
-
-#if defined(__GNUC__)
-
-/* warn_unused_result attribute only supported by GCC 3.4 or later */
-#if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
-#define LWS_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
-#else
-#define LWS_WARN_UNUSED_RESULT
-#endif
-
-#define LWS_VISIBLE __attribute__((visibility("default")))
-#define LWS_WARN_DEPRECATED __attribute__ ((deprecated))
-#define LWS_FORMAT(string_index) __attribute__ ((format(printf, string_index, string_index+1)))
-#else
-#define LWS_VISIBLE
-#define LWS_WARN_UNUSED_RESULT
-#define LWS_WARN_DEPRECATED
-#define LWS_FORMAT(string_index)
-#endif
-
-#if defined(__ANDROID__)
-#include <netinet/in.h>
-#include <unistd.h>
-#define getdtablesize() sysconf(_SC_OPEN_MAX)
-#endif
-
-#endif
-
-#if defined(LWS_WITH_LIBEV)
-#include <ev.h>
-#endif /* LWS_WITH_LIBEV */
-#ifdef LWS_WITH_LIBUV
-#include <uv.h>
-#ifdef LWS_HAVE_UV_VERSION_H
-#include <uv-version.h>
-#endif
-#ifdef LWS_HAVE_NEW_UV_VERSION_H
-#include <uv/version.h>
-#endif
-#endif /* LWS_WITH_LIBUV */
-#if defined(LWS_WITH_LIBEVENT)
-#include <event2/event.h>
-#endif /* LWS_WITH_LIBEVENT */
-
-#ifndef LWS_EXTERN
-#define LWS_EXTERN extern
-#endif
-
-#ifdef _WIN32
-#define random rand
-#else
-#if !defined(OPTEE_TA)
-#include <sys/time.h>
-#include <unistd.h>
-#endif
-#endif
-
-#if defined(LWS_WITH_TLS)
-
-#ifdef USE_WOLFSSL
-#ifdef USE_OLD_CYASSL
-#ifdef _WIN32
-/*
- * Include user-controlled settings for windows from
- * <wolfssl-root>/IDE/WIN/user_settings.h
- */
-#include <IDE/WIN/user_settings.h>
-#include <cyassl/ctaocrypt/settings.h>
-#else
-#include <cyassl/options.h>
-#endif
-#include <cyassl/openssl/ssl.h>
-#include <cyassl/error-ssl.h>
-
-#else
-#ifdef _WIN32
-/*
- * Include user-controlled settings for windows from
- * <wolfssl-root>/IDE/WIN/user_settings.h
- */
-#include <IDE/WIN/user_settings.h>
-#include <wolfssl/wolfcrypt/settings.h>
-#else
-#include <wolfssl/options.h>
-#endif
-#include <wolfssl/openssl/ssl.h>
-#include <wolfssl/error-ssl.h>
-#endif /* not USE_OLD_CYASSL */
-#else
-#if defined(LWS_WITH_MBEDTLS)
-#if defined(LWS_WITH_ESP32)
-/* this filepath is passed to us but without quotes or <> */
-#undef MBEDTLS_CONFIG_FILE
-#define MBEDTLS_CONFIG_FILE <mbedtls/esp_config.h>
-#endif
-#include <mbedtls/ssl.h>
-#else
-#include <openssl/ssl.h>
-#if !defined(LWS_WITH_MBEDTLS)
-#include <openssl/err.h>
-#endif
-#endif
-#endif /* not USE_WOLFSSL */
-#endif
-
-/*
- * Helpers for pthread mutex in user code... if lws is built for
- * multiple service threads, these resolve to pthread mutex
- * operations. In the case LWS_MAX_SMP is 1 (the default), they
- * are all NOPs and no pthread type or api is referenced.
- */
-
-#if LWS_MAX_SMP > 1
-
-#include <pthread.h>
-
-#define lws_pthread_mutex(name) pthread_mutex_t name;
-
-static LWS_INLINE void
-lws_pthread_mutex_init(pthread_mutex_t *lock)
-{
- pthread_mutex_init(lock, NULL);
-}
-
-static LWS_INLINE void
-lws_pthread_mutex_destroy(pthread_mutex_t *lock)
-{
- pthread_mutex_destroy(lock);
-}
-
-static LWS_INLINE void
-lws_pthread_mutex_lock(pthread_mutex_t *lock)
-{
- pthread_mutex_lock(lock);
-}
-
-static LWS_INLINE void
-lws_pthread_mutex_unlock(pthread_mutex_t *lock)
-{
- pthread_mutex_unlock(lock);
-}
-
-#else
-#define lws_pthread_mutex(name)
-#define lws_pthread_mutex_init(_a)
-#define lws_pthread_mutex_destroy(_a)
-#define lws_pthread_mutex_lock(_a)
-#define lws_pthread_mutex_unlock(_a)
-#endif
-
-
-#define CONTEXT_PORT_NO_LISTEN -1
-#define CONTEXT_PORT_NO_LISTEN_SERVER -2
-
-/** \defgroup log Logging
- *
- * ##Logging
- *
- * Lws provides flexible and filterable logging facilities, which can be
- * used inside lws and in user code.
- *
- * Log categories may be individually filtered bitwise, and directed to built-in
- * sinks for syslog-compatible logging, or a user-defined function.
- */
-///@{
-
-enum lws_log_levels {
- LLL_ERR = 1 << 0,
- LLL_WARN = 1 << 1,
- LLL_NOTICE = 1 << 2,
- LLL_INFO = 1 << 3,
- LLL_DEBUG = 1 << 4,
- LLL_PARSER = 1 << 5,
- LLL_HEADER = 1 << 6,
- LLL_EXT = 1 << 7,
- LLL_CLIENT = 1 << 8,
- LLL_LATENCY = 1 << 9,
- LLL_USER = 1 << 10,
-
- LLL_COUNT = 11 /* set to count of valid flags */
-};
-
-LWS_VISIBLE LWS_EXTERN void _lws_log(int filter, const char *format, ...) LWS_FORMAT(2);
-LWS_VISIBLE LWS_EXTERN void _lws_logv(int filter, const char *format, va_list vl);
-/**
- * lwsl_timestamp: generate logging timestamp string
- *
- * \param level: logging level
- * \param p: char * buffer to take timestamp
- * \param len: length of p
- *
- * returns length written in p
- */
-LWS_VISIBLE LWS_EXTERN int
-lwsl_timestamp(int level, char *p, int len);
-
-/* these guys are unconditionally included */
-
-#define lwsl_err(...) _lws_log(LLL_ERR, __VA_ARGS__)
-#define lwsl_user(...) _lws_log(LLL_USER, __VA_ARGS__)
-
-#if !defined(LWS_WITH_NO_LOGS)
-/* notice and warn are usually included by being compiled in */
-#define lwsl_warn(...) _lws_log(LLL_WARN, __VA_ARGS__)
-#define lwsl_notice(...) _lws_log(LLL_NOTICE, __VA_ARGS__)
-#endif
-/*
- * weaker logging can be deselected by telling CMake to build in RELEASE mode
- * that gets rid of the overhead of checking while keeping _warn and _err
- * active
- */
-
-#ifdef _DEBUG
-#if defined(LWS_WITH_NO_LOGS)
-/* notice, warn and log are always compiled in */
-#define lwsl_warn(...) _lws_log(LLL_WARN, __VA_ARGS__)
-#define lwsl_notice(...) _lws_log(LLL_NOTICE, __VA_ARGS__)
-#endif
-#define lwsl_info(...) _lws_log(LLL_INFO, __VA_ARGS__)
-#define lwsl_debug(...) _lws_log(LLL_DEBUG, __VA_ARGS__)
-#define lwsl_parser(...) _lws_log(LLL_PARSER, __VA_ARGS__)
-#define lwsl_header(...) _lws_log(LLL_HEADER, __VA_ARGS__)
-#define lwsl_ext(...) _lws_log(LLL_EXT, __VA_ARGS__)
-#define lwsl_client(...) _lws_log(LLL_CLIENT, __VA_ARGS__)
-#define lwsl_latency(...) _lws_log(LLL_LATENCY, __VA_ARGS__)
-
-#else /* no debug */
-#if defined(LWS_WITH_NO_LOGS)
-#define lwsl_warn(...) do {} while(0)
-#define lwsl_notice(...) do {} while(0)
-#endif
-#define lwsl_info(...) do {} while(0)
-#define lwsl_debug(...) do {} while(0)
-#define lwsl_parser(...) do {} while(0)
-#define lwsl_header(...) do {} while(0)
-#define lwsl_ext(...) do {} while(0)
-#define lwsl_client(...) do {} while(0)
-#define lwsl_latency(...) do {} while(0)
-
-#endif
-
-#define lwsl_hexdump_err(...) lwsl_hexdump_level(LLL_ERR, __VA_ARGS__)
-#define lwsl_hexdump_warn(...) lwsl_hexdump_level(LLL_WARN, __VA_ARGS__)
-#define lwsl_hexdump_notice(...) lwsl_hexdump_level(LLL_NOTICE, __VA_ARGS__)
-#define lwsl_hexdump_info(...) lwsl_hexdump_level(LLL_INFO, __VA_ARGS__)
-#define lwsl_hexdump_debug(...) lwsl_hexdump_level(LLL_DEBUG, __VA_ARGS__)
-
-/**
- * lwsl_hexdump_level() - helper to hexdump a buffer at a selected debug level
- *
- * \param level: one of LLL_ constants
- * \param vbuf: buffer start to dump
- * \param len: length of buffer to dump
- *
- * If \p level is visible, does a nice hexdump -C style dump of \p vbuf for
- * \p len bytes. This can be extremely convenient while debugging.
- */
-LWS_VISIBLE LWS_EXTERN void
-lwsl_hexdump_level(int level, const void *vbuf, size_t len);
-
-/**
- * lwsl_hexdump() - helper to hexdump a buffer (DEBUG builds only)
- *
- * \param buf: buffer start to dump
- * \param len: length of buffer to dump
- *
- * Calls through to lwsl_hexdump_level(LLL_DEBUG, ... for compatability.
- * It's better to use lwsl_hexdump_level(level, ... directly so you can control
- * the visibility.
- */
-LWS_VISIBLE LWS_EXTERN void
-lwsl_hexdump(const void *buf, size_t len);
-
-/**
- * lws_is_be() - returns nonzero if the platform is Big Endian
- */
-static LWS_INLINE int lws_is_be(void) {
- const int probe = ~0xff;
-
- return *(const char *)&probe;
-}
-
-/**
- * lws_set_log_level() - Set the logging bitfield
- * \param level: OR together the LLL_ debug contexts you want output from
- * \param log_emit_function: NULL to leave it as it is, or a user-supplied
- * function to perform log string emission instead of
- * the default stderr one.
- *
- * log level defaults to "err", "warn" and "notice" contexts enabled and
- * emission on stderr. If stderr is a tty (according to isatty()) then
- * the output is coloured according to the log level using ANSI escapes.
- */
-LWS_VISIBLE LWS_EXTERN void
-lws_set_log_level(int level,
- void (*log_emit_function)(int level, const char *line));
-
-/**
- * lwsl_emit_syslog() - helper log emit function writes to system log
- *
- * \param level: one of LLL_ log level indexes
- * \param line: log string
- *
- * You use this by passing the function pointer to lws_set_log_level(), to set
- * it as the log emit function, it is not called directly.
- */
-LWS_VISIBLE LWS_EXTERN void
-lwsl_emit_syslog(int level, const char *line);
-
-/**
- * lwsl_visible() - returns true if the log level should be printed
- *
- * \param level: one of LLL_ log level indexes
- *
- * This is useful if you have to do work to generate the log content, you
- * can skip the work if the log level used to print it is not actually
- * enabled at runtime.
- */
-LWS_VISIBLE LWS_EXTERN int
-lwsl_visible(int level);
-
-///@}
-
-
-#include <stddef.h>
-
-#ifndef lws_container_of
-#define lws_container_of(P,T,M) ((T *)((char *)(P) - offsetof(T, M)))
-#endif
-
-struct lws;
-
-typedef int64_t lws_usec_t;
-
-/* api change list for user code to test against */
-
-#define LWS_FEATURE_SERVE_HTTP_FILE_HAS_OTHER_HEADERS_ARG
-
-/* the struct lws_protocols has the id field present */
-#define LWS_FEATURE_PROTOCOLS_HAS_ID_FIELD
-
-/* you can call lws_get_peer_write_allowance */
-#define LWS_FEATURE_PROTOCOLS_HAS_PEER_WRITE_ALLOWANCE
-
-/* extra parameter introduced in 917f43ab821 */
-#define LWS_FEATURE_SERVE_HTTP_FILE_HAS_OTHER_HEADERS_LEN
-
-/* File operations stuff exists */
-#define LWS_FEATURE_FOPS
-
-
-#if defined(_WIN32)
-typedef SOCKET lws_sockfd_type;
-typedef HANDLE lws_filefd_type;
-
-struct lws_pollfd {
- lws_sockfd_type fd; /**< file descriptor */
- SHORT events; /**< which events to respond to */
- SHORT revents; /**< which events happened */
-};
-#define LWS_POLLHUP (FD_CLOSE)
-#define LWS_POLLIN (FD_READ | FD_ACCEPT)
-#define LWS_POLLOUT (FD_WRITE)
-#else
-
-
-#if defined(LWS_WITH_ESP32)
-
-typedef int lws_sockfd_type;
-typedef int lws_filefd_type;
-
-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/FreeRTOS.h>
-#include <freertos/event_groups.h>
-#include <string.h>
-#include "esp_wifi.h"
-#include "esp_system.h"
-#include "esp_event.h"
-#include "esp_event_loop.h"
-#include "nvs.h"
-#include "driver/gpio.h"
-#include "esp_spi_flash.h"
-#include "freertos/timers.h"
-
-#if !defined(CONFIG_FREERTOS_HZ)
-#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 LWS_INLINE void uv_timer_init(void *l, uv_timer_t *t)
-{
- (void)l;
- *t = NULL;
-}
-
-extern void esp32_uvtimer_cb(TimerHandle_t t);
-
-static LWS_INLINE void uv_timer_start(uv_timer_t *t, uv_cb_t *cb, int first, int rep)
-{
- struct timer_mapping *tm = (struct timer_mapping *)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 LWS_INLINE void uv_timer_stop(uv_timer_t *t)
-{
- xTimerStop(*t, 0);
-}
-
-static LWS_INLINE void uv_close(uv_handle_t *h, void *v)
-{
- free(pvTimerGetTimerID((uv_timer_t)h));
- xTimerDelete(*(uv_timer_t *)h, 0);
-}
-
-/* ESP32 helper declarations */
-
-#include <mdns.h>
-#include <esp_partition.h>
-
-#define LWS_PLUGIN_STATIC
-#define LWS_MAGIC_REBOOT_TYPE_ADS 0x50001ffc
-#define LWS_MAGIC_REBOOT_TYPE_REQ_FACTORY 0xb00bcafe
-#define LWS_MAGIC_REBOOT_TYPE_FORCED_FACTORY 0xfaceb00b
-#define LWS_MAGIC_REBOOT_TYPE_FORCED_FACTORY_BUTTON 0xf0cedfac
-
-
-/* user code provides these */
-
-extern void
-lws_esp32_identify_physical_device(void);
-
-/* lws-plat-esp32 provides these */
-
-typedef void (*lws_cb_scan_done)(uint16_t count, wifi_ap_record_t *recs, void *arg);
-
-enum genled_state {
- LWSESP32_GENLED__INIT,
- LWSESP32_GENLED__LOST_NETWORK,
- LWSESP32_GENLED__NO_NETWORK,
- LWSESP32_GENLED__CONN_AP,
- LWSESP32_GENLED__GOT_IP,
- LWSESP32_GENLED__OK,
-};
-
-struct lws_group_member {
- struct lws_group_member *next;
- uint64_t last_seen;
- char model[16];
- char role[16];
- char host[32];
- char mac[20];
- int width, height;
- struct ip4_addr addr;
- struct ip6_addr addrv6;
- uint8_t flags;
-};
-
-#define LWS_SYSTEM_GROUP_MEMBER_ADD 1
-#define LWS_SYSTEM_GROUP_MEMBER_CHANGE 2
-#define LWS_SYSTEM_GROUP_MEMBER_REMOVE 3
-
-#define LWS_GROUP_FLAG_SELF 1
-
-struct lws_esp32 {
- char sta_ip[16];
- char sta_mask[16];
- char sta_gw[16];
- char serial[16];
- char opts[16];
- char model[16];
- char group[16];
- char role[16];
- char ssid[4][64];
- char password[4][64];
- char active_ssid[64];
- char access_pw[16];
- char hostname[32];
- char mac[20];
- char le_dns[64];
- char le_email[64];
- char region;
- char inet;
- char conn_ap;
-
- enum genled_state genled;
- uint64_t genled_t;
-
- lws_cb_scan_done scan_consumer;
- void *scan_consumer_arg;
- struct lws_group_member *first;
- int extant_group_members;
-
- char acme;
- char upload;
-
- volatile char button_is_down;
-};
-
-struct lws_esp32_image {
- uint32_t romfs;
- uint32_t romfs_len;
- uint32_t json;
- uint32_t json_len;
-};
-
-extern struct lws_esp32 lws_esp32;
-struct lws_vhost;
-
-extern esp_err_t
-lws_esp32_event_passthru(void *ctx, system_event_t *event);
-extern void
-lws_esp32_wlan_config(void);
-extern void
-lws_esp32_wlan_start_ap(void);
-extern void
-lws_esp32_wlan_start_station(void);
-struct lws_context_creation_info;
-extern void
-lws_esp32_set_creation_defaults(struct lws_context_creation_info *info);
-extern struct lws_context *
-lws_esp32_init(struct lws_context_creation_info *, struct lws_vhost **pvh);
-extern int
-lws_esp32_wlan_nvs_get(int retry);
-extern esp_err_t
-lws_nvs_set_str(nvs_handle handle, const char* key, const char* value);
-extern void
-lws_esp32_restart_guided(uint32_t type);
-extern const esp_partition_t *
-lws_esp_ota_get_boot_partition(void);
-extern int
-lws_esp32_get_image_info(const esp_partition_t *part, struct lws_esp32_image *i, char *json, int json_len);
-extern int
-lws_esp32_leds_network_indication(void);
-
-extern uint32_t lws_esp32_get_reboot_type(void);
-extern uint16_t lws_esp32_sine_interp(int n);
-
-/* required in external code by esp32 plat (may just return if no leds) */
-extern void lws_esp32_leds_timer_cb(TimerHandle_t th);
-#else
-typedef int lws_sockfd_type;
-typedef int lws_filefd_type;
-#endif
-
-#define lws_pollfd pollfd
-#define LWS_POLLHUP (POLLHUP|POLLERR)
-#define LWS_POLLIN (POLLIN)
-#define LWS_POLLOUT (POLLOUT)
-#endif
-
-
-#if (defined(WIN32) || defined(_WIN32)) && !defined(__MINGW32__)
-/* ... */
-#define ssize_t SSIZE_T
-#endif
-
-#if defined(WIN32) && defined(LWS_HAVE__STAT32I64)
-#include <sys/types.h>
-#include <sys/stat.h>
-#endif
-
-#if defined(LWS_HAVE_STDINT_H)
-#include <stdint.h>
-#else
-#if defined(WIN32) || defined(_WIN32)
-/* !!! >:-[ */
-typedef unsigned __int32 uint32_t;
-typedef unsigned __int16 uint16_t;
-typedef unsigned __int8 uint8_t;
-#else
-typedef unsigned int uint32_t;
-typedef unsigned short uint16_t;
-typedef unsigned char uint8_t;
-#endif
-#endif
-
-typedef unsigned long long lws_filepos_t;
-typedef long long lws_fileofs_t;
-typedef uint32_t lws_fop_flags_t;
-
-/** struct lws_pollargs - argument structure for all external poll related calls
- * passed in via 'in' */
-struct lws_pollargs {
- lws_sockfd_type fd; /**< applicable socket descriptor */
- int events; /**< the new event mask */
- int prev_events; /**< the previous event mask */
-};
-
-struct lws_tokens;
-struct lws_token_limits;
-
-/*! \defgroup wsclose Websocket Close
- *
- * ##Websocket close frame control
- *
- * When we close a ws connection, we can send a reason code and a short
- * UTF-8 description back with the close packet.
- */
-///@{
-
-/*
- * NOTE: These public enums are part of the abi. If you want to add one,
- * add it at where specified so existing users are unaffected.
- */
-/** enum lws_close_status - RFC6455 close status codes */
-enum lws_close_status {
- LWS_CLOSE_STATUS_NOSTATUS = 0,
- LWS_CLOSE_STATUS_NORMAL = 1000,
- /**< 1000 indicates a normal closure, meaning that the purpose for
- which the connection was established has been fulfilled. */
- LWS_CLOSE_STATUS_GOINGAWAY = 1001,
- /**< 1001 indicates that an endpoint is "going away", such as a server
- going down or a browser having navigated away from a page. */
- LWS_CLOSE_STATUS_PROTOCOL_ERR = 1002,
- /**< 1002 indicates that an endpoint is terminating the connection due
- to a protocol error. */
- LWS_CLOSE_STATUS_UNACCEPTABLE_OPCODE = 1003,
- /**< 1003 indicates that an endpoint is terminating the connection
- because it has received a type of data it cannot accept (e.g., an
- endpoint that understands only text data MAY send this if it
- receives a binary message). */
- LWS_CLOSE_STATUS_RESERVED = 1004,
- /**< Reserved. The specific meaning might be defined in the future. */
- LWS_CLOSE_STATUS_NO_STATUS = 1005,
- /**< 1005 is a reserved value and MUST NOT be set as a status code in a
- Close control frame by an endpoint. It is designated for use in
- applications expecting a status code to indicate that no status
- code was actually present. */
- LWS_CLOSE_STATUS_ABNORMAL_CLOSE = 1006,
- /**< 1006 is a reserved value and MUST NOT be set as a status code in a
- Close control frame by an endpoint. It is designated for use in
- applications expecting a status code to indicate that the
- connection was closed abnormally, e.g., without sending or
- receiving a Close control frame. */
- LWS_CLOSE_STATUS_INVALID_PAYLOAD = 1007,
- /**< 1007 indicates that an endpoint is terminating the connection
- because it has received data within a message that was not
- consistent with the type of the message (e.g., non-UTF-8 [RFC3629]
- data within a text message). */
- LWS_CLOSE_STATUS_POLICY_VIOLATION = 1008,
- /**< 1008 indicates that an endpoint is terminating the connection
- because it has received a message that violates its policy. This
- is a generic status code that can be returned when there is no
- other more suitable status code (e.g., 1003 or 1009) or if there
- is a need to hide specific details about the policy. */
- LWS_CLOSE_STATUS_MESSAGE_TOO_LARGE = 1009,
- /**< 1009 indicates that an endpoint is terminating the connection
- because it has received a message that is too big for it to
- process. */
- LWS_CLOSE_STATUS_EXTENSION_REQUIRED = 1010,
- /**< 1010 indicates that an endpoint (client) is terminating the
- connection because it has expected the server to negotiate one or
- more extension, but the server didn't return them in the response
- message of the WebSocket handshake. The list of extensions that
- are needed SHOULD appear in the /reason/ part of the Close frame.
- Note that this status code is not used by the server, because it
- can fail the WebSocket handshake instead */
- LWS_CLOSE_STATUS_UNEXPECTED_CONDITION = 1011,
- /**< 1011 indicates that a server is terminating the connection because
- it encountered an unexpected condition that prevented it from
- fulfilling the request. */
- LWS_CLOSE_STATUS_TLS_FAILURE = 1015,
- /**< 1015 is a reserved value and MUST NOT be set as a status code in a
- Close control frame by an endpoint. It is designated for use in
- applications expecting a status code to indicate that the
- connection was closed due to a failure to perform a TLS handshake
- (e.g., the server certificate can't be verified). */
-
- LWS_CLOSE_STATUS_CLIENT_TRANSACTION_DONE = 2000,
-
- /****** add new things just above ---^ ******/
-
- LWS_CLOSE_STATUS_NOSTATUS_CONTEXT_DESTROY = 9999,
-};
-
-/**
- * lws_close_reason - Set reason and aux data to send with Close packet
- * If you are going to return nonzero from the callback
- * requesting the connection to close, you can optionally
- * call this to set the reason the peer will be told if
- * possible.
- *
- * \param wsi: The websocket connection to set the close reason on
- * \param status: A valid close status from websocket standard
- * \param buf: NULL or buffer containing up to 124 bytes of auxiliary data
- * \param len: Length of data in \param buf to send
- */
-LWS_VISIBLE LWS_EXTERN void
-lws_close_reason(struct lws *wsi, enum lws_close_status status,
- unsigned char *buf, size_t len);
-
-///@}
-
-struct lws;
-struct lws_context;
-/* needed even with extensions disabled for create context */
-struct lws_extension;
-
-
-/*! \defgroup usercb User Callback
- *
- * ##User protocol callback
- *
- * The protocol callback is the primary way lws interacts with
- * user code. For one of a list of a few dozen reasons the callback gets
- * called at some event to be handled.
- *
- * All of the events can be ignored, returning 0 is taken as "OK" and returning
- * nonzero in most cases indicates that the connection should be closed.
- */
-///@{
-
-struct lws_ssl_info {
- int where;
- int ret;
-};
-
-enum lws_cert_update_state {
- LWS_CUS_IDLE,
- LWS_CUS_STARTING,
- LWS_CUS_SUCCESS,
- LWS_CUS_FAILED,
-
- LWS_CUS_CREATE_KEYS,
- LWS_CUS_REG,
- LWS_CUS_AUTH,
- LWS_CUS_CHALLENGE,
- LWS_CUS_CREATE_REQ,
- LWS_CUS_REQ,
- LWS_CUS_CONFIRM,
- LWS_CUS_ISSUE,
-};
-
-enum {
- LWS_TLS_REQ_ELEMENT_COUNTRY,
- LWS_TLS_REQ_ELEMENT_STATE,
- LWS_TLS_REQ_ELEMENT_LOCALITY,
- LWS_TLS_REQ_ELEMENT_ORGANIZATION,
- LWS_TLS_REQ_ELEMENT_COMMON_NAME,
- LWS_TLS_REQ_ELEMENT_EMAIL,
-
- LWS_TLS_REQ_ELEMENT_COUNT,
-
- LWS_TLS_SET_DIR_URL = LWS_TLS_REQ_ELEMENT_COUNT,
- LWS_TLS_SET_AUTH_PATH,
- LWS_TLS_SET_CERT_PATH,
- LWS_TLS_SET_KEY_PATH,
-
- LWS_TLS_TOTAL_COUNT
-};
-
-struct lws_acme_cert_aging_args {
- struct lws_vhost *vh;
- const char *element_overrides[LWS_TLS_TOTAL_COUNT]; /* NULL = use pvo */
-};
-
-/*
- * NOTE: These public enums are part of the abi. If you want to add one,
- * add it at where specified so existing users are unaffected.
- */
-/** enum lws_callback_reasons - reason you're getting a protocol callback */
-enum lws_callback_reasons {
-
- /* ---------------------------------------------------------------------
- * ----- Callbacks related to wsi and protocol binding lifecycle -----
- */
-
- LWS_CALLBACK_PROTOCOL_INIT = 27,
- /**< One-time call per protocol, per-vhost using it, so it can
- * do initial setup / allocations etc */
-
- LWS_CALLBACK_PROTOCOL_DESTROY = 28,
- /**< One-time call per protocol, per-vhost using it, indicating
- * this protocol won't get used at all after this callback, the
- * vhost is getting destroyed. Take the opportunity to
- * deallocate everything that was allocated by the protocol. */
-
- LWS_CALLBACK_WSI_CREATE = 29,
- /**< outermost (earliest) wsi create notification to protocols[0] */
-
- LWS_CALLBACK_WSI_DESTROY = 30,
- /**< outermost (latest) wsi destroy notification to protocols[0] */
-
- LWS_CALLBACK_HTTP_BIND_PROTOCOL = 49,
- /**< By default, all HTTP handling is done in protocols[0].
- * However you can bind different protocols (by name) to
- * different parts of the URL space using callback mounts. This
- * callback occurs in the new protocol when a wsi is bound
- * to that protocol. Any protocol allocation related to the
- * http transaction processing should be created then.
- * These specific callbacks are necessary because with HTTP/1.1,
- * a single connection may perform at series of different
- * transactions at different URLs, thus the lifetime of the
- * protocol bind is just for one transaction, not connection. */
-
- LWS_CALLBACK_HTTP_DROP_PROTOCOL = 50,
- /**< This is called when a transaction is unbound from a protocol.
- * It indicates the connection completed its transaction and may
- * do something different now. Any protocol allocation related
- * to the http transaction processing should be destroyed. */
-
- /* ---------------------------------------------------------------------
- * ----- Callbacks related to Server TLS -----
- */
-
- LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS = 21,
- /**< if configured for
- * including OpenSSL support, this callback allows your user code
- * to perform extra SSL_CTX_load_verify_locations() or similar
- * calls to direct OpenSSL where to find certificates the client
- * can use to confirm the remote server identity. user is the
- * OpenSSL SSL_CTX* */
-
- LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS = 22,
- /**< if configured for
- * including OpenSSL support, this callback allows your user code
- * to load extra certificates into the server which allow it to
- * verify the validity of certificates returned by clients. user
- * is the server's OpenSSL SSL_CTX* and in is the lws_vhost */
-
- LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION = 23,
- /**< if the libwebsockets vhost was created with the option
- * LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT, then this
- * callback is generated during OpenSSL verification of the cert
- * sent from the client. It is sent to protocol[0] callback as
- * no protocol has been negotiated on the connection yet.
- * Notice that the libwebsockets context and wsi are both NULL
- * during this callback. See
- * http://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html
- * to understand more detail about the OpenSSL callback that
- * generates this libwebsockets callback and the meanings of the
- * arguments passed. In this callback, user is the x509_ctx,
- * in is the ssl pointer and len is preverify_ok
- * Notice that this callback maintains libwebsocket return
- * conventions, return 0 to mean the cert is OK or 1 to fail it.
- * This also means that if you don't handle this callback then
- * the default callback action of returning 0 allows the client
- * certificates. */
-
- LWS_CALLBACK_OPENSSL_CONTEXT_REQUIRES_PRIVATE_KEY = 37,
- /**< if configured for including OpenSSL support but no private key
- * file has been specified (ssl_private_key_filepath is NULL), this is
- * called to allow the user to set the private key directly via
- * libopenssl and perform further operations if required; this might be
- * useful in situations where the private key is not directly accessible
- * by the OS, for example if it is stored on a smartcard.
- * user is the server's OpenSSL SSL_CTX* */
-
- LWS_CALLBACK_SSL_INFO = 67,
- /**< SSL connections only. An event you registered an
- * interest in at the vhost has occurred on a connection
- * using the vhost. in is a pointer to a
- * struct lws_ssl_info containing information about the
- * event*/
-
- /* ---------------------------------------------------------------------
- * ----- Callbacks related to Client TLS -----
- */
-
- LWS_CALLBACK_OPENSSL_PERFORM_SERVER_CERT_VERIFICATION = 58,
- /**< Similar to LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION
- * this callback is called during OpenSSL verification of the cert
- * sent from the server to the client. It is sent to protocol[0]
- * callback as no protocol has been negotiated on the connection yet.
- * Notice that the wsi is set because lws_client_connect_via_info was
- * successful.
- *
- * See http://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html
- * to understand more detail about the OpenSSL callback that
- * generates this libwebsockets callback and the meanings of the
- * arguments passed. In this callback, user is the x509_ctx,
- * in is the ssl pointer and len is preverify_ok.
- *
- * THIS IS NOT RECOMMENDED BUT if a cert validation error shall be
- * overruled and cert shall be accepted as ok,
- * X509_STORE_CTX_set_error((X509_STORE_CTX*)user, X509_V_OK); must be
- * called and return value must be 0 to mean the cert is OK;
- * returning 1 will fail the cert in any case.
- *
- * This also means that if you don't handle this callback then
- * the default callback action of returning 0 will not accept the
- * certificate in case of a validation error decided by the SSL lib.
- *
- * This is expected and secure behaviour when validating certificates.
- *
- * Note: LCCSCF_ALLOW_SELFSIGNED and
- * LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK still work without this
- * callback being implemented.
- */
-
- /* ---------------------------------------------------------------------
- * ----- Callbacks related to HTTP Server -----
- */
-
- LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED = 19,
- /**< A new client has been accepted by the ws server. This
- * callback allows setting any relevant property to it. Because this
- * happens immediately after the instantiation of a new client,
- * there's no websocket protocol selected yet so this callback is
- * issued only to protocol 0. Only wsi is defined, pointing to the
- * new client, and the return value is ignored. */
-
- LWS_CALLBACK_HTTP = 12,
- /**< an http request has come from a client that is not
- * asking to upgrade the connection to a websocket
- * one. This is a chance to serve http content,
- * for example, to send a script to the client
- * which will then open the websockets connection.
- * in points to the URI path requested and
- * lws_serve_http_file() makes it very
- * simple to send back a file to the client.
- * Normally after sending the file you are done
- * with the http connection, since the rest of the
- * activity will come by websockets from the script
- * that was delivered by http, so you will want to
- * return 1; to close and free up the connection. */
-
- LWS_CALLBACK_HTTP_BODY = 13,
- /**< the next len bytes data from the http
- * request body HTTP connection is now available in in. */
-
- LWS_CALLBACK_HTTP_BODY_COMPLETION = 14,
- /**< the expected amount of http request body has been delivered */
-
- LWS_CALLBACK_HTTP_FILE_COMPLETION = 15,
- /**< a file requested to be sent down http link has completed. */
-
- LWS_CALLBACK_HTTP_WRITEABLE = 16,
- /**< you can write more down the http protocol link now. */
-
- LWS_CALLBACK_CLOSED_HTTP = 5,
- /**< when a HTTP (non-websocket) session ends */
-
- LWS_CALLBACK_FILTER_HTTP_CONNECTION = 18,
- /**< called when the request has
- * been received and parsed from the client, but the response is
- * not sent yet. Return non-zero to disallow the connection.
- * user is a pointer to the connection user space allocation,
- * in is the URI, eg, "/"
- * In your handler you can use the public APIs
- * lws_hdr_total_length() / lws_hdr_copy() to access all of the
- * headers using the header enums lws_token_indexes from
- * libwebsockets.h to check for and read the supported header
- * presence and content before deciding to allow the http
- * connection to proceed or to kill the connection. */
-
- LWS_CALLBACK_ADD_HEADERS = 53,
- /**< This gives your user code a chance to add headers to a server
- * transaction bound to your protocol. `in` points to a
- * `struct lws_process_html_args` describing a buffer and length
- * you can add headers into using the normal lws apis.
- *
- * (see LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER to add headers to
- * a client transaction)
- *
- * Only `args->p` and `args->len` are valid, and `args->p` should
- * be moved on by the amount of bytes written, if any. Eg
- *
- * case LWS_CALLBACK_ADD_HEADERS:
- *
- * struct lws_process_html_args *args =
- * (struct lws_process_html_args *)in;
- *
- * if (lws_add_http_header_by_name(wsi,
- * (unsigned char *)"set-cookie:",
- * (unsigned char *)cookie, cookie_len,
- * (unsigned char **)&args->p,
- * (unsigned char *)args->p + args->max_len))
- * return 1;
- *
- * break;
- */
-
- LWS_CALLBACK_CHECK_ACCESS_RIGHTS = 51,
- /**< This gives the user code a chance to forbid an http access.
- * `in` points to a `struct lws_process_html_args`, which
- * describes the URL, and a bit mask describing the type of
- * authentication required. If the callback returns nonzero,
- * the transaction ends with HTTP_STATUS_UNAUTHORIZED. */
-
- LWS_CALLBACK_PROCESS_HTML = 52,
- /**< This gives your user code a chance to mangle outgoing
- * HTML. `in` points to a `struct lws_process_html_args`
- * which describes the buffer containing outgoing HTML.
- * The buffer may grow up to `.max_len` (currently +128
- * bytes per buffer).
- */
-
- /* ---------------------------------------------------------------------
- * ----- Callbacks related to HTTP Client -----
- */
-
- LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP = 44,
- /**< The HTTP client connection has succeeded, and is now
- * connected to the server */
-
- LWS_CALLBACK_CLOSED_CLIENT_HTTP = 45,
- /**< The HTTP client connection is closing */
-
- LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ = 48,
- /**< This is generated by lws_http_client_read() used to drain
- * incoming data. In the case the incoming data was chunked, it will
- * be split into multiple smaller callbacks for each chunk block,
- * removing the chunk headers. If not chunked, it will appear all in
- * one callback. */
-
- LWS_CALLBACK_RECEIVE_CLIENT_HTTP = 46,
- /**< This simply indicates data was received on the HTTP client
- * connection. It does NOT drain or provide the data.
- * This exists to neatly allow a proxying type situation,
- * where this incoming data will go out on another connection.
- * If the outgoing connection stalls, we should stall processing
- * the incoming data. So a handler for this in that case should
- * simply set a flag to indicate there is incoming data ready
- * and ask for a writeable callback on the outgoing connection.
- * In the writable callback he can check the flag and then get
- * and drain the waiting incoming data using lws_http_client_read().
- * This will use callbacks to LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ
- * to get and drain the incoming data, where it should be sent
- * back out on the outgoing connection. */
- LWS_CALLBACK_COMPLETED_CLIENT_HTTP = 47,
- /**< The client transaction completed... at the moment this
- * is the same as closing since transaction pipelining on
- * client side is not yet supported. */
-
- LWS_CALLBACK_CLIENT_HTTP_WRITEABLE = 57,
- /**< when doing an HTTP type client connection, you can call
- * lws_client_http_body_pending(wsi, 1) from
- * LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER to get these callbacks
- * sending the HTTP headers.
- *
- * From this callback, when you have sent everything, you should let
- * lws know by calling lws_client_http_body_pending(wsi, 0)
- */
-
- /* ---------------------------------------------------------------------
- * ----- Callbacks related to Websocket Server -----
- */
-
- LWS_CALLBACK_ESTABLISHED = 0,
- /**< (VH) after the server completes a handshake with an incoming
- * client. If you built the library with ssl support, in is a
- * pointer to the ssl struct associated with the connection or NULL.
- *
- * b0 of len is set if the connection was made using ws-over-h2
- */
-
- LWS_CALLBACK_CLOSED = 4,
- /**< when the websocket session ends */
-
- LWS_CALLBACK_SERVER_WRITEABLE = 11,
- /**< See LWS_CALLBACK_CLIENT_WRITEABLE */
-
- LWS_CALLBACK_RECEIVE = 6,
- /**< data has appeared for this server endpoint from a
- * remote client, it can be found at *in and is
- * len bytes long */
-
- LWS_CALLBACK_RECEIVE_PONG = 7,
- /**< servers receive PONG packets with this callback reason */
-
- LWS_CALLBACK_WS_PEER_INITIATED_CLOSE = 38,
- /**< The peer has sent an unsolicited Close WS packet. in and
- * len are the optional close code (first 2 bytes, network
- * order) and the optional additional information which is not
- * defined in the standard, and may be a string or non human-readable
- * data.
- * If you return 0 lws will echo the close and then close the
- * connection. If you return nonzero lws will just close the
- * connection. */
-
- LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION = 20,
- /**< called when the handshake has
- * been received and parsed from the client, but the response is
- * not sent yet. Return non-zero to disallow the connection.
- * user is a pointer to the connection user space allocation,
- * in is the requested protocol name
- * In your handler you can use the public APIs
- * lws_hdr_total_length() / lws_hdr_copy() to access all of the
- * headers using the header enums lws_token_indexes from
- * libwebsockets.h to check for and read the supported header
- * presence and content before deciding to allow the handshake
- * to proceed or to kill the connection. */
-
- LWS_CALLBACK_CONFIRM_EXTENSION_OKAY = 25,
- /**< When the server handshake code
- * sees that it does support a requested extension, before
- * accepting the extension by additing to the list sent back to
- * the client it gives this callback just to check that it's okay
- * to use that extension. It calls back to the requested protocol
- * and with in being the extension name, len is 0 and user is
- * valid. Note though at this time the ESTABLISHED callback hasn't
- * happened yet so if you initialize user content there, user
- * content during this callback might not be useful for anything. */
-
- /* ---------------------------------------------------------------------
- * ----- Callbacks related to Websocket Client -----
- */
-
- LWS_CALLBACK_CLIENT_CONNECTION_ERROR = 1,
- /**< the request client connection has been unable to complete a
- * handshake with the remote server. If in is non-NULL, you can
- * find an error string of length len where it points to
- *
- * Diagnostic strings that may be returned include
- *
- * "getaddrinfo (ipv6) failed"
- * "unknown address family"
- * "getaddrinfo (ipv4) failed"
- * "set socket opts failed"
- * "insert wsi failed"
- * "lws_ssl_client_connect1 failed"
- * "lws_ssl_client_connect2 failed"
- * "Peer hung up"
- * "read failed"
- * "HS: URI missing"
- * "HS: Redirect code but no Location"
- * "HS: URI did not parse"
- * "HS: Redirect failed"
- * "HS: Server did not return 200"
- * "HS: OOM"
- * "HS: disallowed by client filter"
- * "HS: disallowed at ESTABLISHED"
- * "HS: ACCEPT missing"
- * "HS: ws upgrade response not 101"
- * "HS: UPGRADE missing"
- * "HS: Upgrade to something other than websocket"
- * "HS: CONNECTION missing"
- * "HS: UPGRADE malformed"
- * "HS: PROTOCOL malformed"
- * "HS: Cannot match protocol"
- * "HS: EXT: list too big"
- * "HS: EXT: failed setting defaults"
- * "HS: EXT: failed parsing defaults"
- * "HS: EXT: failed parsing options"
- * "HS: EXT: Rejects server options"
- * "HS: EXT: unknown ext"
- * "HS: Accept hash wrong"
- * "HS: Rejected by filter cb"
- * "HS: OOM"
- * "HS: SO_SNDBUF failed"
- * "HS: Rejected at CLIENT_ESTABLISHED"
- */
-
- LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH = 2,
- /**< this is the last chance for the client user code to examine the
- * http headers and decide to reject the connection. If the
- * content in the headers is interesting to the
- * client (url, etc) it needs to copy it out at
- * this point since it will be destroyed before
- * the CLIENT_ESTABLISHED call */
-
- LWS_CALLBACK_CLIENT_ESTABLISHED = 3,
- /**< after your client connection completed the websocket upgrade
- * handshake with the remote server */
-
- LWS_CALLBACK_CLIENT_CLOSED = 75,
- /**< when a client websocket session ends */
-
- LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER = 24,
- /**< this callback happens
- * when a client handshake is being compiled. user is NULL,
- * in is a char **, it's pointing to a char * which holds the
- * next location in the header buffer where you can add
- * headers, and len is the remaining space in the header buffer,
- * which is typically some hundreds of bytes. So, to add a canned
- * cookie, your handler code might look similar to:
- *
- * char **p = (char **)in;
- *
- * if (len < 100)
- * return 1;
- *
- * *p += sprintf(*p, "Cookie: a=b\x0d\x0a");
- *
- * return 0;
- *
- * Notice if you add anything, you just have to take care about
- * the CRLF on the line you added. Obviously this callback is
- * optional, if you don't handle it everything is fine.
- *
- * Notice the callback is coming to protocols[0] all the time,
- * because there is no specific protocol negotiated yet.
- *
- * See LWS_CALLBACK_ADD_HEADERS for adding headers to server
- * transactions.
- */
-
- LWS_CALLBACK_CLIENT_RECEIVE = 8,
- /**< data has appeared from the server for the client connection, it
- * can be found at *in and is len bytes long */
-
- LWS_CALLBACK_CLIENT_RECEIVE_PONG = 9,
- /**< clients receive PONG packets with this callback reason */
-
- LWS_CALLBACK_CLIENT_WRITEABLE = 10,
- /**< If you call lws_callback_on_writable() on a connection, you will
- * get one of these callbacks coming when the connection socket
- * is able to accept another write packet without blocking.
- * If it already was able to take another packet without blocking,
- * you'll get this callback at the next call to the service loop
- * function. Notice that CLIENTs get LWS_CALLBACK_CLIENT_WRITEABLE
- * and servers get LWS_CALLBACK_SERVER_WRITEABLE. */
-
- LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED = 26,
- /**< When a ws client
- * connection is being prepared to start a handshake to a server,
- * each supported extension is checked with protocols[0] callback
- * with this reason, giving the user code a chance to suppress the
- * claim to support that extension by returning non-zero. If
- * unhandled, by default 0 will be returned and the extension
- * support included in the header to the server. Notice this
- * callback comes to protocols[0]. */
-
- LWS_CALLBACK_WS_EXT_DEFAULTS = 39,
- /**< Gives client connections an opportunity to adjust negotiated
- * extension defaults. `user` is the extension name that was
- * negotiated (eg, "permessage-deflate"). `in` points to a
- * buffer and `len` is the buffer size. The user callback can
- * set the buffer to a string describing options the extension
- * should parse. Or just ignore for defaults. */
-
-
- LWS_CALLBACK_FILTER_NETWORK_CONNECTION = 17,
- /**< called when a client connects to
- * the server at network level; the connection is accepted but then
- * passed to this callback to decide whether to hang up immediately
- * or not, based on the client IP. in contains the connection
- * socket's descriptor. Since the client connection information is
- * not available yet, wsi still pointing to the main server socket.
- * Return non-zero to terminate the connection before sending or
- * receiving anything. Because this happens immediately after the
- * network connection from the client, there's no websocket protocol
- * selected yet so this callback is issued only to protocol 0. */
-
- /* ---------------------------------------------------------------------
- * ----- Callbacks related to external poll loop integration -----
- */
-
- LWS_CALLBACK_GET_THREAD_ID = 31,
- /**< lws can accept callback when writable requests from other
- * threads, if you implement this callback and return an opaque
- * current thread ID integer. */
-
- /* external poll() management support */
- LWS_CALLBACK_ADD_POLL_FD = 32,
- /**< lws normally deals with its poll() or other event loop
- * internally, but in the case you are integrating with another
- * server you will need to have lws sockets share a
- * polling array with the other server. This and the other
- * POLL_FD related callbacks let you put your specialized
- * poll array interface code in the callback for protocol 0, the
- * first protocol you support, usually the HTTP protocol in the
- * serving case.
- * This callback happens when a socket needs to be
- * added to the polling loop: in points to a struct
- * lws_pollargs; the fd member of the struct is the file
- * descriptor, and events contains the active events
- *
- * If you are using the internal lws polling / event loop
- * you can just ignore these callbacks. */
-
- LWS_CALLBACK_DEL_POLL_FD = 33,
- /**< This callback happens when a socket descriptor
- * needs to be removed from an external polling array. in is
- * again the struct lws_pollargs containing the fd member
- * to be removed. If you are using the internal polling
- * loop, you can just ignore it. */
-
- LWS_CALLBACK_CHANGE_MODE_POLL_FD = 34,
- /**< This callback happens when lws wants to modify the events for
- * a connection.
- * in is the struct lws_pollargs with the fd to change.
- * The new event mask is in events member and the old mask is in
- * the prev_events member.
- * If you are using the internal polling loop, you can just ignore
- * it. */
-
- LWS_CALLBACK_LOCK_POLL = 35,
- /**< These allow the external poll changes driven
- * by lws to participate in an external thread locking
- * scheme around the changes, so the whole thing is threadsafe.
- * These are called around three activities in the library,
- * - inserting a new wsi in the wsi / fd table (len=1)
- * - deleting a wsi from the wsi / fd table (len=1)
- * - changing a wsi's POLLIN/OUT state (len=0)
- * Locking and unlocking external synchronization objects when
- * len == 1 allows external threads to be synchronized against
- * wsi lifecycle changes if it acquires the same lock for the
- * duration of wsi dereference from the other thread context. */
-
- LWS_CALLBACK_UNLOCK_POLL = 36,
- /**< See LWS_CALLBACK_LOCK_POLL, ignore if using lws internal poll */
-
- /* ---------------------------------------------------------------------
- * ----- Callbacks related to CGI serving -----
- */
-
- LWS_CALLBACK_CGI = 40,
- /**< CGI: CGI IO events on stdin / out / err are sent here on
- * protocols[0]. The provided `lws_callback_http_dummy()`
- * handles this and the callback should be directed there if
- * you use CGI. */
-
- LWS_CALLBACK_CGI_TERMINATED = 41,
- /**< CGI: The related CGI process ended, this is called before
- * the wsi is closed. Used to, eg, terminate chunking.
- * The provided `lws_callback_http_dummy()`
- * handles this and the callback should be directed there if
- * you use CGI. The child PID that terminated is in len. */
-
- LWS_CALLBACK_CGI_STDIN_DATA = 42,
- /**< CGI: Data is, to be sent to the CGI process stdin, eg from
- * a POST body. The provided `lws_callback_http_dummy()`
- * handles this and the callback should be directed there if
- * you use CGI. */
-
- LWS_CALLBACK_CGI_STDIN_COMPLETED = 43,
- /**< CGI: no more stdin is coming. The provided
- * `lws_callback_http_dummy()` handles this and the callback
- * should be directed there if you use CGI. */
-
- LWS_CALLBACK_CGI_PROCESS_ATTACH = 70,
- /**< CGI: Sent when the CGI process is spawned for the wsi. The
- * len parameter is the PID of the child process */
-
- /* ---------------------------------------------------------------------
- * ----- Callbacks related to Generic Sessions -----
- */
-
- LWS_CALLBACK_SESSION_INFO = 54,
- /**< This is only generated by user code using generic sessions.
- * It's used to get a `struct lws_session_info` filled in by
- * generic sessions with information about the logged-in user.
- * See the messageboard sample for an example of how to use. */
-
- LWS_CALLBACK_GS_EVENT = 55,
- /**< Indicates an event happened to the Generic Sessions session.
- * `in` contains a `struct lws_gs_event_args` describing the event. */
-
- LWS_CALLBACK_HTTP_PMO = 56,
- /**< per-mount options for this connection, called before
- * the normal LWS_CALLBACK_HTTP when the mount has per-mount
- * options.
- */
-
- /* ---------------------------------------------------------------------
- * ----- Callbacks related to RAW sockets -----
- */
-
- LWS_CALLBACK_RAW_RX = 59,
- /**< RAW mode connection RX */
-
- LWS_CALLBACK_RAW_CLOSE = 60,
- /**< RAW mode connection is closing */
-
- LWS_CALLBACK_RAW_WRITEABLE = 61,
- /**< RAW mode connection may be written */
-
- LWS_CALLBACK_RAW_ADOPT = 62,
- /**< RAW mode connection was adopted (equivalent to 'wsi created') */
-
- /* ---------------------------------------------------------------------
- * ----- Callbacks related to RAW file handles -----
- */
-
- LWS_CALLBACK_RAW_ADOPT_FILE = 63,
- /**< RAW mode file was adopted (equivalent to 'wsi created') */
-
- LWS_CALLBACK_RAW_RX_FILE = 64,
- /**< This is the indication the RAW mode file has something to read.
- * This doesn't actually do the read of the file and len is always
- * 0... your code should do the read having been informed there is
- * something to read now. */
-
- LWS_CALLBACK_RAW_WRITEABLE_FILE = 65,
- /**< RAW mode file is writeable */
-
- LWS_CALLBACK_RAW_CLOSE_FILE = 66,
- /**< RAW mode wsi that adopted a file is closing */
-
- /* ---------------------------------------------------------------------
- * ----- Callbacks related to generic wsi events -----
- */
-
- LWS_CALLBACK_TIMER = 73,
- /**< When the time elapsed after a call to
- * lws_set_timer_usecs(wsi, usecs) is up, the wsi will get one of
- * these callbacks. The deadline can be continuously extended into the
- * future by later calls to lws_set_timer_usecs() before the deadline
- * expires, or cancelled by lws_set_timer_usecs(wsi, -1);
- * See the note on lws_set_timer_usecs() about which event loops are
- * supported. */
-
- LWS_CALLBACK_EVENT_WAIT_CANCELLED = 71,
- /**< This is sent to every protocol of every vhost in response
- * to lws_cancel_service() or lws_cancel_service_pt(). This
- * callback is serialized in the lws event loop normally, even
- * if the lws_cancel_service[_pt]() call was from a different
- * thread. */
-
- LWS_CALLBACK_CHILD_CLOSING = 69,
- /**< Sent to parent to notify them a child is closing / being
- * destroyed. in is the child wsi.
- */
-
- LWS_CALLBACK_CHILD_WRITE_VIA_PARENT = 68,
- /**< Child has been marked with parent_carries_io attribute, so
- * lws_write directs the to this callback at the parent,
- * in is a struct lws_write_passthru containing the args
- * the lws_write() was called with.
- */
-
- /* ---------------------------------------------------------------------
- * ----- Callbacks related to TLS certificate management -----
- */
-
- LWS_CALLBACK_VHOST_CERT_AGING = 72,
- /**< When a vhost TLS cert has its expiry checked, this callback
- * is broadcast to every protocol of every vhost in case the
- * protocol wants to take some action with this information.
- * \p in is a pointer to a struct lws_acme_cert_aging_args,
- * and \p len is the number of days left before it expires, as
- * a (ssize_t). In the struct lws_acme_cert_aging_args, vh
- * points to the vhost the cert aging information applies to,
- * and element_overrides[] is an optional way to update information
- * from the pvos... NULL in an index means use the information from
- * from the pvo for the cert renewal, non-NULL in the array index
- * means use that pointer instead for the index. */
-
- LWS_CALLBACK_VHOST_CERT_UPDATE = 74,
- /**< When a vhost TLS cert is being updated, progress is
- * reported to the vhost in question here, including completion
- * and failure. in points to optional JSON, and len represents the
- * connection state using enum lws_cert_update_state */
-
-
- /****** add new things just above ---^ ******/
-
- LWS_CALLBACK_USER = 1000,
- /**< user code can use any including above without fear of clashes */
-};
-
-
-
-/**
- * typedef lws_callback_function() - User server actions
- * \param wsi: Opaque websocket instance pointer
- * \param reason: The reason for the call
- * \param user: Pointer to per-session user data allocated by library
- * \param in: Pointer used for some callback reasons
- * \param len: Length set for some callback reasons
- *
- * This callback is the way the user controls what is served. All the
- * protocol detail is hidden and handled by the library.
- *
- * For each connection / session there is user data allocated that is
- * pointed to by "user". You set the size of this user data area when
- * the library is initialized with lws_create_server.
- */
-typedef int
-lws_callback_function(struct lws *wsi, enum lws_callback_reasons reason,
- void *user, void *in, size_t len);
-
-#define LWS_CB_REASON_AUX_BF__CGI 1
-#define LWS_CB_REASON_AUX_BF__PROXY 2
-#define LWS_CB_REASON_AUX_BF__CGI_CHUNK_END 4
-#define LWS_CB_REASON_AUX_BF__CGI_HEADERS 8
-///@}
-
-struct lws_vhost;
-
-/*! \defgroup generic hash
- * ## Generic Hash related functions
- *
- * Lws provides generic hash / digest accessors that abstract the ones
- * provided by whatever OpenSSL library you are linking against.
- *
- * It lets you use the same code if you build against mbedtls or OpenSSL
- * for example.
- */
-///@{
-
-#if defined(LWS_WITH_TLS)
-
-#if defined(LWS_WITH_MBEDTLS)
-#include <mbedtls/sha1.h>
-#include <mbedtls/sha256.h>
-#include <mbedtls/sha512.h>
-#endif
-
-enum lws_genhash_types {
- LWS_GENHASH_TYPE_SHA1,
- LWS_GENHASH_TYPE_SHA256,
- LWS_GENHASH_TYPE_SHA384,
- LWS_GENHASH_TYPE_SHA512,
-};
-
-enum lws_genhmac_types {
- LWS_GENHMAC_TYPE_SHA256,
- LWS_GENHMAC_TYPE_SHA384,
- LWS_GENHMAC_TYPE_SHA512,
-};
-
-#define LWS_GENHASH_LARGEST 64
-
-struct lws_genhash_ctx {
- uint8_t type;
-#if defined(LWS_WITH_MBEDTLS)
- union {
- mbedtls_sha1_context sha1;
- mbedtls_sha256_context sha256;
- mbedtls_sha512_context sha512; /* 384 also uses this */
- const mbedtls_md_info_t *hmac;
- } u;
-#else
- const EVP_MD *evp_type;
- EVP_MD_CTX *mdctx;
-#endif
-};
-
-struct lws_genhmac_ctx {
- uint8_t type;
-#if defined(LWS_WITH_MBEDTLS)
- const mbedtls_md_info_t *hmac;
- mbedtls_md_context_t ctx;
-#else
- const EVP_MD *evp_type;
- EVP_MD_CTX *ctx;
-#endif
-};
-
-/** lws_genhash_size() - get hash size in bytes
- *
- * \param type: one of LWS_GENHASH_TYPE_...
- *
- * Returns number of bytes in this type of hash
- */
-LWS_VISIBLE LWS_EXTERN size_t LWS_WARN_UNUSED_RESULT
-lws_genhash_size(enum lws_genhash_types type);
-
-/** lws_genhmac_size() - get hash size in bytes
- *
- * \param type: one of LWS_GENHASH_TYPE_...
- *
- * Returns number of bytes in this type of hmac
- */
-LWS_VISIBLE LWS_EXTERN size_t LWS_WARN_UNUSED_RESULT
-lws_genhmac_size(enum lws_genhmac_types type);
-
-/** lws_genhash_init() - prepare your struct lws_genhash_ctx for use
- *
- * \param ctx: your struct lws_genhash_ctx
- * \param type: one of LWS_GENHASH_TYPE_...
- *
- * Initializes the hash context for the type you requested
- */
-LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_genhash_init(struct lws_genhash_ctx *ctx, enum lws_genhash_types type);
-
-/** lws_genhash_update() - digest len bytes of the buffer starting at in
- *
- * \param ctx: your struct lws_genhash_ctx
- * \param in: start of the bytes to digest
- * \param len: count of bytes to digest
- *
- * Updates the state of your hash context to reflect digesting len bytes from in
- */
-LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_genhash_update(struct lws_genhash_ctx *ctx, const void *in, size_t len);
-
-/** lws_genhash_destroy() - copy out the result digest and destroy the ctx
- *
- * \param ctx: your struct lws_genhash_ctx
- * \param result: NULL, or where to copy the result hash
- *
- * Finalizes the hash and copies out the digest. Destroys any allocations such
- * that ctx can safely go out of scope after calling this.
- *
- * NULL result is supported so that you can destroy the ctx cleanly on error
- * conditions, where there is no valid result.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_genhash_destroy(struct lws_genhash_ctx *ctx, void *result);
-
-/** lws_genhmac_init() - prepare your struct lws_genhmac_ctx for use
- *
- * \param ctx: your struct lws_genhmac_ctx
- * \param type: one of LWS_GENHMAC_TYPE_...
- * \param key: pointer to the start of the HMAC key
- * \param key_len: length of the HMAC key
- *
- * Initializes the hash context for the type you requested
- *
- * If the return is nonzero, it failed and there is nothing needing to be
- * destroyed.
- */
-LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_genhmac_init(struct lws_genhmac_ctx *ctx, enum lws_genhmac_types type,
- const uint8_t *key, size_t key_len);
-
-/** lws_genhmac_update() - digest len bytes of the buffer starting at in
- *
- * \param ctx: your struct lws_genhmac_ctx
- * \param in: start of the bytes to digest
- * \param len: count of bytes to digest
- *
- * Updates the state of your hash context to reflect digesting len bytes from in
- *
- * If the return is nonzero, it failed and needs destroying.
- */
-LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_genhmac_update(struct lws_genhmac_ctx *ctx, const void *in, size_t len);
-
-/** lws_genhmac_destroy() - copy out the result digest and destroy the ctx
- *
- * \param ctx: your struct lws_genhmac_ctx
- * \param result: NULL, or where to copy the result hash
- *
- * Finalizes the hash and copies out the digest. Destroys any allocations such
- * that ctx can safely go out of scope after calling this.
- *
- * NULL result is supported so that you can destroy the ctx cleanly on error
- * conditions, where there is no valid result.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_genhmac_destroy(struct lws_genhmac_ctx *ctx, void *result);
-///@}
-
-/*! \defgroup generic RSA
- * ## Generic RSA related functions
- *
- * Lws provides generic RSA functions that abstract the ones
- * provided by whatever OpenSSL library you are linking against.
- *
- * It lets you use the same code if you build against mbedtls or OpenSSL
- * for example.
- */
-///@{
-
-enum enum_jwk_tok {
- JWK_KEY_E,
- JWK_KEY_N,
- JWK_KEY_D,
- JWK_KEY_P,
- JWK_KEY_Q,
- JWK_KEY_DP,
- JWK_KEY_DQ,
- JWK_KEY_QI,
- JWK_KTY, /* also serves as count of real elements */
- JWK_KEY,
-};
-
-#define LWS_COUNT_RSA_ELEMENTS JWK_KTY
-
-struct lws_genrsa_ctx {
-#if defined(LWS_WITH_MBEDTLS)
- mbedtls_rsa_context *ctx;
-#else
- BIGNUM *bn[LWS_COUNT_RSA_ELEMENTS];
- RSA *rsa;
-#endif
-};
-
-struct lws_genrsa_element {
- uint8_t *buf;
- uint16_t len;
-};
-
-struct lws_genrsa_elements {
- struct lws_genrsa_element e[LWS_COUNT_RSA_ELEMENTS];
-};
-
-/** lws_jwk_destroy_genrsa_elements() - Free allocations in genrsa_elements
- *
- * \param el: your struct lws_genrsa_elements
- *
- * This is a helper for user code making use of struct lws_genrsa_elements
- * where the elements are allocated on the heap, it frees any non-NULL
- * buf element and sets the buf to NULL.
- *
- * NB: lws_genrsa_public_... apis do not need this as they take care of the key
- * creation and destruction themselves.
- */
-LWS_VISIBLE LWS_EXTERN void
-lws_jwk_destroy_genrsa_elements(struct lws_genrsa_elements *el);
-
-/** lws_genrsa_public_decrypt_create() - Create RSA public decrypt context
- *
- * \param ctx: your struct lws_genrsa_ctx
- * \param el: struct prepared with key element data
- *
- * Creates an RSA context with a public key associated with it, formed from
- * the key elements in \p el.
- *
- * Returns 0 for OK or nonzero for error.
- *
- * This and related APIs operate identically with OpenSSL or mbedTLS backends.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_genrsa_create(struct lws_genrsa_ctx *ctx, struct lws_genrsa_elements *el);
-
-/** lws_genrsa_new_keypair() - Create new RSA keypair
- *
- * \param context: your struct lws_context (may be used for RNG)
- * \param ctx: your struct lws_genrsa_ctx
- * \param el: struct to get the new key element data allocated into it
- * \param bits: key size, eg, 4096
- *
- * Creates a new RSA context and generates a new keypair into it, with \p bits
- * bits.
- *
- * Returns 0 for OK or nonzero for error.
- *
- * This and related APIs operate identically with OpenSSL or mbedTLS backends.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_genrsa_new_keypair(struct lws_context *context, struct lws_genrsa_ctx *ctx,
- struct lws_genrsa_elements *el, int bits);
-
-/** lws_genrsa_public_decrypt() - Perform RSA public decryption
- *
- * \param ctx: your struct lws_genrsa_ctx
- * \param in: encrypted input
- * \param in_len: length of encrypted input
- * \param out: decrypted output
- * \param out_max: size of output buffer
- *
- * Performs the decryption.
- *
- * Returns <0 for error, or length of decrypted data.
- *
- * This and related APIs operate identically with OpenSSL or mbedTLS backends.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_genrsa_public_decrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in,
- size_t in_len, uint8_t *out, size_t out_max);
-
-/** lws_genrsa_public_verify() - Perform RSA public verification
- *
- * \param ctx: your struct lws_genrsa_ctx
- * \param in: unencrypted payload (usually a recomputed hash)
- * \param hash_type: one of LWS_GENHASH_TYPE_
- * \param sig: pointer to the signature we received with the payload
- * \param sig_len: length of the signature we are checking in bytes
- *
- * Returns <0 for error, or 0 if signature matches the payload + key.
- *
- * This and related APIs operate identically with OpenSSL or mbedTLS backends.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_genrsa_public_verify(struct lws_genrsa_ctx *ctx, const uint8_t *in,
- enum lws_genhash_types hash_type,
- const uint8_t *sig, size_t sig_len);
-
-/** lws_genrsa_public_sign() - Create RSA signature
- *
- * \param ctx: your struct lws_genrsa_ctx
- * \param in: precomputed hash
- * \param hash_type: one of LWS_GENHASH_TYPE_
- * \param sig: pointer to buffer to take signature
- * \param sig_len: length of the buffer (must be >= length of key N)
- *
- * Returns <0 for error, or 0 for success.
- *
- * This and related APIs operate identically with OpenSSL or mbedTLS backends.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_genrsa_public_sign(struct lws_genrsa_ctx *ctx, const uint8_t *in,
- enum lws_genhash_types hash_type, uint8_t *sig,
- size_t sig_len);
-
-/** lws_genrsa_public_decrypt_destroy() - Destroy RSA public decrypt context
- *
- * \param ctx: your struct lws_genrsa_ctx
- *
- * Destroys any allocations related to \p ctx.
- *
- * This and related APIs operate identically with OpenSSL or mbedTLS backends.
- */
-LWS_VISIBLE LWS_EXTERN void
-lws_genrsa_destroy(struct lws_genrsa_ctx *ctx);
-
-/** lws_genrsa_render_pkey_asn1() - Exports public or private key to ASN1/DER
- *
- * \param ctx: your struct lws_genrsa_ctx
- * \param _private: 0 = public part only, 1 = all parts of the key
- * \param pkey_asn1: pointer to buffer to take the ASN1
- * \param pkey_asn1_len: max size of the pkey_asn1_len
- *
- * Returns length of pkey_asn1 written, or -1 for error.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_genrsa_render_pkey_asn1(struct lws_genrsa_ctx *ctx, int _private,
- uint8_t *pkey_asn1, size_t pkey_asn1_len);
-///@}
-
-/*! \defgroup jwk JSON Web Keys
- * ## JSON Web Keys API
- *
- * Lws provides an API to parse JSON Web Keys into a struct lws_genrsa_elements.
- *
- * "oct" and "RSA" type keys are supported. For "oct" keys, they are held in
- * the "e" member of the struct lws_genrsa_elements.
- *
- * Keys elements are allocated on the heap. You must destroy the allocations
- * in the struct lws_genrsa_elements by calling
- * lws_jwk_destroy_genrsa_elements() when you are finished with it.
- */
-///@{
-
-struct lws_jwk {
- char keytype[5]; /**< "oct" or "RSA" */
- struct lws_genrsa_elements el; /**< OCTet key is in el.e */
-};
-
-/** lws_jwk_import() - Create a JSON Web key from the textual representation
- *
- * \param s: the JWK object to create
- * \param in: a single JWK JSON stanza in utf-8
- * \param len: the length of the JWK JSON stanza in bytes
- *
- * Creates an lws_jwk struct filled with data from the JSON representation.
- * "oct" and "rsa" key types are supported.
- *
- * For "oct" type keys, it is loaded into el.e.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_jwk_import(struct lws_jwk *s, const char *in, size_t len);
-
-/** lws_jwk_destroy() - Destroy a JSON Web key
- *
- * \param s: the JWK object to destroy
- *
- * All allocations in the lws_jwk are destroyed
- */
-LWS_VISIBLE LWS_EXTERN void
-lws_jwk_destroy(struct lws_jwk *s);
-
-/** lws_jwk_export() - Export a JSON Web key to a textual representation
- *
- * \param s: the JWK object to export
- * \param _private: 0 = just export public parts, 1 = export everything
- * \param p: the buffer to write the exported JWK to
- * \param len: the length of the buffer \p p in bytes
- *
- * Returns length of the used part of the buffer if OK, or -1 for error.
- *
- * Serializes the content of the JWK into a char buffer.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_jwk_export(struct lws_jwk *s, int _private, char *p, size_t len);
-
-/** lws_jwk_load() - Import a JSON Web key from a file
- *
- * \param s: the JWK object to load into
- * \param filename: filename to load from
- *
- * Returns 0 for OK or -1 for failure
- */
-LWS_VISIBLE int
-lws_jwk_load(struct lws_jwk *s, const char *filename);
-
-/** lws_jwk_save() - Export a JSON Web key to a file
- *
- * \param s: the JWK object to save from
- * \param filename: filename to save to
- *
- * Returns 0 for OK or -1 for failure
- */
-LWS_VISIBLE int
-lws_jwk_save(struct lws_jwk *s, const char *filename);
-
-/** lws_jwk_rfc7638_fingerprint() - jwk to RFC7638 compliant fingerprint
- *
- * \param s: the JWK object to fingerprint
- * \param digest32: buffer to take 32-byte digest
- *
- * Returns 0 for OK or -1 for failure
- */
-LWS_VISIBLE int
-lws_jwk_rfc7638_fingerprint(struct lws_jwk *s, char *digest32);
-///@}
-
-
-/*! \defgroup jws JSON Web Signature
- * ## JSON Web Signature API
- *
- * Lws provides an API to check and create RFC7515 JSON Web Signatures
- *
- * SHA256/384/512 HMAC, and RSA 256/384/512 are supported.
- *
- * The API uses your TLS library crypto, but works exactly the same no matter
- * what you TLS backend is.
- */
-///@{
-
-LWS_VISIBLE LWS_EXTERN int
-lws_jws_confirm_sig(const char *in, size_t len, struct lws_jwk *jwk);
-
-/**
- * lws_jws_sign_from_b64() - add b64 sig to b64 hdr + payload
- *
- * \param b64_hdr: protected header encoded in b64, may be NULL
- * \param hdr_len: bytes in b64 coding of protected header
- * \param b64_pay: payload encoded in b64
- * \param pay_len: bytes in b64 coding of payload
- * \param b64_sig: buffer to write the b64 encoded signature into
- * \param sig_len: max bytes we can write at b64_sig
- * \param hash_type: one of LWS_GENHASH_TYPE_SHA[256|384|512]
- * \param jwk: the struct lws_jwk containing the signing key
- *
- * This adds a b64-coded JWS signature of the b64-encoded protected header
- * and b64-encoded payload, at \p b64_sig. The signature will be as large
- * as the N element of the RSA key when the RSA key is used, eg, 512 bytes for
- * a 4096-bit key, and then b64-encoding on top.
- *
- * In some special cases, there is only payload to sign and no header, in that
- * case \p b64_hdr may be NULL, and only the payload will be hashed before
- * signing.
- *
- * Returns the length of the encoded signature written to \p b64_sig, or -1.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_jws_sign_from_b64(const char *b64_hdr, size_t hdr_len, const char *b64_pay,
- size_t pay_len, char *b64_sig, size_t sig_len,
- enum lws_genhash_types hash_type, struct lws_jwk *jwk);
-
-/**
- * lws_jws_create_packet() - add b64 sig to b64 hdr + payload
- *
- * \param jwk: the struct lws_jwk containing the signing key
- * \param payload: unencoded payload JSON
- * \param len: length of unencoded payload JSON
- * \param nonce: Nonse string to include in protected header
- * \param out: buffer to take signed packet
- * \param out_len: size of \p out buffer
- *
- * This creates a "flattened" JWS packet from the jwk and the plaintext
- * payload, and signs it. The packet is written into \p out.
- *
- * This does the whole packet assembly and signing, calling through to
- * lws_jws_sign_from_b64() as part of the process.
- *
- * Returns the length written to \p out, or -1.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_jws_create_packet(struct lws_jwk *jwk, const char *payload, size_t len,
- const char *nonce, char *out, size_t out_len);
-
-/**
- * lws_jws_base64_enc() - encode input data into b64url data
- *
- * \param in: the incoming plaintext
- * \param in_len: the length of the incoming plaintext in bytes
- * \param out: the buffer to store the b64url encoded data to
- * \param out_max: the length of \p out in bytes
- *
- * Returns either -1 if problems, or the number of bytes written to \p out.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_jws_base64_enc(const char *in, size_t in_len, char *out, size_t out_max);
-///@}
-#endif
-
-/*! \defgroup extensions Extension related functions
- * ##Extension releated functions
- *
- * Ws defines optional extensions, lws provides the ability to implement these
- * in user code if so desired.
- *
- * We provide one extensions permessage-deflate.
- */
-///@{
-
-/*
- * NOTE: These public enums are part of the abi. If you want to add one,
- * add it at where specified so existing users are unaffected.
- */
-enum lws_extension_callback_reasons {
- LWS_EXT_CB_CONSTRUCT = 4,
- LWS_EXT_CB_CLIENT_CONSTRUCT = 5,
- LWS_EXT_CB_DESTROY = 8,
- LWS_EXT_CB_PACKET_TX_PRESEND = 12,
- LWS_EXT_CB_PAYLOAD_TX = 21,
- LWS_EXT_CB_PAYLOAD_RX = 22,
- LWS_EXT_CB_OPTION_DEFAULT = 23,
- LWS_EXT_CB_OPTION_SET = 24,
- LWS_EXT_CB_OPTION_CONFIRM = 25,
- LWS_EXT_CB_NAMED_OPTION_SET = 26,
-
- /****** add new things just above ---^ ******/
-};
-
-/** enum lws_ext_options_types */
-enum lws_ext_options_types {
- EXTARG_NONE, /**< does not take an argument */
- EXTARG_DEC, /**< requires a decimal argument */
- EXTARG_OPT_DEC /**< may have an optional decimal argument */
-
- /* Add new things just above here ---^
- * This is part of the ABI, don't needlessly break compatibility */
-};
-
-/** struct lws_ext_options - Option arguments to the extension. These are
- * used in the negotiation at ws upgrade time.
- * The helper function lws_ext_parse_options()
- * uses these to generate callbacks */
-struct lws_ext_options {
- const char *name; /**< Option name, eg, "server_no_context_takeover" */
- enum lws_ext_options_types type; /**< What kind of args the option can take */
-
- /* Add new things just above here ---^
- * This is part of the ABI, don't needlessly break compatibility */
-};
-
-/** struct lws_ext_option_arg */
-struct lws_ext_option_arg {
- const char *option_name; /**< may be NULL, option_index used then */
- int option_index; /**< argument ordinal to use if option_name missing */
- const char *start; /**< value */
- int len; /**< length of value */
-};
-
-/**
- * typedef lws_extension_callback_function() - Hooks to allow extensions to operate
- * \param context: Websockets context
- * \param ext: This extension
- * \param wsi: Opaque websocket instance pointer
- * \param reason: The reason for the call
- * \param user: Pointer to ptr to per-session user data allocated by library
- * \param in: Pointer used for some callback reasons
- * \param len: Length set for some callback reasons
- *
- * Each extension that is active on a particular connection receives
- * callbacks during the connection lifetime to allow the extension to
- * operate on websocket data and manage itself.
- *
- * Libwebsockets takes care of allocating and freeing "user" memory for
- * each active extension on each connection. That is what is pointed to
- * by the user parameter.
- *
- * LWS_EXT_CB_CONSTRUCT: called when the server has decided to
- * select this extension from the list provided by the client,
- * just before the server will send back the handshake accepting
- * the connection with this extension active. This gives the
- * extension a chance to initialize its connection context found
- * in user.
- *
- * LWS_EXT_CB_CLIENT_CONSTRUCT: same as LWS_EXT_CB_CONSTRUCT
- * but called when client is instantiating this extension. Some
- * extensions will work the same on client and server side and then
- * you can just merge handlers for both CONSTRUCTS.
- *
- * LWS_EXT_CB_DESTROY: called when the connection the extension was
- * being used on is about to be closed and deallocated. It's the
- * last chance for the extension to deallocate anything it has
- * allocated in the user data (pointed to by user) before the
- * user data is deleted. This same callback is used whether you
- * are in client or server instantiation context.
- *
- * LWS_EXT_CB_PACKET_TX_PRESEND: this works the same way as
- * LWS_EXT_CB_PACKET_RX_PREPARSE above, except it gives the
- * extension a chance to change websocket data just before it will
- * be sent out. Using the same lws_token pointer scheme in in,
- * the extension can change the buffer and the length to be
- * transmitted how it likes. Again if it wants to grow the
- * buffer safely, it should copy the data into its own buffer and
- * set the lws_tokens token pointer to it.
- *
- * LWS_EXT_CB_ARGS_VALIDATE:
- */
-typedef int
-lws_extension_callback_function(struct lws_context *context,
- const struct lws_extension *ext, struct lws *wsi,
- enum lws_extension_callback_reasons reason,
- void *user, void *in, size_t len);
-
-/** struct lws_extension - An extension we support */
-struct lws_extension {
- const char *name; /**< Formal extension name, eg, "permessage-deflate" */
- lws_extension_callback_function *callback; /**< Service callback */
- const char *client_offer; /**< String containing exts and options client offers */
-
- /* Add new things just above here ---^
- * This is part of the ABI, don't needlessly break compatibility */
-};
-
-/**
- * lws_set_extension_option(): set extension option if possible
- *
- * \param wsi: websocket connection
- * \param ext_name: name of ext, like "permessage-deflate"
- * \param opt_name: name of option, like "rx_buf_size"
- * \param opt_val: value to set option to
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_set_extension_option(struct lws *wsi, const char *ext_name,
- const char *opt_name, const char *opt_val);
-
-/**
- * lws_ext_parse_options() - deal with parsing negotiated extension options
- *
- * \param ext: related extension struct
- * \param wsi: websocket connection
- * \param ext_user: per-connection extension private data
- * \param opts: list of supported options
- * \param o: option string to parse
- * \param len: length
- */
-LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_ext_parse_options(const struct lws_extension *ext, struct lws *wsi,
- void *ext_user, const struct lws_ext_options *opts,
- const char *o, int len);
-
-/** lws_extension_callback_pm_deflate() - extension for RFC7692
- *
- * \param context: lws context
- * \param ext: related lws_extension struct
- * \param wsi: websocket connection
- * \param reason: incoming callback reason
- * \param user: per-connection extension private data
- * \param in: pointer parameter
- * \param len: length parameter
- *
- * Built-in callback implementing RFC7692 permessage-deflate
- */
-LWS_EXTERN
-int lws_extension_callback_pm_deflate(
- struct lws_context *context, const struct lws_extension *ext,
- struct lws *wsi, enum lws_extension_callback_reasons reason,
- void *user, void *in, size_t len);
-
-/*
- * The internal exts are part of the public abi
- * If we add more extensions, publish the callback here ------v
- */
-///@}
-
-/*! \defgroup Protocols-and-Plugins Protocols and Plugins
- * \ingroup lwsapi
- *
- * ##Protocol and protocol plugin -related apis
- *
- * Protocols bind ws protocol names to a custom callback specific to that
- * protocol implementaion.
- *
- * A list of protocols can be passed in at context creation time, but it is
- * also legal to leave that NULL and add the protocols and their callback code
- * using plugins.
- *
- * Plugins are much preferable compared to cut and pasting code into an
- * application each time, since they can be used standalone.
- */
-///@{
-/** struct lws_protocols - List of protocols and handlers client or server
- * supports. */
-
-struct lws_protocols {
- const char *name;
- /**< Protocol name that must match the one given in the client
- * Javascript new WebSocket(url, 'protocol') name. */
- lws_callback_function *callback;
- /**< The service callback used for this protocol. It allows the
- * service action for an entire protocol to be encapsulated in
- * the protocol-specific callback */
- size_t per_session_data_size;
- /**< Each new connection using this protocol gets
- * this much memory allocated on connection establishment and
- * freed on connection takedown. A pointer to this per-connection
- * allocation is passed into the callback in the 'user' parameter */
- size_t rx_buffer_size;
- /**< lws allocates this much space for rx data and informs callback
- * when something came. Due to rx flow control, the callback may not
- * be able to consume it all without having to return to the event
- * loop. That is supported in lws.
- *
- * If .tx_packet_size is 0, this also controls how much may be sent at
- * once for backwards compatibility.
- */
- unsigned int id;
- /**< ignored by lws, but useful to contain user information bound
- * to the selected protocol. For example if this protocol was
- * called "myprotocol-v2", you might set id to 2, and the user
- * code that acts differently according to the version can do so by
- * switch (wsi->protocol->id), user code might use some bits as
- * capability flags based on selected protocol version, etc. */
- void *user; /**< ignored by lws, but user code can pass a pointer
- here it can later access from the protocol callback */
- size_t tx_packet_size;
- /**< 0 indicates restrict send() size to .rx_buffer_size for backwards-
- * compatibility.
- * If greater than zero, a single send() is restricted to this amount
- * and any remainder is buffered by lws and sent afterwards also in
- * these size chunks. Since that is expensive, it's preferable
- * to restrict one fragment you are trying to send to match this
- * size.
- */
-
- /* Add new things just above here ---^
- * This is part of the ABI, don't needlessly break compatibility */
-};
-
-/**
- * lws_vhost_name_to_protocol() - get vhost's protocol object from its name
- *
- * \param vh: vhost to search
- * \param name: protocol name
- *
- * Returns NULL or a pointer to the vhost's protocol of the requested name
- */
-LWS_VISIBLE LWS_EXTERN const struct lws_protocols *
-lws_vhost_name_to_protocol(struct lws_vhost *vh, const char *name);
-
-/**
- * lws_get_protocol() - Returns a protocol pointer from a websocket
- * connection.
- * \param wsi: pointer to struct websocket you want to know the protocol of
- *
- *
- * Some apis can act on all live connections of a given protocol,
- * this is how you can get a pointer to the active protocol if needed.
- */
-LWS_VISIBLE LWS_EXTERN const struct lws_protocols *
-lws_get_protocol(struct lws *wsi);
-
-/** lws_protocol_get() - deprecated: use lws_get_protocol */
-LWS_VISIBLE LWS_EXTERN const struct lws_protocols *
-lws_protocol_get(struct lws *wsi) LWS_WARN_DEPRECATED;
-
-/**
- * lws_protocol_vh_priv_zalloc() - Allocate and zero down a protocol's per-vhost
- * storage
- * \param vhost: vhost the instance is related to
- * \param prot: protocol the instance is related to
- * \param size: bytes to allocate
- *
- * Protocols often find it useful to allocate a per-vhost struct, this is a
- * helper to be called in the per-vhost init LWS_CALLBACK_PROTOCOL_INIT
- */
-LWS_VISIBLE LWS_EXTERN void *
-lws_protocol_vh_priv_zalloc(struct lws_vhost *vhost, const struct lws_protocols *prot,
- int size);
-
-/**
- * lws_protocol_vh_priv_get() - retreive a protocol's per-vhost storage
- *
- * \param vhost: vhost the instance is related to
- * \param prot: protocol the instance is related to
- *
- * Recover a pointer to the allocated per-vhost storage for the protocol created
- * by lws_protocol_vh_priv_zalloc() earlier
- */
-LWS_VISIBLE LWS_EXTERN void *
-lws_protocol_vh_priv_get(struct lws_vhost *vhost, const struct lws_protocols *prot);
-
-/**
- * lws_adjust_protocol_psds - change a vhost protocol's per session data size
- *
- * \param wsi: a connection with the protocol to change
- * \param new_size: the new size of the per session data size for the protocol
- *
- * Returns user_space for the wsi, after allocating
- *
- * This should not be used except to initalize a vhost protocol's per session
- * data size one time, before any connections are accepted.
- *
- * Sometimes the protocol wraps another protocol and needs to discover and set
- * its per session data size at runtime.
- */
-LWS_VISIBLE LWS_EXTERN void *
-lws_adjust_protocol_psds(struct lws *wsi, size_t new_size);
-
-/**
- * lws_finalize_startup() - drop initial process privileges
- *
- * \param context: lws context
- *
- * This is called after the end of the vhost protocol initializations, but
- * you may choose to call it earlier
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_finalize_startup(struct lws_context *context);
-
-/**
- * lws_pvo_search() - helper to find a named pvo in a linked-list
- *
- * \param pvo: the first pvo in the linked-list
- * \param name: the name of the pvo to return if found
- *
- * Returns NULL, or a pointer to the name pvo in the linked-list
- */
-LWS_VISIBLE LWS_EXTERN const struct lws_protocol_vhost_options *
-lws_pvo_search(const struct lws_protocol_vhost_options *pvo, const char *name);
-
-LWS_VISIBLE LWS_EXTERN int
-lws_protocol_init(struct lws_context *context);
-
-#ifdef LWS_WITH_PLUGINS
-
-/* PLUGINS implies LIBUV */
-
-#define LWS_PLUGIN_API_MAGIC 180
-
-/** struct lws_plugin_capability - how a plugin introduces itself to lws */
-struct lws_plugin_capability {
- unsigned int api_magic; /**< caller fills this in, plugin fills rest */
- const struct lws_protocols *protocols; /**< array of supported protocols provided by plugin */
- int count_protocols; /**< how many protocols */
- const struct lws_extension *extensions; /**< array of extensions provided by plugin */
- int count_extensions; /**< how many extensions */
-};
-
-typedef int (*lws_plugin_init_func)(struct lws_context *,
- struct lws_plugin_capability *);
-typedef int (*lws_plugin_destroy_func)(struct lws_context *);
-
-/** struct lws_plugin */
-struct lws_plugin {
- struct lws_plugin *list; /**< linked list */
-#if (UV_VERSION_MAJOR > 0)
- uv_lib_t lib; /**< shared library pointer */
-#else
- void *l; /**< so we can compile on ancient libuv */
-#endif
- char name[64]; /**< name of the plugin */
- struct lws_plugin_capability caps; /**< plugin capabilities */
-};
-
-#endif
-
-///@}
-
-
-/*! \defgroup generic-sessions plugin: generic-sessions
- * \ingroup Protocols-and-Plugins
- *
- * ##Plugin Generic-sessions related
- *
- * generic-sessions plugin provides a reusable, generic session and login /
- * register / forgot password framework including email verification.
- */
-///@{
-
-#define LWSGS_EMAIL_CONTENT_SIZE 16384
-/**< Maximum size of email we might send */
-
-/* SHA-1 binary and hexified versions */
-/** typedef struct lwsgw_hash_bin */
-typedef struct { unsigned char bin[20]; /**< binary representation of hash */} lwsgw_hash_bin;
-/** typedef struct lwsgw_hash */
-typedef struct { char id[41]; /**< ascii hex representation of hash */ } lwsgw_hash;
-
-/** enum lwsgs_auth_bits */
-enum lwsgs_auth_bits {
- LWSGS_AUTH_LOGGED_IN = 1, /**< user is logged in as somebody */
- LWSGS_AUTH_ADMIN = 2, /**< logged in as the admin user */
- LWSGS_AUTH_VERIFIED = 4, /**< user has verified his email */
- LWSGS_AUTH_FORGOT_FLOW = 8, /**< he just completed "forgot password" flow */
-};
-
-/** struct lws_session_info - information about user session status */
-struct lws_session_info {
- char username[32]; /**< username logged in as, or empty string */
- char email[100]; /**< email address associated with login, or empty string */
- char ip[72]; /**< ip address session was started from */
- unsigned int mask; /**< access rights mask associated with session
- * see enum lwsgs_auth_bits */
- char session[42]; /**< session id string, usable as opaque uid when not logged in */
-};
-
-/** enum lws_gs_event */
-enum lws_gs_event {
- LWSGSE_CREATED, /**< a new user was created */
- LWSGSE_DELETED /**< an existing user was deleted */
-};
-
-/** struct lws_gs_event_args */
-struct lws_gs_event_args {
- enum lws_gs_event event; /**< which event happened */
- const char *username; /**< which username the event happened to */
- const char *email; /**< the email address of that user */
-};
-
-///@}
-
-
-/*! \defgroup context-and-vhost context and vhost related functions
- * ##Context and Vhost releated functions
- * \ingroup lwsapi
- *
- *
- * LWS requires that there is one context, in which you may define multiple
- * vhosts. Each vhost is a virtual host, with either its own listen port
- * or sharing an existing one. Each vhost has its own SSL context that can
- * be set up individually or left disabled.
- *
- * If you don't care about multiple "site" support, you can ignore it and
- * lws will create a single default vhost at context creation time.
- */
-///@{
-
-/*
- * NOTE: These public enums are part of the abi. If you want to add one,
- * add it at where specified so existing users are unaffected.
- */
-
-/** enum lws_context_options - context and vhost options */
-enum lws_context_options {
- LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT = (1 << 1) |
- (1 << 12),
- /**< (VH) Don't allow the connection unless the client has a
- * client cert that we recognize; provides
- * LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT */
- LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME = (1 << 2),
- /**< (CTX) Don't try to get the server's hostname */
- LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT = (1 << 3) |
- (1 << 12),
- /**< (VH) Allow non-SSL (plaintext) connections on the same
- * port as SSL is listening... undermines the security of SSL;
- * provides LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT */
- LWS_SERVER_OPTION_LIBEV = (1 << 4),
- /**< (CTX) Use libev event loop */
- LWS_SERVER_OPTION_DISABLE_IPV6 = (1 << 5),
- /**< (VH) Disable IPV6 support */
- LWS_SERVER_OPTION_DISABLE_OS_CA_CERTS = (1 << 6),
- /**< (VH) Don't load OS CA certs, you will need to load your
- * own CA cert(s) */
- LWS_SERVER_OPTION_PEER_CERT_NOT_REQUIRED = (1 << 7),
- /**< (VH) Accept connections with no valid Cert (eg, selfsigned) */
- LWS_SERVER_OPTION_VALIDATE_UTF8 = (1 << 8),
- /**< (VH) Check UT-8 correctness */
- LWS_SERVER_OPTION_SSL_ECDH = (1 << 9) |
- (1 << 12),
- /**< (VH) initialize ECDH ciphers */
- LWS_SERVER_OPTION_LIBUV = (1 << 10),
- /**< (CTX) Use libuv event loop */
- LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS = (1 << 11) |
- (1 << 12),
- /**< (VH) Use http redirect to force http to https
- * (deprecated: use mount redirection) */
- LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT = (1 << 12),
- /**< (CTX) Initialize the SSL library at all */
- LWS_SERVER_OPTION_EXPLICIT_VHOSTS = (1 << 13),
- /**< (CTX) Only create the context when calling context
- * create api, implies user code will create its own vhosts */
- LWS_SERVER_OPTION_UNIX_SOCK = (1 << 14),
- /**< (VH) Use Unix socket */
- LWS_SERVER_OPTION_STS = (1 << 15),
- /**< (VH) Send Strict Transport Security header, making
- * clients subsequently go to https even if user asked for http */
- LWS_SERVER_OPTION_IPV6_V6ONLY_MODIFY = (1 << 16),
- /**< (VH) Enable LWS_SERVER_OPTION_IPV6_V6ONLY_VALUE to take effect */
- LWS_SERVER_OPTION_IPV6_V6ONLY_VALUE = (1 << 17),
- /**< (VH) if set, only ipv6 allowed on the vhost */
- LWS_SERVER_OPTION_UV_NO_SIGSEGV_SIGFPE_SPIN = (1 << 18),
- /**< (CTX) Libuv only: Do not spin on SIGSEGV / SIGFPE. A segfault
- * normally makes the lib spin so you can attach a debugger to it
- * even if it happened without a debugger in place. You can disable
- * that by giving this option.
- */
- LWS_SERVER_OPTION_JUST_USE_RAW_ORIGIN = (1 << 19),
- /**< For backwards-compatibility reasons, by default
- * lws prepends "http://" to the origin you give in the client
- * connection info struct. If you give this flag when you create
- * the context, only the string you give in the client connect
- * info for .origin (if any) will be used directly.
- */
- LWS_SERVER_OPTION_FALLBACK_TO_RAW = (1 << 20),
- /**< (VH) if invalid http is coming in the first line, */
- LWS_SERVER_OPTION_LIBEVENT = (1 << 21),
- /**< (CTX) Use libevent event loop */
- LWS_SERVER_OPTION_ONLY_RAW = (1 << 22),
- /**< (VH) All connections to this vhost / port are RAW as soon as
- * the connection is accepted, no HTTP is going to be coming.
- */
- LWS_SERVER_OPTION_ALLOW_LISTEN_SHARE = (1 << 23),
- /**< (VH) Set to allow multiple listen sockets on one interface +
- * address + port. The default is to strictly allow only one
- * listen socket at a time. This is automatically selected if you
- * have multiple service threads.
- */
- LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX = (1 << 24),
- /**< (VH) Force setting up the vhost SSL_CTX, even though the user
- * code doesn't explicitly provide a cert in the info struct. It
- * implies the user code is going to provide a cert at the
- * LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS callback, which
- * provides the vhost SSL_CTX * in the user parameter.
- */
- LWS_SERVER_OPTION_SKIP_PROTOCOL_INIT = (1 << 25),
- /**< (VH) You probably don't want this. It forces this vhost to not
- * call LWS_CALLBACK_PROTOCOL_INIT on its protocols. It's used in the
- * special case of a temporary vhost bound to a single protocol.
- */
- LWS_SERVER_OPTION_IGNORE_MISSING_CERT = (1 << 26),
- /**< (VH) Don't fail if the vhost TLS cert or key are missing, just
- * continue. The vhost won't be able to serve anything, but if for
- * example the ACME plugin was configured to fetch a cert, this lets
- * you bootstrap your vhost from having no cert to start with.
- */
-
- /****** add new things just above ---^ ******/
-};
-
-#define lws_check_opt(c, f) (((c) & (f)) == (f))
-
-struct lws_plat_file_ops;
-
-/** struct lws_context_creation_info - parameters to create context and /or vhost with
- *
- * This is also used to create vhosts.... if LWS_SERVER_OPTION_EXPLICIT_VHOSTS
- * is not given, then for backwards compatibility one vhost is created at
- * context-creation time using the info from this struct.
- *
- * If LWS_SERVER_OPTION_EXPLICIT_VHOSTS is given, then no vhosts are created
- * at the same time as the context, they are expected to be created afterwards.
- */
-struct lws_context_creation_info {
- int port;
- /**< VHOST: Port to listen on. Use CONTEXT_PORT_NO_LISTEN to suppress
- * listening for a client. Use CONTEXT_PORT_NO_LISTEN_SERVER if you are
- * writing a server but you are using \ref sock-adopt instead of the
- * built-in listener.
- *
- * You can also set port to 0, in which case the kernel will pick
- * a random port that is not already in use. You can find out what
- * port the vhost is listening on using lws_get_vhost_listen_port() */
- const char *iface;
- /**< VHOST: NULL to bind the listen socket to all interfaces, or the
- * interface name, eg, "eth2"
- * If options specifies LWS_SERVER_OPTION_UNIX_SOCK, this member is
- * the pathname of a UNIX domain socket. you can use the UNIX domain
- * sockets in abstract namespace, by prepending an at symbol to the
- * socket name. */
- const struct lws_protocols *protocols;
- /**< VHOST: Array of structures listing supported protocols and a protocol-
- * specific callback for each one. The list is ended with an
- * entry that has a NULL callback pointer. */
- const struct lws_extension *extensions;
- /**< VHOST: NULL or array of lws_extension structs listing the
- * extensions this context supports. */
- const struct lws_token_limits *token_limits;
- /**< CONTEXT: NULL or struct lws_token_limits pointer which is initialized
- * with a token length limit for each possible WSI_TOKEN_ */
- const char *ssl_private_key_password;
- /**< VHOST: NULL or the passphrase needed for the private key. (For
- * backwards compatibility, this can also be used to pass the client
- * cert passphrase when setting up a vhost client SSL context, but it is
- * preferred to use .client_ssl_private_key_password for that.) */
- const char *ssl_cert_filepath;
- /**< VHOST: If libwebsockets was compiled to use ssl, and you want
- * to listen using SSL, set to the filepath to fetch the
- * server cert from, otherwise NULL for unencrypted. (For backwards
- * compatibility, this can also be used to pass the client certificate
- * when setting up a vhost client SSL context, but it is preferred to
- * use .client_ssl_cert_filepath for that.) */
- const char *ssl_private_key_filepath;
- /**< VHOST: filepath to private key if wanting SSL mode;
- * if this is set to NULL but ssl_cert_filepath is set, the
- * OPENSSL_CONTEXT_REQUIRES_PRIVATE_KEY callback is called
- * to allow setting of the private key directly via openSSL
- * library calls. (For backwards compatibility, this can also be used
- * to pass the client cert private key filepath when setting up a
- * vhost client SSL context, but it is preferred to use
- * .client_ssl_private_key_filepath for that.) */
- const char *ssl_ca_filepath;
- /**< VHOST: CA certificate filepath or NULL. (For backwards
- * compatibility, this can also be used to pass the client CA
- * filepath when setting up a vhost client SSL context,
- * but it is preferred to use .client_ssl_ca_filepath for that.) */
- const char *ssl_cipher_list;
- /**< VHOST: List of valid ciphers to use (eg,
- * "RC4-MD5:RC4-SHA:AES128-SHA:AES256-SHA:HIGH:!DSS:!aNULL"
- * or you can leave it as NULL to get "DEFAULT" (For backwards
- * compatibility, this can also be used to pass the client cipher
- * list when setting up a vhost client SSL context,
- * but it is preferred to use .client_ssl_cipher_list for that.)*/
- const char *http_proxy_address;
- /**< VHOST: If non-NULL, attempts to proxy via the given address.
- * If proxy auth is required, use format "username:password\@server:port" */
- unsigned int http_proxy_port;
- /**< VHOST: If http_proxy_address was non-NULL, uses this port */
- int gid;
- /**< CONTEXT: group id to change to after setting listen socket, or -1. */
- int uid;
- /**< CONTEXT: user id to change to after setting listen socket, or -1. */
- unsigned int options;
- /**< VHOST + CONTEXT: 0, or LWS_SERVER_OPTION_... bitfields */
- void *user;
- /**< VHOST + CONTEXT: optional user pointer that will be associated
- * with the context when creating the context (and can be retrieved by
- * lws_context_user(context), or with the vhost when creating the vhost
- * (and can be retrieved by lws_vhost_user(vhost)). You will need to
- * use LWS_SERVER_OPTION_EXPLICIT_VHOSTS and create the vhost separately
- * if you care about giving the context and vhost different user pointer
- * values.
- */
- int ka_time;
- /**< CONTEXT: 0 for no TCP keepalive, otherwise apply this keepalive
- * timeout to all libwebsocket sockets, client or server */
- int ka_probes;
- /**< CONTEXT: if ka_time was nonzero, after the timeout expires how many
- * times to try to get a response from the peer before giving up
- * and killing the connection */
- int ka_interval;
- /**< CONTEXT: if ka_time was nonzero, how long to wait before each ka_probes
- * attempt */
-#if defined(LWS_WITH_TLS) && !defined(LWS_WITH_MBEDTLS)
- SSL_CTX *provided_client_ssl_ctx;
- /**< CONTEXT: If non-null, swap out libwebsockets ssl
- * implementation for the one provided by provided_ssl_ctx.
- * Libwebsockets no longer is responsible for freeing the context
- * if this option is selected. */
-#else /* maintain structure layout either way */
- void *provided_client_ssl_ctx; /**< dummy if ssl disabled */
-#endif
-
- short max_http_header_data;
- /**< CONTEXT: The max amount of header payload that can be handled
- * in an http request (unrecognized header payload is dropped) */
- short max_http_header_pool;
- /**< CONTEXT: The max number of connections with http headers that
- * can be processed simultaneously (the corresponding memory is
- * allocated and deallocated dynamically as needed). If the pool is
- * fully busy new incoming connections must wait for accept until one
- * becomes free. 0 = allow as many ah as number of availble fds for
- * the process */
-
- unsigned int count_threads;
- /**< CONTEXT: how many contexts to create in an array, 0 = 1 */
- unsigned int fd_limit_per_thread;
- /**< CONTEXT: nonzero means restrict each service thread to this
- * many fds, 0 means the default which is divide the process fd
- * limit by the number of threads. */
- unsigned int timeout_secs;
- /**< VHOST: various processes involving network roundtrips in the
- * library are protected from hanging forever by timeouts. If
- * nonzero, this member lets you set the timeout used in seconds.
- * Otherwise a default timeout is used. */
- const char *ecdh_curve;
- /**< VHOST: if NULL, defaults to initializing server with "prime256v1" */
- const char *vhost_name;
- /**< VHOST: name of vhost, must match external DNS name used to
- * access the site, like "warmcat.com" as it's used to match
- * Host: header and / or SNI name for SSL. */
- const char * const *plugin_dirs;
- /**< CONTEXT: NULL, or NULL-terminated array of directories to
- * scan for lws protocol plugins at context creation time */
- const struct lws_protocol_vhost_options *pvo;
- /**< VHOST: pointer to optional linked list of per-vhost
- * options made accessible to protocols */
- int keepalive_timeout;
- /**< VHOST: (default = 0 = 5s) seconds to allow remote
- * client to hold on to an idle HTTP/1.1 connection */
- const char *log_filepath;
- /**< VHOST: filepath to append logs to... this is opened before
- * any dropping of initial privileges */
- const struct lws_http_mount *mounts;
- /**< VHOST: optional linked list of mounts for this vhost */
- const char *server_string;
- /**< CONTEXT: string used in HTTP headers to identify server
- * software, if NULL, "libwebsockets". */
- unsigned int pt_serv_buf_size;
- /**< CONTEXT: 0 = default of 4096. This buffer is used by
- * various service related features including file serving, it
- * defines the max chunk of file that can be sent at once.
- * At the risk of lws having to buffer failed large sends, it
- * can be increased to, eg, 128KiB to improve throughput. */
- unsigned int max_http_header_data2;
- /**< CONTEXT: if max_http_header_data is 0 and this
- * is nonzero, this will be used in place of the default. It's
- * like this for compatibility with the original short version,
- * this is unsigned int length. */
- long ssl_options_set;
- /**< VHOST: Any bits set here will be set as SSL options */
- long ssl_options_clear;
- /**< VHOST: Any bits set here will be cleared as SSL options */
- unsigned short ws_ping_pong_interval;
- /**< CONTEXT: 0 for none, else interval in seconds between sending
- * PINGs on idle websocket connections. When the PING is sent,
- * the PONG must come within the normal timeout_secs timeout period
- * or the connection will be dropped.
- * Any RX or TX traffic on the connection restarts the interval timer,
- * so a connection which always sends or receives something at intervals
- * less than the interval given here will never send PINGs / expect
- * PONGs. Conversely as soon as the ws connection is established, an
- * idle connection will do the PING / PONG roundtrip as soon as
- * ws_ping_pong_interval seconds has passed without traffic
- */
- const struct lws_protocol_vhost_options *headers;
- /**< VHOST: pointer to optional linked list of per-vhost
- * canned headers that are added to server responses */
-
- const struct lws_protocol_vhost_options *reject_service_keywords;
- /**< CONTEXT: Optional list of keywords and rejection codes + text.
- *
- * The keywords are checked for existing in the user agent string.
- *
- * Eg, "badrobot" "404 Not Found"
- */
- void *external_baggage_free_on_destroy;
- /**< CONTEXT: NULL, or pointer to something externally malloc'd, that
- * should be freed when the context is destroyed. This allows you to
- * automatically sync the freeing action to the context destruction
- * action, so there is no need for an external free() if the context
- * succeeded to create.
- */
-
- const char *client_ssl_private_key_password;
- /**< VHOST: Client SSL context init: NULL or the passphrase needed
- * for the private key */
- const char *client_ssl_cert_filepath;
- /**< VHOST: Client SSL context init:T he certificate the client
- * should present to the peer on connection */
- const char *client_ssl_private_key_filepath;
- /**< VHOST: Client SSL context init: filepath to client private key
- * if this is set to NULL but client_ssl_cert_filepath is set, you
- * can handle the LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS
- * callback of protocols[0] to allow setting of the private key directly
- * via openSSL library calls */
- const char *client_ssl_ca_filepath;
- /**< VHOST: Client SSL context init: CA certificate filepath or NULL */
- const char *client_ssl_cipher_list;
- /**< VHOST: Client SSL context init: List of valid ciphers to use (eg,
- * "RC4-MD5:RC4-SHA:AES128-SHA:AES256-SHA:HIGH:!DSS:!aNULL"
- * or you can leave it as NULL to get "DEFAULT" */
-
- const struct lws_plat_file_ops *fops;
- /**< CONTEXT: NULL, or pointer to an array of fops structs, terminated
- * by a sentinel with NULL .open.
- *
- * If NULL, lws provides just the platform file operations struct for
- * backwards compatibility.
- */
- int simultaneous_ssl_restriction;
- /**< CONTEXT: 0 (no limit) or limit of simultaneous SSL sessions possible.*/
- const char *socks_proxy_address;
- /**< VHOST: If non-NULL, attempts to proxy via the given address.
- * If proxy auth is required, use format "username:password\@server:port" */
- unsigned int socks_proxy_port;
- /**< VHOST: If socks_proxy_address was non-NULL, uses this port */
-#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
- cap_value_t caps[4];
- /**< CONTEXT: array holding Linux capabilities you want to
- * continue to be available to the server after it transitions
- * to a noprivileged user. Usually none are needed but for, eg,
- * .bind_iface, CAP_NET_RAW is required. This gives you a way
- * to still have the capability but drop root.
- */
- char count_caps;
- /**< CONTEXT: count of Linux capabilities in .caps[]. 0 means
- * no capabilities will be inherited from root (the default) */
-#endif
- int bind_iface;
- /**< VHOST: nonzero to strictly bind sockets to the interface name in
- * .iface (eg, "eth2"), using SO_BIND_TO_DEVICE.
- *
- * Requires SO_BINDTODEVICE support from your OS and CAP_NET_RAW
- * capability.
- *
- * Notice that common things like access network interface IP from
- * your local machine use your lo / loopback interface and will be
- * disallowed by this.
- */
- int ssl_info_event_mask;
- /**< VHOST: mask of ssl events to be reported on LWS_CALLBACK_SSL_INFO
- * callback for connections on this vhost. The mask values are of
- * the form SSL_CB_ALERT, defined in openssl/ssl.h. The default of
- * 0 means no info events will be reported.
- */
- unsigned int timeout_secs_ah_idle;
- /**< VHOST: seconds to allow a client to hold an ah without using it.
- * 0 defaults to 10s. */
- unsigned short ip_limit_ah;
- /**< CONTEXT: max number of ah a single IP may use simultaneously
- * 0 is no limit. This is a soft limit: if the limit is
- * reached, connections from that IP will wait in the ah
- * waiting list and not be able to acquire an ah until
- * a connection belonging to the IP relinquishes one it
- * already has.
- */
- unsigned short ip_limit_wsi;
- /**< CONTEXT: max number of wsi a single IP may use simultaneously.
- * 0 is no limit. This is a hard limit, connections from
- * the same IP will simply be dropped once it acquires the
- * amount of simultaneous wsi / accepted connections
- * given here.
- */
- uint32_t http2_settings[7];
- /**< VHOST: if http2_settings[0] is nonzero, the values given in
- * http2_settings[1]..[6] are used instead of the lws
- * platform default values.
- * Just leave all at 0 if you don't care.
- */
- const char *error_document_404;
- /**< VHOST: If non-NULL, when asked to serve a non-existent file,
- * lws attempts to server this url path instead. Eg,
- * "/404.html" */
- const char *alpn;
- /**< CONTEXT: If non-NULL, default list of advertised alpn, comma-
- * separated
- *
- * VHOST: If non-NULL, per-vhost list of advertised alpn, comma-
- * separated
- */
- void **foreign_loops;
- /**< CONTEXT: This is ignored if the context is not being started with
- * an event loop, ie, .options has a flag like
- * LWS_SERVER_OPTION_LIBUV.
- *
- * NULL indicates lws should start its own even loop for
- * each service thread, and deal with closing the loops
- * when the context is destroyed.
- *
- * Non-NULL means it points to an array of external
- * ("foreign") event loops that are to be used in turn for
- * each service thread. In the default case of 1 service
- * thread, it can just point to one foreign event loop.
- */
- void (*signal_cb)(void *event_lib_handle, int signum);
- /**< CONTEXT: NULL: default signal handling. Otherwise this receives
- * the signal handler callback. event_lib_handle is the
- * native event library signal handle, eg uv_signal_t *
- * for libuv.
- */
-
- /* Add new things just above here ---^
- * This is part of the ABI, don't needlessly break compatibility
- *
- * The below is to ensure later library versions with new
- * members added above will see 0 (default) even if the app
- * was not built against the newer headers.
- */
- struct lws_context **pcontext;
- /**< CONTEXT: if non-NULL, at the end of context destroy processing,
- * the pointer pointed to by pcontext is written with NULL. You can
- * use this to let foreign event loops know that lws context destruction
- * is fully completed.
- */
-
- void *_unused[4]; /**< dummy */
-};
-
-/**
- * lws_create_context() - Create the websocket handler
- * \param info: pointer to struct with parameters
- *
- * This function creates the listening socket (if serving) and takes care
- * of all initialization in one step.
- *
- * If option LWS_SERVER_OPTION_EXPLICIT_VHOSTS is given, no vhost is
- * created; you're expected to create your own vhosts afterwards using
- * lws_create_vhost(). Otherwise a vhost named "default" is also created
- * using the information in the vhost-related members, for compatibility.
- *
- * After initialization, it returns a struct lws_context * that
- * represents this server. After calling, user code needs to take care
- * of calling lws_service() with the context pointer to get the
- * server's sockets serviced. This must be done in the same process
- * context as the initialization call.
- *
- * The protocol callback functions are called for a handful of events
- * including http requests coming in, websocket connections becoming
- * established, and data arriving; it's also called periodically to allow
- * async transmission.
- *
- * HTTP requests are sent always to the FIRST protocol in protocol, since
- * at that time websocket protocol has not been negotiated. Other
- * protocols after the first one never see any HTTP callback activity.
- *
- * The server created is a simple http server by default; part of the
- * websocket standard is upgrading this http connection to a websocket one.
- *
- * This allows the same server to provide files like scripts and favicon /
- * images or whatever over http and dynamic data over websockets all in
- * one place; they're all handled in the user callback.
- */
-LWS_VISIBLE LWS_EXTERN struct lws_context *
-lws_create_context(const struct lws_context_creation_info *info);
-
-
-/**
- * lws_context_destroy() - Destroy the websocket context
- * \param context: Websocket context
- *
- * This function closes any active connections and then frees the
- * context. After calling this, any further use of the context is
- * undefined.
- */
-LWS_VISIBLE LWS_EXTERN void
-lws_context_destroy(struct lws_context *context);
-
-typedef int (*lws_reload_func)(void);
-
-/**
- * lws_context_deprecate() - Deprecate the websocket context
- *
- * \param context: Websocket context
- * \param cb: Callback notified when old context listen sockets are closed
- *
- * This function is used on an existing context before superceding it
- * with a new context.
- *
- * It closes any listen sockets in the context, so new connections are
- * not possible.
- *
- * And it marks the context to be deleted when the number of active
- * connections into it falls to zero.
- *
- * Otherwise if you attach the deprecated context to the replacement
- * context when it has been created using lws_context_attach_deprecated()
- * both any deprecated and the new context will service their connections.
- *
- * This is aimed at allowing seamless configuration reloads.
- *
- * The callback cb will be called after the listen sockets are actually
- * closed and may be reopened. In the callback the new context should be
- * configured and created. (With libuv, socket close happens async after
- * more loop events).
- */
-LWS_VISIBLE LWS_EXTERN void
-lws_context_deprecate(struct lws_context *context, lws_reload_func cb);
-
-LWS_VISIBLE LWS_EXTERN int
-lws_context_is_deprecated(struct lws_context *context);
-
-/**
- * lws_set_proxy() - Setups proxy to lws_context.
- * \param vhost: pointer to struct lws_vhost you want set proxy for
- * \param proxy: pointer to c string containing proxy in format address:port
- *
- * Returns 0 if proxy string was parsed and proxy was setup.
- * Returns -1 if proxy is NULL or has incorrect format.
- *
- * This is only required if your OS does not provide the http_proxy
- * environment variable (eg, OSX)
- *
- * IMPORTANT! You should call this function right after creation of the
- * lws_context and before call to connect. If you call this
- * function after connect behavior is undefined.
- * This function will override proxy settings made on lws_context
- * creation with genenv() call.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_set_proxy(struct lws_vhost *vhost, const char *proxy);
-
-/**
- * lws_set_socks() - Setup socks to lws_context.
- * \param vhost: pointer to struct lws_vhost you want set socks for
- * \param socks: pointer to c string containing socks in format address:port
- *
- * Returns 0 if socks string was parsed and socks was setup.
- * Returns -1 if socks is NULL or has incorrect format.
- *
- * This is only required if your OS does not provide the socks_proxy
- * environment variable (eg, OSX)
- *
- * IMPORTANT! You should call this function right after creation of the
- * lws_context and before call to connect. If you call this
- * function after connect behavior is undefined.
- * This function will override proxy settings made on lws_context
- * creation with genenv() call.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_set_socks(struct lws_vhost *vhost, const char *socks);
-
-struct lws_vhost;
-
-/**
- * lws_create_vhost() - Create a vhost (virtual server context)
- * \param context: pointer to result of lws_create_context()
- * \param info: pointer to struct with parameters
- *
- * This function creates a virtual server (vhost) using the vhost-related
- * members of the info struct. You can create many vhosts inside one context
- * if you created the context with the option LWS_SERVER_OPTION_EXPLICIT_VHOSTS
- */
-LWS_VISIBLE LWS_EXTERN struct lws_vhost *
-lws_create_vhost(struct lws_context *context,
- const struct lws_context_creation_info *info);
-
-/**
- * lws_vhost_destroy() - Destroy a vhost (virtual server context)
- *
- * \param vh: pointer to result of lws_create_vhost()
- *
- * This function destroys a vhost. Normally, if you just want to exit,
- * then lws_destroy_context() will take care of everything. If you want
- * to destroy an individual vhost and all connections and allocations, you
- * can do it with this.
- *
- * If the vhost has a listen sockets shared by other vhosts, it will be given
- * to one of the vhosts sharing it rather than closed.
- */
-LWS_VISIBLE LWS_EXTERN void
-lws_vhost_destroy(struct lws_vhost *vh);
-
-/**
- * lwsws_get_config_globals() - Parse a JSON server config file
- * \param info: pointer to struct with parameters
- * \param d: filepath of the config file
- * \param config_strings: storage for the config strings extracted from JSON,
- * the pointer is incremented as strings are stored
- * \param len: pointer to the remaining length left in config_strings
- * the value is decremented as strings are stored
- *
- * This function prepares a n lws_context_creation_info struct with global
- * settings from a file d.
- *
- * Requires CMake option LWS_WITH_LEJP_CONF to have been enabled
- */
-LWS_VISIBLE LWS_EXTERN int
-lwsws_get_config_globals(struct lws_context_creation_info *info, const char *d,
- char **config_strings, int *len);
-
-/**
- * lwsws_get_config_vhosts() - Create vhosts from a JSON server config file
- * \param context: pointer to result of lws_create_context()
- * \param info: pointer to struct with parameters
- * \param d: filepath of the config file
- * \param config_strings: storage for the config strings extracted from JSON,
- * the pointer is incremented as strings are stored
- * \param len: pointer to the remaining length left in config_strings
- * the value is decremented as strings are stored
- *
- * This function creates vhosts into a context according to the settings in
- *JSON files found in directory d.
- *
- * Requires CMake option LWS_WITH_LEJP_CONF to have been enabled
- */
-LWS_VISIBLE LWS_EXTERN int
-lwsws_get_config_vhosts(struct lws_context *context,
- struct lws_context_creation_info *info, const char *d,
- char **config_strings, int *len);
-
-/** lws_vhost_get() - \deprecated deprecated: use lws_get_vhost() */
-LWS_VISIBLE LWS_EXTERN struct lws_vhost *
-lws_vhost_get(struct lws *wsi) LWS_WARN_DEPRECATED;
-
-/**
- * lws_get_vhost() - return the vhost a wsi belongs to
- *
- * \param wsi: which connection
- */
-LWS_VISIBLE LWS_EXTERN struct lws_vhost *
-lws_get_vhost(struct lws *wsi);
-
-/**
- * lws_get_vhost_name() - returns the name of a vhost
- *
- * \param vhost: which vhost
- */
-LWS_VISIBLE LWS_EXTERN const char *
-lws_get_vhost_name(struct lws_vhost *vhost);
-
-/**
- * lws_get_vhost_port() - returns the port a vhost listens on, or -1
- *
- * \param vhost: which vhost
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_get_vhost_port(struct lws_vhost *vhost);
-
-/**
- * lws_get_vhost_user() - returns the user pointer for the vhost
- *
- * \param vhost: which vhost
- */
-LWS_VISIBLE LWS_EXTERN void *
-lws_get_vhost_user(struct lws_vhost *vhost);
-
-/**
- * lws_get_vhost_iface() - returns the binding for the vhost listen socket
- *
- * \param vhost: which vhost
- */
-LWS_VISIBLE LWS_EXTERN const char *
-lws_get_vhost_iface(struct lws_vhost *vhost);
-
-/**
- * lws_json_dump_vhost() - describe vhost state and stats in JSON
- *
- * \param vh: the vhost
- * \param buf: buffer to fill with JSON
- * \param len: max length of buf
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_json_dump_vhost(const struct lws_vhost *vh, char *buf, int len);
-
-/**
- * lws_json_dump_context() - describe context state and stats in JSON
- *
- * \param context: the context
- * \param buf: buffer to fill with JSON
- * \param len: max length of buf
- * \param hide_vhosts: nonzero to not provide per-vhost mount etc information
- *
- * Generates a JSON description of vhost state into buf
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_json_dump_context(const struct lws_context *context, char *buf, int len,
- int hide_vhosts);
-
-/**
- * lws_vhost_user() - get the user data associated with the vhost
- * \param vhost: Websocket vhost
- *
- * This returns the optional user pointer that can be attached to
- * a vhost when it was created. Lws never dereferences this pointer, it only
- * sets it when the vhost is created, and returns it using this api.
- */
-LWS_VISIBLE LWS_EXTERN void *
-lws_vhost_user(struct lws_vhost *vhost);
-
-/**
- * lws_context_user() - get the user data associated with the context
- * \param context: Websocket context
- *
- * This returns the optional user allocation that can be attached to
- * the context the sockets live in at context_create time. It's a way
- * to let all sockets serviced in the same context share data without
- * using globals statics in the user code.
- */
-LWS_VISIBLE LWS_EXTERN void *
-lws_context_user(struct lws_context *context);
-
-/*! \defgroup vhost-mounts Vhost mounts and options
- * \ingroup context-and-vhost-creation
- *
- * ##Vhost mounts and options
- */
-///@{
-/** struct lws_protocol_vhost_options - linked list of per-vhost protocol
- * name=value options
- *
- * This provides a general way to attach a linked-list of name=value pairs,
- * which can also have an optional child link-list using the options member.
- */
-struct lws_protocol_vhost_options {
- const struct lws_protocol_vhost_options *next; /**< linked list */
- const struct lws_protocol_vhost_options *options; /**< child linked-list of more options for this node */
- const char *name; /**< name of name=value pair */
- const char *value; /**< value of name=value pair */
-};
-
-/** enum lws_mount_protocols
- * This specifies the mount protocol for a mountpoint, whether it is to be
- * served from a filesystem, or it is a cgi etc.
- */
-enum lws_mount_protocols {
- LWSMPRO_HTTP = 0, /**< http reverse proxy */
- LWSMPRO_HTTPS = 1, /**< https reverse proxy */
- LWSMPRO_FILE = 2, /**< serve from filesystem directory */
- LWSMPRO_CGI = 3, /**< pass to CGI to handle */
- LWSMPRO_REDIR_HTTP = 4, /**< redirect to http:// url */
- LWSMPRO_REDIR_HTTPS = 5, /**< redirect to https:// url */
- LWSMPRO_CALLBACK = 6, /**< hand by named protocol's callback */
-};
-
-/** struct lws_http_mount
- *
- * arguments for mounting something in a vhost's url namespace
- */
-struct lws_http_mount {
- const struct lws_http_mount *mount_next;
- /**< pointer to next struct lws_http_mount */
- const char *mountpoint;
- /**< mountpoint in http pathspace, eg, "/" */
- const char *origin;
- /**< path to be mounted, eg, "/var/www/warmcat.com" */
- const char *def;
- /**< default target, eg, "index.html" */
- const char *protocol;
- /**<"protocol-name" to handle mount */
-
- const struct lws_protocol_vhost_options *cgienv;
- /**< optional linked-list of cgi options. These are created
- * as environment variables for the cgi process
- */
- const struct lws_protocol_vhost_options *extra_mimetypes;
- /**< optional linked-list of mimetype mappings */
- const struct lws_protocol_vhost_options *interpret;
- /**< optional linked-list of files to be interpreted */
-
- int cgi_timeout;
- /**< seconds cgi is allowed to live, if cgi://mount type */
- int cache_max_age;
- /**< max-age for reuse of client cache of files, seconds */
- unsigned int auth_mask;
- /**< bits set here must be set for authorized client session */
-
- unsigned int cache_reusable:1; /**< set if client cache may reuse this */
- unsigned int cache_revalidate:1; /**< set if client cache should revalidate on use */
- unsigned int cache_intermediaries:1; /**< set if intermediaries are allowed to cache */
-
- unsigned char origin_protocol; /**< one of enum lws_mount_protocols */
- unsigned char mountpoint_len; /**< length of mountpoint string */
-
- const char *basic_auth_login_file;
- /**<NULL, or filepath to use to check basic auth logins against */
-
- /* Add new things just above here ---^
- * This is part of the ABI, don't needlessly break compatibility
- *
- * The below is to ensure later library versions with new
- * members added above will see 0 (default) even if the app
- * was not built against the newer headers.
- */
-
- void *_unused[2]; /**< dummy */
-};
-///@}
-///@}
-
-/*! \defgroup client Client related functions
- * ##Client releated functions
- * \ingroup lwsapi
- *
- * */
-///@{
-
-/** enum lws_client_connect_ssl_connection_flags - flags that may be used
- * with struct lws_client_connect_info ssl_connection member to control if
- * and how SSL checks apply to the client connection being created
- */
-
-enum lws_client_connect_ssl_connection_flags {
- LCCSCF_USE_SSL = (1 << 0),
- LCCSCF_ALLOW_SELFSIGNED = (1 << 1),
- LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK = (1 << 2),
- LCCSCF_ALLOW_EXPIRED = (1 << 3),
-
- LCCSCF_PIPELINE = (1 << 16),
- /**< Serialize / pipeline multiple client connections
- * on a single connection where possible.
- *
- * HTTP/1.0: possible if Keep-Alive: yes sent by server
- * HTTP/1.1: always possible... uses pipelining
- * HTTP/2: always possible... uses parallel streams
- * */
-};
-
-/** struct lws_client_connect_info - parameters to connect with when using
- * lws_client_connect_via_info() */
-
-struct lws_client_connect_info {
- struct lws_context *context;
- /**< lws context to create connection in */
- const char *address;
- /**< remote address to connect to */
- int port;
- /**< remote port to connect to */
- int ssl_connection;
- /**< 0, or a combination of LCCSCF_ flags */
- const char *path;
- /**< uri path */
- const char *host;
- /**< content of host header */
- const char *origin;
- /**< content of origin header */
- const char *protocol;
- /**< list of ws protocols we could accept */
- int ietf_version_or_minus_one;
- /**< deprecated: currently leave at 0 or -1 */
- void *userdata;
- /**< if non-NULL, use this as wsi user_data instead of malloc it */
- const void *client_exts;
- /**< UNUSED... provide in info.extensions at context creation time */
- const char *method;
- /**< if non-NULL, do this http method instead of ws[s] upgrade.
- * use "GET" to be a simple http client connection. "RAW" gets
- * you a connected socket that lws itself will leave alone once
- * connected. */
- struct lws *parent_wsi;
- /**< if another wsi is responsible for this connection, give it here.
- * this is used to make sure if the parent closes so do any
- * child connections first. */
- const char *uri_replace_from;
- /**< if non-NULL, when this string is found in URIs in
- * text/html content-encoding, it's replaced with uri_replace_to */
- const char *uri_replace_to;
- /**< see uri_replace_from */
- struct lws_vhost *vhost;
- /**< vhost to bind to (used to determine related SSL_CTX) */
- struct lws **pwsi;
- /**< if not NULL, store the new wsi here early in the connection
- * process. Although we return the new wsi, the call to create the
- * client connection does progress the connection somewhat and may
- * meet an error that will result in the connection being scrubbed and
- * NULL returned. While the wsi exists though, he may process a
- * callback like CLIENT_CONNECTION_ERROR with his wsi: this gives the
- * user callback a way to identify which wsi it is that faced the error
- * even before the new wsi is returned and even if ultimately no wsi
- * is returned.
- */
- const char *iface;
- /**< NULL to allow routing on any interface, or interface name or IP
- * to bind the socket to */
- const char *local_protocol_name;
- /**< NULL: .protocol is used both to select the local protocol handler
- * to bind to and as the list of remote ws protocols we could
- * accept.
- * non-NULL: this protocol name is used to bind the connection to
- * the local protocol handler. .protocol is used for the
- * list of remote ws protocols we could accept */
-
- /* Add new things just above here ---^
- * This is part of the ABI, don't needlessly break compatibility
- *
- * The below is to ensure later library versions with new
- * members added above will see 0 (default) even if the app
- * was not built against the newer headers.
- */
- const char *alpn;
- /* NULL: allow lws default ALPN list, from vhost if present or from
- * list of roles built into lws
- * non-NULL: require one from provided comma-separated list of alpn
- * tokens
- */
-
- void *_unused[4]; /**< dummy */
-};
-
-/**
- * lws_client_connect_via_info() - Connect to another websocket server
- * \param ccinfo: pointer to lws_client_connect_info struct
- *
- * This function creates a connection to a remote server using the
- * information provided in ccinfo.
- */
-LWS_VISIBLE LWS_EXTERN struct lws *
-lws_client_connect_via_info(struct lws_client_connect_info * ccinfo);
-
-/**
- * lws_client_connect() - Connect to another websocket server
- * \deprecated DEPRECATED use lws_client_connect_via_info
- * \param clients: Websocket context
- * \param address: Remote server address, eg, "myserver.com"
- * \param port: Port to connect to on the remote server, eg, 80
- * \param ssl_connection: 0 = ws://, 1 = wss:// encrypted, 2 = wss:// allow self
- * signed certs
- * \param path: Websocket path on server
- * \param host: Hostname on server
- * \param origin: Socket origin name
- * \param protocol: Comma-separated list of protocols being asked for from
- * the server, or just one. The server will pick the one it
- * likes best. If you don't want to specify a protocol, which is
- * legal, use NULL here.
- * \param ietf_version_or_minus_one: -1 to ask to connect using the default, latest
- * protocol supported, or the specific protocol ordinal
- *
- * This function creates a connection to a remote server
- */
-/* deprecated, use lws_client_connect_via_info() */
-LWS_VISIBLE LWS_EXTERN struct lws * LWS_WARN_UNUSED_RESULT
-lws_client_connect(struct lws_context *clients, const char *address,
- int port, int ssl_connection, const char *path,
- const char *host, const char *origin, const char *protocol,
- int ietf_version_or_minus_one) LWS_WARN_DEPRECATED;
-/* deprecated, use lws_client_connect_via_info() */
-/**
- * lws_client_connect_extended() - Connect to another websocket server
- * \deprecated DEPRECATED use lws_client_connect_via_info
- * \param clients: Websocket context
- * \param address: Remote server address, eg, "myserver.com"
- * \param port: Port to connect to on the remote server, eg, 80
- * \param ssl_connection: 0 = ws://, 1 = wss:// encrypted, 2 = wss:// allow self
- * signed certs
- * \param path: Websocket path on server
- * \param host: Hostname on server
- * \param origin: Socket origin name
- * \param protocol: Comma-separated list of protocols being asked for from
- * the server, or just one. The server will pick the one it
- * likes best.
- * \param ietf_version_or_minus_one: -1 to ask to connect using the default, latest
- * protocol supported, or the specific protocol ordinal
- * \param userdata: Pre-allocated user data
- *
- * This function creates a connection to a remote server
- */
-LWS_VISIBLE LWS_EXTERN struct lws * LWS_WARN_UNUSED_RESULT
-lws_client_connect_extended(struct lws_context *clients, const char *address,
- int port, int ssl_connection, const char *path,
- const char *host, const char *origin,
- const char *protocol, int ietf_version_or_minus_one,
- void *userdata) LWS_WARN_DEPRECATED;
-
-/**
- * lws_init_vhost_client_ssl() - also enable client SSL on an existing vhost
- *
- * \param info: client ssl related info
- * \param vhost: which vhost to initialize client ssl operations on
- *
- * You only need to call this if you plan on using SSL client connections on
- * the vhost. For non-SSL client connections, it's not necessary to call this.
- *
- * The following members of info are used during the call
- *
- * - options must have LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT set,
- * otherwise the call does nothing
- * - provided_client_ssl_ctx must be NULL to get a generated client
- * ssl context, otherwise you can pass a prepared one in by setting it
- * - ssl_cipher_list may be NULL or set to the client valid cipher list
- * - ssl_ca_filepath may be NULL or client cert filepath
- * - ssl_cert_filepath may be NULL or client cert filepath
- * - ssl_private_key_filepath may be NULL or client cert private key
- *
- * You must create your vhost explicitly if you want to use this, so you have
- * a pointer to the vhost. Create the context first with the option flag
- * LWS_SERVER_OPTION_EXPLICIT_VHOSTS and then call lws_create_vhost() with
- * the same info struct.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_init_vhost_client_ssl(const struct lws_context_creation_info *info,
- struct lws_vhost *vhost);
-/**
- * lws_http_client_read() - consume waiting received http client data
- *
- * \param wsi: client connection
- * \param buf: pointer to buffer pointer - fill with pointer to your buffer
- * \param len: pointer to chunk length - fill with max length of buffer
- *
- * This is called when the user code is notified client http data has arrived.
- * The user code may choose to delay calling it to consume the data, for example
- * waiting until an onward connection is writeable.
- *
- * For non-chunked connections, up to len bytes of buf are filled with the
- * received content. len is set to the actual amount filled before return.
- *
- * For chunked connections, the linear buffer content contains the chunking
- * headers and it cannot be passed in one lump. Instead, this function will
- * call back LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ with in pointing to the
- * chunk start and len set to the chunk length. There will be as many calls
- * as there are chunks or partial chunks in the buffer.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_http_client_read(struct lws *wsi, char **buf, int *len);
-
-/**
- * lws_http_client_http_response() - get last HTTP response code
- *
- * \param wsi: client connection
- *
- * Returns the last server response code, eg, 200 for client http connections.
- *
- * You should capture this during the LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP
- * callback, because after that the memory reserved for storing the related
- * headers is freed and this value is lost.
- */
-LWS_VISIBLE LWS_EXTERN unsigned int
-lws_http_client_http_response(struct lws *wsi);
-
-LWS_VISIBLE LWS_EXTERN void
-lws_client_http_body_pending(struct lws *wsi, int something_left_to_send);
-
-/**
- * lws_client_http_body_pending() - control if client connection neeeds to send body
- *
- * \param wsi: client connection
- * \param something_left_to_send: nonzero if need to send more body, 0 (default)
- * if nothing more to send
- *
- * If you will send payload data with your HTTP client connection, eg, for POST,
- * when you set the related http headers in
- * LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER callback you should also call
- * this API with something_left_to_send nonzero, and call
- * lws_callback_on_writable(wsi);
- *
- * After sending the headers, lws will call your callback with
- * LWS_CALLBACK_CLIENT_HTTP_WRITEABLE reason when writable. You can send the
- * next part of the http body payload, calling lws_callback_on_writable(wsi);
- * if there is more to come, or lws_client_http_body_pending(wsi, 0); to
- * let lws know the last part is sent and the connection can move on.
- */
-
-///@}
-
-/** \defgroup service Built-in service loop entry
- *
- * ##Built-in service loop entry
- *
- * If you're not using libev / libuv, these apis are needed to enter the poll()
- * wait in lws and service any connections with pending events.
- */
-///@{
-
-/**
- * lws_service() - Service any pending websocket activity
- * \param context: Websocket context
- * \param timeout_ms: Timeout for poll; 0 means return immediately if nothing needed
- * service otherwise block and service immediately, returning
- * after the timeout if nothing needed service.
- *
- * This function deals with any pending websocket traffic, for three
- * kinds of event. It handles these events on both server and client
- * types of connection the same.
- *
- * 1) Accept new connections to our context's server
- *
- * 2) Call the receive callback for incoming frame data received by
- * server or client connections.
- *
- * You need to call this service function periodically to all the above
- * functions to happen; if your application is single-threaded you can
- * just call it in your main event loop.
- *
- * Alternatively you can fork a new process that asynchronously handles
- * calling this service in a loop. In that case you are happy if this
- * call blocks your thread until it needs to take care of something and
- * would call it with a large nonzero timeout. Your loop then takes no
- * CPU while there is nothing happening.
- *
- * If you are calling it in a single-threaded app, you don't want it to
- * wait around blocking other things in your loop from happening, so you
- * would call it with a timeout_ms of 0, so it returns immediately if
- * nothing is pending, or as soon as it services whatever was pending.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_service(struct lws_context *context, int timeout_ms);
-
-/**
- * lws_service_tsi() - Service any pending websocket activity
- *
- * \param context: Websocket context
- * \param timeout_ms: Timeout for poll; 0 means return immediately if nothing needed
- * service otherwise block and service immediately, returning
- * after the timeout if nothing needed service.
- * \param tsi: Thread service index, starting at 0
- *
- * Same as lws_service(), but for a specific thread service index. Only needed
- * if you are spawning multiple service threads.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_service_tsi(struct lws_context *context, int timeout_ms, int tsi);
-
-/**
- * lws_cancel_service_pt() - Cancel servicing of pending socket activity
- * on one thread
- * \param wsi: Cancel service on the thread this wsi is serviced by
- *
- * Same as lws_cancel_service(), but targets a single service thread, the one
- * the wsi belongs to. You probably want to use lws_cancel_service() instead.
- */
-LWS_VISIBLE LWS_EXTERN void
-lws_cancel_service_pt(struct lws *wsi);
-
-/**
- * lws_cancel_service() - Cancel wait for new pending socket activity
- * \param context: Websocket context
- *
- * This function creates an immediate "synchronous interrupt" to the lws poll()
- * wait or event loop. As soon as possible in the serialzed service sequencing,
- * a LWS_CALLBACK_EVENT_WAIT_CANCELLED callback is sent to every protocol on
- * every vhost.
- *
- * lws_cancel_service() may be called from another thread while the context
- * exists, and its effect will be immediately serialized.
- */
-LWS_VISIBLE LWS_EXTERN void
-lws_cancel_service(struct lws_context *context);
-
-/**
- * lws_service_fd() - Service polled socket with something waiting
- * \param context: Websocket context
- * \param pollfd: The pollfd entry describing the socket fd and which events
- * happened, or NULL to tell lws to do only timeout servicing.
- *
- * This function takes a pollfd that has POLLIN or POLLOUT activity and
- * services it according to the state of the associated
- * struct lws.
- *
- * The one call deals with all "service" that might happen on a socket
- * including listen accepts, http files as well as websocket protocol.
- *
- * If a pollfd says it has something, you can just pass it to
- * lws_service_fd() whether it is a socket handled by lws or not.
- * If it sees it is a lws socket, the traffic will be handled and
- * pollfd->revents will be zeroed now.
- *
- * If the socket is foreign to lws, it leaves revents alone. So you can
- * see if you should service yourself by checking the pollfd revents
- * after letting lws try to service it.
- *
- * You should also call this with pollfd = NULL to just allow the
- * once-per-second global timeout checks; if less than a second since the last
- * check it returns immediately then.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_service_fd(struct lws_context *context, struct lws_pollfd *pollfd);
-
-/**
- * lws_service_fd_tsi() - Service polled socket in specific service thread
- * \param context: Websocket context
- * \param pollfd: The pollfd entry describing the socket fd and which events
- * happened.
- * \param tsi: thread service index
- *
- * Same as lws_service_fd() but used with multiple service threads
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd,
- int tsi);
-
-/**
- * lws_service_adjust_timeout() - Check for any connection needing forced service
- * \param context: Websocket context
- * \param timeout_ms: The original poll timeout value. You can just set this
- * to 1 if you don't really have a poll timeout.
- * \param tsi: thread service index
- *
- * Under some conditions connections may need service even though there is no
- * pending network action on them, this is "forced service". For default
- * poll() and libuv / libev, the library takes care of calling this and
- * dealing with it for you. But for external poll() integration, you need
- * access to the apis.
- *
- * If anybody needs "forced service", returned timeout is zero. In that case,
- * you can call lws_service_tsi() with a timeout of -1 to only service
- * guys who need forced service.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_service_adjust_timeout(struct lws_context *context, int timeout_ms, int tsi);
-
-/* Backwards compatibility */
-#define lws_plat_service_tsi lws_service_tsi
-
-LWS_VISIBLE LWS_EXTERN int
-lws_handle_POLLOUT_event(struct lws *wsi, struct lws_pollfd *pollfd);
-
-///@}
-
-/*! \defgroup http HTTP
-
- Modules related to handling HTTP
-*/
-//@{
-
-/*! \defgroup httpft HTTP File transfer
- * \ingroup http
-
- APIs for sending local files in response to HTTP requests
-*/
-//@{
-
-/**
- * lws_get_mimetype() - Determine mimetype to use from filename
- *
- * \param file: filename
- * \param m: NULL, or mount context
- *
- * This uses a canned list of known filetypes first, if no match and m is
- * non-NULL, then tries a list of per-mount file suffix to mimtype mappings.
- *
- * Returns either NULL or a pointer to the mimetype matching the file.
- */
-LWS_VISIBLE LWS_EXTERN const char *
-lws_get_mimetype(const char *file, const struct lws_http_mount *m);
-
-/**
- * lws_serve_http_file() - Send a file back to the client using http
- * \param wsi: Websocket instance (available from user callback)
- * \param file: The file to issue over http
- * \param content_type: The http content type, eg, text/html
- * \param other_headers: NULL or pointer to header string
- * \param other_headers_len: length of the other headers if non-NULL
- *
- * This function is intended to be called from the callback in response
- * to http requests from the client. It allows the callback to issue
- * local files down the http link in a single step.
- *
- * Returning <0 indicates error and the wsi should be closed. Returning
- * >0 indicates the file was completely sent and
- * lws_http_transaction_completed() called on the wsi (and close if != 0)
- * ==0 indicates the file transfer is started and needs more service later,
- * the wsi should be left alone.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_serve_http_file(struct lws *wsi, const char *file, const char *content_type,
- const char *other_headers, int other_headers_len);
-
-LWS_VISIBLE LWS_EXTERN int
-lws_serve_http_file_fragment(struct lws *wsi);
-//@}
-
-
-enum http_status {
- HTTP_STATUS_CONTINUE = 100,
-
- HTTP_STATUS_OK = 200,
- HTTP_STATUS_NO_CONTENT = 204,
- HTTP_STATUS_PARTIAL_CONTENT = 206,
-
- HTTP_STATUS_MOVED_PERMANENTLY = 301,
- HTTP_STATUS_FOUND = 302,
- HTTP_STATUS_SEE_OTHER = 303,
- HTTP_STATUS_NOT_MODIFIED = 304,
-
- HTTP_STATUS_BAD_REQUEST = 400,
- HTTP_STATUS_UNAUTHORIZED,
- HTTP_STATUS_PAYMENT_REQUIRED,
- HTTP_STATUS_FORBIDDEN,
- HTTP_STATUS_NOT_FOUND,
- HTTP_STATUS_METHOD_NOT_ALLOWED,
- HTTP_STATUS_NOT_ACCEPTABLE,
- HTTP_STATUS_PROXY_AUTH_REQUIRED,
- HTTP_STATUS_REQUEST_TIMEOUT,
- HTTP_STATUS_CONFLICT,
- HTTP_STATUS_GONE,
- HTTP_STATUS_LENGTH_REQUIRED,
- HTTP_STATUS_PRECONDITION_FAILED,
- HTTP_STATUS_REQ_ENTITY_TOO_LARGE,
- HTTP_STATUS_REQ_URI_TOO_LONG,
- HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE,
- HTTP_STATUS_REQ_RANGE_NOT_SATISFIABLE,
- HTTP_STATUS_EXPECTATION_FAILED,
-
- HTTP_STATUS_INTERNAL_SERVER_ERROR = 500,
- HTTP_STATUS_NOT_IMPLEMENTED,
- HTTP_STATUS_BAD_GATEWAY,
- HTTP_STATUS_SERVICE_UNAVAILABLE,
- HTTP_STATUS_GATEWAY_TIMEOUT,
- HTTP_STATUS_HTTP_VERSION_NOT_SUPPORTED,
-};
-/*! \defgroup html-chunked-substitution HTML Chunked Substitution
- * \ingroup http
- *
- * ##HTML chunked Substitution
- *
- * APIs for receiving chunks of text, replacing a set of variable names via
- * a callback, and then prepending and appending HTML chunked encoding
- * headers.
- */
-//@{
-
-struct lws_process_html_args {
- char *p; /**< pointer to the buffer containing the data */
- int len; /**< length of the original data at p */
- int max_len; /**< maximum length we can grow the data to */
- int final; /**< set if this is the last chunk of the file */
- int chunked; /**< 0 == unchunked, 1 == produce chunk headers (incompatible with HTTP/2) */
-};
-
-typedef const char *(*lws_process_html_state_cb)(void *data, int index);
-
-struct lws_process_html_state {
- char *start; /**< pointer to start of match */
- char swallow[16]; /**< matched character buffer */
- int pos; /**< position in match */
- void *data; /**< opaque pointer */
- const char * const *vars; /**< list of variable names */
- int count_vars; /**< count of variable names */
-
- lws_process_html_state_cb replace; /**< called on match to perform substitution */
-};
-
-/*! lws_chunked_html_process() - generic chunked substitution
- * \param args: buffer to process using chunked encoding
- * \param s: current processing state
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_chunked_html_process(struct lws_process_html_args *args,
- struct lws_process_html_state *s);
-//@}
-
-/** \defgroup HTTP-headers-read HTTP headers: read
- * \ingroup http
- *
- * ##HTTP header releated functions
- *
- * In lws the client http headers are temporarily stored in a pool, only for the
- * duration of the http part of the handshake. It's because in most cases,
- * the header content is ignored for the whole rest of the connection lifetime
- * and would then just be taking up space needlessly.
- *
- * During LWS_CALLBACK_HTTP when the URI path is delivered is the last time
- * the http headers are still allocated, you can use these apis then to
- * look at and copy out interesting header content (cookies, etc)
- *
- * Notice that the header total length reported does not include a terminating
- * '\0', however you must allocate for it when using the _copy apis. So the
- * length reported for a header containing "123" is 3, but you must provide
- * a buffer of length 4 so that "123\0" may be copied into it, or the copy
- * will fail with a nonzero return code.
- *
- * In the special case of URL arguments, like ?x=1&y=2, the arguments are
- * stored in a token named for the method, eg, WSI_TOKEN_GET_URI if it
- * was a GET or WSI_TOKEN_POST_URI if POST. You can check the total
- * length to confirm the method.
- *
- * For URL arguments, each argument is stored urldecoded in a "fragment", so
- * you can use the fragment-aware api lws_hdr_copy_fragment() to access each
- * argument in turn: the fragments contain urldecoded strings like x=1 or y=2.
- *
- * As a convenience, lws has an api that will find the fragment with a
- * given name= part, lws_get_urlarg_by_name().
- */
-///@{
-
-/** struct lws_tokens
- * you need these to look at headers that have been parsed if using the
- * LWS_CALLBACK_FILTER_CONNECTION callback. If a header from the enum
- * list below is absent, .token = NULL and len = 0. Otherwise .token
- * points to .len chars containing that header content.
- */
-struct lws_tokens {
- char *token; /**< pointer to start of the token */
- int len; /**< length of the token's value */
-};
-
-/* enum lws_token_indexes
- * these have to be kept in sync with lextable.h / minilex.c
- *
- * NOTE: These public enums are part of the abi. If you want to add one,
- * add it at where specified so existing users are unaffected.
- */
-enum lws_token_indexes {
- WSI_TOKEN_GET_URI = 0,
- WSI_TOKEN_POST_URI = 1,
- WSI_TOKEN_OPTIONS_URI = 2,
- WSI_TOKEN_HOST = 3,
- WSI_TOKEN_CONNECTION = 4,
- WSI_TOKEN_UPGRADE = 5,
- WSI_TOKEN_ORIGIN = 6,
- WSI_TOKEN_DRAFT = 7,
- WSI_TOKEN_CHALLENGE = 8,
- WSI_TOKEN_EXTENSIONS = 9,
- WSI_TOKEN_KEY1 = 10,
- WSI_TOKEN_KEY2 = 11,
- WSI_TOKEN_PROTOCOL = 12,
- WSI_TOKEN_ACCEPT = 13,
- WSI_TOKEN_NONCE = 14,
- WSI_TOKEN_HTTP = 15,
- WSI_TOKEN_HTTP2_SETTINGS = 16,
- WSI_TOKEN_HTTP_ACCEPT = 17,
- WSI_TOKEN_HTTP_AC_REQUEST_HEADERS = 18,
- WSI_TOKEN_HTTP_IF_MODIFIED_SINCE = 19,
- WSI_TOKEN_HTTP_IF_NONE_MATCH = 20,
- WSI_TOKEN_HTTP_ACCEPT_ENCODING = 21,
- WSI_TOKEN_HTTP_ACCEPT_LANGUAGE = 22,
- WSI_TOKEN_HTTP_PRAGMA = 23,
- WSI_TOKEN_HTTP_CACHE_CONTROL = 24,
- WSI_TOKEN_HTTP_AUTHORIZATION = 25,
- WSI_TOKEN_HTTP_COOKIE = 26,
- WSI_TOKEN_HTTP_CONTENT_LENGTH = 27,
- WSI_TOKEN_HTTP_CONTENT_TYPE = 28,
- WSI_TOKEN_HTTP_DATE = 29,
- WSI_TOKEN_HTTP_RANGE = 30,
- WSI_TOKEN_HTTP_REFERER = 31,
- WSI_TOKEN_KEY = 32,
- WSI_TOKEN_VERSION = 33,
- WSI_TOKEN_SWORIGIN = 34,
-
- WSI_TOKEN_HTTP_COLON_AUTHORITY = 35,
- WSI_TOKEN_HTTP_COLON_METHOD = 36,
- WSI_TOKEN_HTTP_COLON_PATH = 37,
- WSI_TOKEN_HTTP_COLON_SCHEME = 38,
- WSI_TOKEN_HTTP_COLON_STATUS = 39,
-
- WSI_TOKEN_HTTP_ACCEPT_CHARSET = 40,
- WSI_TOKEN_HTTP_ACCEPT_RANGES = 41,
- WSI_TOKEN_HTTP_ACCESS_CONTROL_ALLOW_ORIGIN = 42,
- WSI_TOKEN_HTTP_AGE = 43,
- WSI_TOKEN_HTTP_ALLOW = 44,
- WSI_TOKEN_HTTP_CONTENT_DISPOSITION = 45,
- WSI_TOKEN_HTTP_CONTENT_ENCODING = 46,
- WSI_TOKEN_HTTP_CONTENT_LANGUAGE = 47,
- WSI_TOKEN_HTTP_CONTENT_LOCATION = 48,
- WSI_TOKEN_HTTP_CONTENT_RANGE = 49,
- WSI_TOKEN_HTTP_ETAG = 50,
- WSI_TOKEN_HTTP_EXPECT = 51,
- WSI_TOKEN_HTTP_EXPIRES = 52,
- WSI_TOKEN_HTTP_FROM = 53,
- WSI_TOKEN_HTTP_IF_MATCH = 54,
- WSI_TOKEN_HTTP_IF_RANGE = 55,
- WSI_TOKEN_HTTP_IF_UNMODIFIED_SINCE = 56,
- WSI_TOKEN_HTTP_LAST_MODIFIED = 57,
- WSI_TOKEN_HTTP_LINK = 58,
- WSI_TOKEN_HTTP_LOCATION = 59,
- WSI_TOKEN_HTTP_MAX_FORWARDS = 60,
- WSI_TOKEN_HTTP_PROXY_AUTHENTICATE = 61,
- WSI_TOKEN_HTTP_PROXY_AUTHORIZATION = 62,
- WSI_TOKEN_HTTP_REFRESH = 63,
- WSI_TOKEN_HTTP_RETRY_AFTER = 64,
- WSI_TOKEN_HTTP_SERVER = 65,
- WSI_TOKEN_HTTP_SET_COOKIE = 66,
- WSI_TOKEN_HTTP_STRICT_TRANSPORT_SECURITY = 67,
- WSI_TOKEN_HTTP_TRANSFER_ENCODING = 68,
- WSI_TOKEN_HTTP_USER_AGENT = 69,
- WSI_TOKEN_HTTP_VARY = 70,
- WSI_TOKEN_HTTP_VIA = 71,
- WSI_TOKEN_HTTP_WWW_AUTHENTICATE = 72,
-
- WSI_TOKEN_PATCH_URI = 73,
- WSI_TOKEN_PUT_URI = 74,
- WSI_TOKEN_DELETE_URI = 75,
-
- WSI_TOKEN_HTTP_URI_ARGS = 76,
- WSI_TOKEN_PROXY = 77,
- WSI_TOKEN_HTTP_X_REAL_IP = 78,
- WSI_TOKEN_HTTP1_0 = 79,
- WSI_TOKEN_X_FORWARDED_FOR = 80,
- WSI_TOKEN_CONNECT = 81,
- WSI_TOKEN_HEAD_URI = 82,
- WSI_TOKEN_TE = 83,
- WSI_TOKEN_REPLAY_NONCE = 84,
- WSI_TOKEN_COLON_PROTOCOL = 85,
- WSI_TOKEN_X_AUTH_TOKEN = 86,
-
- /****** add new things just above ---^ ******/
-
- /* use token storage to stash these internally, not for
- * user use */
-
- _WSI_TOKEN_CLIENT_SENT_PROTOCOLS,
- _WSI_TOKEN_CLIENT_PEER_ADDRESS,
- _WSI_TOKEN_CLIENT_URI,
- _WSI_TOKEN_CLIENT_HOST,
- _WSI_TOKEN_CLIENT_ORIGIN,
- _WSI_TOKEN_CLIENT_METHOD,
- _WSI_TOKEN_CLIENT_IFACE,
- _WSI_TOKEN_CLIENT_ALPN,
-
- /* always last real token index*/
- WSI_TOKEN_COUNT,
-
- /* parser state additions, no storage associated */
- WSI_TOKEN_NAME_PART,
- WSI_TOKEN_SKIPPING,
- WSI_TOKEN_SKIPPING_SAW_CR,
- WSI_PARSING_COMPLETE,
- WSI_INIT_TOKEN_MUXURL,
-};
-
-struct lws_token_limits {
- unsigned short token_limit[WSI_TOKEN_COUNT]; /**< max chars for this token */
-};
-
-/**
- * lws_token_to_string() - returns a textual representation of a hdr token index
- *
- * \param token: token index
- */
-LWS_VISIBLE LWS_EXTERN const unsigned char *
-lws_token_to_string(enum lws_token_indexes token);
-
-/**
- * lws_hdr_total_length: report length of all fragments of a header totalled up
- * The returned length does not include the space for a
- * terminating '\0'
- *
- * \param wsi: websocket connection
- * \param h: which header index we are interested in
- */
-LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_hdr_total_length(struct lws *wsi, enum lws_token_indexes h);
-
-/**
- * lws_hdr_fragment_length: report length of a single fragment of a header
- * The returned length does not include the space for a
- * terminating '\0'
- *
- * \param wsi: websocket connection
- * \param h: which header index we are interested in
- * \param frag_idx: which fragment of h we want to get the length of
- */
-LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_hdr_fragment_length(struct lws *wsi, enum lws_token_indexes h, int frag_idx);
-
-/**
- * lws_hdr_copy() - copy a single fragment of the given header to a buffer
- * The buffer length len must include space for an additional
- * terminating '\0', or it will fail returning -1.
- *
- * \param wsi: websocket connection
- * \param dest: destination buffer
- * \param len: length of destination buffer
- * \param h: which header index we are interested in
- *
- * copies the whole, aggregated header, even if it was delivered in
- * several actual headers piece by piece
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_hdr_copy(struct lws *wsi, char *dest, int len, enum lws_token_indexes h);
-
-/**
- * lws_hdr_copy_fragment() - copy a single fragment of the given header to a buffer
- * The buffer length len must include space for an additional
- * terminating '\0', or it will fail returning -1.
- * If the requested fragment index is not present, it fails
- * returning -1.
- *
- * \param wsi: websocket connection
- * \param dest: destination buffer
- * \param len: length of destination buffer
- * \param h: which header index we are interested in
- * \param frag_idx: which fragment of h we want to copy
- *
- * Normally this is only useful
- * to parse URI arguments like ?x=1&y=2, token index WSI_TOKEN_HTTP_URI_ARGS
- * fragment 0 will contain "x=1" and fragment 1 "y=2"
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_hdr_copy_fragment(struct lws *wsi, char *dest, int len,
- enum lws_token_indexes h, int frag_idx);
-
-/**
- * lws_get_urlarg_by_name() - return pointer to arg value if present
- * \param wsi: the connection to check
- * \param name: the arg name, like "token="
- * \param buf: the buffer to receive the urlarg (including the name= part)
- * \param len: the length of the buffer to receive the urlarg
- *
- * Returns NULL if not found or a pointer inside buf to just after the
- * name= part.
- */
-LWS_VISIBLE LWS_EXTERN const char *
-lws_get_urlarg_by_name(struct lws *wsi, const char *name, char *buf, int len);
-///@}
-
-/*! \defgroup HTTP-headers-create HTTP headers: create
- *
- * ## HTTP headers: Create
- *
- * These apis allow you to create HTTP response headers in a way compatible with
- * both HTTP/1.x and HTTP/2.
- *
- * They each append to a buffer taking care about the buffer end, which is
- * passed in as a pointer. When data is written to the buffer, the current
- * position p is updated accordingly.
- *
- * All of these apis are LWS_WARN_UNUSED_RESULT as they can run out of space
- * and fail with nonzero return.
- */
-///@{
-
-#define LWSAHH_CODE_MASK ((1 << 16) - 1)
-#define LWSAHH_FLAG_NO_SERVER_NAME (1 << 30)
-
-/**
- * lws_add_http_header_status() - add the HTTP response status code
- *
- * \param wsi: the connection to check
- * \param code: an HTTP code like 200, 404 etc (see enum http_status)
- * \param p: pointer to current position in buffer pointer
- * \param end: pointer to end of buffer
- *
- * Adds the initial response code, so should be called first.
- *
- * Code may additionally take OR'd flags:
- *
- * LWSAHH_FLAG_NO_SERVER_NAME: don't apply server name header this time
- */
-LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_add_http_header_status(struct lws *wsi,
- unsigned int code, unsigned char **p,
- unsigned char *end);
-/**
- * lws_add_http_header_by_name() - append named header and value
- *
- * \param wsi: the connection to check
- * \param name: the hdr name, like "my-header"
- * \param value: the value after the = for this header
- * \param length: the length of the value
- * \param p: pointer to current position in buffer pointer
- * \param end: pointer to end of buffer
- *
- * Appends name: value to the headers
- */
-LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_add_http_header_by_name(struct lws *wsi, const unsigned char *name,
- const unsigned char *value, int length,
- unsigned char **p, unsigned char *end);
-/**
- * lws_add_http_header_by_token() - append given header and value
- *
- * \param wsi: the connection to check
- * \param token: the token index for the hdr
- * \param value: the value after the = for this header
- * \param length: the length of the value
- * \param p: pointer to current position in buffer pointer
- * \param end: pointer to end of buffer
- *
- * Appends name=value to the headers, but is able to take advantage of better
- * HTTP/2 coding mechanisms where possible.
- */
-LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_add_http_header_by_token(struct lws *wsi, enum lws_token_indexes token,
- const unsigned char *value, int length,
- unsigned char **p, unsigned char *end);
-/**
- * lws_add_http_header_content_length() - append content-length helper
- *
- * \param wsi: the connection to check
- * \param content_length: the content length to use
- * \param p: pointer to current position in buffer pointer
- * \param end: pointer to end of buffer
- *
- * Appends content-length: content_length to the headers
- */
-LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_add_http_header_content_length(struct lws *wsi,
- lws_filepos_t content_length,
- unsigned char **p, unsigned char *end);
-/**
- * lws_finalize_http_header() - terminate header block
- *
- * \param wsi: the connection to check
- * \param p: pointer to current position in buffer pointer
- * \param end: pointer to end of buffer
- *
- * Indicates no more headers will be added
- */
-LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_finalize_http_header(struct lws *wsi, unsigned char **p,
- unsigned char *end);
-
-/**
- * lws_finalize_write_http_header() - Helper finializing and writing http headers
- *
- * \param wsi: the connection to check
- * \param start: pointer to the start of headers in the buffer, eg &buf[LWS_PRE]
- * \param p: pointer to current position in buffer pointer
- * \param end: pointer to end of buffer
- *
- * Terminates the headers correctly accoring to the protocol in use (h1 / h2)
- * and writes the headers. Returns nonzero for error.
- */
-LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_finalize_write_http_header(struct lws *wsi, unsigned char *start,
- unsigned char **p, unsigned char *end);
-
-#define LWS_ILLEGAL_HTTP_CONTENT_LEN ((lws_filepos_t)-1ll)
-
-/**
- * lws_add_http_common_headers() - Helper preparing common http headers
- *
- * \param wsi: the connection to check
- * \param code: an HTTP code like 200, 404 etc (see enum http_status)
- * \param content_type: the content type, like "text/html"
- * \param content_len: the content length, in bytes
- * \param p: pointer to current position in buffer pointer
- * \param end: pointer to end of buffer
- *
- * Adds the initial response code, so should be called first.
- *
- * Code may additionally take OR'd flags:
- *
- * LWSAHH_FLAG_NO_SERVER_NAME: don't apply server name header this time
- *
- * This helper just calls public apis to simplify adding headers that are
- * commonly needed. If it doesn't fit your case, or you want to add additional
- * headers just call the public apis directly yourself for what you want.
- *
- * You can miss out the content length header by providing the constant
- * LWS_ILLEGAL_HTTP_CONTENT_LEN for the content_len.
- *
- * It does not call lws_finalize_http_header(), to allow you to add further
- * headers after calling this. You will need to call that yourself at the end.
- */
-LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_add_http_common_headers(struct lws *wsi, unsigned int code,
- const char *content_type, lws_filepos_t content_len,
- unsigned char **p, unsigned char *end);
-///@}
-
-/** \defgroup form-parsing Form Parsing
- * \ingroup http
- * ##POSTed form parsing functions
- *
- * These lws_spa (stateful post arguments) apis let you parse and urldecode
- * POSTed form arguments, both using simple urlencoded and multipart transfer
- * encoding.
- *
- * It's capable of handling file uploads as well a named input parsing,
- * and the apis are the same for both form upload styles.
- *
- * You feed it a list of parameter names and it creates pointers to the
- * urldecoded arguments: file upload parameters pass the file data in chunks to
- * a user-supplied callback as they come.
- *
- * Since it's stateful, it handles the incoming data needing more than one
- * POST_BODY callback and has no limit on uploaded file size.
- */
-///@{
-
-/** enum lws_spa_fileupload_states */
-enum lws_spa_fileupload_states {
- LWS_UFS_CONTENT,
- /**< a chunk of file content has arrived */
- LWS_UFS_FINAL_CONTENT,
- /**< the last chunk (possibly zero length) of file content has arrived */
- LWS_UFS_OPEN
- /**< a new file is starting to arrive */
-};
-
-/**
- * lws_spa_fileupload_cb() - callback to receive file upload data
- *
- * \param data: opt_data pointer set in lws_spa_create
- * \param name: name of the form field being uploaded
- * \param filename: original filename from client
- * \param buf: start of data to receive
- * \param len: length of data to receive
- * \param state: information about how this call relates to file
- *
- * Notice name and filename shouldn't be trusted, as they are passed from
- * HTTP provided by the client.
- */
-typedef int (*lws_spa_fileupload_cb)(void *data, const char *name,
- const char *filename, char *buf, int len,
- enum lws_spa_fileupload_states state);
-
-/** struct lws_spa - opaque urldecode parser capable of handling multipart
- * and file uploads */
-struct lws_spa;
-
-/**
- * lws_spa_create() - create urldecode parser
- *
- * \param wsi: lws connection (used to find Content Type)
- * \param param_names: array of form parameter names, like "username"
- * \param count_params: count of param_names
- * \param max_storage: total amount of form parameter values we can store
- * \param opt_cb: NULL, or callback to receive file upload data.
- * \param opt_data: NULL, or user pointer provided to opt_cb.
- *
- * Creates a urldecode parser and initializes it.
- *
- * opt_cb can be NULL if you just want normal name=value parsing, however
- * if one or more entries in your form are bulk data (file transfer), you
- * can provide this callback and filter on the name callback parameter to
- * treat that urldecoded data separately. The callback should return -1
- * in case of fatal error, and 0 if OK.
- */
-LWS_VISIBLE LWS_EXTERN struct lws_spa *
-lws_spa_create(struct lws *wsi, const char * const *param_names,
- int count_params, int max_storage, lws_spa_fileupload_cb opt_cb,
- void *opt_data);
-
-/**
- * lws_spa_process() - parses a chunk of input data
- *
- * \param spa: the parser object previously created
- * \param in: incoming, urlencoded data
- * \param len: count of bytes valid at \param in
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_spa_process(struct lws_spa *spa, const char *in, int len);
-
-/**
- * lws_spa_finalize() - indicate incoming data completed
- *
- * \param spa: the parser object previously created
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_spa_finalize(struct lws_spa *spa);
-
-/**
- * lws_spa_get_length() - return length of parameter value
- *
- * \param spa: the parser object previously created
- * \param n: parameter ordinal to return length of value for
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_spa_get_length(struct lws_spa *spa, int n);
-
-/**
- * lws_spa_get_string() - return pointer to parameter value
- * \param spa: the parser object previously created
- * \param n: parameter ordinal to return pointer to value for
- */
-LWS_VISIBLE LWS_EXTERN const char *
-lws_spa_get_string(struct lws_spa *spa, int n);
-
-/**
- * lws_spa_destroy() - destroy parser object
- *
- * \param spa: the parser object previously created
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_spa_destroy(struct lws_spa *spa);
-///@}
-
-/*! \defgroup urlendec Urlencode and Urldecode
- * \ingroup http
- *
- * ##HTML chunked Substitution
- *
- * APIs for receiving chunks of text, replacing a set of variable names via
- * a callback, and then prepending and appending HTML chunked encoding
- * headers.
- */
-//@{
-
-/**
- * lws_urlencode() - like strncpy but with urlencoding
- *
- * \param escaped: output buffer
- * \param string: input buffer ('/0' terminated)
- * \param len: output buffer max length
- *
- * Because urlencoding expands the output string, it's not
- * possible to do it in-place, ie, with escaped == string
- */
-LWS_VISIBLE LWS_EXTERN const char *
-lws_urlencode(char *escaped, const char *string, int len);
-
-/*
- * URLDECODE 1 / 2
- *
- * This simple urldecode only operates until the first '\0' and requires the
- * data to exist all at once
- */
-/**
- * lws_urldecode() - like strncpy but with urldecoding
- *
- * \param string: output buffer
- * \param escaped: input buffer ('\0' terminated)
- * \param len: output buffer max length
- *
- * This is only useful for '\0' terminated strings
- *
- * Since urldecoding only shrinks the output string, it is possible to
- * do it in-place, ie, string == escaped
- *
- * Returns 0 if completed OK or nonzero for urldecode violation (non-hex chars
- * where hex required, etc)
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_urldecode(char *string, const char *escaped, int len);
-///@}
-/**
- * lws_return_http_status() - Return simple http status
- * \param wsi: Websocket instance (available from user callback)
- * \param code: Status index, eg, 404
- * \param html_body: User-readable HTML description < 1KB, or NULL
- *
- * Helper to report HTTP errors back to the client cleanly and
- * consistently
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_return_http_status(struct lws *wsi, unsigned int code,
- const char *html_body);
-
-/**
- * lws_http_redirect() - write http redirect out on wsi
- *
- * \param wsi: websocket connection
- * \param code: HTTP response code (eg, 301)
- * \param loc: where to redirect to
- * \param len: length of loc
- * \param p: pointer current position in buffer (updated as we write)
- * \param end: pointer to end of buffer
- *
- * Returns amount written, or < 0 indicating fatal write failure.
- */
-LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_http_redirect(struct lws *wsi, int code, const unsigned char *loc, int len,
- unsigned char **p, unsigned char *end);
-
-/**
- * lws_http_transaction_completed() - wait for new http transaction or close
- * \param wsi: websocket connection
- *
- * Returns 1 if the HTTP connection must close now
- * Returns 0 and resets connection to wait for new HTTP header /
- * transaction if possible
- */
-LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_http_transaction_completed(struct lws *wsi);
-///@}
-
-/*! \defgroup pur Sanitize / purify SQL and JSON helpers
- *
- * ##Sanitize / purify SQL and JSON helpers
- *
- * APIs for escaping untrusted JSON and SQL safely before use
- */
-//@{
-
-/**
- * lws_sql_purify() - like strncpy but with escaping for sql quotes
- *
- * \param escaped: output buffer
- * \param string: input buffer ('/0' terminated)
- * \param len: output buffer max length
- *
- * Because escaping expands the output string, it's not
- * possible to do it in-place, ie, with escaped == string
- */
-LWS_VISIBLE LWS_EXTERN const char *
-lws_sql_purify(char *escaped, const char *string, int len);
-
-/**
- * lws_json_purify() - like strncpy but with escaping for json chars
- *
- * \param escaped: output buffer
- * \param string: input buffer ('/0' terminated)
- * \param len: output buffer max length
- *
- * Because escaping expands the output string, it's not
- * possible to do it in-place, ie, with escaped == string
- */
-LWS_VISIBLE LWS_EXTERN const char *
-lws_json_purify(char *escaped, const char *string, int len);
-
-/**
- * lws_filename_purify_inplace() - replace scary filename chars with underscore
- *
- * \param filename: filename to be purified
- *
- * Replace scary characters in the filename (it should not be a path)
- * with underscore, so it's safe to use.
- */
-LWS_VISIBLE LWS_EXTERN void
-lws_filename_purify_inplace(char *filename);
-
-LWS_VISIBLE LWS_EXTERN int
-lws_plat_write_cert(struct lws_vhost *vhost, int is_key, int fd, void *buf,
- int len);
-LWS_VISIBLE LWS_EXTERN int
-lws_plat_write_file(const char *filename, void *buf, int len);
-
-LWS_VISIBLE LWS_EXTERN int
-lws_plat_read_file(const char *filename, void *buf, int len);
-
-LWS_VISIBLE LWS_EXTERN int
-lws_plat_recommended_rsa_bits(void);
-///@}
-
-/*! \defgroup uv libuv helpers
- *
- * ##libuv helpers
- *
- * APIs specific to libuv event loop itegration
- */
-///@{
-#ifdef LWS_WITH_LIBUV
-/*
- * Any direct libuv allocations in lws protocol handlers must participate in the
- * lws reference counting scheme. Two apis are provided:
- *
- * - lws_libuv_static_refcount_add(handle, context) to mark the handle with
- * a pointer to the context and increment the global uv object counter
- *
- * - lws_libuv_static_refcount_del() which should be used as the close callback
- * for your own libuv objects declared in the protocol scope.
- *
- * Using the apis allows lws to detach itself from a libuv loop completely
- * cleanly and at the moment all of its libuv objects have completed close.
- */
-
-LWS_VISIBLE LWS_EXTERN uv_loop_t *
-lws_uv_getloop(struct lws_context *context, int tsi);
-
-LWS_VISIBLE LWS_EXTERN void
-lws_libuv_static_refcount_add(uv_handle_t *, struct lws_context *context);
-
-LWS_VISIBLE LWS_EXTERN void
-lws_libuv_static_refcount_del(uv_handle_t *);
-
-#endif /* LWS_WITH_LIBUV */
-
-#if defined(LWS_WITH_ESP32)
-#define lws_libuv_static_refcount_add(_a, _b)
-#define lws_libuv_static_refcount_del NULL
-#endif
-///@}
-
-
-/*! \defgroup timeout Connection timeouts
-
- APIs related to setting connection timeouts
-*/
-//@{
-
-/*
- * NOTE: These public enums are part of the abi. If you want to add one,
- * add it at where specified so existing users are unaffected.
- */
-enum pending_timeout {
- NO_PENDING_TIMEOUT = 0,
- PENDING_TIMEOUT_AWAITING_PROXY_RESPONSE = 1,
- PENDING_TIMEOUT_AWAITING_CONNECT_RESPONSE = 2,
- PENDING_TIMEOUT_ESTABLISH_WITH_SERVER = 3,
- PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE = 4,
- PENDING_TIMEOUT_AWAITING_PING = 5,
- PENDING_TIMEOUT_CLOSE_ACK = 6,
- PENDING_TIMEOUT_UNUSED1 = 7,
- PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE = 8,
- PENDING_TIMEOUT_SSL_ACCEPT = 9,
- PENDING_TIMEOUT_HTTP_CONTENT = 10,
- PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND = 11,
- PENDING_FLUSH_STORED_SEND_BEFORE_CLOSE = 12,
- PENDING_TIMEOUT_SHUTDOWN_FLUSH = 13,
- PENDING_TIMEOUT_CGI = 14,
- PENDING_TIMEOUT_HTTP_KEEPALIVE_IDLE = 15,
- PENDING_TIMEOUT_WS_PONG_CHECK_SEND_PING = 16,
- PENDING_TIMEOUT_WS_PONG_CHECK_GET_PONG = 17,
- PENDING_TIMEOUT_CLIENT_ISSUE_PAYLOAD = 18,
- PENDING_TIMEOUT_AWAITING_SOCKS_GREETING_REPLY = 19,
- PENDING_TIMEOUT_AWAITING_SOCKS_CONNECT_REPLY = 20,
- PENDING_TIMEOUT_AWAITING_SOCKS_AUTH_REPLY = 21,
- PENDING_TIMEOUT_KILLED_BY_SSL_INFO = 22,
- PENDING_TIMEOUT_KILLED_BY_PARENT = 23,
- PENDING_TIMEOUT_CLOSE_SEND = 24,
- PENDING_TIMEOUT_HOLDING_AH = 25,
- PENDING_TIMEOUT_UDP_IDLE = 26,
- PENDING_TIMEOUT_CLIENT_CONN_IDLE = 27,
- PENDING_TIMEOUT_LAGGING = 28,
-
- /****** add new things just above ---^ ******/
-
- PENDING_TIMEOUT_USER_REASON_BASE = 1000
-};
-
-#define LWS_TO_KILL_ASYNC -1
-/**< If LWS_TO_KILL_ASYNC is given as the timeout sec in a lws_set_timeout()
- * call, then the connection is marked to be killed at the next timeout
- * check. This is how you should force-close the wsi being serviced if
- * you are doing it outside the callback (where you should close by nonzero
- * return).
- */
-#define LWS_TO_KILL_SYNC -2
-/**< If LWS_TO_KILL_SYNC is given as the timeout sec in a lws_set_timeout()
- * call, then the connection is closed before returning (which may delete
- * the wsi). This should only be used where the wsi being closed is not the
- * wsi currently being serviced.
- */
-/**
- * lws_set_timeout() - marks the wsi as subject to a timeout
- *
- * You will not need this unless you are doing something special
- *
- * \param wsi: Websocket connection instance
- * \param reason: timeout reason
- * \param secs: how many seconds. You may set to LWS_TO_KILL_ASYNC to
- * force the connection to timeout at the next opportunity, or
- * LWS_TO_KILL_SYNC to close it synchronously if you know the
- * wsi is not the one currently being serviced.
- */
-LWS_VISIBLE LWS_EXTERN void
-lws_set_timeout(struct lws *wsi, enum pending_timeout reason, int secs);
-
-#define LWS_SET_TIMER_USEC_CANCEL ((lws_usec_t)-1ll)
-#define LWS_USEC_PER_SEC (1000000ll)
-
-/**
- * lws_set_timer_usecs() - schedules a callback on the wsi in the future
- *
- * \param wsi: Websocket connection instance
- * \param usecs: LWS_SET_TIMER_USEC_CANCEL removes any existing scheduled
- * callback, otherwise number of microseconds in the future
- * the callback will occur at.
- *
- * NOTE: event loop support for this:
- *
- * default poll() loop: yes
- * libuv event loop: yes
- * libev: not implemented (patch welcome)
- * libevent: not implemented (patch welcome)
- *
- * After the deadline expires, the wsi will get a callback of type
- * LWS_CALLBACK_TIMER and the timer is exhausted. The deadline may be
- * continuously deferred by further calls to lws_set_timer_usecs() with a later
- * deadline, or cancelled by lws_set_timer_usecs(wsi, -1).
- *
- * If the timer should repeat, lws_set_timer_usecs() must be called again from
- * LWS_CALLBACK_TIMER.
- *
- * Accuracy depends on the platform and the load on the event loop or system...
- * all that's guaranteed is the callback will come after the requested wait
- * period.
- */
-LWS_VISIBLE LWS_EXTERN void
-lws_set_timer_usecs(struct lws *wsi, lws_usec_t usecs);
-
-/*
- * lws_timed_callback_vh_protocol() - calls back a protocol on a vhost after
- * the specified delay
- *
- * \param vh: the vhost to call back
- * \param protocol: the protocol to call back
- * \param reason: callback reason
- * \param secs: how many seconds in the future to do the callback. Set to
- * -1 to cancel the timer callback.
- *
- * Callback the specified protocol with a fake wsi pointing to the specified
- * vhost and protocol, with the specified reason, at the specified time in the
- * future.
- *
- * Returns 0 if OK.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_timed_callback_vh_protocol(struct lws_vhost *vh,
- const struct lws_protocols *prot,
- int reason, int secs);
-///@}
-
-/*! \defgroup sending-data Sending data
-
- APIs related to writing data on a connection
-*/
-//@{
-#if !defined(LWS_SIZEOFPTR)
-#define LWS_SIZEOFPTR ((int)sizeof (void *))
-#endif
-
-#if defined(__x86_64__)
-#define _LWS_PAD_SIZE 16 /* Intel recommended for best performance */
-#else
-#define _LWS_PAD_SIZE LWS_SIZEOFPTR /* Size of a pointer on the target arch */
-#endif
-#define _LWS_PAD(n) (((n) % _LWS_PAD_SIZE) ? \
- ((n) + (_LWS_PAD_SIZE - ((n) % _LWS_PAD_SIZE))) : (n))
-/* last 2 is for lws-meta */
-#define LWS_PRE _LWS_PAD(4 + 10 + 2)
-/* used prior to 1.7 and retained for backward compatibility */
-#define LWS_SEND_BUFFER_PRE_PADDING LWS_PRE
-#define LWS_SEND_BUFFER_POST_PADDING 0
-
-#define LWS_WRITE_RAW LWS_WRITE_HTTP
-
-/*
- * NOTE: These public enums are part of the abi. If you want to add one,
- * add it at where specified so existing users are unaffected.
- */
-enum lws_write_protocol {
- LWS_WRITE_TEXT = 0,
- /**< Send a ws TEXT message,the pointer must have LWS_PRE valid
- * memory behind it. The receiver expects only valid utf-8 in the
- * payload */
- LWS_WRITE_BINARY = 1,
- /**< Send a ws BINARY message, the pointer must have LWS_PRE valid
- * memory behind it. Any sequence of bytes is valid */
- LWS_WRITE_CONTINUATION = 2,
- /**< Continue a previous ws message, the pointer must have LWS_PRE valid
- * memory behind it */
- LWS_WRITE_HTTP = 3,
- /**< Send HTTP content */
-
- /* LWS_WRITE_CLOSE is handled by lws_close_reason() */
- LWS_WRITE_PING = 5,
- LWS_WRITE_PONG = 6,
-
- /* Same as write_http but we know this write ends the transaction */
- LWS_WRITE_HTTP_FINAL = 7,
-
- /* HTTP2 */
-
- LWS_WRITE_HTTP_HEADERS = 8,
- /**< Send http headers (http2 encodes this payload and LWS_WRITE_HTTP
- * payload differently, http 1.x links also handle this correctly. so
- * to be compatible with both in the future,header response part should
- * be sent using this regardless of http version expected)
- */
- LWS_WRITE_HTTP_HEADERS_CONTINUATION = 9,
- /**< Continuation of http/2 headers
- */
-
- /****** add new things just above ---^ ******/
-
- /* flags */
-
- LWS_WRITE_NO_FIN = 0x40,
- /**< This part of the message is not the end of the message */
-
- LWS_WRITE_H2_STREAM_END = 0x80,
- /**< Flag indicates this packet should go out with STREAM_END if h2
- * STREAM_END is allowed on DATA or HEADERS.
- */
-
- LWS_WRITE_CLIENT_IGNORE_XOR_MASK = 0x80
- /**< client packet payload goes out on wire unmunged
- * only useful for security tests since normal servers cannot
- * decode the content if used */
-};
-
-/* used with LWS_CALLBACK_CHILD_WRITE_VIA_PARENT */
-
-struct lws_write_passthru {
- struct lws *wsi;
- unsigned char *buf;
- size_t len;
- enum lws_write_protocol wp;
-};
-
-
-/**
- * lws_write() - Apply protocol then write data to client
- * \param wsi: Websocket instance (available from user callback)
- * \param buf: The data to send. For data being sent on a websocket
- * connection (ie, not default http), this buffer MUST have
- * LWS_PRE bytes valid BEFORE the pointer.
- * This is so the protocol header data can be added in-situ.
- * \param len: Count of the data bytes in the payload starting from buf
- * \param protocol: Use LWS_WRITE_HTTP to reply to an http connection, and one
- * of LWS_WRITE_BINARY or LWS_WRITE_TEXT to send appropriate
- * data on a websockets connection. Remember to allow the extra
- * bytes before and after buf if LWS_WRITE_BINARY or LWS_WRITE_TEXT
- * are used.
- *
- * This function provides the way to issue data back to the client
- * for both http and websocket protocols.
- *
- * IMPORTANT NOTICE!
- *
- * When sending with websocket protocol
- *
- * LWS_WRITE_TEXT,
- * LWS_WRITE_BINARY,
- * LWS_WRITE_CONTINUATION,
- * LWS_WRITE_PING,
- * LWS_WRITE_PONG
- *
- * the send buffer has to have LWS_PRE bytes valid BEFORE
- * the buffer pointer you pass to lws_write().
- *
- * This allows us to add protocol info before and after the data, and send as
- * one packet on the network without payload copying, for maximum efficiency.
- *
- * So for example you need this kind of code to use lws_write with a
- * 128-byte payload
- *
- * char buf[LWS_PRE + 128];
- *
- * // fill your part of the buffer... for example here it's all zeros
- * memset(&buf[LWS_PRE], 0, 128);
- *
- * lws_write(wsi, &buf[LWS_PRE], 128, LWS_WRITE_TEXT);
- *
- * When sending HTTP, with
- *
- * LWS_WRITE_HTTP,
- * LWS_WRITE_HTTP_HEADERS
- * LWS_WRITE_HTTP_FINAL
- *
- * there is no protocol data prepended, and don't need to take care about the
- * LWS_PRE bytes valid before the buffer pointer.
- *
- * LWS_PRE is at least the frame nonce + 2 header + 8 length
- * LWS_SEND_BUFFER_POST_PADDING is deprecated, it's now 0 and can be left off.
- * The example apps no longer use it.
- *
- * Pad LWS_PRE to the CPU word size, so that word references
- * to the address immediately after the padding won't cause an unaligned access
- * error. Sometimes for performance reasons the recommended padding is even
- * larger than sizeof(void *).
- *
- * In the case of sending using websocket protocol, be sure to allocate
- * valid storage before and after buf as explained above. This scheme
- * allows maximum efficiency of sending data and protocol in a single
- * packet while not burdening the user code with any protocol knowledge.
- *
- * Return may be -1 for a fatal error needing connection close, or the
- * number of bytes sent.
- *
- * Truncated Writes
- * ================
- *
- * The OS may not accept everything you asked to write on the connection.
- *
- * Posix defines POLLOUT indication from poll() to show that the connection
- * will accept more write data, but it doesn't specifiy how much. It may just
- * accept one byte of whatever you wanted to send.
- *
- * LWS will buffer the remainder automatically, and send it out autonomously.
- *
- * During that time, WRITABLE callbacks will be suppressed.
- *
- * This is to handle corner cases where unexpectedly the OS refuses what we
- * usually expect it to accept. You should try to send in chunks that are
- * almost always accepted in order to avoid the inefficiency of the buffering.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_write(struct lws *wsi, unsigned char *buf, size_t len,
- enum lws_write_protocol protocol);
-
-/* helper for case where buffer may be const */
-#define lws_write_http(wsi, buf, len) \
- lws_write(wsi, (unsigned char *)(buf), len, LWS_WRITE_HTTP)
-
-/* helper for multi-frame ws message flags */
-static LWS_INLINE int
-lws_write_ws_flags(int initial, int is_start, int is_end)
-{
- int r;
-
- if (is_start)
- r = initial;
- else
- r = LWS_WRITE_CONTINUATION;
-
- if (!is_end)
- r |= LWS_WRITE_NO_FIN;
-
- return r;
-}
-///@}
-
-/** \defgroup callback-when-writeable Callback when writeable
- *
- * ##Callback When Writeable
- *
- * lws can only write data on a connection when it is able to accept more
- * data without blocking.
- *
- * So a basic requirement is we should only use the lws_write() apis when the
- * connection we want to write on says that he can accept more data.
- *
- * When lws cannot complete your send at the time, it will buffer the data
- * and send it in the background, suppressing any further WRITEABLE callbacks
- * on that connection until it completes. So it is important to write new
- * things in a new writeable callback.
- *
- * These apis reflect the various ways we can indicate we would like to be
- * called back when one or more connections is writeable.
- */
-///@{
-
-/**
- * lws_callback_on_writable() - Request a callback when this socket
- * becomes able to be written to without
- * blocking
- *
- * \param wsi: Websocket connection instance to get callback for
- *
- * - Which: only this wsi
- * - When: when the individual connection becomes writeable
- * - What: LWS_CALLBACK_*_WRITEABLE
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_callback_on_writable(struct lws *wsi);
-
-/**
- * lws_callback_on_writable_all_protocol() - Request a callback for all
- * connections using the given protocol when it
- * becomes possible to write to each socket without
- * blocking in turn.
- *
- * \param context: lws_context
- * \param protocol: Protocol whose connections will get callbacks
- *
- * - Which: connections using this protocol on ANY VHOST
- * - When: when the individual connection becomes writeable
- * - What: LWS_CALLBACK_*_WRITEABLE
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_callback_on_writable_all_protocol(const struct lws_context *context,
- const struct lws_protocols *protocol);
-
-/**
- * lws_callback_on_writable_all_protocol_vhost() - Request a callback for
- * all connections on same vhost using the given protocol
- * when it becomes possible to write to each socket without
- * blocking in turn.
- *
- * \param vhost: Only consider connections on this lws_vhost
- * \param protocol: Protocol whose connections will get callbacks
- *
- * - Which: connections using this protocol on GIVEN VHOST ONLY
- * - When: when the individual connection becomes writeable
- * - What: LWS_CALLBACK_*_WRITEABLE
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_callback_on_writable_all_protocol_vhost(const struct lws_vhost *vhost,
- const struct lws_protocols *protocol);
-
-/**
- * lws_callback_all_protocol() - Callback all connections using
- * the given protocol with the given reason
- *
- * \param context: lws_context
- * \param protocol: Protocol whose connections will get callbacks
- * \param reason: Callback reason index
- *
- * - Which: connections using this protocol on ALL VHOSTS
- * - When: before returning
- * - What: reason
- *
- * This isn't normally what you want... normally any update of connection-
- * specific information can wait until a network-related callback like rx,
- * writable, or close.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_callback_all_protocol(struct lws_context *context,
- const struct lws_protocols *protocol, int reason);
-
-/**
- * lws_callback_all_protocol_vhost() - Callback all connections using
- * the given protocol with the given reason. This is
- * deprecated since v2.4: use lws_callback_all_protocol_vhost_args
- *
- * \param vh: Vhost whose connections will get callbacks
- * \param protocol: Which protocol to match. NULL means all.
- * \param reason: Callback reason index
- *
- * - Which: connections using this protocol on GIVEN VHOST ONLY
- * - When: now
- * - What: reason
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_callback_all_protocol_vhost(struct lws_vhost *vh,
- const struct lws_protocols *protocol, int reason)
-LWS_WARN_DEPRECATED;
-
-/**
- * lws_callback_all_protocol_vhost_args() - Callback all connections using
- * the given protocol with the given reason and args
- *
- * \param vh: Vhost whose connections will get callbacks
- * \param protocol: Which protocol to match. NULL means all.
- * \param reason: Callback reason index
- * \param argp: Callback "in" parameter
- * \param len: Callback "len" parameter
- *
- * - Which: connections using this protocol on GIVEN VHOST ONLY
- * - When: now
- * - What: reason
- */
-LWS_VISIBLE int
-lws_callback_all_protocol_vhost_args(struct lws_vhost *vh,
- const struct lws_protocols *protocol, int reason,
- void *argp, size_t len);
-
-/**
- * lws_callback_vhost_protocols() - Callback all protocols enabled on a vhost
- * with the given reason
- *
- * \param wsi: wsi whose vhost will get callbacks
- * \param reason: Callback reason index
- * \param in: in argument to callback
- * \param len: len argument to callback
- *
- * - Which: connections using this protocol on same VHOST as wsi ONLY
- * - When: now
- * - What: reason
- *
- * This is deprecated since v2.5, use lws_callback_vhost_protocols_vhost()
- * which takes the pointer to the vhost directly without using or needing the
- * wsi.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_callback_vhost_protocols(struct lws *wsi, int reason, void *in, int len)
-LWS_WARN_DEPRECATED;
-
-/**
- * lws_callback_vhost_protocols_vhost() - Callback all protocols enabled on a vhost
- * with the given reason
- *
- * \param vh: vhost that will get callbacks
- * \param reason: Callback reason index
- * \param in: in argument to callback
- * \param len: len argument to callback
- *
- * - Which: connections using this protocol on same VHOST as wsi ONLY
- * - When: now
- * - What: reason
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_callback_vhost_protocols_vhost(struct lws_vhost *vh, int reason, void *in,
- size_t len);
-
-LWS_VISIBLE LWS_EXTERN int
-lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
- void *user, void *in, size_t len);
-
-/**
- * lws_get_socket_fd() - returns the socket file descriptor
- *
- * This is needed to use sendto() on UDP raw sockets
- *
- * \param wsi: Websocket connection instance
- */
-LWS_VISIBLE LWS_EXTERN lws_sockfd_type
-lws_get_socket_fd(struct lws *wsi);
-
-/**
- * lws_get_peer_write_allowance() - get the amount of data writeable to peer
- * if known
- *
- * \param wsi: Websocket connection instance
- *
- * if the protocol does not have any guidance, returns -1. Currently only
- * http2 connections get send window information from this API. But your code
- * should use it so it can work properly with any protocol.
- *
- * If nonzero return is the amount of payload data the peer or intermediary has
- * reported it has buffer space for. That has NO relationship with the amount
- * of buffer space your OS can accept on this connection for a write action.
- *
- * This number represents the maximum you could send to the peer or intermediary
- * on this connection right now without the protocol complaining.
- *
- * lws manages accounting for send window updates and payload writes
- * automatically, so this number reflects the situation at the peer or
- * intermediary dynamically.
- */
-LWS_VISIBLE LWS_EXTERN lws_fileofs_t
-lws_get_peer_write_allowance(struct lws *wsi);
-///@}
-
-enum {
- /*
- * Flags for enable and disable rxflow with reason bitmap and with
- * backwards-compatible single bool
- */
- LWS_RXFLOW_REASON_USER_BOOL = (1 << 0),
- LWS_RXFLOW_REASON_HTTP_RXBUFFER = (1 << 6),
- LWS_RXFLOW_REASON_H2_PPS_PENDING = (1 << 7),
-
- LWS_RXFLOW_REASON_APPLIES = (1 << 14),
- LWS_RXFLOW_REASON_APPLIES_ENABLE_BIT = (1 << 13),
- LWS_RXFLOW_REASON_APPLIES_ENABLE = LWS_RXFLOW_REASON_APPLIES |
- LWS_RXFLOW_REASON_APPLIES_ENABLE_BIT,
- LWS_RXFLOW_REASON_APPLIES_DISABLE = LWS_RXFLOW_REASON_APPLIES,
- LWS_RXFLOW_REASON_FLAG_PROCESS_NOW = (1 << 12),
-
-};
-
-/**
- * lws_rx_flow_control() - Enable and disable socket servicing for
- * received packets.
- *
- * If the output side of a server process becomes choked, this allows flow
- * control for the input side.
- *
- * \param wsi: Websocket connection instance to get callback for
- * \param enable: 0 = disable read servicing for this connection, 1 = enable
- *
- * If you need more than one additive reason for rxflow control, you can give
- * iLWS_RXFLOW_REASON_APPLIES_ENABLE or _DISABLE together with one or more of
- * b5..b0 set to idicate which bits to enable or disable. If any bits are
- * enabled, rx on the connection is suppressed.
- *
- * LWS_RXFLOW_REASON_FLAG_PROCESS_NOW flag may also be given to force any change
- * in rxflowbstatus to benapplied immediately, this should be used when you are
- * changing a wsi flow control state from outside a callback on that wsi.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_rx_flow_control(struct lws *wsi, int enable);
-
-/**
- * lws_rx_flow_allow_all_protocol() - Allow all connections with this protocol to receive
- *
- * When the user server code realizes it can accept more input, it can
- * call this to have the RX flow restriction removed from all connections using
- * the given protocol.
- * \param context: lws_context
- * \param protocol: all connections using this protocol will be allowed to receive
- */
-LWS_VISIBLE LWS_EXTERN void
-lws_rx_flow_allow_all_protocol(const struct lws_context *context,
- const struct lws_protocols *protocol);
-
-/**
- * lws_remaining_packet_payload() - Bytes to come before "overall"
- * rx fragment is complete
- * \param wsi: Websocket instance (available from user callback)
- *
- * This tracks how many bytes are left in the current ws fragment, according
- * to the ws length given in the fragment header.
- *
- * If the message was in a single fragment, and there is no compression, this
- * is the same as "how much data is left to read for this message".
- *
- * However, if the message is being sent in multiple fragments, this will
- * reflect the unread amount of the current **fragment**, not the message. With
- * ws, it is legal to not know the length of the message before it completes.
- *
- * Additionally if the message is sent via the negotiated permessage-deflate
- * extension, this number only tells the amount of **compressed** data left to
- * be read, since that is the only information available at the ws layer.
- */
-LWS_VISIBLE LWS_EXTERN size_t
-lws_remaining_packet_payload(struct lws *wsi);
-
-
-/** \defgroup sock-adopt Socket adoption helpers
- * ##Socket adoption helpers
- *
- * When integrating with an external app with its own event loop, these can
- * be used to accept connections from someone else's listening socket.
- *
- * When using lws own event loop, these are not needed.
- */
-///@{
-
-/**
- * lws_adopt_socket() - adopt foreign socket as if listen socket accepted it
- * for the default vhost of context.
- *
- * \param context: lws context
- * \param accept_fd: fd of already-accepted socket to adopt
- *
- * Either returns new wsi bound to accept_fd, or closes accept_fd and
- * returns NULL, having cleaned up any new wsi pieces.
- *
- * LWS adopts the socket in http serving mode, it's ready to accept an upgrade
- * to ws or just serve http.
- */
-LWS_VISIBLE LWS_EXTERN struct lws *
-lws_adopt_socket(struct lws_context *context, lws_sockfd_type accept_fd);
-/**
- * lws_adopt_socket_vhost() - adopt foreign socket as if listen socket accepted it
- * for vhost
- *
- * \param vh: lws vhost
- * \param accept_fd: fd of already-accepted socket to adopt
- *
- * Either returns new wsi bound to accept_fd, or closes accept_fd and
- * returns NULL, having cleaned up any new wsi pieces.
- *
- * LWS adopts the socket in http serving mode, it's ready to accept an upgrade
- * to ws or just serve http.
- */
-LWS_VISIBLE LWS_EXTERN struct lws *
-lws_adopt_socket_vhost(struct lws_vhost *vh, lws_sockfd_type accept_fd);
-
-typedef enum {
- LWS_ADOPT_RAW_FILE_DESC = 0, /* convenience constant */
- LWS_ADOPT_HTTP = 1, /* flag: absent implies RAW */
- LWS_ADOPT_SOCKET = 2, /* flag: absent implies file descr */
- LWS_ADOPT_ALLOW_SSL = 4, /* flag: if set requires LWS_ADOPT_SOCKET */
- LWS_ADOPT_WS_PARENTIO = 8, /* flag: ws mode parent handles IO
- * if given must be only flag
- * wsi put directly into ws mode */
- LWS_ADOPT_FLAG_UDP = 16, /* flag: socket is UDP */
-
- LWS_ADOPT_RAW_SOCKET_UDP = LWS_ADOPT_SOCKET | LWS_ADOPT_FLAG_UDP,
-} lws_adoption_type;
-
-typedef union {
- lws_sockfd_type sockfd;
- lws_filefd_type filefd;
-} lws_sock_file_fd_type;
-
-#if !defined(LWS_WITH_ESP32)
-struct lws_udp {
- struct sockaddr sa;
- socklen_t salen;
-
- struct sockaddr sa_pending;
- socklen_t salen_pending;
-};
-#endif
-
-/*
-* lws_adopt_descriptor_vhost() - adopt foreign socket or file descriptor
-* if socket descriptor, should already have been accepted from listen socket
-*
-* \param vhost: lws vhost
-* \param type: OR-ed combinations of lws_adoption_type flags
-* \param fd: union with either .sockfd or .filefd set
-* \param vh_prot_name: NULL or vh protocol name to bind raw connection to
-* \param parent: NULL or struct lws to attach new_wsi to as a child
-*
-* Either returns new wsi bound to accept_fd, or closes accept_fd and
-* returns NULL, having cleaned up any new wsi pieces.
-*
-* If LWS_ADOPT_SOCKET is set, LWS adopts the socket in http serving mode, it's
-* ready to accept an upgrade to ws or just serve http.
-*
-* parent may be NULL, if given it should be an existing wsi that will become the
-* parent of the new wsi created by this call.
-*/
-LWS_VISIBLE LWS_EXTERN struct lws *
-lws_adopt_descriptor_vhost(struct lws_vhost *vh, lws_adoption_type type,
- lws_sock_file_fd_type fd, const char *vh_prot_name,
- struct lws *parent);
-
-/**
- * lws_adopt_socket_readbuf() - adopt foreign socket and first rx as if listen socket accepted it
- * for the default vhost of context.
- * \param context: lws context
- * \param accept_fd: fd of already-accepted socket to adopt
- * \param readbuf: NULL or pointer to data that must be drained before reading from
- * accept_fd
- * \param len: The length of the data held at \param readbuf
- *
- * Either returns new wsi bound to accept_fd, or closes accept_fd and
- * returns NULL, having cleaned up any new wsi pieces.
- *
- * LWS adopts the socket in http serving mode, it's ready to accept an upgrade
- * to ws or just serve http.
- *
- * If your external code did not already read from the socket, you can use
- * lws_adopt_socket() instead.
- *
- * This api is guaranteed to use the data at \param readbuf first, before reading from
- * the socket.
- *
- * readbuf is limited to the size of the ah rx buf, currently 2048 bytes.
- */
-LWS_VISIBLE LWS_EXTERN struct lws *
-lws_adopt_socket_readbuf(struct lws_context *context, lws_sockfd_type accept_fd,
- const char *readbuf, size_t len);
-/**
- * lws_adopt_socket_vhost_readbuf() - adopt foreign socket and first rx as if listen socket
- * accepted it for vhost.
- * \param vhost: lws vhost
- * \param accept_fd: fd of already-accepted socket to adopt
- * \param readbuf: NULL or pointer to data that must be drained before reading from
- * accept_fd
- * \param len: The length of the data held at \param readbuf
- *
- * Either returns new wsi bound to accept_fd, or closes accept_fd and
- * returns NULL, having cleaned up any new wsi pieces.
- *
- * LWS adopts the socket in http serving mode, it's ready to accept an upgrade
- * to ws or just serve http.
- *
- * If your external code did not already read from the socket, you can use
- * lws_adopt_socket() instead.
- *
- * This api is guaranteed to use the data at \param readbuf first, before reading from
- * the socket.
- *
- * readbuf is limited to the size of the ah rx buf, currently 2048 bytes.
- */
-LWS_VISIBLE LWS_EXTERN struct lws *
-lws_adopt_socket_vhost_readbuf(struct lws_vhost *vhost, lws_sockfd_type accept_fd,
- const char *readbuf, size_t len);
-
-#define LWS_CAUDP_BIND 1
-
-/**
- * lws_create_adopt_udp() - create, bind and adopt a UDP socket
- *
- * \param vhost: lws vhost
- * \param port: UDP port to bind to, -1 means unbound
- * \param flags: 0 or LWS_CAUDP_NO_BIND
- * \param protocol_name: Name of protocol on vhost to bind wsi to
- * \param parent_wsi: NULL or parent wsi new wsi will be a child of
- *
- * Either returns new wsi bound to accept_fd, or closes accept_fd and
- * returns NULL, having cleaned up any new wsi pieces.
- * */
-LWS_VISIBLE LWS_EXTERN struct lws *
-lws_create_adopt_udp(struct lws_vhost *vhost, int port, int flags,
- const char *protocol_name, struct lws *parent_wsi);
-///@}
-
-/** \defgroup net Network related helper APIs
- * ##Network related helper APIs
- *
- * These wrap miscellaneous useful network-related functions
- */
-///@{
-
-/**
- * lws_canonical_hostname() - returns this host's hostname
- *
- * This is typically used by client code to fill in the host parameter
- * when making a client connection. You can only call it after the context
- * has been created.
- *
- * \param context: Websocket context
- */
-LWS_VISIBLE LWS_EXTERN const char * LWS_WARN_UNUSED_RESULT
-lws_canonical_hostname(struct lws_context *context);
-
-/**
- * lws_get_peer_addresses() - Get client address information
- * \param wsi: Local struct lws associated with
- * \param fd: Connection socket descriptor
- * \param name: Buffer to take client address name
- * \param name_len: Length of client address name buffer
- * \param rip: Buffer to take client address IP dotted quad
- * \param rip_len: Length of client address IP buffer
- *
- * This function fills in name and rip with the name and IP of
- * the client connected with socket descriptor fd. Names may be
- * truncated if there is not enough room. If either cannot be
- * determined, they will be returned as valid zero-length strings.
- */
-LWS_VISIBLE LWS_EXTERN void
-lws_get_peer_addresses(struct lws *wsi, lws_sockfd_type fd, char *name,
- int name_len, char *rip, int rip_len);
-
-/**
- * lws_get_peer_simple() - Get client address information without RDNS
- *
- * \param wsi: Local struct lws associated with
- * \param name: Buffer to take client address name
- * \param namelen: Length of client address name buffer
- *
- * This provides a 123.123.123.123 type IP address in name from the
- * peer that has connected to wsi
- */
-LWS_VISIBLE LWS_EXTERN const char *
-lws_get_peer_simple(struct lws *wsi, char *name, int namelen);
-
-
-#define LWS_ITOSA_NOT_EXIST -1
-#define LWS_ITOSA_NOT_USABLE -2
-#define LWS_ITOSA_USABLE 0
-#if !defined(LWS_WITH_ESP32)
-/**
- * lws_interface_to_sa() - Convert interface name or IP to sockaddr struct
- *
- * \param ipv6: Allow IPV6 addresses
- * \param ifname: Interface name or IP
- * \param addr: struct sockaddr_in * to be written
- * \param addrlen: Length of addr
- *
- * This converts a textual network interface name to a sockaddr usable by
- * other network functions.
- *
- * If the network interface doesn't exist, it will return LWS_ITOSA_NOT_EXIST.
- *
- * If the network interface is not usable, eg ethernet cable is removed, it
- * may logically exist but not have any IP address. As such it will return
- * LWS_ITOSA_NOT_USABLE.
- *
- * If the network interface exists and is usable, it will return
- * LWS_ITOSA_USABLE.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_interface_to_sa(int ipv6, const char *ifname, struct sockaddr_in *addr,
- size_t addrlen);
-///@}
-#endif
-
-/** \defgroup misc Miscellaneous APIs
-* ##Miscellaneous APIs
-*
-* Various APIs outside of other categories
-*/
-///@{
-
-/**
- * lws_start_foreach_ll(): linkedlist iterator helper start
- *
- * \param type: type of iteration, eg, struct xyz *
- * \param it: iterator var name to create
- * \param start: start of list
- *
- * This helper creates an iterator and starts a while (it) {
- * loop. The iterator runs through the linked list starting at start and
- * ends when it gets a NULL.
- * The while loop should be terminated using lws_start_foreach_ll().
- */
-#define lws_start_foreach_ll(type, it, start)\
-{ \
- type it = start; \
- while (it) {
-
-/**
- * lws_end_foreach_ll(): linkedlist iterator helper end
- *
- * \param it: same iterator var name given when starting
- * \param nxt: member name in the iterator pointing to next list element
- *
- * This helper is the partner for lws_start_foreach_ll() that ends the
- * while loop.
- */
-
-#define lws_end_foreach_ll(it, nxt) \
- it = it->nxt; \
- } \
-}
-
-/**
- * lws_start_foreach_llp(): linkedlist pointer iterator helper start
- *
- * \param type: type of iteration, eg, struct xyz **
- * \param it: iterator var name to create
- * \param start: start of list
- *
- * This helper creates an iterator and starts a while (it) {
- * loop. The iterator runs through the linked list starting at the
- * address of start and ends when it gets a NULL.
- * The while loop should be terminated using lws_start_foreach_llp().
- *
- * This helper variant iterates using a pointer to the previous linked-list
- * element. That allows you to easily delete list members by rewriting the
- * previous pointer to the element's next pointer.
- */
-#define lws_start_foreach_llp(type, it, start)\
-{ \
- type it = &(start); \
- while (*(it)) {
-
-#define lws_start_foreach_llp_safe(type, it, start, nxt)\
-{ \
- type it = &(start); \
- type next; \
- while (*(it)) { \
- next = &((*(it))->nxt); \
-
-/**
- * lws_end_foreach_llp(): linkedlist pointer iterator helper end
- *
- * \param it: same iterator var name given when starting
- * \param nxt: member name in the iterator pointing to next list element
- *
- * This helper is the partner for lws_start_foreach_llp() that ends the
- * while loop.
- */
-
-#define lws_end_foreach_llp(it, nxt) \
- it = &(*(it))->nxt; \
- } \
-}
-
-#define lws_end_foreach_llp_safe(it) \
- it = next; \
- } \
-}
-
-#define lws_ll_fwd_insert(\
- ___new_object, /* pointer to new object */ \
- ___m_list, /* member for next list object ptr */ \
- ___list_head /* list head */ \
- ) {\
- ___new_object->___m_list = ___list_head; \
- ___list_head = ___new_object; \
- }
-
-#define lws_ll_fwd_remove(\
- ___type, /* type of listed object */ \
- ___m_list, /* member for next list object ptr */ \
- ___target, /* object to remove from list */ \
- ___list_head /* list head */ \
- ) { \
- lws_start_foreach_llp(___type **, ___ppss, ___list_head) { \
- if (*___ppss == ___target) { \
- *___ppss = ___target->___m_list; \
- break; \
- } \
- } lws_end_foreach_llp(___ppss, ___m_list); \
- }
-
-/*
- * doubly linked-list
- */
-
-struct lws_dll { /* abstract */
- struct lws_dll *prev;
- struct lws_dll *next;
-};
-
-/*
- * these all point to the composed list objects... you have to use the
- * lws_container_of() helper to recover the start of the containing struct
- */
-
-LWS_VISIBLE LWS_EXTERN void
-lws_dll_add_front(struct lws_dll *d, struct lws_dll *phead);
-
-LWS_VISIBLE LWS_EXTERN void
-lws_dll_remove(struct lws_dll *d);
-
-struct lws_dll_lws { /* typed as struct lws * */
- struct lws_dll_lws *prev;
- struct lws_dll_lws *next;
-};
-
-#define lws_dll_is_null(___dll) (!(___dll)->prev && !(___dll)->next)
-
-static LWS_INLINE void
-lws_dll_lws_add_front(struct lws_dll_lws *_a, struct lws_dll_lws *_head)
-{
- lws_dll_add_front((struct lws_dll *)_a, (struct lws_dll *)_head);
-}
-
-static LWS_INLINE void
-lws_dll_lws_remove(struct lws_dll_lws *_a)
-{
- lws_dll_remove((struct lws_dll *)_a);
-}
-
-/*
- * these are safe against the current container object getting deleted,
- * since the hold his next in a temp and go to that next. ___tmp is
- * the temp.
- */
-
-#define lws_start_foreach_dll_safe(___type, ___it, ___tmp, ___start) \
-{ \
- ___type ___it = ___start; \
- while (___it) { \
- ___type ___tmp = (___it)->next;
-
-#define lws_end_foreach_dll_safe(___it, ___tmp) \
- ___it = ___tmp; \
- } \
-}
-
-#define lws_start_foreach_dll(___type, ___it, ___start) \
-{ \
- ___type ___it = ___start; \
- while (___it) {
-
-#define lws_end_foreach_dll(___it) \
- ___it = (___it)->next; \
- } \
-}
-
-struct lws_buflist;
-
-/**
- * lws_buflist_append_segment(): add buffer to buflist at head
- *
- * \param head: list head
- * \param buf: buffer to stash
- * \param len: length of buffer to stash
- *
- * Returns -1 on OOM, 1 if this was the first segment on the list, and 0 if
- * it was a subsequent segment.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_buflist_append_segment(struct lws_buflist **head, const uint8_t *buf,
- size_t len);
-/**
- * lws_buflist_next_segment_len(): number of bytes left in current segment
- *
- * \param head: list head
- * \param buf: if non-NULL, *buf is written with the address of the start of
- * the remaining data in the segment
- *
- * Returns the number of bytes left in the current segment. 0 indicates
- * that the buflist is empty (there are no segments on the buflist).
- */
-LWS_VISIBLE LWS_EXTERN size_t
-lws_buflist_next_segment_len(struct lws_buflist **head, uint8_t **buf);
-/**
- * lws_buflist_use_segment(): remove len bytes from the current segment
- *
- * \param head: list head
- * \param len: number of bytes to mark as used
- *
- * If len is less than the remaining length of the current segment, the position
- * in the current segment is simply advanced and it returns.
- *
- * If len uses up the remaining length of the current segment, then the segment
- * is deleted and the list head moves to the next segment if any.
- *
- * Returns the number of bytes left in the current segment. 0 indicates
- * that the buflist is empty (there are no segments on the buflist).
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_buflist_use_segment(struct lws_buflist **head, size_t len);
-/**
- * lws_buflist_destroy_all_segments(): free all segments on the list
- *
- * \param head: list head
- *
- * This frees everything on the list unconditionally. *head is always
- * NULL after this.
- */
-LWS_VISIBLE LWS_EXTERN void
-lws_buflist_destroy_all_segments(struct lws_buflist **head);
-
-void
-lws_buflist_describe(struct lws_buflist **head, void *id);
-
-/**
- * lws_ptr_diff(): helper to report distance between pointers as an int
- *
- * \param head: the pointer with the larger address
- * \param tail: the pointer with the smaller address
- *
- * This helper gives you an int representing the number of bytes further
- * forward the first pointer is compared to the second pointer.
- */
-#define lws_ptr_diff(head, tail) \
- ((int)((char *)(head) - (char *)(tail)))
-
-/**
- * lws_snprintf(): snprintf that truncates the returned length too
- *
- * \param str: destination buffer
- * \param size: bytes left in destination buffer
- * \param format: format string
- * \param ...: args for format
- *
- * This lets you correctly truncate buffers by concatenating lengths, if you
- * reach the limit the reported length doesn't exceed the limit.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_snprintf(char *str, size_t size, const char *format, ...) LWS_FORMAT(3);
-
-/**
- * lws_strncpy(): strncpy that guarantees NUL on truncated copy
- *
- * \param dest: destination buffer
- * \param src: source buffer
- * \param size: bytes left in destination buffer
- *
- * This lets you correctly truncate buffers by concatenating lengths, if you
- * reach the limit the reported length doesn't exceed the limit.
- */
-LWS_VISIBLE LWS_EXTERN char *
-lws_strncpy(char *dest, const char *src, size_t size);
-
-/**
- * lws_get_random(): fill a buffer with platform random data
- *
- * \param context: the lws context
- * \param buf: buffer to fill
- * \param len: how much to fill
- *
- * This is intended to be called from the LWS_CALLBACK_RECEIVE callback if
- * it's interested to see if the frame it's dealing with was sent in binary
- * mode.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_get_random(struct lws_context *context, void *buf, int len);
-/**
- * lws_daemonize(): make current process run in the background
- *
- * \param _lock_path: the filepath to write the lock file
- *
- * Spawn lws as a background process, taking care of various things
- */
-LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_daemonize(const char *_lock_path);
-/**
- * lws_get_library_version(): return string describing the version of lws
- *
- * On unix, also includes the git describe
- */
-LWS_VISIBLE LWS_EXTERN const char * LWS_WARN_UNUSED_RESULT
-lws_get_library_version(void);
-
-/**
- * lws_wsi_user() - get the user data associated with the connection
- * \param wsi: lws connection
- *
- * Not normally needed since it's passed into the callback
- */
-LWS_VISIBLE LWS_EXTERN void *
-lws_wsi_user(struct lws *wsi);
-
-/**
- * lws_wsi_set_user() - set the user data associated with the client connection
- * \param wsi: lws connection
- * \param user: user data
- *
- * By default lws allocates this and it's not legal to externally set it
- * yourself. However client connections may have it set externally when the
- * connection is created... if so, this api can be used to modify it at
- * runtime additionally.
- */
-LWS_VISIBLE LWS_EXTERN void
-lws_set_wsi_user(struct lws *wsi, void *user);
-
-/**
- * lws_parse_uri: cut up prot:/ads:port/path into pieces
- * Notice it does so by dropping '\0' into input string
- * and the leading / on the path is consequently lost
- *
- * \param p: incoming uri string.. will get written to
- * \param prot: result pointer for protocol part (https://)
- * \param ads: result pointer for address part
- * \param port: result pointer for port part
- * \param path: result pointer for path part
- */
-LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_parse_uri(char *p, const char **prot, const char **ads, int *port,
- const char **path);
-/**
- * lws_cmdline_option(): simple commandline parser
- *
- * \param argc: count of argument strings
- * \param argv: argument strings
- * \param val: string to find
- *
- * Returns NULL if the string \p val is not found in the arguments.
- *
- * If it is found, then it returns a pointer to the next character after \p val.
- * So if \p val is "-d", then for the commandlines "myapp -d15" and
- * "myapp -d 15", in both cases the return will point to the "15".
- *
- * In the case there is no argument, like "myapp -d", the return will
- * either point to the '\\0' at the end of -d, or to the start of the
- * next argument, ie, will be non-NULL.
- */
-LWS_VISIBLE LWS_EXTERN const char *
-lws_cmdline_option(int argc, const char **argv, const char *val);
-
-/**
- * lws_now_secs(): return seconds since 1970-1-1
- */
-LWS_VISIBLE LWS_EXTERN unsigned long
-lws_now_secs(void);
-
-/**
- * lws_compare_time_t(): return relationship between two time_t
- *
- * \param context: struct lws_context
- * \param t1: time_t 1
- * \param t2: time_t 2
- *
- * returns <0 if t2 > t1; >0 if t1 > t2; or == 0 if t1 == t2.
- *
- * This is aware of clock discontiguities that may have affected either t1 or
- * t2 and adapts the comparison for them.
- *
- * For the discontiguity detection to work, you must avoid any arithmetic on
- * the times being compared. For example to have a timeout that triggers
- * 15s from when it was set, store the time it was set and compare like
- * `if (lws_compare_time_t(context, now, set_time) > 15)`
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_compare_time_t(struct lws_context *context, time_t t1, time_t t2);
-
-/**
- * lws_get_context - Allow getting lws_context from a Websocket connection
- * instance
- *
- * With this function, users can access context in the callback function.
- * Otherwise users may have to declare context as a global variable.
- *
- * \param wsi: Websocket connection instance
- */
-LWS_VISIBLE LWS_EXTERN struct lws_context * LWS_WARN_UNUSED_RESULT
-lws_get_context(const struct lws *wsi);
-
-/**
- * lws_get_vhost_listen_port - Find out the port number a vhost is listening on
- *
- * In the case you passed 0 for the port number at context creation time, you
- * can discover the port number that was actually chosen for the vhost using
- * this api.
- *
- * \param vhost: Vhost to get listen port from
- */
-LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_get_vhost_listen_port(struct lws_vhost *vhost);
-
-/**
- * lws_get_count_threads(): how many service threads the context uses
- *
- * \param context: the lws context
- *
- * By default this is always 1, if you asked for more than lws can handle it
- * will clip the number of threads. So you can use this to find out how many
- * threads are actually in use.
- */
-LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_get_count_threads(struct lws_context *context);
-
-/**
- * lws_get_parent() - get parent wsi or NULL
- * \param wsi: lws connection
- *
- * Specialized wsi like cgi stdin/out/err are associated to a parent wsi,
- * this allows you to get their parent.
- */
-LWS_VISIBLE LWS_EXTERN struct lws * LWS_WARN_UNUSED_RESULT
-lws_get_parent(const struct lws *wsi);
-
-/**
- * lws_get_child() - get child wsi or NULL
- * \param wsi: lws connection
- *
- * Allows you to find a related wsi from the parent wsi.
- */
-LWS_VISIBLE LWS_EXTERN struct lws * LWS_WARN_UNUSED_RESULT
-lws_get_child(const struct lws *wsi);
-
-/**
- * lws_get_udp() - get wsi's udp struct
- *
- * \param wsi: lws connection
- *
- * Returns NULL or pointer to the wsi's UDP-specific information
- */
-LWS_VISIBLE LWS_EXTERN const struct lws_udp * LWS_WARN_UNUSED_RESULT
-lws_get_udp(const struct lws *wsi);
-
-/**
- * lws_parent_carries_io() - mark wsi as needing to send messages via parent
- *
- * \param wsi: child lws connection
- */
-
-LWS_VISIBLE LWS_EXTERN void
-lws_set_parent_carries_io(struct lws *wsi);
-
-LWS_VISIBLE LWS_EXTERN void *
-lws_get_opaque_parent_data(const struct lws *wsi);
-
-LWS_VISIBLE LWS_EXTERN void
-lws_set_opaque_parent_data(struct lws *wsi, void *data);
-
-LWS_VISIBLE LWS_EXTERN int
-lws_get_child_pending_on_writable(const struct lws *wsi);
-
-LWS_VISIBLE LWS_EXTERN void
-lws_clear_child_pending_on_writable(struct lws *wsi);
-
-LWS_VISIBLE LWS_EXTERN int
-lws_get_close_length(struct lws *wsi);
-
-LWS_VISIBLE LWS_EXTERN unsigned char *
-lws_get_close_payload(struct lws *wsi);
-
-/**
- * lws_get_network_wsi() - Returns wsi that has the tcp connection for this wsi
- *
- * \param wsi: wsi you have
- *
- * Returns wsi that has the tcp connection (which may be the incoming wsi)
- *
- * HTTP/1 connections will always return the incoming wsi
- * HTTP/2 connections may return a different wsi that has the tcp connection
- */
-LWS_VISIBLE LWS_EXTERN
-struct lws *lws_get_network_wsi(struct lws *wsi);
-
-/**
- * lws_set_allocator() - custom allocator support
- *
- * \param realloc
- *
- * Allows you to replace the allocator (and deallocator) used by lws
- */
-LWS_VISIBLE LWS_EXTERN void
-lws_set_allocator(void *(*realloc)(void *ptr, size_t size, const char *reason));
-///@}
-
-/** \defgroup wsstatus Websocket status APIs
- * ##Websocket connection status APIs
- *
- * These provide information about ws connection or message status
- */
-///@{
-/**
- * lws_send_pipe_choked() - tests if socket is writable or not
- * \param wsi: lws connection
- *
- * Allows you to check if you can write more on the socket
- */
-LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_send_pipe_choked(struct lws *wsi);
-
-/**
- * lws_is_final_fragment() - tests if last part of ws message
- *
- * \param wsi: lws connection
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_is_final_fragment(struct lws *wsi);
-
-/**
- * lws_is_first_fragment() - tests if first part of ws message
- *
- * \param wsi: lws connection
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_is_first_fragment(struct lws *wsi);
-
-/**
- * lws_get_reserved_bits() - access reserved bits of ws frame
- * \param wsi: lws connection
- */
-LWS_VISIBLE LWS_EXTERN unsigned char
-lws_get_reserved_bits(struct lws *wsi);
-
-/**
- * lws_partial_buffered() - find out if lws buffered the last write
- * \param wsi: websocket connection to check
- *
- * Returns 1 if you cannot use lws_write because the last
- * write on this connection is still buffered, and can't be cleared without
- * returning to the service loop and waiting for the connection to be
- * writeable again.
- *
- * If you will try to do >1 lws_write call inside a single
- * WRITEABLE callback, you must check this after every write and bail if
- * set, ask for a new writeable callback and continue writing from there.
- *
- * This is never set at the start of a writeable callback, but any write
- * may set it.
- */
-LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_partial_buffered(struct lws *wsi);
-
-/**
- * lws_frame_is_binary(): true if the current frame was sent in binary mode
- *
- * \param wsi: the connection we are inquiring about
- *
- * This is intended to be called from the LWS_CALLBACK_RECEIVE callback if
- * it's interested to see if the frame it's dealing with was sent in binary
- * mode.
- */
-LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_frame_is_binary(struct lws *wsi);
-
-/**
- * lws_is_ssl() - Find out if connection is using SSL
- * \param wsi: websocket connection to check
- *
- * Returns 0 if the connection is not using SSL, 1 if using SSL and
- * using verified cert, and 2 if using SSL but the cert was not
- * checked (appears for client wsi told to skip check on connection)
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_is_ssl(struct lws *wsi);
-/**
- * lws_is_cgi() - find out if this wsi is running a cgi process
- * \param wsi: lws connection
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_is_cgi(struct lws *wsi);
-
-
-struct lws_wifi_scan { /* generic wlan scan item */
- struct lws_wifi_scan *next;
- char ssid[32];
- int32_t rssi; /* divide by .count to get db */
- uint8_t bssid[6];
- uint8_t count;
- uint8_t channel;
- uint8_t authmode;
-};
-
-#if defined(LWS_WITH_TLS) && !defined(LWS_WITH_MBEDTLS)
-/**
- * lws_get_ssl() - Return wsi's SSL context structure
- * \param wsi: websocket connection
- *
- * Returns pointer to the SSL library's context structure
- */
-LWS_VISIBLE LWS_EXTERN SSL*
-lws_get_ssl(struct lws *wsi);
-#endif
-
-enum lws_tls_cert_info {
- LWS_TLS_CERT_INFO_VALIDITY_FROM,
- /**< fills .time with the time_t the cert validity started from */
- LWS_TLS_CERT_INFO_VALIDITY_TO,
- /**< fills .time with the time_t the cert validity ends at */
- LWS_TLS_CERT_INFO_COMMON_NAME,
- /**< fills up to len bytes of .ns.name with the cert common name */
- LWS_TLS_CERT_INFO_ISSUER_NAME,
- /**< fills up to len bytes of .ns.name with the cert issuer name */
- LWS_TLS_CERT_INFO_USAGE,
- /**< fills verified with a bitfield asserting the valid uses */
- LWS_TLS_CERT_INFO_VERIFIED,
- /**< fills .verified with a bool representing peer cert validity,
- * call returns -1 if no cert */
- LWS_TLS_CERT_INFO_OPAQUE_PUBLIC_KEY,
- /**< the certificate's public key, as an opaque bytestream. These
- * opaque bytestreams can only be compared with each other using the
- * same tls backend, ie, OpenSSL or mbedTLS. The different backends
- * produce different, incompatible representations for the same cert.
- */
-};
-
-union lws_tls_cert_info_results {
- unsigned int verified;
- time_t time;
- unsigned int usage;
- struct {
- int len;
- /* KEEP LAST... notice the [64] is only there because
- * name[] is not allowed in a union. The actual length of
- * name[] is arbitrary and is passed into the api using the
- * len parameter. Eg
- *
- * char big[1024];
- * union lws_tls_cert_info_results *buf =
- * (union lws_tls_cert_info_results *)big;
- *
- * lws_tls_peer_cert_info(wsi, type, buf, sizeof(big) -
- * sizeof(*buf) + sizeof(buf->ns.name));
- */
- char name[64];
- } ns;
-};
-
-/**
- * lws_tls_peer_cert_info() - get information from the peer's TLS cert
- *
- * \param wsi: the connection to query
- * \param type: one of LWS_TLS_CERT_INFO_
- * \param buf: pointer to union to take result
- * \param len: when result is a string, the true length of buf->ns.name[]
- *
- * lws_tls_peer_cert_info() lets you get hold of information from the peer
- * certificate.
- *
- * Return 0 if there is a result in \p buf, or -1 indicating there was no cert
- * or another problem.
- *
- * This function works the same no matter if the TLS backend is OpenSSL or
- * mbedTLS.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_tls_peer_cert_info(struct lws *wsi, enum lws_tls_cert_info type,
- union lws_tls_cert_info_results *buf, size_t len);
-
-/**
- * lws_tls_vhost_cert_info() - get information from the vhost's own TLS cert
- *
- * \param vhost: the vhost to query
- * \param type: one of LWS_TLS_CERT_INFO_
- * \param buf: pointer to union to take result
- * \param len: when result is a string, the true length of buf->ns.name[]
- *
- * lws_tls_vhost_cert_info() lets you get hold of information from the vhost
- * certificate.
- *
- * Return 0 if there is a result in \p buf, or -1 indicating there was no cert
- * or another problem.
- *
- * This function works the same no matter if the TLS backend is OpenSSL or
- * mbedTLS.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_tls_vhost_cert_info(struct lws_vhost *vhost, enum lws_tls_cert_info type,
- union lws_tls_cert_info_results *buf, size_t len);
-
-/**
- * lws_tls_acme_sni_cert_create() - creates a temp selfsigned cert
- * and attaches to a vhost
- *
- * \param vhost: the vhost to acquire the selfsigned cert
- * \param san_a: SAN written into the certificate
- * \param san_b: second SAN written into the certificate
- *
- *
- * Returns 0 if created and attached to the vhost. Returns -1 if problems and
- * frees all allocations before returning.
- *
- * On success, any allocations are destroyed at vhost destruction automatically.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_tls_acme_sni_cert_create(struct lws_vhost *vhost, const char *san_a,
- const char *san_b);
-
-/**
- * lws_tls_acme_sni_csr_create() - creates a CSR and related private key PEM
- *
- * \param context: lws_context used for random
- * \param elements: array of LWS_TLS_REQ_ELEMENT_COUNT const char *
- * \param csr: buffer that will get the b64URL(ASN-1 CSR)
- * \param csr_len: max length of the csr buffer
- * \param privkey_pem: pointer to pointer allocated to hold the privkey_pem
- * \param privkey_len: pointer to size_t set to the length of the privkey_pem
- *
- * Creates a CSR according to the information in \p elements, and a private
- * RSA key used to sign the CSR.
- *
- * The outputs are the b64URL(ASN-1 CSR) into csr, and the PEM private key into
- * privkey_pem.
- *
- * Notice that \p elements points to an array of const char *s pointing to the
- * information listed in the enum above. If an entry is NULL or an empty
- * string, the element is set to "none" in the CSR.
- *
- * Returns 0 on success or nonzero for failure.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_tls_acme_sni_csr_create(struct lws_context *context, const char *elements[],
- uint8_t *csr, size_t csr_len, char **privkey_pem,
- size_t *privkey_len);
-
-/**
- * lws_tls_cert_updated() - update every vhost using the given cert path
- *
- * \param context: our lws_context
- * \param certpath: the filepath to the certificate
- * \param keypath: the filepath to the private key of the certificate
- * \param mem_cert: copy of the cert in memory
- * \param len_mem_cert: length of the copy of the cert in memory
- * \param mem_privkey: copy of the private key in memory
- * \param len_mem_privkey: length of the copy of the private key in memory
- *
- * Checks every vhost to see if it is the using certificate described by the
- * the given filepaths. If so, it attempts to update the vhost ssl_ctx to use
- * the new certificate.
- *
- * Returns 0 on success or nonzero for failure.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_tls_cert_updated(struct lws_context *context, const char *certpath,
- const char *keypath,
- const char *mem_cert, size_t len_mem_cert,
- const char *mem_privkey, size_t len_mem_privkey);
-///@}
-
-/** \defgroup lws_ring LWS Ringbuffer APIs
- * ##lws_ring: generic ringbuffer struct
- *
- * Provides an abstract ringbuffer api supporting one head and one or an
- * unlimited number of tails.
- *
- * All of the members are opaque and manipulated by lws_ring_...() apis.
- *
- * The lws_ring and its buffer is allocated at runtime on the heap, using
- *
- * - lws_ring_create()
- * - lws_ring_destroy()
- *
- * It may contain any type, the size of the "element" stored in the ring
- * buffer and the number of elements is given at creation time.
- *
- * When you create the ringbuffer, you can optionally provide an element
- * destroy callback that frees any allocations inside the element. This is then
- * automatically called for elements with no tail behind them, ie, elements
- * which don't have any pending consumer are auto-freed.
- *
- * Whole elements may be inserted into the ringbuffer and removed from it, using
- *
- * - lws_ring_insert()
- * - lws_ring_consume()
- *
- * You can find out how many whole elements are free or waiting using
- *
- * - lws_ring_get_count_free_elements()
- * - lws_ring_get_count_waiting_elements()
- *
- * In addition there are special purpose optional byte-centric apis
- *
- * - lws_ring_next_linear_insert_range()
- * - lws_ring_bump_head()
- *
- * which let you, eg, read() directly into the ringbuffer without needing
- * an intermediate bounce buffer.
- *
- * The accessors understand that the ring wraps, and optimizes insertion and
- * consumption into one or two memcpy()s depending on if the head or tail
- * wraps.
- *
- * lws_ring only supports a single head, but optionally multiple tails with
- * an API to inform it when the "oldest" tail has moved on. You can give
- * NULL where-ever an api asks for a tail pointer, and it will use an internal
- * single tail pointer for convenience.
- *
- * The "oldest tail", which is the only tail if you give it NULL instead of
- * some other tail, is used to track which elements in the ringbuffer are
- * still unread by anyone.
- *
- * - lws_ring_update_oldest_tail()
- */
-///@{
-struct lws_ring;
-
-/**
- * lws_ring_create(): create a new ringbuffer
- *
- * \param element_len: the size in bytes of one element in the ringbuffer
- * \param count: the number of elements the ringbuffer can contain
- * \param destroy_element: NULL, or callback to be called for each element
- * that is removed from the ringbuffer due to the
- * oldest tail moving beyond it
- *
- * Creates the ringbuffer and allocates the storage. Returns the new
- * lws_ring *, or NULL if the allocation failed.
- *
- * If non-NULL, destroy_element will get called back for every element that is
- * retired from the ringbuffer after the oldest tail has gone past it, and for
- * any element still left in the ringbuffer when it is destroyed. It replaces
- * all other element destruction code in your user code.
- */
-LWS_VISIBLE LWS_EXTERN struct lws_ring *
-lws_ring_create(size_t element_len, size_t count,
- void (*destroy_element)(void *element));
-
-/**
- * lws_ring_destroy(): destroy a previously created ringbuffer
- *
- * \param ring: the struct lws_ring to destroy
- *
- * Destroys the ringbuffer allocation and the struct lws_ring itself.
- */
-LWS_VISIBLE LWS_EXTERN void
-lws_ring_destroy(struct lws_ring *ring);
-
-/**
- * lws_ring_get_count_free_elements(): return how many elements can fit
- * in the free space
- *
- * \param ring: the struct lws_ring to report on
- *
- * Returns how much room is left in the ringbuffer for whole element insertion.
- */
-LWS_VISIBLE LWS_EXTERN size_t
-lws_ring_get_count_free_elements(struct lws_ring *ring);
-
-/**
- * lws_ring_get_count_waiting_elements(): return how many elements can be consumed
- *
- * \param ring: the struct lws_ring to report on
- * \param tail: a pointer to the tail struct to use, or NULL for single tail
- *
- * Returns how many elements are waiting to be consumed from the perspective
- * of the tail pointer given.
- */
-LWS_VISIBLE LWS_EXTERN size_t
-lws_ring_get_count_waiting_elements(struct lws_ring *ring, uint32_t *tail);
-
-/**
- * lws_ring_insert(): attempt to insert up to max_count elements from src
- *
- * \param ring: the struct lws_ring to report on
- * \param src: the array of elements to be inserted
- * \param max_count: the number of available elements at src
- *
- * Attempts to insert as many of the elements at src as possible, up to the
- * maximum max_count. Returns the number of elements actually inserted.
- */
-LWS_VISIBLE LWS_EXTERN size_t
-lws_ring_insert(struct lws_ring *ring, const void *src, size_t max_count);
-
-/**
- * lws_ring_consume(): attempt to copy out and remove up to max_count elements
- * to src
- *
- * \param ring: the struct lws_ring to report on
- * \param tail: a pointer to the tail struct to use, or NULL for single tail
- * \param dest: the array of elements to be inserted. or NULL for no copy
- * \param max_count: the number of available elements at src
- *
- * Attempts to copy out as many waiting elements as possible into dest, from
- * the perspective of the given tail, up to max_count. If dest is NULL, the
- * copying out is not done but the elements are logically consumed as usual.
- * NULL dest is useful in combination with lws_ring_get_element(), where you
- * can use the element direct from the ringbuffer and then call this with NULL
- * dest to logically consume it.
- *
- * Increments the tail position according to how many elements could be
- * consumed.
- *
- * Returns the number of elements consumed.
- */
-LWS_VISIBLE LWS_EXTERN size_t
-lws_ring_consume(struct lws_ring *ring, uint32_t *tail, void *dest,
- size_t max_count);
-
-/**
- * lws_ring_get_element(): get a pointer to the next waiting element for tail
- *
- * \param ring: the struct lws_ring to report on
- * \param tail: a pointer to the tail struct to use, or NULL for single tail
- *
- * Points to the next element that tail would consume, directly in the
- * ringbuffer. This lets you write() or otherwise use the element without
- * having to copy it out somewhere first.
- *
- * After calling this, you must call lws_ring_consume(ring, &tail, NULL, 1)
- * which will logically consume the element you used up and increment your
- * tail (tail may also be NULL there if you use a single tail).
- *
- * Returns NULL if no waiting element, or a const void * pointing to it.
- */
-LWS_VISIBLE LWS_EXTERN const void *
-lws_ring_get_element(struct lws_ring *ring, uint32_t *tail);
-
-/**
- * lws_ring_update_oldest_tail(): free up elements older than tail for reuse
- *
- * \param ring: the struct lws_ring to report on
- * \param tail: a pointer to the tail struct to use, or NULL for single tail
- *
- * If you are using multiple tails, you must use this API to inform the
- * lws_ring when none of the tails still need elements in the fifo any more,
- * by updating it when the "oldest" tail has moved on.
- */
-LWS_VISIBLE LWS_EXTERN void
-lws_ring_update_oldest_tail(struct lws_ring *ring, uint32_t tail);
-
-/**
- * lws_ring_get_oldest_tail(): get current oldest available data index
- *
- * \param ring: the struct lws_ring to report on
- *
- * If you are initializing a new ringbuffer consumer, you can set its tail to
- * this to start it from the oldest ringbuffer entry still available.
- */
-LWS_VISIBLE LWS_EXTERN uint32_t
-lws_ring_get_oldest_tail(struct lws_ring *ring);
-
-/**
- * lws_ring_next_linear_insert_range(): used to write directly into the ring
- *
- * \param ring: the struct lws_ring to report on
- * \param start: pointer to a void * set to the start of the next ringbuffer area
- * \param bytes: pointer to a size_t set to the max length you may use from *start
- *
- * This provides a low-level, bytewise access directly into the ringbuffer
- * allowing direct insertion of data without having to use a bounce buffer.
- *
- * The api reports the position and length of the next linear range that can
- * be written in the ringbuffer, ie, up to the point it would wrap, and sets
- * *start and *bytes accordingly. You can then, eg, directly read() into
- * *start for up to *bytes, and use lws_ring_bump_head() to update the lws_ring
- * with what you have done.
- *
- * Returns nonzero if no insertion is currently possible.
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_ring_next_linear_insert_range(struct lws_ring *ring, void **start,
- size_t *bytes);
-
-/**
- * lws_ring_bump_head(): used to write directly into the ring
- *
- * \param ring: the struct lws_ring to operate on
- * \param bytes: the number of bytes you inserted at the current head
- */
-LWS_VISIBLE LWS_EXTERN void
-lws_ring_bump_head(struct lws_ring *ring, size_t bytes);
-
-LWS_VISIBLE LWS_EXTERN void
-lws_ring_dump(struct lws_ring *ring, uint32_t *tail);
-
-/*
- * This is a helper that combines the common pattern of needing to consume
- * some ringbuffer elements, move the consumer tail on, and check if that
- * has moved any ringbuffer elements out of scope, because it was the last
- * consumer that had not already consumed them.
- *
- * Elements that go out of scope because the oldest tail is now after them
- * get garbage-collected by calling the destroy_element callback on them
- * defined when the ringbuffer was created.
- */
-
-#define lws_ring_consume_and_update_oldest_tail(\
- ___ring, /* the lws_ring object */ \
- ___type, /* type of objects with tails */ \
- ___ptail, /* ptr to tail of obj with tail doing consuming */ \
- ___count, /* count of payload objects being consumed */ \
- ___list_head, /* head of list of objects with tails */ \
- ___mtail, /* member name of tail in ___type */ \
- ___mlist /* member name of next list member ptr in ___type */ \
- ) { \
- int ___n, ___m; \
- \
- ___n = lws_ring_get_oldest_tail(___ring) == *(___ptail); \
- lws_ring_consume(___ring, ___ptail, NULL, ___count); \
- if (___n) { \
- uint32_t ___oldest; \
- ___n = 0; \
- ___oldest = *(___ptail); \
- lws_start_foreach_llp(___type **, ___ppss, ___list_head) { \
- ___m = lws_ring_get_count_waiting_elements( \
- ___ring, &(*___ppss)->tail); \
- if (___m >= ___n) { \
- ___n = ___m; \
- ___oldest = (*___ppss)->tail; \
- } \
- } lws_end_foreach_llp(___ppss, ___mlist); \
- \
- lws_ring_update_oldest_tail(___ring, ___oldest); \
- } \
-}
-
-/*
- * This does the same as the lws_ring_consume_and_update_oldest_tail()
- * helper, but for the simpler case there is only one consumer, so one
- * tail, and that tail is always the oldest tail.
- */
-
-#define lws_ring_consume_single_tail(\
- ___ring, /* the lws_ring object */ \
- ___ptail, /* ptr to tail of obj with tail doing consuming */ \
- ___count /* count of payload objects being consumed */ \
- ) { \
- lws_ring_consume(___ring, ___ptail, NULL, ___count); \
- lws_ring_update_oldest_tail(___ring, *(___ptail)); \
-}
-///@}
-
-/** \defgroup sha SHA and B64 helpers
- * ##SHA and B64 helpers
- *
- * These provide SHA-1 and B64 helper apis
- */
-///@{
-#ifdef LWS_SHA1_USE_OPENSSL_NAME
-#define lws_SHA1 SHA1
-#else
-/**
- * lws_SHA1(): make a SHA-1 digest of a buffer
- *
- * \param d: incoming buffer
- * \param n: length of incoming buffer
- * \param md: buffer for message digest (must be >= 20 bytes)
- *
- * Reduces any size buffer into a 20-byte SHA-1 hash.
- */
-LWS_VISIBLE LWS_EXTERN unsigned char *
-lws_SHA1(const unsigned char *d, size_t n, unsigned char *md);
-#endif
-/**
- * lws_b64_encode_string(): encode a string into base 64
- *
- * \param in: incoming buffer
- * \param in_len: length of incoming buffer
- * \param out: result buffer
- * \param out_size: length of result buffer
- *
- * Encodes a string using b64
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_b64_encode_string(const char *in, int in_len, char *out, int out_size);
-/**
- * lws_b64_encode_string_url(): encode a string into base 64
- *
- * \param in: incoming buffer
- * \param in_len: length of incoming buffer
- * \param out: result buffer
- * \param out_size: length of result buffer
- *
- * Encodes a string using b64 with the "URL" variant (+ -> -, and / -> _)
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_b64_encode_string_url(const char *in, int in_len, char *out, int out_size);
-/**
- * lws_b64_decode_string(): decode a string from base 64
- *
- * \param in: incoming buffer
- * \param out: result buffer
- * \param out_size: length of result buffer
- *
- * Decodes a NUL-terminated string using b64
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_b64_decode_string(const char *in, char *out, int out_size);
-/**
- * lws_b64_decode_string_len(): decode a string from base 64
- *
- * \param in: incoming buffer
- * \param in_len: length of incoming buffer
- * \param out: result buffer
- * \param out_size: length of result buffer
- *
- * Decodes a range of chars using b64
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_b64_decode_string_len(const char *in, int in_len, char *out, int out_size);
-///@}
-
-
-/*! \defgroup cgi cgi handling
- *
- * ##CGI handling
- *
- * These functions allow low-level control over stdin/out/err of the cgi.
- *
- * However for most cases, binding the cgi to http in and out, the default
- * lws implementation already does the right thing.
- */
-
-enum lws_enum_stdinouterr {
- LWS_STDIN = 0,
- LWS_STDOUT = 1,
- LWS_STDERR = 2,
-};
-
-enum lws_cgi_hdr_state {
- LCHS_HEADER,
- LCHS_CR1,
- LCHS_LF1,
- LCHS_CR2,
- LCHS_LF2,
- LHCS_RESPONSE,
- LHCS_DUMP_HEADERS,
- LHCS_PAYLOAD,
- LCHS_SINGLE_0A,
-};
-
-struct lws_cgi_args {
- struct lws **stdwsi; /**< get fd with lws_get_socket_fd() */
- enum lws_enum_stdinouterr ch; /**< channel index */
- unsigned char *data; /**< for messages with payload */
- enum lws_cgi_hdr_state hdr_state; /**< track where we are in cgi headers */
- int len; /**< length */
-};
-
-#ifdef LWS_WITH_CGI
-/**
- * lws_cgi: spawn network-connected cgi process
- *
- * \param wsi: connection to own the process
- * \param exec_array: array of "exec-name" "arg1" ... "argn" NULL
- * \param script_uri_path_len: how many chars on the left of the uri are the
- * path to the cgi, or -1 to spawn without URL-related env vars
- * \param timeout_secs: seconds script should be allowed to run
- * \param mp_cgienv: pvo list with per-vhost cgi options to put in env
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_cgi(struct lws *wsi, const char * const *exec_array,
- int script_uri_path_len, int timeout_secs,
- const struct lws_protocol_vhost_options *mp_cgienv);
-
-/**
- * lws_cgi_write_split_stdout_headers: write cgi output accounting for header part
- *
- * \param wsi: connection to own the process
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_cgi_write_split_stdout_headers(struct lws *wsi);
-
-/**
- * lws_cgi_kill: terminate cgi process associated with wsi
- *
- * \param wsi: connection to own the process
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_cgi_kill(struct lws *wsi);
-
-/**
- * lws_cgi_get_stdwsi: get wsi for stdin, stdout, or stderr
- *
- * \param wsi: parent wsi that has cgi
- * \param ch: which of LWS_STDIN, LWS_STDOUT or LWS_STDERR
- */
-LWS_VISIBLE LWS_EXTERN struct lws *
-lws_cgi_get_stdwsi(struct lws *wsi, enum lws_enum_stdinouterr ch);
-
-#endif
-///@}
-
-
-/*! \defgroup fops file operation wrapping
- *
- * ##File operation wrapping
- *
- * Use these helper functions if you want to access a file from the perspective
- * of a specific wsi, which is usually the case. If you just want contextless
- * file access, use the fops callbacks directly with NULL wsi instead of these
- * helpers.
- *
- * If so, then it calls the platform handler or user overrides where present
- * (as defined in info->fops)
- *
- * The advantage from all this is user code can be portable for file operations
- * without having to deal with differences between platforms.
- */
-//@{
-
-/** struct lws_plat_file_ops - Platform-specific file operations
- *
- * These provide platform-agnostic ways to deal with filesystem access in the
- * 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)
-#define LWS_FOP_FLAG_COMPR_IS_GZIP (1 << 25)
-#define LWS_FOP_FLAG_MOD_TIME_VALID (1 << 26)
-#define LWS_FOP_FLAG_VIRTUAL (1 << 27)
-
-struct lws_plat_file_ops;
-
-struct lws_fop_fd {
- lws_filefd_type fd;
- /**< real file descriptor related to the file... */
- const struct lws_plat_file_ops *fops;
- /**< fops that apply to this fop_fd */
- void *filesystem_priv;
- /**< ignored by lws; owned by the fops handlers */
- lws_filepos_t pos;
- /**< generic "position in file" */
- lws_filepos_t len;
- /**< generic "length of file" */
- lws_fop_flags_t flags;
- /**< copy of the returned flags */
- uint32_t mod_time;
- /**< optional "modification time of file", only valid if .open()
- * set the LWS_FOP_FLAG_MOD_TIME_VALID flag */
-};
-typedef struct lws_fop_fd *lws_fop_fd_t;
-
-struct lws_fops_index {
- const char *sig; /* NULL or vfs signature, eg, ".zip/" */
- uint8_t len; /* length of above string */
-};
-
-struct lws_plat_file_ops {
- lws_fop_fd_t (*LWS_FOP_OPEN)(const struct lws_plat_file_ops *fops,
- const char *filename, const char *vpath,
- lws_fop_flags_t *flags);
- /**< Open file (always binary access if plat supports it)
- * vpath may be NULL, or if the fops understands it, the point at which
- * the filename's virtual part starts.
- * *flags & LWS_FOP_FLAGS_MASK should be set to O_RDONLY or O_RDWR.
- * If the file may be gzip-compressed,
- * LWS_FOP_FLAG_COMPR_ACCEPTABLE_GZIP is set. If it actually is
- * gzip-compressed, then the open handler should OR
- * LWS_FOP_FLAG_COMPR_IS_GZIP on to *flags before returning.
- */
- int (*LWS_FOP_CLOSE)(lws_fop_fd_t *fop_fd);
- /**< close file AND set the pointer to NULL */
- lws_fileofs_t (*LWS_FOP_SEEK_CUR)(lws_fop_fd_t fop_fd,
- lws_fileofs_t offset_from_cur_pos);
- /**< seek from current position */
- int (*LWS_FOP_READ)(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
- uint8_t *buf, lws_filepos_t len);
- /**< Read from file, on exit *amount is set to amount actually read */
- int (*LWS_FOP_WRITE)(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
- uint8_t *buf, lws_filepos_t len);
- /**< Write to file, on exit *amount is set to amount actually written */
-
- struct lws_fops_index fi[3];
- /**< vfs path signatures implying use of this fops */
-
- const struct lws_plat_file_ops *next;
- /**< NULL or next fops in list */
-
- /* Add new things just above here ---^
- * This is part of the ABI, don't needlessly break compatibility */
-};
-
-/**
- * lws_get_fops() - get current file ops
- *
- * \param context: context
- */
-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, const struct lws_plat_file_ops *fops);
-/**
- * lws_vfs_tell() - get current file position
- *
- * \param fop_fd: fop_fd we are asking about
- */
-LWS_VISIBLE LWS_EXTERN lws_filepos_t LWS_WARN_UNUSED_RESULT
-lws_vfs_tell(lws_fop_fd_t fop_fd);
-/**
- * lws_vfs_get_length() - get current file total length in bytes
- *
- * \param fop_fd: fop_fd we are asking about
- */
-LWS_VISIBLE LWS_EXTERN lws_filepos_t LWS_WARN_UNUSED_RESULT
-lws_vfs_get_length(lws_fop_fd_t fop_fd);
-/**
- * lws_vfs_get_mod_time() - get time file last modified
- *
- * \param fop_fd: fop_fd we are asking about
- */
-LWS_VISIBLE LWS_EXTERN uint32_t LWS_WARN_UNUSED_RESULT
-lws_vfs_get_mod_time(lws_fop_fd_t fop_fd);
-/**
- * lws_vfs_file_seek_set() - seek relative to start of file
- *
- * \param fop_fd: fop_fd we are seeking in
- * \param offset: offset from start of file
- */
-LWS_VISIBLE LWS_EXTERN lws_fileofs_t
-lws_vfs_file_seek_set(lws_fop_fd_t fop_fd, lws_fileofs_t offset);
-/**
- * lws_vfs_file_seek_end() - seek relative to end of file
- *
- * \param fop_fd: fop_fd we are seeking in
- * \param offset: offset from start of file
- */
-LWS_VISIBLE LWS_EXTERN lws_fileofs_t
-lws_vfs_file_seek_end(lws_fop_fd_t fop_fd, lws_fileofs_t offset);
-
-extern struct lws_plat_file_ops fops_zip;
-
-/**
- * lws_plat_file_open() - open vfs filepath
- *
- * \param fops: file ops struct that applies to this descriptor
- * \param vfs_path: filename to open
- * \param flags: pointer to open flags
- *
- * The vfs_path is scanned for known fops signatures, and the open directed
- * to any matching fops open.
- *
- * User code should use this api to perform vfs opens.
- *
- * returns semi-opaque handle
- */
-LWS_VISIBLE LWS_EXTERN lws_fop_fd_t LWS_WARN_UNUSED_RESULT
-lws_vfs_file_open(const struct lws_plat_file_ops *fops, const char *vfs_path,
- lws_fop_flags_t *flags);
-
-/**
- * lws_plat_file_close() - close file
- *
- * \param fop_fd: file handle to close
- */
-static LWS_INLINE int
-lws_vfs_file_close(lws_fop_fd_t *fop_fd)
-{
- return (*fop_fd)->fops->LWS_FOP_CLOSE(fop_fd);
-}
-
-/**
- * lws_plat_file_seek_cur() - close file
- *
- *
- * \param fop_fd: file handle
- * \param offset: position to seek to
- */
-static LWS_INLINE lws_fileofs_t
-lws_vfs_file_seek_cur(lws_fop_fd_t fop_fd, lws_fileofs_t offset)
-{
- return fop_fd->fops->LWS_FOP_SEEK_CUR(fop_fd, offset);
-}
-/**
- * lws_plat_file_read() - read from file
- *
- * \param fop_fd: file handle
- * \param amount: how much to read (rewritten by call)
- * \param buf: buffer to write to
- * \param len: max length
- */
-static LWS_INLINE int LWS_WARN_UNUSED_RESULT
-lws_vfs_file_read(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
- uint8_t *buf, lws_filepos_t len)
-{
- return fop_fd->fops->LWS_FOP_READ(fop_fd, amount, buf, len);
-}
-/**
- * lws_plat_file_write() - write from file
- *
- * \param fop_fd: file handle
- * \param amount: how much to write (rewritten by call)
- * \param buf: buffer to read from
- * \param len: max length
- */
-static LWS_INLINE int LWS_WARN_UNUSED_RESULT
-lws_vfs_file_write(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
- uint8_t *buf, lws_filepos_t len)
-{
- return fop_fd->fops->LWS_FOP_WRITE(fop_fd, amount, buf, len);
-}
-
-/* these are the platform file operations implementations... they can
- * be called directly and used in fops arrays
- */
-
-LWS_VISIBLE LWS_EXTERN lws_fop_fd_t
-_lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename,
- const char *vpath, lws_fop_flags_t *flags);
-LWS_VISIBLE LWS_EXTERN int
-_lws_plat_file_close(lws_fop_fd_t *fop_fd);
-LWS_VISIBLE LWS_EXTERN lws_fileofs_t
-_lws_plat_file_seek_cur(lws_fop_fd_t fop_fd, lws_fileofs_t offset);
-LWS_VISIBLE LWS_EXTERN int
-_lws_plat_file_read(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
- uint8_t *buf, lws_filepos_t len);
-LWS_VISIBLE LWS_EXTERN int
-_lws_plat_file_write(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
- uint8_t *buf, lws_filepos_t len);
-
-LWS_VISIBLE LWS_EXTERN int
-lws_alloc_vfs_file(struct lws_context *context, const char *filename,
- uint8_t **buf, lws_filepos_t *amount);
-//@}
-
-/** \defgroup smtp SMTP related functions
- * ##SMTP related functions
- * \ingroup lwsapi
- *
- * These apis let you communicate with a local SMTP server to send email from
- * lws. It handles all the SMTP sequencing and protocol actions.
- *
- * Your system should have postfix, sendmail or another MTA listening on port
- * 25 and able to send email using the "mail" commandline app. Usually distro
- * MTAs are configured for this by default.
- *
- * It runs via its own libuv events if initialized (which requires giving it
- * a libuv loop to attach to).
- *
- * It operates using three callbacks, on_next() queries if there is a new email
- * to send, on_get_body() asks for the body of the email, and on_sent() is
- * called after the email is successfully sent.
- *
- * To use it
- *
- * - create an lws_email struct
- *
- * - initialize data, loop, the email_* strings, max_content_size and
- * the callbacks
- *
- * - call lws_email_init()
- *
- * When you have at least one email to send, call lws_email_check() to
- * schedule starting to send it.
- */
-//@{
-#ifdef LWS_WITH_SMTP
-
-/** enum lwsgs_smtp_states - where we are in SMTP protocol sequence */
-enum lwsgs_smtp_states {
- LGSSMTP_IDLE, /**< awaiting new email */
- LGSSMTP_CONNECTING, /**< opening tcp connection to MTA */
- LGSSMTP_CONNECTED, /**< tcp connection to MTA is connected */
- LGSSMTP_SENT_HELO, /**< sent the HELO */
- LGSSMTP_SENT_FROM, /**< sent FROM */
- LGSSMTP_SENT_TO, /**< sent TO */
- LGSSMTP_SENT_DATA, /**< sent DATA request */
- LGSSMTP_SENT_BODY, /**< sent the email body */
- LGSSMTP_SENT_QUIT, /**< sent the session quit */
-};
-
-/** struct lws_email - abstract context for performing SMTP operations */
-struct lws_email {
- void *data;
- /**< opaque pointer set by user code and available to the callbacks */
- uv_loop_t *loop;
- /**< the libuv loop we will work on */
-
- char email_smtp_ip[32]; /**< Fill before init, eg, "127.0.0.1" */
- char email_helo[32]; /**< Fill before init, eg, "myserver.com" */
- char email_from[100]; /**< Fill before init or on_next */
- char email_to[100]; /**< Fill before init or on_next */
-
- unsigned int max_content_size;
- /**< largest possible email body size */
-
- /* Fill all the callbacks before init */
-
- int (*on_next)(struct lws_email *email);
- /**< (Fill in before calling lws_email_init)
- * called when idle, 0 = another email to send, nonzero is idle.
- * If you return 0, all of the email_* char arrays must be set
- * to something useful. */
- int (*on_sent)(struct lws_email *email);
- /**< (Fill in before calling lws_email_init)
- * called when transfer of the email to the SMTP server was
- * successful, your callback would remove the current email
- * from its queue */
- int (*on_get_body)(struct lws_email *email, char *buf, int len);
- /**< (Fill in before calling lws_email_init)
- * called when the body part of the queued email is about to be
- * sent to the SMTP server. */
-
-
- /* private things */
- uv_timer_t timeout_email; /**< private */
- enum lwsgs_smtp_states estate; /**< private */
- uv_connect_t email_connect_req; /**< private */
- uv_tcp_t email_client; /**< private */
- time_t email_connect_started; /**< private */
- char email_buf[256]; /**< private */
- char *content; /**< private */
-};
-
-/**
- * lws_email_init() - Initialize a struct lws_email
- *
- * \param email: struct lws_email to init
- * \param loop: libuv loop to use
- * \param max_content: max email content size
- *
- * Prepares a struct lws_email for use ending SMTP
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_email_init(struct lws_email *email, uv_loop_t *loop, int max_content);
-
-/**
- * lws_email_check() - Request check for new email
- *
- * \param email: struct lws_email context to check
- *
- * Schedules a check for new emails in 1s... call this when you have queued an
- * email for send.
- */
-LWS_VISIBLE LWS_EXTERN void
-lws_email_check(struct lws_email *email);
-/**
- * lws_email_destroy() - stop using the struct lws_email
- *
- * \param email: the struct lws_email context
- *
- * Stop sending email using email and free allocations
- */
-LWS_VISIBLE LWS_EXTERN void
-lws_email_destroy(struct lws_email *email);
-
-#endif
-//@}
-
-
-/** \defgroup lejp JSON parser
- * ##JSON parsing related functions
- * \ingroup lwsapi
- *
- * LEJP is an extremely lightweight JSON stream parser included in lws.
- */
-//@{
-struct lejp_ctx;
-
-#define LWS_ARRAY_SIZE(_x) (sizeof(_x) / sizeof(_x[0]))
-#define LEJP_FLAG_WS_KEEP 64
-#define LEJP_FLAG_WS_COMMENTLINE 32
-
-enum lejp_states {
- LEJP_IDLE = 0,
- LEJP_MEMBERS = 1,
- LEJP_M_P = 2,
- LEJP_MP_STRING = LEJP_FLAG_WS_KEEP | 3,
- LEJP_MP_STRING_ESC = LEJP_FLAG_WS_KEEP | 4,
- LEJP_MP_STRING_ESC_U1 = LEJP_FLAG_WS_KEEP | 5,
- LEJP_MP_STRING_ESC_U2 = LEJP_FLAG_WS_KEEP | 6,
- LEJP_MP_STRING_ESC_U3 = LEJP_FLAG_WS_KEEP | 7,
- LEJP_MP_STRING_ESC_U4 = LEJP_FLAG_WS_KEEP | 8,
- LEJP_MP_DELIM = 9,
- LEJP_MP_VALUE = 10,
- LEJP_MP_VALUE_NUM_INT = LEJP_FLAG_WS_KEEP | 11,
- LEJP_MP_VALUE_NUM_EXP = LEJP_FLAG_WS_KEEP | 12,
- LEJP_MP_VALUE_TOK = LEJP_FLAG_WS_KEEP | 13,
- LEJP_MP_COMMA_OR_END = 14,
- LEJP_MP_ARRAY_END = 15,
-};
-
-enum lejp_reasons {
- LEJP_CONTINUE = -1,
- LEJP_REJECT_IDLE_NO_BRACE = -2,
- LEJP_REJECT_MEMBERS_NO_CLOSE = -3,
- LEJP_REJECT_MP_NO_OPEN_QUOTE = -4,
- LEJP_REJECT_MP_STRING_UNDERRUN = -5,
- LEJP_REJECT_MP_ILLEGAL_CTRL = -6,
- LEJP_REJECT_MP_STRING_ESC_ILLEGAL_ESC = -7,
- LEJP_REJECT_ILLEGAL_HEX = -8,
- LEJP_REJECT_MP_DELIM_MISSING_COLON = -9,
- LEJP_REJECT_MP_DELIM_BAD_VALUE_START = -10,
- LEJP_REJECT_MP_VAL_NUM_INT_NO_FRAC = -11,
- LEJP_REJECT_MP_VAL_NUM_FORMAT = -12,
- LEJP_REJECT_MP_VAL_NUM_EXP_BAD_EXP = -13,
- LEJP_REJECT_MP_VAL_TOK_UNKNOWN = -14,
- LEJP_REJECT_MP_C_OR_E_UNDERF = -15,
- LEJP_REJECT_MP_C_OR_E_NOTARRAY = -16,
- LEJP_REJECT_MP_ARRAY_END_MISSING = -17,
- LEJP_REJECT_STACK_OVERFLOW = -18,
- LEJP_REJECT_MP_DELIM_ISTACK = -19,
- LEJP_REJECT_NUM_TOO_LONG = -20,
- LEJP_REJECT_MP_C_OR_E_NEITHER = -21,
- LEJP_REJECT_UNKNOWN = -22,
- LEJP_REJECT_CALLBACK = -23
-};
-
-#define LEJP_FLAG_CB_IS_VALUE 64
-
-enum lejp_callbacks {
- LEJPCB_CONSTRUCTED = 0,
- LEJPCB_DESTRUCTED = 1,
-
- LEJPCB_START = 2,
- LEJPCB_COMPLETE = 3,
- LEJPCB_FAILED = 4,
-
- LEJPCB_PAIR_NAME = 5,
-
- LEJPCB_VAL_TRUE = LEJP_FLAG_CB_IS_VALUE | 6,
- LEJPCB_VAL_FALSE = LEJP_FLAG_CB_IS_VALUE | 7,
- LEJPCB_VAL_NULL = LEJP_FLAG_CB_IS_VALUE | 8,
- LEJPCB_VAL_NUM_INT = LEJP_FLAG_CB_IS_VALUE | 9,
- LEJPCB_VAL_NUM_FLOAT = LEJP_FLAG_CB_IS_VALUE | 10,
- LEJPCB_VAL_STR_START = 11, /* notice handle separately */
- LEJPCB_VAL_STR_CHUNK = LEJP_FLAG_CB_IS_VALUE | 12,
- LEJPCB_VAL_STR_END = LEJP_FLAG_CB_IS_VALUE | 13,
-
- LEJPCB_ARRAY_START = 14,
- LEJPCB_ARRAY_END = 15,
-
- LEJPCB_OBJECT_START = 16,
- LEJPCB_OBJECT_END = 17
-};
-
-/**
- * _lejp_callback() - User parser actions
- * \param ctx: LEJP context
- * \param reason: Callback reason
- *
- * Your user callback is associated with the context at construction time,
- * and receives calls as the parsing progresses.
- *
- * All of the callbacks may be ignored and just return 0.
- *
- * The reasons it might get called, found in @reason, are:
- *
- * LEJPCB_CONSTRUCTED: The context was just constructed... you might want to
- * perform one-time allocation for the life of the context.
- *
- * LEJPCB_DESTRUCTED: The context is being destructed... if you made any
- * allocations at construction-time, you can free them now
- *
- * LEJPCB_START: Parsing is beginning at the first byte of input
- *
- * LEJPCB_COMPLETE: Parsing has completed successfully. You'll get a 0 or
- * positive return code from lejp_parse indicating the
- * amount of unused bytes left in the input buffer
- *
- * LEJPCB_FAILED: Parsing failed. You'll get a negative error code
- * returned from lejp_parse
- *
- * LEJPCB_PAIR_NAME: When a "name":"value" pair has had the name parsed,
- * this callback occurs. You can find the new name at
- * the end of ctx->path[]
- *
- * LEJPCB_VAL_TRUE: The "true" value appeared
- *
- * LEJPCB_VAL_FALSE: The "false" value appeared
- *
- * LEJPCB_VAL_NULL: The "null" value appeared
- *
- * LEJPCB_VAL_NUM_INT: A string representing an integer is in ctx->buf
- *
- * LEJPCB_VAL_NUM_FLOAT: A string representing a float is in ctx->buf
- *
- * LEJPCB_VAL_STR_START: We are starting to parse a string, no data yet
- *
- * LEJPCB_VAL_STR_CHUNK: We parsed LEJP_STRING_CHUNK -1 bytes of string data in
- * ctx->buf, which is as much as we can buffer, so we are
- * spilling it. If all your strings are less than
- * LEJP_STRING_CHUNK - 1 bytes, you will never see this
- * callback.
- *
- * LEJPCB_VAL_STR_END: String parsing has completed, the last chunk of the
- * string is in ctx->buf.
- *
- * LEJPCB_ARRAY_START: An array started
- *
- * LEJPCB_ARRAY_END: An array ended
- *
- * LEJPCB_OBJECT_START: An object started
- *
- * LEJPCB_OBJECT_END: An object ended
- */
-LWS_EXTERN signed char _lejp_callback(struct lejp_ctx *ctx, char reason);
-
-typedef signed char (*lejp_callback)(struct lejp_ctx *ctx, char reason);
-
-#ifndef LEJP_MAX_DEPTH
-#define LEJP_MAX_DEPTH 12
-#endif
-#ifndef LEJP_MAX_INDEX_DEPTH
-#define LEJP_MAX_INDEX_DEPTH 5
-#endif
-#ifndef LEJP_MAX_PATH
-#define LEJP_MAX_PATH 128
-#endif
-#ifndef LEJP_STRING_CHUNK
-/* must be >= 30 to assemble floats */
-#define LEJP_STRING_CHUNK 254
-#endif
-
-enum num_flags {
- LEJP_SEEN_MINUS = (1 << 0),
- LEJP_SEEN_POINT = (1 << 1),
- LEJP_SEEN_POST_POINT = (1 << 2),
- LEJP_SEEN_EXP = (1 << 3)
-};
-
-struct _lejp_stack {
- char s; /* lejp_state stack*/
- char p; /* path length */
- char i; /* index array length */
- char b; /* user bitfield */
-};
-
-struct lejp_ctx {
-
- /* sorted by type for most compact alignment
- *
- * pointers
- */
-
- signed char (*callback)(struct lejp_ctx *ctx, char reason);
- void *user;
- const char * const *paths;
-
- /* arrays */
-
- struct _lejp_stack st[LEJP_MAX_DEPTH];
- uint16_t i[LEJP_MAX_INDEX_DEPTH]; /* index array */
- uint16_t wild[LEJP_MAX_INDEX_DEPTH]; /* index array */
- char path[LEJP_MAX_PATH];
- char buf[LEJP_STRING_CHUNK + 1];
-
- /* int */
-
- uint32_t line;
-
- /* short */
-
- uint16_t uni;
-
- /* char */
-
- uint8_t npos;
- uint8_t dcount;
- uint8_t f;
- uint8_t sp; /* stack head */
- uint8_t ipos; /* index stack depth */
- uint8_t ppos;
- uint8_t count_paths;
- uint8_t path_match;
- uint8_t path_match_len;
- uint8_t wildcount;
-};
-
-LWS_VISIBLE LWS_EXTERN void
-lejp_construct(struct lejp_ctx *ctx,
- signed char (*callback)(struct lejp_ctx *ctx, char reason),
- void *user, const char * const *paths, unsigned char paths_count);
-
-LWS_VISIBLE LWS_EXTERN void
-lejp_destruct(struct lejp_ctx *ctx);
-
-LWS_VISIBLE LWS_EXTERN int
-lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len);
-
-LWS_VISIBLE LWS_EXTERN void
-lejp_change_callback(struct lejp_ctx *ctx,
- signed char (*callback)(struct lejp_ctx *ctx, char reason));
-
-LWS_VISIBLE LWS_EXTERN int
-lejp_get_wildcard(struct lejp_ctx *ctx, int wildcard, char *dest, int len);
-//@}
-
-/*
- * Stats are all uint64_t numbers that start at 0.
- * Index names here have the convention
- *
- * _C_ counter
- * _B_ byte count
- * _MS_ millisecond count
- */
-
-enum {
- LWSSTATS_C_CONNECTIONS, /**< count incoming connections */
- LWSSTATS_C_API_CLOSE, /**< count calls to close api */
- LWSSTATS_C_API_READ, /**< count calls to read from socket api */
- LWSSTATS_C_API_LWS_WRITE, /**< count calls to lws_write API */
- LWSSTATS_C_API_WRITE, /**< count calls to write API */
- LWSSTATS_C_WRITE_PARTIALS, /**< count of partial writes */
- LWSSTATS_C_WRITEABLE_CB_REQ, /**< count of writable callback requests */
- LWSSTATS_C_WRITEABLE_CB_EFF_REQ, /**< count of effective writable callback requests */
- LWSSTATS_C_WRITEABLE_CB, /**< count of writable callbacks */
- LWSSTATS_C_SSL_CONNECTIONS_FAILED, /**< count of failed SSL connections */
- LWSSTATS_C_SSL_CONNECTIONS_ACCEPTED, /**< count of accepted SSL connections */
- LWSSTATS_C_SSL_CONNECTIONS_ACCEPT_SPIN, /**< count of SSL_accept() attempts */
- LWSSTATS_C_SSL_CONNS_HAD_RX, /**< count of accepted SSL conns that have had some RX */
- LWSSTATS_C_TIMEOUTS, /**< count of timed-out connections */
- LWSSTATS_C_SERVICE_ENTRY, /**< count of entries to lws service loop */
- LWSSTATS_B_READ, /**< aggregate bytes read */
- LWSSTATS_B_WRITE, /**< aggregate bytes written */
- LWSSTATS_B_PARTIALS_ACCEPTED_PARTS, /**< aggreate of size of accepted write data from new partials */
- LWSSTATS_MS_SSL_CONNECTIONS_ACCEPTED_DELAY, /**< aggregate delay in accepting connection */
- LWSSTATS_MS_WRITABLE_DELAY, /**< aggregate delay between asking for writable and getting cb */
- LWSSTATS_MS_WORST_WRITABLE_DELAY, /**< single worst delay between asking for writable and getting cb */
- LWSSTATS_MS_SSL_RX_DELAY, /**< aggregate delay between ssl accept complete and first RX */
- LWSSTATS_C_PEER_LIMIT_AH_DENIED, /**< number of times we would have given an ah but for the peer limit */
- LWSSTATS_C_PEER_LIMIT_WSI_DENIED, /**< number of times we would have given a wsi but for the peer limit */
-
- /* Add new things just above here ---^
- * This is part of the ABI, don't needlessly break compatibility */
- LWSSTATS_SIZE
-};
-
-#if defined(LWS_WITH_STATS)
-
-LWS_VISIBLE LWS_EXTERN uint64_t
-lws_stats_get(struct lws_context *context, int index);
-LWS_VISIBLE LWS_EXTERN void
-lws_stats_log_dump(struct lws_context *context);
-#else
-static LWS_INLINE uint64_t
-lws_stats_get(struct lws_context *context, int index) { (void)context; (void)index; return 0; }
-static LWS_INLINE void
-lws_stats_log_dump(struct lws_context *context) { (void)context; }
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/thirdparty/libwebsockets/lws_config.h b/thirdparty/libwebsockets/lws_config.h
deleted file mode 100644
index fdf02157cc..0000000000
--- a/thirdparty/libwebsockets/lws_config.h
+++ /dev/null
@@ -1,195 +0,0 @@
-/* lws_config.h Generated from lws_config.h.in */
-
-/* GODOT ADDITION */
-#ifndef DEBUG_ENABLED
-#define LWS_WITH_NO_LOGS
-#endif
-/* END GODOT ADDITION */
-
-#ifndef NDEBUG
- #ifndef _DEBUG
- #define _DEBUG
- #endif
-#endif
-
-#define LWS_INSTALL_DATADIR "/usr/local/share"
-
-#define LWS_ROLE_H1
-#define LWS_ROLE_WS
-#define LWS_ROLE_RAW
-/* #undef LWS_ROLE_H2 */
-/* #undef LWS_ROLE_CGI */
-
-/* Define to 1 to use wolfSSL/CyaSSL as a replacement for OpenSSL.
- * LWS_OPENSSL_SUPPORT needs to be set also for this to work. */
-/* #undef USE_WOLFSSL */
-
-/* Also define to 1 (in addition to USE_WOLFSSL) when using the
- (older) CyaSSL library */
-/* #undef USE_OLD_CYASSL */
-/* #undef LWS_WITH_BORINGSSL */
-
-#define LWS_WITH_MBEDTLS
-/* #undef LWS_WITH_POLARSSL */
-/* #undef LWS_WITH_ESP32 */
-
-/* #undef LWS_WITH_PLUGINS */
-/* #undef LWS_WITH_NO_LOGS */
-
-/* The Libwebsocket version */
-#define LWS_LIBRARY_VERSION "3.0.0"
-
-#define LWS_LIBRARY_VERSION_MAJOR 3
-#define LWS_LIBRARY_VERSION_MINOR 0
-#define LWS_LIBRARY_VERSION_PATCH 0
-/* LWS_LIBRARY_VERSION_NUMBER looks like 1005001 for e.g. version 1.5.1 */
-#define LWS_LIBRARY_VERSION_NUMBER (LWS_LIBRARY_VERSION_MAJOR*1000000)+(LWS_LIBRARY_VERSION_MINOR*1000)+LWS_LIBRARY_VERSION_PATCH
-
-/* The current git commit hash that we're building from */
-#define LWS_BUILD_HASH "v2.0.0-948-geaa935a8"
-
-/* Build with OpenSSL support ... alias of LWS_WITH_TLS for compatibility*/
-#define LWS_OPENSSL_SUPPORT
-#define LWS_WITH_TLS
-
-/* The client should load and trust CA root certs it finds in the OS */
-/* #undef LWS_SSL_CLIENT_USE_OS_CA_CERTS */
-
-/* Sets the path where the client certs should be installed. */
-/* #undef LWS_OPENSSL_CLIENT_CERTS "../share" */
-
-/* Turn off websocket extensions */
-#define LWS_WITHOUT_EXTENSIONS
-
-/* notice if client or server gone */
-/* #undef LWS_WITHOUT_SERVER */
-/* #undef LWS_WITHOUT_CLIENT */
-
-#define LWS_WITH_POLL
-
-/* Enable libev io loop */
-/* #undef LWS_WITH_LIBEV */
-
-/* Enable libuv io loop */
-/* #undef LWS_WITH_LIBUV */
-
-/* Enable libevent io loop */
-/* #undef LWS_WITH_LIBEVENT */
-
-/* Build with support for ipv6 */
-/* Everywhere, except in OpenBSD which does not support dual stacking */
-#if !defined(__OpenBSD__)
-#define LWS_WITH_IPV6
-#endif
-
-/* Build with support for UNIX domain socket */
-/* #undef LWS_WITH_UNIX_SOCK */
-
-/* Build with support for HTTP2 */
-/* #undef LWS_WITH_HTTP2 */
-
-/* Turn on latency measuring code */
-/* #undef LWS_LATENCY */
-
-/* Don't build the daemonizeation api */
-#define LWS_NO_DAEMONIZE
-
-/* Build without server support */
-/* #undef LWS_NO_SERVER */
-
-/* Build without client support */
-/* #undef LWS_NO_CLIENT */
-
-/* If we should compile with MinGW support */
-/* #undef LWS_MINGW_SUPPORT */
-
-/* Use the BSD getifaddrs that comes with libwebsocket, for uclibc support */
-/* #undef LWS_BUILTIN_GETIFADDRS */
-
-/* use SHA1() not internal libwebsockets_SHA1 */
-/* #undef LWS_SHA1_USE_OPENSSL_NAME */
-
-/* SSL server using ECDH certificate */
-/* #undef LWS_SSL_SERVER_WITH_ECDH_CERT */
-/* #undef LWS_HAVE_SSL_CTX_set1_param */
-#define LWS_HAVE_X509_VERIFY_PARAM_set1_host
-/* #undef LWS_HAVE_RSA_SET0_KEY */
-/* #undef LWS_HAVE_X509_get_key_usage */
-/* #undef LWS_HAVE_SSL_CTX_get0_certificate */
-
-/* #undef LWS_HAVE_UV_VERSION_H */
-/* #undef LWS_HAVE_PTHREAD_H */
-
-/* CGI apis */
-/* #undef LWS_WITH_CGI */
-
-/* whether the Openssl is recent enough, and / or built with, ecdh */
-/* #undef LWS_HAVE_OPENSSL_ECDH_H */
-
-/* HTTP Proxy support */
-/* #undef LWS_WITH_HTTP_PROXY */
-
-/* HTTP Ranges support */
-/* #undef LWS_WITH_RANGES */
-
-/* Http access log support */
-/* #undef LWS_WITH_ACCESS_LOG */
-/* #undef LWS_WITH_SERVER_STATUS */
-
-/* #undef LWS_WITH_STATEFUL_URLDECODE */
-/* #undef LWS_WITH_PEER_LIMITS */
-
-/* Maximum supported service threads */
-#define LWS_MAX_SMP 1
-
-/* Lightweight JSON Parser */
-/* #undef LWS_WITH_LEJP */
-
-/* SMTP */
-/* #undef LWS_WITH_SMTP */
-
-/* OPTEE */
-/* #undef LWS_PLAT_OPTEE */
-
-/* ZIP FOPS */
-/* #undef LWS_WITH_ZIP_FOPS */
-#define LWS_HAVE_STDINT_H
-
-/* #undef LWS_AVOID_SIGPIPE_IGN */
-
-/* #undef LWS_FALLBACK_GETHOSTBYNAME */
-
-/* #undef LWS_WITH_STATS */
-/* #undef LWS_WITH_SOCKS5 */
-
-/* #undef LWS_HAVE_SYS_CAPABILITY_H */
-/* #undef LWS_HAVE_LIBCAP */
-
-#define LWS_HAVE_ATOLL
-/* #undef LWS_HAVE__ATOI64 */
-/* #undef LWS_HAVE__STAT32I64 */
-
-/* #undef LWS_WITH_JWS */
-/* #undef LWS_WITH_ACME */
-/* #undef LWS_WITH_SELFTESTS */
-
-#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
-#define LWS_HAVE_MALLOC_H
-#endif
-
-#if !defined(__APPLE__) && !defined(__HAIKU__)
-#define LWS_HAVE_PIPE2
-#endif
-
-/* OpenSSL various APIs */
-
-#define LWS_HAVE_TLS_CLIENT_METHOD
-/* #undef LWS_HAVE_TLSV1_2_CLIENT_METHOD */
-/* #undef LWS_HAVE_SSL_SET_INFO_CALLBACK */
-/* #undef LWS_HAVE_SSL_EXTRA_CHAIN_CERTS */
-/* #undef LWS_HAVE_SSL_get0_alpn_selected */
-/* #undef LWS_HAVE_SSL_set_alpn_protos */
-
-#define LWS_HAS_INTPTR_T
-
-
diff --git a/thirdparty/libwebsockets/lws_config_private.h b/thirdparty/libwebsockets/lws_config_private.h
deleted file mode 100644
index e531777624..0000000000
--- a/thirdparty/libwebsockets/lws_config_private.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/* lws_config_private.h.in. Private compilation options. */
-#ifndef DEBUG_ENABLED
-#define NDEBUG
-#endif
-
-#ifndef NDEBUG
- #ifndef _DEBUG
- #define _DEBUG
- #endif
-#endif
-
-/* Define to 1 to use CyaSSL as a replacement for OpenSSL.
- * LWS_OPENSSL_SUPPORT needs to be set also for this to work. */
-/* #undef USE_CYASSL */
-
-/* Define to 1 if you have the `bzero' function. */
-#define LWS_HAVE_BZERO
-/* Windows has no bzero function */
-#ifdef WINDOWS_ENABLED
-#undef LWS_HAVE_BZERO
-#endif
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#define LWS_HAVE_DLFCN_H
-
-/* Define to 1 if you have the <fcntl.h> header file. */
-#define LWS_HAVE_FCNTL_H
-#ifdef NO_FCNTL
-#undef LWS_HAVE_FCNTL_H
-#endif
-
-/* Define to 1 if you have the `fork' function. */
-#define LWS_HAVE_FORK
-
-/* Define to 1 if you have the `getenv’ function. */
-#define LWS_HAVE_GETENV
-
-/* Define to 1 if you have the <in6addr.h> header file. */
-/* #undef LWS_HAVE_IN6ADDR_H */
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#define LWS_HAVE_INTTYPES_H
-
-/* Define to 1 if you have the `ssl' library (-lssl). */
-/* #undef LWS_HAVE_LIBSSL */
-
-/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
- to 0 otherwise. */
-#define LWS_HAVE_MALLOC
-
-/* Define to 1 if you have the <memory.h> header file. */
-#define LWS_HAVE_MEMORY_H
-
-/* Define to 1 if you have the `memset' function. */
-#define LWS_HAVE_MEMSET
-
-/* Define to 1 if you have the <netinet/in.h> header file. */
-#define LWS_HAVE_NETINET_IN_H
-
-/* Define to 1 if your system has a GNU libc compatible `realloc' function,
- and to 0 otherwise. */
-#define LWS_HAVE_REALLOC
-
-/* Define to 1 if you have the `socket' function. */
-#define LWS_HAVE_SOCKET
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define LWS_HAVE_STDINT_H
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define LWS_HAVE_STDLIB_H
-
-/* Define to 1 if you have the `strerror' function. */
-#define LWS_HAVE_STRERROR
-
-/* Define to 1 if you have the <strings.h> header file. */
-#define LWS_HAVE_STRINGS_H
-
-/* Define to 1 if you have the <string.h> header file. */
-#define LWS_HAVE_STRING_H
-
-/* Define to 1 if you have the <sys/prctl.h> header file. */
-#define LWS_HAVE_SYS_PRCTL_H
-#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__HAIKU__)
-#undef LWS_HAVE_SYS_PRCTL_H
-#endif
-
-/* Define to 1 if you have the <sys/socket.h> header file. */
-#define LWS_HAVE_SYS_SOCKET_H
-
-/* Define to 1 if you have the <sys/sockio.h> header file. */
-/* #undef LWS_HAVE_SYS_SOCKIO_H */
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define LWS_HAVE_SYS_STAT_H
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define LWS_HAVE_SYS_TYPES_H
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#define LWS_HAVE_UNISTD_H
-
-#define LWS_HAVE_TCP_USER_TIMEOUT
-
-/* Define to 1 if you have the `vfork' function. */
-#define LWS_HAVE_VFORK
-
-/* Define to 1 if you have the <vfork.h> header file. */
-/* #undef LWS_HAVE_VFORK_H */
-
-/* Define to 1 if `fork' works. */
-#define LWS_HAVE_WORKING_FORK
-
-/* Define to 1 if `vfork' works. */
-#define LWS_HAVE_WORKING_VFORK
-
-/* Define to 1 if execvpe() exists */
-#define LWS_HAVE_EXECVPE
-
-/* Define to 1 if you have the <zlib.h> header file. */
-#define LWS_HAVE_ZLIB_H
-
-#define LWS_HAVE_GETLOADAVG
-
-/* Define to the sub-directory in which libtool stores uninstalled libraries.
- */
-#undef LT_OBJDIR // We're not using libtool
-
-/* Define to rpl_malloc if the replacement function should be used. */
-/* #undef malloc */
-
-/* Define to rpl_realloc if the replacement function should be used. */
-/* #undef realloc */
-
-/* Define to 1 if we have getifaddrs */
-#define LWS_HAVE_GETIFADDRS
-#if defined(ANDROID_ENABLED)
-#undef LWS_HAVE_GETIFADDRS
-#define LWS_BUILTIN_GETIFADDRS
-#endif
-
-/* Define if the inline keyword doesn't exist. */
-/* #undef inline */
-
-
diff --git a/thirdparty/libwebsockets/misc/base64-decode.c b/thirdparty/libwebsockets/misc/base64-decode.c
deleted file mode 100644
index 64b84d78fa..0000000000
--- a/thirdparty/libwebsockets/misc/base64-decode.c
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * This code originally came from here
- *
- * http://base64.sourceforge.net/b64.c
- *
- * with the following license:
- *
- * LICENCE: Copyright (c) 2001 Bob Trower, Trantor Standard Systems Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated
- * documentation files (the "Software"), to deal in the
- * Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute,
- * sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall
- * be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
- * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
- * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
- * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * VERSION HISTORY:
- * Bob Trower 08/04/01 -- Create Version 0.00.00B
- *
- * I cleaned it up quite a bit to match the (linux kernel) style of the rest
- * of libwebsockets; this version is under LGPL2.1 + SLE like the rest of lws
- * since he explicitly allows sublicensing, but I give the URL above so you can
- * get the original with Bob's super-liberal terms directly if you prefer.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include "core/private.h"
-
-static const char encode_orig[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz0123456789+/";
-static const char encode_url[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz0123456789-_";
-static const char decode[] = "|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW"
- "$$$$$$XYZ[\\]^_`abcdefghijklmnopq";
-
-static int
-_lws_b64_encode_string(const char *encode, const char *in, int in_len,
- char *out, int out_size)
-{
- unsigned char triple[3];
- int i;
- int len;
- int line = 0;
- int done = 0;
-
- while (in_len) {
- len = 0;
- for (i = 0; i < 3; i++) {
- if (in_len) {
- triple[i] = *in++;
- len++;
- in_len--;
- } else
- triple[i] = 0;
- }
-
- if (done + 4 >= out_size)
- return -1;
-
- *out++ = encode[triple[0] >> 2];
- *out++ = encode[((triple[0] & 0x03) << 4) |
- ((triple[1] & 0xf0) >> 4)];
- *out++ = (len > 1 ? encode[((triple[1] & 0x0f) << 2) |
- ((triple[2] & 0xc0) >> 6)] : '=');
- *out++ = (len > 2 ? encode[triple[2] & 0x3f] : '=');
-
- done += 4;
- line += 4;
- }
-
- if (done + 1 >= out_size)
- return -1;
-
- *out++ = '\0';
-
- return done;
-}
-
-LWS_VISIBLE int
-lws_b64_encode_string(const char *in, int in_len, char *out, int out_size)
-{
- return _lws_b64_encode_string(encode_orig, in, in_len, out, out_size);
-}
-
-LWS_VISIBLE int
-lws_b64_encode_string_url(const char *in, int in_len, char *out, int out_size)
-{
- return _lws_b64_encode_string(encode_url, in, in_len, out, out_size);
-}
-
-/*
- * returns length of decoded string in out, or -1 if out was too small
- * according to out_size
- *
- * Only reads up to in_len chars, otherwise if in_len is -1 on entry reads until
- * the first NUL in the input.
- */
-
-static int
-_lws_b64_decode_string(const char *in, int in_len, char *out, int out_size)
-{
- int len, i, c = 0, done = 0;
- unsigned char v, quad[4];
-
- while (in_len && *in) {
-
- len = 0;
- for (i = 0; i < 4 && in_len && *in; i++) {
-
- v = 0;
- c = 0;
- while (in_len && *in && !v) {
- c = v = *in++;
- in_len--;
- /* support the url base64 variant too */
- if (v == '-')
- c = v = '+';
- if (v == '_')
- c = v = '/';
- v = (v < 43 || v > 122) ? 0 : decode[v - 43];
- if (v)
- v = (v == '$') ? 0 : v - 61;
- }
- if (c) {
- len++;
- if (v)
- quad[i] = v - 1;
- } else
- quad[i] = 0;
- }
-
- if (out_size < (done + len - 1))
- /* out buffer is too small */
- return -1;
-
- /*
- * "The '==' sequence indicates that the last group contained
- * only one byte, and '=' indicates that it contained two
- * bytes." (wikipedia)
- */
-
- if ((!in_len || !*in) && c == '=')
- len--;
-
- if (len >= 2)
- *out++ = quad[0] << 2 | quad[1] >> 4;
- if (len >= 3)
- *out++ = quad[1] << 4 | quad[2] >> 2;
- if (len >= 4)
- *out++ = ((quad[2] << 6) & 0xc0) | quad[3];
-
- done += len - 1;
- }
-
- if (done + 1 >= out_size)
- return -1;
-
- *out = '\0';
-
- return done;
-}
-
-LWS_VISIBLE int
-lws_b64_decode_string(const char *in, char *out, int out_size)
-{
- return _lws_b64_decode_string(in, -1, out, out_size);
-}
-
-LWS_VISIBLE int
-lws_b64_decode_string_len(const char *in, int in_len, char *out, int out_size)
-{
- return _lws_b64_decode_string(in, in_len, out, out_size);
-}
-
-#if 0
-int
-lws_b64_selftest(void)
-{
- char buf[64];
- unsigned int n, r = 0;
- unsigned int test;
- /* examples from https://en.wikipedia.org/wiki/Base64 */
- static const char * const plaintext[] = {
- "any carnal pleasure.",
- "any carnal pleasure",
- "any carnal pleasur",
- "any carnal pleasu",
- "any carnal pleas",
- "Admin:kloikloi"
- };
- static const char * const coded[] = {
- "YW55IGNhcm5hbCBwbGVhc3VyZS4=",
- "YW55IGNhcm5hbCBwbGVhc3VyZQ==",
- "YW55IGNhcm5hbCBwbGVhc3Vy",
- "YW55IGNhcm5hbCBwbGVhc3U=",
- "YW55IGNhcm5hbCBwbGVhcw==",
- "QWRtaW46a2xvaWtsb2k="
- };
-
- for (test = 0; test < sizeof plaintext / sizeof(plaintext[0]); test++) {
-
- buf[sizeof(buf) - 1] = '\0';
- n = lws_b64_encode_string(plaintext[test],
- strlen(plaintext[test]), buf, sizeof buf);
- if (n != strlen(coded[test]) || strcmp(buf, coded[test])) {
- lwsl_err("Failed lws_b64 encode selftest "
- "%d result '%s' %d\n", test, buf, n);
- r = -1;
- }
-
- buf[sizeof(buf) - 1] = '\0';
- n = lws_b64_decode_string(coded[test], buf, sizeof buf);
- if (n != strlen(plaintext[test]) ||
- strcmp(buf, plaintext[test])) {
- lwsl_err("Failed lws_b64 decode selftest "
- "%d result '%s' / '%s', %d / %d\n",
- test, buf, plaintext[test], n, strlen(plaintext[test]));
- r = -1;
- }
- }
-
- lwsl_notice("Base 64 selftests passed\n");
-
- return r;
-}
-#endif
diff --git a/thirdparty/libwebsockets/misc/getifaddrs.c b/thirdparty/libwebsockets/misc/getifaddrs.c
deleted file mode 100644
index 735b899f48..0000000000
--- a/thirdparty/libwebsockets/misc/getifaddrs.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright (c) 2000 - 2001 Kungliga Tekniska H�gskolan
- * (Royal Institute of Technology, Stockholm, Sweden).
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * 3. Neither the name of the Institute nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * originally downloaded from
- *
- * http://ftp.uninett.no/pub/OpenBSD/src/kerberosV/src/lib/roken/getifaddrs.c
- */
-
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <net/if.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-#include "core/private.h"
-
-#ifdef LWS_HAVE_SYS_SOCKIO_H
-#include <sys/sockio.h>
-#endif
-
-#ifdef LWS_HAVE_NETINET_IN6_VAR_H
-#include <netinet/in6_var.h>
-#endif
-
-#ifndef max
-#define max(a, b) ((a) > (b) ? (a) : (b))
-#endif
-
-#include "getifaddrs.h"
-
-static int
-getifaddrs2(struct ifaddrs **ifap, int af, int siocgifconf, int siocgifflags,
- size_t ifreq_sz)
-{
- int ret;
- int fd;
- size_t buf_size;
- char *buf;
- struct ifconf ifconf;
- char *p;
- size_t sz;
- struct sockaddr sa_zero;
- struct ifreq *ifr;
- struct ifaddrs *start, **end = &start;
-
- buf = NULL;
-
- memset(&sa_zero, 0, sizeof(sa_zero));
- fd = socket(af, SOCK_DGRAM, 0);
- if (fd < 0)
- return -1;
-
- buf_size = 8192;
- for (;;) {
- buf = lws_zalloc(buf_size, "getifaddrs2");
- if (buf == NULL) {
- ret = ENOMEM;
- goto error_out;
- }
- ifconf.ifc_len = buf_size;
- ifconf.ifc_buf = buf;
-
- /*
- * Solaris returns EINVAL when the buffer is too small.
- */
- if (ioctl(fd, siocgifconf, &ifconf) < 0 && errno != EINVAL) {
- ret = errno;
- goto error_out;
- }
- /*
- * Can the difference between a full and a overfull buf
- * be determined?
- */
-
- if (ifconf.ifc_len < (int)buf_size)
- break;
- lws_free(buf);
- buf_size *= 2;
- }
-
- for (p = ifconf.ifc_buf; p < ifconf.ifc_buf + ifconf.ifc_len; p += sz) {
- struct ifreq ifreq;
- struct sockaddr *sa;
- size_t salen;
-
- ifr = (struct ifreq *)p;
- sa = &ifr->ifr_addr;
-
- sz = ifreq_sz;
- salen = sizeof(struct sockaddr);
-#ifdef LWS_HAVE_STRUCT_SOCKADDR_SA_LEN
- salen = sa->sa_len;
- sz = max(sz, sizeof(ifr->ifr_name) + sa->sa_len);
-#endif
-#ifdef SA_LEN
- salen = SA_LEN(sa);
- sz = max(sz, sizeof(ifr->ifr_name) + SA_LEN(sa));
-#endif
- memset(&ifreq, 0, sizeof(ifreq));
- memcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifr->ifr_name));
-
- if (ioctl(fd, siocgifflags, &ifreq) < 0) {
- ret = errno;
- goto error_out;
- }
-
- *end = lws_malloc(sizeof(**end), "getifaddrs");
-
- (*end)->ifa_next = NULL;
- (*end)->ifa_name = strdup(ifr->ifr_name);
- (*end)->ifa_flags = ifreq.ifr_flags;
- (*end)->ifa_addr = lws_malloc(salen, "getifaddrs");
- memcpy((*end)->ifa_addr, sa, salen);
- (*end)->ifa_netmask = NULL;
-
-#if 0
- /* fix these when we actually need them */
- if (ifreq.ifr_flags & IFF_BROADCAST) {
- (*end)->ifa_broadaddr =
- lws_malloc(sizeof(ifr->ifr_broadaddr), "getifaddrs");
- memcpy((*end)->ifa_broadaddr, &ifr->ifr_broadaddr,
- sizeof(ifr->ifr_broadaddr));
- } else if (ifreq.ifr_flags & IFF_POINTOPOINT) {
- (*end)->ifa_dstaddr =
- lws_malloc(sizeof(ifr->ifr_dstaddr), "getifaddrs");
- memcpy((*end)->ifa_dstaddr, &ifr->ifr_dstaddr,
- sizeof(ifr->ifr_dstaddr));
- } else
- (*end)->ifa_dstaddr = NULL;
-#else
- (*end)->ifa_dstaddr = NULL;
-#endif
- (*end)->ifa_data = NULL;
-
- end = &(*end)->ifa_next;
-
- }
- *ifap = start;
- close(fd);
- lws_free(buf);
- return 0;
-
-error_out:
- close(fd);
- lws_free(buf);
- errno = ret;
-
- return -1;
-}
-
-int
-getifaddrs(struct ifaddrs **ifap)
-{
- int ret = -1;
- errno = ENXIO;
-#if defined(AF_INET6) && defined(SIOCGIF6CONF) && defined(SIOCGIF6FLAGS)
- if (ret)
- ret = getifaddrs2(ifap, AF_INET6, SIOCGIF6CONF, SIOCGIF6FLAGS,
- sizeof(struct in6_ifreq));
-#endif
-#if defined(LWS_HAVE_IPV6) && defined(SIOCGIFCONF)
- if (ret)
- ret = getifaddrs2(ifap, AF_INET6, SIOCGIFCONF, SIOCGIFFLAGS,
- sizeof(struct ifreq));
-#endif
-#if defined(AF_INET) && defined(SIOCGIFCONF) && defined(SIOCGIFFLAGS)
- if (ret)
- ret = getifaddrs2(ifap, AF_INET, SIOCGIFCONF, SIOCGIFFLAGS,
- sizeof(struct ifreq));
-#endif
- return ret;
-}
-
-void
-freeifaddrs(struct ifaddrs *ifp)
-{
- struct ifaddrs *p, *q;
-
- for (p = ifp; p; ) {
- lws_free(p->ifa_name);
- lws_free(p->ifa_addr);
- lws_free(p->ifa_dstaddr);
- lws_free(p->ifa_netmask);
- lws_free(p->ifa_data);
- q = p;
- p = p->ifa_next;
- lws_free(q);
- }
-}
-
-#ifdef TEST
-
-void
-print_addr(const char *s, struct sockaddr *sa)
-{
- int i;
- printf(" %s=%d/", s, sa->sa_family);
-#ifdef LWS_HAVE_STRUCT_SOCKADDR_SA_LEN
- for (i = 0;
- i < sa->sa_len - ((lws_intptr_t)sa->sa_data - (lws_intptr_t)&sa->sa_family); i++)
- printf("%02x", ((unsigned char *)sa->sa_data)[i]);
-#else
- for (i = 0; i < sizeof(sa->sa_data); i++)
- printf("%02x", ((unsigned char *)sa->sa_data)[i]);
-#endif
- printf("\n");
-}
-
-void
-print_ifaddrs(struct ifaddrs *x)
-{
- struct ifaddrs *p;
-
- for (p = x; p; p = p->ifa_next) {
- printf("%s\n", p->ifa_name);
- printf(" flags=%x\n", p->ifa_flags);
- if (p->ifa_addr)
- print_addr("addr", p->ifa_addr);
- if (p->ifa_dstaddr)
- print_addr("dstaddr", p->ifa_dstaddr);
- if (p->ifa_netmask)
- print_addr("netmask", p->ifa_netmask);
- printf(" %p\n", p->ifa_data);
- }
-}
-
-int
-main()
-{
- struct ifaddrs *a = NULL, *b;
- getifaddrs2(&a, AF_INET, SIOCGIFCONF, SIOCGIFFLAGS,
- sizeof(struct ifreq));
- print_ifaddrs(a);
- printf("---\n");
- getifaddrs(&b);
- print_ifaddrs(b);
- return 0;
-}
-#endif
diff --git a/thirdparty/libwebsockets/misc/getifaddrs.h b/thirdparty/libwebsockets/misc/getifaddrs.h
deleted file mode 100644
index d26670c082..0000000000
--- a/thirdparty/libwebsockets/misc/getifaddrs.h
+++ /dev/null
@@ -1,80 +0,0 @@
-#ifndef LWS_HAVE_GETIFADDRS
-#define LWS_HAVE_GETIFADDRS 0
-#endif
-
-#if LWS_HAVE_GETIFADDRS
-#include <sys/types.h>
-#include <ifaddrs.h>
-#else
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * Copyright (c) 2000 Kungliga Tekniska H�gskolan
- * (Royal Institute of Technology, Stockholm, Sweden).
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * 3. Neither the name of the Institute nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/* $KTH: ifaddrs.hin,v 1.3 2000/12/11 00:01:13 assar Exp $ */
-
-#ifndef ifaddrs_h_7467027A95AD4B5C8DDD40FE7D973791
-#define ifaddrs_h_7467027A95AD4B5C8DDD40FE7D973791
-
-/*
- * the interface is defined in terms of the fields below, and this is
- * sometimes #define'd, so there seems to be no simple way of solving
- * this and this seemed the best. */
-
-#undef ifa_dstaddr
-
-struct ifaddrs {
- struct ifaddrs *ifa_next;
- char *ifa_name;
- unsigned int ifa_flags;
- struct sockaddr *ifa_addr;
- struct sockaddr *ifa_netmask;
- struct sockaddr *ifa_dstaddr;
- void *ifa_data;
-};
-
-#ifndef ifa_broadaddr
-#define ifa_broadaddr ifa_dstaddr
-#endif
-
-int getifaddrs(struct ifaddrs **);
-
-void freeifaddrs(struct ifaddrs *);
-
-#endif /* __ifaddrs_h__ */
-
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/thirdparty/libwebsockets/misc/lejp.c b/thirdparty/libwebsockets/misc/lejp.c
deleted file mode 100644
index 99142b9553..0000000000
--- a/thirdparty/libwebsockets/misc/lejp.c
+++ /dev/null
@@ -1,753 +0,0 @@
-/*
- * Lightweight Embedded JSON Parser
- *
- * Copyright (C) 2013-2017 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- */
-
-#include <libwebsockets.h>
-#include "core/private.h"
-#include <string.h>
-#include <stdio.h>
-
-/**
- * lejp_construct - prepare a struct lejp_ctx for use
- *
- * \param ctx: pointer to your struct lejp_ctx
- * \param callback: your user callback which will received parsed tokens
- * \param user: optional user data pointer untouched by lejp
- * \param paths: your array of name elements you are interested in
- * \param count_paths: LWS_ARRAY_SIZE() of @paths
- *
- * Prepares your context struct for use with lejp
- */
-
-void
-lejp_construct(struct lejp_ctx *ctx,
- signed char (*callback)(struct lejp_ctx *ctx, char reason), void *user,
- const char * const *paths, unsigned char count_paths)
-{
- ctx->st[0].s = 0;
- ctx->st[0].p = 0;
- ctx->st[0].i = 0;
- ctx->st[0].b = 0;
- ctx->sp = 0;
- ctx->ipos = 0;
- ctx->ppos = 0;
- ctx->path_match = 0;
- ctx->path[0] = '\0';
- ctx->callback = callback;
- ctx->user = user;
- ctx->paths = paths;
- ctx->count_paths = count_paths;
- ctx->line = 1;
- ctx->callback(ctx, LEJPCB_CONSTRUCTED);
-}
-
-/**
- * lejp_destruct - retire a previously constructed struct lejp_ctx
- *
- * \param ctx: pointer to your struct lejp_ctx
- *
- * lejp does not perform any allocations, but since your user code might, this
- * provides a one-time LEJPCB_DESTRUCTED callback at destruction time where
- * you can clean up in your callback.
- */
-
-void
-lejp_destruct(struct lejp_ctx *ctx)
-{
- /* no allocations... just let callback know what it happening */
- ctx->callback(ctx, LEJPCB_DESTRUCTED);
-}
-
-/**
- * lejp_change_callback - switch to a different callback from now on
- *
- * \param ctx: pointer to your struct lejp_ctx
- * \param callback: your user callback which will received parsed tokens
- *
- * This tells the old callback it was destroyed, in case you want to take any
- * action because that callback "lost focus", then changes to the new
- * callback and tells it first that it was constructed, and then started.
- *
- * Changing callback is a cheap and powerful trick to split out handlers
- * according to information earlier in the parse. For example you may have
- * a JSON pair "schema" whose value defines what can be expected for the rest
- * of the JSON. Rather than having one huge callback for all cases, you can
- * have an initial one looking for "schema" which then calls
- * lejp_change_callback() to a handler specific for the schema.
- *
- * Notice that afterwards, you need to construct the context again anyway to
- * parse another JSON object, and the callback is reset then to the main,
- * schema-interpreting one. The construction action is very lightweight.
- */
-
-void
-lejp_change_callback(struct lejp_ctx *ctx,
- signed char (*callback)(struct lejp_ctx *ctx, char reason))
-{
- ctx->callback(ctx, LEJPCB_DESTRUCTED);
- ctx->callback = callback;
- ctx->callback(ctx, LEJPCB_CONSTRUCTED);
- ctx->callback(ctx, LEJPCB_START);
-}
-
-static void
-lejp_check_path_match(struct lejp_ctx *ctx)
-{
- const char *p, *q;
- int n;
-
- /* we only need to check if a match is not active */
- for (n = 0; !ctx->path_match && n < ctx->count_paths; n++) {
- ctx->wildcount = 0;
- p = ctx->path;
- q = ctx->paths[n];
- while (*p && *q) {
- if (*q != '*') {
- if (*p != *q)
- break;
- p++;
- q++;
- continue;
- }
- ctx->wild[ctx->wildcount++] = p - ctx->path;
- q++;
- /*
- * if * has something after it, match to .
- * if ends with *, eat everything.
- * This implies match sequences must be ordered like
- * x.*.*
- * x.*
- * if both options are possible
- */
- while (*p && (*p != '.' || !*q))
- p++;
- }
- if (*p || *q)
- continue;
-
- ctx->path_match = n + 1;
- ctx->path_match_len = ctx->ppos;
- return;
- }
-
- if (!ctx->path_match)
- ctx->wildcount = 0;
-}
-
-int
-lejp_get_wildcard(struct lejp_ctx *ctx, int wildcard, char *dest, int len)
-{
- int n;
-
- if (wildcard >= ctx->wildcount || !len)
- return 0;
-
- n = ctx->wild[wildcard];
-
- while (--len && n < ctx->ppos &&
- (n == ctx->wild[wildcard] || ctx->path[n] != '.'))
- *dest++ = ctx->path[n++];
-
- *dest = '\0';
- n++;
-
- return n - ctx->wild[wildcard];
-}
-
-/**
- * lejp_parse - interpret some more incoming data incrementally
- *
- * \param ctx: previously constructed parsing context
- * \param json: char buffer with the new data to interpret
- * \param len: amount of data in the buffer
- *
- * Because lejp is a stream parser, it incrementally parses as new data
- * becomes available, maintaining all state in the context struct. So an
- * incomplete JSON is a normal situation, getting you a LEJP_CONTINUE
- * return, signalling there's no error but to call again with more data when
- * it comes to complete the parsing. Successful parsing completes with a
- * 0 or positive integer indicating how much of the last input buffer was
- * unused.
- */
-
-int
-lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len)
-{
- unsigned char c, n, s, ret = LEJP_REJECT_UNKNOWN;
- static const char esc_char[] = "\"\\/bfnrt";
- static const char esc_tran[] = "\"\\/\b\f\n\r\t";
- static const char tokens[] = "rue alse ull ";
-
- if (!ctx->sp && !ctx->ppos)
- ctx->callback(ctx, LEJPCB_START);
-
- while (len--) {
- c = *json++;
- s = ctx->st[ctx->sp].s;
-
- /* skip whitespace unless we should care */
- if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '#') {
- if (c == '\n') {
- ctx->line++;
- ctx->st[ctx->sp].s &= ~LEJP_FLAG_WS_COMMENTLINE;
- }
- if (!(s & LEJP_FLAG_WS_KEEP)) {
- if (c == '#')
- ctx->st[ctx->sp].s |=
- LEJP_FLAG_WS_COMMENTLINE;
- continue;
- }
- }
-
- if (ctx->st[ctx->sp].s & LEJP_FLAG_WS_COMMENTLINE)
- continue;
-
- switch (s) {
- case LEJP_IDLE:
- if (c != '{') {
- ret = LEJP_REJECT_IDLE_NO_BRACE;
- goto reject;
- }
- if (ctx->callback(ctx, LEJPCB_OBJECT_START)) {
- ret = LEJP_REJECT_CALLBACK;
- goto reject;
- }
- ctx->st[ctx->sp].s = LEJP_MEMBERS;
- break;
- case LEJP_MEMBERS:
- if (c == '}') {
- ctx->st[ctx->sp].s = LEJP_IDLE;
- ret = LEJP_REJECT_MEMBERS_NO_CLOSE;
- goto reject;
- }
- ctx->st[ctx->sp].s = LEJP_M_P;
- goto redo_character;
- case LEJP_M_P:
- if (c != '\"') {
- ret = LEJP_REJECT_MP_NO_OPEN_QUOTE;
- goto reject;
- }
- /* push */
- ctx->st[ctx->sp].s = LEJP_MP_DELIM;
- c = LEJP_MP_STRING;
- goto add_stack_level;
-
- case LEJP_MP_STRING:
- if (c == '\"') {
- if (!ctx->sp) { /* JSON can't end on quote */
- ret = LEJP_REJECT_MP_STRING_UNDERRUN;
- goto reject;
- }
- if (ctx->st[ctx->sp - 1].s != LEJP_MP_DELIM) {
- ctx->buf[ctx->npos] = '\0';
- if (ctx->callback(ctx,
- LEJPCB_VAL_STR_END) < 0) {
- ret = LEJP_REJECT_CALLBACK;
- goto reject;
- }
- }
- /* pop */
- ctx->sp--;
- break;
- }
- if (c == '\\') {
- ctx->st[ctx->sp].s = LEJP_MP_STRING_ESC;
- break;
- }
- if (c < ' ') {/* "control characters" not allowed */
- ret = LEJP_REJECT_MP_ILLEGAL_CTRL;
- goto reject;
- }
- goto emit_string_char;
-
- case LEJP_MP_STRING_ESC:
- if (c == 'u') {
- ctx->st[ctx->sp].s = LEJP_MP_STRING_ESC_U1;
- ctx->uni = 0;
- break;
- }
- for (n = 0; n < sizeof(esc_char); n++) {
- if (c != esc_char[n])
- continue;
- /* found it */
- c = esc_tran[n];
- ctx->st[ctx->sp].s = LEJP_MP_STRING;
- goto emit_string_char;
- }
- ret = LEJP_REJECT_MP_STRING_ESC_ILLEGAL_ESC;
- /* illegal escape char */
- goto reject;
-
- case LEJP_MP_STRING_ESC_U1:
- case LEJP_MP_STRING_ESC_U2:
- case LEJP_MP_STRING_ESC_U3:
- case LEJP_MP_STRING_ESC_U4:
- ctx->uni <<= 4;
- if (c >= '0' && c <= '9')
- ctx->uni |= c - '0';
- else
- if (c >= 'a' && c <= 'f')
- ctx->uni = c - 'a' + 10;
- else
- if (c >= 'A' && c <= 'F')
- ctx->uni = c - 'A' + 10;
- else {
- ret = LEJP_REJECT_ILLEGAL_HEX;
- goto reject;
- }
- ctx->st[ctx->sp].s++;
- switch (s) {
- case LEJP_MP_STRING_ESC_U2:
- if (ctx->uni < 0x08)
- break;
- /*
- * 0x08-0xff (0x0800 - 0xffff)
- * emit 3-byte UTF-8
- */
- c = 0xe0 | ((ctx->uni >> 4) & 0xf);
- goto emit_string_char;
-
- case LEJP_MP_STRING_ESC_U3:
- if (ctx->uni >= 0x080) {
- /*
- * 0x080 - 0xfff (0x0800 - 0xffff)
- * middle 3-byte seq
- * send ....XXXXXX..
- */
- c = 0x80 | ((ctx->uni >> 2) & 0x3f);
- goto emit_string_char;
- }
- if (ctx->uni < 0x008)
- break;
- /*
- * 0x008 - 0x7f (0x0080 - 0x07ff)
- * start 2-byte seq
- */
- c = 0xc0 | (ctx->uni >> 2);
- goto emit_string_char;
-
- case LEJP_MP_STRING_ESC_U4:
- if (ctx->uni >= 0x0080)
- /* end of 2 or 3-byte seq */
- c = 0x80 | (ctx->uni & 0x3f);
- else
- /* literal */
- c = (unsigned char)ctx->uni;
-
- ctx->st[ctx->sp].s = LEJP_MP_STRING;
- goto emit_string_char;
- default:
- break;
- }
- break;
-
- case LEJP_MP_DELIM:
- if (c != ':') {
- ret = LEJP_REJECT_MP_DELIM_MISSING_COLON;
- goto reject;
- }
- ctx->st[ctx->sp].s = LEJP_MP_VALUE;
- ctx->path[ctx->ppos] = '\0';
-
- lejp_check_path_match(ctx);
- if (ctx->callback(ctx, LEJPCB_PAIR_NAME)) {
- ret = LEJP_REJECT_CALLBACK;
- goto reject;
- }
- break;
-
- case LEJP_MP_VALUE:
- if (c >= '0' && c <= '9') {
- ctx->npos = 0;
- ctx->dcount = 0;
- ctx->f = 0;
- ctx->st[ctx->sp].s = LEJP_MP_VALUE_NUM_INT;
- goto redo_character;
- }
- switch (c) {
- case'\"':
- /* push */
- ctx->st[ctx->sp].s = LEJP_MP_COMMA_OR_END;
- c = LEJP_MP_STRING;
- ctx->npos = 0;
- ctx->buf[0] = '\0';
- if (ctx->callback(ctx, LEJPCB_VAL_STR_START)) {
- ret = LEJP_REJECT_CALLBACK;
- goto reject;
- }
- goto add_stack_level;
-
- case '{':
- /* push */
- ctx->st[ctx->sp].s = LEJP_MP_COMMA_OR_END;
- c = LEJP_MEMBERS;
- lejp_check_path_match(ctx);
- if (ctx->callback(ctx, LEJPCB_OBJECT_START)) {
- ret = LEJP_REJECT_CALLBACK;
- goto reject;
- }
- ctx->path_match = 0;
- goto add_stack_level;
-
- case '[':
- /* push */
- ctx->st[ctx->sp].s = LEJP_MP_ARRAY_END;
- c = LEJP_MP_VALUE;
- ctx->path[ctx->ppos++] = '[';
- ctx->path[ctx->ppos++] = ']';
- ctx->path[ctx->ppos] = '\0';
- if (ctx->callback(ctx, LEJPCB_ARRAY_START)) {
- ret = LEJP_REJECT_CALLBACK;
- goto reject;
- }
- ctx->i[ctx->ipos++] = 0;
- if (ctx->ipos > LWS_ARRAY_SIZE(ctx->i)) {
- ret = LEJP_REJECT_MP_DELIM_ISTACK;
- goto reject;
- }
- goto add_stack_level;
-
- case ']':
- /* pop */
- if (!ctx->sp) { /* JSON can't end on ] */
- ret = LEJP_REJECT_MP_C_OR_E_UNDERF;
- goto reject;
- }
- ctx->sp--;
- if (ctx->st[ctx->sp].s != LEJP_MP_ARRAY_END) {
- ret = LEJP_REJECT_MP_C_OR_E_NOTARRAY;
- goto reject;
- }
- /* drop the path [n] bit */
- if (ctx->sp) {
- ctx->ppos = ctx->st[ctx->sp - 1].p;
- ctx->ipos = ctx->st[ctx->sp - 1].i;
- }
- ctx->path[ctx->ppos] = '\0';
- if (ctx->path_match &&
- ctx->ppos <= ctx->path_match_len)
- /*
- * we shrank the path to be
- * smaller than the matching point
- */
- ctx->path_match = 0;
- goto array_end;
-
- case 't': /* true */
- ctx->uni = 0;
- ctx->st[ctx->sp].s = LEJP_MP_VALUE_TOK;
- break;
-
- case 'f':
- ctx->uni = 4;
- ctx->st[ctx->sp].s = LEJP_MP_VALUE_TOK;
- break;
-
- case 'n':
- ctx->uni = 4 + 5;
- ctx->st[ctx->sp].s = LEJP_MP_VALUE_TOK;
- break;
- default:
- ret = LEJP_REJECT_MP_DELIM_BAD_VALUE_START;
- goto reject;
- }
- break;
-
- case LEJP_MP_VALUE_NUM_INT:
- if (!ctx->npos && c == '-') {
- ctx->f |= LEJP_SEEN_MINUS;
- goto append_npos;
- }
-
- if (ctx->dcount < 10 && c >= '0' && c <= '9') {
- if (ctx->f & LEJP_SEEN_POINT)
- ctx->f |= LEJP_SEEN_POST_POINT;
- ctx->dcount++;
- goto append_npos;
- }
- if (c == '.') {
- if (!ctx->dcount || (ctx->f & LEJP_SEEN_POINT)) {
- ret = LEJP_REJECT_MP_VAL_NUM_FORMAT;
- goto reject;
- }
- ctx->f |= LEJP_SEEN_POINT;
- goto append_npos;
- }
- /*
- * before exponent, if we had . we must have had at
- * least one more digit
- */
- if ((ctx->f &
- (LEJP_SEEN_POINT | LEJP_SEEN_POST_POINT)) ==
- LEJP_SEEN_POINT) {
- ret = LEJP_REJECT_MP_VAL_NUM_INT_NO_FRAC;
- goto reject;
- }
- if (c == 'e' || c == 'E') {
- if (ctx->f & LEJP_SEEN_EXP) {
- ret = LEJP_REJECT_MP_VAL_NUM_FORMAT;
- goto reject;
- }
- ctx->f |= LEJP_SEEN_EXP;
- ctx->st[ctx->sp].s = LEJP_MP_VALUE_NUM_EXP;
- goto append_npos;
- }
- /* if none of the above, did we even have a number? */
- if (!ctx->dcount) {
- ret = LEJP_REJECT_MP_VAL_NUM_FORMAT;
- goto reject;
- }
-
- ctx->buf[ctx->npos] = '\0';
- if (ctx->f & LEJP_SEEN_POINT) {
- if (ctx->callback(ctx, LEJPCB_VAL_NUM_FLOAT)) {
- ret = LEJP_REJECT_CALLBACK;
- goto reject;
- }
- } else {
- if (ctx->callback(ctx, LEJPCB_VAL_NUM_INT)) {
- ret = LEJP_REJECT_CALLBACK;
- goto reject;
- }
- }
-
- /* then this is the post-number character, loop */
- ctx->st[ctx->sp].s = LEJP_MP_COMMA_OR_END;
- goto redo_character;
-
- case LEJP_MP_VALUE_NUM_EXP:
- ctx->st[ctx->sp].s = LEJP_MP_VALUE_NUM_INT;
- if (c >= '0' && c <= '9')
- goto redo_character;
- if (c == '+' || c == '-')
- goto append_npos;
- ret = LEJP_REJECT_MP_VAL_NUM_EXP_BAD_EXP;
- goto reject;
-
- case LEJP_MP_VALUE_TOK: /* true, false, null */
- if (c != tokens[ctx->uni]) {
- ret = LEJP_REJECT_MP_VAL_TOK_UNKNOWN;
- goto reject;
- }
- ctx->uni++;
- if (tokens[ctx->uni] != ' ')
- break;
- switch (ctx->uni) {
- case 3:
- ctx->buf[0] = '1';
- ctx->buf[1] = '\0';
- if (ctx->callback(ctx, LEJPCB_VAL_TRUE)) {
- ret = LEJP_REJECT_CALLBACK;
- goto reject;
- }
- break;
- case 8:
- ctx->buf[0] = '0';
- ctx->buf[1] = '\0';
- if (ctx->callback(ctx, LEJPCB_VAL_FALSE)) {
- ret = LEJP_REJECT_CALLBACK;
- goto reject;
- }
- break;
- case 12:
- ctx->buf[0] = '\0';
- if (ctx->callback(ctx, LEJPCB_VAL_NULL)) {
- ret = LEJP_REJECT_CALLBACK;
- goto reject;
- }
- break;
- }
- ctx->st[ctx->sp].s = LEJP_MP_COMMA_OR_END;
- break;
-
- case LEJP_MP_COMMA_OR_END:
- ctx->path[ctx->ppos] = '\0';
- if (c == ',') {
- /* increment this stack level's index */
- ctx->st[ctx->sp].s = LEJP_M_P;
- if (!ctx->sp) {
- ctx->ppos = 0;
- /*
- * since we came back to root level,
- * no path can still match
- */
- ctx->path_match = 0;
- break;
- }
- ctx->ppos = ctx->st[ctx->sp - 1].p;
- ctx->path[ctx->ppos] = '\0';
- if (ctx->path_match &&
- ctx->ppos <= ctx->path_match_len)
- /*
- * we shrank the path to be
- * smaller than the matching point
- */
- ctx->path_match = 0;
-
- if (ctx->st[ctx->sp - 1].s != LEJP_MP_ARRAY_END)
- break;
- /* top level is definitely an array... */
- if (ctx->ipos)
- ctx->i[ctx->ipos - 1]++;
- ctx->st[ctx->sp].s = LEJP_MP_VALUE;
- break;
- }
- if (c == ']') {
- if (!ctx->sp) { /* JSON can't end on ] */
- ret = LEJP_REJECT_MP_C_OR_E_UNDERF;
- goto reject;
- }
- /* pop */
- ctx->sp--;
- if (ctx->st[ctx->sp].s != LEJP_MP_ARRAY_END) {
- ret = LEJP_REJECT_MP_C_OR_E_NOTARRAY;
- goto reject;
- }
- /* drop the path [n] bit */
- if (ctx->sp) {
- ctx->ppos = ctx->st[ctx->sp - 1].p;
- ctx->ipos = ctx->st[ctx->sp - 1].i;
- }
- ctx->path[ctx->ppos] = '\0';
- if (ctx->path_match &&
- ctx->ppos <= ctx->path_match_len)
- /*
- * we shrank the path to be
- * smaller than the matching point
- */
- ctx->path_match = 0;
-
- /* do LEJP_MP_ARRAY_END processing */
- goto redo_character;
- }
- if (c == '}') {
- if (!ctx->sp) {
- lejp_check_path_match(ctx);
- if (ctx->callback(ctx, LEJPCB_OBJECT_END)) {
- ret = LEJP_REJECT_CALLBACK;
- goto reject;
- }
- ctx->callback(ctx, LEJPCB_COMPLETE);
- /* done, return unused amount */
- return len;
- }
- /* pop */
- ctx->sp--;
- if (ctx->sp) {
- ctx->ppos = ctx->st[ctx->sp - 1].p;
- ctx->ipos = ctx->st[ctx->sp - 1].i;
- }
- ctx->path[ctx->ppos] = '\0';
- if (ctx->path_match &&
- ctx->ppos <= ctx->path_match_len)
- /*
- * we shrank the path to be
- * smaller than the matching point
- */
- ctx->path_match = 0;
- lejp_check_path_match(ctx);
- if (ctx->callback(ctx, LEJPCB_OBJECT_END)) {
- ret = LEJP_REJECT_CALLBACK;
- goto reject;
- }
- break;
- }
-
- ret = LEJP_REJECT_MP_C_OR_E_NEITHER;
- goto reject;
-
- case LEJP_MP_ARRAY_END:
-array_end:
- ctx->path[ctx->ppos] = '\0';
- if (c == ',') {
- /* increment this stack level's index */
- if (ctx->ipos)
- ctx->i[ctx->ipos - 1]++;
- ctx->st[ctx->sp].s = LEJP_MP_VALUE;
- if (ctx->sp)
- ctx->ppos = ctx->st[ctx->sp - 1].p;
- ctx->path[ctx->ppos] = '\0';
- break;
- }
- if (c != ']') {
- ret = LEJP_REJECT_MP_ARRAY_END_MISSING;
- goto reject;
- }
-
- ctx->st[ctx->sp].s = LEJP_MP_COMMA_OR_END;
- ctx->callback(ctx, LEJPCB_ARRAY_END);
- break;
- }
-
- continue;
-
-emit_string_char:
- if (!ctx->sp || ctx->st[ctx->sp - 1].s != LEJP_MP_DELIM) {
- /* assemble the string value into chunks */
- ctx->buf[ctx->npos++] = c;
- if (ctx->npos == sizeof(ctx->buf) - 1) {
- if (ctx->callback(ctx, LEJPCB_VAL_STR_CHUNK)) {
- ret = LEJP_REJECT_CALLBACK;
- goto reject;
- }
- ctx->npos = 0;
- }
- continue;
- }
- /* name part of name:value pair */
- ctx->path[ctx->ppos++] = c;
- continue;
-
-add_stack_level:
- /* push on to the object stack */
- if (ctx->ppos && ctx->st[ctx->sp].s != LEJP_MP_COMMA_OR_END &&
- ctx->st[ctx->sp].s != LEJP_MP_ARRAY_END)
- ctx->path[ctx->ppos++] = '.';
-
- ctx->st[ctx->sp].p = ctx->ppos;
- ctx->st[ctx->sp].i = ctx->ipos;
- if (++ctx->sp == LWS_ARRAY_SIZE(ctx->st)) {
- ret = LEJP_REJECT_STACK_OVERFLOW;
- goto reject;
- }
- ctx->path[ctx->ppos] = '\0';
- ctx->st[ctx->sp].s = c;
- ctx->st[ctx->sp].b = 0;
- continue;
-
-append_npos:
- if (ctx->npos >= sizeof(ctx->buf)) {
- ret = LEJP_REJECT_NUM_TOO_LONG;
- goto reject;
- }
- ctx->buf[ctx->npos++] = c;
- continue;
-
-redo_character:
- json--;
- len++;
- }
-
- return LEJP_CONTINUE;
-
-reject:
- ctx->callback(ctx, LEJPCB_FAILED);
- return ret;
-}
diff --git a/thirdparty/libwebsockets/misc/sha-1.c b/thirdparty/libwebsockets/misc/sha-1.c
deleted file mode 100644
index 2e4db52693..0000000000
--- a/thirdparty/libwebsockets/misc/sha-1.c
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-/*
- * FIPS pub 180-1: Secure Hash Algorithm (SHA-1)
- * based on: http://csrc.nist.gov/fips/fip180-1.txt
- * implemented by Jun-ichiro itojun Itoh <itojun@itojun.org>
- */
-
-#include "core/private.h"
-
-#ifdef LWS_HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-struct sha1_ctxt {
- union {
- unsigned char b8[20];
- unsigned int b32[5];
- } h;
- union {
- unsigned char b8[8];
- uint64_t b64[1];
- } c;
- union {
- unsigned char b8[64];
- unsigned int b32[16];
- } m;
- unsigned char count;
-};
-
-/* sanity check */
-#if !defined(BYTE_ORDER) || !defined(LITTLE_ENDIAN) || !defined(BIG_ENDIAN)
-# define unsupported 1
-#elif BYTE_ORDER != BIG_ENDIAN
-# if BYTE_ORDER != LITTLE_ENDIAN
-# define unsupported 1
-# endif
-#endif
-
-#ifndef unsupported
-
-/* constant table */
-static const unsigned int _K[] =
- { 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6 };
-#define K(t) _K[(t) / 20]
-
-#define F0(b, c, d) (((b) & (c)) | ((~(b)) & (d)))
-#define F1(b, c, d) (((b) ^ (c)) ^ (d))
-#define F2(b, c, d) (((b) & (c)) | ((b) & (d)) | ((c) & (d)))
-#define F3(b, c, d) (((b) ^ (c)) ^ (d))
-
-#define S(n, x) (((x) << (n)) | ((x) >> (32 - n)))
-
-#define H(n) (ctxt->h.b32[(n)])
-#define COUNT (ctxt->count)
-#define BCOUNT (ctxt->c.b64[0] / 8)
-#define W(n) (ctxt->m.b32[(n)])
-
-#define PUTBYTE(x) { \
- ctxt->m.b8[(COUNT % 64)] = (x); \
- COUNT++; \
- COUNT %= 64; \
- ctxt->c.b64[0] += 8; \
- if (COUNT % 64 == 0) \
- sha1_step(ctxt); \
- }
-
-#define PUTPAD(x) { \
- ctxt->m.b8[(COUNT % 64)] = (x); \
- COUNT++; \
- COUNT %= 64; \
- if (COUNT % 64 == 0) \
- sha1_step(ctxt); \
- }
-
-
-static void
-sha1_step(struct sha1_ctxt *ctxt)
-{
- unsigned int a, b, c, d, e, tmp;
- size_t t, s;
-
-#if BYTE_ORDER == LITTLE_ENDIAN
- struct sha1_ctxt tctxt;
-
- memcpy(&tctxt.m.b8[0], &ctxt->m.b8[0], 64);
- ctxt->m.b8[0] = tctxt.m.b8[3]; ctxt->m.b8[1] = tctxt.m.b8[2];
- ctxt->m.b8[2] = tctxt.m.b8[1]; ctxt->m.b8[3] = tctxt.m.b8[0];
- ctxt->m.b8[4] = tctxt.m.b8[7]; ctxt->m.b8[5] = tctxt.m.b8[6];
- ctxt->m.b8[6] = tctxt.m.b8[5]; ctxt->m.b8[7] = tctxt.m.b8[4];
- ctxt->m.b8[8] = tctxt.m.b8[11]; ctxt->m.b8[9] = tctxt.m.b8[10];
- ctxt->m.b8[10] = tctxt.m.b8[9]; ctxt->m.b8[11] = tctxt.m.b8[8];
- ctxt->m.b8[12] = tctxt.m.b8[15]; ctxt->m.b8[13] = tctxt.m.b8[14];
- ctxt->m.b8[14] = tctxt.m.b8[13]; ctxt->m.b8[15] = tctxt.m.b8[12];
- ctxt->m.b8[16] = tctxt.m.b8[19]; ctxt->m.b8[17] = tctxt.m.b8[18];
- ctxt->m.b8[18] = tctxt.m.b8[17]; ctxt->m.b8[19] = tctxt.m.b8[16];
- ctxt->m.b8[20] = tctxt.m.b8[23]; ctxt->m.b8[21] = tctxt.m.b8[22];
- ctxt->m.b8[22] = tctxt.m.b8[21]; ctxt->m.b8[23] = tctxt.m.b8[20];
- ctxt->m.b8[24] = tctxt.m.b8[27]; ctxt->m.b8[25] = tctxt.m.b8[26];
- ctxt->m.b8[26] = tctxt.m.b8[25]; ctxt->m.b8[27] = tctxt.m.b8[24];
- ctxt->m.b8[28] = tctxt.m.b8[31]; ctxt->m.b8[29] = tctxt.m.b8[30];
- ctxt->m.b8[30] = tctxt.m.b8[29]; ctxt->m.b8[31] = tctxt.m.b8[28];
- ctxt->m.b8[32] = tctxt.m.b8[35]; ctxt->m.b8[33] = tctxt.m.b8[34];
- ctxt->m.b8[34] = tctxt.m.b8[33]; ctxt->m.b8[35] = tctxt.m.b8[32];
- ctxt->m.b8[36] = tctxt.m.b8[39]; ctxt->m.b8[37] = tctxt.m.b8[38];
- ctxt->m.b8[38] = tctxt.m.b8[37]; ctxt->m.b8[39] = tctxt.m.b8[36];
- ctxt->m.b8[40] = tctxt.m.b8[43]; ctxt->m.b8[41] = tctxt.m.b8[42];
- ctxt->m.b8[42] = tctxt.m.b8[41]; ctxt->m.b8[43] = tctxt.m.b8[40];
- ctxt->m.b8[44] = tctxt.m.b8[47]; ctxt->m.b8[45] = tctxt.m.b8[46];
- ctxt->m.b8[46] = tctxt.m.b8[45]; ctxt->m.b8[47] = tctxt.m.b8[44];
- ctxt->m.b8[48] = tctxt.m.b8[51]; ctxt->m.b8[49] = tctxt.m.b8[50];
- ctxt->m.b8[50] = tctxt.m.b8[49]; ctxt->m.b8[51] = tctxt.m.b8[48];
- ctxt->m.b8[52] = tctxt.m.b8[55]; ctxt->m.b8[53] = tctxt.m.b8[54];
- ctxt->m.b8[54] = tctxt.m.b8[53]; ctxt->m.b8[55] = tctxt.m.b8[52];
- ctxt->m.b8[56] = tctxt.m.b8[59]; ctxt->m.b8[57] = tctxt.m.b8[58];
- ctxt->m.b8[58] = tctxt.m.b8[57]; ctxt->m.b8[59] = tctxt.m.b8[56];
- ctxt->m.b8[60] = tctxt.m.b8[63]; ctxt->m.b8[61] = tctxt.m.b8[62];
- ctxt->m.b8[62] = tctxt.m.b8[61]; ctxt->m.b8[63] = tctxt.m.b8[60];
-#endif
-
- a = H(0); b = H(1); c = H(2); d = H(3); e = H(4);
-
- for (t = 0; t < 20; t++) {
- s = t & 0x0f;
- if (t >= 16)
- W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^
- W((s+2) & 0x0f) ^ W(s));
-
- tmp = S(5, a) + F0(b, c, d) + e + W(s) + K(t);
- e = d; d = c; c = S(30, b); b = a; a = tmp;
- }
- for (t = 20; t < 40; t++) {
- s = t & 0x0f;
- W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^
- W((s+2) & 0x0f) ^ W(s));
- tmp = S(5, a) + F1(b, c, d) + e + W(s) + K(t);
- e = d; d = c; c = S(30, b); b = a; a = tmp;
- }
- for (t = 40; t < 60; t++) {
- s = t & 0x0f;
- W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^
- W((s+2) & 0x0f) ^ W(s));
- tmp = S(5, a) + F2(b, c, d) + e + W(s) + K(t);
- e = d; d = c; c = S(30, b); b = a; a = tmp;
- }
- for (t = 60; t < 80; t++) {
- s = t & 0x0f;
- W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^
- W((s+2) & 0x0f) ^ W(s));
- tmp = S(5, a) + F3(b, c, d) + e + W(s) + K(t);
- e = d; d = c; c = S(30, b); b = a; a = tmp;
- }
-
- H(0) = H(0) + a;
- H(1) = H(1) + b;
- H(2) = H(2) + c;
- H(3) = H(3) + d;
- H(4) = H(4) + e;
-
- bzero(&ctxt->m.b8[0], 64);
-}
-
-/*------------------------------------------------------------*/
-
-static void
-_sha1_init(struct sha1_ctxt *ctxt)
-{
- bzero(ctxt, sizeof(struct sha1_ctxt));
- H(0) = 0x67452301;
- H(1) = 0xefcdab89;
- H(2) = 0x98badcfe;
- H(3) = 0x10325476;
- H(4) = 0xc3d2e1f0;
-}
-
-void
-sha1_pad(struct sha1_ctxt *ctxt)
-{
- size_t padlen; /*pad length in bytes*/
- size_t padstart;
-
- PUTPAD(0x80);
-
- padstart = COUNT % 64;
- padlen = 64 - padstart;
- if (padlen < 8) {
- bzero(&ctxt->m.b8[padstart], padlen);
- COUNT += (unsigned char)padlen;
- COUNT %= 64;
- sha1_step(ctxt);
- padstart = COUNT % 64; /* should be 0 */
- padlen = 64 - padstart; /* should be 64 */
- }
- bzero(&ctxt->m.b8[padstart], padlen - 8);
- COUNT += ((unsigned char)padlen - 8);
- COUNT %= 64;
-#if BYTE_ORDER == BIG_ENDIAN
- PUTPAD(ctxt->c.b8[0]); PUTPAD(ctxt->c.b8[1]);
- PUTPAD(ctxt->c.b8[2]); PUTPAD(ctxt->c.b8[3]);
- PUTPAD(ctxt->c.b8[4]); PUTPAD(ctxt->c.b8[5]);
- PUTPAD(ctxt->c.b8[6]); PUTPAD(ctxt->c.b8[7]);
-#else
- PUTPAD(ctxt->c.b8[7]); PUTPAD(ctxt->c.b8[6]);
- PUTPAD(ctxt->c.b8[5]); PUTPAD(ctxt->c.b8[4]);
- PUTPAD(ctxt->c.b8[3]); PUTPAD(ctxt->c.b8[2]);
- PUTPAD(ctxt->c.b8[1]); PUTPAD(ctxt->c.b8[0]);
-#endif
-}
-
-void
-sha1_loop(struct sha1_ctxt *ctxt, const unsigned char *input, size_t len)
-{
- size_t gaplen;
- size_t gapstart;
- size_t off;
- size_t copysiz;
-
- off = 0;
-
- while (off < len) {
- gapstart = COUNT % 64;
- gaplen = 64 - gapstart;
-
- copysiz = (gaplen < len - off) ? gaplen : len - off;
- memcpy(&ctxt->m.b8[gapstart], &input[off], copysiz);
- COUNT += (unsigned char)copysiz;
- COUNT %= 64;
- ctxt->c.b64[0] += copysiz * 8;
- if (COUNT % 64 == 0)
- sha1_step(ctxt);
- off += copysiz;
- }
-}
-
-void
-sha1_result(struct sha1_ctxt *ctxt, void *digest0)
-{
- unsigned char *digest;
-
- digest = (unsigned char *)digest0;
- sha1_pad(ctxt);
-#if BYTE_ORDER == BIG_ENDIAN
- memcpy(digest, &ctxt->h.b8[0], 20);
-#else
- digest[0] = ctxt->h.b8[3]; digest[1] = ctxt->h.b8[2];
- digest[2] = ctxt->h.b8[1]; digest[3] = ctxt->h.b8[0];
- digest[4] = ctxt->h.b8[7]; digest[5] = ctxt->h.b8[6];
- digest[6] = ctxt->h.b8[5]; digest[7] = ctxt->h.b8[4];
- digest[8] = ctxt->h.b8[11]; digest[9] = ctxt->h.b8[10];
- digest[10] = ctxt->h.b8[9]; digest[11] = ctxt->h.b8[8];
- digest[12] = ctxt->h.b8[15]; digest[13] = ctxt->h.b8[14];
- digest[14] = ctxt->h.b8[13]; digest[15] = ctxt->h.b8[12];
- digest[16] = ctxt->h.b8[19]; digest[17] = ctxt->h.b8[18];
- digest[18] = ctxt->h.b8[17]; digest[19] = ctxt->h.b8[16];
-#endif
-}
-
-/*
- * This should look and work like the libcrypto implementation
- */
-
-LWS_VISIBLE unsigned char *
-lws_SHA1(const unsigned char *d, size_t n, unsigned char *md)
-{
- struct sha1_ctxt ctx;
-
- _sha1_init(&ctx);
- sha1_loop(&ctx, d, n);
- sha1_result(&ctx, (void *)md);
-
- return md;
-}
-
-#endif /*unsupported*/
diff --git a/thirdparty/libwebsockets/plat/lws-plat-unix.c b/thirdparty/libwebsockets/plat/lws-plat-unix.c
deleted file mode 100644
index d1bca8b5df..0000000000
--- a/thirdparty/libwebsockets/plat/lws-plat-unix.c
+++ /dev/null
@@ -1,982 +0,0 @@
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010-2017 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- */
-
-#define _GNU_SOURCE
-#include "core/private.h"
-
-#include <pwd.h>
-#include <grp.h>
-
-#ifdef LWS_WITH_PLUGINS
-#include <dlfcn.h>
-#endif
-#include <dirent.h>
-
-void lws_plat_apply_FD_CLOEXEC(int n)
-{
- if (n != -1)
- fcntl(n, F_SETFD, FD_CLOEXEC );
-}
-
-int
-lws_plat_socket_offset(void)
-{
- return 0;
-}
-
-int
-lws_plat_pipe_create(struct lws *wsi)
-{
- struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
-
-#if defined(LWS_HAVE_PIPE2)
- return pipe2(pt->dummy_pipe_fds, O_NONBLOCK);
-#else
- return pipe(pt->dummy_pipe_fds);
-#endif
-}
-
-int
-lws_plat_pipe_signal(struct lws *wsi)
-{
- struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
- char buf = 0;
- int n;
-
- n = write(pt->dummy_pipe_fds[1], &buf, 1);
-
- return n != 1;
-}
-
-void
-lws_plat_pipe_close(struct lws *wsi)
-{
- struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
-
- if (pt->dummy_pipe_fds[0] && pt->dummy_pipe_fds[0] != -1)
- close(pt->dummy_pipe_fds[0]);
- if (pt->dummy_pipe_fds[1] && pt->dummy_pipe_fds[1] != -1)
- close(pt->dummy_pipe_fds[1]);
-
- pt->dummy_pipe_fds[0] = pt->dummy_pipe_fds[1] = -1;
-}
-
-#ifdef __QNX__
-# include "netinet/tcp_var.h"
-# define TCP_KEEPINTVL TCPCTL_KEEPINTVL
-# define TCP_KEEPIDLE TCPCTL_KEEPIDLE
-# define TCP_KEEPCNT TCPCTL_KEEPCNT
-#endif
-
-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 read(context->fd_random, (char *)buf, len);
-}
-
-LWS_VISIBLE int
-lws_send_pipe_choked(struct lws *wsi)
-{
- struct lws_pollfd fds;
- struct lws *wsi_eff = wsi;
-
-#if defined(LWS_WITH_HTTP2)
- wsi_eff = lws_get_network_wsi(wsi);
-#endif
-
- /* the fact we checked implies we avoided back-to-back writes */
- wsi_eff->could_have_pending = 0;
-
- /* treat the fact we got a truncated send pending as if we're choked */
- if (wsi_eff->trunc_len)
- return 1;
-
- fds.fd = wsi_eff->desc.sockfd;
- fds.events = POLLOUT;
- fds.revents = 0;
-
- if (poll(&fds, 1, 0) != 1)
- return 1;
-
- if ((fds.revents & POLLOUT) == 0)
- return 1;
-
- /* okay to send another packet without blocking */
-
- return 0;
-}
-
-LWS_VISIBLE int
-lws_poll_listen_fd(struct lws_pollfd *fd)
-{
- return poll(fd, 1, 0);
-}
-
-LWS_VISIBLE void lwsl_emit_syslog(int level, const char *line)
-{
- int syslog_level = LOG_DEBUG;
-
- switch (level) {
- case LLL_ERR:
- syslog_level = LOG_ERR;
- break;
- case LLL_WARN:
- syslog_level = LOG_WARNING;
- break;
- case LLL_NOTICE:
- syslog_level = LOG_NOTICE;
- break;
- case LLL_INFO:
- syslog_level = LOG_INFO;
- break;
- }
- syslog(syslog_level, "%s", line);
-}
-
-LWS_VISIBLE LWS_EXTERN int
-_lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
-{
- volatile struct lws_foreign_thread_pollfd *ftp, *next;
- volatile struct lws_context_per_thread *vpt;
- 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];
- vpt = (volatile struct lws_context_per_thread *)pt;
-
- lws_stats_atomic_bump(context, pt, LWSSTATS_C_SERVICE_ENTRY, 1);
-
- if (timeout_ms < 0)
- goto faked_service;
-
- if (context->event_loop_ops->run_pt)
- context->event_loop_ops->run_pt(context, tsi);
-
- 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;
- context->service_tid_detected = 1;
- }
-
- /*
- * 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;
- }
-
- if (timeout_ms) {
- lws_pt_lock(pt, __func__);
- /* don't stay in poll wait longer than next hr timeout */
- lws_usec_t t = __lws_hrtimer_service(pt);
- if ((lws_usec_t)timeout_ms * 1000 > t)
- timeout_ms = t / 1000;
- lws_pt_unlock(pt);
- }
-
- vpt->inside_poll = 1;
- lws_memory_barrier();
- n = poll(pt->fds, pt->fds_count, timeout_ms);
- vpt->inside_poll = 0;
- lws_memory_barrier();
-
- /* Collision will be rare and brief. Just spin until it completes */
- while (vpt->foreign_spinlock)
- ;
-
- /*
- * At this point we are not inside a foreign thread pollfd change,
- * and we have marked ourselves as outside the poll() wait. So we
- * are the only guys that can modify the lws_foreign_thread_pollfd
- * list on the pt. Drain the list and apply the changes to the
- * affected pollfds in the correct order.
- */
-
- lws_pt_lock(pt, __func__);
-
- ftp = vpt->foreign_pfd_list;
- //lwsl_notice("cleared list %p\n", ftp);
- while (ftp) {
- struct lws *wsi;
- struct lws_pollfd *pfd;
-
- next = ftp->next;
- pfd = &vpt->fds[ftp->fd_index];
- if (lws_socket_is_valid(pfd->fd)) {
- wsi = wsi_from_fd(context, pfd->fd);
- if (wsi)
- __lws_change_pollfd(wsi, ftp->_and, ftp->_or);
- }
- lws_free((void *)ftp);
- ftp = next;
- }
- vpt->foreign_pfd_list = NULL;
- lws_memory_barrier();
-
- /* we have come out of a poll wait... check the hrtimer list */
-
- __lws_hrtimer_service(pt);
-
- lws_pt_unlock(pt);
-
- m = 0;
-#if defined(LWS_ROLE_WS) && !defined(LWS_WITHOUT_EXTENSIONS)
- m |= !!pt->ws.rx_draining_ext_list;
-#endif
-
- if (pt->context->tls_ops &&
- pt->context->tls_ops->fake_POLLIN_for_buffered)
- m |= pt->context->tls_ops->fake_POLLIN_for_buffered(pt);
-
- if (!m && !n) { /* nothing to do */
- lws_service_fd_tsi(context, NULL, tsi);
- lws_service_do_ripe_rxflow(pt);
-
- 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 < (int)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--;
- }
-
- lws_service_do_ripe_rxflow(pt);
-
- 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);
-
-#ifdef LWS_WITH_IPV6
- optval = 0;
- setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const void*)&optval, optlen);
-#endif
-
-#if defined(__APPLE__) || \
- defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
- defined(__NetBSD__) || \
- defined(__OpenBSD__) || \
- defined(__HAIKU__)
- struct protoent *tcp_proto;
-#endif
-
- fcntl(fd, F_SETFD, FD_CLOEXEC);
-
- 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) || \
- defined(__HAIKU__)
-
- /*
- * 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 */
-
-#if defined(LWS_HAVE_TCP_USER_TIMEOUT)
- optval = 1000 * (vhost->ka_time +
- (vhost->ka_interval * vhost->ka_probes));
- if (setsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT,
- (const void *)&optval, optlen) < 0)
- return 1;
-#endif
- 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 defined(SO_BINDTODEVICE)
- if (vhost->bind_iface && vhost->iface) {
- lwsl_info("binding listen skt to %s using SO_BINDTODEVICE\n", vhost->iface);
- if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, vhost->iface,
- strlen(vhost->iface)) < 0) {
- lwsl_warn("Failed to bind to device %s\n", vhost->iface);
- return 1;
- }
- }
-#endif
-
- /* Disable Nagle */
- optval = 1;
-#if defined (__sun) || defined(__QNX__)
- if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const void *)&optval, optlen) < 0)
- return 1;
-#elif !defined(__APPLE__) && \
- !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) && \
- !defined(__NetBSD__) && \
- !defined(__OpenBSD__) && \
- !defined(__HAIKU__)
- if (setsockopt(fd, SOL_TCP, TCP_NODELAY, (const void *)&optval, optlen) < 0)
- return 1;
-#else
- 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;
-}
-
-#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
-static void
-_lws_plat_apply_caps(int mode, const cap_value_t *cv, int count)
-{
- cap_t caps;
-
- if (!count)
- return;
-
- caps = cap_get_proc();
-
- cap_set_flag(caps, mode, count, cv, CAP_SET);
- cap_set_proc(caps);
- prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
- cap_free(caps);
-}
-#endif
-
-LWS_VISIBLE void
-lws_plat_drop_app_privileges(const struct lws_context_creation_info *info)
-{
-#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
- int n;
-#endif
-
- if (info->gid && info->gid != -1)
- if (setgid(info->gid))
- lwsl_warn("setgid: %s\n", strerror(LWS_ERRNO));
-
- if (info->uid && info->uid != -1) {
- struct passwd *p = getpwuid(info->uid);
-
- if (p) {
-
-#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
- _lws_plat_apply_caps(CAP_PERMITTED, info->caps, info->count_caps);
-#endif
-
- initgroups(p->pw_name, info->gid);
- if (setuid(info->uid))
- lwsl_warn("setuid: %s\n", strerror(LWS_ERRNO));
- else
- lwsl_notice("Set privs to user '%s'\n", p->pw_name);
-
-#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
- _lws_plat_apply_caps(CAP_EFFECTIVE, info->caps, info->count_caps);
-
- if (info->count_caps)
- for (n = 0; n < info->count_caps; n++)
- lwsl_notice(" RETAINING CAPABILITY %d\n", (int)info->caps[n]);
-#endif
-
- } else
- lwsl_warn("getpwuid: unable to find uid %d", info->uid);
- }
-}
-
-#ifdef LWS_WITH_PLUGINS
-
-#if defined(LWS_WITH_LIBUV) && UV_VERSION_MAJOR > 0
-
-/* libuv.c implements these in a cross-platform way */
-
-#else
-
-static int filter(const struct dirent *ent)
-{
- if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
- return 0;
-
- return 1;
-}
-
-LWS_VISIBLE int
-lws_plat_plugins_init(struct lws_context * context, const char * const *d)
-{
- struct lws_plugin_capability lcaps;
- struct lws_plugin *plugin;
- lws_plugin_init_func initfunc;
- struct dirent **namelist;
- int n, i, m, ret = 0;
- char path[256];
- void *l;
-
- lwsl_notice(" Plugins:\n");
-
- while (d && *d) {
- n = scandir(*d, &namelist, filter, alphasort);
- if (n < 0) {
- lwsl_err("Scandir on %s failed\n", *d);
- return 1;
- }
-
- for (i = 0; i < n; i++) {
- if (strlen(namelist[i]->d_name) < 7)
- goto inval;
-
- lwsl_notice(" %s\n", namelist[i]->d_name);
-
- lws_snprintf(path, sizeof(path) - 1, "%s/%s", *d,
- namelist[i]->d_name);
- l = dlopen(path, RTLD_NOW);
- if (!l) {
- lwsl_err("Error loading DSO: %s\n", dlerror());
- while (i++ < n)
- free(namelist[i]);
- goto bail;
- }
- /* we could open it, can we get his init function? */
- m = lws_snprintf(path, sizeof(path) - 1, "init_%s",
- namelist[i]->d_name + 3 /* snip lib... */);
- path[m - 3] = '\0'; /* snip the .so */
- initfunc = dlsym(l, path);
- if (!initfunc) {
- lwsl_err("Failed to get init on %s: %s",
- namelist[i]->d_name, dlerror());
- dlclose(l);
- }
- lcaps.api_magic = LWS_PLUGIN_API_MAGIC;
- m = initfunc(context, &lcaps);
- if (m) {
- lwsl_err("Initializing %s failed %d\n",
- namelist[i]->d_name, m);
- dlclose(l);
- goto skip;
- }
-
- plugin = lws_malloc(sizeof(*plugin), "plugin");
- if (!plugin) {
- lwsl_err("OOM\n");
- goto bail;
- }
- plugin->list = context->plugin_list;
- context->plugin_list = plugin;
- lws_strncpy(plugin->name, namelist[i]->d_name,
- sizeof(plugin->name));
- plugin->l = l;
- plugin->caps = lcaps;
- context->plugin_protocol_count += lcaps.count_protocols;
- context->plugin_extension_count += lcaps.count_extensions;
-
- free(namelist[i]);
- continue;
-
- skip:
- dlclose(l);
- inval:
- free(namelist[i]);
- }
- free(namelist);
- d++;
- }
-
-bail:
- free(namelist);
-
- return ret;
-}
-
-LWS_VISIBLE int
-lws_plat_plugins_destroy(struct lws_context * context)
-{
- struct lws_plugin *plugin = context->plugin_list, *p;
- lws_plugin_destroy_func func;
- char path[256];
- int m;
-
- if (!plugin)
- return 0;
-
- lwsl_notice("%s\n", __func__);
-
- while (plugin) {
- p = plugin;
- m = lws_snprintf(path, sizeof(path) - 1, "destroy_%s", plugin->name + 3);
- path[m - 3] = '\0';
- func = dlsym(plugin->l, path);
- if (!func) {
- lwsl_err("Failed to get destroy on %s: %s",
- plugin->name, dlerror());
- goto next;
- }
- m = func(context);
- if (m)
- lwsl_err("Initializing %s failed %d\n",
- plugin->name, m);
-next:
- dlclose(p->l);
- plugin = p->list;
- p->list = NULL;
- free(p);
- }
-
- context->plugin_list = NULL;
-
- return 0;
-}
-
-#endif
-#endif
-
-
-#if 0
-static void
-sigabrt_handler(int x)
-{
- printf("%s\n", __func__);
-}
-#endif
-
-LWS_VISIBLE int
-lws_plat_context_early_init(void)
-{
-#if !defined(LWS_AVOID_SIGPIPE_IGN)
- signal(SIGPIPE, SIG_IGN);
-#endif
-
- 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);
-
- if (!context->fd_random)
- lwsl_err("ZERO RANDOM FD\n");
- if (context->fd_random != LWS_INVALID_FILE)
- close(context->fd_random);
-}
-
-/* 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)
-{
- int rc = LWS_ITOSA_NOT_EXIST;
-
- struct ifaddrs *ifr;
- struct ifaddrs *ifc;
-#ifdef LWS_WITH_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_debug(" interface %s vs %s (fam %d) ipv6 %d\n", ifc->ifa_name, ifname, ifc->ifa_addr->sa_family, ipv6);
-
- if (strcmp(ifc->ifa_name, ifname))
- continue;
-
- switch (ifc->ifa_addr->sa_family) {
-#if defined(AF_PACKET)
- case AF_PACKET:
- /* interface exists but is not usable */
- rc = LWS_ITOSA_NOT_USABLE;
- continue;
-#endif
-
- case AF_INET:
-#ifdef LWS_WITH_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_WITH_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 = LWS_ITOSA_USABLE;
- }
-
- freeifaddrs(ifr);
-
- if (rc) {
- /* check if bind to IP address */
-#ifdef LWS_WITH_IPV6
- if (inet_pton(AF_INET6, ifname, &addr6->sin6_addr) == 1)
- rc = LWS_ITOSA_USABLE;
- else
-#endif
- if (inet_pton(AF_INET, ifname, &addr->sin_addr) == 1)
- rc = LWS_ITOSA_USABLE;
- }
-
- return rc;
-}
-
-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];
-
- if (context->event_loop_ops->io)
- context->event_loop_ops->io(wsi, LWS_EV_START | LWS_EV_READ);
-
- 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];
-
- if (context->event_loop_ops->io)
- context->event_loop_ops->io(wsi,
- LWS_EV_STOP | LWS_EV_READ | LWS_EV_WRITE);
-
- pt->fds_count--;
-}
-
-LWS_VISIBLE void
-lws_plat_service_periodic(struct lws_context *context)
-{
- /* if our parent went down, don't linger around */
- if (context->started_with_parent &&
- kill(context->started_with_parent, 0) < 0)
- kill(getpid(), SIGTERM);
-}
-
-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);
-}
-
-LWS_VISIBLE int
-lws_plat_inet_pton(int af, const char *src, void *dst)
-{
- return inet_pton(af, src, dst);
-}
-
-LWS_VISIBLE lws_fop_fd_t
-_lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename,
- const char *vpath, lws_fop_flags_t *flags)
-{
- struct stat stat_buf;
- int ret = open(filename, (*flags) & LWS_FOP_FLAGS_MASK, 0664);
- lws_fop_fd_t fop_fd;
-
- if (ret < 0)
- return NULL;
-
- if (fstat(ret, &stat_buf) < 0)
- goto bail;
-
- fop_fd = malloc(sizeof(*fop_fd));
- if (!fop_fd)
- goto bail;
-
- fop_fd->fops = fops;
- fop_fd->flags = *flags;
- fop_fd->fd = ret;
- fop_fd->filesystem_priv = NULL; /* we don't use it */
- fop_fd->len = stat_buf.st_size;
- fop_fd->pos = 0;
-
- return fop_fd;
-
-bail:
- close(ret);
- return NULL;
-}
-
-LWS_VISIBLE int
-_lws_plat_file_close(lws_fop_fd_t *fop_fd)
-{
- int fd = (*fop_fd)->fd;
-
- free(*fop_fd);
- *fop_fd = NULL;
-
- return close(fd);
-}
-
-LWS_VISIBLE lws_fileofs_t
-_lws_plat_file_seek_cur(lws_fop_fd_t fop_fd, lws_fileofs_t offset)
-{
- lws_fileofs_t r;
-
- if (offset > 0 &&
- offset > (lws_fileofs_t)fop_fd->len - (lws_fileofs_t)fop_fd->pos)
- offset = fop_fd->len - fop_fd->pos;
-
- if ((lws_fileofs_t)fop_fd->pos + offset < 0)
- offset = -fop_fd->pos;
-
- r = lseek(fop_fd->fd, offset, SEEK_CUR);
-
- if (r >= 0)
- fop_fd->pos = r;
- else
- lwsl_err("error seeking from cur %ld, offset %ld\n",
- (long)fop_fd->pos, (long)offset);
-
- return r;
-}
-
-LWS_VISIBLE int
-_lws_plat_file_read(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
- uint8_t *buf, lws_filepos_t len)
-{
- long n;
-
- n = read((int)fop_fd->fd, buf, len);
- if (n == -1) {
- *amount = 0;
- return -1;
- }
- fop_fd->pos += n;
- lwsl_debug("%s: read %ld of req %ld, pos %ld, len %ld\n", __func__, n,
- (long)len, (long)fop_fd->pos, (long)fop_fd->len);
- *amount = n;
-
- return 0;
-}
-
-LWS_VISIBLE int
-_lws_plat_file_write(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
- uint8_t *buf, lws_filepos_t len)
-{
- long n;
-
- n = write((int)fop_fd->fd, buf, len);
- if (n == -1) {
- *amount = 0;
- return -1;
- }
-
- fop_fd->pos += n;
- *amount = n;
-
- return 0;
-}
-
-LWS_VISIBLE int
-lws_plat_init(struct lws_context *context,
- const struct lws_context_creation_info *info)
-{
- int fd;
-
- /* master context has the global fd lookup array */
- context->lws_lookup = lws_zalloc(sizeof(struct lws *) *
- context->max_fds, "lws_lookup");
- if (context->lws_lookup == NULL) {
- lwsl_err("OOM on lws_lookup array for %d connections\n",
- context->max_fds);
- return 1;
- }
-
- lwsl_info(" mem: platform fd map: %5lu bytes\n",
- (unsigned long)(sizeof(struct lws *) * context->max_fds));
- fd = open(SYSTEM_RANDOM_FILEPATH, O_RDONLY);
-
- context->fd_random = fd;
- if (context->fd_random < 0) {
- lwsl_err("Unable to open random device %s %d\n",
- SYSTEM_RANDOM_FILEPATH, context->fd_random);
- return 1;
- }
-
-#ifdef LWS_WITH_PLUGINS
- if (info->plugin_dirs)
- lws_plat_plugins_init(context, info->plugin_dirs);
-#endif
-
- return 0;
-}
-
-LWS_VISIBLE int
-lws_plat_write_cert(struct lws_vhost *vhost, int is_key, int fd, void *buf,
- int len)
-{
- int n;
-
- n = write(fd, buf, len);
-
- fsync(fd);
- lseek(fd, 0, SEEK_SET);
-
- return n != len;
-}
-
-LWS_VISIBLE int
-lws_plat_write_file(const char *filename, void *buf, int len)
-{
- int m, fd;
-
- fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
-
- if (fd == -1)
- return 1;
-
- m = write(fd, buf, len);
- close(fd);
-
- return m != len;
-}
-
-LWS_VISIBLE int
-lws_plat_read_file(const char *filename, void *buf, int len)
-{
- int n, fd = lws_open(filename, O_RDONLY);
- if (fd == -1)
- return -1;
-
- n = read(fd, buf, len);
- close(fd);
-
- return n;
-}
-
-LWS_VISIBLE int
-lws_plat_recommended_rsa_bits(void)
-{
- return 4096;
-}
diff --git a/thirdparty/libwebsockets/plat/lws-plat-win.c b/thirdparty/libwebsockets/plat/lws-plat-win.c
deleted file mode 100644
index 26caab2cde..0000000000
--- a/thirdparty/libwebsockets/plat/lws-plat-win.c
+++ /dev/null
@@ -1,852 +0,0 @@
-#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
-#define _WINSOCK_DEPRECATED_NO_WARNINGS
-#endif
-#include "core/private.h"
-
-void lws_plat_apply_FD_CLOEXEC(int n)
-{
-}
-
-int
-lws_plat_socket_offset(void)
-{
- return 0;
-}
-
-int
-lws_plat_pipe_create(struct lws *wsi)
-{
- return 1;
-}
-
-int
-lws_plat_pipe_signal(struct lws *wsi)
-{
- struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
-
- WSASetEvent(pt->events[0]); /* trigger the cancel event */
-
- return 0;
-}
-
-void
-lws_plat_pipe_close(struct lws *wsi)
-{
-}
-
-unsigned long long
-time_in_microseconds()
-{
-#ifndef DELTA_EPOCH_IN_MICROSECS
-#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
-#endif
- FILETIME filetime;
- ULARGE_INTEGER datetime;
-
-#ifdef _WIN32_WCE
- GetCurrentFT(&filetime);
-#else
- GetSystemTimeAsFileTime(&filetime);
-#endif
-
- /*
- * As per Windows documentation for FILETIME, copy the resulting
- * FILETIME structure to a ULARGE_INTEGER structure using memcpy
- * (using memcpy instead of direct assignment can prevent alignment
- * faults on 64-bit Windows).
- */
- memcpy(&datetime, &filetime, sizeof(datetime));
-
- /* Windows file times are in 100s of nanoseconds. */
- return (datetime.QuadPart / 10) - DELTA_EPOCH_IN_MICROSECS;
-}
-
-#ifdef _WIN32_WCE
-time_t time(time_t *t)
-{
- time_t ret = time_in_microseconds() / 1000000;
-
- if(t != NULL)
- *t = ret;
-
- return ret;
-}
-#endif
-
-/* file descriptor hash management */
-
-struct lws *
-wsi_from_fd(const struct lws_context *context, lws_sockfd_type fd)
-{
- int h = LWS_FD_HASH(fd);
- int n = 0;
-
- for (n = 0; n < context->fd_hashtable[h].length; n++)
- if (context->fd_hashtable[h].wsi[n]->desc.sockfd == fd)
- return context->fd_hashtable[h].wsi[n];
-
- return NULL;
-}
-
-int
-insert_wsi(struct lws_context *context, struct lws *wsi)
-{
- int h = LWS_FD_HASH(wsi->desc.sockfd);
-
- if (context->fd_hashtable[h].length == (getdtablesize() - 1)) {
- lwsl_err("hash table overflow\n");
- return 1;
- }
-
- context->fd_hashtable[h].wsi[context->fd_hashtable[h].length++] = wsi;
-
- return 0;
-}
-
-int
-delete_from_fd(struct lws_context *context, lws_sockfd_type fd)
-{
- int h = LWS_FD_HASH(fd);
- int n = 0;
-
- for (n = 0; n < context->fd_hashtable[h].length; n++)
- if (context->fd_hashtable[h].wsi[n]->desc.sockfd == fd) {
- while (n < context->fd_hashtable[h].length) {
- context->fd_hashtable[h].wsi[n] =
- context->fd_hashtable[h].wsi[n + 1];
- n++;
- }
- context->fd_hashtable[h].length--;
-
- return 0;
- }
-
- lwsl_err("Failed to find fd %d requested for "
- "delete in hashtable\n", fd);
- return 1;
-}
-
-LWS_VISIBLE int
-lws_get_random(struct lws_context *context, void *buf, int len)
-{
- int n;
- char *p = (char *)buf;
-
- for (n = 0; n < len; n++)
- p[n] = (unsigned char)rand();
-
- return n;
-}
-
-LWS_VISIBLE int
-lws_send_pipe_choked(struct lws *wsi)
-{ struct lws *wsi_eff = wsi;
-
-#if defined(LWS_WITH_HTTP2)
- wsi_eff = lws_get_network_wsi(wsi);
-#endif
- /* the fact we checked implies we avoided back-to-back writes */
- wsi_eff->could_have_pending = 0;
-
- /* treat the fact we got a truncated send pending as if we're choked */
- if (wsi_eff->trunc_len)
- return 1;
-
- return (int)wsi_eff->sock_send_blocking;
-}
-
-LWS_VISIBLE int
-lws_poll_listen_fd(struct lws_pollfd *fd)
-{
- fd_set readfds;
- struct timeval tv = { 0, 0 };
-
- assert((fd->events & LWS_POLLIN) == LWS_POLLIN);
-
- FD_ZERO(&readfds);
- FD_SET(fd->fd, &readfds);
-
- return select(((int)fd->fd) + 1, &readfds, NULL, NULL, &tv);
-}
-
-LWS_VISIBLE void
-lwsl_emit_syslog(int level, const char *line)
-{
- lwsl_emit_stderr(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;
- WSANETWORKEVENTS networkevents;
- struct lws_pollfd *pfd;
- struct lws *wsi;
- unsigned int i;
- DWORD ev;
- int n, m;
-
- /* stay dead once we are dead */
- if (context == NULL || !context->vhost_list)
- return 1;
-
- pt = &context->pt[tsi];
-
- 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;
- context->service_tid_detected = 1;
- }
-
- if (timeout_ms < 0) {
- if (lws_service_flag_pending(context, tsi)) {
- /* any socket with events to service? */
- for (n = 0; n < (int)pt->fds_count; n++) {
- if (!pt->fds[n].revents)
- continue;
-
- 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;
- }
-
- if (context->event_loop_ops->run_pt)
- context->event_loop_ops->run_pt(context, tsi);
-
- for (i = 0; i < pt->fds_count; ++i) {
- pfd = &pt->fds[i];
-
- if (!(pfd->events & LWS_POLLOUT))
- continue;
-
- wsi = wsi_from_fd(context, pfd->fd);
- if (!wsi || wsi->listener)
- continue;
- if (wsi->sock_send_blocking)
- continue;
- pfd->revents = LWS_POLLOUT;
- n = lws_service_fd(context, pfd);
- if (n < 0)
- return -1;
-
- /* Force WSAWaitForMultipleEvents() to check events and then return immediately. */
- timeout_ms = 0;
-
- /* if something closed, retry this slot */
- if (n)
- i--;
- }
-
- /*
- * 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;
- }
-
- if (timeout_ms) {
- lws_usec_t t;
-
- lws_pt_lock(pt, __func__);
- /* don't stay in poll wait longer than next hr timeout */
- t = __lws_hrtimer_service(pt);
-
- if ((lws_usec_t)timeout_ms * 1000 > t)
- timeout_ms = (int)(t / 1000);
- lws_pt_unlock(pt);
- }
-
- ev = WSAWaitForMultipleEvents(1, pt->events, FALSE, timeout_ms, FALSE);
- if (ev == WSA_WAIT_EVENT_0) {
- unsigned int eIdx, err;
-
- WSAResetEvent(pt->events[0]);
-
- if (pt->context->tls_ops &&
- pt->context->tls_ops->fake_POLLIN_for_buffered)
- pt->context->tls_ops->fake_POLLIN_for_buffered(pt);
-
- for (eIdx = 0; eIdx < pt->fds_count; ++eIdx) {
- if (WSAEnumNetworkEvents(pt->fds[eIdx].fd, 0,
- &networkevents) == SOCKET_ERROR) {
- lwsl_err("WSAEnumNetworkEvents() failed "
- "with error %d\n", LWS_ERRNO);
- return -1;
- }
-
- pfd = &pt->fds[eIdx];
- pfd->revents = (short)networkevents.lNetworkEvents;
-
- err = networkevents.iErrorCode[FD_CONNECT_BIT];
-
- if ((networkevents.lNetworkEvents & FD_CONNECT) &&
- err && err != LWS_EALREADY &&
- err != LWS_EINPROGRESS && err != LWS_EWOULDBLOCK &&
- err != WSAEINVAL) {
- lwsl_debug("Unable to connect errno=%d\n", err);
- pfd->revents |= LWS_POLLHUP;
- }
-
- if (pfd->revents & LWS_POLLOUT) {
- wsi = wsi_from_fd(context, pfd->fd);
- if (wsi)
- wsi->sock_send_blocking = 0;
- }
- /* if something closed, retry this slot */
- if (pfd->revents & LWS_POLLHUP)
- --eIdx;
-
- if (pfd->revents) {
- recv(pfd->fd, NULL, 0, 0);
- lws_service_fd_tsi(context, pfd, tsi);
- }
- }
- }
-
- context->service_tid = 0;
-
- if (ev == WSA_WAIT_TIMEOUT)
- lws_service_fd(context, NULL);
-
- 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, lws_sockfd_type fd)
-{
- int optval = 1;
- int optlen = sizeof(optval);
- u_long optl = 1;
- DWORD dwBytesRet;
- struct tcp_keepalive alive;
- int protonbr;
-#ifndef _WIN32_WCE
- struct protoent *tcp_proto;
-#endif
-
-#ifdef LWS_WITH_IPV6
- optval = 0;
- setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const void*)&optval, optlen);
-#endif
-
- if (vhost->ka_time) {
- /* enable keepalive on this socket */
- optval = 1;
- if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,
- (const char *)&optval, optlen) < 0)
- return 1;
-
- alive.onoff = TRUE;
- alive.keepalivetime = vhost->ka_time;
- alive.keepaliveinterval = vhost->ka_interval;
-
- if (WSAIoctl(fd, SIO_KEEPALIVE_VALS, &alive, sizeof(alive),
- NULL, 0, &dwBytesRet, NULL, NULL))
- return 1;
- }
-
- /* Disable Nagle */
- optval = 1;
-#ifndef _WIN32_WCE
- tcp_proto = getprotobyname("TCP");
- if (!tcp_proto) {
- lwsl_err("getprotobyname() failed with error %d\n", LWS_ERRNO);
- return 1;
- }
- protonbr = tcp_proto->p_proto;
-#else
- protonbr = 6;
-#endif
-
- setsockopt(fd, protonbr, TCP_NODELAY, (const char *)&optval, optlen);
-
- /* We are nonblocking... */
- ioctlsocket(fd, FIONBIO, &optl);
-
- return 0;
-}
-
-LWS_VISIBLE void
-lws_plat_drop_app_privileges(const struct lws_context_creation_info *info)
-{
-}
-
-LWS_VISIBLE int
-lws_plat_context_early_init(void)
-{
- WORD wVersionRequested;
- WSADATA wsaData;
- int err;
-
- /* Use the MAKEWORD(lowbyte, highbyte) macro from Windef.h */
- wVersionRequested = MAKEWORD(2, 2);
-
- err = WSAStartup(wVersionRequested, &wsaData);
- if (!err)
- return 0;
- /*
- * Tell the user that we could not find a usable
- * Winsock DLL
- */
- lwsl_err("WSAStartup failed with error: %d\n", err);
-
- return 1;
-}
-
-LWS_VISIBLE void
-lws_plat_context_early_destroy(struct lws_context *context)
-{
- struct lws_context_per_thread *pt = &context->pt[0];
- int n = context->count_threads;
-
- while (n--) {
- if (pt->events) {
- WSACloseEvent(pt->events[0]);
- lws_free(pt->events);
- }
- pt++;
- }
-}
-
-LWS_VISIBLE void
-lws_plat_context_late_destroy(struct lws_context *context)
-{
- int n;
-
- for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
- if (context->fd_hashtable[n].wsi)
- lws_free(context->fd_hashtable[n].wsi);
- }
-
- WSACleanup();
-}
-
-LWS_VISIBLE LWS_EXTERN int
-lws_interface_to_sa(int ipv6,
- const char *ifname, struct sockaddr_in *addr, size_t addrlen)
-{
-#ifdef LWS_WITH_IPV6
- struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
-
- if (ipv6) {
- if (lws_plat_inet_pton(AF_INET6, ifname, &addr6->sin6_addr) == 1) {
- return LWS_ITOSA_USABLE;
- }
- }
-#endif
-
- long long address = inet_addr(ifname);
-
- if (address == INADDR_NONE) {
- struct hostent *entry = gethostbyname(ifname);
- if (entry)
- address = ((struct in_addr *)entry->h_addr_list[0])->s_addr;
- }
-
- if (address == INADDR_NONE)
- return LWS_ITOSA_NOT_EXIST;
-
- addr->sin_addr.s_addr = (unsigned long)(lws_intptr_t)address;
-
- return LWS_ITOSA_USABLE;
-}
-
-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;
- pt->events[pt->fds_count] = pt->events[0];
- WSAEventSelect(wsi->desc.sockfd, pt->events[0],
- LWS_POLLIN | LWS_POLLHUP | FD_CONNECT);
-}
-
-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->events[m + 1] = pt->events[pt->fds_count--];
-}
-
-LWS_VISIBLE void
-lws_plat_service_periodic(struct lws_context *context)
-{
-}
-
-LWS_VISIBLE int
-lws_plat_check_connection_error(struct lws *wsi)
-{
- int optVal;
- int optLen = sizeof(int);
-
- if (getsockopt(wsi->desc.sockfd, SOL_SOCKET, SO_ERROR,
- (char*)&optVal, &optLen) != SOCKET_ERROR && optVal &&
- optVal != LWS_EALREADY && optVal != LWS_EINPROGRESS &&
- optVal != LWS_EWOULDBLOCK && optVal != WSAEINVAL) {
- lwsl_debug("Connect failed SO_ERROR=%d\n", optVal);
- return 1;
- }
-
- return 0;
-}
-
-LWS_VISIBLE int
-lws_plat_change_pollfd(struct lws_context *context,
- struct lws *wsi, struct lws_pollfd *pfd)
-{
- struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
- long networkevents = LWS_POLLHUP | FD_CONNECT;
-
- if ((pfd->events & LWS_POLLIN))
- networkevents |= LWS_POLLIN;
-
- if ((pfd->events & LWS_POLLOUT))
- networkevents |= LWS_POLLOUT;
-
- if (WSAEventSelect(wsi->desc.sockfd,
- pt->events[0],
- networkevents) != SOCKET_ERROR)
- return 0;
-
- lwsl_err("WSAEventSelect() failed with error %d\n", LWS_ERRNO);
-
- return 1;
-}
-
-LWS_VISIBLE const char *
-lws_plat_inet_ntop(int af, const void *src, char *dst, int cnt)
-{
- WCHAR *buffer;
- DWORD bufferlen = cnt;
- BOOL ok = FALSE;
-
- buffer = lws_malloc(bufferlen * 2, "inet_ntop");
- if (!buffer) {
- lwsl_err("Out of memory\n");
- return NULL;
- }
-
- if (af == AF_INET) {
- struct sockaddr_in srcaddr;
- bzero(&srcaddr, sizeof(srcaddr));
- srcaddr.sin_family = AF_INET;
- memcpy(&(srcaddr.sin_addr), src, sizeof(srcaddr.sin_addr));
-
- if (!WSAAddressToStringW((struct sockaddr*)&srcaddr, sizeof(srcaddr), 0, buffer, &bufferlen))
- ok = TRUE;
-#ifdef LWS_WITH_IPV6
- } else if (af == AF_INET6) {
- struct sockaddr_in6 srcaddr;
- bzero(&srcaddr, sizeof(srcaddr));
- srcaddr.sin6_family = AF_INET6;
- memcpy(&(srcaddr.sin6_addr), src, sizeof(srcaddr.sin6_addr));
-
- if (!WSAAddressToStringW((struct sockaddr*)&srcaddr, sizeof(srcaddr), 0, buffer, &bufferlen))
- ok = TRUE;
-#endif
- } else
- lwsl_err("Unsupported type\n");
-
- if (!ok) {
- int rv = WSAGetLastError();
- lwsl_err("WSAAddressToString() : %d\n", rv);
- } else {
- if (WideCharToMultiByte(CP_ACP, 0, buffer, bufferlen, dst, cnt, 0, NULL) <= 0)
- ok = FALSE;
- }
-
- lws_free(buffer);
- return ok ? dst : NULL;
-}
-
-LWS_VISIBLE int
-lws_plat_inet_pton(int af, const char *src, void *dst)
-{
- WCHAR *buffer;
- DWORD bufferlen = (int)strlen(src) + 1;
- BOOL ok = FALSE;
-
- buffer = lws_malloc(bufferlen * 2, "inet_pton");
- if (!buffer) {
- lwsl_err("Out of memory\n");
- return -1;
- }
-
- if (MultiByteToWideChar(CP_ACP, 0, src, bufferlen, buffer, bufferlen) <= 0) {
- lwsl_err("Failed to convert multi byte to wide char\n");
- lws_free(buffer);
- return -1;
- }
-
- if (af == AF_INET) {
- struct sockaddr_in dstaddr;
- int dstaddrlen = sizeof(dstaddr);
- bzero(&dstaddr, sizeof(dstaddr));
- dstaddr.sin_family = AF_INET;
-
- if (!WSAStringToAddressW(buffer, af, 0, (struct sockaddr *) &dstaddr, &dstaddrlen)) {
- ok = TRUE;
- memcpy(dst, &dstaddr.sin_addr, sizeof(dstaddr.sin_addr));
- }
-#ifdef LWS_WITH_IPV6
- } else if (af == AF_INET6) {
- struct sockaddr_in6 dstaddr;
- int dstaddrlen = sizeof(dstaddr);
- bzero(&dstaddr, sizeof(dstaddr));
- dstaddr.sin6_family = AF_INET6;
-
- if (!WSAStringToAddressW(buffer, af, 0, (struct sockaddr *) &dstaddr, &dstaddrlen)) {
- ok = TRUE;
- memcpy(dst, &dstaddr.sin6_addr, sizeof(dstaddr.sin6_addr));
- }
-#endif
- } else
- lwsl_err("Unsupported type\n");
-
- if (!ok) {
- int rv = WSAGetLastError();
- lwsl_err("WSAAddressToString() : %d\n", rv);
- }
-
- lws_free(buffer);
- return ok ? 1 : -1;
-}
-
-LWS_VISIBLE lws_fop_fd_t
-_lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename,
- const char *vpath, lws_fop_flags_t *flags)
-{
- HANDLE ret;
- WCHAR buf[MAX_PATH];
- lws_fop_fd_t fop_fd;
- FILE_STANDARD_INFO fInfo = {0};
-
- MultiByteToWideChar(CP_UTF8, 0, filename, -1, buf, LWS_ARRAY_SIZE(buf));
-
-#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0602 // Windows 8 (minimum when UWP_ENABLED, but can be used in Windows builds)
- CREATEFILE2_EXTENDED_PARAMETERS extParams = {0};
- extParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
-
- if (((*flags) & 7) == _O_RDONLY) {
- ret = CreateFile2(buf, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, &extParams);
- } else {
- ret = CreateFile2(buf, GENERIC_WRITE, 0, CREATE_ALWAYS, &extParams);
- }
-#else
- if (((*flags) & 7) == _O_RDONLY) {
- ret = CreateFileW(buf, GENERIC_READ, FILE_SHARE_READ,
- NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- } else {
- ret = CreateFileW(buf, GENERIC_WRITE, 0, NULL,
- CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
- }
-#endif
-
- if (ret == LWS_INVALID_FILE)
- goto bail;
-
- fop_fd = malloc(sizeof(*fop_fd));
- if (!fop_fd)
- goto bail;
-
- fop_fd->fops = fops;
- fop_fd->fd = ret;
- fop_fd->filesystem_priv = NULL; /* we don't use it */
- fop_fd->flags = *flags;
- fop_fd->len = 0;
- if(GetFileInformationByHandleEx(ret, FileStandardInfo, &fInfo, sizeof(fInfo)))
- fop_fd->len = fInfo.EndOfFile.QuadPart;
-
- fop_fd->pos = 0;
-
- return fop_fd;
-
-bail:
- return NULL;
-}
-
-LWS_VISIBLE int
-_lws_plat_file_close(lws_fop_fd_t *fop_fd)
-{
- HANDLE fd = (*fop_fd)->fd;
-
- free(*fop_fd);
- *fop_fd = NULL;
-
- CloseHandle((HANDLE)fd);
-
- return 0;
-}
-
-LWS_VISIBLE lws_fileofs_t
-_lws_plat_file_seek_cur(lws_fop_fd_t fop_fd, lws_fileofs_t offset)
-{
- LARGE_INTEGER l;
-
- l.QuadPart = offset;
- return SetFilePointerEx((HANDLE)fop_fd->fd, l, NULL, FILE_CURRENT);
-}
-
-LWS_VISIBLE int
-_lws_plat_file_read(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
- uint8_t *buf, lws_filepos_t len)
-{
- DWORD _amount;
-
- if (!ReadFile((HANDLE)fop_fd->fd, buf, (DWORD)len, &_amount, NULL)) {
- *amount = 0;
-
- return 1;
- }
-
- fop_fd->pos += _amount;
- *amount = (unsigned long)_amount;
-
- return 0;
-}
-
-LWS_VISIBLE int
-_lws_plat_file_write(lws_fop_fd_t fop_fd, lws_filepos_t *amount,
- uint8_t* buf, lws_filepos_t len)
-{
- DWORD _amount;
-
- if (!WriteFile((HANDLE)fop_fd->fd, buf, (DWORD)len, &_amount, NULL)) {
- *amount = 0;
-
- return 1;
- }
-
- fop_fd->pos += _amount;
- *amount = (unsigned long)_amount;
-
- return 0;
-}
-
-LWS_VISIBLE int
-lws_plat_init(struct lws_context *context,
- const struct lws_context_creation_info *info)
-{
- struct lws_context_per_thread *pt = &context->pt[0];
- int i, n = context->count_threads;
-
- for (i = 0; i < FD_HASHTABLE_MODULUS; i++) {
- context->fd_hashtable[i].wsi =
- lws_zalloc(sizeof(struct lws*) * context->max_fds, "win hashtable");
-
- if (!context->fd_hashtable[i].wsi)
- return -1;
- }
-
- while (n--) {
- pt->events = lws_malloc(sizeof(WSAEVENT) *
- (context->fd_limit_per_thread + 1), "event table");
- if (pt->events == NULL) {
- lwsl_err("Unable to allocate events array for %d connections\n",
- context->fd_limit_per_thread + 1);
- return 1;
- }
-
- pt->fds_count = 0;
- pt->events[0] = WSACreateEvent(); /* the cancel event */
-
- pt++;
- }
-
- context->fd_random = 0;
-
-#ifdef LWS_WITH_PLUGINS
- if (info->plugin_dirs)
- lws_plat_plugins_init(context, info->plugin_dirs);
-#endif
-
- return 0;
-}
-
-
-int kill(int pid, int sig)
-{
- lwsl_err("Sorry Windows doesn't support kill().");
- exit(0);
-}
-
-int fork(void)
-{
- lwsl_err("Sorry Windows doesn't support fork().");
- exit(0);
-}
-
-LWS_VISIBLE int
-lws_plat_write_cert(struct lws_vhost *vhost, int is_key, int fd, void *buf,
- int len)
-{
- int n;
-
- n = write(fd, buf, len);
-
- lseek(fd, 0, SEEK_SET);
-
- return n != len;
-}
-
-LWS_VISIBLE int
-lws_plat_write_file(const char *filename, void *buf, int len)
-{
- int m, fd;
-
- fd = lws_open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
-
- if (fd == -1)
- return -1;
-
- m = write(fd, buf, len);
- close(fd);
-
- return m != len;
-}
-
-LWS_VISIBLE int
-lws_plat_read_file(const char *filename, void *buf, int len)
-{
- int n, fd = lws_open(filename, O_RDONLY);
- if (fd == -1)
- return -1;
-
- n = read(fd, buf, len);
- close(fd);
-
- return n;
-}
-
-LWS_VISIBLE int
-lws_plat_recommended_rsa_bits(void)
-{
- return 4096;
-}
diff --git a/thirdparty/libwebsockets/roles/h1/ops-h1.c b/thirdparty/libwebsockets/roles/h1/ops-h1.c
deleted file mode 100644
index 9001c864ea..0000000000
--- a/thirdparty/libwebsockets/roles/h1/ops-h1.c
+++ /dev/null
@@ -1,701 +0,0 @@
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010-2018 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- */
-
-#include <core/private.h>
-
-#ifndef min
-#define min(a, b) ((a) < (b) ? (a) : (b))
-#endif
-
-
-/*
- * We have to take care about parsing because the headers may be split
- * into multiple fragments. They may contain unknown headers with arbitrary
- * argument lengths. So, we parse using a single-character at a time state
- * machine that is completely independent of packet size.
- *
- * Returns <0 for error or length of chars consumed from buf (up to len)
- */
-
-int
-lws_read_h1(struct lws *wsi, unsigned char *buf, lws_filepos_t len)
-{
- unsigned char *last_char, *oldbuf = buf;
- lws_filepos_t body_chunk_len;
- size_t n;
-
- // lwsl_notice("%s: h1 path: wsi state 0x%x\n", __func__, lwsi_state(wsi));
-
- switch (lwsi_state(wsi)) {
-
- case LRS_ISSUING_FILE:
- return 0;
-
- case LRS_ESTABLISHED:
-
- if (lwsi_role_ws(wsi))
- goto ws_mode;
-
- if (lwsi_role_client(wsi))
- break;
-
- wsi->hdr_parsing_completed = 0;
-
- /* fallthru */
-
- case LRS_HEADERS:
- if (!wsi->http.ah) {
- lwsl_err("%s: LRS_HEADERS: NULL ah\n", __func__);
- assert(0);
- }
- lwsl_parser("issuing %d bytes to parser\n", (int)len);
-#if defined(LWS_ROLE_WS) && !defined(LWS_NO_CLIENT)
- if (lws_ws_handshake_client(wsi, &buf, (size_t)len))
- goto bail;
-#endif
- last_char = buf;
- if (lws_handshake_server(wsi, &buf, (size_t)len))
- /* Handshake indicates this session is done. */
- goto bail;
-
- /* we might have transitioned to RAW */
- if (wsi->role_ops == &role_ops_raw_skt ||
- wsi->role_ops == &role_ops_raw_file)
- /* we gave the read buffer to RAW handler already */
- goto read_ok;
-
- /*
- * It's possible that we've exhausted our data already, or
- * rx flow control has stopped us dealing with this early,
- * but lws_handshake_server doesn't update len for us.
- * Figure out how much was read, so that we can proceed
- * appropriately:
- */
- len -= (buf - last_char);
-// lwsl_debug("%s: thinks we have used %ld\n", __func__, (long)len);
-
- if (!wsi->hdr_parsing_completed)
- /* More header content on the way */
- goto read_ok;
-
- switch (lwsi_state(wsi)) {
- case LRS_ESTABLISHED:
- case LRS_HEADERS:
- goto read_ok;
- case LRS_ISSUING_FILE:
- goto read_ok;
- case LRS_BODY:
- wsi->http.rx_content_remain =
- wsi->http.rx_content_length;
- if (wsi->http.rx_content_remain)
- goto http_postbody;
-
- /* there is no POST content */
- goto postbody_completion;
- default:
- break;
- }
- break;
-
- case LRS_BODY:
-http_postbody:
- lwsl_debug("%s: http post body: remain %d\n", __func__,
- (int)wsi->http.rx_content_remain);
- while (len && wsi->http.rx_content_remain) {
- /* Copy as much as possible, up to the limit of:
- * what we have in the read buffer (len)
- * remaining portion of the POST body (content_remain)
- */
- body_chunk_len = min(wsi->http.rx_content_remain, len);
- wsi->http.rx_content_remain -= body_chunk_len;
- len -= body_chunk_len;
-#ifdef LWS_WITH_CGI
- if (wsi->http.cgi) {
- struct lws_cgi_args args;
-
- args.ch = LWS_STDIN;
- args.stdwsi = &wsi->http.cgi->stdwsi[0];
- args.data = buf;
- args.len = body_chunk_len;
-
- /* returns how much used */
- n = user_callback_handle_rxflow(
- wsi->protocol->callback,
- wsi, LWS_CALLBACK_CGI_STDIN_DATA,
- wsi->user_space,
- (void *)&args, 0);
- if ((int)n < 0)
- goto bail;
- } else {
-#endif
- n = wsi->protocol->callback(wsi,
- LWS_CALLBACK_HTTP_BODY, wsi->user_space,
- buf, (size_t)body_chunk_len);
- if (n)
- goto bail;
- n = (size_t)body_chunk_len;
-#ifdef LWS_WITH_CGI
- }
-#endif
- buf += n;
-
- if (wsi->http.rx_content_remain) {
- lws_set_timeout(wsi, PENDING_TIMEOUT_HTTP_CONTENT,
- wsi->context->timeout_secs);
- break;
- }
- /* he sent all the content in time */
-postbody_completion:
-#ifdef LWS_WITH_CGI
- /*
- * If we're running a cgi, we can't let him off the
- * hook just because he sent his POST data
- */
- if (wsi->http.cgi)
- lws_set_timeout(wsi, PENDING_TIMEOUT_CGI,
- wsi->context->timeout_secs);
- else
-#endif
- lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
-#ifdef LWS_WITH_CGI
- if (!wsi->http.cgi)
-#endif
- {
- lwsl_info("HTTP_BODY_COMPLETION: %p (%s)\n",
- wsi, wsi->protocol->name);
- n = wsi->protocol->callback(wsi,
- LWS_CALLBACK_HTTP_BODY_COMPLETION,
- wsi->user_space, NULL, 0);
- if (n)
- goto bail;
-
- if (wsi->http2_substream)
- lwsi_set_state(wsi, LRS_ESTABLISHED);
- }
-
- break;
- }
- break;
-
- case LRS_RETURNED_CLOSE:
- case LRS_AWAITING_CLOSE_ACK:
- case LRS_WAITING_TO_SEND_CLOSE:
- case LRS_SHUTDOWN:
-
-ws_mode:
-#if !defined(LWS_NO_CLIENT) && defined(LWS_ROLE_WS)
- // lwsl_notice("%s: ws_mode\n", __func__);
- if (lws_ws_handshake_client(wsi, &buf, (size_t)len))
- goto bail;
-#endif
-#if defined(LWS_ROLE_WS)
- if (lwsi_role_ws(wsi) && lwsi_role_server(wsi) &&
- /*
- * for h2 we are on the swsi
- */
- lws_parse_ws(wsi, &buf, (size_t)len) < 0) {
- lwsl_info("%s: lws_parse_ws bailed\n", __func__);
- goto bail;
- }
-#endif
- // lwsl_notice("%s: ws_mode: buf moved on by %d\n", __func__,
- // lws_ptr_diff(buf, oldbuf));
- break;
-
- case LRS_DEFERRING_ACTION:
- lwsl_debug("%s: LRS_DEFERRING_ACTION\n", __func__);
- break;
-
- case LRS_SSL_ACK_PENDING:
- break;
-
- case LRS_DEAD_SOCKET:
- lwsl_err("%s: Unhandled state LRS_DEAD_SOCKET\n", __func__);
- goto bail;
- // assert(0);
- /* fallthru */
-
- default:
- lwsl_err("%s: Unhandled state %d\n", __func__, lwsi_state(wsi));
- assert(0);
- goto bail;
- }
-
-read_ok:
- /* Nothing more to do for now */
-// lwsl_info("%s: %p: read_ok, used %ld (len %d, state %d)\n", __func__,
-// wsi, (long)(buf - oldbuf), (int)len, wsi->state);
-
- return lws_ptr_diff(buf, oldbuf);
-
-bail:
- /*
- * h2 / h2-ws calls us recursively in
- *
- * lws_read_h1()->
- * lws_h2_parser()->
- * lws_read_h1()
- *
- * pattern, having stripped the h2 framing in the middle.
- *
- * When taking down the whole connection, make sure that only the
- * outer lws_read() does the wsi close.
- */
- if (!wsi->outer_will_close)
- lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS,
- "lws_read_h1 bail");
-
- return -1;
-}
-#if !defined(LWS_NO_SERVER)
-static int
-lws_h1_server_socket_service(struct lws *wsi, struct lws_pollfd *pollfd)
-{
- struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
- struct lws_tokens ebuf;
- int n, buffered;
-
- if (lwsi_state(wsi) == LRS_DEFERRING_ACTION)
- goto try_pollout;
-
- /* any incoming data ready? */
-
- if (!(pollfd->revents & pollfd->events & LWS_POLLIN))
- goto try_pollout;
-
- /*
- * If we previously just did POLLIN when IN and OUT were signaled
- * (because POLLIN processing may have used up the POLLOUT), don't let
- * that happen twice in a row... next time we see the situation favour
- * POLLOUT
- */
-
- if (wsi->favoured_pollin &&
- (pollfd->revents & pollfd->events & LWS_POLLOUT)) {
- // lwsl_notice("favouring pollout\n");
- wsi->favoured_pollin = 0;
- goto try_pollout;
- }
-
- /*
- * We haven't processed that the tunnel is set up yet, so
- * defer reading
- */
-
- if (lwsi_state(wsi) == LRS_SSL_ACK_PENDING)
- return LWS_HPI_RET_HANDLED;
-
- /* these states imply we MUST have an ah attached */
-
- if ((lwsi_state(wsi) == LRS_ESTABLISHED ||
- lwsi_state(wsi) == LRS_ISSUING_FILE ||
- lwsi_state(wsi) == LRS_HEADERS ||
- lwsi_state(wsi) == LRS_BODY)) {
-
- if (!wsi->http.ah && lws_header_table_attach(wsi, 0)) {
- lwsl_info("%s: wsi %p: ah not available\n", __func__, wsi);
- goto try_pollout;
- }
-
- /*
- * We got here because there was specifically POLLIN...
- * regardless of our buflist state, we need to get it,
- * and either use it, or append to the buflist and use
- * buflist head material.
- *
- * We will not notice a connection close until the buflist is
- * exhausted and we tried to do a read of some kind.
- */
-
- buffered = lws_buflist_aware_read(pt, wsi, &ebuf);
- switch (ebuf.len) {
- case 0:
- lwsl_info("%s: read 0 len a\n", __func__);
- wsi->seen_zero_length_recv = 1;
- lws_change_pollfd(wsi, LWS_POLLIN, 0);
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- /*
- * autobahn requires us to win the race between close
- * and draining the extensions
- */
- if (wsi->ws &&
- (wsi->ws->rx_draining_ext || wsi->ws->tx_draining_ext))
- goto try_pollout;
-#endif
- /*
- * normally, we respond to close with logically closing
- * our side immediately
- */
- goto fail;
-
- case LWS_SSL_CAPABLE_ERROR:
- goto fail;
- case LWS_SSL_CAPABLE_MORE_SERVICE:
- goto try_pollout;
- }
-
- /* just ignore incoming if waiting for close */
- if (lwsi_state(wsi) == LRS_FLUSHING_BEFORE_CLOSE) {
- lwsl_notice("%s: just ignoring\n", __func__);
- goto try_pollout;
- }
-
- if (lwsi_state(wsi) == LRS_ISSUING_FILE) {
- // lwsl_notice("stashing: wsi %p: bd %d\n", wsi, buffered);
- if (lws_buflist_aware_consume(wsi, &ebuf, 0, buffered))
- return LWS_HPI_RET_PLEASE_CLOSE_ME;
-
- goto try_pollout;
- }
-
- /*
- * Otherwise give it to whoever wants it according to the
- * connection state
- */
-#if defined(LWS_ROLE_H2)
- if (lwsi_role_h2(wsi) && lwsi_state(wsi) != LRS_BODY)
- n = lws_read_h2(wsi, (uint8_t *)ebuf.token, ebuf.len);
- else
-#endif
- n = lws_read_h1(wsi, (uint8_t *)ebuf.token, ebuf.len);
- if (n < 0) /* we closed wsi */
- return LWS_HPI_RET_WSI_ALREADY_DIED;
-
- lwsl_debug("%s: consumed %d\n", __func__, n);
-
- if (lws_buflist_aware_consume(wsi, &ebuf, n, buffered))
- return LWS_HPI_RET_PLEASE_CLOSE_ME;
-
- /*
- * during the parsing our role changed to something non-http,
- * so the ah has no further meaning
- */
-
- if (wsi->http.ah &&
- !lwsi_role_h1(wsi) &&
- !lwsi_role_h2(wsi) &&
- !lwsi_role_cgi(wsi))
- lws_header_table_detach(wsi, 0);
-
- /*
- * He may have used up the writability above, if we will defer
- * POLLOUT processing in favour of POLLIN, note it
- */
-
- if (pollfd->revents & LWS_POLLOUT)
- wsi->favoured_pollin = 1;
-
- return LWS_HPI_RET_HANDLED;
- }
-
- /*
- * He may have used up the writability above, if we will defer POLLOUT
- * processing in favour of POLLIN, note it
- */
-
- if (pollfd->revents & LWS_POLLOUT)
- wsi->favoured_pollin = 1;
-
-try_pollout:
-
- /* this handles POLLOUT for http serving fragments */
-
- if (!(pollfd->revents & LWS_POLLOUT))
- return LWS_HPI_RET_HANDLED;
-
- /* one shot */
- if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) {
- lwsl_notice("%s a\n", __func__);
- goto fail;
- }
-
- /* clear back-to-back write detection */
- wsi->could_have_pending = 0;
-
- if (lwsi_state(wsi) == LRS_DEFERRING_ACTION) {
- lwsl_debug("%s: LRS_DEFERRING_ACTION now writable\n", __func__);
-
- lwsi_set_state(wsi, LRS_ESTABLISHED);
- if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) {
- lwsl_info("failed at set pollfd\n");
- goto fail;
- }
- }
-
- if (!wsi->hdr_parsing_completed)
- return LWS_HPI_RET_HANDLED;
-
- if (lwsi_state(wsi) != LRS_ISSUING_FILE) {
-
- if (wsi->trunc_len) {
- //lwsl_notice("%s: completing partial\n", __func__);
- if (lws_issue_raw(wsi, wsi->trunc_alloc + wsi->trunc_offset,
- wsi->trunc_len) < 0) {
- lwsl_info("%s signalling to close\n", __func__);
- goto fail;
- }
- return LWS_HPI_RET_HANDLED;
- }
-
- lws_stats_atomic_bump(wsi->context, pt,
- LWSSTATS_C_WRITEABLE_CB, 1);
-#if defined(LWS_WITH_STATS)
- if (wsi->active_writable_req_us) {
- uint64_t ul = time_in_microseconds() -
- wsi->active_writable_req_us;
-
- lws_stats_atomic_bump(wsi->context, pt,
- LWSSTATS_MS_WRITABLE_DELAY, ul);
- lws_stats_atomic_max(wsi->context, pt,
- LWSSTATS_MS_WORST_WRITABLE_DELAY, ul);
- wsi->active_writable_req_us = 0;
- }
-#endif
-
- n = user_callback_handle_rxflow(wsi->protocol->callback, wsi,
- LWS_CALLBACK_HTTP_WRITEABLE,
- wsi->user_space, NULL, 0);
- if (n < 0) {
- lwsl_info("writeable_fail\n");
- goto fail;
- }
-
- return LWS_HPI_RET_HANDLED;
- }
-
- /* >0 == completion, <0 == error
- *
- * We'll get a LWS_CALLBACK_HTTP_FILE_COMPLETION callback when
- * it's done. That's the case even if we just completed the
- * send, so wait for that.
- */
- n = lws_serve_http_file_fragment(wsi);
- if (n < 0)
- goto fail;
-
- return LWS_HPI_RET_HANDLED;
-
-
-fail:
- lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS,
- "server socket svc fail");
-
- return LWS_HPI_RET_WSI_ALREADY_DIED;
-}
-#endif
-
-static int
-rops_handle_POLLIN_h1(struct lws_context_per_thread *pt, struct lws *wsi,
- struct lws_pollfd *pollfd)
-{
-
-// lwsl_notice("%s: %p: wsistate 0x%x %s, revents 0x%x\n", __func__, wsi,
-// wsi->wsistate, wsi->role_ops->name, pollfd->revents);
-
-#ifdef LWS_WITH_CGI
- if (wsi->http.cgi && (pollfd->revents & LWS_POLLOUT)) {
- if (lws_handle_POLLOUT_event(wsi, pollfd))
- return LWS_HPI_RET_PLEASE_CLOSE_ME;
-
- return LWS_HPI_RET_HANDLED;
- }
-#endif
-
- if (lws_is_flowcontrolled(wsi))
- /* We cannot deal with any kind of new RX because we are
- * RX-flowcontrolled.
- */
- return LWS_HPI_RET_HANDLED;
-
-#if !defined(LWS_NO_SERVER)
- if (!lwsi_role_client(wsi)) {
- int n;
-
- lwsl_debug("%s: %p: wsistate 0x%x\n", __func__, wsi, wsi->wsistate);
- n = lws_h1_server_socket_service(wsi, pollfd);
- if (n != LWS_HPI_RET_HANDLED)
- return n;
- if (lwsi_state(wsi) != LRS_SSL_INIT)
- if (lws_server_socket_service_ssl(wsi, LWS_SOCK_INVALID))
- return LWS_HPI_RET_PLEASE_CLOSE_ME;
-
- return LWS_HPI_RET_HANDLED;
- }
-#endif
-
-#ifndef LWS_NO_CLIENT
- if ((pollfd->revents & LWS_POLLIN) &&
- wsi->hdr_parsing_completed && !wsi->told_user_closed) {
-
- /*
- * In SSL mode we get POLLIN notification about
- * encrypted data in.
- *
- * But that is not necessarily related to decrypted
- * data out becoming available; in may need to perform
- * other in or out before that happens.
- *
- * simply mark ourselves as having readable data
- * and turn off our POLLIN
- */
- wsi->client_rx_avail = 1;
- lws_change_pollfd(wsi, LWS_POLLIN, 0);
-
- //lwsl_notice("calling back %s\n", wsi->protocol->name);
-
- /* let user code know, he'll usually ask for writeable
- * callback and drain / re-enable it there
- */
- if (user_callback_handle_rxflow(
- wsi->protocol->callback,
- wsi, LWS_CALLBACK_RECEIVE_CLIENT_HTTP,
- wsi->user_space, NULL, 0)) {
- lwsl_info("RECEIVE_CLIENT_HTTP closed it\n");
- return LWS_HPI_RET_PLEASE_CLOSE_ME;
- }
-
- return LWS_HPI_RET_HANDLED;
- }
-#endif
-
-// if (lwsi_state(wsi) == LRS_ESTABLISHED)
-// return LWS_HPI_RET_HANDLED;
-
-#if !defined(LWS_NO_CLIENT)
- if ((pollfd->revents & LWS_POLLOUT) &&
- lws_handle_POLLOUT_event(wsi, pollfd)) {
- lwsl_debug("POLLOUT event closed it\n");
- return LWS_HPI_RET_PLEASE_CLOSE_ME;
- }
-
- if (lws_client_socket_service(wsi, pollfd, NULL))
- return LWS_HPI_RET_WSI_ALREADY_DIED;
-#endif
-
- return LWS_HPI_RET_HANDLED;
-}
-
-int rops_handle_POLLOUT_h1(struct lws *wsi)
-{
- if (lwsi_state(wsi) == LRS_ISSUE_HTTP_BODY)
- return LWS_HP_RET_USER_SERVICE;
-
- if (lwsi_role_client(wsi))
- return LWS_HP_RET_USER_SERVICE;
-
- return LWS_HP_RET_BAIL_OK;
-}
-
-static int
-rops_write_role_protocol_h1(struct lws *wsi, unsigned char *buf, size_t len,
- enum lws_write_protocol *wp)
-{
-#if 0
- /* if not in a state to send stuff, then just send nothing */
-
- if ((lwsi_state(wsi) != LRS_RETURNED_CLOSE &&
- lwsi_state(wsi) != LRS_WAITING_TO_SEND_CLOSE &&
- lwsi_state(wsi) != LRS_AWAITING_CLOSE_ACK)) {
- //assert(0);
- lwsl_debug("binning %d %d\n", lwsi_state(wsi), *wp);
- return 0;
- }
-#endif
-
- return lws_issue_raw(wsi, (unsigned char *)buf, len);
-}
-
-static int
-rops_alpn_negotiated_h1(struct lws *wsi, const char *alpn)
-{
- lwsl_debug("%s: client %d\n", __func__, lwsi_role_client(wsi));
-#if !defined(LWS_NO_CLIENT)
- if (lwsi_role_client(wsi)) {
- /*
- * If alpn asserts it is http/1.1, server support for KA is
- * mandatory.
- *
- * Knowing this lets us proceed with sending pipelined headers
- * before we received the first response headers.
- */
- wsi->keepalive_active = 1;
- }
-#endif
-
- return 0;
-}
-
-static int
-rops_destroy_role_h1(struct lws *wsi)
-{
- struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
- struct allocated_headers *ah;
-
- /* we may not have an ah, but may be on the waiting list... */
- lwsl_info("%s: ah det due to close\n", __func__);
- __lws_header_table_detach(wsi, 0);
-
- ah = pt->http.ah_list;
-
- while (ah) {
- if (ah->in_use && ah->wsi == wsi) {
- lwsl_err("%s: ah leak: wsi %p\n", __func__, wsi);
- ah->in_use = 0;
- ah->wsi = NULL;
- pt->http.ah_count_in_use--;
- break;
- }
- ah = ah->next;
- }
-
-#ifdef LWS_ROLE_WS
- lws_free_set_NULL(wsi->ws);
-#endif
- return 0;
-}
-
-struct lws_role_ops role_ops_h1 = {
- /* role name */ "h1",
- /* alpn id */ "http/1.1",
- /* check_upgrades */ NULL,
- /* init_context */ NULL,
- /* init_vhost */ NULL,
- /* destroy_vhost */ NULL,
- /* periodic_checks */ NULL,
- /* service_flag_pending */ NULL,
- /* handle_POLLIN */ rops_handle_POLLIN_h1,
- /* handle_POLLOUT */ rops_handle_POLLOUT_h1,
- /* perform_user_POLLOUT */ NULL,
- /* callback_on_writable */ NULL,
- /* tx_credit */ NULL,
- /* write_role_protocol */ rops_write_role_protocol_h1,
- /* encapsulation_parent */ NULL,
- /* alpn_negotiated */ rops_alpn_negotiated_h1,
- /* close_via_role_protocol */ NULL,
- /* close_role */ NULL,
- /* close_kill_connection */ NULL,
- /* destroy_role */ rops_destroy_role_h1,
- /* writeable cb clnt, srv */ { LWS_CALLBACK_CLIENT_HTTP_WRITEABLE,
- LWS_CALLBACK_HTTP_WRITEABLE },
- /* close cb clnt, srv */ { LWS_CALLBACK_CLOSED_CLIENT_HTTP,
- LWS_CALLBACK_CLOSED_HTTP },
- /* file_handle */ 0,
-};
diff --git a/thirdparty/libwebsockets/roles/h1/private.h b/thirdparty/libwebsockets/roles/h1/private.h
deleted file mode 100644
index 3f53954d33..0000000000
--- a/thirdparty/libwebsockets/roles/h1/private.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010 - 2018 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * This is included from core/private.h if LWS_ROLE_H1
- *
- * Most of the h1 business is defined in the h1 / h2 common roles/http dir
- */
-
-extern struct lws_role_ops role_ops_h1;
-#define lwsi_role_h1(wsi) (wsi->role_ops == &role_ops_h1)
diff --git a/thirdparty/libwebsockets/roles/http/client/client-handshake.c b/thirdparty/libwebsockets/roles/http/client/client-handshake.c
deleted file mode 100644
index 0095c79a69..0000000000
--- a/thirdparty/libwebsockets/roles/http/client/client-handshake.c
+++ /dev/null
@@ -1,1284 +0,0 @@
-#include "core/private.h"
-
-static int
-lws_getaddrinfo46(struct lws *wsi, const char *ads, struct addrinfo **result)
-{
- struct addrinfo hints;
-
- memset(&hints, 0, sizeof(hints));
- *result = NULL;
-
-#ifdef LWS_WITH_IPV6
- if (wsi->ipv6) {
-
-#if !defined(__ANDROID__)
- hints.ai_family = AF_INET6;
- hints.ai_flags = AI_V4MAPPED;
-#endif
- } else
-#endif
- {
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- }
-
- return getaddrinfo(ads, NULL, &hints, result);
-}
-
-struct lws *
-lws_client_connect_2(struct lws *wsi)
-{
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- struct lws_context *context = wsi->context;
- struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
- const char *adsin;
- struct lws *wsi_piggyback = NULL;
- struct lws_pollfd pfd;
- ssize_t plen = 0;
-#endif
- struct addrinfo *result;
- const char *ads;
- sockaddr46 sa46;
- int n, port;
- const char *cce = "", *iface;
- const char *meth = NULL;
-#ifdef LWS_WITH_IPV6
- char ipv6only = lws_check_opt(wsi->vhost->options,
- LWS_SERVER_OPTION_IPV6_V6ONLY_MODIFY |
- LWS_SERVER_OPTION_IPV6_V6ONLY_VALUE);
-
-#if defined(__ANDROID__)
- ipv6only = 0;
-#endif
-#endif
-
- lwsl_client("%s: %p\n", __func__, wsi);
-
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- if (!wsi->http.ah) {
- cce = "ah was NULL at cc2";
- lwsl_err("%s\n", cce);
- goto oom4;
- }
-
- /* we can only piggyback GET or POST */
-
- meth = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_METHOD);
- if (meth && strcmp(meth, "GET") && strcmp(meth, "POST"))
- goto create_new_conn;
-
- /* we only pipeline connections that said it was okay */
-
- if (!wsi->client_pipeline)
- goto create_new_conn;
-
- /*
- * let's take a look first and see if there are any already-active
- * client connections we can piggy-back on.
- */
-
- adsin = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS);
-
- lws_vhost_lock(wsi->vhost); /* ----------------------------------- { */
-
- lws_start_foreach_dll_safe(struct lws_dll_lws *, d, d1,
- wsi->vhost->dll_active_client_conns.next) {
- struct lws *w = lws_container_of(d, struct lws,
- dll_active_client_conns);
-
- lwsl_debug("%s: check %s %s %d %d\n", __func__, adsin,
- w->client_hostname_copy, wsi->c_port, w->c_port);
-
- if (w != wsi && w->client_hostname_copy &&
- !strcmp(adsin, w->client_hostname_copy) &&
-#if defined(LWS_WITH_TLS)
- (wsi->tls.use_ssl & LCCSCF_USE_SSL) ==
- (w->tls.use_ssl & LCCSCF_USE_SSL) &&
-#endif
- wsi->c_port == w->c_port) {
-
- /* someone else is already connected to the right guy */
-
- /* do we know for a fact pipelining won't fly? */
- if (w->keepalive_rejected) {
- lwsl_info("defeating pipelining due to no "
- "keepalive on server\n");
- lws_vhost_unlock(wsi->vhost); /* } ---------- */
- goto create_new_conn;
- }
-#if defined (LWS_WITH_HTTP2)
- /*
- * h2: in usable state already: just use it without
- * going through the queue
- */
- if (w->client_h2_alpn &&
- (lwsi_state(w) == LRS_H2_WAITING_TO_SEND_HEADERS ||
- lwsi_state(w) == LRS_ESTABLISHED)) {
-
- lwsl_info("%s: just join h2 directly\n",
- __func__);
-
- wsi->client_h2_alpn = 1;
- lws_wsi_h2_adopt(w, wsi);
- lws_vhost_unlock(wsi->vhost); /* } ---------- */
-
- return wsi;
- }
-#endif
-
- lwsl_info("applying %p to txn queue on %p (wsistate 0x%x)\n",
- wsi, w, w->wsistate);
- /*
- * ...let's add ourselves to his transaction queue...
- * we are adding ourselves at the HEAD
- */
- lws_dll_lws_add_front(&wsi->dll_client_transaction_queue,
- &w->dll_client_transaction_queue_head);
-
- /*
- * h1: pipeline our headers out on him,
- * and wait for our turn at client transaction_complete
- * to take over parsing the rx.
- */
-
- wsi_piggyback = w;
-
- lws_vhost_unlock(wsi->vhost); /* } ---------- */
- goto send_hs;
- }
-
- } lws_end_foreach_dll_safe(d, d1);
-
- lws_vhost_unlock(wsi->vhost); /* } ---------------------------------- */
-
-create_new_conn:
-#endif
-
- /*
- * clients who will create their own fresh connection keep a copy of
- * the hostname they originally connected to, in case other connections
- * want to use it too
- */
-
- if (!wsi->client_hostname_copy)
- wsi->client_hostname_copy =
- lws_strdup(lws_hdr_simple_ptr(wsi,
- _WSI_TOKEN_CLIENT_PEER_ADDRESS));
-
- /*
- * If we made our own connection, and we're doing a method that can take
- * a pipeline, we are an "active client connection".
- *
- * Add ourselves to the vhost list of those so that others can
- * piggyback on our transaction queue
- */
-
- if (meth && (!strcmp(meth, "GET") || !strcmp(meth, "POST")) &&
- lws_dll_is_null(&wsi->dll_client_transaction_queue) &&
- lws_dll_is_null(&wsi->dll_active_client_conns)) {
- lws_vhost_lock(wsi->vhost);
- lws_dll_lws_add_front(&wsi->dll_active_client_conns,
- &wsi->vhost->dll_active_client_conns);
- lws_vhost_unlock(wsi->vhost);
- }
-
- /*
- * start off allowing ipv6 on connection if vhost allows it
- */
- wsi->ipv6 = LWS_IPV6_ENABLED(wsi->vhost);
-
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
-
- /* Decide what it is we need to connect to:
- *
- * Priority 1: connect to http proxy */
-
- if (wsi->vhost->http.http_proxy_port) {
- plen = sprintf((char *)pt->serv_buf,
- "CONNECT %s:%u HTTP/1.0\x0d\x0a"
- "User-agent: libwebsockets\x0d\x0a",
- lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS),
- wsi->c_port);
-
- if (wsi->vhost->proxy_basic_auth_token[0])
- plen += sprintf((char *)pt->serv_buf + plen,
- "Proxy-authorization: basic %s\x0d\x0a",
- wsi->vhost->proxy_basic_auth_token);
-
- plen += sprintf((char *)pt->serv_buf + plen, "\x0d\x0a");
- ads = wsi->vhost->http.http_proxy_address;
- port = wsi->vhost->http.http_proxy_port;
-#else
- if (0) {
-#endif
-
-#if defined(LWS_WITH_SOCKS5)
-
- /* Priority 2: Connect to SOCK5 Proxy */
-
- } else if (wsi->vhost->socks_proxy_port) {
- socks_generate_msg(wsi, SOCKS_MSG_GREETING, &plen);
- lwsl_client("Sending SOCKS Greeting\n");
- ads = wsi->vhost->socks_proxy_address;
- port = wsi->vhost->socks_proxy_port;
-#endif
- } else {
-
- /* Priority 3: Connect directly */
-
- ads = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS);
- port = wsi->c_port;
- }
-
- /*
- * prepare the actual connection
- * to whatever we decided to connect to
- */
-
- lwsl_info("%s: %p: address %s\n", __func__, wsi, ads);
-
- n = lws_getaddrinfo46(wsi, ads, &result);
-
-#ifdef LWS_WITH_IPV6
- if (wsi->ipv6) {
- struct sockaddr_in6 *sa6 =
- ((struct sockaddr_in6 *)result->ai_addr);
-
- if (n) {
- /* lws_getaddrinfo46 failed, there is no usable result */
- lwsl_notice("%s: lws_getaddrinfo46 failed %d\n",
- __func__, n);
- cce = "ipv6 lws_getaddrinfo46 failed";
- goto oom4;
- }
-
- memset(&sa46, 0, sizeof(sa46));
-
- sa46.sa6.sin6_family = AF_INET6;
- switch (result->ai_family) {
- case AF_INET:
- if (ipv6only)
- break;
- /* map IPv4 to IPv6 */
- bzero((char *)&sa46.sa6.sin6_addr,
- sizeof(sa46.sa6.sin6_addr));
- sa46.sa6.sin6_addr.s6_addr[10] = 0xff;
- sa46.sa6.sin6_addr.s6_addr[11] = 0xff;
- memcpy(&sa46.sa6.sin6_addr.s6_addr[12],
- &((struct sockaddr_in *)result->ai_addr)->sin_addr,
- sizeof(struct in_addr));
- lwsl_notice("uplevelling AF_INET to AF_INET6\n");
- break;
-
- case AF_INET6:
- memcpy(&sa46.sa6.sin6_addr, &sa6->sin6_addr,
- sizeof(struct in6_addr));
- sa46.sa6.sin6_scope_id = sa6->sin6_scope_id;
- sa46.sa6.sin6_flowinfo = sa6->sin6_flowinfo;
- break;
- default:
- lwsl_err("Unknown address family\n");
- freeaddrinfo(result);
- cce = "unknown address family";
- goto oom4;
- }
- } else
-#endif /* use ipv6 */
-
- /* use ipv4 */
- {
- void *p = NULL;
-
- if (!n) {
- struct addrinfo *res = result;
-
- /* pick the first AF_INET (IPv4) result */
-
- while (!p && res) {
- switch (res->ai_family) {
- case AF_INET:
- p = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
- break;
- }
-
- res = res->ai_next;
- }
-#if defined(LWS_FALLBACK_GETHOSTBYNAME)
- } else if (n == EAI_SYSTEM) {
- struct hostent *host;
-
- lwsl_info("getaddrinfo (ipv4) failed, trying gethostbyname\n");
- host = gethostbyname(ads);
- if (host) {
- p = host->h_addr;
- } else {
- lwsl_err("gethostbyname failed\n");
- cce = "gethostbyname (ipv4) failed";
- goto oom4;
- }
-#endif
- } else {
- lwsl_err("getaddrinfo failed\n");
- cce = "getaddrinfo failed";
- goto oom4;
- }
-
- if (!p) {
- if (result)
- freeaddrinfo(result);
- lwsl_err("Couldn't identify address\n");
- cce = "unable to lookup address";
- goto oom4;
- }
-
- sa46.sa4.sin_family = AF_INET;
- sa46.sa4.sin_addr = *((struct in_addr *)p);
- bzero(&sa46.sa4.sin_zero, 8);
- }
-
- if (result)
- freeaddrinfo(result);
-
- /* now we decided on ipv4 or ipv6, set the port */
-
- if (!lws_socket_is_valid(wsi->desc.sockfd)) {
-
- if (wsi->context->event_loop_ops->check_client_connect_ok &&
- wsi->context->event_loop_ops->check_client_connect_ok(wsi)) {
- cce = "waiting for event loop watcher to close";
- goto oom4;
- }
-
-#ifdef LWS_WITH_IPV6
- if (wsi->ipv6)
- wsi->desc.sockfd = socket(AF_INET6, SOCK_STREAM, 0);
- else
-#endif
- wsi->desc.sockfd = socket(AF_INET, SOCK_STREAM, 0);
-
- if (!lws_socket_is_valid(wsi->desc.sockfd)) {
- lwsl_warn("Unable to open socket\n");
- cce = "unable to open socket";
- goto oom4;
- }
-
- if (lws_plat_set_socket_options(wsi->vhost, wsi->desc.sockfd)) {
- lwsl_err("Failed to set wsi socket options\n");
- compatible_close(wsi->desc.sockfd);
- cce = "set socket opts failed";
- goto oom4;
- }
-
- lwsi_set_state(wsi, LRS_WAITING_CONNECT);
-
- if (wsi->context->event_loop_ops->accept)
- wsi->context->event_loop_ops->accept(wsi);
-
- if (__insert_wsi_socket_into_fds(wsi->context, wsi)) {
- compatible_close(wsi->desc.sockfd);
- cce = "insert wsi failed";
- goto oom4;
- }
-
- lws_change_pollfd(wsi, 0, LWS_POLLIN);
-
- /*
- * past here, we can't simply free the structs as error
- * handling as oom4 does. We have to run the whole close flow.
- */
-
- if (!wsi->protocol)
- wsi->protocol = &wsi->vhost->protocols[0];
-
- wsi->protocol->callback(wsi, LWS_CALLBACK_WSI_CREATE,
- wsi->user_space, NULL, 0);
-
- lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CONNECT_RESPONSE,
- AWAITING_TIMEOUT);
-
- iface = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_IFACE);
-
- if (iface) {
- n = lws_socket_bind(wsi->vhost, wsi->desc.sockfd, 0, iface);
- if (n < 0) {
- cce = "unable to bind socket";
- goto failed;
- }
- }
- }
-
-#ifdef LWS_WITH_IPV6
- if (wsi->ipv6) {
- sa46.sa6.sin6_port = htons(port);
- n = sizeof(struct sockaddr_in6);
- } else
-#endif
- {
- sa46.sa4.sin_port = htons(port);
- n = sizeof(struct sockaddr);
- }
-
- if (connect(wsi->desc.sockfd, (const struct sockaddr *)&sa46, n) == -1 ||
- LWS_ERRNO == LWS_EISCONN) {
- if (LWS_ERRNO == LWS_EALREADY ||
- LWS_ERRNO == LWS_EINPROGRESS ||
- LWS_ERRNO == LWS_EWOULDBLOCK
-#ifdef _WIN32
- || LWS_ERRNO == WSAEINVAL
-#endif
- ) {
- lwsl_client("nonblocking connect retry (errno = %d)\n",
- LWS_ERRNO);
-
- if (lws_plat_check_connection_error(wsi)) {
- cce = "socket connect failed";
- goto failed;
- }
-
- /*
- * must do specifically a POLLOUT poll to hear
- * about the connect completion
- */
- if (lws_change_pollfd(wsi, 0, LWS_POLLOUT)) {
- cce = "POLLOUT set failed";
- goto failed;
- }
-
- return wsi;
- }
-
- if (LWS_ERRNO != LWS_EISCONN) {
- lwsl_notice("Connect failed errno=%d\n", LWS_ERRNO);
- cce = "connect failed";
- goto failed;
- }
- }
-
- lwsl_client("connected\n");
-
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- /* we are connected to server, or proxy */
-
- /* http proxy */
- if (wsi->vhost->http.http_proxy_port) {
-
- /*
- * OK from now on we talk via the proxy, so connect to that
- *
- * (will overwrite existing pointer,
- * leaving old string/frag there but unreferenced)
- */
- if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS,
- wsi->vhost->http.http_proxy_address))
- goto failed;
- wsi->c_port = wsi->vhost->http.http_proxy_port;
-
- n = send(wsi->desc.sockfd, (char *)pt->serv_buf, (int)plen,
- MSG_NOSIGNAL);
- if (n < 0) {
- lwsl_debug("ERROR writing to proxy socket\n");
- cce = "proxy write failed";
- goto failed;
- }
-
- lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_PROXY_RESPONSE,
- AWAITING_TIMEOUT);
-
- lwsi_set_state(wsi, LRS_WAITING_PROXY_REPLY);
-
- return wsi;
- }
-#endif
-#if defined(LWS_WITH_SOCKS5)
- /* socks proxy */
- else if (wsi->vhost->socks_proxy_port) {
- n = send(wsi->desc.sockfd, (char *)pt->serv_buf, plen,
- MSG_NOSIGNAL);
- if (n < 0) {
- lwsl_debug("ERROR writing socks greeting\n");
- cce = "socks write failed";
- goto failed;
- }
-
- lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SOCKS_GREETING_REPLY,
- AWAITING_TIMEOUT);
-
- lwsi_set_state(wsi, LRS_WAITING_SOCKS_GREETING_REPLY);
-
- return wsi;
- }
-#endif
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
-send_hs:
-
- if (wsi_piggyback &&
- !lws_dll_is_null(&wsi->dll_client_transaction_queue)) {
- /*
- * We are pipelining on an already-established connection...
- * we can skip tls establishment.
- */
-
- lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE2);
-
- /*
- * we can't send our headers directly, because they have to
- * be sent when the parent is writeable. The parent will check
- * for anybody on his client transaction queue that is in
- * LRS_H1C_ISSUE_HANDSHAKE2, and let them write.
- *
- * If we are trying to do this too early, before the master
- * connection has written his own headers, then it will just
- * wait in the queue until it's possible to send them.
- */
- lws_callback_on_writable(wsi_piggyback);
- lwsl_info("%s: wsi %p: waiting to send headers (parent state %x)\n",
- __func__, wsi, lwsi_state(wsi_piggyback));
- } else {
- lwsl_info("%s: wsi %p: client creating own connection\n",
- __func__, wsi);
-
- /* we are making our own connection */
- lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE);
-
- /*
- * provoke service to issue the handshake directly.
- *
- * we need to do it this way because in the proxy case, this is
- * the next state and executed only if and when we get a good
- * proxy response inside the state machine... but notice in
- * SSL case this may not have sent anything yet with 0 return,
- * and won't until many retries from main loop. To stop that
- * becoming endless, cover with a timeout.
- */
-
- lws_set_timeout(wsi, PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE,
- AWAITING_TIMEOUT);
-
- pfd.fd = wsi->desc.sockfd;
- pfd.events = LWS_POLLIN;
- pfd.revents = LWS_POLLIN;
-
- n = lws_service_fd(context, &pfd);
- if (n < 0) {
- cce = "first service failed";
- goto failed;
- }
- if (n) /* returns 1 on failure after closing wsi */
- return NULL;
- }
-#endif
- return wsi;
-
-oom4:
- if (lwsi_role_client(wsi) && lwsi_state_est(wsi)) {
- wsi->protocol->callback(wsi,
- LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
- wsi->user_space, (void *)cce, strlen(cce));
- wsi->already_did_cce = 1;
- }
- /* take care that we might be inserted in fds already */
- if (wsi->position_in_fds_table != LWS_NO_FDS_POS)
- goto failed1;
- lws_remove_from_timeout_list(wsi);
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- lws_header_table_detach(wsi, 0);
-#endif
- lws_client_stash_destroy(wsi);
- lws_free_set_NULL(wsi->client_hostname_copy);
- lws_free(wsi);
-
- return NULL;
-
-failed:
- wsi->protocol->callback(wsi,
- LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
- wsi->user_space, (void *)cce, strlen(cce));
- wsi->already_did_cce = 1;
-failed1:
- lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "client_connect2");
-
- return NULL;
-}
-
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
-
-/**
- * lws_client_reset() - retarget a connected wsi to start over with a new connection (ie, redirect)
- * this only works if still in HTTP, ie, not upgraded yet
- * wsi: connection to reset
- * address: network address of the new server
- * port: port to connect to
- * path: uri path to connect to on the new server
- * host: host header to send to the new server
- */
-LWS_VISIBLE struct lws *
-lws_client_reset(struct lws **pwsi, int ssl, const char *address, int port,
- const char *path, const char *host)
-{
- char origin[300] = "", protocol[300] = "", method[32] = "",
- iface[16] = "", alpn[32] = "", *p;
- struct lws *wsi = *pwsi;
-
- if (wsi->redirects == 3) {
- lwsl_err("%s: Too many redirects\n", __func__);
- return NULL;
- }
- wsi->redirects++;
-
- p = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN);
- if (p)
- lws_strncpy(origin, p, sizeof(origin));
-
- p = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS);
- if (p)
- lws_strncpy(protocol, p, sizeof(protocol));
-
- p = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_METHOD);
- if (p)
- lws_strncpy(method, p, sizeof(method));
-
- p = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_IFACE);
- if (p)
- lws_strncpy(iface, p, sizeof(iface));
-
- p = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ALPN);
- if (p)
- lws_strncpy(alpn, p, sizeof(alpn));
-
- lwsl_info("redirect ads='%s', port=%d, path='%s', ssl = %d\n",
- address, port, path, ssl);
-
- /* close the connection by hand */
-
-#if defined(LWS_WITH_TLS)
- lws_ssl_close(wsi);
-#endif
-
- __remove_wsi_socket_from_fds(wsi);
-
- if (wsi->context->event_loop_ops->close_handle_manually)
- wsi->context->event_loop_ops->close_handle_manually(wsi);
- else
- compatible_close(wsi->desc.sockfd);
-
-#if defined(LWS_WITH_TLS)
- wsi->tls.use_ssl = ssl;
-#else
- if (ssl) {
- lwsl_err("%s: not configured for ssl\n", __func__);
- return NULL;
- }
-#endif
-
- wsi->desc.sockfd = LWS_SOCK_INVALID;
- lwsi_set_state(wsi, LRS_UNCONNECTED);
- wsi->protocol = NULL;
- wsi->pending_timeout = NO_PENDING_TIMEOUT;
- wsi->c_port = port;
- wsi->hdr_parsing_completed = 0;
- _lws_header_table_reset(wsi->http.ah);
-
- if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS, address))
- return NULL;
-
- if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_HOST, host))
- return NULL;
-
- if (origin[0])
- if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_ORIGIN,
- origin))
- return NULL;
- if (protocol[0])
- if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS,
- protocol))
- return NULL;
- if (method[0])
- if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_METHOD,
- method))
- return NULL;
-
- if (iface[0])
- if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_IFACE,
- iface))
- return NULL;
- if (alpn[0])
- if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_ALPN,
- alpn))
- return NULL;
-
- origin[0] = '/';
- strncpy(&origin[1], path, sizeof(origin) - 2);
- if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_URI, origin))
- return NULL;
-
- *pwsi = lws_client_connect_2(wsi);
-
- return *pwsi;
-}
-
-#ifdef LWS_WITH_HTTP_PROXY
-hubbub_error
-html_parser_cb(const hubbub_token *token, void *pw)
-{
- struct lws_rewrite *r = (struct lws_rewrite *)pw;
- char buf[1024], *start = buf + LWS_PRE, *p = start,
- *end = &buf[sizeof(buf) - 1];
- size_t i;
-
- switch (token->type) {
- case HUBBUB_TOKEN_DOCTYPE:
-
- p += lws_snprintf(p, end - p, "<!DOCTYPE %.*s %s ",
- (int) token->data.doctype.name.len,
- token->data.doctype.name.ptr,
- token->data.doctype.force_quirks ?
- "(force-quirks) " : "");
-
- if (token->data.doctype.public_missing)
- lwsl_debug("\tpublic: missing\n");
- else
- p += lws_snprintf(p, end - p, "PUBLIC \"%.*s\"\n",
- (int) token->data.doctype.public_id.len,
- token->data.doctype.public_id.ptr);
-
- if (token->data.doctype.system_missing)
- lwsl_debug("\tsystem: missing\n");
- else
- p += lws_snprintf(p, end - p, " \"%.*s\">\n",
- (int) token->data.doctype.system_id.len,
- token->data.doctype.system_id.ptr);
-
- break;
- case HUBBUB_TOKEN_START_TAG:
- p += lws_snprintf(p, end - p, "<%.*s", (int)token->data.tag.name.len,
- token->data.tag.name.ptr);
-
-/* (token->data.tag.self_closing) ?
- "(self-closing) " : "",
- (token->data.tag.n_attributes > 0) ?
- "attributes:" : "");
-*/
- for (i = 0; i < token->data.tag.n_attributes; i++) {
- if (!hstrcmp(&token->data.tag.attributes[i].name, "href", 4) ||
- !hstrcmp(&token->data.tag.attributes[i].name, "action", 6) ||
- !hstrcmp(&token->data.tag.attributes[i].name, "src", 3)) {
- const char *pp = (const char *)token->data.tag.attributes[i].value.ptr;
- int plen = (int) token->data.tag.attributes[i].value.len;
-
- if (strncmp(pp, "http:", 5) && strncmp(pp, "https:", 6)) {
-
- if (!hstrcmp(&token->data.tag.attributes[i].value,
- r->from, r->from_len)) {
- pp += r->from_len;
- plen -= r->from_len;
- }
- p += lws_snprintf(p, end - p, " %.*s=\"%s/%.*s\"",
- (int) token->data.tag.attributes[i].name.len,
- token->data.tag.attributes[i].name.ptr,
- r->to, plen, pp);
- continue;
- }
- }
-
- p += lws_snprintf(p, end - p, " %.*s=\"%.*s\"",
- (int) token->data.tag.attributes[i].name.len,
- token->data.tag.attributes[i].name.ptr,
- (int) token->data.tag.attributes[i].value.len,
- token->data.tag.attributes[i].value.ptr);
- }
- p += lws_snprintf(p, end - p, ">");
- break;
- case HUBBUB_TOKEN_END_TAG:
- p += lws_snprintf(p, end - p, "</%.*s", (int) token->data.tag.name.len,
- token->data.tag.name.ptr);
-/*
- (token->data.tag.self_closing) ?
- "(self-closing) " : "",
- (token->data.tag.n_attributes > 0) ?
- "attributes:" : "");
-*/
- for (i = 0; i < token->data.tag.n_attributes; i++) {
- p += lws_snprintf(p, end - p, " %.*s='%.*s'\n",
- (int) token->data.tag.attributes[i].name.len,
- token->data.tag.attributes[i].name.ptr,
- (int) token->data.tag.attributes[i].value.len,
- token->data.tag.attributes[i].value.ptr);
- }
- p += lws_snprintf(p, end - p, ">");
- break;
- case HUBBUB_TOKEN_COMMENT:
- p += lws_snprintf(p, end - p, "<!-- %.*s -->\n",
- (int) token->data.comment.len,
- token->data.comment.ptr);
- break;
- case HUBBUB_TOKEN_CHARACTER:
- if (token->data.character.len == 1) {
- if (*token->data.character.ptr == '<') {
- p += lws_snprintf(p, end - p, "&lt;");
- break;
- }
- if (*token->data.character.ptr == '>') {
- p += lws_snprintf(p, end - p, "&gt;");
- break;
- }
- if (*token->data.character.ptr == '&') {
- p += lws_snprintf(p, end - p, "&amp;");
- break;
- }
- }
-
- p += lws_snprintf(p, end - p, "%.*s", (int) token->data.character.len,
- token->data.character.ptr);
- break;
- case HUBBUB_TOKEN_EOF:
- p += lws_snprintf(p, end - p, "\n");
- break;
- }
-
- if (user_callback_handle_rxflow(r->wsi->protocol->callback,
- r->wsi, LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ,
- r->wsi->user_space, start, p - start))
- return -1;
-
- return HUBBUB_OK;
-}
-#endif
-
-#endif
-
-char *
-lws_strdup(const char *s)
-{
- char *d = lws_malloc(strlen(s) + 1, "strdup");
-
- if (d)
- strcpy(d, s);
-
- return d;
-}
-
-void
-lws_client_stash_destroy(struct lws *wsi)
-{
- if (!wsi || !wsi->stash)
- return;
-
- lws_free_set_NULL(wsi->stash->address);
- lws_free_set_NULL(wsi->stash->path);
- lws_free_set_NULL(wsi->stash->host);
- lws_free_set_NULL(wsi->stash->origin);
- lws_free_set_NULL(wsi->stash->protocol);
- lws_free_set_NULL(wsi->stash->method);
- lws_free_set_NULL(wsi->stash->iface);
- lws_free_set_NULL(wsi->stash->alpn);
-
- lws_free_set_NULL(wsi->stash);
-}
-
-LWS_VISIBLE struct lws *
-lws_client_connect_via_info(struct lws_client_connect_info *i)
-{
- struct lws *wsi;
- const struct lws_protocols *p;
- const char *local = i->protocol;
-
- if (i->context->requested_kill)
- return NULL;
-
- if (!i->context->protocol_init_done)
- lws_protocol_init(i->context);
- /*
- * If we have .local_protocol_name, use it to select the
- * local protocol handler to bind to. Otherwise use .protocol if
- * http[s].
- */
- if (i->local_protocol_name)
- local = i->local_protocol_name;
-
- wsi = lws_zalloc(sizeof(struct lws), "client wsi");
- if (wsi == NULL)
- goto bail;
-
- wsi->context = i->context;
-#if defined(LWS_ROLE_H1)
- /* assert the mode and union status (hdr) clearly */
- lws_role_transition(wsi, LWSIFR_CLIENT, LRS_UNCONNECTED, &role_ops_h1);
-#else
- lws_role_transition(wsi, LWSIFR_CLIENT, LRS_UNCONNECTED, &role_ops_raw_skt);
-#endif
- wsi->desc.sockfd = LWS_SOCK_INVALID;
-
- /* 1) fill up the wsi with stuff from the connect_info as far as it
- * can go. It's because not only is our connection async, we might
- * not even be able to get ahold of an ah at this point.
- */
-
- if (!i->method) /* ie, ws */
-#if defined(LWS_ROLE_WS)
- if (lws_create_client_ws_object(i, wsi))
- return NULL;
-#else
- return NULL;
-#endif
-
- wsi->user_space = NULL;
- wsi->pending_timeout = NO_PENDING_TIMEOUT;
- wsi->position_in_fds_table = LWS_NO_FDS_POS;
- wsi->c_port = i->port;
- wsi->vhost = i->vhost;
- if (!wsi->vhost)
- wsi->vhost = i->context->vhost_list;
-
- if (!wsi->vhost) {
- lwsl_err("At least one vhost in the context is required\n");
-
- goto bail;
- }
-
- wsi->protocol = &wsi->vhost->protocols[0];
- wsi->client_pipeline = !!(i->ssl_connection & LCCSCF_PIPELINE);
-
- /* reasonable place to start */
- lws_role_transition(wsi, LWSIFR_CLIENT, LRS_UNCONNECTED,
-#if defined(LWS_ROLE_H1)
- &role_ops_h1);
-#else
- &role_ops_raw_skt);
-#endif
-
- /*
- * 1) for http[s] connection, allow protocol selection by name
- * 2) for ws[s], if local_protocol_name given also use it for
- * local protocol binding... this defeats the server
- * protocol negotiation if so
- *
- * Otherwise leave at protocols[0]... the server will tell us
- * which protocol we are associated with since we can give it a
- * list.
- */
- if (/*(i->method || i->local_protocol_name) && */local) {
- lwsl_info("binding to %s\n", local);
- p = lws_vhost_name_to_protocol(wsi->vhost, local);
- if (p)
- wsi->protocol = p;
- }
-
- if (wsi && !wsi->user_space && i->userdata) {
- wsi->user_space_externally_allocated = 1;
- wsi->user_space = i->userdata;
- } else
- /* if we stay in http, we can assign the user space now,
- * otherwise do it after the protocol negotiated
- */
- if (i->method)
- if (lws_ensure_user_space(wsi))
- goto bail;
-
-#if defined(LWS_WITH_TLS)
- wsi->tls.use_ssl = i->ssl_connection;
-#else
- if (i->ssl_connection & LCCSCF_USE_SSL) {
- lwsl_err("libwebsockets not configured for ssl\n");
- goto bail;
- }
-#endif
-
- /* 2) stash the things from connect_info that we can't process without
- * an ah. Because if no ah, we will go on the ah waiting list and
- * process those things later (after the connect_info and maybe the
- * things pointed to have gone out of scope.
- */
-
- wsi->stash = lws_zalloc(sizeof(*wsi->stash), "client stash");
- if (!wsi->stash) {
- lwsl_err("%s: OOM\n", __func__);
- goto bail1;
- }
-
- wsi->stash->address = lws_strdup(i->address);
- wsi->stash->path = lws_strdup(i->path);
- wsi->stash->host = lws_strdup(i->host);
-
- if (!wsi->stash->address || !wsi->stash->path || !wsi->stash->host)
- goto bail1;
-
- if (i->origin) {
- wsi->stash->origin = lws_strdup(i->origin);
- if (!wsi->stash->origin)
- goto bail1;
- }
- if (i->protocol) {
- wsi->stash->protocol = lws_strdup(i->protocol);
- if (!wsi->stash->protocol)
- goto bail1;
- }
- if (i->method) {
- wsi->stash->method = lws_strdup(i->method);
- if (!wsi->stash->method)
- goto bail1;
- }
- if (i->iface) {
- wsi->stash->iface = lws_strdup(i->iface);
- if (!wsi->stash->iface)
- goto bail1;
- }
- /*
- * For ws, default to http/1.1 only. If i->alpn is set, defer to
- * whatever he has set in there (eg, "h2").
- *
- * The problem is he has to commit to h2 before he can find out if the
- * server has the SETTINGS for ws-over-h2 enabled; if not then ws is
- * not possible on that connection. So we only try it if he
- * assertively said to use h2 alpn.
- */
- if (!i->method && !i->alpn) {
- wsi->stash->alpn = lws_strdup("http/1.1");
- if (!wsi->stash->alpn)
- goto bail1;
- } else
- if (i->alpn) {
- wsi->stash->alpn = lws_strdup(i->alpn);
- if (!wsi->stash->alpn)
- goto bail1;
- }
-
- if (i->pwsi)
- *i->pwsi = wsi;
-
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- /* if we went on the waiting list, no probs just return the wsi
- * when we get the ah, now or later, he will call
- * lws_client_connect_via_info2() below.
- */
- if (lws_header_table_attach(wsi, 0) < 0) {
- /*
- * if we failed here, the connection is already closed
- * and freed.
- */
- goto bail2;
- }
-
-#endif
-
- if (i->parent_wsi) {
- lwsl_info("%s: created child %p of parent %p\n", __func__,
- wsi, i->parent_wsi);
- wsi->parent = i->parent_wsi;
- wsi->sibling_list = i->parent_wsi->child_list;
- i->parent_wsi->child_list = wsi;
- }
-#ifdef LWS_WITH_HTTP_PROXY
- if (i->uri_replace_to)
- wsi->http.rw = lws_rewrite_create(wsi, html_parser_cb,
- i->uri_replace_from,
- i->uri_replace_to);
-#endif
-
- return wsi;
-
-bail1:
- lws_client_stash_destroy(wsi);
-
-bail:
- lws_free(wsi);
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
-bail2:
-#endif
- if (i->pwsi)
- *i->pwsi = NULL;
-
- return NULL;
-}
-
-struct lws *
-lws_client_connect_via_info2(struct lws *wsi)
-{
- struct client_info_stash *stash = wsi->stash;
-
- if (!stash)
- return wsi;
-
- /*
- * we're not necessarily in a position to action these right away,
- * stash them... we only need during connect phase so into a temp
- * allocated stash
- */
- if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS,
- stash->address))
- goto bail1;
-
- if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_URI, stash->path))
- goto bail1;
-
- if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_HOST, stash->host))
- goto bail1;
-
- if (stash->origin)
- if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_ORIGIN,
- stash->origin))
- goto bail1;
- /*
- * this is a list of protocols we tell the server we're okay with
- * stash it for later when we compare server response with it
- */
- if (stash->protocol)
- if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS,
- stash->protocol))
- goto bail1;
- if (stash->method)
- if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_METHOD,
- stash->method))
- goto bail1;
- if (stash->iface)
- if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_IFACE,
- stash->iface))
- goto bail1;
- if (stash->alpn)
- if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_ALPN,
- stash->alpn))
- goto bail1;
-
-#if defined(LWS_WITH_SOCKS5)
- if (!wsi->vhost->socks_proxy_port)
- lws_client_stash_destroy(wsi);
-#endif
-
- wsi->context->count_wsi_allocated++;
-
- return lws_client_connect_2(wsi);
-
-bail1:
-#if defined(LWS_WITH_SOCKS5)
- if (!wsi->vhost->socks_proxy_port)
- lws_free_set_NULL(wsi->stash);
-#endif
-
- return NULL;
-}
-
-LWS_VISIBLE struct lws *
-lws_client_connect_extended(struct lws_context *context, const char *address,
- int port, int ssl_connection, const char *path,
- const char *host, const char *origin,
- const char *protocol, int ietf_version_or_minus_one,
- void *userdata)
-{
- struct lws_client_connect_info i;
-
- memset(&i, 0, sizeof(i));
-
- i.context = context;
- i.address = address;
- i.port = port;
- i.ssl_connection = ssl_connection;
- i.path = path;
- i.host = host;
- i.origin = origin;
- i.protocol = protocol;
- i.ietf_version_or_minus_one = ietf_version_or_minus_one;
- i.userdata = userdata;
-
- return lws_client_connect_via_info(&i);
-}
-
-LWS_VISIBLE struct lws *
-lws_client_connect(struct lws_context *context, const char *address,
- int port, int ssl_connection, const char *path,
- const char *host, const char *origin,
- const char *protocol, int ietf_version_or_minus_one)
-{
- struct lws_client_connect_info i;
-
- memset(&i, 0, sizeof(i));
-
- i.context = context;
- i.address = address;
- i.port = port;
- i.ssl_connection = ssl_connection;
- i.path = path;
- i.host = host;
- i.origin = origin;
- i.protocol = protocol;
- i.ietf_version_or_minus_one = ietf_version_or_minus_one;
- i.userdata = NULL;
-
- return lws_client_connect_via_info(&i);
-}
-
-#if defined(LWS_WITH_SOCKS5)
-void socks_generate_msg(struct lws *wsi, enum socks_msg_type type,
- ssize_t *msg_len)
-{
- struct lws_context *context = wsi->context;
- struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
- ssize_t len = 0, n, passwd_len;
- short net_num;
- char *p;
-
- switch (type) {
- case SOCKS_MSG_GREETING:
- /* socks version, version 5 only */
- pt->serv_buf[len++] = SOCKS_VERSION_5;
- /* number of methods */
- pt->serv_buf[len++] = 2;
- /* username password method */
- pt->serv_buf[len++] = SOCKS_AUTH_USERNAME_PASSWORD;
- /* no authentication method */
- pt->serv_buf[len++] = SOCKS_AUTH_NO_AUTH;
- break;
-
- case SOCKS_MSG_USERNAME_PASSWORD:
- n = strlen(wsi->vhost->socks_user);
- passwd_len = strlen(wsi->vhost->socks_password);
-
- /* the subnegotiation version */
- pt->serv_buf[len++] = SOCKS_SUBNEGOTIATION_VERSION_1;
- /* length of the user name */
- pt->serv_buf[len++] = n;
- /* user name */
- lws_strncpy((char *)&pt->serv_buf[len], wsi->vhost->socks_user,
- context->pt_serv_buf_size - len + 1);
- len += n;
- /* length of the password */
- pt->serv_buf[len++] = passwd_len;
- /* password */
- lws_strncpy((char *)&pt->serv_buf[len], wsi->vhost->socks_password,
- context->pt_serv_buf_size - len + 1);
- len += passwd_len;
- break;
-
- case SOCKS_MSG_CONNECT:
- p = (char*)&net_num;
-
- /* socks version */
- pt->serv_buf[len++] = SOCKS_VERSION_5;
- /* socks command */
- pt->serv_buf[len++] = SOCKS_COMMAND_CONNECT;
- /* reserved */
- pt->serv_buf[len++] = 0;
- /* address type */
- pt->serv_buf[len++] = SOCKS_ATYP_DOMAINNAME;
- /* skip length, we fill it in at the end */
- n = len++;
-
- /* the address we tell SOCKS proxy to connect to */
- lws_strncpy((char *)&(pt->serv_buf[len]), wsi->stash->address,
- context->pt_serv_buf_size - len + 1);
- len += strlen(wsi->stash->address);
- net_num = htons(wsi->c_port);
-
- /* the port we tell SOCKS proxy to connect to */
- pt->serv_buf[len++] = p[0];
- pt->serv_buf[len++] = p[1];
-
- /* the length of the address, excluding port */
- pt->serv_buf[n] = strlen(wsi->stash->address);
- break;
-
- default:
- return;
- }
-
- *msg_len = len;
-}
-#endif
diff --git a/thirdparty/libwebsockets/roles/http/client/client.c b/thirdparty/libwebsockets/roles/http/client/client.c
deleted file mode 100644
index 5645fa2b7a..0000000000
--- a/thirdparty/libwebsockets/roles/http/client/client.c
+++ /dev/null
@@ -1,1243 +0,0 @@
-/*
- * libwebsockets - lib/client/client.c
- *
- * Copyright (C) 2010-2017 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- */
-
-#include "core/private.h"
-
-LWS_VISIBLE LWS_EXTERN void
-lws_client_http_body_pending(struct lws *wsi, int something_left_to_send)
-{
- wsi->client_http_body_pending = !!something_left_to_send;
-}
-
-/*
- * return self, or queued client wsi we are acting on behalf of
- *
- * That is the TAIL of the queue (new queue elements are added at the HEAD)
- */
-
-struct lws *
-lws_client_wsi_effective(struct lws *wsi)
-{
- struct lws_dll_lws *tail = NULL;
-
- if (!wsi->transaction_from_pipeline_queue ||
- !wsi->dll_client_transaction_queue_head.next)
- return wsi;
-
- lws_start_foreach_dll_safe(struct lws_dll_lws *, d, d1,
- wsi->dll_client_transaction_queue_head.next) {
- tail = d;
- } lws_end_foreach_dll_safe(d, d1);
-
- return lws_container_of(tail, struct lws,
- dll_client_transaction_queue);
-}
-
-/*
- * return self or the guy we are queued under
- *
- * REQUIRES VHOST LOCK HELD
- */
-
-static struct lws *
-_lws_client_wsi_master(struct lws *wsi)
-{
- struct lws *wsi_eff = wsi;
- struct lws_dll_lws *d;
-
- d = wsi->dll_client_transaction_queue.prev;
- while (d) {
- wsi_eff = lws_container_of(d, struct lws,
- dll_client_transaction_queue_head);
-
- d = d->prev;
- }
-
- return wsi_eff;
-}
-
-int
-lws_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd,
- struct lws *wsi_conn)
-{
- struct lws_context *context = wsi->context;
- struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
- char *p = (char *)&pt->serv_buf[0];
- struct lws *w;
-#if defined(LWS_WITH_TLS)
- char ebuf[128];
-#endif
- const char *cce = NULL;
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- ssize_t len = 0;
- unsigned char c;
-#endif
- char *sb = p;
- int n = 0;
-#if defined(LWS_WITH_SOCKS5)
- int conn_mode = 0, pending_timeout = 0;
-#endif
-
- if ((pollfd->revents & LWS_POLLOUT) &&
- wsi->keepalive_active &&
- wsi->dll_client_transaction_queue_head.next) {
- struct lws *wfound = NULL;
-
- lwsl_debug("%s: pollout HANDSHAKE2\n", __func__);
-
- /*
- * We have a transaction queued that wants to pipeline.
- *
- * We have to allow it to send headers strictly in the order
- * that it was queued, ie, tail-first.
- */
- lws_vhost_lock(wsi->vhost);
- lws_start_foreach_dll_safe(struct lws_dll_lws *, d, d1,
- wsi->dll_client_transaction_queue_head.next) {
- struct lws *w = lws_container_of(d, struct lws,
- dll_client_transaction_queue);
-
- lwsl_debug("%s: %p states 0x%x\n", __func__, w, w->wsistate);
- if (lwsi_state(w) == LRS_H1C_ISSUE_HANDSHAKE2)
- wfound = w;
- } lws_end_foreach_dll_safe(d, d1);
-
- if (wfound) {
- /*
- * pollfd has the master sockfd in it... we
- * need to use that in HANDSHAKE2 to understand
- * which wsi to actually write on
- */
- lws_client_socket_service(wfound, pollfd, wsi);
- lws_callback_on_writable(wsi);
- } else
- lwsl_debug("%s: didn't find anything in txn q in HS2\n",
- __func__);
-
- lws_vhost_unlock(wsi->vhost);
-
- return 0;
- }
-
- switch (lwsi_state(wsi)) {
-
- case LRS_WAITING_CONNECT:
-
- /*
- * we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE
- * timeout protection set in client-handshake.c
- */
-
- if (!lws_client_connect_2(wsi)) {
- /* closed */
- lwsl_client("closed\n");
- return -1;
- }
-
- /* either still pending connection, or changed mode */
- return 0;
-
-#if defined(LWS_WITH_SOCKS5)
- /* SOCKS Greeting Reply */
- case LRS_WAITING_SOCKS_GREETING_REPLY:
- case LRS_WAITING_SOCKS_AUTH_REPLY:
- case LRS_WAITING_SOCKS_CONNECT_REPLY:
-
- /* handle proxy hung up on us */
-
- if (pollfd->revents & LWS_POLLHUP) {
- lwsl_warn("SOCKS connection %p (fd=%d) dead\n",
- (void *)wsi, pollfd->fd);
- goto bail3;
- }
-
- n = recv(wsi->desc.sockfd, sb, context->pt_serv_buf_size, 0);
- if (n < 0) {
- if (LWS_ERRNO == LWS_EAGAIN) {
- lwsl_debug("SOCKS read EAGAIN, retrying\n");
- return 0;
- }
- lwsl_err("ERROR reading from SOCKS socket\n");
- goto bail3;
- }
-
- switch (lwsi_state(wsi)) {
-
- case LRS_WAITING_SOCKS_GREETING_REPLY:
- if (pt->serv_buf[0] != SOCKS_VERSION_5)
- goto socks_reply_fail;
-
- if (pt->serv_buf[1] == SOCKS_AUTH_NO_AUTH) {
- lwsl_client("SOCKS GR: No Auth Method\n");
- socks_generate_msg(wsi, SOCKS_MSG_CONNECT, &len);
- conn_mode = LRS_WAITING_SOCKS_CONNECT_REPLY;
- pending_timeout =
- PENDING_TIMEOUT_AWAITING_SOCKS_CONNECT_REPLY;
- goto socks_send;
- }
-
- if (pt->serv_buf[1] == SOCKS_AUTH_USERNAME_PASSWORD) {
- lwsl_client("SOCKS GR: User/Pw Method\n");
- socks_generate_msg(wsi,
- SOCKS_MSG_USERNAME_PASSWORD,
- &len);
- conn_mode = LRS_WAITING_SOCKS_AUTH_REPLY;
- pending_timeout =
- PENDING_TIMEOUT_AWAITING_SOCKS_AUTH_REPLY;
- goto socks_send;
- }
- goto socks_reply_fail;
-
- case LRS_WAITING_SOCKS_AUTH_REPLY:
- if (pt->serv_buf[0] != SOCKS_SUBNEGOTIATION_VERSION_1 ||
- pt->serv_buf[1] != SOCKS_SUBNEGOTIATION_STATUS_SUCCESS)
- goto socks_reply_fail;
-
- lwsl_client("SOCKS password OK, sending connect\n");
- socks_generate_msg(wsi, SOCKS_MSG_CONNECT, &len);
- conn_mode = LRS_WAITING_SOCKS_CONNECT_REPLY;
- pending_timeout =
- PENDING_TIMEOUT_AWAITING_SOCKS_CONNECT_REPLY;
-socks_send:
- n = send(wsi->desc.sockfd, (char *)pt->serv_buf, len,
- MSG_NOSIGNAL);
- if (n < 0) {
- lwsl_debug("ERROR writing to socks proxy\n");
- goto bail3;
- }
-
- lws_set_timeout(wsi, pending_timeout, AWAITING_TIMEOUT);
- lwsi_set_state(wsi, conn_mode);
- break;
-
-socks_reply_fail:
- lwsl_notice("socks reply: v%d, err %d\n",
- pt->serv_buf[0], pt->serv_buf[1]);
- goto bail3;
-
- case LRS_WAITING_SOCKS_CONNECT_REPLY:
- if (pt->serv_buf[0] != SOCKS_VERSION_5 ||
- pt->serv_buf[1] != SOCKS_REQUEST_REPLY_SUCCESS)
- goto socks_reply_fail;
-
- lwsl_client("socks connect OK\n");
-
- /* free stash since we are done with it */
- lws_client_stash_destroy(wsi);
- if (lws_hdr_simple_create(wsi,
- _WSI_TOKEN_CLIENT_PEER_ADDRESS,
- wsi->vhost->socks_proxy_address))
- goto bail3;
-
- wsi->c_port = wsi->vhost->socks_proxy_port;
-
- /* clear his proxy connection timeout */
- lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
- goto start_ws_handshake;
- default:
- break;
- }
- break;
-#endif
-
- case LRS_WAITING_PROXY_REPLY:
-
- /* handle proxy hung up on us */
-
- if (pollfd->revents & LWS_POLLHUP) {
-
- lwsl_warn("Proxy connection %p (fd=%d) dead\n",
- (void *)wsi, pollfd->fd);
-
- goto bail3;
- }
-
- n = recv(wsi->desc.sockfd, sb, context->pt_serv_buf_size, 0);
- if (n < 0) {
- if (LWS_ERRNO == LWS_EAGAIN) {
- lwsl_debug("Proxy read EAGAIN... retrying\n");
- return 0;
- }
- lwsl_err("ERROR reading from proxy socket\n");
- goto bail3;
- }
-
- pt->serv_buf[13] = '\0';
- if (strcmp(sb, "HTTP/1.0 200 ") &&
- strcmp(sb, "HTTP/1.1 200 ")) {
- lwsl_err("ERROR proxy: %s\n", sb);
- goto bail3;
- }
-
- /* clear his proxy connection timeout */
-
- lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
-
- /* fallthru */
-
- case LRS_H1C_ISSUE_HANDSHAKE:
-
- /*
- * we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE
- * timeout protection set in client-handshake.c
- *
- * take care of our lws_callback_on_writable
- * happening at a time when there's no real connection yet
- */
-#if defined(LWS_WITH_SOCKS5)
-start_ws_handshake:
-#endif
- if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
- return -1;
-
-#if defined(LWS_WITH_TLS)
- /* we can retry this... just cook the SSL BIO the first time */
-
- if ((wsi->tls.use_ssl & LCCSCF_USE_SSL) && !wsi->tls.ssl &&
- lws_ssl_client_bio_create(wsi) < 0) {
- cce = "bio_create failed";
- goto bail3;
- }
-
- if (wsi->tls.use_ssl & LCCSCF_USE_SSL) {
- n = lws_ssl_client_connect1(wsi);
- if (!n)
- return 0;
- if (n < 0) {
- cce = "lws_ssl_client_connect1 failed";
- goto bail3;
- }
- } else
- wsi->tls.ssl = NULL;
-
- /* fallthru */
-
- case LRS_WAITING_SSL:
-
- if (wsi->tls.use_ssl & LCCSCF_USE_SSL) {
- n = lws_ssl_client_connect2(wsi, ebuf, sizeof(ebuf));
- if (!n)
- return 0;
- if (n < 0) {
- cce = ebuf;
- goto bail3;
- }
- } else
- wsi->tls.ssl = NULL;
-#endif
-#if defined (LWS_WITH_HTTP2)
- if (wsi->client_h2_alpn) {
- /*
- * We connected to the server and set up tls, and
- * negotiated "h2".
- *
- * So this is it, we are an h2 master client connection
- * now, not an h1 client connection.
- */
- lws_tls_server_conn_alpn(wsi);
-
- /* send the H2 preface to legitimize the connection */
- if (lws_h2_issue_preface(wsi)) {
- cce = "error sending h2 preface";
- goto bail3;
- }
-
- break;
- }
-#endif
- lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE2);
- lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND,
- context->timeout_secs);
-
- /* fallthru */
-
- case LRS_H1C_ISSUE_HANDSHAKE2:
- p = lws_generate_client_handshake(wsi, p);
- if (p == NULL) {
- if (wsi->role_ops == &role_ops_raw_skt ||
- wsi->role_ops == &role_ops_raw_file)
- return 0;
-
- lwsl_err("Failed to generate handshake for client\n");
- lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "chs");
- return 0;
- }
-
- /* send our request to the server */
- lws_latency_pre(context, wsi);
-
- w = _lws_client_wsi_master(wsi);
- lwsl_info("%s: HANDSHAKE2: %p: sending headers on %p (wsistate 0x%x 0x%x)\n",
- __func__, wsi, w, wsi->wsistate, w->wsistate);
-
- n = lws_ssl_capable_write(w, (unsigned char *)sb, (int)(p - sb));
- lws_latency(context, wsi, "send lws_issue_raw", n,
- n == p - sb);
- switch (n) {
- case LWS_SSL_CAPABLE_ERROR:
- lwsl_debug("ERROR writing to client socket\n");
- lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "cws");
- return 0;
- case LWS_SSL_CAPABLE_MORE_SERVICE:
- lws_callback_on_writable(wsi);
- break;
- }
-
- if (wsi->client_http_body_pending) {
- lwsi_set_state(wsi, LRS_ISSUE_HTTP_BODY);
- lws_set_timeout(wsi,
- PENDING_TIMEOUT_CLIENT_ISSUE_PAYLOAD,
- context->timeout_secs);
- /* user code must ask for writable callback */
- break;
- }
-
- lwsi_set_state(wsi, LRS_WAITING_SERVER_REPLY);
- wsi->hdr_parsing_completed = 0;
-
- if (lwsi_state(w) == LRS_IDLING) {
- lwsi_set_state(w, LRS_WAITING_SERVER_REPLY);
- w->hdr_parsing_completed = 0;
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- w->http.ah->parser_state = WSI_TOKEN_NAME_PART;
- w->http.ah->lextable_pos = 0;
- /* If we're (re)starting on headers, need other implied init */
- wsi->http.ah->ues = URIES_IDLE;
-#endif
- }
-
- lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE,
- wsi->context->timeout_secs);
-
- lws_callback_on_writable(w);
-
- goto client_http_body_sent;
-
- case LRS_ISSUE_HTTP_BODY:
- if (wsi->client_http_body_pending) {
- //lws_set_timeout(wsi,
- // PENDING_TIMEOUT_CLIENT_ISSUE_PAYLOAD,
- // context->timeout_secs);
- /* user code must ask for writable callback */
- break;
- }
-client_http_body_sent:
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- /* prepare ourselves to do the parsing */
- wsi->http.ah->parser_state = WSI_TOKEN_NAME_PART;
- wsi->http.ah->lextable_pos = 0;
-#endif
- lwsi_set_state(wsi, LRS_WAITING_SERVER_REPLY);
- lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE,
- context->timeout_secs);
- break;
-
- case LRS_WAITING_SERVER_REPLY:
- /*
- * handle server hanging up on us...
- * but if there is POLLIN waiting, handle that first
- */
- if ((pollfd->revents & (LWS_POLLIN | LWS_POLLHUP)) ==
- LWS_POLLHUP) {
-
- lwsl_debug("Server connection %p (fd=%d) dead\n",
- (void *)wsi, pollfd->fd);
- cce = "Peer hung up";
- goto bail3;
- }
-
- if (!(pollfd->revents & LWS_POLLIN))
- break;
-
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- /* interpret the server response
- *
- * HTTP/1.1 101 Switching Protocols
- * Upgrade: websocket
- * Connection: Upgrade
- * Sec-WebSocket-Accept: me89jWimTRKTWwrS3aRrL53YZSo=
- * Sec-WebSocket-Nonce: AQIDBAUGBwgJCgsMDQ4PEC==
- * Sec-WebSocket-Protocol: chat
- *
- * we have to take some care here to only take from the
- * socket bytewise. The browser may (and has been seen to
- * in the case that onopen() performs websocket traffic)
- * coalesce both handshake response and websocket traffic
- * in one packet, since at that point the connection is
- * definitively ready from browser pov.
- */
- len = 1;
- while (wsi->http.ah->parser_state != WSI_PARSING_COMPLETE &&
- len > 0) {
- int plen = 1;
-
- n = lws_ssl_capable_read(wsi, &c, 1);
- lws_latency(context, wsi, "send lws_issue_raw", n,
- n == 1);
- switch (n) {
- case 0:
- case LWS_SSL_CAPABLE_ERROR:
- cce = "read failed";
- goto bail3;
- case LWS_SSL_CAPABLE_MORE_SERVICE:
- return 0;
- }
-
- if (lws_parse(wsi, &c, &plen)) {
- lwsl_warn("problems parsing header\n");
- goto bail3;
- }
- }
-
- /*
- * hs may also be coming in multiple packets, there is a 5-sec
- * libwebsocket timeout still active here too, so if parsing did
- * not complete just wait for next packet coming in this state
- */
- if (wsi->http.ah->parser_state != WSI_PARSING_COMPLETE)
- break;
-
-#endif
-
- /*
- * otherwise deal with the handshake. If there's any
- * packet traffic already arrived we'll trigger poll() again
- * right away and deal with it that way
- */
- return lws_client_interpret_server_handshake(wsi);
-
-bail3:
- lwsl_info("closing conn at LWS_CONNMODE...SERVER_REPLY\n");
- if (cce)
- lwsl_info("reason: %s\n", cce);
- wsi->protocol->callback(wsi,
- LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
- wsi->user_space, (void *)cce, cce ? strlen(cce) : 0);
- wsi->already_did_cce = 1;
- lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "cbail3");
- return -1;
-
- default:
- break;
- }
-
- return 0;
-}
-
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
-
-int LWS_WARN_UNUSED_RESULT
-lws_http_transaction_completed_client(struct lws *wsi)
-{
- struct lws *wsi_eff = lws_client_wsi_effective(wsi);
-
- lwsl_info("%s: wsi: %p, wsi_eff: %p\n", __func__, wsi, wsi_eff);
-
- if (user_callback_handle_rxflow(wsi_eff->protocol->callback,
- wsi_eff, LWS_CALLBACK_COMPLETED_CLIENT_HTTP,
- wsi_eff->user_space, NULL, 0)) {
- lwsl_debug("%s: Completed call returned nonzero (role 0x%x)\n",
- __func__, lwsi_role(wsi_eff));
- return -1;
- }
-
- /*
- * Are we constitutionally capable of having a queue, ie, we are on
- * the "active client connections" list?
- *
- * If not, that's it for us.
- */
-
- if (lws_dll_is_null(&wsi->dll_active_client_conns))
- return -1;
-
- /* if this was a queued guy, close him and remove from queue */
-
- if (wsi->transaction_from_pipeline_queue) {
- lwsl_debug("closing queued wsi %p\n", wsi_eff);
- /* so the close doesn't trigger a CCE */
- wsi_eff->already_did_cce = 1;
- __lws_close_free_wsi(wsi_eff,
- LWS_CLOSE_STATUS_CLIENT_TRANSACTION_DONE,
- "queued client done");
- }
-
- _lws_header_table_reset(wsi->http.ah);
-
- /* after the first one, they can only be coming from the queue */
- wsi->transaction_from_pipeline_queue = 1;
-
- wsi->http.rx_content_length = 0;
- wsi->hdr_parsing_completed = 0;
-
- /* is there a new tail after removing that one? */
- wsi_eff = lws_client_wsi_effective(wsi);
-
- /*
- * Do we have something pipelined waiting?
- * it's OK if he hasn't managed to send his headers yet... he's next
- * in line to do that...
- */
- if (wsi_eff == wsi) {
- /*
- * Nothing pipelined... we should hang around a bit
- * in case something turns up...
- */
- lwsl_info("%s: nothing pipelined waiting\n", __func__);
- lwsi_set_state(wsi, LRS_IDLING);
-
- lws_set_timeout(wsi, PENDING_TIMEOUT_CLIENT_CONN_IDLE, 5);
-
- return 0;
- }
-
- /*
- * H1: we can serialize the queued guys into the same ah
- * H2: everybody needs their own ah until their own STREAM_END
- */
-
- /* otherwise set ourselves up ready to go again */
- lwsi_set_state(wsi, LRS_WAITING_SERVER_REPLY);
-
- wsi->http.ah->parser_state = WSI_TOKEN_NAME_PART;
- wsi->http.ah->lextable_pos = 0;
-
- lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE,
- wsi->context->timeout_secs);
-
- /* If we're (re)starting on headers, need other implied init */
- wsi->http.ah->ues = URIES_IDLE;
-
- lwsl_info("%s: %p: new queued transaction as %p\n", __func__, wsi, wsi_eff);
- lws_callback_on_writable(wsi);
-
- return 0;
-}
-
-LWS_VISIBLE LWS_EXTERN unsigned int
-lws_http_client_http_response(struct lws *_wsi)
-{
- struct lws *wsi;
- unsigned int resp;
-
- if (_wsi->http.ah && _wsi->http.ah->http_response)
- return _wsi->http.ah->http_response;
-
- lws_vhost_lock(_wsi->vhost);
- wsi = _lws_client_wsi_master(_wsi);
- resp = wsi->http.ah->http_response;
- lws_vhost_unlock(_wsi->vhost);
-
- return resp;
-}
-#endif
-#if defined(LWS_PLAT_OPTEE)
-char *
-strrchr(const char *s, int c)
-{
- char *hit = NULL;
-
- while (*s)
- if (*(s++) == (char)c)
- hit = (char *)s - 1;
-
- return hit;
-}
-
-#define atoll atoi
-#endif
-
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
-int
-lws_client_interpret_server_handshake(struct lws *wsi)
-{
- int n, port = 0, ssl = 0;
- int close_reason = LWS_CLOSE_STATUS_PROTOCOL_ERR;
- const char *prot, *ads = NULL, *path, *cce = NULL;
- struct allocated_headers *ah = NULL;
- struct lws *w = lws_client_wsi_effective(wsi);
- char *p, *q;
- char new_path[300];
-
- lws_client_stash_destroy(wsi);
-
- ah = wsi->http.ah;
- if (!wsi->do_ws) {
- /* we are being an http client...
- */
-#if defined(LWS_ROLE_H2)
- if (wsi->client_h2_alpn || wsi->client_h2_substream) {
- lwsl_debug("%s: %p: transitioning to h2 client\n", __func__, wsi);
- lws_role_transition(wsi, LWSIFR_CLIENT,
- LRS_ESTABLISHED, &role_ops_h2);
- } else
-#endif
- {
-#if defined(LWS_ROLE_H1)
- {
- lwsl_debug("%s: %p: transitioning to h1 client\n", __func__, wsi);
- lws_role_transition(wsi, LWSIFR_CLIENT,
- LRS_ESTABLISHED, &role_ops_h1);
- }
-#else
- return -1;
-#endif
- }
-
- wsi->http.ah = ah;
- ah->http_response = 0;
- }
-
- /*
- * well, what the server sent looked reasonable for syntax.
- * Now let's confirm it sent all the necessary headers
- *
- * http (non-ws) client will expect something like this
- *
- * HTTP/1.0.200
- * server:.libwebsockets
- * content-type:.text/html
- * content-length:.17703
- * set-cookie:.test=LWS_1456736240_336776_COOKIE;Max-Age=360000
- */
-
- wsi->http.connection_type = HTTP_CONNECTION_KEEP_ALIVE;
- if (!wsi->client_h2_substream) {
- p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP);
- if (wsi->do_ws && !p) {
- lwsl_info("no URI\n");
- cce = "HS: URI missing";
- goto bail3;
- }
- if (!p) {
- p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP1_0);
- wsi->http.connection_type = HTTP_CONNECTION_CLOSE;
- }
- if (!p) {
- cce = "HS: URI missing";
- lwsl_info("no URI\n");
- goto bail3;
- }
- } else {
- p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_STATUS);
- if (!p) {
- cce = "HS: :status missing";
- lwsl_info("no status\n");
- goto bail3;
- }
- }
- n = atoi(p);
- if (ah)
- ah->http_response = n;
-
- if (n == 301 || n == 302 || n == 303 || n == 307 || n == 308) {
- p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_LOCATION);
- if (!p) {
- cce = "HS: Redirect code but no Location";
- goto bail3;
- }
-
- /* Relative reference absolute path */
- if (p[0] == '/') {
-#if defined(LWS_WITH_TLS)
- ssl = wsi->tls.use_ssl & LCCSCF_USE_SSL;
-#endif
- ads = lws_hdr_simple_ptr(wsi,
- _WSI_TOKEN_CLIENT_PEER_ADDRESS);
- port = wsi->c_port;
- /* +1 as lws_client_reset expects leading / omitted */
- path = p + 1;
- }
- /* Absolute (Full) URI */
- else if (strchr(p, ':')) {
- if (lws_parse_uri(p, &prot, &ads, &port, &path)) {
- cce = "HS: URI did not parse";
- goto bail3;
- }
-
- if (!strcmp(prot, "wss") || !strcmp(prot, "https"))
- ssl = 1;
- }
- /* Relative reference relative path */
- else {
- /* This doesn't try to calculate an absolute path,
- * that will be left to the server */
-#if defined(LWS_WITH_TLS)
- ssl = wsi->tls.use_ssl & LCCSCF_USE_SSL;
-#endif
- ads = lws_hdr_simple_ptr(wsi,
- _WSI_TOKEN_CLIENT_PEER_ADDRESS);
- port = wsi->c_port;
- /* +1 as lws_client_reset expects leading / omitted */
- path = new_path + 1;
- lws_strncpy(new_path, lws_hdr_simple_ptr(wsi,
- _WSI_TOKEN_CLIENT_URI), sizeof(new_path));
- q = strrchr(new_path, '/');
- if (q)
- lws_strncpy(q + 1, p, sizeof(new_path) -
- (q - new_path) - 1);
- else
- path = p;
- }
-
-#if defined(LWS_WITH_TLS)
- if ((wsi->tls.use_ssl & LCCSCF_USE_SSL) && !ssl) {
- cce = "HS: Redirect attempted SSL downgrade";
- goto bail3;
- }
-#endif
-
- if (!lws_client_reset(&wsi, ssl, ads, port, path, ads)) {
- /* there are two ways to fail out with NULL return...
- * simple, early problem where the wsi is intact, or
- * we went through with the reconnect attempt and the
- * wsi is already closed. In the latter case, the wsi
- * has beet set to NULL additionally.
- */
- lwsl_err("Redirect failed\n");
- cce = "HS: Redirect failed";
- if (wsi)
- goto bail3;
-
- return 1;
- }
- return 0;
- }
-
- if (!wsi->do_ws) {
-
- /* if h1 KA is allowed, enable the queued pipeline guys */
-
- if (!wsi->client_h2_alpn && !wsi->client_h2_substream && w == wsi) { /* ie, coming to this for the first time */
- if (wsi->http.connection_type == HTTP_CONNECTION_KEEP_ALIVE)
- wsi->keepalive_active = 1;
- else {
- /*
- * Ugh... now the main http connection has seen
- * both sides, we learn the server doesn't
- * support keepalive.
- *
- * That means any guys queued on us are going
- * to have to be restarted from connect2 with
- * their own connections.
- */
-
- /*
- * stick around telling any new guys they can't
- * pipeline to this server
- */
- wsi->keepalive_rejected = 1;
-
- lws_vhost_lock(wsi->vhost);
- lws_start_foreach_dll_safe(struct lws_dll_lws *, d, d1,
- wsi->dll_client_transaction_queue_head.next) {
- struct lws *ww = lws_container_of(d, struct lws,
- dll_client_transaction_queue);
-
- /* remove him from our queue */
- lws_dll_lws_remove(&ww->dll_client_transaction_queue);
- /* give up on pipelining */
- ww->client_pipeline = 0;
-
- /* go back to "trying to connect" state */
- lws_role_transition(ww, LWSIFR_CLIENT,
- LRS_UNCONNECTED,
-#if defined(LWS_ROLE_H1)
- &role_ops_h1);
-#else
-#if defined (LWS_ROLE_H2)
- &role_ops_h2);
-#else
- &role_ops_raw);
-#endif
-#endif
- ww->user_space = NULL;
- } lws_end_foreach_dll_safe(d, d1);
- lws_vhost_unlock(wsi->vhost);
- }
- }
-
-#ifdef LWS_WITH_HTTP_PROXY
- wsi->http.perform_rewrite = 0;
- if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE)) {
- if (!strncmp(lws_hdr_simple_ptr(wsi,
- WSI_TOKEN_HTTP_CONTENT_TYPE),
- "text/html", 9))
- wsi->http.perform_rewrite = 1;
- }
-#endif
-
- /* allocate the per-connection user memory (if any) */
- if (lws_ensure_user_space(wsi)) {
- lwsl_err("Problem allocating wsi user mem\n");
- cce = "HS: OOM";
- goto bail2;
- }
-
- /* he may choose to send us stuff in chunked transfer-coding */
- wsi->chunked = 0;
- wsi->chunk_remaining = 0; /* ie, next thing is chunk size */
- if (lws_hdr_total_length(wsi,
- WSI_TOKEN_HTTP_TRANSFER_ENCODING)) {
- wsi->chunked = !strcmp(lws_hdr_simple_ptr(wsi,
- WSI_TOKEN_HTTP_TRANSFER_ENCODING),
- "chunked");
- /* first thing is hex, after payload there is crlf */
- wsi->chunk_parser = ELCP_HEX;
- }
-
- if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH)) {
- wsi->http.rx_content_length =
- atoll(lws_hdr_simple_ptr(wsi,
- WSI_TOKEN_HTTP_CONTENT_LENGTH));
- lwsl_info("%s: incoming content length %llu\n",
- __func__, (unsigned long long)
- wsi->http.rx_content_length);
- wsi->http.rx_content_remain =
- wsi->http.rx_content_length;
- } else /* can't do 1.1 without a content length or chunked */
- if (!wsi->chunked)
- wsi->http.connection_type =
- HTTP_CONNECTION_CLOSE;
-
- /*
- * we seem to be good to go, give client last chance to check
- * headers and OK it
- */
- if (w->protocol->callback(w,
- LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH,
- w->user_space, NULL, 0)) {
-
- cce = "HS: disallowed by client filter";
- goto bail2;
- }
-
- /* clear his proxy connection timeout */
- lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
-
- wsi->rxflow_change_to = LWS_RXFLOW_ALLOW;
-
- /* call him back to inform him he is up */
- if (w->protocol->callback(w,
- LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP,
- w->user_space, NULL, 0)) {
- cce = "HS: disallowed at ESTABLISHED";
- goto bail3;
- }
-
- /*
- * for pipelining, master needs to keep his ah... guys who
- * queued on him can drop it now though.
- */
-
- if (w != wsi)
- /* free up parsing allocations for queued guy */
- lws_header_table_detach(w, 0);
-
- lwsl_info("%s: client connection up\n", __func__);
-
- return 0;
- }
-
-#if defined(LWS_ROLE_WS)
- switch (lws_client_ws_upgrade(wsi, &cce)) {
- case 2:
- goto bail2;
- case 3:
- goto bail3;
- }
-
- return 0;
-#endif
-
-bail3:
- close_reason = LWS_CLOSE_STATUS_NOSTATUS;
-
-bail2:
- if (wsi->protocol) {
- n = 0;
- if (cce)
- n = (int)strlen(cce);
- w->protocol->callback(w,
- LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
- w->user_space, (void *)cce,
- (unsigned int)n);
- }
- wsi->already_did_cce = 1;
-
- lwsl_info("closing connection due to bail2 connection error\n");
-
- /* closing will free up his parsing allocations */
- lws_close_free_wsi(wsi, close_reason, "c hs interp");
-
- return 1;
-}
-#endif
-
-char *
-lws_generate_client_handshake(struct lws *wsi, char *pkt)
-{
- char *p = pkt;
- const char *meth;
- const char *pp = lws_hdr_simple_ptr(wsi,
- _WSI_TOKEN_CLIENT_SENT_PROTOCOLS);
-
- meth = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_METHOD);
- if (!meth) {
- meth = "GET";
- wsi->do_ws = 1;
- } else {
- wsi->do_ws = 0;
- }
-
- if (!strcmp(meth, "RAW")) {
- lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
- lwsl_notice("client transition to raw\n");
-
- if (pp) {
- const struct lws_protocols *pr;
-
- pr = lws_vhost_name_to_protocol(wsi->vhost, pp);
-
- if (!pr) {
- lwsl_err("protocol %s not enabled on vhost\n",
- pp);
- return NULL;
- }
-
- lws_bind_protocol(wsi, pr);
- }
-
- if ((wsi->protocol->callback)(wsi, LWS_CALLBACK_RAW_ADOPT,
- wsi->user_space, NULL, 0))
- return NULL;
-
- lws_role_transition(wsi, 0, LRS_ESTABLISHED, &role_ops_raw_skt);
- lws_header_table_detach(wsi, 1);
-
- return NULL;
- }
-
- /*
- * 04 example client handshake
- *
- * GET /chat HTTP/1.1
- * Host: server.example.com
- * Upgrade: websocket
- * Connection: Upgrade
- * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
- * Sec-WebSocket-Origin: http://example.com
- * Sec-WebSocket-Protocol: chat, superchat
- * Sec-WebSocket-Version: 4
- */
-
- p += sprintf(p, "%s %s HTTP/1.1\x0d\x0a", meth,
- lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_URI));
-
- p += sprintf(p, "Pragma: no-cache\x0d\x0a"
- "Cache-Control: no-cache\x0d\x0a");
-
- p += sprintf(p, "Host: %s\x0d\x0a",
- lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_HOST));
-
- if (lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN)) {
- if (lws_check_opt(wsi->context->options,
- LWS_SERVER_OPTION_JUST_USE_RAW_ORIGIN))
- p += sprintf(p, "Origin: %s\x0d\x0a",
- lws_hdr_simple_ptr(wsi,
- _WSI_TOKEN_CLIENT_ORIGIN));
- else
- p += sprintf(p, "Origin: http://%s\x0d\x0a",
- lws_hdr_simple_ptr(wsi,
- _WSI_TOKEN_CLIENT_ORIGIN));
- }
-#if defined(LWS_ROLE_WS)
- if (wsi->do_ws)
- p = lws_generate_client_ws_handshake(wsi, p);
-#endif
-
- /* give userland a chance to append, eg, cookies */
-
- if (wsi->protocol->callback(wsi,
- LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER,
- wsi->user_space, &p,
- (pkt + wsi->context->pt_serv_buf_size) - p - 12))
- return NULL;
-
- p += sprintf(p, "\x0d\x0a");
-
- return p;
-}
-
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
-
-LWS_VISIBLE int
-lws_http_client_read(struct lws *wsi, char **buf, int *len)
-{
- int rlen, n;
-
- rlen = lws_ssl_capable_read(wsi, (unsigned char *)*buf, *len);
- *len = 0;
-
- // lwsl_notice("%s: rlen %d\n", __func__, rlen);
-
- /* allow the source to signal he has data again next time */
- lws_change_pollfd(wsi, 0, LWS_POLLIN);
-
- if (rlen == LWS_SSL_CAPABLE_ERROR) {
- lwsl_notice("%s: SSL capable error\n", __func__);
- return -1;
- }
-
- if (rlen == 0)
- return -1;
-
- if (rlen < 0)
- return 0;
-
- *len = rlen;
- wsi->client_rx_avail = 0;
-
- /*
- * server may insist on transfer-encoding: chunked,
- * so http client must deal with it
- */
-spin_chunks:
- while (wsi->chunked && (wsi->chunk_parser != ELCP_CONTENT) && *len) {
- switch (wsi->chunk_parser) {
- case ELCP_HEX:
- if ((*buf)[0] == '\x0d') {
- wsi->chunk_parser = ELCP_CR;
- break;
- }
- n = char_to_hex((*buf)[0]);
- if (n < 0) {
- lwsl_debug("chunking failure\n");
- return -1;
- }
- wsi->chunk_remaining <<= 4;
- wsi->chunk_remaining |= n;
- break;
- case ELCP_CR:
- if ((*buf)[0] != '\x0a') {
- lwsl_debug("chunking failure\n");
- return -1;
- }
- wsi->chunk_parser = ELCP_CONTENT;
- lwsl_info("chunk %d\n", wsi->chunk_remaining);
- if (wsi->chunk_remaining)
- break;
- lwsl_info("final chunk\n");
- goto completed;
-
- case ELCP_CONTENT:
- break;
-
- case ELCP_POST_CR:
- if ((*buf)[0] != '\x0d') {
- lwsl_debug("chunking failure\n");
-
- return -1;
- }
-
- wsi->chunk_parser = ELCP_POST_LF;
- break;
-
- case ELCP_POST_LF:
- if ((*buf)[0] != '\x0a')
- return -1;
-
- wsi->chunk_parser = ELCP_HEX;
- wsi->chunk_remaining = 0;
- break;
- }
- (*buf)++;
- (*len)--;
- }
-
- if (wsi->chunked && !wsi->chunk_remaining)
- return 0;
-
- if (wsi->http.rx_content_remain &&
- wsi->http.rx_content_remain < (unsigned int)*len)
- n = (int)wsi->http.rx_content_remain;
- else
- n = *len;
-
- if (wsi->chunked && wsi->chunk_remaining &&
- wsi->chunk_remaining < n)
- n = wsi->chunk_remaining;
-
-#ifdef LWS_WITH_HTTP_PROXY
- /* hubbub */
- if (wsi->http.perform_rewrite)
- lws_rewrite_parse(wsi->http.rw, (unsigned char *)*buf, n);
- else
-#endif
- {
- struct lws *wsi_eff = lws_client_wsi_effective(wsi);
-
- if (user_callback_handle_rxflow(wsi_eff->protocol->callback,
- wsi_eff, LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ,
- wsi_eff->user_space, *buf, n)) {
- lwsl_debug("%s: RECEIVE_CLIENT_HTTP_READ returned -1\n",
- __func__);
-
- return -1;
- }
- }
-
- if (wsi->chunked && wsi->chunk_remaining) {
- (*buf) += n;
- wsi->chunk_remaining -= n;
- *len -= n;
- }
-
- if (wsi->chunked && !wsi->chunk_remaining)
- wsi->chunk_parser = ELCP_POST_CR;
-
- if (wsi->chunked && *len)
- goto spin_chunks;
-
- if (wsi->chunked)
- return 0;
-
- /* if we know the content length, decrement the content remaining */
- if (wsi->http.rx_content_length > 0)
- wsi->http.rx_content_remain -= n;
-
- // lwsl_notice("rx_content_remain %lld, rx_content_length %lld\n",
- // wsi->http.rx_content_remain, wsi->http.rx_content_length);
-
- if (wsi->http.rx_content_remain || !wsi->http.rx_content_length)
- return 0;
-
-completed:
-
- if (lws_http_transaction_completed_client(wsi)) {
- lwsl_notice("%s: transaction completed says -1\n", __func__);
- return -1;
- }
-
- return 0;
-}
-
-#endif
diff --git a/thirdparty/libwebsockets/roles/http/header.c b/thirdparty/libwebsockets/roles/http/header.c
deleted file mode 100644
index dbcf27cbd1..0000000000
--- a/thirdparty/libwebsockets/roles/http/header.c
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010-2017 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- */
-
-#include "core/private.h"
-#include "lextable-strings.h"
-
-
-const unsigned char *
-lws_token_to_string(enum lws_token_indexes token)
-{
- if ((unsigned int)token >= LWS_ARRAY_SIZE(set))
- return NULL;
-
- return (unsigned char *)set[token];
-}
-
-int
-lws_add_http_header_by_name(struct lws *wsi, const unsigned char *name,
- const unsigned char *value, int length,
- unsigned char **p, unsigned char *end)
-{
-#ifdef LWS_WITH_HTTP2
- if (lwsi_role_h2(wsi) || lwsi_role_h2_ENCAPSULATION(wsi))
- return lws_add_http2_header_by_name(wsi, name,
- value, length, p, end);
-#else
- (void)wsi;
-#endif
- if (name) {
- while (*p < end && *name)
- *((*p)++) = *name++;
- if (*p == end)
- return 1;
- *((*p)++) = ' ';
- }
- if (*p + length + 3 >= end)
- return 1;
-
- memcpy(*p, value, length);
- *p += length;
- *((*p)++) = '\x0d';
- *((*p)++) = '\x0a';
-
- return 0;
-}
-
-int lws_finalize_http_header(struct lws *wsi, unsigned char **p,
- unsigned char *end)
-{
-#ifdef LWS_WITH_HTTP2
- if (lwsi_role_h2(wsi) || lwsi_role_h2_ENCAPSULATION(wsi))
- return 0;
-#else
- (void)wsi;
-#endif
- if ((lws_intptr_t)(end - *p) < 3)
- return 1;
- *((*p)++) = '\x0d';
- *((*p)++) = '\x0a';
-
- return 0;
-}
-
-int
-lws_finalize_write_http_header(struct lws *wsi, unsigned char *start,
- unsigned char **pp, unsigned char *end)
-{
- unsigned char *p;
- int len;
-
- if (lws_finalize_http_header(wsi, pp, end))
- return 1;
-
- p = *pp;
- len = lws_ptr_diff(p, start);
-
- if (lws_write(wsi, start, len, LWS_WRITE_HTTP_HEADERS) != len)
- return 1;
-
- return 0;
-}
-
-int
-lws_add_http_header_by_token(struct lws *wsi, enum lws_token_indexes token,
- const unsigned char *value, int length,
- unsigned char **p, unsigned char *end)
-{
- const unsigned char *name;
-#ifdef LWS_WITH_HTTP2
- if (lwsi_role_h2(wsi) || lwsi_role_h2_ENCAPSULATION(wsi))
- return lws_add_http2_header_by_token(wsi, token, value,
- length, p, end);
-#endif
- name = lws_token_to_string(token);
- if (!name)
- return 1;
-
- return lws_add_http_header_by_name(wsi, name, value, length, p, end);
-}
-
-int lws_add_http_header_content_length(struct lws *wsi,
- lws_filepos_t content_length,
- unsigned char **p, unsigned char *end)
-{
- char b[24];
- int n;
-
- n = sprintf(b, "%llu", (unsigned long long)content_length);
- if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH,
- (unsigned char *)b, n, p, end))
- return 1;
- wsi->http.tx_content_length = content_length;
- wsi->http.tx_content_remain = content_length;
-
- lwsl_info("%s: wsi %p: tx_content_length/remain %llu\n", __func__,
- wsi, (unsigned long long)content_length);
-
- return 0;
-}
-
-int
-lws_add_http_common_headers(struct lws *wsi, unsigned int code,
- const char *content_type, lws_filepos_t content_len,
- unsigned char **p, unsigned char *end)
-{
- if (lws_add_http_header_status(wsi, code, p, end))
- return 1;
-
- if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,
- (unsigned char *)content_type,
- (int)strlen(content_type), p, end))
- return 1;
-
- if (content_len != LWS_ILLEGAL_HTTP_CONTENT_LEN) {
- if (lws_add_http_header_content_length(wsi, content_len, p, end))
- return 1;
- } else {
- if (lws_add_http_header_by_token(wsi, WSI_TOKEN_CONNECTION,
- (unsigned char *)"close", 5,
- p, end))
- return 1;
-
- wsi->http.connection_type = HTTP_CONNECTION_CLOSE;
- }
-
- return 0;
-}
-
-STORE_IN_ROM static const char * const err400[] = {
- "Bad Request",
- "Unauthorized",
- "Payment Required",
- "Forbidden",
- "Not Found",
- "Method Not Allowed",
- "Not Acceptable",
- "Proxy Auth Required",
- "Request Timeout",
- "Conflict",
- "Gone",
- "Length Required",
- "Precondition Failed",
- "Request Entity Too Large",
- "Request URI too Long",
- "Unsupported Media Type",
- "Requested Range Not Satisfiable",
- "Expectation Failed"
-};
-
-STORE_IN_ROM static const char * const err500[] = {
- "Internal Server Error",
- "Not Implemented",
- "Bad Gateway",
- "Service Unavailable",
- "Gateway Timeout",
- "HTTP Version Not Supported"
-};
-
-int
-lws_add_http_header_status(struct lws *wsi, unsigned int _code,
- unsigned char **p, unsigned char *end)
-{
- STORE_IN_ROM static const char * const hver[] = {
- "HTTP/1.0", "HTTP/1.1", "HTTP/2"
- };
- const struct lws_protocol_vhost_options *headers;
- unsigned int code = _code & LWSAHH_CODE_MASK;
- const char *description = "", *p1;
- unsigned char code_and_desc[60];
- int n;
-
-#ifdef LWS_WITH_ACCESS_LOG
- wsi->http.access_log.response = code;
-#endif
-
-#ifdef LWS_WITH_HTTP2
- if (lwsi_role_h2(wsi) || lwsi_role_h2_ENCAPSULATION(wsi)) {
- n = lws_add_http2_header_status(wsi, code, p, end);
- if (n)
- return n;
- } else
-#endif
- {
- if (code >= 400 && code < (400 + LWS_ARRAY_SIZE(err400)))
- description = err400[code - 400];
- if (code >= 500 && code < (500 + LWS_ARRAY_SIZE(err500)))
- description = err500[code - 500];
-
- if (code == 100)
- description = "Continue";
- if (code == 200)
- description = "OK";
- if (code == 304)
- description = "Not Modified";
- else
- if (code >= 300 && code < 400)
- description = "Redirect";
-
- if (wsi->http.request_version < LWS_ARRAY_SIZE(hver))
- p1 = hver[wsi->http.request_version];
- else
- p1 = hver[0];
-
- n = sprintf((char *)code_and_desc, "%s %u %s", p1, code,
- description);
-
- if (lws_add_http_header_by_name(wsi, NULL, code_and_desc, n, p,
- end))
- return 1;
- }
- headers = wsi->vhost->headers;
- while (headers) {
- if (lws_add_http_header_by_name(wsi,
- (const unsigned char *)headers->name,
- (unsigned char *)headers->value,
- (int)strlen(headers->value), p, end))
- return 1;
-
- headers = headers->next;
- }
-
- if (wsi->context->server_string &&
- !(_code & LWSAHH_FLAG_NO_SERVER_NAME))
- if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_SERVER,
- (unsigned char *)wsi->context->server_string,
- wsi->context->server_string_len, p, end))
- return 1;
-
- if (wsi->vhost->options & LWS_SERVER_OPTION_STS)
- if (lws_add_http_header_by_name(wsi, (unsigned char *)
- "Strict-Transport-Security:",
- (unsigned char *)"max-age=15768000 ; "
- "includeSubDomains", 36, p, end))
- return 1;
-
- return 0;
-}
-
-LWS_VISIBLE int
-lws_return_http_status(struct lws *wsi, unsigned int code,
- const char *html_body)
-{
- struct lws_context *context = lws_get_context(wsi);
- struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
- unsigned char *p = pt->serv_buf + LWS_PRE;
- unsigned char *start = p;
- unsigned char *end = p + context->pt_serv_buf_size - LWS_PRE;
- int n = 0, m = 0, len;
- char slen[20];
-
- if (!wsi->vhost) {
- lwsl_err("%s: wsi not bound to vhost\n", __func__);
-
- return 1;
- }
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- if (!wsi->handling_404 &&
- wsi->vhost->http.error_document_404 &&
- code == HTTP_STATUS_NOT_FOUND)
- /* we should do a redirect, and do the 404 there */
- if (lws_http_redirect(wsi, HTTP_STATUS_FOUND,
- (uint8_t *)wsi->vhost->http.error_document_404,
- (int)strlen(wsi->vhost->http.error_document_404),
- &p, end) > 0)
- return 0;
-#endif
-
- /* if the redirect failed, just do a simple status */
- p = start;
-
- if (!html_body)
- html_body = "";
-
- if (lws_add_http_header_status(wsi, code, &p, end))
- return 1;
-
- if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,
- (unsigned char *)"text/html", 9,
- &p, end))
- return 1;
-
- len = 35 + (int)strlen(html_body) + sprintf(slen, "%d", code);
- n = sprintf(slen, "%d", len);
-
- if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH,
- (unsigned char *)slen, n, &p, end))
- return 1;
-
- if (lws_finalize_http_header(wsi, &p, end))
- return 1;
-
-#if defined(LWS_WITH_HTTP2)
- if (wsi->http2_substream) {
- unsigned char *body = p + 512;
-
- /*
- * for HTTP/2, the headers must be sent separately, since they
- * go out in their own frame. That puts us in a bind that
- * we won't always be able to get away with two lws_write()s in
- * sequence, since the first may use up the writability due to
- * the pipe being choked or SSL_WANT_.
- *
- * However we do need to send the human-readable body, and the
- * END_STREAM.
- *
- * Solve it by writing the headers now...
- */
- m = lws_write(wsi, start, p - start, LWS_WRITE_HTTP_HEADERS);
- if (m != lws_ptr_diff(p, start))
- return 1;
-
- /*
- * ... but stash the body and send it as a priority next
- * handle_POLLOUT
- */
-
- len = sprintf((char *)body,
- "<html><body><h1>%u</h1>%s</body></html>",
- code, html_body);
- wsi->http.tx_content_length = len;
- wsi->http.tx_content_remain = len;
-
- wsi->h2.pending_status_body = lws_malloc(len + LWS_PRE + 1,
- "pending status body");
- if (!wsi->h2.pending_status_body)
- return -1;
-
- strcpy(wsi->h2.pending_status_body + LWS_PRE,
- (const char *)body);
- lws_callback_on_writable(wsi);
-
- return 0;
- } else
-#endif
- {
- /*
- * for http/1, we can just append the body after the finalized
- * headers and send it all in one go.
- */
- p += lws_snprintf((char *)p, end - p - 1,
- "<html><body><h1>%u</h1>%s</body></html>",
- code, html_body);
-
- n = lws_ptr_diff(p, start);
- m = lws_write(wsi, start, n, LWS_WRITE_HTTP);
- if (m != n)
- return 1;
- }
-
- return m != n;
-}
-
-LWS_VISIBLE int
-lws_http_redirect(struct lws *wsi, int code, const unsigned char *loc, int len,
- unsigned char **p, unsigned char *end)
-{
- unsigned char *start = *p;
-
- if (lws_add_http_header_status(wsi, code, p, end))
- return -1;
-
- if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_LOCATION, loc, len,
- p, end))
- return -1;
- /*
- * if we're going with http/1.1 and keepalive, we have to give fake
- * content metadata so the client knows we completed the transaction and
- * it can do the redirect...
- */
- if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,
- (unsigned char *)"text/html", 9, p,
- end))
- return -1;
- if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH,
- (unsigned char *)"0", 1, p, end))
- return -1;
-
- if (lws_finalize_http_header(wsi, p, end))
- return -1;
-
- return lws_write(wsi, start, *p - start, LWS_WRITE_HTTP_HEADERS |
- LWS_WRITE_H2_STREAM_END);
-}
diff --git a/thirdparty/libwebsockets/roles/http/lextable-strings.h b/thirdparty/libwebsockets/roles/http/lextable-strings.h
deleted file mode 100644
index 631f5cb600..0000000000
--- a/thirdparty/libwebsockets/roles/http/lextable-strings.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/* set of parsable strings -- ALL LOWER CASE */
-
-#if !defined(STORE_IN_ROM)
-#define STORE_IN_ROM
-#endif
-
-STORE_IN_ROM static const char * const set[] = {
- "get ",
- "post ",
- "options ",
- "host:",
- "connection:",
- "upgrade:",
- "origin:",
- "sec-websocket-draft:",
- "\x0d\x0a",
-
- "sec-websocket-extensions:",
- "sec-websocket-key1:",
- "sec-websocket-key2:",
- "sec-websocket-protocol:",
-
- "sec-websocket-accept:",
- "sec-websocket-nonce:",
- "http/1.1 ",
- "http2-settings:",
-
- "accept:",
- "access-control-request-headers:",
- "if-modified-since:",
- "if-none-match:",
- "accept-encoding:",
- "accept-language:",
- "pragma:",
- "cache-control:",
- "authorization:",
- "cookie:",
- "content-length:",
- "content-type:",
- "date:",
- "range:",
- "referer:",
- "sec-websocket-key:",
- "sec-websocket-version:",
- "sec-websocket-origin:",
-
- ":authority",
- ":method",
- ":path",
- ":scheme",
- ":status",
-
- "accept-charset:",
- "accept-ranges:",
- "access-control-allow-origin:",
- "age:",
- "allow:",
- "content-disposition:",
- "content-encoding:",
- "content-language:",
- "content-location:",
- "content-range:",
- "etag:",
- "expect:",
- "expires:",
- "from:",
- "if-match:",
- "if-range:",
- "if-unmodified-since:",
- "last-modified:",
- "link:",
- "location:",
- "max-forwards:",
- "proxy-authenticate:",
- "proxy-authorization:",
- "refresh:",
- "retry-after:",
- "server:",
- "set-cookie:",
- "strict-transport-security:",
- "transfer-encoding:",
- "user-agent:",
- "vary:",
- "via:",
- "www-authenticate:",
-
- "patch",
- "put",
- "delete",
-
- "uri-args", /* fake header used for uri-only storage */
-
- "proxy ",
- "x-real-ip:",
- "http/1.0 ",
-
- "x-forwarded-for",
- "connect ",
- "head ",
- "te:", /* http/2 wants it to reject it */
- "replay-nonce:", /* ACME */
- ":protocol", /* defined in mcmanus-httpbis-h2-ws-02 */
-
- "x-auth-token:",
-
- "", /* not matchable */
-
-};
diff --git a/thirdparty/libwebsockets/roles/http/lextable.h b/thirdparty/libwebsockets/roles/http/lextable.h
deleted file mode 100644
index 9a8063b157..0000000000
--- a/thirdparty/libwebsockets/roles/http/lextable.h
+++ /dev/null
@@ -1,838 +0,0 @@
-/* pos 0000: 0 */ 0x67 /* 'g' */, 0x40, 0x00 /* (to 0x0040 state 1) */,
- 0x70 /* 'p' */, 0x42, 0x00 /* (to 0x0045 state 5) */,
- 0x6F /* 'o' */, 0x51, 0x00 /* (to 0x0057 state 10) */,
- 0x68 /* 'h' */, 0x5D, 0x00 /* (to 0x0066 state 18) */,
- 0x63 /* 'c' */, 0x69, 0x00 /* (to 0x0075 state 23) */,
- 0x75 /* 'u' */, 0x8A, 0x00 /* (to 0x0099 state 34) */,
- 0x73 /* 's' */, 0xA0, 0x00 /* (to 0x00B2 state 48) */,
- 0x0D /* '.' */, 0xD9, 0x00 /* (to 0x00EE state 68) */,
- 0x61 /* 'a' */, 0x31, 0x01 /* (to 0x0149 state 129) */,
- 0x69 /* 'i' */, 0x70, 0x01 /* (to 0x018B state 163) */,
- 0x64 /* 'd' */, 0x19, 0x02 /* (to 0x0237 state 265) */,
- 0x72 /* 'r' */, 0x22, 0x02 /* (to 0x0243 state 270) */,
- 0x3A /* ':' */, 0x56, 0x02 /* (to 0x027A state 299) */,
- 0x65 /* 'e' */, 0xE8, 0x02 /* (to 0x030F state 409) */,
- 0x66 /* 'f' */, 0x04, 0x03 /* (to 0x032E state 425) */,
- 0x6C /* 'l' */, 0x26, 0x03 /* (to 0x0353 state 458) */,
- 0x6D /* 'm' */, 0x49, 0x03 /* (to 0x0379 state 484) */,
- 0x74 /* 't' */, 0xB8, 0x03 /* (to 0x03EB state 578) */,
- 0x76 /* 'v' */, 0xD9, 0x03 /* (to 0x040F state 606) */,
- 0x77 /* 'w' */, 0xE6, 0x03 /* (to 0x041F state 614) */,
- 0x78 /* 'x' */, 0x0D, 0x04 /* (to 0x0449 state 650) */,
- 0x08, /* fail */
-/* pos 0040: 1 */ 0xE5 /* 'e' -> */,
-/* pos 0041: 2 */ 0xF4 /* 't' -> */,
-/* pos 0042: 3 */ 0xA0 /* ' ' -> */,
-/* pos 0043: 4 */ 0x00, 0x00 /* - terminal marker 0 - */,
-/* pos 0045: 5 */ 0x6F /* 'o' */, 0x0D, 0x00 /* (to 0x0052 state 6) */,
- 0x72 /* 'r' */, 0x95, 0x01 /* (to 0x01DD state 211) */,
- 0x61 /* 'a' */, 0xE6, 0x03 /* (to 0x0431 state 631) */,
- 0x75 /* 'u' */, 0xE8, 0x03 /* (to 0x0436 state 635) */,
- 0x08, /* fail */
-/* pos 0052: 6 */ 0xF3 /* 's' -> */,
-/* pos 0053: 7 */ 0xF4 /* 't' -> */,
-/* pos 0054: 8 */ 0xA0 /* ' ' -> */,
-/* pos 0055: 9 */ 0x00, 0x01 /* - terminal marker 1 - */,
-/* pos 0057: 10 */ 0x70 /* 'p' */, 0x07, 0x00 /* (to 0x005E state 11) */,
- 0x72 /* 'r' */, 0x51, 0x00 /* (to 0x00AB state 42) */,
- 0x08, /* fail */
-/* pos 005e: 11 */ 0xF4 /* 't' -> */,
-/* pos 005f: 12 */ 0xE9 /* 'i' -> */,
-/* pos 0060: 13 */ 0xEF /* 'o' -> */,
-/* pos 0061: 14 */ 0xEE /* 'n' -> */,
-/* pos 0062: 15 */ 0xF3 /* 's' -> */,
-/* pos 0063: 16 */ 0xA0 /* ' ' -> */,
-/* pos 0064: 17 */ 0x00, 0x02 /* - terminal marker 2 - */,
-/* pos 0066: 18 */ 0x6F /* 'o' */, 0x0A, 0x00 /* (to 0x0070 state 19) */,
- 0x74 /* 't' */, 0xBF, 0x00 /* (to 0x0128 state 110) */,
- 0x65 /* 'e' */, 0x04, 0x04 /* (to 0x0470 state 676) */,
- 0x08, /* fail */
-/* pos 0070: 19 */ 0xF3 /* 's' -> */,
-/* pos 0071: 20 */ 0xF4 /* 't' -> */,
-/* pos 0072: 21 */ 0xBA /* ':' -> */,
-/* pos 0073: 22 */ 0x00, 0x03 /* - terminal marker 3 - */,
-/* pos 0075: 23 */ 0x6F /* 'o' */, 0x07, 0x00 /* (to 0x007C state 24) */,
- 0x61 /* 'a' */, 0x72, 0x01 /* (to 0x01EA state 217) */,
- 0x08, /* fail */
-/* pos 007c: 24 */ 0x6E /* 'n' */, 0x07, 0x00 /* (to 0x0083 state 25) */,
- 0x6F /* 'o' */, 0x87, 0x01 /* (to 0x0206 state 243) */,
- 0x08, /* fail */
-/* pos 0083: 25 */ 0x6E /* 'n' */, 0x07, 0x00 /* (to 0x008A state 26) */,
- 0x74 /* 't' */, 0x86, 0x01 /* (to 0x020C state 248) */,
- 0x08, /* fail */
-/* pos 008a: 26 */ 0xE5 /* 'e' -> */,
-/* pos 008b: 27 */ 0xE3 /* 'c' -> */,
-/* pos 008c: 28 */ 0xF4 /* 't' -> */,
-/* pos 008d: 29 */ 0x69 /* 'i' */, 0x07, 0x00 /* (to 0x0094 state 30) */,
- 0x20 /* ' ' */, 0xDE, 0x03 /* (to 0x046E state 675) */,
- 0x08, /* fail */
-/* pos 0094: 30 */ 0xEF /* 'o' -> */,
-/* pos 0095: 31 */ 0xEE /* 'n' -> */,
-/* pos 0096: 32 */ 0xBA /* ':' -> */,
-/* pos 0097: 33 */ 0x00, 0x04 /* - terminal marker 4 - */,
-/* pos 0099: 34 */ 0x70 /* 'p' */, 0x0A, 0x00 /* (to 0x00A3 state 35) */,
- 0x73 /* 's' */, 0x68, 0x03 /* (to 0x0404 state 596) */,
- 0x72 /* 'r' */, 0xA0, 0x03 /* (to 0x043F state 642) */,
- 0x08, /* fail */
-/* pos 00a3: 35 */ 0xE7 /* 'g' -> */,
-/* pos 00a4: 36 */ 0xF2 /* 'r' -> */,
-/* pos 00a5: 37 */ 0xE1 /* 'a' -> */,
-/* pos 00a6: 38 */ 0xE4 /* 'd' -> */,
-/* pos 00a7: 39 */ 0xE5 /* 'e' -> */,
-/* pos 00a8: 40 */ 0xBA /* ':' -> */,
-/* pos 00a9: 41 */ 0x00, 0x05 /* - terminal marker 5 - */,
-/* pos 00ab: 42 */ 0xE9 /* 'i' -> */,
-/* pos 00ac: 43 */ 0xE7 /* 'g' -> */,
-/* pos 00ad: 44 */ 0xE9 /* 'i' -> */,
-/* pos 00ae: 45 */ 0xEE /* 'n' -> */,
-/* pos 00af: 46 */ 0xBA /* ':' -> */,
-/* pos 00b0: 47 */ 0x00, 0x06 /* - terminal marker 6 - */,
-/* pos 00b2: 48 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x00B9 state 49) */,
- 0x74 /* 't' */, 0x1C, 0x03 /* (to 0x03D1 state 553) */,
- 0x08, /* fail */
-/* pos 00b9: 49 */ 0x63 /* 'c' */, 0x0A, 0x00 /* (to 0x00C3 state 50) */,
- 0x72 /* 'r' */, 0x05, 0x03 /* (to 0x03C1 state 539) */,
- 0x74 /* 't' */, 0x08, 0x03 /* (to 0x03C7 state 544) */,
- 0x08, /* fail */
-/* pos 00c3: 50 */ 0xAD /* '-' -> */,
-/* pos 00c4: 51 */ 0xF7 /* 'w' -> */,
-/* pos 00c5: 52 */ 0xE5 /* 'e' -> */,
-/* pos 00c6: 53 */ 0xE2 /* 'b' -> */,
-/* pos 00c7: 54 */ 0xF3 /* 's' -> */,
-/* pos 00c8: 55 */ 0xEF /* 'o' -> */,
-/* pos 00c9: 56 */ 0xE3 /* 'c' -> */,
-/* pos 00ca: 57 */ 0xEB /* 'k' -> */,
-/* pos 00cb: 58 */ 0xE5 /* 'e' -> */,
-/* pos 00cc: 59 */ 0xF4 /* 't' -> */,
-/* pos 00cd: 60 */ 0xAD /* '-' -> */,
-/* pos 00ce: 61 */ 0x64 /* 'd' */, 0x19, 0x00 /* (to 0x00E7 state 62) */,
- 0x65 /* 'e' */, 0x20, 0x00 /* (to 0x00F1 state 70) */,
- 0x6B /* 'k' */, 0x29, 0x00 /* (to 0x00FD state 81) */,
- 0x70 /* 'p' */, 0x38, 0x00 /* (to 0x010F state 88) */,
- 0x61 /* 'a' */, 0x3F, 0x00 /* (to 0x0119 state 97) */,
- 0x6E /* 'n' */, 0x44, 0x00 /* (to 0x0121 state 104) */,
- 0x76 /* 'v' */, 0x89, 0x01 /* (to 0x0269 state 284) */,
- 0x6F /* 'o' */, 0x8F, 0x01 /* (to 0x0272 state 292) */,
- 0x08, /* fail */
-/* pos 00e7: 62 */ 0xF2 /* 'r' -> */,
-/* pos 00e8: 63 */ 0xE1 /* 'a' -> */,
-/* pos 00e9: 64 */ 0xE6 /* 'f' -> */,
-/* pos 00ea: 65 */ 0xF4 /* 't' -> */,
-/* pos 00eb: 66 */ 0xBA /* ':' -> */,
-/* pos 00ec: 67 */ 0x00, 0x07 /* - terminal marker 7 - */,
-/* pos 00ee: 68 */ 0x8A /* '.' -> */,
-/* pos 00ef: 69 */ 0x00, 0x08 /* - terminal marker 8 - */,
-/* pos 00f1: 70 */ 0xF8 /* 'x' -> */,
-/* pos 00f2: 71 */ 0xF4 /* 't' -> */,
-/* pos 00f3: 72 */ 0xE5 /* 'e' -> */,
-/* pos 00f4: 73 */ 0xEE /* 'n' -> */,
-/* pos 00f5: 74 */ 0xF3 /* 's' -> */,
-/* pos 00f6: 75 */ 0xE9 /* 'i' -> */,
-/* pos 00f7: 76 */ 0xEF /* 'o' -> */,
-/* pos 00f8: 77 */ 0xEE /* 'n' -> */,
-/* pos 00f9: 78 */ 0xF3 /* 's' -> */,
-/* pos 00fa: 79 */ 0xBA /* ':' -> */,
-/* pos 00fb: 80 */ 0x00, 0x09 /* - terminal marker 9 - */,
-/* pos 00fd: 81 */ 0xE5 /* 'e' -> */,
-/* pos 00fe: 82 */ 0xF9 /* 'y' -> */,
-/* pos 00ff: 83 */ 0x31 /* '1' */, 0x0A, 0x00 /* (to 0x0109 state 84) */,
- 0x32 /* '2' */, 0x0A, 0x00 /* (to 0x010C state 86) */,
- 0x3A /* ':' */, 0x62, 0x01 /* (to 0x0267 state 283) */,
- 0x08, /* fail */
-/* pos 0109: 84 */ 0xBA /* ':' -> */,
-/* pos 010a: 85 */ 0x00, 0x0A /* - terminal marker 10 - */,
-/* pos 010c: 86 */ 0xBA /* ':' -> */,
-/* pos 010d: 87 */ 0x00, 0x0B /* - terminal marker 11 - */,
-/* pos 010f: 88 */ 0xF2 /* 'r' -> */,
-/* pos 0110: 89 */ 0xEF /* 'o' -> */,
-/* pos 0111: 90 */ 0xF4 /* 't' -> */,
-/* pos 0112: 91 */ 0xEF /* 'o' -> */,
-/* pos 0113: 92 */ 0xE3 /* 'c' -> */,
-/* pos 0114: 93 */ 0xEF /* 'o' -> */,
-/* pos 0115: 94 */ 0xEC /* 'l' -> */,
-/* pos 0116: 95 */ 0xBA /* ':' -> */,
-/* pos 0117: 96 */ 0x00, 0x0C /* - terminal marker 12 - */,
-/* pos 0119: 97 */ 0xE3 /* 'c' -> */,
-/* pos 011a: 98 */ 0xE3 /* 'c' -> */,
-/* pos 011b: 99 */ 0xE5 /* 'e' -> */,
-/* pos 011c: 100 */ 0xF0 /* 'p' -> */,
-/* pos 011d: 101 */ 0xF4 /* 't' -> */,
-/* pos 011e: 102 */ 0xBA /* ':' -> */,
-/* pos 011f: 103 */ 0x00, 0x0D /* - terminal marker 13 - */,
-/* pos 0121: 104 */ 0xEF /* 'o' -> */,
-/* pos 0122: 105 */ 0xEE /* 'n' -> */,
-/* pos 0123: 106 */ 0xE3 /* 'c' -> */,
-/* pos 0124: 107 */ 0xE5 /* 'e' -> */,
-/* pos 0125: 108 */ 0xBA /* ':' -> */,
-/* pos 0126: 109 */ 0x00, 0x0E /* - terminal marker 14 - */,
-/* pos 0128: 110 */ 0xF4 /* 't' -> */,
-/* pos 0129: 111 */ 0xF0 /* 'p' -> */,
-/* pos 012a: 112 */ 0x2F /* '/' */, 0x07, 0x00 /* (to 0x0131 state 113) */,
- 0x32 /* '2' */, 0x10, 0x00 /* (to 0x013D state 118) */,
- 0x08, /* fail */
-/* pos 0131: 113 */ 0xB1 /* '1' -> */,
-/* pos 0132: 114 */ 0xAE /* '.' -> */,
-/* pos 0133: 115 */ 0x31 /* '1' */, 0x07, 0x00 /* (to 0x013A state 116) */,
- 0x30 /* '0' */, 0x27, 0x03 /* (to 0x045D state 660) */,
- 0x08, /* fail */
-/* pos 013a: 116 */ 0xA0 /* ' ' -> */,
-/* pos 013b: 117 */ 0x00, 0x0F /* - terminal marker 15 - */,
-/* pos 013d: 118 */ 0xAD /* '-' -> */,
-/* pos 013e: 119 */ 0xF3 /* 's' -> */,
-/* pos 013f: 120 */ 0xE5 /* 'e' -> */,
-/* pos 0140: 121 */ 0xF4 /* 't' -> */,
-/* pos 0141: 122 */ 0xF4 /* 't' -> */,
-/* pos 0142: 123 */ 0xE9 /* 'i' -> */,
-/* pos 0143: 124 */ 0xEE /* 'n' -> */,
-/* pos 0144: 125 */ 0xE7 /* 'g' -> */,
-/* pos 0145: 126 */ 0xF3 /* 's' -> */,
-/* pos 0146: 127 */ 0xBA /* ':' -> */,
-/* pos 0147: 128 */ 0x00, 0x10 /* - terminal marker 16 - */,
-/* pos 0149: 129 */ 0x63 /* 'c' */, 0x0D, 0x00 /* (to 0x0156 state 130) */,
- 0x75 /* 'u' */, 0xAC, 0x00 /* (to 0x01F8 state 230) */,
- 0x67 /* 'g' */, 0x86, 0x01 /* (to 0x02D5 state 358) */,
- 0x6C /* 'l' */, 0x87, 0x01 /* (to 0x02D9 state 361) */,
- 0x08, /* fail */
-/* pos 0156: 130 */ 0xE3 /* 'c' -> */,
-/* pos 0157: 131 */ 0xE5 /* 'e' -> */,
-/* pos 0158: 132 */ 0x70 /* 'p' */, 0x07, 0x00 /* (to 0x015F state 133) */,
- 0x73 /* 's' */, 0x0E, 0x00 /* (to 0x0169 state 136) */,
- 0x08, /* fail */
-/* pos 015f: 133 */ 0xF4 /* 't' -> */,
-/* pos 0160: 134 */ 0x3A /* ':' */, 0x07, 0x00 /* (to 0x0167 state 135) */,
- 0x2D /* '-' */, 0x59, 0x00 /* (to 0x01BC state 192) */,
- 0x08, /* fail */
-/* pos 0167: 135 */ 0x00, 0x11 /* - terminal marker 17 - */,
-/* pos 0169: 136 */ 0xF3 /* 's' -> */,
-/* pos 016a: 137 */ 0xAD /* '-' -> */,
-/* pos 016b: 138 */ 0xE3 /* 'c' -> */,
-/* pos 016c: 139 */ 0xEF /* 'o' -> */,
-/* pos 016d: 140 */ 0xEE /* 'n' -> */,
-/* pos 016e: 141 */ 0xF4 /* 't' -> */,
-/* pos 016f: 142 */ 0xF2 /* 'r' -> */,
-/* pos 0170: 143 */ 0xEF /* 'o' -> */,
-/* pos 0171: 144 */ 0xEC /* 'l' -> */,
-/* pos 0172: 145 */ 0xAD /* '-' -> */,
-/* pos 0173: 146 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x017A state 147) */,
- 0x61 /* 'a' */, 0x51, 0x01 /* (to 0x02C7 state 345) */,
- 0x08, /* fail */
-/* pos 017a: 147 */ 0xE5 /* 'e' -> */,
-/* pos 017b: 148 */ 0xF1 /* 'q' -> */,
-/* pos 017c: 149 */ 0xF5 /* 'u' -> */,
-/* pos 017d: 150 */ 0xE5 /* 'e' -> */,
-/* pos 017e: 151 */ 0xF3 /* 's' -> */,
-/* pos 017f: 152 */ 0xF4 /* 't' -> */,
-/* pos 0180: 153 */ 0xAD /* '-' -> */,
-/* pos 0181: 154 */ 0xE8 /* 'h' -> */,
-/* pos 0182: 155 */ 0xE5 /* 'e' -> */,
-/* pos 0183: 156 */ 0xE1 /* 'a' -> */,
-/* pos 0184: 157 */ 0xE4 /* 'd' -> */,
-/* pos 0185: 158 */ 0xE5 /* 'e' -> */,
-/* pos 0186: 159 */ 0xF2 /* 'r' -> */,
-/* pos 0187: 160 */ 0xF3 /* 's' -> */,
-/* pos 0188: 161 */ 0xBA /* ':' -> */,
-/* pos 0189: 162 */ 0x00, 0x12 /* - terminal marker 18 - */,
-/* pos 018b: 163 */ 0xE6 /* 'f' -> */,
-/* pos 018c: 164 */ 0xAD /* '-' -> */,
-/* pos 018d: 165 */ 0x6D /* 'm' */, 0x0D, 0x00 /* (to 0x019A state 166) */,
- 0x6E /* 'n' */, 0x20, 0x00 /* (to 0x01B0 state 181) */,
- 0x72 /* 'r' */, 0xA7, 0x01 /* (to 0x033A state 435) */,
- 0x75 /* 'u' */, 0xAB, 0x01 /* (to 0x0341 state 441) */,
- 0x08, /* fail */
-/* pos 019a: 166 */ 0x6F /* 'o' */, 0x07, 0x00 /* (to 0x01A1 state 167) */,
- 0x61 /* 'a' */, 0x97, 0x01 /* (to 0x0334 state 430) */,
- 0x08, /* fail */
-/* pos 01a1: 167 */ 0xE4 /* 'd' -> */,
-/* pos 01a2: 168 */ 0xE9 /* 'i' -> */,
-/* pos 01a3: 169 */ 0xE6 /* 'f' -> */,
-/* pos 01a4: 170 */ 0xE9 /* 'i' -> */,
-/* pos 01a5: 171 */ 0xE5 /* 'e' -> */,
-/* pos 01a6: 172 */ 0xE4 /* 'd' -> */,
-/* pos 01a7: 173 */ 0xAD /* '-' -> */,
-/* pos 01a8: 174 */ 0xF3 /* 's' -> */,
-/* pos 01a9: 175 */ 0xE9 /* 'i' -> */,
-/* pos 01aa: 176 */ 0xEE /* 'n' -> */,
-/* pos 01ab: 177 */ 0xE3 /* 'c' -> */,
-/* pos 01ac: 178 */ 0xE5 /* 'e' -> */,
-/* pos 01ad: 179 */ 0xBA /* ':' -> */,
-/* pos 01ae: 180 */ 0x00, 0x13 /* - terminal marker 19 - */,
-/* pos 01b0: 181 */ 0xEF /* 'o' -> */,
-/* pos 01b1: 182 */ 0xEE /* 'n' -> */,
-/* pos 01b2: 183 */ 0xE5 /* 'e' -> */,
-/* pos 01b3: 184 */ 0xAD /* '-' -> */,
-/* pos 01b4: 185 */ 0xED /* 'm' -> */,
-/* pos 01b5: 186 */ 0xE1 /* 'a' -> */,
-/* pos 01b6: 187 */ 0xF4 /* 't' -> */,
-/* pos 01b7: 188 */ 0xE3 /* 'c' -> */,
-/* pos 01b8: 189 */ 0xE8 /* 'h' -> */,
-/* pos 01b9: 190 */ 0xBA /* ':' -> */,
-/* pos 01ba: 191 */ 0x00, 0x14 /* - terminal marker 20 - */,
-/* pos 01bc: 192 */ 0x65 /* 'e' */, 0x0D, 0x00 /* (to 0x01C9 state 193) */,
- 0x6C /* 'l' */, 0x14, 0x00 /* (to 0x01D3 state 202) */,
- 0x63 /* 'c' */, 0xF4, 0x00 /* (to 0x02B6 state 330) */,
- 0x72 /* 'r' */, 0xFA, 0x00 /* (to 0x02BF state 338) */,
- 0x08, /* fail */
-/* pos 01c9: 193 */ 0xEE /* 'n' -> */,
-/* pos 01ca: 194 */ 0xE3 /* 'c' -> */,
-/* pos 01cb: 195 */ 0xEF /* 'o' -> */,
-/* pos 01cc: 196 */ 0xE4 /* 'd' -> */,
-/* pos 01cd: 197 */ 0xE9 /* 'i' -> */,
-/* pos 01ce: 198 */ 0xEE /* 'n' -> */,
-/* pos 01cf: 199 */ 0xE7 /* 'g' -> */,
-/* pos 01d0: 200 */ 0xBA /* ':' -> */,
-/* pos 01d1: 201 */ 0x00, 0x15 /* - terminal marker 21 - */,
-/* pos 01d3: 202 */ 0xE1 /* 'a' -> */,
-/* pos 01d4: 203 */ 0xEE /* 'n' -> */,
-/* pos 01d5: 204 */ 0xE7 /* 'g' -> */,
-/* pos 01d6: 205 */ 0xF5 /* 'u' -> */,
-/* pos 01d7: 206 */ 0xE1 /* 'a' -> */,
-/* pos 01d8: 207 */ 0xE7 /* 'g' -> */,
-/* pos 01d9: 208 */ 0xE5 /* 'e' -> */,
-/* pos 01da: 209 */ 0xBA /* ':' -> */,
-/* pos 01db: 210 */ 0x00, 0x16 /* - terminal marker 22 - */,
-/* pos 01dd: 211 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x01E4 state 212) */,
- 0x6F /* 'o' */, 0xA7, 0x01 /* (to 0x0387 state 497) */,
- 0x08, /* fail */
-/* pos 01e4: 212 */ 0xE7 /* 'g' -> */,
-/* pos 01e5: 213 */ 0xED /* 'm' -> */,
-/* pos 01e6: 214 */ 0xE1 /* 'a' -> */,
-/* pos 01e7: 215 */ 0xBA /* ':' -> */,
-/* pos 01e8: 216 */ 0x00, 0x17 /* - terminal marker 23 - */,
-/* pos 01ea: 217 */ 0xE3 /* 'c' -> */,
-/* pos 01eb: 218 */ 0xE8 /* 'h' -> */,
-/* pos 01ec: 219 */ 0xE5 /* 'e' -> */,
-/* pos 01ed: 220 */ 0xAD /* '-' -> */,
-/* pos 01ee: 221 */ 0xE3 /* 'c' -> */,
-/* pos 01ef: 222 */ 0xEF /* 'o' -> */,
-/* pos 01f0: 223 */ 0xEE /* 'n' -> */,
-/* pos 01f1: 224 */ 0xF4 /* 't' -> */,
-/* pos 01f2: 225 */ 0xF2 /* 'r' -> */,
-/* pos 01f3: 226 */ 0xEF /* 'o' -> */,
-/* pos 01f4: 227 */ 0xEC /* 'l' -> */,
-/* pos 01f5: 228 */ 0xBA /* ':' -> */,
-/* pos 01f6: 229 */ 0x00, 0x18 /* - terminal marker 24 - */,
-/* pos 01f8: 230 */ 0xF4 /* 't' -> */,
-/* pos 01f9: 231 */ 0xE8 /* 'h' -> */,
-/* pos 01fa: 232 */ 0xEF /* 'o' -> */,
-/* pos 01fb: 233 */ 0xF2 /* 'r' -> */,
-/* pos 01fc: 234 */ 0xE9 /* 'i' -> */,
-/* pos 01fd: 235 */ 0xFA /* 'z' -> */,
-/* pos 01fe: 236 */ 0xE1 /* 'a' -> */,
-/* pos 01ff: 237 */ 0xF4 /* 't' -> */,
-/* pos 0200: 238 */ 0xE9 /* 'i' -> */,
-/* pos 0201: 239 */ 0xEF /* 'o' -> */,
-/* pos 0202: 240 */ 0xEE /* 'n' -> */,
-/* pos 0203: 241 */ 0xBA /* ':' -> */,
-/* pos 0204: 242 */ 0x00, 0x19 /* - terminal marker 25 - */,
-/* pos 0206: 243 */ 0xEB /* 'k' -> */,
-/* pos 0207: 244 */ 0xE9 /* 'i' -> */,
-/* pos 0208: 245 */ 0xE5 /* 'e' -> */,
-/* pos 0209: 246 */ 0xBA /* ':' -> */,
-/* pos 020a: 247 */ 0x00, 0x1A /* - terminal marker 26 - */,
-/* pos 020c: 248 */ 0xE5 /* 'e' -> */,
-/* pos 020d: 249 */ 0xEE /* 'n' -> */,
-/* pos 020e: 250 */ 0xF4 /* 't' -> */,
-/* pos 020f: 251 */ 0xAD /* '-' -> */,
-/* pos 0210: 252 */ 0x6C /* 'l' */, 0x10, 0x00 /* (to 0x0220 state 253) */,
- 0x74 /* 't' */, 0x1E, 0x00 /* (to 0x0231 state 260) */,
- 0x64 /* 'd' */, 0xC9, 0x00 /* (to 0x02DF state 366) */,
- 0x65 /* 'e' */, 0xD3, 0x00 /* (to 0x02EC state 378) */,
- 0x72 /* 'r' */, 0xEC, 0x00 /* (to 0x0308 state 403) */,
- 0x08, /* fail */
-/* pos 0220: 253 */ 0x65 /* 'e' */, 0x0A, 0x00 /* (to 0x022A state 254) */,
- 0x61 /* 'a' */, 0xD3, 0x00 /* (to 0x02F6 state 387) */,
- 0x6F /* 'o' */, 0xD9, 0x00 /* (to 0x02FF state 395) */,
- 0x08, /* fail */
-/* pos 022a: 254 */ 0xEE /* 'n' -> */,
-/* pos 022b: 255 */ 0xE7 /* 'g' -> */,
-/* pos 022c: 256 */ 0xF4 /* 't' -> */,
-/* pos 022d: 257 */ 0xE8 /* 'h' -> */,
-/* pos 022e: 258 */ 0xBA /* ':' -> */,
-/* pos 022f: 259 */ 0x00, 0x1B /* - terminal marker 27 - */,
-/* pos 0231: 260 */ 0xF9 /* 'y' -> */,
-/* pos 0232: 261 */ 0xF0 /* 'p' -> */,
-/* pos 0233: 262 */ 0xE5 /* 'e' -> */,
-/* pos 0234: 263 */ 0xBA /* ':' -> */,
-/* pos 0235: 264 */ 0x00, 0x1C /* - terminal marker 28 - */,
-/* pos 0237: 265 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x023E state 266) */,
- 0x65 /* 'e' */, 0xFF, 0x01 /* (to 0x0439 state 637) */,
- 0x08, /* fail */
-/* pos 023e: 266 */ 0xF4 /* 't' -> */,
-/* pos 023f: 267 */ 0xE5 /* 'e' -> */,
-/* pos 0240: 268 */ 0xBA /* ':' -> */,
-/* pos 0241: 269 */ 0x00, 0x1D /* - terminal marker 29 - */,
-/* pos 0243: 270 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x024A state 271) */,
- 0x65 /* 'e' */, 0x0A, 0x00 /* (to 0x0250 state 276) */,
- 0x08, /* fail */
-/* pos 024a: 271 */ 0xEE /* 'n' -> */,
-/* pos 024b: 272 */ 0xE7 /* 'g' -> */,
-/* pos 024c: 273 */ 0xE5 /* 'e' -> */,
-/* pos 024d: 274 */ 0xBA /* ':' -> */,
-/* pos 024e: 275 */ 0x00, 0x1E /* - terminal marker 30 - */,
-/* pos 0250: 276 */ 0x66 /* 'f' */, 0x0A, 0x00 /* (to 0x025A state 277) */,
- 0x74 /* 't' */, 0x63, 0x01 /* (to 0x03B6 state 529) */,
- 0x70 /* 'p' */, 0x22, 0x02 /* (to 0x0478 state 682) */,
- 0x08, /* fail */
-/* pos 025a: 277 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0261 state 278) */,
- 0x72 /* 'r' */, 0x53, 0x01 /* (to 0x03B0 state 524) */,
- 0x08, /* fail */
-/* pos 0261: 278 */ 0xF2 /* 'r' -> */,
-/* pos 0262: 279 */ 0xE5 /* 'e' -> */,
-/* pos 0263: 280 */ 0xF2 /* 'r' -> */,
-/* pos 0264: 281 */ 0xBA /* ':' -> */,
-/* pos 0265: 282 */ 0x00, 0x1F /* - terminal marker 31 - */,
-/* pos 0267: 283 */ 0x00, 0x20 /* - terminal marker 32 - */,
-/* pos 0269: 284 */ 0xE5 /* 'e' -> */,
-/* pos 026a: 285 */ 0xF2 /* 'r' -> */,
-/* pos 026b: 286 */ 0xF3 /* 's' -> */,
-/* pos 026c: 287 */ 0xE9 /* 'i' -> */,
-/* pos 026d: 288 */ 0xEF /* 'o' -> */,
-/* pos 026e: 289 */ 0xEE /* 'n' -> */,
-/* pos 026f: 290 */ 0xBA /* ':' -> */,
-/* pos 0270: 291 */ 0x00, 0x21 /* - terminal marker 33 - */,
-/* pos 0272: 292 */ 0xF2 /* 'r' -> */,
-/* pos 0273: 293 */ 0xE9 /* 'i' -> */,
-/* pos 0274: 294 */ 0xE7 /* 'g' -> */,
-/* pos 0275: 295 */ 0xE9 /* 'i' -> */,
-/* pos 0276: 296 */ 0xEE /* 'n' -> */,
-/* pos 0277: 297 */ 0xBA /* ':' -> */,
-/* pos 0278: 298 */ 0x00, 0x22 /* - terminal marker 34 - */,
-/* pos 027a: 299 */ 0x61 /* 'a' */, 0x0D, 0x00 /* (to 0x0287 state 300) */,
- 0x6D /* 'm' */, 0x14, 0x00 /* (to 0x0291 state 309) */,
- 0x70 /* 'p' */, 0x18, 0x00 /* (to 0x0298 state 315) */,
- 0x73 /* 's' */, 0x20, 0x00 /* (to 0x02A3 state 319) */,
- 0x08, /* fail */
-/* pos 0287: 300 */ 0xF5 /* 'u' -> */,
-/* pos 0288: 301 */ 0xF4 /* 't' -> */,
-/* pos 0289: 302 */ 0xE8 /* 'h' -> */,
-/* pos 028a: 303 */ 0xEF /* 'o' -> */,
-/* pos 028b: 304 */ 0xF2 /* 'r' -> */,
-/* pos 028c: 305 */ 0xE9 /* 'i' -> */,
-/* pos 028d: 306 */ 0xF4 /* 't' -> */,
-/* pos 028e: 307 */ 0xF9 /* 'y' -> */,
-/* pos 028f: 308 */ 0x00, 0x23 /* - terminal marker 35 - */,
-/* pos 0291: 309 */ 0xE5 /* 'e' -> */,
-/* pos 0292: 310 */ 0xF4 /* 't' -> */,
-/* pos 0293: 311 */ 0xE8 /* 'h' -> */,
-/* pos 0294: 312 */ 0xEF /* 'o' -> */,
-/* pos 0295: 313 */ 0xE4 /* 'd' -> */,
-/* pos 0296: 314 */ 0x00, 0x24 /* - terminal marker 36 - */,
-/* pos 0298: 315 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x029F state 316) */,
- 0x72 /* 'r' */, 0xE9, 0x01 /* (to 0x0484 state 693) */,
- 0x08, /* fail */
-/* pos 029f: 316 */ 0xF4 /* 't' -> */,
-/* pos 02a0: 317 */ 0xE8 /* 'h' -> */,
-/* pos 02a1: 318 */ 0x00, 0x25 /* - terminal marker 37 - */,
-/* pos 02a3: 319 */ 0x63 /* 'c' */, 0x07, 0x00 /* (to 0x02AA state 320) */,
- 0x74 /* 't' */, 0x0A, 0x00 /* (to 0x02B0 state 325) */,
- 0x08, /* fail */
-/* pos 02aa: 320 */ 0xE8 /* 'h' -> */,
-/* pos 02ab: 321 */ 0xE5 /* 'e' -> */,
-/* pos 02ac: 322 */ 0xED /* 'm' -> */,
-/* pos 02ad: 323 */ 0xE5 /* 'e' -> */,
-/* pos 02ae: 324 */ 0x00, 0x26 /* - terminal marker 38 - */,
-/* pos 02b0: 325 */ 0xE1 /* 'a' -> */,
-/* pos 02b1: 326 */ 0xF4 /* 't' -> */,
-/* pos 02b2: 327 */ 0xF5 /* 'u' -> */,
-/* pos 02b3: 328 */ 0xF3 /* 's' -> */,
-/* pos 02b4: 329 */ 0x00, 0x27 /* - terminal marker 39 - */,
-/* pos 02b6: 330 */ 0xE8 /* 'h' -> */,
-/* pos 02b7: 331 */ 0xE1 /* 'a' -> */,
-/* pos 02b8: 332 */ 0xF2 /* 'r' -> */,
-/* pos 02b9: 333 */ 0xF3 /* 's' -> */,
-/* pos 02ba: 334 */ 0xE5 /* 'e' -> */,
-/* pos 02bb: 335 */ 0xF4 /* 't' -> */,
-/* pos 02bc: 336 */ 0xBA /* ':' -> */,
-/* pos 02bd: 337 */ 0x00, 0x28 /* - terminal marker 40 - */,
-/* pos 02bf: 338 */ 0xE1 /* 'a' -> */,
-/* pos 02c0: 339 */ 0xEE /* 'n' -> */,
-/* pos 02c1: 340 */ 0xE7 /* 'g' -> */,
-/* pos 02c2: 341 */ 0xE5 /* 'e' -> */,
-/* pos 02c3: 342 */ 0xF3 /* 's' -> */,
-/* pos 02c4: 343 */ 0xBA /* ':' -> */,
-/* pos 02c5: 344 */ 0x00, 0x29 /* - terminal marker 41 - */,
-/* pos 02c7: 345 */ 0xEC /* 'l' -> */,
-/* pos 02c8: 346 */ 0xEC /* 'l' -> */,
-/* pos 02c9: 347 */ 0xEF /* 'o' -> */,
-/* pos 02ca: 348 */ 0xF7 /* 'w' -> */,
-/* pos 02cb: 349 */ 0xAD /* '-' -> */,
-/* pos 02cc: 350 */ 0xEF /* 'o' -> */,
-/* pos 02cd: 351 */ 0xF2 /* 'r' -> */,
-/* pos 02ce: 352 */ 0xE9 /* 'i' -> */,
-/* pos 02cf: 353 */ 0xE7 /* 'g' -> */,
-/* pos 02d0: 354 */ 0xE9 /* 'i' -> */,
-/* pos 02d1: 355 */ 0xEE /* 'n' -> */,
-/* pos 02d2: 356 */ 0xBA /* ':' -> */,
-/* pos 02d3: 357 */ 0x00, 0x2A /* - terminal marker 42 - */,
-/* pos 02d5: 358 */ 0xE5 /* 'e' -> */,
-/* pos 02d6: 359 */ 0xBA /* ':' -> */,
-/* pos 02d7: 360 */ 0x00, 0x2B /* - terminal marker 43 - */,
-/* pos 02d9: 361 */ 0xEC /* 'l' -> */,
-/* pos 02da: 362 */ 0xEF /* 'o' -> */,
-/* pos 02db: 363 */ 0xF7 /* 'w' -> */,
-/* pos 02dc: 364 */ 0xBA /* ':' -> */,
-/* pos 02dd: 365 */ 0x00, 0x2C /* - terminal marker 44 - */,
-/* pos 02df: 366 */ 0xE9 /* 'i' -> */,
-/* pos 02e0: 367 */ 0xF3 /* 's' -> */,
-/* pos 02e1: 368 */ 0xF0 /* 'p' -> */,
-/* pos 02e2: 369 */ 0xEF /* 'o' -> */,
-/* pos 02e3: 370 */ 0xF3 /* 's' -> */,
-/* pos 02e4: 371 */ 0xE9 /* 'i' -> */,
-/* pos 02e5: 372 */ 0xF4 /* 't' -> */,
-/* pos 02e6: 373 */ 0xE9 /* 'i' -> */,
-/* pos 02e7: 374 */ 0xEF /* 'o' -> */,
-/* pos 02e8: 375 */ 0xEE /* 'n' -> */,
-/* pos 02e9: 376 */ 0xBA /* ':' -> */,
-/* pos 02ea: 377 */ 0x00, 0x2D /* - terminal marker 45 - */,
-/* pos 02ec: 378 */ 0xEE /* 'n' -> */,
-/* pos 02ed: 379 */ 0xE3 /* 'c' -> */,
-/* pos 02ee: 380 */ 0xEF /* 'o' -> */,
-/* pos 02ef: 381 */ 0xE4 /* 'd' -> */,
-/* pos 02f0: 382 */ 0xE9 /* 'i' -> */,
-/* pos 02f1: 383 */ 0xEE /* 'n' -> */,
-/* pos 02f2: 384 */ 0xE7 /* 'g' -> */,
-/* pos 02f3: 385 */ 0xBA /* ':' -> */,
-/* pos 02f4: 386 */ 0x00, 0x2E /* - terminal marker 46 - */,
-/* pos 02f6: 387 */ 0xEE /* 'n' -> */,
-/* pos 02f7: 388 */ 0xE7 /* 'g' -> */,
-/* pos 02f8: 389 */ 0xF5 /* 'u' -> */,
-/* pos 02f9: 390 */ 0xE1 /* 'a' -> */,
-/* pos 02fa: 391 */ 0xE7 /* 'g' -> */,
-/* pos 02fb: 392 */ 0xE5 /* 'e' -> */,
-/* pos 02fc: 393 */ 0xBA /* ':' -> */,
-/* pos 02fd: 394 */ 0x00, 0x2F /* - terminal marker 47 - */,
-/* pos 02ff: 395 */ 0xE3 /* 'c' -> */,
-/* pos 0300: 396 */ 0xE1 /* 'a' -> */,
-/* pos 0301: 397 */ 0xF4 /* 't' -> */,
-/* pos 0302: 398 */ 0xE9 /* 'i' -> */,
-/* pos 0303: 399 */ 0xEF /* 'o' -> */,
-/* pos 0304: 400 */ 0xEE /* 'n' -> */,
-/* pos 0305: 401 */ 0xBA /* ':' -> */,
-/* pos 0306: 402 */ 0x00, 0x30 /* - terminal marker 48 - */,
-/* pos 0308: 403 */ 0xE1 /* 'a' -> */,
-/* pos 0309: 404 */ 0xEE /* 'n' -> */,
-/* pos 030a: 405 */ 0xE7 /* 'g' -> */,
-/* pos 030b: 406 */ 0xE5 /* 'e' -> */,
-/* pos 030c: 407 */ 0xBA /* ':' -> */,
-/* pos 030d: 408 */ 0x00, 0x31 /* - terminal marker 49 - */,
-/* pos 030f: 409 */ 0x74 /* 't' */, 0x07, 0x00 /* (to 0x0316 state 410) */,
- 0x78 /* 'x' */, 0x09, 0x00 /* (to 0x031B state 414) */,
- 0x08, /* fail */
-/* pos 0316: 410 */ 0xE1 /* 'a' -> */,
-/* pos 0317: 411 */ 0xE7 /* 'g' -> */,
-/* pos 0318: 412 */ 0xBA /* ':' -> */,
-/* pos 0319: 413 */ 0x00, 0x32 /* - terminal marker 50 - */,
-/* pos 031b: 414 */ 0xF0 /* 'p' -> */,
-/* pos 031c: 415 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0323 state 416) */,
- 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x0328 state 420) */,
- 0x08, /* fail */
-/* pos 0323: 416 */ 0xE3 /* 'c' -> */,
-/* pos 0324: 417 */ 0xF4 /* 't' -> */,
-/* pos 0325: 418 */ 0xBA /* ':' -> */,
-/* pos 0326: 419 */ 0x00, 0x33 /* - terminal marker 51 - */,
-/* pos 0328: 420 */ 0xF2 /* 'r' -> */,
-/* pos 0329: 421 */ 0xE5 /* 'e' -> */,
-/* pos 032a: 422 */ 0xF3 /* 's' -> */,
-/* pos 032b: 423 */ 0xBA /* ':' -> */,
-/* pos 032c: 424 */ 0x00, 0x34 /* - terminal marker 52 - */,
-/* pos 032e: 425 */ 0xF2 /* 'r' -> */,
-/* pos 032f: 426 */ 0xEF /* 'o' -> */,
-/* pos 0330: 427 */ 0xED /* 'm' -> */,
-/* pos 0331: 428 */ 0xBA /* ':' -> */,
-/* pos 0332: 429 */ 0x00, 0x35 /* - terminal marker 53 - */,
-/* pos 0334: 430 */ 0xF4 /* 't' -> */,
-/* pos 0335: 431 */ 0xE3 /* 'c' -> */,
-/* pos 0336: 432 */ 0xE8 /* 'h' -> */,
-/* pos 0337: 433 */ 0xBA /* ':' -> */,
-/* pos 0338: 434 */ 0x00, 0x36 /* - terminal marker 54 - */,
-/* pos 033a: 435 */ 0xE1 /* 'a' -> */,
-/* pos 033b: 436 */ 0xEE /* 'n' -> */,
-/* pos 033c: 437 */ 0xE7 /* 'g' -> */,
-/* pos 033d: 438 */ 0xE5 /* 'e' -> */,
-/* pos 033e: 439 */ 0xBA /* ':' -> */,
-/* pos 033f: 440 */ 0x00, 0x37 /* - terminal marker 55 - */,
-/* pos 0341: 441 */ 0xEE /* 'n' -> */,
-/* pos 0342: 442 */ 0xED /* 'm' -> */,
-/* pos 0343: 443 */ 0xEF /* 'o' -> */,
-/* pos 0344: 444 */ 0xE4 /* 'd' -> */,
-/* pos 0345: 445 */ 0xE9 /* 'i' -> */,
-/* pos 0346: 446 */ 0xE6 /* 'f' -> */,
-/* pos 0347: 447 */ 0xE9 /* 'i' -> */,
-/* pos 0348: 448 */ 0xE5 /* 'e' -> */,
-/* pos 0349: 449 */ 0xE4 /* 'd' -> */,
-/* pos 034a: 450 */ 0xAD /* '-' -> */,
-/* pos 034b: 451 */ 0xF3 /* 's' -> */,
-/* pos 034c: 452 */ 0xE9 /* 'i' -> */,
-/* pos 034d: 453 */ 0xEE /* 'n' -> */,
-/* pos 034e: 454 */ 0xE3 /* 'c' -> */,
-/* pos 034f: 455 */ 0xE5 /* 'e' -> */,
-/* pos 0350: 456 */ 0xBA /* ':' -> */,
-/* pos 0351: 457 */ 0x00, 0x38 /* - terminal marker 56 - */,
-/* pos 0353: 458 */ 0x61 /* 'a' */, 0x0A, 0x00 /* (to 0x035D state 459) */,
- 0x69 /* 'i' */, 0x15, 0x00 /* (to 0x036B state 472) */,
- 0x6F /* 'o' */, 0x17, 0x00 /* (to 0x0370 state 476) */,
- 0x08, /* fail */
-/* pos 035d: 459 */ 0xF3 /* 's' -> */,
-/* pos 035e: 460 */ 0xF4 /* 't' -> */,
-/* pos 035f: 461 */ 0xAD /* '-' -> */,
-/* pos 0360: 462 */ 0xED /* 'm' -> */,
-/* pos 0361: 463 */ 0xEF /* 'o' -> */,
-/* pos 0362: 464 */ 0xE4 /* 'd' -> */,
-/* pos 0363: 465 */ 0xE9 /* 'i' -> */,
-/* pos 0364: 466 */ 0xE6 /* 'f' -> */,
-/* pos 0365: 467 */ 0xE9 /* 'i' -> */,
-/* pos 0366: 468 */ 0xE5 /* 'e' -> */,
-/* pos 0367: 469 */ 0xE4 /* 'd' -> */,
-/* pos 0368: 470 */ 0xBA /* ':' -> */,
-/* pos 0369: 471 */ 0x00, 0x39 /* - terminal marker 57 - */,
-/* pos 036b: 472 */ 0xEE /* 'n' -> */,
-/* pos 036c: 473 */ 0xEB /* 'k' -> */,
-/* pos 036d: 474 */ 0xBA /* ':' -> */,
-/* pos 036e: 475 */ 0x00, 0x3A /* - terminal marker 58 - */,
-/* pos 0370: 476 */ 0xE3 /* 'c' -> */,
-/* pos 0371: 477 */ 0xE1 /* 'a' -> */,
-/* pos 0372: 478 */ 0xF4 /* 't' -> */,
-/* pos 0373: 479 */ 0xE9 /* 'i' -> */,
-/* pos 0374: 480 */ 0xEF /* 'o' -> */,
-/* pos 0375: 481 */ 0xEE /* 'n' -> */,
-/* pos 0376: 482 */ 0xBA /* ':' -> */,
-/* pos 0377: 483 */ 0x00, 0x3B /* - terminal marker 59 - */,
-/* pos 0379: 484 */ 0xE1 /* 'a' -> */,
-/* pos 037a: 485 */ 0xF8 /* 'x' -> */,
-/* pos 037b: 486 */ 0xAD /* '-' -> */,
-/* pos 037c: 487 */ 0xE6 /* 'f' -> */,
-/* pos 037d: 488 */ 0xEF /* 'o' -> */,
-/* pos 037e: 489 */ 0xF2 /* 'r' -> */,
-/* pos 037f: 490 */ 0xF7 /* 'w' -> */,
-/* pos 0380: 491 */ 0xE1 /* 'a' -> */,
-/* pos 0381: 492 */ 0xF2 /* 'r' -> */,
-/* pos 0382: 493 */ 0xE4 /* 'd' -> */,
-/* pos 0383: 494 */ 0xF3 /* 's' -> */,
-/* pos 0384: 495 */ 0xBA /* ':' -> */,
-/* pos 0385: 496 */ 0x00, 0x3C /* - terminal marker 60 - */,
-/* pos 0387: 497 */ 0xF8 /* 'x' -> */,
-/* pos 0388: 498 */ 0xF9 /* 'y' -> */,
-/* pos 0389: 499 */ 0x2D /* '-' */, 0x07, 0x00 /* (to 0x0390 state 500) */,
- 0x20 /* ' ' */, 0xBB, 0x00 /* (to 0x0447 state 649) */,
- 0x08, /* fail */
-/* pos 0390: 500 */ 0xE1 /* 'a' -> */,
-/* pos 0391: 501 */ 0xF5 /* 'u' -> */,
-/* pos 0392: 502 */ 0xF4 /* 't' -> */,
-/* pos 0393: 503 */ 0xE8 /* 'h' -> */,
-/* pos 0394: 504 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x039B state 505) */,
- 0x6F /* 'o' */, 0x0E, 0x00 /* (to 0x03A5 state 514) */,
- 0x08, /* fail */
-/* pos 039b: 505 */ 0xEE /* 'n' -> */,
-/* pos 039c: 506 */ 0xF4 /* 't' -> */,
-/* pos 039d: 507 */ 0xE9 /* 'i' -> */,
-/* pos 039e: 508 */ 0xE3 /* 'c' -> */,
-/* pos 039f: 509 */ 0xE1 /* 'a' -> */,
-/* pos 03a0: 510 */ 0xF4 /* 't' -> */,
-/* pos 03a1: 511 */ 0xE5 /* 'e' -> */,
-/* pos 03a2: 512 */ 0xBA /* ':' -> */,
-/* pos 03a3: 513 */ 0x00, 0x3D /* - terminal marker 61 - */,
-/* pos 03a5: 514 */ 0xF2 /* 'r' -> */,
-/* pos 03a6: 515 */ 0xE9 /* 'i' -> */,
-/* pos 03a7: 516 */ 0xFA /* 'z' -> */,
-/* pos 03a8: 517 */ 0xE1 /* 'a' -> */,
-/* pos 03a9: 518 */ 0xF4 /* 't' -> */,
-/* pos 03aa: 519 */ 0xE9 /* 'i' -> */,
-/* pos 03ab: 520 */ 0xEF /* 'o' -> */,
-/* pos 03ac: 521 */ 0xEE /* 'n' -> */,
-/* pos 03ad: 522 */ 0xBA /* ':' -> */,
-/* pos 03ae: 523 */ 0x00, 0x3E /* - terminal marker 62 - */,
-/* pos 03b0: 524 */ 0xE5 /* 'e' -> */,
-/* pos 03b1: 525 */ 0xF3 /* 's' -> */,
-/* pos 03b2: 526 */ 0xE8 /* 'h' -> */,
-/* pos 03b3: 527 */ 0xBA /* ':' -> */,
-/* pos 03b4: 528 */ 0x00, 0x3F /* - terminal marker 63 - */,
-/* pos 03b6: 529 */ 0xF2 /* 'r' -> */,
-/* pos 03b7: 530 */ 0xF9 /* 'y' -> */,
-/* pos 03b8: 531 */ 0xAD /* '-' -> */,
-/* pos 03b9: 532 */ 0xE1 /* 'a' -> */,
-/* pos 03ba: 533 */ 0xE6 /* 'f' -> */,
-/* pos 03bb: 534 */ 0xF4 /* 't' -> */,
-/* pos 03bc: 535 */ 0xE5 /* 'e' -> */,
-/* pos 03bd: 536 */ 0xF2 /* 'r' -> */,
-/* pos 03be: 537 */ 0xBA /* ':' -> */,
-/* pos 03bf: 538 */ 0x00, 0x40 /* - terminal marker 64 - */,
-/* pos 03c1: 539 */ 0xF6 /* 'v' -> */,
-/* pos 03c2: 540 */ 0xE5 /* 'e' -> */,
-/* pos 03c3: 541 */ 0xF2 /* 'r' -> */,
-/* pos 03c4: 542 */ 0xBA /* ':' -> */,
-/* pos 03c5: 543 */ 0x00, 0x41 /* - terminal marker 65 - */,
-/* pos 03c7: 544 */ 0xAD /* '-' -> */,
-/* pos 03c8: 545 */ 0xE3 /* 'c' -> */,
-/* pos 03c9: 546 */ 0xEF /* 'o' -> */,
-/* pos 03ca: 547 */ 0xEF /* 'o' -> */,
-/* pos 03cb: 548 */ 0xEB /* 'k' -> */,
-/* pos 03cc: 549 */ 0xE9 /* 'i' -> */,
-/* pos 03cd: 550 */ 0xE5 /* 'e' -> */,
-/* pos 03ce: 551 */ 0xBA /* ':' -> */,
-/* pos 03cf: 552 */ 0x00, 0x42 /* - terminal marker 66 - */,
-/* pos 03d1: 553 */ 0xF2 /* 'r' -> */,
-/* pos 03d2: 554 */ 0xE9 /* 'i' -> */,
-/* pos 03d3: 555 */ 0xE3 /* 'c' -> */,
-/* pos 03d4: 556 */ 0xF4 /* 't' -> */,
-/* pos 03d5: 557 */ 0xAD /* '-' -> */,
-/* pos 03d6: 558 */ 0xF4 /* 't' -> */,
-/* pos 03d7: 559 */ 0xF2 /* 'r' -> */,
-/* pos 03d8: 560 */ 0xE1 /* 'a' -> */,
-/* pos 03d9: 561 */ 0xEE /* 'n' -> */,
-/* pos 03da: 562 */ 0xF3 /* 's' -> */,
-/* pos 03db: 563 */ 0xF0 /* 'p' -> */,
-/* pos 03dc: 564 */ 0xEF /* 'o' -> */,
-/* pos 03dd: 565 */ 0xF2 /* 'r' -> */,
-/* pos 03de: 566 */ 0xF4 /* 't' -> */,
-/* pos 03df: 567 */ 0xAD /* '-' -> */,
-/* pos 03e0: 568 */ 0xF3 /* 's' -> */,
-/* pos 03e1: 569 */ 0xE5 /* 'e' -> */,
-/* pos 03e2: 570 */ 0xE3 /* 'c' -> */,
-/* pos 03e3: 571 */ 0xF5 /* 'u' -> */,
-/* pos 03e4: 572 */ 0xF2 /* 'r' -> */,
-/* pos 03e5: 573 */ 0xE9 /* 'i' -> */,
-/* pos 03e6: 574 */ 0xF4 /* 't' -> */,
-/* pos 03e7: 575 */ 0xF9 /* 'y' -> */,
-/* pos 03e8: 576 */ 0xBA /* ':' -> */,
-/* pos 03e9: 577 */ 0x00, 0x43 /* - terminal marker 67 - */,
-/* pos 03eb: 578 */ 0x72 /* 'r' */, 0x07, 0x00 /* (to 0x03F2 state 579) */,
- 0x65 /* 'e' */, 0x87, 0x00 /* (to 0x0475 state 680) */,
- 0x08, /* fail */
-/* pos 03f2: 579 */ 0xE1 /* 'a' -> */,
-/* pos 03f3: 580 */ 0xEE /* 'n' -> */,
-/* pos 03f4: 581 */ 0xF3 /* 's' -> */,
-/* pos 03f5: 582 */ 0xE6 /* 'f' -> */,
-/* pos 03f6: 583 */ 0xE5 /* 'e' -> */,
-/* pos 03f7: 584 */ 0xF2 /* 'r' -> */,
-/* pos 03f8: 585 */ 0xAD /* '-' -> */,
-/* pos 03f9: 586 */ 0xE5 /* 'e' -> */,
-/* pos 03fa: 587 */ 0xEE /* 'n' -> */,
-/* pos 03fb: 588 */ 0xE3 /* 'c' -> */,
-/* pos 03fc: 589 */ 0xEF /* 'o' -> */,
-/* pos 03fd: 590 */ 0xE4 /* 'd' -> */,
-/* pos 03fe: 591 */ 0xE9 /* 'i' -> */,
-/* pos 03ff: 592 */ 0xEE /* 'n' -> */,
-/* pos 0400: 593 */ 0xE7 /* 'g' -> */,
-/* pos 0401: 594 */ 0xBA /* ':' -> */,
-/* pos 0402: 595 */ 0x00, 0x44 /* - terminal marker 68 - */,
-/* pos 0404: 596 */ 0xE5 /* 'e' -> */,
-/* pos 0405: 597 */ 0xF2 /* 'r' -> */,
-/* pos 0406: 598 */ 0xAD /* '-' -> */,
-/* pos 0407: 599 */ 0xE1 /* 'a' -> */,
-/* pos 0408: 600 */ 0xE7 /* 'g' -> */,
-/* pos 0409: 601 */ 0xE5 /* 'e' -> */,
-/* pos 040a: 602 */ 0xEE /* 'n' -> */,
-/* pos 040b: 603 */ 0xF4 /* 't' -> */,
-/* pos 040c: 604 */ 0xBA /* ':' -> */,
-/* pos 040d: 605 */ 0x00, 0x45 /* - terminal marker 69 - */,
-/* pos 040f: 606 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0416 state 607) */,
- 0x69 /* 'i' */, 0x09, 0x00 /* (to 0x041B state 611) */,
- 0x08, /* fail */
-/* pos 0416: 607 */ 0xF2 /* 'r' -> */,
-/* pos 0417: 608 */ 0xF9 /* 'y' -> */,
-/* pos 0418: 609 */ 0xBA /* ':' -> */,
-/* pos 0419: 610 */ 0x00, 0x46 /* - terminal marker 70 - */,
-/* pos 041b: 611 */ 0xE1 /* 'a' -> */,
-/* pos 041c: 612 */ 0xBA /* ':' -> */,
-/* pos 041d: 613 */ 0x00, 0x47 /* - terminal marker 71 - */,
-/* pos 041f: 614 */ 0xF7 /* 'w' -> */,
-/* pos 0420: 615 */ 0xF7 /* 'w' -> */,
-/* pos 0421: 616 */ 0xAD /* '-' -> */,
-/* pos 0422: 617 */ 0xE1 /* 'a' -> */,
-/* pos 0423: 618 */ 0xF5 /* 'u' -> */,
-/* pos 0424: 619 */ 0xF4 /* 't' -> */,
-/* pos 0425: 620 */ 0xE8 /* 'h' -> */,
-/* pos 0426: 621 */ 0xE5 /* 'e' -> */,
-/* pos 0427: 622 */ 0xEE /* 'n' -> */,
-/* pos 0428: 623 */ 0xF4 /* 't' -> */,
-/* pos 0429: 624 */ 0xE9 /* 'i' -> */,
-/* pos 042a: 625 */ 0xE3 /* 'c' -> */,
-/* pos 042b: 626 */ 0xE1 /* 'a' -> */,
-/* pos 042c: 627 */ 0xF4 /* 't' -> */,
-/* pos 042d: 628 */ 0xE5 /* 'e' -> */,
-/* pos 042e: 629 */ 0xBA /* ':' -> */,
-/* pos 042f: 630 */ 0x00, 0x48 /* - terminal marker 72 - */,
-/* pos 0431: 631 */ 0xF4 /* 't' -> */,
-/* pos 0432: 632 */ 0xE3 /* 'c' -> */,
-/* pos 0433: 633 */ 0xE8 /* 'h' -> */,
-/* pos 0434: 634 */ 0x00, 0x49 /* - terminal marker 73 - */,
-/* pos 0436: 635 */ 0xF4 /* 't' -> */,
-/* pos 0437: 636 */ 0x00, 0x4A /* - terminal marker 74 - */,
-/* pos 0439: 637 */ 0xEC /* 'l' -> */,
-/* pos 043a: 638 */ 0xE5 /* 'e' -> */,
-/* pos 043b: 639 */ 0xF4 /* 't' -> */,
-/* pos 043c: 640 */ 0xE5 /* 'e' -> */,
-/* pos 043d: 641 */ 0x00, 0x4B /* - terminal marker 75 - */,
-/* pos 043f: 642 */ 0xE9 /* 'i' -> */,
-/* pos 0440: 643 */ 0xAD /* '-' -> */,
-/* pos 0441: 644 */ 0xE1 /* 'a' -> */,
-/* pos 0442: 645 */ 0xF2 /* 'r' -> */,
-/* pos 0443: 646 */ 0xE7 /* 'g' -> */,
-/* pos 0444: 647 */ 0xF3 /* 's' -> */,
-/* pos 0445: 648 */ 0x00, 0x4C /* - terminal marker 76 - */,
-/* pos 0447: 649 */ 0x00, 0x4D /* - terminal marker 77 - */,
-/* pos 0449: 650 */ 0xAD /* '-' -> */,
-/* pos 044a: 651 */ 0x72 /* 'r' */, 0x0A, 0x00 /* (to 0x0454 state 652) */,
- 0x66 /* 'f' */, 0x13, 0x00 /* (to 0x0460 state 662) */,
- 0x61 /* 'a' */, 0x3C, 0x00 /* (to 0x048C state 700) */,
- 0x08, /* fail */
-/* pos 0454: 652 */ 0xE5 /* 'e' -> */,
-/* pos 0455: 653 */ 0xE1 /* 'a' -> */,
-/* pos 0456: 654 */ 0xEC /* 'l' -> */,
-/* pos 0457: 655 */ 0xAD /* '-' -> */,
-/* pos 0458: 656 */ 0xE9 /* 'i' -> */,
-/* pos 0459: 657 */ 0xF0 /* 'p' -> */,
-/* pos 045a: 658 */ 0xBA /* ':' -> */,
-/* pos 045b: 659 */ 0x00, 0x4E /* - terminal marker 78 - */,
-/* pos 045d: 660 */ 0xA0 /* ' ' -> */,
-/* pos 045e: 661 */ 0x00, 0x4F /* - terminal marker 79 - */,
-/* pos 0460: 662 */ 0xEF /* 'o' -> */,
-/* pos 0461: 663 */ 0xF2 /* 'r' -> */,
-/* pos 0462: 664 */ 0xF7 /* 'w' -> */,
-/* pos 0463: 665 */ 0xE1 /* 'a' -> */,
-/* pos 0464: 666 */ 0xF2 /* 'r' -> */,
-/* pos 0465: 667 */ 0xE4 /* 'd' -> */,
-/* pos 0466: 668 */ 0xE5 /* 'e' -> */,
-/* pos 0467: 669 */ 0xE4 /* 'd' -> */,
-/* pos 0468: 670 */ 0xAD /* '-' -> */,
-/* pos 0469: 671 */ 0xE6 /* 'f' -> */,
-/* pos 046a: 672 */ 0xEF /* 'o' -> */,
-/* pos 046b: 673 */ 0xF2 /* 'r' -> */,
-/* pos 046c: 674 */ 0x00, 0x50 /* - terminal marker 80 - */,
-/* pos 046e: 675 */ 0x00, 0x51 /* - terminal marker 81 - */,
-/* pos 0470: 676 */ 0xE1 /* 'a' -> */,
-/* pos 0471: 677 */ 0xE4 /* 'd' -> */,
-/* pos 0472: 678 */ 0xA0 /* ' ' -> */,
-/* pos 0473: 679 */ 0x00, 0x52 /* - terminal marker 82 - */,
-/* pos 0475: 680 */ 0xBA /* ':' -> */,
-/* pos 0476: 681 */ 0x00, 0x53 /* - terminal marker 83 - */,
-/* pos 0478: 682 */ 0xEC /* 'l' -> */,
-/* pos 0479: 683 */ 0xE1 /* 'a' -> */,
-/* pos 047a: 684 */ 0xF9 /* 'y' -> */,
-/* pos 047b: 685 */ 0xAD /* '-' -> */,
-/* pos 047c: 686 */ 0xEE /* 'n' -> */,
-/* pos 047d: 687 */ 0xEF /* 'o' -> */,
-/* pos 047e: 688 */ 0xEE /* 'n' -> */,
-/* pos 047f: 689 */ 0xE3 /* 'c' -> */,
-/* pos 0480: 690 */ 0xE5 /* 'e' -> */,
-/* pos 0481: 691 */ 0xBA /* ':' -> */,
-/* pos 0482: 692 */ 0x00, 0x54 /* - terminal marker 84 - */,
-/* pos 0484: 693 */ 0xEF /* 'o' -> */,
-/* pos 0485: 694 */ 0xF4 /* 't' -> */,
-/* pos 0486: 695 */ 0xEF /* 'o' -> */,
-/* pos 0487: 696 */ 0xE3 /* 'c' -> */,
-/* pos 0488: 697 */ 0xEF /* 'o' -> */,
-/* pos 0489: 698 */ 0xEC /* 'l' -> */,
-/* pos 048a: 699 */ 0x00, 0x55 /* - terminal marker 85 - */,
-/* pos 048c: 700 */ 0xF5 /* 'u' -> */,
-/* pos 048d: 701 */ 0xF4 /* 't' -> */,
-/* pos 048e: 702 */ 0xE8 /* 'h' -> */,
-/* pos 048f: 703 */ 0xAD /* '-' -> */,
-/* pos 0490: 704 */ 0xF4 /* 't' -> */,
-/* pos 0491: 705 */ 0xEF /* 'o' -> */,
-/* pos 0492: 706 */ 0xEB /* 'k' -> */,
-/* pos 0493: 707 */ 0xE5 /* 'e' -> */,
-/* pos 0494: 708 */ 0xEE /* 'n' -> */,
-/* pos 0495: 709 */ 0xBA /* ':' -> */,
-/* pos 0496: 710 */ 0x00, 0x56 /* - terminal marker 86 - */,
-/* total size 1176 bytes */
diff --git a/thirdparty/libwebsockets/roles/http/private.h b/thirdparty/libwebsockets/roles/http/private.h
deleted file mode 100644
index 5699914742..0000000000
--- a/thirdparty/libwebsockets/roles/http/private.h
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010 - 2018 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * This is included from core/private.h if either H1 or H2 roles are
- * enabled
- */
-
-#if defined(LWS_WITH_HTTP_PROXY)
- #include <hubbub/hubbub.h>
- #include <hubbub/parser.h>
- #endif
-
-#define lwsi_role_http(wsi) (lwsi_role_h1(wsi) || lwsi_role_h2(wsi))
-
-enum http_version {
- HTTP_VERSION_1_0,
- HTTP_VERSION_1_1,
- HTTP_VERSION_2
-};
-
-enum http_connection_type {
- HTTP_CONNECTION_CLOSE,
- HTTP_CONNECTION_KEEP_ALIVE
-};
-
-/*
- * This is totally opaque to code using the library. It's exported as a
- * forward-reference pointer-only declaration; the user can use the pointer with
- * other APIs to get information out of it.
- */
-
-#if defined(LWS_WITH_ESP32)
-typedef uint16_t ah_data_idx_t;
-#else
-typedef uint32_t ah_data_idx_t;
-#endif
-
-struct lws_fragments {
- ah_data_idx_t offset;
- uint16_t len;
- uint8_t nfrag; /* which ah->frag[] continues this content, or 0 */
- uint8_t flags; /* only http2 cares */
-};
-
-#if defined(LWS_WITH_RANGES)
-enum range_states {
- LWSRS_NO_ACTIVE_RANGE,
- LWSRS_BYTES_EQ,
- LWSRS_FIRST,
- LWSRS_STARTING,
- LWSRS_ENDING,
- LWSRS_COMPLETED,
- LWSRS_SYNTAX,
-};
-
-struct lws_range_parsing {
- unsigned long long start, end, extent, agg, budget;
- const char buf[128];
- int pos;
- enum range_states state;
- char start_valid, end_valid, ctr, count_ranges, did_try, inside, send_ctr;
-};
-
-int
-lws_ranges_init(struct lws *wsi, struct lws_range_parsing *rp,
- unsigned long long extent);
-int
-lws_ranges_next(struct lws_range_parsing *rp);
-void
-lws_ranges_reset(struct lws_range_parsing *rp);
-#endif
-
-/*
- * these are assigned from a pool held in the context.
- * Both client and server mode uses them for http header analysis
- */
-
-struct allocated_headers {
- struct allocated_headers *next; /* linked list */
- struct lws *wsi; /* owner */
- char *data; /* prepared by context init to point to dedicated storage */
- ah_data_idx_t data_length;
- /*
- * the randomly ordered fragments, indexed by frag_index and
- * lws_fragments->nfrag for continuation.
- */
- struct lws_fragments frags[WSI_TOKEN_COUNT];
- time_t assigned;
- /*
- * for each recognized token, frag_index says which frag[] his data
- * starts in (0 means the token did not appear)
- * the actual header data gets dumped as it comes in, into data[]
- */
- uint8_t frag_index[WSI_TOKEN_COUNT];
-
-#ifndef LWS_NO_CLIENT
- char initial_handshake_hash_base64[30];
-#endif
-
- uint32_t pos;
- uint32_t http_response;
- uint32_t current_token_limit;
- int hdr_token_idx;
-
- int16_t lextable_pos;
-
- uint8_t in_use;
- uint8_t nfrag;
- char /*enum uri_path_states */ ups;
- char /*enum uri_esc_states */ ues;
-
- char esc_stash;
- char post_literal_equal;
- uint8_t /* enum lws_token_indexes */ parser_state;
-};
-
-
-
-#if defined(LWS_WITH_HTTP_PROXY)
-struct lws_rewrite {
- hubbub_parser *parser;
- hubbub_parser_optparams params;
- const char *from, *to;
- int from_len, to_len;
- unsigned char *p, *end;
- struct lws *wsi;
-};
-static LWS_INLINE int hstrcmp(hubbub_string *s, const char *p, int len)
-{
- if ((int)s->len != len)
- return 1;
-
- return strncmp((const char *)s->ptr, p, len);
-}
-typedef hubbub_error (*hubbub_callback_t)(const hubbub_token *token, void *pw);
-LWS_EXTERN struct lws_rewrite *
-lws_rewrite_create(struct lws *wsi, hubbub_callback_t cb, const char *from, const char *to);
-LWS_EXTERN void
-lws_rewrite_destroy(struct lws_rewrite *r);
-LWS_EXTERN int
-lws_rewrite_parse(struct lws_rewrite *r, const unsigned char *in, int in_len);
-#endif
-
-struct lws_pt_role_http {
- struct allocated_headers *ah_list;
- struct lws *ah_wait_list;
-#ifdef LWS_WITH_CGI
- struct lws_cgi *cgi_list;
-#endif
- int ah_wait_list_length;
- uint32_t ah_pool_length;
-
- int ah_count_in_use;
-};
-
-struct lws_peer_role_http {
- uint32_t count_ah;
- uint32_t total_ah;
-};
-
-struct lws_vhost_role_http {
- char http_proxy_address[128];
- const struct lws_http_mount *mount_list;
- const char *error_document_404;
- unsigned int http_proxy_port;
-};
-
-#ifdef LWS_WITH_ACCESS_LOG
-struct lws_access_log {
- char *header_log;
- char *user_agent;
- char *referrer;
- unsigned long sent;
- int response;
-};
-#endif
-
-struct _lws_http_mode_related {
- struct lws *new_wsi_list;
-
-#if defined(LWS_WITH_HTTP_PROXY)
- struct lws_rewrite *rw;
-#endif
- struct allocated_headers *ah;
- struct lws *ah_wait_list;
-
- lws_filepos_t filepos;
- lws_filepos_t filelen;
- lws_fop_fd_t fop_fd;
-
-#if defined(LWS_WITH_RANGES)
- struct lws_range_parsing range;
- char multipart_content_type[64];
-#endif
-
-#ifdef LWS_WITH_ACCESS_LOG
- struct lws_access_log access_log;
-#endif
-#ifdef LWS_WITH_CGI
- struct lws_cgi *cgi; /* wsi being cgi master have one of these */
-#endif
-
- enum http_version request_version;
- enum http_connection_type connection_type;
- lws_filepos_t tx_content_length;
- lws_filepos_t tx_content_remain;
- lws_filepos_t rx_content_length;
- lws_filepos_t rx_content_remain;
-
-#if defined(LWS_WITH_HTTP_PROXY)
- unsigned int perform_rewrite:1;
-#endif
- unsigned int deferred_transaction_completed:1;
-};
-
-
-#ifndef LWS_NO_CLIENT
-enum lws_chunk_parser {
- ELCP_HEX,
- ELCP_CR,
- ELCP_CONTENT,
- ELCP_POST_CR,
- ELCP_POST_LF,
-};
-#endif
-
-enum lws_parse_urldecode_results {
- LPUR_CONTINUE,
- LPUR_SWALLOW,
- LPUR_FORBID,
- LPUR_EXCESSIVE,
-};
-
-int
-lws_read_h1(struct lws *wsi, unsigned char *buf, lws_filepos_t len);
-
-void
-_lws_header_table_reset(struct allocated_headers *ah);
-
-LWS_EXTERN int
-_lws_destroy_ah(struct lws_context_per_thread *pt, struct allocated_headers *ah);
diff --git a/thirdparty/libwebsockets/roles/http/server/access-log.c b/thirdparty/libwebsockets/roles/http/server/access-log.c
deleted file mode 100644
index 0e75309d7a..0000000000
--- a/thirdparty/libwebsockets/roles/http/server/access-log.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * libwebsockets - server access log handling
- *
- * Copyright (C) 2010-2017 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- */
-
-#include "core/private.h"
-
-/*
- * Produce Apache-compatible log string for wsi, like this:
- *
- * 2.31.234.19 - - [27/Mar/2016:03:22:44 +0800]
- * "GET /aep-screen.png HTTP/1.1"
- * 200 152987 "https://libwebsockets.org/index.html"
- * "Mozilla/5.0 (Macint... Chrome/49.0.2623.87 Safari/537.36"
- *
- */
-
-extern const char * const method_names[];
-
-static const char * const hver[] = {
- "HTTP/1.0", "HTTP/1.1", "HTTP/2"
-};
-
-void
-lws_prepare_access_log_info(struct lws *wsi, char *uri_ptr, int meth)
-{
-#ifdef LWS_WITH_IPV6
- char ads[INET6_ADDRSTRLEN];
-#else
- char ads[INET_ADDRSTRLEN];
-#endif
- char da[64];
- const char *pa, *me;
- struct tm *tmp;
- time_t t = time(NULL);
- int l = 256, m;
-
- if (!wsi->vhost)
- return;
-
- /* only worry about preparing it if we store it */
- if (wsi->vhost->log_fd == (int)LWS_INVALID_FILE)
- return;
-
- if (wsi->access_log_pending)
- lws_access_log(wsi);
-
- wsi->http.access_log.header_log = lws_malloc(l, "access log");
- if (wsi->http.access_log.header_log) {
-
- tmp = localtime(&t);
- if (tmp)
- strftime(da, sizeof(da), "%d/%b/%Y:%H:%M:%S %z", tmp);
- else
- strcpy(da, "01/Jan/1970:00:00:00 +0000");
-
- pa = lws_get_peer_simple(wsi, ads, sizeof(ads));
- if (!pa)
- pa = "(unknown)";
-
- if (wsi->http2_substream)
- me = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_METHOD);
- else
- me = method_names[meth];
- if (!me)
- me = "(null)";
-
- lws_snprintf(wsi->http.access_log.header_log, l,
- "%s - - [%s] \"%s %s %s\"",
- pa, da, me, uri_ptr,
- hver[wsi->http.request_version]);
-
- l = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_USER_AGENT);
- if (l) {
- wsi->http.access_log.user_agent = lws_malloc(l + 2, "access log");
- if (!wsi->http.access_log.user_agent) {
- lwsl_err("OOM getting user agent\n");
- lws_free_set_NULL(wsi->http.access_log.header_log);
- return;
- }
-
- lws_hdr_copy(wsi, wsi->http.access_log.user_agent,
- l + 1, WSI_TOKEN_HTTP_USER_AGENT);
-
- for (m = 0; m < l; m++)
- if (wsi->http.access_log.user_agent[m] == '\"')
- wsi->http.access_log.user_agent[m] = '\'';
- }
- l = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_REFERER);
- if (l) {
- wsi->http.access_log.referrer = lws_malloc(l + 2, "referrer");
- if (!wsi->http.access_log.referrer) {
- lwsl_err("OOM getting user agent\n");
- lws_free_set_NULL(wsi->http.access_log.user_agent);
- lws_free_set_NULL(wsi->http.access_log.header_log);
- return;
- }
- lws_hdr_copy(wsi, wsi->http.access_log.referrer,
- l + 1, WSI_TOKEN_HTTP_REFERER);
-
- for (m = 0; m < l; m++)
- if (wsi->http.access_log.referrer[m] == '\"')
- wsi->http.access_log.referrer[m] = '\'';
- }
- wsi->access_log_pending = 1;
- }
-}
-
-
-int
-lws_access_log(struct lws *wsi)
-{
- char *p = wsi->http.access_log.user_agent, ass[512],
- *p1 = wsi->http.access_log.referrer;
- int l;
-
- if (!wsi->vhost)
- return 0;
-
- if (wsi->vhost->log_fd == (int)LWS_INVALID_FILE)
- return 0;
-
- if (!wsi->access_log_pending)
- return 0;
-
- if (!wsi->http.access_log.header_log)
- return 0;
-
- if (!p)
- p = "";
-
- if (!p1)
- p1 = "";
-
- /*
- * We do this in two parts to restrict an oversize referrer such that
- * we will always have space left to append an empty useragent, while
- * maintaining the structure of the log text
- */
- l = lws_snprintf(ass, sizeof(ass) - 7, "%s %d %lu \"%s",
- wsi->http.access_log.header_log,
- wsi->http.access_log.response, wsi->http.access_log.sent, p1);
- if (strlen(p) > sizeof(ass) - 6 - l)
- p[sizeof(ass) - 6 - l] = '\0';
- l += lws_snprintf(ass + l, sizeof(ass) - 1 - l, "\" \"%s\"\n", p);
-
- if (write(wsi->vhost->log_fd, ass, l) != l)
- lwsl_err("Failed to write log\n");
-
- if (wsi->http.access_log.header_log) {
- lws_free(wsi->http.access_log.header_log);
- wsi->http.access_log.header_log = NULL;
- }
- if (wsi->http.access_log.user_agent) {
- lws_free(wsi->http.access_log.user_agent);
- wsi->http.access_log.user_agent = NULL;
- }
- if (wsi->http.access_log.referrer) {
- lws_free(wsi->http.access_log.referrer);
- wsi->http.access_log.referrer = NULL;
- }
- wsi->access_log_pending = 0;
-
- return 0;
-}
-
diff --git a/thirdparty/libwebsockets/roles/http/server/fops-zip.c b/thirdparty/libwebsockets/roles/http/server/fops-zip.c
deleted file mode 100644
index 4db83ce621..0000000000
--- a/thirdparty/libwebsockets/roles/http/server/fops-zip.c
+++ /dev/null
@@ -1,668 +0,0 @@
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Original code used in this source file:
- *
- * https://github.com/PerBothner/DomTerm.git @912add15f3d0aec
- *
- * ./lws-term/io.c
- * ./lws-term/junzip.c
- *
- * Copyright (C) 2017 Per Bothner <per@bothner.com>
- *
- * MIT License
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * ( copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- *
- * lws rewrite:
- *
- * Copyright (C) 2017 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- */
-
-#include "core/private.h"
-
-#include <zlib.h>
-
-/*
- * This code works with zip format containers which may have files compressed
- * with gzip deflate (type 8) or store uncompressed (type 0).
- *
- * Linux zip produces such zipfiles by default, eg
- *
- * $ zip ../myzip.zip file1 file2 file3
- */
-
-#define ZIP_COMPRESSION_METHOD_STORE 0
-#define ZIP_COMPRESSION_METHOD_DEFLATE 8
-
-typedef struct {
- lws_filepos_t filename_start;
- uint32_t crc32;
- uint32_t comp_size;
- uint32_t uncomp_size;
- uint32_t offset;
- uint32_t mod_time;
- uint16_t filename_len;
- uint16_t extra;
- uint16_t method;
- uint16_t file_com_len;
-} lws_fops_zip_hdr_t;
-
-typedef struct {
- struct lws_fop_fd fop_fd; /* MUST BE FIRST logical fop_fd into
- * file inside zip: fops_zip fops */
- lws_fop_fd_t zip_fop_fd; /* logical fop fd on to zip file
- * itself: using platform fops */
- lws_fops_zip_hdr_t hdr;
- z_stream inflate;
- lws_filepos_t content_start;
- lws_filepos_t exp_uncomp_pos;
- union {
- uint8_t trailer8[8];
- uint32_t trailer32[2];
- } u;
- uint8_t rbuf[128]; /* decompression chunk size */
- int entry_count;
-
- unsigned int decompress:1; /* 0 = direct from file */
- unsigned int add_gzip_container:1;
-} *lws_fops_zip_t;
-
-struct lws_plat_file_ops fops_zip;
-#define fop_fd_to_priv(FD) ((lws_fops_zip_t)(FD))
-
-static const uint8_t hd[] = { 31, 139, 8, 0, 0, 0, 0, 0, 0, 3 };
-
-enum {
- ZC_SIGNATURE = 0,
- ZC_VERSION_MADE_BY = 4,
- ZC_VERSION_NEEDED_TO_EXTRACT = 6,
- ZC_GENERAL_PURPOSE_BIT_FLAG = 8,
- ZC_COMPRESSION_METHOD = 10,
- ZC_LAST_MOD_FILE_TIME = 12,
- ZC_LAST_MOD_FILE_DATE = 14,
- ZC_CRC32 = 16,
- ZC_COMPRESSED_SIZE = 20,
- ZC_UNCOMPRESSED_SIZE = 24,
- ZC_FILE_NAME_LENGTH = 28,
- ZC_EXTRA_FIELD_LENGTH = 30,
-
- ZC_FILE_COMMENT_LENGTH = 32,
- ZC_DISK_NUMBER_START = 34,
- ZC_INTERNAL_FILE_ATTRIBUTES = 36,
- ZC_EXTERNAL_FILE_ATTRIBUTES = 38,
- ZC_REL_OFFSET_LOCAL_HEADER = 42,
- ZC_DIRECTORY_LENGTH = 46,
-
- ZE_SIGNATURE_OFFSET = 0,
- ZE_DESK_NUMBER = 4,
- ZE_CENTRAL_DIRECTORY_DISK_NUMBER = 6,
- ZE_NUM_ENTRIES_THIS_DISK = 8,
- ZE_NUM_ENTRIES = 10,
- ZE_CENTRAL_DIRECTORY_SIZE = 12,
- ZE_CENTRAL_DIR_OFFSET = 16,
- ZE_ZIP_COMMENT_LENGTH = 20,
- ZE_DIRECTORY_LENGTH = 22,
-
- ZL_REL_OFFSET_CONTENT = 28,
- ZL_HEADER_LENGTH = 30,
-
- LWS_FZ_ERR_SEEK_END_RECORD = 1,
- LWS_FZ_ERR_READ_END_RECORD,
- LWS_FZ_ERR_END_RECORD_MAGIC,
- LWS_FZ_ERR_END_RECORD_SANITY,
- LWS_FZ_ERR_CENTRAL_SEEK,
- LWS_FZ_ERR_CENTRAL_READ,
- LWS_FZ_ERR_CENTRAL_SANITY,
- LWS_FZ_ERR_NAME_TOO_LONG,
- LWS_FZ_ERR_NAME_SEEK,
- LWS_FZ_ERR_NAME_READ,
- LWS_FZ_ERR_CONTENT_SANITY,
- LWS_FZ_ERR_CONTENT_SEEK,
- LWS_FZ_ERR_SCAN_SEEK,
- LWS_FZ_ERR_NOT_FOUND,
- LWS_FZ_ERR_ZLIB_INIT,
- LWS_FZ_ERR_READ_CONTENT,
- LWS_FZ_ERR_SEEK_COMPRESSED,
-};
-
-static uint16_t
-get_u16(void *p)
-{
- const uint8_t *c = (const uint8_t *)p;
-
- return (uint16_t)((c[0] | (c[1] << 8)));
-}
-
-static uint32_t
-get_u32(void *p)
-{
- const uint8_t *c = (const uint8_t *)p;
-
- return (uint32_t)((c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24)));
-}
-
-int
-lws_fops_zip_scan(lws_fops_zip_t priv, const char *name, int len)
-{
- lws_filepos_t amount;
- uint8_t buf[96];
- int i;
-
- if (lws_vfs_file_seek_end(priv->zip_fop_fd, -ZE_DIRECTORY_LENGTH) < 0)
- return LWS_FZ_ERR_SEEK_END_RECORD;
-
- if (lws_vfs_file_read(priv->zip_fop_fd, &amount, buf,
- ZE_DIRECTORY_LENGTH))
- return LWS_FZ_ERR_READ_END_RECORD;
-
- if (amount != ZE_DIRECTORY_LENGTH)
- return LWS_FZ_ERR_READ_END_RECORD;
-
- /*
- * We require the zip to have the last record right at the end
- * Linux zip always does this if no zip comment.
- */
- if (buf[0] != 'P' || buf[1] != 'K' || buf[2] != 5 || buf[3] != 6)
- return LWS_FZ_ERR_END_RECORD_MAGIC;
-
- i = get_u16(buf + ZE_NUM_ENTRIES);
-
- if (get_u16(buf + ZE_DESK_NUMBER) ||
- get_u16(buf + ZE_CENTRAL_DIRECTORY_DISK_NUMBER) ||
- i != get_u16(buf + ZE_NUM_ENTRIES_THIS_DISK))
- return LWS_FZ_ERR_END_RECORD_SANITY;
-
- /* end record is OK... look for our file in the central dir */
-
- if (lws_vfs_file_seek_set(priv->zip_fop_fd,
- get_u32(buf + ZE_CENTRAL_DIR_OFFSET)) < 0)
- return LWS_FZ_ERR_CENTRAL_SEEK;
-
- while (i--) {
- priv->content_start = lws_vfs_tell(priv->zip_fop_fd);
-
- if (lws_vfs_file_read(priv->zip_fop_fd, &amount, buf,
- ZC_DIRECTORY_LENGTH))
- return LWS_FZ_ERR_CENTRAL_READ;
-
- if (amount != ZC_DIRECTORY_LENGTH)
- return LWS_FZ_ERR_CENTRAL_READ;
-
- if (get_u32(buf + ZC_SIGNATURE) != 0x02014B50)
- return LWS_FZ_ERR_CENTRAL_SANITY;
-
- lwsl_debug("cstart 0x%lx\n", (unsigned long)priv->content_start);
-
- priv->hdr.filename_len = get_u16(buf + ZC_FILE_NAME_LENGTH);
- priv->hdr.extra = get_u16(buf + ZC_EXTRA_FIELD_LENGTH);
- priv->hdr.filename_start = lws_vfs_tell(priv->zip_fop_fd);
-
- priv->hdr.method = get_u16(buf + ZC_COMPRESSION_METHOD);
- priv->hdr.crc32 = get_u32(buf + ZC_CRC32);
- priv->hdr.comp_size = get_u32(buf + ZC_COMPRESSED_SIZE);
- priv->hdr.uncomp_size = get_u32(buf + ZC_UNCOMPRESSED_SIZE);
- priv->hdr.offset = get_u32(buf + ZC_REL_OFFSET_LOCAL_HEADER);
- priv->hdr.mod_time = get_u32(buf + ZC_LAST_MOD_FILE_TIME);
- priv->hdr.file_com_len = get_u16(buf + ZC_FILE_COMMENT_LENGTH);
-
- if (priv->hdr.filename_len != len)
- goto next;
-
- if (len >= (int)sizeof(buf) - 1)
- return LWS_FZ_ERR_NAME_TOO_LONG;
-
- if (priv->zip_fop_fd->fops->LWS_FOP_READ(priv->zip_fop_fd,
- &amount, buf, len))
- return LWS_FZ_ERR_NAME_READ;
- if ((int)amount != len)
- return LWS_FZ_ERR_NAME_READ;
-
- buf[len] = '\0';
- lwsl_debug("check %s vs %s\n", buf, name);
-
- if (strcmp((const char *)buf, name))
- goto next;
-
- /* we found a match */
- if (lws_vfs_file_seek_set(priv->zip_fop_fd, priv->hdr.offset) < 0)
- return LWS_FZ_ERR_NAME_SEEK;
- if (priv->zip_fop_fd->fops->LWS_FOP_READ(priv->zip_fop_fd,
- &amount, buf,
- ZL_HEADER_LENGTH))
- return LWS_FZ_ERR_NAME_READ;
- if (amount != ZL_HEADER_LENGTH)
- return LWS_FZ_ERR_NAME_READ;
-
- priv->content_start = priv->hdr.offset +
- ZL_HEADER_LENGTH +
- priv->hdr.filename_len +
- get_u16(buf + ZL_REL_OFFSET_CONTENT);
-
- lwsl_debug("content supposed to start at 0x%lx\n",
- (unsigned long)priv->content_start);
-
- if (priv->content_start > priv->zip_fop_fd->len)
- return LWS_FZ_ERR_CONTENT_SANITY;
-
- if (lws_vfs_file_seek_set(priv->zip_fop_fd,
- priv->content_start) < 0)
- return LWS_FZ_ERR_CONTENT_SEEK;
-
- /* we are aligned at the start of the content */
-
- priv->exp_uncomp_pos = 0;
-
- return 0;
-
-next:
- if (i && lws_vfs_file_seek_set(priv->zip_fop_fd,
- priv->content_start +
- ZC_DIRECTORY_LENGTH +
- priv->hdr.filename_len +
- priv->hdr.extra +
- priv->hdr.file_com_len) < 0)
- return LWS_FZ_ERR_SCAN_SEEK;
- }
-
- return LWS_FZ_ERR_NOT_FOUND;
-}
-
-static int
-lws_fops_zip_reset_inflate(lws_fops_zip_t priv)
-{
- if (priv->decompress)
- inflateEnd(&priv->inflate);
-
- priv->inflate.zalloc = Z_NULL;
- priv->inflate.zfree = Z_NULL;
- priv->inflate.opaque = Z_NULL;
- priv->inflate.avail_in = 0;
- priv->inflate.next_in = Z_NULL;
-
- if (inflateInit2(&priv->inflate, -MAX_WBITS) != Z_OK) {
- lwsl_err("inflate init failed\n");
- return LWS_FZ_ERR_ZLIB_INIT;
- }
-
- if (lws_vfs_file_seek_set(priv->zip_fop_fd, priv->content_start) < 0)
- return LWS_FZ_ERR_CONTENT_SEEK;
-
- priv->exp_uncomp_pos = 0;
-
- return 0;
-}
-
-static lws_fop_fd_t
-lws_fops_zip_open(const struct lws_plat_file_ops *fops, const char *vfs_path,
- const char *vpath, lws_fop_flags_t *flags)
-{
- lws_fop_flags_t local_flags = 0;
- lws_fops_zip_t priv;
- char rp[192];
- int m;
-
- /*
- * vpath points at the / after the fops signature in vfs_path, eg
- * with a vfs_path "/var/www/docs/manual.zip/index.html", vpath
- * will come pointing at "/index.html"
- */
-
- priv = lws_zalloc(sizeof(*priv), "fops_zip priv");
- if (!priv)
- return NULL;
-
- priv->fop_fd.fops = &fops_zip;
-
- m = sizeof(rp) - 1;
- if ((vpath - vfs_path - 1) < m)
- m = lws_ptr_diff(vpath, vfs_path) - 1;
- lws_strncpy(rp, vfs_path, m + 1);
-
- /* open the zip file itself using the incoming fops, not fops_zip */
-
- priv->zip_fop_fd = fops->LWS_FOP_OPEN(fops, rp, NULL, &local_flags);
- if (!priv->zip_fop_fd) {
- lwsl_err("unable to open zip %s\n", rp);
- goto bail1;
- }
-
- if (*vpath == '/')
- vpath++;
-
- m = lws_fops_zip_scan(priv, vpath, (int)strlen(vpath));
- if (m) {
- lwsl_err("unable to find record matching '%s' %d\n", vpath, m);
- goto bail2;
- }
-
- /* the directory metadata tells us modification time, so pass it on */
- priv->fop_fd.mod_time = priv->hdr.mod_time;
- *flags |= LWS_FOP_FLAG_MOD_TIME_VALID | LWS_FOP_FLAG_VIRTUAL;
- priv->fop_fd.flags = *flags;
-
- /* The zip fop_fd is left pointing at the start of the content.
- *
- * 1) Content could be uncompressed (STORE), and we can always serve
- * that directly
- *
- * 2) Content could be compressed (GZIP), and the client can handle
- * receiving GZIP... we can wrap it in a GZIP header and trailer
- * and serve the content part directly. The flag indicating we
- * are providing GZIP directly is set so lws will send the right
- * headers.
- *
- * 3) Content could be compressed (GZIP) but the client can't handle
- * receiving GZIP... we can decompress it and serve as it is
- * inflated piecemeal.
- *
- * 4) Content may be compressed some unknown way... fail
- *
- */
- if (priv->hdr.method == ZIP_COMPRESSION_METHOD_STORE) {
- /*
- * it is stored uncompressed, leave it indicated as
- * uncompressed, and just serve it from inside the
- * zip with no gzip container;
- */
-
- lwsl_info("direct zip serving (stored)\n");
-
- priv->fop_fd.len = priv->hdr.uncomp_size;
-
- return &priv->fop_fd;
- }
-
- if ((*flags & LWS_FOP_FLAG_COMPR_ACCEPTABLE_GZIP) &&
- priv->hdr.method == ZIP_COMPRESSION_METHOD_DEFLATE) {
-
- /*
- * We can serve the gzipped file contents directly as gzip
- * from inside the zip container; client says it is OK.
- *
- * To convert to standalone gzip, we have to add a 10-byte
- * constant header and a variable 8-byte trailer around the
- * content.
- *
- * The 8-byte trailer is prepared now and held in the priv.
- */
-
- lwsl_info("direct zip serving (gzipped)\n");
-
- priv->fop_fd.len = sizeof(hd) + priv->hdr.comp_size +
- sizeof(priv->u);
-
- if (lws_is_be()) {
- uint8_t *p = priv->u.trailer8;
-
- *p++ = (uint8_t)priv->hdr.crc32;
- *p++ = (uint8_t)(priv->hdr.crc32 >> 8);
- *p++ = (uint8_t)(priv->hdr.crc32 >> 16);
- *p++ = (uint8_t)(priv->hdr.crc32 >> 24);
- *p++ = (uint8_t)priv->hdr.uncomp_size;
- *p++ = (uint8_t)(priv->hdr.uncomp_size >> 8);
- *p++ = (uint8_t)(priv->hdr.uncomp_size >> 16);
- *p = (uint8_t)(priv->hdr.uncomp_size >> 24);
- } else {
- priv->u.trailer32[0] = priv->hdr.crc32;
- priv->u.trailer32[1] = priv->hdr.uncomp_size;
- }
-
- *flags |= LWS_FOP_FLAG_COMPR_IS_GZIP;
- priv->fop_fd.flags = *flags;
- priv->add_gzip_container = 1;
-
- return &priv->fop_fd;
- }
-
- if (priv->hdr.method == ZIP_COMPRESSION_METHOD_DEFLATE) {
-
- /* we must decompress it to serve it */
-
- lwsl_info("decompressed zip serving\n");
-
- priv->fop_fd.len = priv->hdr.uncomp_size;
-
- if (lws_fops_zip_reset_inflate(priv)) {
- lwsl_err("inflate init failed\n");
- goto bail2;
- }
-
- priv->decompress = 1;
-
- return &priv->fop_fd;
- }
-
- /* we can't handle it ... */
-
- lwsl_err("zipped file %s compressed in unknown way (%d)\n", vfs_path,
- priv->hdr.method);
-
-bail2:
- lws_vfs_file_close(&priv->zip_fop_fd);
-bail1:
- free(priv);
-
- return NULL;
-}
-
-/* ie, we are closing the fop_fd for the file inside the gzip */
-
-static int
-lws_fops_zip_close(lws_fop_fd_t *fd)
-{
- lws_fops_zip_t priv = fop_fd_to_priv(*fd);
-
- if (priv->decompress)
- inflateEnd(&priv->inflate);
-
- lws_vfs_file_close(&priv->zip_fop_fd); /* close the gzip fop_fd */
-
- free(priv);
- *fd = NULL;
-
- return 0;
-}
-
-static lws_fileofs_t
-lws_fops_zip_seek_cur(lws_fop_fd_t fd, lws_fileofs_t offset_from_cur_pos)
-{
- fd->pos += offset_from_cur_pos;
-
- return fd->pos;
-}
-
-static int
-lws_fops_zip_read(lws_fop_fd_t fd, lws_filepos_t *amount, uint8_t *buf,
- lws_filepos_t len)
-{
- lws_fops_zip_t priv = fop_fd_to_priv(fd);
- lws_filepos_t ramount, rlen, cur = lws_vfs_tell(fd);
- int ret;
-
- if (priv->decompress) {
-
- if (priv->exp_uncomp_pos != fd->pos) {
- /*
- * there has been a seek in the uncompressed fop_fd
- * we have to restart the decompression and loop eating
- * the decompressed data up to the seek point
- */
- lwsl_info("seek in decompressed\n");
-
- lws_fops_zip_reset_inflate(priv);
-
- while (priv->exp_uncomp_pos != fd->pos) {
- rlen = len;
- if (rlen > fd->pos - priv->exp_uncomp_pos)
- rlen = fd->pos - priv->exp_uncomp_pos;
- if (lws_fops_zip_read(fd, amount, buf, rlen))
- return LWS_FZ_ERR_SEEK_COMPRESSED;
- }
- *amount = 0;
- }
-
- priv->inflate.avail_out = (unsigned int)len;
- priv->inflate.next_out = buf;
-
-spin:
- if (!priv->inflate.avail_in) {
- rlen = sizeof(priv->rbuf);
- if (rlen > priv->hdr.comp_size -
- (cur - priv->content_start))
- rlen = priv->hdr.comp_size -
- (priv->hdr.comp_size -
- priv->content_start);
-
- if (priv->zip_fop_fd->fops->LWS_FOP_READ(
- priv->zip_fop_fd, &ramount, priv->rbuf,
- rlen))
- return LWS_FZ_ERR_READ_CONTENT;
-
- cur += ramount;
-
- priv->inflate.avail_in = (unsigned int)ramount;
- priv->inflate.next_in = priv->rbuf;
- }
-
- ret = inflate(&priv->inflate, Z_NO_FLUSH);
- if (ret == Z_STREAM_ERROR)
- return ret;
-
- switch (ret) {
- case Z_NEED_DICT:
- ret = Z_DATA_ERROR;
- /* fallthru */
- case Z_DATA_ERROR:
- case Z_MEM_ERROR:
-
- return ret;
- }
-
- if (!priv->inflate.avail_in && priv->inflate.avail_out &&
- cur != priv->content_start + priv->hdr.comp_size)
- goto spin;
-
- *amount = len - priv->inflate.avail_out;
-
- priv->exp_uncomp_pos += *amount;
- fd->pos += *amount;
-
- return 0;
- }
-
- if (priv->add_gzip_container) {
-
- lwsl_info("%s: gzip + container\n", __func__);
- *amount = 0;
-
- /* place the canned header at the start */
-
- if (len && fd->pos < sizeof(hd)) {
- rlen = sizeof(hd) - fd->pos;
- if (rlen > len)
- rlen = len;
- /* provide stuff from canned header */
- memcpy(buf, hd + fd->pos, (size_t)rlen);
- fd->pos += rlen;
- buf += rlen;
- len -= rlen;
- *amount += rlen;
- }
-
- /* serve gzipped data direct from zipfile */
-
- if (len && fd->pos >= sizeof(hd) &&
- fd->pos < priv->hdr.comp_size + sizeof(hd)) {
-
- rlen = priv->hdr.comp_size - (priv->zip_fop_fd->pos -
- priv->content_start);
- if (rlen > len)
- rlen = len;
-
- if (rlen &&
- priv->zip_fop_fd->pos < (priv->hdr.comp_size +
- priv->content_start)) {
- if (lws_vfs_file_read(priv->zip_fop_fd,
- &ramount, buf, rlen))
- return LWS_FZ_ERR_READ_CONTENT;
- *amount += ramount;
- fd->pos += ramount; // virtual pos
- buf += ramount;
- len -= ramount;
- }
- }
-
- /* place the prepared trailer at the end */
-
- if (len && fd->pos >= priv->hdr.comp_size + sizeof(hd) &&
- fd->pos < priv->hdr.comp_size + sizeof(hd) +
- sizeof(priv->u)) {
- cur = fd->pos - priv->hdr.comp_size - sizeof(hd);
- rlen = sizeof(priv->u) - cur;
- if (rlen > len)
- rlen = len;
-
- memcpy(buf, priv->u.trailer8 + cur, (size_t)rlen);
-
- *amount += rlen;
- fd->pos += rlen;
- }
-
- return 0;
- }
-
- lwsl_info("%s: store\n", __func__);
-
- if (len > priv->hdr.uncomp_size - (cur - priv->content_start))
- len = priv->hdr.comp_size - (priv->hdr.comp_size -
- priv->content_start);
-
- if (priv->zip_fop_fd->fops->LWS_FOP_READ(priv->zip_fop_fd,
- amount, buf, len))
- return LWS_FZ_ERR_READ_CONTENT;
-
- return 0;
-}
-
-struct lws_plat_file_ops fops_zip = {
- lws_fops_zip_open,
- lws_fops_zip_close,
- lws_fops_zip_seek_cur,
- lws_fops_zip_read,
- NULL,
- { { ".zip/", 5 }, { ".jar/", 5 }, { ".war/", 5 } },
- NULL,
-};
diff --git a/thirdparty/libwebsockets/roles/http/server/lejp-conf.c b/thirdparty/libwebsockets/roles/http/server/lejp-conf.c
deleted file mode 100644
index fbf10c288e..0000000000
--- a/thirdparty/libwebsockets/roles/http/server/lejp-conf.c
+++ /dev/null
@@ -1,993 +0,0 @@
-/*
- * libwebsockets web server application
- *
- * Copyright (C) 2010-2017 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- */
-
-#include "core/private.h"
-
-#ifndef _WIN32
-/* this is needed for Travis CI */
-#include <dirent.h>
-#endif
-
-#define ESC_INSTALL_DATADIR "_lws_ddir_"
-
-static const char * const paths_global[] = {
- "global.uid",
- "global.gid",
- "global.count-threads",
- "global.init-ssl",
- "global.server-string",
- "global.plugin-dir",
- "global.ws-pingpong-secs",
- "global.timeout-secs",
- "global.reject-service-keywords[].*",
- "global.reject-service-keywords[]",
- "global.default-alpn",
-};
-
-enum lejp_global_paths {
- LEJPGP_UID,
- LEJPGP_GID,
- LEJPGP_COUNT_THREADS,
- LWJPGP_INIT_SSL,
- LEJPGP_SERVER_STRING,
- LEJPGP_PLUGIN_DIR,
- LWJPGP_PINGPONG_SECS,
- LWJPGP_TIMEOUT_SECS,
- LWJPGP_REJECT_SERVICE_KEYWORDS_NAME,
- LWJPGP_REJECT_SERVICE_KEYWORDS,
- LWJPGP_DEFAULT_ALPN,
-};
-
-static const char * const paths_vhosts[] = {
- "vhosts[]",
- "vhosts[].mounts[]",
- "vhosts[].name",
- "vhosts[].port",
- "vhosts[].interface",
- "vhosts[].unix-socket",
- "vhosts[].sts",
- "vhosts[].host-ssl-key",
- "vhosts[].host-ssl-cert",
- "vhosts[].host-ssl-ca",
- "vhosts[].access-log",
- "vhosts[].mounts[].mountpoint",
- "vhosts[].mounts[].origin",
- "vhosts[].mounts[].protocol",
- "vhosts[].mounts[].default",
- "vhosts[].mounts[].auth-mask",
- "vhosts[].mounts[].cgi-timeout",
- "vhosts[].mounts[].cgi-env[].*",
- "vhosts[].mounts[].cache-max-age",
- "vhosts[].mounts[].cache-reuse",
- "vhosts[].mounts[].cache-revalidate",
- "vhosts[].mounts[].basic-auth",
- "vhosts[].mounts[].cache-intermediaries",
- "vhosts[].mounts[].extra-mimetypes.*",
- "vhosts[].mounts[].interpret.*",
- "vhosts[].ws-protocols[].*.*",
- "vhosts[].ws-protocols[].*",
- "vhosts[].ws-protocols[]",
- "vhosts[].keepalive_timeout",
- "vhosts[].enable-client-ssl",
- "vhosts[].ciphers",
- "vhosts[].ecdh-curve",
- "vhosts[].noipv6",
- "vhosts[].ipv6only",
- "vhosts[].ssl-option-set",
- "vhosts[].ssl-option-clear",
- "vhosts[].mounts[].pmo[].*",
- "vhosts[].headers[].*",
- "vhosts[].headers[]",
- "vhosts[].client-ssl-key",
- "vhosts[].client-ssl-cert",
- "vhosts[].client-ssl-ca",
- "vhosts[].client-ssl-ciphers",
- "vhosts[].onlyraw",
- "vhosts[].client-cert-required",
- "vhosts[].ignore-missing-cert",
- "vhosts[].error-document-404",
- "vhosts[].alpn",
-};
-
-enum lejp_vhost_paths {
- LEJPVP,
- LEJPVP_MOUNTS,
- LEJPVP_NAME,
- LEJPVP_PORT,
- LEJPVP_INTERFACE,
- LEJPVP_UNIXSKT,
- LEJPVP_STS,
- LEJPVP_HOST_SSL_KEY,
- LEJPVP_HOST_SSL_CERT,
- LEJPVP_HOST_SSL_CA,
- LEJPVP_ACCESS_LOG,
- LEJPVP_MOUNTPOINT,
- LEJPVP_ORIGIN,
- LEJPVP_MOUNT_PROTOCOL,
- LEJPVP_DEFAULT,
- LEJPVP_DEFAULT_AUTH_MASK,
- LEJPVP_CGI_TIMEOUT,
- LEJPVP_CGI_ENV,
- LEJPVP_MOUNT_CACHE_MAX_AGE,
- LEJPVP_MOUNT_CACHE_REUSE,
- LEJPVP_MOUNT_CACHE_REVALIDATE,
- LEJPVP_MOUNT_BASIC_AUTH,
- LEJPVP_MOUNT_CACHE_INTERMEDIARIES,
- LEJPVP_MOUNT_EXTRA_MIMETYPES,
- LEJPVP_MOUNT_INTERPRET,
- LEJPVP_PROTOCOL_NAME_OPT,
- LEJPVP_PROTOCOL_NAME,
- LEJPVP_PROTOCOL,
- LEJPVP_KEEPALIVE_TIMEOUT,
- LEJPVP_ENABLE_CLIENT_SSL,
- LEJPVP_CIPHERS,
- LEJPVP_ECDH_CURVE,
- LEJPVP_NOIPV6,
- LEJPVP_IPV6ONLY,
- LEJPVP_SSL_OPTION_SET,
- LEJPVP_SSL_OPTION_CLEAR,
- LEJPVP_PMO,
- LEJPVP_HEADERS_NAME,
- LEJPVP_HEADERS,
- LEJPVP_CLIENT_SSL_KEY,
- LEJPVP_CLIENT_SSL_CERT,
- LEJPVP_CLIENT_SSL_CA,
- LEJPVP_CLIENT_CIPHERS,
- LEJPVP_FLAG_ONLYRAW,
- LEJPVP_FLAG_CLIENT_CERT_REQUIRED,
- LEJPVP_IGNORE_MISSING_CERT,
- LEJPVP_ERROR_DOCUMENT_404,
- LEJPVP_ALPN,
-};
-
-static const char * const parser_errs[] = {
- "",
- "",
- "No opening '{'",
- "Expected closing '}'",
- "Expected '\"'",
- "String underrun",
- "Illegal unescaped control char",
- "Illegal escape format",
- "Illegal hex number",
- "Expected ':'",
- "Illegal value start",
- "Digit required after decimal point",
- "Bad number format",
- "Bad exponent format",
- "Unknown token",
- "Too many ']'",
- "Mismatched ']'",
- "Expected ']'",
- "JSON nesting limit exceeded",
- "Nesting tracking used up",
- "Number too long",
- "Comma or block end expected",
- "Unknown",
- "Parser callback errored (see earlier error)",
-};
-
-#define MAX_PLUGIN_DIRS 10
-
-struct jpargs {
- struct lws_context_creation_info *info;
- struct lws_context *context;
- const struct lws_protocols *protocols;
- const struct lws_extension *extensions;
- char *p, *end, valid;
- struct lws_http_mount *head, *last;
-
- struct lws_protocol_vhost_options *pvo;
- struct lws_protocol_vhost_options *pvo_em;
- struct lws_protocol_vhost_options *pvo_int;
- struct lws_http_mount m;
- const char **plugin_dirs;
- int count_plugin_dirs;
-
- unsigned int enable_client_ssl:1;
- unsigned int fresh_mount:1;
- unsigned int any_vhosts:1;
- unsigned int chunk:1;
-};
-
-static void *
-lwsws_align(struct jpargs *a)
-{
- if ((lws_intptr_t)(a->p) & 15)
- a->p += 16 - ((lws_intptr_t)(a->p) & 15);
-
- a->chunk = 0;
-
- return a->p;
-}
-
-static int
-arg_to_bool(const char *s)
-{
- static const char * const on[] = { "on", "yes", "true" };
- int n = atoi(s);
-
- if (n)
- return 1;
-
- for (n = 0; n < (int)LWS_ARRAY_SIZE(on); n++)
- if (!strcasecmp(s, on[n]))
- return 1;
-
- return 0;
-}
-
-static signed char
-lejp_globals_cb(struct lejp_ctx *ctx, char reason)
-{
- struct jpargs *a = (struct jpargs *)ctx->user;
- struct lws_protocol_vhost_options *rej;
- int n;
-
- /* we only match on the prepared path strings */
- if (!(reason & LEJP_FLAG_CB_IS_VALUE) || !ctx->path_match)
- return 0;
-
- /* this catches, eg, vhosts[].headers[].xxx */
- if (reason == LEJPCB_VAL_STR_END &&
- ctx->path_match == LWJPGP_REJECT_SERVICE_KEYWORDS_NAME + 1) {
- rej = lwsws_align(a);
- a->p += sizeof(*rej);
-
- n = lejp_get_wildcard(ctx, 0, a->p, a->end - a->p);
- rej->next = a->info->reject_service_keywords;
- a->info->reject_service_keywords = rej;
- rej->name = a->p;
- lwsl_notice(" adding rej %s=%s\n", a->p, ctx->buf);
- a->p += n - 1;
- *(a->p++) = '\0';
- rej->value = a->p;
- rej->options = NULL;
- goto dostring;
- }
-
- switch (ctx->path_match - 1) {
- case LEJPGP_UID:
- a->info->uid = atoi(ctx->buf);
- return 0;
- case LEJPGP_GID:
- a->info->gid = atoi(ctx->buf);
- return 0;
- case LEJPGP_COUNT_THREADS:
- a->info->count_threads = atoi(ctx->buf);
- return 0;
- case LWJPGP_INIT_SSL:
- if (arg_to_bool(ctx->buf))
- a->info->options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
- return 0;
- case LEJPGP_SERVER_STRING:
- a->info->server_string = a->p;
- break;
- case LEJPGP_PLUGIN_DIR:
- if (a->count_plugin_dirs == MAX_PLUGIN_DIRS - 1) {
- lwsl_err("Too many plugin dirs\n");
- return -1;
- }
- a->plugin_dirs[a->count_plugin_dirs++] = a->p;
- break;
-
- case LWJPGP_PINGPONG_SECS:
- a->info->ws_ping_pong_interval = atoi(ctx->buf);
- return 0;
-
- case LWJPGP_TIMEOUT_SECS:
- a->info->timeout_secs = atoi(ctx->buf);
- return 0;
-
- case LWJPGP_DEFAULT_ALPN:
- a->info->alpn = a->p;
- break;
-
- default:
- return 0;
- }
-
-dostring:
- a->p += lws_snprintf(a->p, a->end - a->p, "%s", ctx->buf);
- *(a->p)++ = '\0';
-
- return 0;
-}
-
-static signed char
-lejp_vhosts_cb(struct lejp_ctx *ctx, char reason)
-{
- struct jpargs *a = (struct jpargs *)ctx->user;
- struct lws_protocol_vhost_options *pvo, *mp_cgienv, *headers;
- struct lws_http_mount *m;
- char *p, *p1;
- int n;
-
-#if 0
- lwsl_notice(" %d: %s (%d)\n", reason, ctx->path, ctx->path_match);
- for (n = 0; n < ctx->wildcount; n++)
- lwsl_notice(" %d\n", ctx->wild[n]);
-#endif
-
- if (reason == LEJPCB_OBJECT_START && ctx->path_match == LEJPVP + 1) {
- uint32_t i[4];
- const char *ss;
-
- /* set the defaults for this vhost */
- a->valid = 1;
- a->head = NULL;
- a->last = NULL;
-
- i[0] = a->info->count_threads;
- i[1] = a->info->options & (
- LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME |
- LWS_SERVER_OPTION_LIBUV |
- LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT |
- LWS_SERVER_OPTION_EXPLICIT_VHOSTS |
- LWS_SERVER_OPTION_UV_NO_SIGSEGV_SIGFPE_SPIN |
- LWS_SERVER_OPTION_LIBEVENT |
- LWS_SERVER_OPTION_LIBEV
- );
- ss = a->info->server_string;
- i[2] = a->info->ws_ping_pong_interval;
- i[3] = a->info->timeout_secs;
-
- memset(a->info, 0, sizeof(*a->info));
-
- a->info->count_threads = i[0];
- a->info->options = i[1];
- a->info->server_string = ss;
- a->info->ws_ping_pong_interval = i[2];
- a->info->timeout_secs = i[3];
-
- a->info->protocols = a->protocols;
- a->info->extensions = a->extensions;
-#if defined(LWS_WITH_TLS)
- a->info->client_ssl_cipher_list = "ECDHE-ECDSA-AES256-GCM-SHA384:"
- "ECDHE-RSA-AES256-GCM-SHA384:"
- "DHE-RSA-AES256-GCM-SHA384:"
- "ECDHE-RSA-AES256-SHA384:"
- "HIGH:!aNULL:!eNULL:!EXPORT:"
- "!DES:!MD5:!PSK:!RC4:!HMAC_SHA1:"
- "!SHA1:!DHE-RSA-AES128-GCM-SHA256:"
- "!DHE-RSA-AES128-SHA256:"
- "!AES128-GCM-SHA256:"
- "!AES128-SHA256:"
- "!DHE-RSA-AES256-SHA256:"
- "!AES256-GCM-SHA384:"
- "!AES256-SHA256";
-#endif
- a->info->ssl_cipher_list = "ECDHE-ECDSA-AES256-GCM-SHA384:"
- "ECDHE-RSA-AES256-GCM-SHA384:"
- "DHE-RSA-AES256-GCM-SHA384:"
- "ECDHE-RSA-AES256-SHA384:"
- "HIGH:!aNULL:!eNULL:!EXPORT:"
- "!DES:!MD5:!PSK:!RC4:!HMAC_SHA1:"
- "!SHA1:!DHE-RSA-AES128-GCM-SHA256:"
- "!DHE-RSA-AES128-SHA256:"
- "!AES128-GCM-SHA256:"
- "!AES128-SHA256:"
- "!DHE-RSA-AES256-SHA256:"
- "!AES256-GCM-SHA384:"
- "!AES256-SHA256";
- a->info->keepalive_timeout = 5;
- }
-
- if (reason == LEJPCB_OBJECT_START &&
- ctx->path_match == LEJPVP_MOUNTS + 1) {
- a->fresh_mount = 1;
- memset(&a->m, 0, sizeof(a->m));
- }
-
- /* this catches, eg, vhosts[].ws-protocols[].xxx-protocol */
- if (reason == LEJPCB_OBJECT_START &&
- ctx->path_match == LEJPVP_PROTOCOL_NAME + 1) {
- a->pvo = lwsws_align(a);
- a->p += sizeof(*a->pvo);
-
- n = lejp_get_wildcard(ctx, 0, a->p, a->end - a->p);
- /* ie, enable this protocol, no options yet */
- a->pvo->next = a->info->pvo;
- a->info->pvo = a->pvo;
- a->pvo->name = a->p;
- lwsl_info(" adding protocol %s\n", a->p);
- a->p += n;
- a->pvo->value = a->p;
- a->pvo->options = NULL;
- goto dostring;
- }
-
- /* this catches, eg, vhosts[].headers[].xxx */
- if ((reason == LEJPCB_VAL_STR_END || reason == LEJPCB_VAL_STR_CHUNK) &&
- ctx->path_match == LEJPVP_HEADERS_NAME + 1) {
- if (!a->chunk) {
- headers = lwsws_align(a);
- a->p += sizeof(*headers);
-
- n = lejp_get_wildcard(ctx, 0, a->p,
- lws_ptr_diff(a->end, a->p));
- /* ie, add this header */
- headers->next = a->info->headers;
- a->info->headers = headers;
- headers->name = a->p;
-
- lwsl_notice(" adding header %s=%s\n", a->p, ctx->buf);
- a->p += n - 1;
- *(a->p++) = ':';
- if (a->p < a->end)
- *(a->p++) = '\0';
- else
- *(a->p - 1) = '\0';
- headers->value = a->p;
- headers->options = NULL;
- }
- a->chunk = reason == LEJPCB_VAL_STR_CHUNK;
- goto dostring;
- }
-
- if (reason == LEJPCB_OBJECT_END &&
- (ctx->path_match == LEJPVP + 1 || !ctx->path[0]) &&
- a->valid) {
-
- struct lws_vhost *vhost;
-
- //lwsl_notice("%s\n", ctx->path);
- if (!a->info->port) {
- lwsl_err("Port required (eg, 443)");
- return 1;
- }
- a->valid = 0;
- a->info->mounts = a->head;
-
- vhost = lws_create_vhost(a->context, a->info);
- if (!vhost) {
- lwsl_err("Failed to create vhost %s\n",
- a->info->vhost_name);
- return 1;
- }
- a->any_vhosts = 1;
-
-#if defined(LWS_WITH_TLS)
- if (a->enable_client_ssl) {
- const char *cert_filepath = a->info->client_ssl_cert_filepath;
- const char *private_key_filepath = a->info->client_ssl_private_key_filepath;
- const char *ca_filepath = a->info->client_ssl_ca_filepath;
- const char *cipher_list = a->info->client_ssl_cipher_list;
- memset(a->info, 0, sizeof(*a->info));
- a->info->client_ssl_cert_filepath = cert_filepath;
- a->info->client_ssl_private_key_filepath = private_key_filepath;
- a->info->client_ssl_ca_filepath = ca_filepath;
- a->info->client_ssl_cipher_list = cipher_list;
- a->info->options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
- lws_init_vhost_client_ssl(a->info, vhost);
- }
-#endif
-
- return 0;
- }
-
- if (reason == LEJPCB_OBJECT_END &&
- ctx->path_match == LEJPVP_MOUNTS + 1) {
- static const char * const mount_protocols[] = {
- "http://",
- "https://",
- "file://",
- "cgi://",
- ">http://",
- ">https://",
- "callback://",
- "gzip://",
- };
-
- if (!a->fresh_mount)
- return 0;
-
- if (!a->m.mountpoint || !a->m.origin) {
- lwsl_err("mountpoint and origin required\n");
- return 1;
- }
- lwsl_debug("adding mount %s\n", a->m.mountpoint);
- m = lwsws_align(a);
- memcpy(m, &a->m, sizeof(*m));
- if (a->last)
- a->last->mount_next = m;
-
- for (n = 0; n < (int)LWS_ARRAY_SIZE(mount_protocols); n++)
- if (!strncmp(a->m.origin, mount_protocols[n],
- strlen(mount_protocols[n]))) {
- lwsl_info("----%s\n", a->m.origin);
- m->origin_protocol = n;
- m->origin = a->m.origin +
- strlen(mount_protocols[n]);
- break;
- }
-
- if (n == (int)LWS_ARRAY_SIZE(mount_protocols)) {
- lwsl_err("unsupported protocol:// %s\n", a->m.origin);
- return 1;
- }
-
- a->p += sizeof(*m);
- if (!a->head)
- a->head = m;
-
- a->last = m;
- a->fresh_mount = 0;
- }
-
- /* we only match on the prepared path strings */
- if (!(reason & LEJP_FLAG_CB_IS_VALUE) || !ctx->path_match)
- return 0;
-
- switch (ctx->path_match - 1) {
- case LEJPVP_NAME:
- a->info->vhost_name = a->p;
- break;
- case LEJPVP_PORT:
- a->info->port = atoi(ctx->buf);
- return 0;
- case LEJPVP_INTERFACE:
- a->info->iface = a->p;
- break;
- case LEJPVP_UNIXSKT:
- if (arg_to_bool(ctx->buf))
- a->info->options |= LWS_SERVER_OPTION_UNIX_SOCK;
- else
- a->info->options &= ~(LWS_SERVER_OPTION_UNIX_SOCK);
- return 0;
- case LEJPVP_STS:
- if (arg_to_bool(ctx->buf))
- a->info->options |= LWS_SERVER_OPTION_STS;
- else
- a->info->options &= ~(LWS_SERVER_OPTION_STS);
- return 0;
- case LEJPVP_HOST_SSL_KEY:
- a->info->ssl_private_key_filepath = a->p;
- break;
- case LEJPVP_HOST_SSL_CERT:
- a->info->ssl_cert_filepath = a->p;
- break;
- case LEJPVP_HOST_SSL_CA:
- a->info->ssl_ca_filepath = a->p;
- break;
- case LEJPVP_ACCESS_LOG:
- a->info->log_filepath = a->p;
- break;
- case LEJPVP_MOUNTPOINT:
- a->m.mountpoint = a->p;
- a->m.mountpoint_len = (unsigned char)strlen(ctx->buf);
- break;
- case LEJPVP_ORIGIN:
- if (!strncmp(ctx->buf, "callback://", 11))
- a->m.protocol = a->p + 11;
-
- if (!a->m.origin)
- a->m.origin = a->p;
- break;
- case LEJPVP_DEFAULT:
- a->m.def = a->p;
- break;
- case LEJPVP_DEFAULT_AUTH_MASK:
- a->m.auth_mask = atoi(ctx->buf);
- return 0;
- case LEJPVP_MOUNT_CACHE_MAX_AGE:
- a->m.cache_max_age = atoi(ctx->buf);
- return 0;
- case LEJPVP_MOUNT_CACHE_REUSE:
- a->m.cache_reusable = arg_to_bool(ctx->buf);
- return 0;
- case LEJPVP_MOUNT_CACHE_REVALIDATE:
- a->m.cache_revalidate = arg_to_bool(ctx->buf);
- return 0;
- case LEJPVP_MOUNT_CACHE_INTERMEDIARIES:
- a->m.cache_intermediaries = arg_to_bool(ctx->buf);;
- return 0;
- case LEJPVP_MOUNT_BASIC_AUTH:
- a->m.basic_auth_login_file = a->p;
- break;
- case LEJPVP_CGI_TIMEOUT:
- a->m.cgi_timeout = atoi(ctx->buf);
- return 0;
- case LEJPVP_KEEPALIVE_TIMEOUT:
- a->info->keepalive_timeout = atoi(ctx->buf);
- return 0;
-#if defined(LWS_WITH_TLS)
- case LEJPVP_CLIENT_CIPHERS:
- a->info->client_ssl_cipher_list = a->p;
- break;
-#endif
- case LEJPVP_CIPHERS:
- a->info->ssl_cipher_list = a->p;
- break;
- case LEJPVP_ECDH_CURVE:
- a->info->ecdh_curve = a->p;
- break;
- case LEJPVP_PMO:
- case LEJPVP_CGI_ENV:
- mp_cgienv = lwsws_align(a);
- a->p += sizeof(*a->m.cgienv);
-
- mp_cgienv->next = a->m.cgienv;
- a->m.cgienv = mp_cgienv;
-
- n = lejp_get_wildcard(ctx, 0, a->p, a->end - a->p);
- mp_cgienv->name = a->p;
- a->p += n;
- mp_cgienv->value = a->p;
- mp_cgienv->options = NULL;
- //lwsl_notice(" adding pmo / cgi-env '%s' = '%s'\n", mp_cgienv->name,
- // mp_cgienv->value);
- goto dostring;
-
- case LEJPVP_PROTOCOL_NAME_OPT:
- /* this catches, eg,
- * vhosts[].ws-protocols[].xxx-protocol.yyy-option
- * ie, these are options attached to a protocol with { }
- */
- pvo = lwsws_align(a);
- a->p += sizeof(*a->pvo);
-
- n = lejp_get_wildcard(ctx, 1, a->p, a->end - a->p);
- /* ie, enable this protocol, no options yet */
- pvo->next = a->pvo->options;
- a->pvo->options = pvo;
- pvo->name = a->p;
- a->p += n;
- pvo->value = a->p;
- pvo->options = NULL;
- break;
-
- case LEJPVP_MOUNT_EXTRA_MIMETYPES:
- a->pvo_em = lwsws_align(a);
- a->p += sizeof(*a->pvo_em);
-
- n = lejp_get_wildcard(ctx, 0, a->p, a->end - a->p);
- /* ie, enable this protocol, no options yet */
- a->pvo_em->next = a->m.extra_mimetypes;
- a->m.extra_mimetypes = a->pvo_em;
- a->pvo_em->name = a->p;
- lwsl_notice(" adding extra-mimetypes %s -> %s\n", a->p, ctx->buf);
- a->p += n;
- a->pvo_em->value = a->p;
- a->pvo_em->options = NULL;
- break;
-
- case LEJPVP_MOUNT_INTERPRET:
- a->pvo_int = lwsws_align(a);
- a->p += sizeof(*a->pvo_int);
-
- n = lejp_get_wildcard(ctx, 0, a->p, a->end - a->p);
- /* ie, enable this protocol, no options yet */
- a->pvo_int->next = a->m.interpret;
- a->m.interpret = a->pvo_int;
- a->pvo_int->name = a->p;
- lwsl_notice(" adding interpret %s -> %s\n", a->p,
- ctx->buf);
- a->p += n;
- a->pvo_int->value = a->p;
- a->pvo_int->options = NULL;
- break;
-
- case LEJPVP_ENABLE_CLIENT_SSL:
- a->enable_client_ssl = arg_to_bool(ctx->buf);
- return 0;
-#if defined(LWS_WITH_TLS)
- case LEJPVP_CLIENT_SSL_KEY:
- a->info->client_ssl_private_key_filepath = a->p;
- break;
- case LEJPVP_CLIENT_SSL_CERT:
- a->info->client_ssl_cert_filepath = a->p;
- break;
- case LEJPVP_CLIENT_SSL_CA:
- a->info->client_ssl_ca_filepath = a->p;
- break;
-#endif
-
- case LEJPVP_NOIPV6:
- if (arg_to_bool(ctx->buf))
- a->info->options |= LWS_SERVER_OPTION_DISABLE_IPV6;
- else
- a->info->options &= ~(LWS_SERVER_OPTION_DISABLE_IPV6);
- return 0;
-
- case LEJPVP_FLAG_ONLYRAW:
- if (arg_to_bool(ctx->buf))
- a->info->options |= LWS_SERVER_OPTION_ONLY_RAW;
- else
- a->info->options &= ~(LWS_SERVER_OPTION_ONLY_RAW);
- return 0;
-
- case LEJPVP_IPV6ONLY:
- a->info->options |= LWS_SERVER_OPTION_IPV6_V6ONLY_MODIFY;
- if (arg_to_bool(ctx->buf))
- a->info->options |= LWS_SERVER_OPTION_IPV6_V6ONLY_VALUE;
- else
- a->info->options &= ~(LWS_SERVER_OPTION_IPV6_V6ONLY_VALUE);
- return 0;
-
- case LEJPVP_FLAG_CLIENT_CERT_REQUIRED:
- if (arg_to_bool(ctx->buf))
- a->info->options |=
- LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT;
- return 0;
-
- case LEJPVP_IGNORE_MISSING_CERT:
- if (arg_to_bool(ctx->buf))
- a->info->options |= LWS_SERVER_OPTION_IGNORE_MISSING_CERT;
- else
- a->info->options &= ~(LWS_SERVER_OPTION_IGNORE_MISSING_CERT);
-
- return 0;
-
- case LEJPVP_ERROR_DOCUMENT_404:
- a->info->error_document_404 = a->p;
- break;
-
- case LEJPVP_SSL_OPTION_SET:
- a->info->ssl_options_set |= atol(ctx->buf);
- return 0;
- case LEJPVP_SSL_OPTION_CLEAR:
- a->info->ssl_options_clear |= atol(ctx->buf);
- return 0;
-
- case LEJPVP_ALPN:
- a->info->alpn = a->p;
- break;
-
- default:
- return 0;
- }
-
-dostring:
- p = ctx->buf;
- p[LEJP_STRING_CHUNK] = '\0';
- p1 = strstr(p, ESC_INSTALL_DATADIR);
- if (p1) {
- n = p1 - p;
- if (n > a->end - a->p)
- n = a->end - a->p;
- lws_strncpy(a->p, p, n + 1);
- a->p += n;
- a->p += lws_snprintf(a->p, a->end - a->p, "%s", LWS_INSTALL_DATADIR);
- p += n + strlen(ESC_INSTALL_DATADIR);
- }
-
- a->p += lws_snprintf(a->p, a->end - a->p, "%s", p);
- if (reason == LEJPCB_VAL_STR_END)
- *(a->p)++ = '\0';
-
- return 0;
-}
-
-/*
- * returns 0 = OK, 1 = can't open, 2 = parsing error
- */
-
-static int
-lwsws_get_config(void *user, const char *f, const char * const *paths,
- int count_paths, lejp_callback cb)
-{
- unsigned char buf[128];
- struct lejp_ctx ctx;
- int n, m, fd;
-
- fd = lws_open(f, O_RDONLY);
- if (fd < 0) {
- lwsl_err("Cannot open %s\n", f);
- return 2;
- }
- lwsl_info("%s: %s\n", __func__, f);
- lejp_construct(&ctx, cb, user, paths, count_paths);
-
- do {
- n = read(fd, buf, sizeof(buf));
- if (!n)
- break;
-
- m = (int)(signed char)lejp_parse(&ctx, buf, n);
- } while (m == LEJP_CONTINUE);
-
- close(fd);
- n = ctx.line;
- lejp_destruct(&ctx);
-
- if (m < 0) {
- lwsl_err("%s(%u): parsing error %d: %s\n", f, n, m,
- parser_errs[-m]);
- return 2;
- }
-
- return 0;
-}
-
-#if defined(LWS_WITH_LIBUV) && UV_VERSION_MAJOR > 0
-
-static int
-lwsws_get_config_d(void *user, const char *d, const char * const *paths,
- int count_paths, lejp_callback cb)
-{
- uv_dirent_t dent;
- uv_fs_t req;
- char path[256];
- int ret = 0, ir;
- uv_loop_t loop;
-
- ir = uv_loop_init(&loop);
- if (ir) {
- lwsl_err("%s: loop init failed %d\n", __func__, ir);
- }
-
- if (!uv_fs_scandir(&loop, &req, d, 0, NULL)) {
- lwsl_err("Scandir on %s failed\n", d);
- return 2;
- }
-
- while (uv_fs_scandir_next(&req, &dent) != UV_EOF) {
- lws_snprintf(path, sizeof(path) - 1, "%s/%s", d, dent.name);
- ret = lwsws_get_config(user, path, paths, count_paths, cb);
- if (ret)
- goto bail;
- }
-
-bail:
- uv_fs_req_cleanup(&req);
- while (uv_loop_close(&loop))
- ;
-
- return ret;
-}
-
-#else
-
-#ifndef _WIN32
-static int filter(const struct dirent *ent)
-{
- if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
- return 0;
-
- return 1;
-}
-#endif
-
-static int
-lwsws_get_config_d(void *user, const char *d, const char * const *paths,
- int count_paths, lejp_callback cb)
-{
-#ifndef _WIN32
- struct dirent **namelist;
- char path[256];
- int n, i, ret = 0;
-
- n = scandir(d, &namelist, filter, alphasort);
- if (n < 0) {
- lwsl_err("Scandir on %s failed\n", d);
- return 1;
- }
-
- for (i = 0; i < n; i++) {
- if (strchr(namelist[i]->d_name, '~'))
- goto skip;
- lws_snprintf(path, sizeof(path) - 1, "%s/%s", d,
- namelist[i]->d_name);
- ret = lwsws_get_config(user, path, paths, count_paths, cb);
- if (ret) {
- while (i++ < n)
- free(namelist[i]);
- goto bail;
- }
-skip:
- free(namelist[i]);
- }
-
-bail:
- free(namelist);
-
- return ret;
-#else
- return 0;
-#endif
-}
-
-#endif
-
-int
-lwsws_get_config_globals(struct lws_context_creation_info *info, const char *d,
- char **cs, int *len)
-{
- struct jpargs a;
- const char * const *old = info->plugin_dirs;
- char dd[128];
-
- memset(&a, 0, sizeof(a));
-
- a.info = info;
- a.p = *cs;
- a.end = (a.p + *len) - 1;
- a.valid = 0;
-
- lwsws_align(&a);
- info->plugin_dirs = (void *)a.p;
- a.plugin_dirs = (void *)a.p; /* writeable version */
- a.p += MAX_PLUGIN_DIRS * sizeof(void *);
-
- /* copy any default paths */
-
- while (old && *old) {
- a.plugin_dirs[a.count_plugin_dirs++] = *old;
- old++;
- }
-
- lws_snprintf(dd, sizeof(dd) - 1, "%s/conf", d);
- if (lwsws_get_config(&a, dd, paths_global,
- LWS_ARRAY_SIZE(paths_global), lejp_globals_cb) > 1)
- return 1;
- lws_snprintf(dd, sizeof(dd) - 1, "%s/conf.d", d);
- if (lwsws_get_config_d(&a, dd, paths_global,
- LWS_ARRAY_SIZE(paths_global), lejp_globals_cb) > 1)
- return 1;
-
- a.plugin_dirs[a.count_plugin_dirs] = NULL;
-
- *cs = a.p;
- *len = a.end - a.p;
-
- return 0;
-}
-
-int
-lwsws_get_config_vhosts(struct lws_context *context,
- struct lws_context_creation_info *info, const char *d,
- char **cs, int *len)
-{
- struct jpargs a;
- char dd[128];
-
- memset(&a, 0, sizeof(a));
-
- a.info = info;
- a.p = *cs;
- a.end = a.p + *len;
- a.valid = 0;
- a.context = context;
- a.protocols = info->protocols;
- a.extensions = info->extensions;
-
- lws_snprintf(dd, sizeof(dd) - 1, "%s/conf", d);
- if (lwsws_get_config(&a, dd, paths_vhosts,
- LWS_ARRAY_SIZE(paths_vhosts), lejp_vhosts_cb) > 1)
- return 1;
- lws_snprintf(dd, sizeof(dd) - 1, "%s/conf.d", d);
- if (lwsws_get_config_d(&a, dd, paths_vhosts,
- LWS_ARRAY_SIZE(paths_vhosts), lejp_vhosts_cb) > 1)
- return 1;
-
- *cs = a.p;
- *len = a.end - a.p;
-
- if (!a.any_vhosts) {
- lwsl_err("Need at least one vhost\n");
- return 1;
- }
-
-// lws_finalize_startup(context);
-
- return 0;
-}
diff --git a/thirdparty/libwebsockets/roles/http/server/parsers.c b/thirdparty/libwebsockets/roles/http/server/parsers.c
deleted file mode 100644
index 482bdc676a..0000000000
--- a/thirdparty/libwebsockets/roles/http/server/parsers.c
+++ /dev/null
@@ -1,1137 +0,0 @@
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010-2018 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- */
-
-#include "core/private.h"
-
-static const unsigned char lextable[] = {
- #include "../lextable.h"
-};
-
-#define FAIL_CHAR 0x08
-
-static struct allocated_headers *
-_lws_create_ah(struct lws_context_per_thread *pt, ah_data_idx_t data_size)
-{
- struct allocated_headers *ah = lws_zalloc(sizeof(*ah), "ah struct");
-
- if (!ah)
- return NULL;
-
- ah->data = lws_malloc(data_size, "ah data");
- if (!ah->data) {
- lws_free(ah);
-
- return NULL;
- }
- ah->next = pt->http.ah_list;
- pt->http.ah_list = ah;
- ah->data_length = data_size;
- pt->http.ah_pool_length++;
-
- lwsl_info("%s: created ah %p (size %d): pool length %d\n", __func__,
- ah, (int)data_size, pt->http.ah_pool_length);
-
- return ah;
-}
-
-int
-_lws_destroy_ah(struct lws_context_per_thread *pt, struct allocated_headers *ah)
-{
- lws_start_foreach_llp(struct allocated_headers **, a, pt->http.ah_list) {
- if ((*a) == ah) {
- *a = ah->next;
- pt->http.ah_pool_length--;
- lwsl_info("%s: freed ah %p : pool length %d\n",
- __func__, ah, pt->http.ah_pool_length);
- if (ah->data)
- lws_free(ah->data);
- lws_free(ah);
-
- return 0;
- }
- } lws_end_foreach_llp(a, next);
-
- return 1;
-}
-
-void
-_lws_header_table_reset(struct allocated_headers *ah)
-{
- /* init the ah to reflect no headers or data have appeared yet */
- memset(ah->frag_index, 0, sizeof(ah->frag_index));
- memset(ah->frags, 0, sizeof(ah->frags));
- ah->nfrag = 0;
- ah->pos = 0;
- ah->http_response = 0;
- ah->parser_state = WSI_TOKEN_NAME_PART;
- ah->lextable_pos = 0;
-}
-
-// doesn't scrub the ah rxbuffer by default, parent must do if needed
-
-void
-__lws_header_table_reset(struct lws *wsi, int autoservice)
-{
- struct allocated_headers *ah = wsi->http.ah;
- struct lws_context_per_thread *pt;
- struct lws_pollfd *pfd;
-
- /* if we have the idea we're resetting 'our' ah, must be bound to one */
- assert(ah);
- /* ah also concurs with ownership */
- assert(ah->wsi == wsi);
-
- _lws_header_table_reset(ah);
-
- /* since we will restart the ah, our new headers are not completed */
- wsi->hdr_parsing_completed = 0;
-
- /* while we hold the ah, keep a timeout on the wsi */
- __lws_set_timeout(wsi, PENDING_TIMEOUT_HOLDING_AH,
- wsi->vhost->timeout_secs_ah_idle);
-
- time(&ah->assigned);
-
- if (wsi->position_in_fds_table != LWS_NO_FDS_POS &&
- lws_buflist_next_segment_len(&wsi->buflist, NULL) &&
- autoservice) {
- lwsl_debug("%s: service on readbuf ah\n", __func__);
-
- pt = &wsi->context->pt[(int)wsi->tsi];
- /*
- * Unlike a normal connect, we have the headers already
- * (or the first part of them anyway)
- */
- pfd = &pt->fds[wsi->position_in_fds_table];
- pfd->revents |= LWS_POLLIN;
- lwsl_err("%s: calling service\n", __func__);
- lws_service_fd_tsi(wsi->context, pfd, wsi->tsi);
- }
-}
-
-void
-lws_header_table_reset(struct lws *wsi, int autoservice)
-{
- struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
-
- lws_pt_lock(pt, __func__);
-
- __lws_header_table_reset(wsi, autoservice);
-
- lws_pt_unlock(pt);
-}
-
-static void
-_lws_header_ensure_we_are_on_waiting_list(struct lws *wsi)
-{
- struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
- struct lws_pollargs pa;
- struct lws **pwsi = &pt->http.ah_wait_list;
-
- while (*pwsi) {
- if (*pwsi == wsi)
- return;
- pwsi = &(*pwsi)->http.ah_wait_list;
- }
-
- lwsl_info("%s: wsi: %p\n", __func__, wsi);
- wsi->http.ah_wait_list = pt->http.ah_wait_list;
- pt->http.ah_wait_list = wsi;
- pt->http.ah_wait_list_length++;
-
- /* we cannot accept input then */
-
- _lws_change_pollfd(wsi, LWS_POLLIN, 0, &pa);
-}
-
-static int
-__lws_remove_from_ah_waiting_list(struct lws *wsi)
-{
- struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
- struct lws **pwsi =&pt->http.ah_wait_list;
-
- while (*pwsi) {
- if (*pwsi == wsi) {
- lwsl_info("%s: wsi %p\n", __func__, wsi);
- /* point prev guy to our next */
- *pwsi = wsi->http.ah_wait_list;
- /* we shouldn't point anywhere now */
- wsi->http.ah_wait_list = NULL;
- pt->http.ah_wait_list_length--;
-
- return 1;
- }
- pwsi = &(*pwsi)->http.ah_wait_list;
- }
-
- return 0;
-}
-
-int LWS_WARN_UNUSED_RESULT
-lws_header_table_attach(struct lws *wsi, int autoservice)
-{
- struct lws_context *context = wsi->context;
- struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
- struct lws_pollargs pa;
- int n;
-
- lwsl_info("%s: wsi %p: ah %p (tsi %d, count = %d) in\n", __func__,
- (void *)wsi, (void *)wsi->http.ah, wsi->tsi,
- pt->http.ah_count_in_use);
-
- lws_pt_lock(pt, __func__);
-
- /* if we are already bound to one, just clear it down */
- if (wsi->http.ah) {
- lwsl_info("%s: cleardown\n", __func__);
- goto reset;
- }
-
- n = pt->http.ah_count_in_use == context->max_http_header_pool;
-#if defined(LWS_WITH_PEER_LIMITS)
- if (!n) {
- n = lws_peer_confirm_ah_attach_ok(context, wsi->peer);
- if (n)
- lws_stats_atomic_bump(wsi->context, pt,
- LWSSTATS_C_PEER_LIMIT_AH_DENIED, 1);
- }
-#endif
- if (n) {
- /*
- * Pool is either all busy, or we don't want to give this
- * particular guy an ah right now...
- *
- * Make sure we are on the waiting list, and return that we
- * weren't able to provide the ah
- */
- _lws_header_ensure_we_are_on_waiting_list(wsi);
-
- goto bail;
- }
-
- __lws_remove_from_ah_waiting_list(wsi);
-
- wsi->http.ah = _lws_create_ah(pt, context->max_http_header_data);
- if (!wsi->http.ah) { /* we could not create an ah */
- _lws_header_ensure_we_are_on_waiting_list(wsi);
-
- goto bail;
- }
-
- wsi->http.ah->in_use = 1;
- wsi->http.ah->wsi = wsi; /* mark our owner */
- pt->http.ah_count_in_use++;
-
-#if defined(LWS_WITH_PEER_LIMITS) && (defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2))
- lws_context_lock(context); /* <====================================== */
- if (wsi->peer)
- wsi->peer->http.count_ah++;
- lws_context_unlock(context); /* ====================================> */
-#endif
-
- _lws_change_pollfd(wsi, 0, LWS_POLLIN, &pa);
-
- lwsl_info("%s: did attach wsi %p: ah %p: count %d (on exit)\n", __func__,
- (void *)wsi, (void *)wsi->http.ah, pt->http.ah_count_in_use);
-
-reset:
- __lws_header_table_reset(wsi, autoservice);
-
- lws_pt_unlock(pt);
-
-#ifndef LWS_NO_CLIENT
- if (lwsi_role_client(wsi) && lwsi_state(wsi) == LRS_UNCONNECTED)
- if (!lws_client_connect_via_info2(wsi))
- /* our client connect has failed, the wsi
- * has been closed
- */
- return -1;
-#endif
-
- return 0;
-
-bail:
- lws_pt_unlock(pt);
-
- return 1;
-}
-
-int __lws_header_table_detach(struct lws *wsi, int autoservice)
-{
- struct lws_context *context = wsi->context;
- struct allocated_headers *ah = wsi->http.ah;
- struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
- struct lws_pollargs pa;
- struct lws **pwsi, **pwsi_eligible;
- time_t now;
-
- __lws_remove_from_ah_waiting_list(wsi);
-
- if (!ah)
- return 0;
-
- lwsl_info("%s: wsi %p: ah %p (tsi=%d, count = %d)\n", __func__,
- (void *)wsi, (void *)ah, wsi->tsi,
- pt->http.ah_count_in_use);
-
- /* we did have an ah attached */
- time(&now);
- if (ah->assigned && now - ah->assigned > 3) {
- /*
- * we're detaching the ah, but it was held an
- * unreasonably long time
- */
- lwsl_debug("%s: wsi %p: ah held %ds, role/state 0x%x 0x%x,"
- "\n", __func__, wsi, (int)(now - ah->assigned),
- lwsi_role(wsi), lwsi_state(wsi));
- }
-
- ah->assigned = 0;
-
- /* if we think we're detaching one, there should be one in use */
- assert(pt->http.ah_count_in_use > 0);
- /* and this specific one should have been in use */
- assert(ah->in_use);
- memset(&wsi->http.ah, 0, sizeof(wsi->http.ah));
-
-#if defined(LWS_WITH_PEER_LIMITS)
- if (ah->wsi)
- lws_peer_track_ah_detach(context, wsi->peer);
-#endif
- ah->wsi = NULL; /* no owner */
-
- pwsi = &pt->http.ah_wait_list;
-
- /* oh there is nobody on the waiting list... leave the ah unattached */
- if (!*pwsi)
- goto nobody_usable_waiting;
-
- /*
- * at least one wsi on the same tsi is waiting, give it to oldest guy
- * who is allowed to take it (if any)
- */
- lwsl_info("pt wait list %p\n", *pwsi);
- wsi = NULL;
- pwsi_eligible = NULL;
-
- while (*pwsi) {
-#if defined(LWS_WITH_PEER_LIMITS)
- /* are we willing to give this guy an ah? */
- if (!lws_peer_confirm_ah_attach_ok(context, (*pwsi)->peer))
-#endif
- {
- wsi = *pwsi;
- pwsi_eligible = pwsi;
- }
-#if defined(LWS_WITH_PEER_LIMITS)
- else
- if (!(*pwsi)->http.ah_wait_list)
- lws_stats_atomic_bump(context, pt,
- LWSSTATS_C_PEER_LIMIT_AH_DENIED, 1);
-#endif
- pwsi = &(*pwsi)->http.ah_wait_list;
- }
-
- if (!wsi) /* everybody waiting already has too many ah... */
- goto nobody_usable_waiting;
-
- lwsl_info("%s: transferring ah to last eligible wsi in wait list %p (wsistate 0x%x)\n", __func__, wsi, wsi->wsistate);
-
- wsi->http.ah = ah;
- ah->wsi = wsi; /* new owner */
-
- __lws_header_table_reset(wsi, autoservice);
-#if defined(LWS_WITH_PEER_LIMITS) && (defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2))
- lws_context_lock(context); /* <====================================== */
- if (wsi->peer)
- wsi->peer->http.count_ah++;
- lws_context_unlock(context); /* ====================================> */
-#endif
-
- /* clients acquire the ah and then insert themselves in fds table... */
- if (wsi->position_in_fds_table != LWS_NO_FDS_POS) {
- lwsl_info("%s: Enabling %p POLLIN\n", __func__, wsi);
-
- /* he has been stuck waiting for an ah, but now his wait is
- * over, let him progress */
-
- _lws_change_pollfd(wsi, 0, LWS_POLLIN, &pa);
- }
-
- /* point prev guy to next guy in list instead */
- *pwsi_eligible = wsi->http.ah_wait_list;
- /* the guy who got one is out of the list */
- wsi->http.ah_wait_list = NULL;
- pt->http.ah_wait_list_length--;
-
-#ifndef LWS_NO_CLIENT
- if (lwsi_role_client(wsi) && lwsi_state(wsi) == LRS_UNCONNECTED) {
- lws_pt_unlock(pt);
-
- if (!lws_client_connect_via_info2(wsi)) {
- /* our client connect has failed, the wsi
- * has been closed
- */
-
- return -1;
- }
- return 0;
- }
-#endif
-
- assert(!!pt->http.ah_wait_list_length == !!(lws_intptr_t)pt->http.ah_wait_list);
-bail:
- lwsl_info("%s: wsi %p: ah %p (tsi=%d, count = %d)\n", __func__,
- (void *)wsi, (void *)ah, pt->tid, pt->http.ah_count_in_use);
-
- return 0;
-
-nobody_usable_waiting:
- lwsl_info("%s: nobody usable waiting\n", __func__);
- _lws_destroy_ah(pt, ah);
- pt->http.ah_count_in_use--;
-
- goto bail;
-}
-
-int lws_header_table_detach(struct lws *wsi, int autoservice)
-{
- struct lws_context *context = wsi->context;
- struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
- int n;
-
- lws_pt_lock(pt, __func__);
- n = __lws_header_table_detach(wsi, autoservice);
- lws_pt_unlock(pt);
-
- return n;
-}
-
-LWS_VISIBLE int
-lws_hdr_fragment_length(struct lws *wsi, enum lws_token_indexes h, int frag_idx)
-{
- int n;
-
- if (!wsi->http.ah)
- return 0;
-
- n = wsi->http.ah->frag_index[h];
- if (!n)
- return 0;
- do {
- if (!frag_idx)
- return wsi->http.ah->frags[n].len;
- n = wsi->http.ah->frags[n].nfrag;
- } while (frag_idx-- && n);
-
- return 0;
-}
-
-LWS_VISIBLE int lws_hdr_total_length(struct lws *wsi, enum lws_token_indexes h)
-{
- int n;
- int len = 0;
-
- if (!wsi->http.ah)
- return 0;
-
- n = wsi->http.ah->frag_index[h];
- if (!n)
- return 0;
- do {
- len += wsi->http.ah->frags[n].len;
- n = wsi->http.ah->frags[n].nfrag;
- } while (n);
-
- return len;
-}
-
-LWS_VISIBLE int lws_hdr_copy_fragment(struct lws *wsi, char *dst, int len,
- enum lws_token_indexes h, int frag_idx)
-{
- int n = 0;
- int f;
-
- if (!wsi->http.ah)
- return -1;
-
- f = wsi->http.ah->frag_index[h];
-
- if (!f)
- return -1;
-
- while (n < frag_idx) {
- f = wsi->http.ah->frags[f].nfrag;
- if (!f)
- return -1;
- n++;
- }
-
- if (wsi->http.ah->frags[f].len >= len)
- return -1;
-
- memcpy(dst, wsi->http.ah->data + wsi->http.ah->frags[f].offset,
- wsi->http.ah->frags[f].len);
- dst[wsi->http.ah->frags[f].len] = '\0';
-
- return wsi->http.ah->frags[f].len;
-}
-
-LWS_VISIBLE int lws_hdr_copy(struct lws *wsi, char *dst, int len,
- enum lws_token_indexes h)
-{
- int toklen = lws_hdr_total_length(wsi, h);
- int n;
-
- if (toklen >= len)
- return -1;
-
- if (!wsi->http.ah)
- return -1;
-
- n = wsi->http.ah->frag_index[h];
- if (!n)
- return 0;
-
- do {
- if (wsi->http.ah->frags[n].len >= len)
- return -1;
- strncpy(dst, &wsi->http.ah->data[wsi->http.ah->frags[n].offset],
- wsi->http.ah->frags[n].len);
- dst += wsi->http.ah->frags[n].len;
- len -= wsi->http.ah->frags[n].len;
- n = wsi->http.ah->frags[n].nfrag;
- } while (n);
- *dst = '\0';
-
- return toklen;
-}
-
-char *lws_hdr_simple_ptr(struct lws *wsi, enum lws_token_indexes h)
-{
- int n;
-
- n = wsi->http.ah->frag_index[h];
- if (!n)
- return NULL;
-
- return wsi->http.ah->data + wsi->http.ah->frags[n].offset;
-}
-
-static int LWS_WARN_UNUSED_RESULT
-lws_pos_in_bounds(struct lws *wsi)
-{
- if (wsi->http.ah->pos <
- (unsigned int)wsi->context->max_http_header_data)
- return 0;
-
- if ((int)wsi->http.ah->pos == wsi->context->max_http_header_data) {
- lwsl_err("Ran out of header data space\n");
- return 1;
- }
-
- /*
- * with these tests everywhere, it should never be able to exceed
- * the limit, only meet it
- */
- lwsl_err("%s: pos %d, limit %d\n", __func__, wsi->http.ah->pos,
- wsi->context->max_http_header_data);
- assert(0);
-
- return 1;
-}
-
-int LWS_WARN_UNUSED_RESULT
-lws_hdr_simple_create(struct lws *wsi, enum lws_token_indexes h, const char *s)
-{
- wsi->http.ah->nfrag++;
- if (wsi->http.ah->nfrag == LWS_ARRAY_SIZE(wsi->http.ah->frags)) {
- lwsl_warn("More hdr frags than we can deal with, dropping\n");
- return -1;
- }
-
- wsi->http.ah->frag_index[h] = wsi->http.ah->nfrag;
-
- wsi->http.ah->frags[wsi->http.ah->nfrag].offset = wsi->http.ah->pos;
- wsi->http.ah->frags[wsi->http.ah->nfrag].len = 0;
- wsi->http.ah->frags[wsi->http.ah->nfrag].nfrag = 0;
-
- do {
- if (lws_pos_in_bounds(wsi))
- return -1;
-
- wsi->http.ah->data[wsi->http.ah->pos++] = *s;
- if (*s)
- wsi->http.ah->frags[wsi->http.ah->nfrag].len++;
- } while (*s++);
-
- return 0;
-}
-
-static int LWS_WARN_UNUSED_RESULT
-issue_char(struct lws *wsi, unsigned char c)
-{
- unsigned short frag_len;
-
- if (lws_pos_in_bounds(wsi))
- return -1;
-
- frag_len = wsi->http.ah->frags[wsi->http.ah->nfrag].len;
- /*
- * If we haven't hit the token limit, just copy the character into
- * the header
- */
- if (frag_len < wsi->http.ah->current_token_limit) {
- wsi->http.ah->data[wsi->http.ah->pos++] = c;
- if (c)
- wsi->http.ah->frags[wsi->http.ah->nfrag].len++;
- return 0;
- }
-
- /* Insert a null character when we *hit* the limit: */
- if (frag_len == wsi->http.ah->current_token_limit) {
- if (lws_pos_in_bounds(wsi))
- return -1;
-
- wsi->http.ah->data[wsi->http.ah->pos++] = '\0';
- lwsl_warn("header %i exceeds limit %d\n",
- wsi->http.ah->parser_state,
- wsi->http.ah->current_token_limit);
- }
-
- return 1;
-}
-
-int
-lws_parse_urldecode(struct lws *wsi, uint8_t *_c)
-{
- struct allocated_headers *ah = wsi->http.ah;
- unsigned int enc = 0;
- uint8_t c = *_c;
-
- // lwsl_notice("ah->ups %d\n", ah->ups);
-
- /*
- * PRIORITY 1
- * special URI processing... convert %xx
- */
- switch (ah->ues) {
- case URIES_IDLE:
- if (c == '%') {
- ah->ues = URIES_SEEN_PERCENT;
- goto swallow;
- }
- break;
- case URIES_SEEN_PERCENT:
- if (char_to_hex(c) < 0)
- /* illegal post-% char */
- goto forbid;
-
- ah->esc_stash = c;
- ah->ues = URIES_SEEN_PERCENT_H1;
- goto swallow;
-
- case URIES_SEEN_PERCENT_H1:
- if (char_to_hex(c) < 0)
- /* illegal post-% char */
- goto forbid;
-
- *_c = (char_to_hex(ah->esc_stash) << 4) |
- char_to_hex(c);
- c = *_c;
- enc = 1;
- ah->ues = URIES_IDLE;
- break;
- }
-
- /*
- * PRIORITY 2
- * special URI processing...
- * convert /.. or /... or /../ etc to /
- * convert /./ to /
- * convert // or /// etc to /
- * leave /.dir or whatever alone
- */
-
- switch (ah->ups) {
- case URIPS_IDLE:
- if (!c)
- return -1;
- /* genuine delimiter */
- if ((c == '&' || c == ';') && !enc) {
- if (issue_char(wsi, '\0') < 0)
- return -1;
- /* link to next fragment */
- ah->frags[ah->nfrag].nfrag = ah->nfrag + 1;
- ah->nfrag++;
- if (ah->nfrag >= LWS_ARRAY_SIZE(ah->frags))
- goto excessive;
- /* start next fragment after the & */
- ah->post_literal_equal = 0;
- ah->frags[ah->nfrag].offset = ++ah->pos;
- ah->frags[ah->nfrag].len = 0;
- ah->frags[ah->nfrag].nfrag = 0;
- goto swallow;
- }
- /* uriencoded = in the name part, disallow */
- if (c == '=' && enc &&
- ah->frag_index[WSI_TOKEN_HTTP_URI_ARGS] &&
- !ah->post_literal_equal) {
- c = '_';
- *_c =c;
- }
-
- /* after the real =, we don't care how many = */
- if (c == '=' && !enc)
- ah->post_literal_equal = 1;
-
- /* + to space */
- if (c == '+' && !enc) {
- c = ' ';
- *_c = c;
- }
- /* issue the first / always */
- if (c == '/' && !ah->frag_index[WSI_TOKEN_HTTP_URI_ARGS])
- ah->ups = URIPS_SEEN_SLASH;
- break;
- case URIPS_SEEN_SLASH:
- /* swallow subsequent slashes */
- if (c == '/')
- goto swallow;
- /* track and swallow the first . after / */
- if (c == '.') {
- ah->ups = URIPS_SEEN_SLASH_DOT;
- goto swallow;
- }
- ah->ups = URIPS_IDLE;
- break;
- case URIPS_SEEN_SLASH_DOT:
- /* swallow second . */
- if (c == '.') {
- ah->ups = URIPS_SEEN_SLASH_DOT_DOT;
- goto swallow;
- }
- /* change /./ to / */
- if (c == '/') {
- ah->ups = URIPS_SEEN_SLASH;
- goto swallow;
- }
- /* it was like /.dir ... regurgitate the . */
- ah->ups = URIPS_IDLE;
- if (issue_char(wsi, '.') < 0)
- return -1;
- break;
-
- case URIPS_SEEN_SLASH_DOT_DOT:
-
- /* /../ or /..[End of URI] --> backup to last / */
- if (c == '/' || c == '?') {
- /*
- * back up one dir level if possible
- * safe against header fragmentation because
- * the method URI can only be in 1 fragment
- */
- if (ah->frags[ah->nfrag].len > 2) {
- ah->pos--;
- ah->frags[ah->nfrag].len--;
- do {
- ah->pos--;
- ah->frags[ah->nfrag].len--;
- } while (ah->frags[ah->nfrag].len > 1 &&
- ah->data[ah->pos] != '/');
- }
- ah->ups = URIPS_SEEN_SLASH;
- if (ah->frags[ah->nfrag].len > 1)
- break;
- goto swallow;
- }
-
- /* /..[^/] ... regurgitate and allow */
-
- if (issue_char(wsi, '.') < 0)
- return -1;
- if (issue_char(wsi, '.') < 0)
- return -1;
- ah->ups = URIPS_IDLE;
- break;
- }
-
- if (c == '?' && !enc &&
- !ah->frag_index[WSI_TOKEN_HTTP_URI_ARGS]) { /* start of URI args */
- if (ah->ues != URIES_IDLE)
- goto forbid;
-
- /* seal off uri header */
- if (issue_char(wsi, '\0') < 0)
- return -1;
-
- /* move to using WSI_TOKEN_HTTP_URI_ARGS */
- ah->nfrag++;
- if (ah->nfrag >= LWS_ARRAY_SIZE(ah->frags))
- goto excessive;
- ah->frags[ah->nfrag].offset = ++ah->pos;
- ah->frags[ah->nfrag].len = 0;
- ah->frags[ah->nfrag].nfrag = 0;
-
- ah->post_literal_equal = 0;
- ah->frag_index[WSI_TOKEN_HTTP_URI_ARGS] = ah->nfrag;
- ah->ups = URIPS_IDLE;
- goto swallow;
- }
-
- return LPUR_CONTINUE;
-
-swallow:
- return LPUR_SWALLOW;
-
-forbid:
- return LPUR_FORBID;
-
-excessive:
- return LPUR_EXCESSIVE;
-}
-
-static const unsigned char methods[] = {
- WSI_TOKEN_GET_URI,
- WSI_TOKEN_POST_URI,
- WSI_TOKEN_OPTIONS_URI,
- WSI_TOKEN_PUT_URI,
- WSI_TOKEN_PATCH_URI,
- WSI_TOKEN_DELETE_URI,
- WSI_TOKEN_CONNECT,
- WSI_TOKEN_HEAD_URI,
-};
-
-/*
- * possible returns:, -1 fail, 0 ok or 2, transition to raw
- */
-
-int LWS_WARN_UNUSED_RESULT
-lws_parse(struct lws *wsi, unsigned char *buf, int *len)
-{
- struct allocated_headers *ah = wsi->http.ah;
- struct lws_context *context = wsi->context;
- unsigned int n, m;
- unsigned char c;
- int r, pos;
-
- assert(wsi->http.ah);
-
- do {
- (*len)--;
- c = *buf++;
-
- switch (ah->parser_state) {
- default:
-
- lwsl_parser("WSI_TOK_(%d) '%c'\n", ah->parser_state, c);
-
- /* collect into malloc'd buffers */
- /* optional initial space swallow */
- if (!ah->frags[ah->frag_index[ah->parser_state]].len &&
- c == ' ')
- break;
-
- for (m = 0; m < LWS_ARRAY_SIZE(methods); m++)
- if (ah->parser_state == methods[m])
- break;
- if (m == LWS_ARRAY_SIZE(methods))
- /* it was not any of the methods */
- goto check_eol;
-
- /* special URI processing... end at space */
-
- if (c == ' ') {
- /* enforce starting with / */
- if (!ah->frags[ah->nfrag].len)
- if (issue_char(wsi, '/') < 0)
- return -1;
-
- if (ah->ups == URIPS_SEEN_SLASH_DOT_DOT) {
- /*
- * back up one dir level if possible
- * safe against header fragmentation because
- * the method URI can only be in 1 fragment
- */
- if (ah->frags[ah->nfrag].len > 2) {
- ah->pos--;
- ah->frags[ah->nfrag].len--;
- do {
- ah->pos--;
- ah->frags[ah->nfrag].len--;
- } while (ah->frags[ah->nfrag].len > 1 &&
- ah->data[ah->pos] != '/');
- }
- }
-
- /* begin parsing HTTP version: */
- if (issue_char(wsi, '\0') < 0)
- return -1;
- ah->parser_state = WSI_TOKEN_HTTP;
- goto start_fragment;
- }
-
- r = lws_parse_urldecode(wsi, &c);
- switch (r) {
- case LPUR_CONTINUE:
- break;
- case LPUR_SWALLOW:
- goto swallow;
- case LPUR_FORBID:
- goto forbid;
- case LPUR_EXCESSIVE:
- goto excessive;
- default:
- return -1;
- }
-check_eol:
- /* bail at EOL */
- if (ah->parser_state != WSI_TOKEN_CHALLENGE &&
- c == '\x0d') {
- if (ah->ues != URIES_IDLE)
- goto forbid;
-
- c = '\0';
- ah->parser_state = WSI_TOKEN_SKIPPING_SAW_CR;
- lwsl_parser("*\n");
- }
-
- n = issue_char(wsi, c);
- if ((int)n < 0)
- return -1;
- if (n > 0)
- ah->parser_state = WSI_TOKEN_SKIPPING;
-
-swallow:
- /* per-protocol end of headers management */
-
- if (ah->parser_state == WSI_TOKEN_CHALLENGE)
- goto set_parsing_complete;
- break;
-
- /* collecting and checking a name part */
- case WSI_TOKEN_NAME_PART:
- lwsl_parser("WSI_TOKEN_NAME_PART '%c' 0x%02X (role=0x%x) "
- "wsi->lextable_pos=%d\n", c, c, lwsi_role(wsi),
- ah->lextable_pos);
-
- if (c >= 'A' && c <= 'Z')
- c += 'a' - 'A';
-
- pos = ah->lextable_pos;
-
- while (1) {
- if (lextable[pos] & (1 << 7)) { /* 1-byte, fail on mismatch */
- if ((lextable[pos] & 0x7f) != c) {
-nope:
- ah->lextable_pos = -1;
- break;
- }
- /* fall thru */
- pos++;
- if (lextable[pos] == FAIL_CHAR)
- goto nope;
-
- ah->lextable_pos = pos;
- break;
- }
-
- if (lextable[pos] == FAIL_CHAR)
- goto nope;
-
- /* b7 = 0, end or 3-byte */
- if (lextable[pos] < FAIL_CHAR) { /* terminal marker */
- ah->lextable_pos = pos;
- break;
- }
-
- if (lextable[pos] == c) { /* goto */
- ah->lextable_pos = pos + (lextable[pos + 1]) +
- (lextable[pos + 2] << 8);
- break;
- }
-
- /* fall thru goto */
- pos += 3;
- /* continue */
- }
-
- /*
- * If it's h1, server needs to look out for unknown
- * methods...
- */
- if (ah->lextable_pos < 0 && lwsi_role_h1(wsi) &&
- lwsi_role_server(wsi)) {
- /* this is not a header we know about */
- for (m = 0; m < LWS_ARRAY_SIZE(methods); m++)
- if (ah->frag_index[methods[m]]) {
- /*
- * already had the method, no idea what
- * this crap from the client is, ignore
- */
- ah->parser_state = WSI_TOKEN_SKIPPING;
- break;
- }
- /*
- * hm it's an unknown http method from a client in fact,
- * it cannot be valid http
- */
- if (m == LWS_ARRAY_SIZE(methods)) {
- /*
- * are we set up to accept raw in these cases?
- */
- if (lws_check_opt(wsi->vhost->options,
- LWS_SERVER_OPTION_FALLBACK_TO_RAW))
- return 2; /* transition to raw */
-
- lwsl_info("Unknown method - dropping\n");
- goto forbid;
- }
- break;
- }
- /*
- * ...otherwise for a client, let him ignore unknown headers
- * coming from the server
- */
- if (ah->lextable_pos < 0) {
- ah->parser_state = WSI_TOKEN_SKIPPING;
- break;
- }
-
- if (lextable[ah->lextable_pos] < FAIL_CHAR) {
- /* terminal state */
-
- n = ((unsigned int)lextable[ah->lextable_pos] << 8) |
- lextable[ah->lextable_pos + 1];
-
- lwsl_parser("known hdr %d\n", n);
- for (m = 0; m < LWS_ARRAY_SIZE(methods); m++)
- if (n == methods[m] &&
- ah->frag_index[methods[m]]) {
- lwsl_warn("Duplicated method\n");
- return -1;
- }
-
- /*
- * WSORIGIN is protocol equiv to ORIGIN,
- * JWebSocket likes to send it, map to ORIGIN
- */
- if (n == WSI_TOKEN_SWORIGIN)
- n = WSI_TOKEN_ORIGIN;
-
- ah->parser_state = (enum lws_token_indexes)
- (WSI_TOKEN_GET_URI + n);
- ah->ups = URIPS_IDLE;
-
- if (context->token_limits)
- ah->current_token_limit = context->
- token_limits->token_limit[
- ah->parser_state];
- else
- ah->current_token_limit =
- wsi->context->max_http_header_data;
-
- if (ah->parser_state == WSI_TOKEN_CHALLENGE)
- goto set_parsing_complete;
-
- goto start_fragment;
- }
- break;
-
-start_fragment:
- ah->nfrag++;
-excessive:
- if (ah->nfrag == LWS_ARRAY_SIZE(ah->frags)) {
- lwsl_warn("More hdr frags than we can deal with\n");
- return -1;
- }
-
- ah->frags[ah->nfrag].offset = ah->pos;
- ah->frags[ah->nfrag].len = 0;
- ah->frags[ah->nfrag].nfrag = 0;
- ah->frags[ah->nfrag].flags = 2;
-
- n = ah->frag_index[ah->parser_state];
- if (!n) { /* first fragment */
- ah->frag_index[ah->parser_state] = ah->nfrag;
- ah->hdr_token_idx = ah->parser_state;
- break;
- }
- /* continuation */
- while (ah->frags[n].nfrag)
- n = ah->frags[n].nfrag;
- ah->frags[n].nfrag = ah->nfrag;
-
- if (issue_char(wsi, ' ') < 0)
- return -1;
- break;
-
- /* skipping arg part of a name we didn't recognize */
- case WSI_TOKEN_SKIPPING:
- lwsl_parser("WSI_TOKEN_SKIPPING '%c'\n", c);
-
- if (c == '\x0d')
- ah->parser_state = WSI_TOKEN_SKIPPING_SAW_CR;
- break;
-
- case WSI_TOKEN_SKIPPING_SAW_CR:
- lwsl_parser("WSI_TOKEN_SKIPPING_SAW_CR '%c'\n", c);
- if (ah->ues != URIES_IDLE)
- goto forbid;
- if (c == '\x0a') {
- ah->parser_state = WSI_TOKEN_NAME_PART;
- ah->lextable_pos = 0;
- } else
- ah->parser_state = WSI_TOKEN_SKIPPING;
- break;
- /* we're done, ignore anything else */
-
- case WSI_PARSING_COMPLETE:
- lwsl_parser("WSI_PARSING_COMPLETE '%c'\n", c);
- break;
- }
-
- } while (*len);
-
- return 0;
-
-set_parsing_complete:
- if (ah->ues != URIES_IDLE)
- goto forbid;
- if (lws_hdr_total_length(wsi, WSI_TOKEN_UPGRADE)) {
- if (lws_hdr_total_length(wsi, WSI_TOKEN_VERSION))
- wsi->rx_frame_type = /* temp for ws version index */
- atoi(lws_hdr_simple_ptr(wsi, WSI_TOKEN_VERSION));
-
- lwsl_parser("v%02d hdrs done\n", wsi->rx_frame_type);
- }
- ah->parser_state = WSI_PARSING_COMPLETE;
- wsi->hdr_parsing_completed = 1;
-
- return 0;
-
-forbid:
- lwsl_notice(" forbidding on uri sanitation\n");
- lws_return_http_status(wsi, HTTP_STATUS_FORBIDDEN, NULL);
-
- return -1;
-}
-
diff --git a/thirdparty/libwebsockets/roles/http/server/server.c b/thirdparty/libwebsockets/roles/http/server/server.c
deleted file mode 100644
index abd86dc9b5..0000000000
--- a/thirdparty/libwebsockets/roles/http/server/server.c
+++ /dev/null
@@ -1,2765 +0,0 @@
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010-2018 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- */
-
-#include "core/private.h"
-
-const char * const method_names[] = {
- "GET", "POST", "OPTIONS", "PUT", "PATCH", "DELETE", "CONNECT", "HEAD",
-#ifdef LWS_WITH_HTTP2
- ":path",
-#endif
- };
-
-/*
- * return 0: all done
- * 1: nonfatal error
- * <0: fatal error
- *
- * REQUIRES CONTEXT LOCK HELD
- */
-
-int
-_lws_vhost_init_server(const struct lws_context_creation_info *info,
- struct lws_vhost *vhost)
-{
- int n, opt = 1, limit = 1;
- lws_sockfd_type sockfd;
- struct lws_vhost *vh;
- struct lws *wsi;
- int m = 0, is;
-
- (void)method_names;
- (void)opt;
-
- if (info) {
- vhost->iface = info->iface;
- vhost->listen_port = info->port;
- }
-
- /* set up our external listening socket we serve on */
-
- if (vhost->listen_port == CONTEXT_PORT_NO_LISTEN ||
- vhost->listen_port == CONTEXT_PORT_NO_LISTEN_SERVER)
- return 0;
-
- vh = vhost->context->vhost_list;
- while (vh) {
- if (vh->listen_port == vhost->listen_port) {
- if (((!vhost->iface && !vh->iface) ||
- (vhost->iface && vh->iface &&
- !strcmp(vhost->iface, vh->iface))) &&
- vh->lserv_wsi
- ) {
- lwsl_notice(" using listen skt from vhost %s\n",
- vh->name);
- return 0;
- }
- }
- vh = vh->vhost_next;
- }
-
- if (vhost->iface) {
- /*
- * let's check before we do anything else about the disposition
- * of the interface he wants to bind to...
- */
- is = lws_socket_bind(vhost, LWS_SOCK_INVALID, vhost->listen_port, vhost->iface);
- lwsl_debug("initial if check says %d\n", is);
-deal:
-
- lws_start_foreach_llp(struct lws_vhost **, pv,
- vhost->context->no_listener_vhost_list) {
- if (is >= LWS_ITOSA_USABLE && *pv == vhost) {
- /* on the list and shouldn't be: remove it */
- lwsl_debug("deferred iface: removing vh %s\n", (*pv)->name);
- *pv = vhost->no_listener_vhost_list;
- vhost->no_listener_vhost_list = NULL;
- goto done_list;
- }
- if (is < LWS_ITOSA_USABLE && *pv == vhost)
- goto done_list;
- } lws_end_foreach_llp(pv, no_listener_vhost_list);
-
- /* not on the list... */
-
- if (is < LWS_ITOSA_USABLE) {
-
- /* ... but needs to be: so add it */
-
- lwsl_debug("deferred iface: adding vh %s\n", vhost->name);
- vhost->no_listener_vhost_list = vhost->context->no_listener_vhost_list;
- vhost->context->no_listener_vhost_list = vhost;
- }
-
-done_list:
-
- switch (is) {
- default:
- break;
- case LWS_ITOSA_NOT_EXIST:
- /* can't add it */
- if (info) /* first time */
- lwsl_err("VH %s: iface %s port %d DOESN'T EXIST\n",
- vhost->name, vhost->iface, vhost->listen_port);
- return 1;
- case LWS_ITOSA_NOT_USABLE:
- /* can't add it */
- if (info) /* first time */
- lwsl_err("VH %s: iface %s port %d NOT USABLE\n",
- vhost->name, vhost->iface, vhost->listen_port);
- return 1;
- }
- }
-
- (void)n;
-#if defined(__linux__)
-#ifdef LWS_WITH_UNIX_SOCK
- /*
- * A Unix domain sockets cannot be bound for several times, even if we set
- * the SO_REUSE* options on.
- * However, fortunately, each thread is able to independently listen when
- * running on a reasonably new Linux kernel. So we can safely assume
- * creating just one listening socket for a multi-threaded environment won't
- * fail in most cases.
- */
- if (!LWS_UNIX_SOCK_ENABLED(vhost))
-#endif
- limit = vhost->context->count_threads;
-#endif
-
- for (m = 0; m < limit; m++) {
-#ifdef LWS_WITH_UNIX_SOCK
- if (LWS_UNIX_SOCK_ENABLED(vhost))
- sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
- else
-#endif
-#ifdef LWS_WITH_IPV6
- if (LWS_IPV6_ENABLED(vhost))
- sockfd = socket(AF_INET6, SOCK_STREAM, 0);
- else
-#endif
- sockfd = socket(AF_INET, SOCK_STREAM, 0);
-
- if (sockfd == LWS_SOCK_INVALID) {
- lwsl_err("ERROR opening socket\n");
- return 1;
- }
-#if !defined(LWS_WITH_ESP32)
-#if (defined(WIN32) || defined(_WIN32)) && defined(SO_EXCLUSIVEADDRUSE)
- /*
- * only accept that we are the only listener on the port
- * https://msdn.microsoft.com/zh-tw/library/
- * windows/desktop/ms740621(v=vs.85).aspx
- *
- * for lws, to match Linux, we default to exclusive listen
- */
- if (!lws_check_opt(vhost->options,
- LWS_SERVER_OPTION_ALLOW_LISTEN_SHARE)) {
- if (setsockopt(sockfd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
- (const void *)&opt, sizeof(opt)) < 0) {
- lwsl_err("reuseaddr failed\n");
- compatible_close(sockfd);
- return -1;
- }
- } else
-#endif
-
- /*
- * 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;
- }
-
-#if defined(LWS_WITH_IPV6) && defined(IPV6_V6ONLY)
- if (LWS_IPV6_ENABLED(vhost) &&
- vhost->options & LWS_SERVER_OPTION_IPV6_V6ONLY_MODIFY) {
- int value = (vhost->options &
- LWS_SERVER_OPTION_IPV6_V6ONLY_VALUE) ? 1 : 0;
- if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY,
- (const void*)&value, sizeof(value)) < 0) {
- compatible_close(sockfd);
- return -1;
- }
- }
-#endif
-
-#if defined(__linux__) && defined(SO_REUSEPORT)
- /* keep coverity happy */
-#if LWS_MAX_SMP > 1
- n = 1;
-#else
- n = lws_check_opt(vhost->options,
- LWS_SERVER_OPTION_ALLOW_LISTEN_SHARE);
-#endif
- if (n && vhost->context->count_threads > 1)
- if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT,
- (const void *)&opt, sizeof(opt)) < 0) {
- compatible_close(sockfd);
- return -1;
- }
-#endif
-#endif
- lws_plat_set_socket_options(vhost, sockfd);
-
- is = lws_socket_bind(vhost, sockfd, vhost->listen_port, vhost->iface);
- /*
- * There is a race where the network device may come up and then
- * go away and fail here. So correctly handle unexpected failure
- * here despite we earlier confirmed it.
- */
- if (is < 0) {
- lwsl_info("%s: lws_socket_bind says %d\n", __func__, is);
- compatible_close(sockfd);
- goto deal;
- }
- vhost->listen_port = is;
-
- lwsl_debug("%s: lws_socket_bind says %d\n", __func__, is);
-
- wsi = lws_zalloc(sizeof(struct lws), "listen wsi");
- if (wsi == NULL) {
- lwsl_err("Out of mem\n");
- goto bail;
- }
- wsi->context = vhost->context;
- wsi->desc.sockfd = sockfd;
- lws_role_transition(wsi, 0, LRS_UNCONNECTED, &role_ops_listen);
- wsi->protocol = vhost->protocols;
- wsi->tsi = m;
- wsi->vhost = vhost;
- wsi->listener = 1;
-
- if (wsi->context->event_loop_ops->init_vhost_listen_wsi)
- wsi->context->event_loop_ops->init_vhost_listen_wsi(wsi);
-
- if (__insert_wsi_socket_into_fds(vhost->context, wsi)) {
- lwsl_notice("inserting wsi socket into fds failed\n");
- goto bail;
- }
-
- vhost->context->count_wsi_allocated++;
- vhost->lserv_wsi = wsi;
-
- n = listen(wsi->desc.sockfd, LWS_SOMAXCONN);
- if (n < 0) {
- lwsl_err("listen failed with error %d\n", LWS_ERRNO);
- vhost->lserv_wsi = NULL;
- vhost->context->count_wsi_allocated--;
- __remove_wsi_socket_from_fds(wsi);
- goto bail;
- }
- } /* for each thread able to independently listen */
-
- if (!lws_check_opt(vhost->context->options, LWS_SERVER_OPTION_EXPLICIT_VHOSTS)) {
-#ifdef LWS_WITH_UNIX_SOCK
- if (LWS_UNIX_SOCK_ENABLED(vhost))
- lwsl_info(" Listening on \"%s\"\n", vhost->iface);
- else
-#endif
- lwsl_info(" Listening on port %d\n", vhost->listen_port);
- }
-
- // info->port = vhost->listen_port;
-
- return 0;
-
-bail:
- compatible_close(sockfd);
-
- return -1;
-}
-
-struct lws_vhost *
-lws_select_vhost(struct lws_context *context, int port, const char *servername)
-{
- struct lws_vhost *vhost = context->vhost_list;
- const char *p;
- int n, m, colon;
-
- n = (int)strlen(servername);
- colon = n;
- p = strchr(servername, ':');
- if (p)
- colon = lws_ptr_diff(p, servername);
-
- /* Priotity 1: first try exact matches */
-
- while (vhost) {
- if (port == vhost->listen_port &&
- !strncmp(vhost->name, servername, colon)) {
- lwsl_info("SNI: Found: %s\n", servername);
- return vhost;
- }
- vhost = vhost->vhost_next;
- }
-
- /*
- * Priority 2: if no exact matches, try matching *.vhost-name
- * unintentional matches are possible but resolve to x.com for *.x.com
- * which is reasonable. If exact match exists we already chose it and
- * never reach here. SSL will still fail it if the cert doesn't allow
- * *.x.com.
- */
- vhost = context->vhost_list;
- while (vhost) {
- m = (int)strlen(vhost->name);
- if (port == vhost->listen_port &&
- m <= (colon - 2) &&
- servername[colon - m - 1] == '.' &&
- !strncmp(vhost->name, servername + colon - m, m)) {
- lwsl_info("SNI: Found %s on wildcard: %s\n",
- servername, vhost->name);
- return vhost;
- }
- vhost = vhost->vhost_next;
- }
-
- /* Priority 3: match the first vhost on our port */
-
- vhost = context->vhost_list;
- while (vhost) {
- if (port == vhost->listen_port) {
- lwsl_info("%s: vhost match to %s based on port %d\n",
- __func__, vhost->name, port);
- return vhost;
- }
- vhost = vhost->vhost_next;
- }
-
- /* no match */
-
- return NULL;
-}
-
-LWS_VISIBLE LWS_EXTERN const char *
-lws_get_mimetype(const char *file, const struct lws_http_mount *m)
-{
- int n = (int)strlen(file);
- const struct lws_protocol_vhost_options *pvo = NULL;
-
- if (m)
- pvo = m->extra_mimetypes;
-
- if (n < 5)
- return NULL;
-
- if (!strcmp(&file[n - 4], ".ico"))
- return "image/x-icon";
-
- if (!strcmp(&file[n - 4], ".gif"))
- return "image/gif";
-
- if (!strcmp(&file[n - 3], ".js"))
- return "text/javascript";
-
- if (!strcmp(&file[n - 4], ".png"))
- return "image/png";
-
- if (!strcmp(&file[n - 4], ".jpg"))
- return "image/jpeg";
-
- if (!strcmp(&file[n - 3], ".gz"))
- return "application/gzip";
-
- if (!strcmp(&file[n - 4], ".JPG"))
- return "image/jpeg";
-
- if (!strcmp(&file[n - 5], ".html"))
- return "text/html";
-
- if (!strcmp(&file[n - 4], ".css"))
- return "text/css";
-
- if (!strcmp(&file[n - 4], ".txt"))
- return "text/plain";
-
- if (!strcmp(&file[n - 4], ".svg"))
- return "image/svg+xml";
-
- if (!strcmp(&file[n - 4], ".ttf"))
- return "application/x-font-ttf";
-
- if (!strcmp(&file[n - 4], ".otf"))
- return "application/font-woff";
-
- if (!strcmp(&file[n - 5], ".woff"))
- return "application/font-woff";
-
- if (!strcmp(&file[n - 4], ".xml"))
- return "application/xml";
-
- while (pvo) {
- if (pvo->name[0] == '*') /* ie, match anything */
- return pvo->value;
-
- if (!strcmp(&file[n - strlen(pvo->name)], pvo->name))
- return pvo->value;
-
- pvo = pvo->next;
- }
-
- return NULL;
-}
-static lws_fop_flags_t
-lws_vfs_prepare_flags(struct lws *wsi)
-{
- lws_fop_flags_t f = 0;
-
- if (!lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_ACCEPT_ENCODING))
- return f;
-
- if (strstr(lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_ACCEPT_ENCODING),
- "gzip")) {
- lwsl_info("client indicates GZIP is acceptable\n");
- f |= LWS_FOP_FLAG_COMPR_ACCEPTABLE_GZIP;
- }
-
- return f;
-}
-
-static int
-lws_http_serve(struct lws *wsi, char *uri, const char *origin,
- const struct lws_http_mount *m)
-{
- const struct lws_protocol_vhost_options *pvo = m->interpret;
- struct lws_process_html_args args;
- const char *mimetype;
-#if !defined(_WIN32_WCE)
- const struct lws_plat_file_ops *fops;
- const char *vpath;
- lws_fop_flags_t fflags = LWS_O_RDONLY;
-#if defined(WIN32) && defined(LWS_HAVE__STAT32I64)
- struct _stat32i64 st;
-#else
- struct stat st;
-#endif
- 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) && !defined(LWS_WITH_ESP32)
- size_t len;
-#endif
- int n;
-
- wsi->handling_404 = 0;
- if (!wsi->vhost)
- return -1;
-
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- if (wsi->vhost->http.error_document_404 &&
- !strcmp(uri, wsi->vhost->http.error_document_404))
- wsi->handling_404 = 1;
-#endif
-
- lws_snprintf(path, sizeof(path) - 1, "%s/%s", origin, uri);
-
-#if !defined(_WIN32_WCE)
-
- fflags |= lws_vfs_prepare_flags(wsi);
-
- do {
- spin++;
- fops = lws_vfs_select_fops(wsi->context->fops, path, &vpath);
-
- if (wsi->http.fop_fd)
- lws_vfs_file_close(&wsi->http.fop_fd);
-
- wsi->http.fop_fd = fops->LWS_FOP_OPEN(wsi->context->fops,
- path, vpath, &fflags);
- if (!wsi->http.fop_fd) {
- lwsl_info("%s: Unable to open '%s': errno %d\n",
- __func__, path, errno);
-
- return -1;
- }
-
- /* if it can't be statted, don't try */
- if (fflags & LWS_FOP_FLAG_VIRTUAL)
- break;
-#if defined(LWS_WITH_ESP32)
- break;
-#endif
-#if !defined(WIN32)
- if (fstat(wsi->http.fop_fd->fd, &st)) {
- lwsl_info("unable to stat %s\n", path);
- goto bail;
- }
-#else
-#if defined(LWS_HAVE__STAT32I64)
- if (_stat32i64(path, &st)) {
- lwsl_info("unable to stat %s\n", path);
- goto bail;
- }
-#else
- if (stat(path, &st)) {
- lwsl_info("unable to stat %s\n", path);
- goto bail;
- }
-#endif
-#endif
-
- wsi->http.fop_fd->mod_time = (uint32_t)st.st_mtime;
- fflags |= LWS_FOP_FLAG_MOD_TIME_VALID;
-
-#if !defined(WIN32) && !defined(LWS_WITH_ESP32)
- if ((S_IFMT & st.st_mode) == S_IFLNK) {
- len = readlink(path, sym, sizeof(sym) - 1);
- if (len) {
- lwsl_err("Failed to read link %s\n", path);
- goto bail;
- }
- sym[len] = '\0';
- lwsl_debug("symlink %s -> %s\n", path, sym);
- lws_snprintf(path, sizeof(path) - 1, "%s", sym);
- }
-#endif
- if ((S_IFMT & st.st_mode) == S_IFDIR) {
- lwsl_debug("default filename append to dir\n");
- lws_snprintf(path, sizeof(path) - 1, "%s/%s/index.html",
- origin, uri);
- }
-
- } while ((S_IFMT & st.st_mode) != S_IFREG && spin < 5);
-
- if (spin == 5)
- lwsl_err("symlink loop %s \n", path);
-
- n = sprintf(sym, "%08llX%08lX",
- (unsigned long long)lws_vfs_get_length(wsi->http.fop_fd),
- (unsigned long)lws_vfs_get_mod_time(wsi->http.fop_fd));
-
- /* disable ranges if IF_RANGE token invalid */
-
- if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_IF_RANGE))
- if (strcmp(sym, lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_IF_RANGE)))
- /* differs - defeat Range: */
- wsi->http.ah->frag_index[WSI_TOKEN_HTTP_RANGE] = 0;
-
- if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_IF_NONE_MATCH)) {
- /*
- * he thinks he has some version of it already,
- * check if the tag matches
- */
- if (!strcmp(sym, lws_hdr_simple_ptr(wsi,
- WSI_TOKEN_HTTP_IF_NONE_MATCH))) {
-
- lwsl_debug("%s: ETAG match %s %s\n", __func__,
- uri, origin);
-
- /* we don't need to send the payload */
- if (lws_add_http_header_status(wsi,
- HTTP_STATUS_NOT_MODIFIED, &p, end))
- return -1;
-
- if (lws_add_http_header_by_token(wsi,
- WSI_TOKEN_HTTP_ETAG,
- (unsigned char *)sym, n, &p, end))
- return -1;
-
- if (lws_finalize_http_header(wsi, &p, end))
- return -1;
-
- n = lws_write(wsi, start, p - start,
- LWS_WRITE_HTTP_HEADERS |
- LWS_WRITE_H2_STREAM_END);
- if (n != (p - start)) {
- lwsl_err("_write returned %d from %ld\n", n,
- (long)(p - start));
- return -1;
- }
-
- lws_vfs_file_close(&wsi->http.fop_fd);
-
- return lws_http_transaction_completed(wsi);
- }
- }
-
- if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_ETAG,
- (unsigned char *)sym, n, &p, end))
- return -1;
-#endif
-
- mimetype = lws_get_mimetype(path, m);
- if (!mimetype) {
- lwsl_err("unknown mimetype for %s\n", path);
- goto bail;
- }
- if (!mimetype[0])
- lwsl_debug("sending no mimetype for %s\n", path);
-
- wsi->sending_chunked = 0;
-
- /*
- * check if this is in the list of file suffixes to be interpreted by
- * a protocol
- */
- while (pvo) {
- n = (int)strlen(path);
- if (n > (int)strlen(pvo->name) &&
- !strcmp(&path[n - strlen(pvo->name)], pvo->name)) {
- wsi->interpreting = 1;
- if (!wsi->http2_substream)
- wsi->sending_chunked = 1;
- wsi->protocol_interpret_idx =
- (char)(lws_intptr_t)pvo->value;
- lwsl_info("want %s interpreted by %s\n", path,
- wsi->vhost->protocols[
- (int)(lws_intptr_t)(pvo->value)].name);
- wsi->protocol = &wsi->vhost->protocols[
- (int)(lws_intptr_t)(pvo->value)];
- if (lws_ensure_user_space(wsi))
- return -1;
- break;
- }
- pvo = pvo->next;
- }
-
- if (m->protocol) {
- const struct lws_protocols *pp = lws_vhost_name_to_protocol(
- wsi->vhost, m->protocol);
-
- if (lws_bind_protocol(wsi, pp))
- return 1;
- args.p = (char *)p;
- args.max_len = lws_ptr_diff(end, p);
- if (pp->callback(wsi, LWS_CALLBACK_ADD_HEADERS,
- wsi->user_space, &args, 0))
- return -1;
- p = (unsigned char *)args.p;
- }
-
- n = lws_serve_http_file(wsi, path, mimetype, (char *)start,
- lws_ptr_diff(p, start));
-
- if (n < 0 || ((n > 0) && lws_http_transaction_completed(wsi)))
- return -1; /* error or can't reuse connection: close the socket */
-
- return 0;
-bail:
-
- return -1;
-}
-
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
-const struct lws_http_mount *
-lws_find_mount(struct lws *wsi, const char *uri_ptr, int uri_len)
-{
- const struct lws_http_mount *hm, *hit = NULL;
- int best = 0;
-
- hm = wsi->vhost->http.mount_list;
- while (hm) {
- if (uri_len >= hm->mountpoint_len &&
- !strncmp(uri_ptr, hm->mountpoint, hm->mountpoint_len) &&
- (uri_ptr[hm->mountpoint_len] == '\0' ||
- uri_ptr[hm->mountpoint_len] == '/' ||
- hm->mountpoint_len == 1)
- ) {
- if (hm->origin_protocol == LWSMPRO_CALLBACK ||
- ((hm->origin_protocol == LWSMPRO_CGI ||
- lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI) ||
- (wsi->http2_substream &&
- lws_hdr_total_length(wsi,
- WSI_TOKEN_HTTP_COLON_PATH)) ||
- hm->protocol) &&
- hm->mountpoint_len > best)) {
- best = hm->mountpoint_len;
- hit = hm;
- }
- }
- hm = hm->mount_next;
- }
-
- return hit;
-}
-#endif
-
-#if !defined(LWS_WITH_ESP32)
-static int
-lws_find_string_in_file(const char *filename, const char *string, int stringlen)
-{
- char buf[128];
- int fd, match = 0, pos = 0, n = 0, hit = 0;
-
- fd = lws_open(filename, O_RDONLY);
- if (fd < 0) {
- lwsl_err("can't open auth file: %s\n", filename);
- return 0;
- }
-
- while (1) {
- if (pos == n) {
- n = read(fd, buf, sizeof(buf));
- if (n <= 0) {
- if (match == stringlen)
- hit = 1;
- break;
- }
- pos = 0;
- }
-
- if (match == stringlen) {
- if (buf[pos] == '\r' || buf[pos] == '\n') {
- hit = 1;
- break;
- }
- match = 0;
- }
-
- if (buf[pos] == string[match])
- match++;
- else
- match = 0;
-
- pos++;
- }
-
- close(fd);
-
- return hit;
-}
-#endif
-
-static int
-lws_unauthorised_basic_auth(struct lws *wsi)
-{
- struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
- unsigned char *start = pt->serv_buf + LWS_PRE,
- *p = start, *end = p + 512;
- char buf[64];
- int n;
-
- /* no auth... tell him it is required */
-
- if (lws_add_http_header_status(wsi, HTTP_STATUS_UNAUTHORIZED, &p, end))
- return -1;
-
- n = lws_snprintf(buf, sizeof(buf), "Basic realm=\"lwsws\"");
- if (lws_add_http_header_by_token(wsi,
- WSI_TOKEN_HTTP_WWW_AUTHENTICATE,
- (unsigned char *)buf, n, &p, end))
- return -1;
-
- if (lws_finalize_http_header(wsi, &p, end))
- return -1;
-
- n = lws_write(wsi, start, p - start, LWS_WRITE_HTTP_HEADERS |
- LWS_WRITE_H2_STREAM_END);
- if (n < 0)
- return -1;
-
- return lws_http_transaction_completed(wsi);
-
-}
-
-int lws_clean_url(char *p)
-{
- if (p[0] == 'h' && p[1] == 't' && p[2] == 't' && p[3] == 'p') {
- p += 4;
- if (*p == 's')
- p++;
- if (*p == ':') {
- p++;
- if (*p == '/')
- p++;
- }
- }
-
- while (*p) {
- if (p[0] == '/' && p[1] == '/') {
- char *p1 = p;
- while (*p1) {
- *p1 = p1[1];
- p1++;
- }
- continue;
- }
- p++;
- }
-
- return 0;
-}
-
-static const unsigned char methods[] = {
- WSI_TOKEN_GET_URI,
- WSI_TOKEN_POST_URI,
- WSI_TOKEN_OPTIONS_URI,
- WSI_TOKEN_PUT_URI,
- WSI_TOKEN_PATCH_URI,
- WSI_TOKEN_DELETE_URI,
- WSI_TOKEN_CONNECT,
- WSI_TOKEN_HEAD_URI,
-#ifdef LWS_WITH_HTTP2
- WSI_TOKEN_HTTP_COLON_PATH,
-#endif
-};
-
-static int
-lws_http_get_uri_and_method(struct lws *wsi, char **puri_ptr, int *puri_len)
-{
- int n, count = 0;
-
- for (n = 0; n < (int)LWS_ARRAY_SIZE(methods); n++)
- if (lws_hdr_total_length(wsi, methods[n]))
- count++;
- if (!count) {
- lwsl_warn("Missing URI in HTTP request\n");
- return -1;
- }
-
- if (count != 1 &&
- !(wsi->http2_substream &&
- lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COLON_PATH))) {
- lwsl_warn("multiple methods?\n");
- return -1;
- }
-
- for (n = 0; n < (int)LWS_ARRAY_SIZE(methods); n++)
- if (lws_hdr_total_length(wsi, methods[n])) {
- *puri_ptr = lws_hdr_simple_ptr(wsi, methods[n]);
- *puri_len = lws_hdr_total_length(wsi, methods[n]);
- return n;
- }
-
- return -1;
-}
-
-int
-lws_http_action(struct lws *wsi)
-{
- struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
- enum http_connection_type connection_type;
- enum http_version request_version;
- char content_length_str[32];
- struct lws_process_html_args args;
- const struct lws_http_mount *hit = NULL;
- unsigned int n;
- char http_version_str[10];
- char http_conn_str[20];
- int http_version_len;
- char *uri_ptr = NULL, *s;
- int uri_len = 0, meth;
- static const char * const oprot[] = {
- "http://", "https://"
- };
-
- meth = lws_http_get_uri_and_method(wsi, &uri_ptr, &uri_len);
- if (meth < 0 || meth >= (int)LWS_ARRAY_SIZE(method_names))
- goto bail_nuke_ah;
-
- /* we insist on absolute paths */
-
- if (!uri_ptr || uri_ptr[0] != '/') {
- lws_return_http_status(wsi, HTTP_STATUS_FORBIDDEN, NULL);
-
- goto bail_nuke_ah;
- }
-
- lwsl_info("Method: '%s' (%d), request for '%s'\n", method_names[meth],
- meth, uri_ptr);
-
- if (wsi->role_ops && wsi->role_ops->check_upgrades)
- switch (wsi->role_ops->check_upgrades(wsi)) {
- case LWS_UPG_RET_DONE:
- return 0;
- case LWS_UPG_RET_CONTINUE:
- break;
- case LWS_UPG_RET_BAIL:
- goto bail_nuke_ah;
- }
-
- if (lws_ensure_user_space(wsi))
- goto bail_nuke_ah;
-
- /* HTTP header had a content length? */
-
- wsi->http.rx_content_length = 0;
- if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI) ||
- lws_hdr_total_length(wsi, WSI_TOKEN_PATCH_URI) ||
- lws_hdr_total_length(wsi, WSI_TOKEN_PUT_URI))
- wsi->http.rx_content_length = 100 * 1024 * 1024;
-
- if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH)) {
- lws_hdr_copy(wsi, content_length_str,
- sizeof(content_length_str) - 1,
- WSI_TOKEN_HTTP_CONTENT_LENGTH);
- wsi->http.rx_content_length = atoll(content_length_str);
- }
-
- if (wsi->http2_substream) {
- wsi->http.request_version = HTTP_VERSION_2;
- } else {
- /* http_version? Default to 1.0, override with token: */
- request_version = HTTP_VERSION_1_0;
-
- /* Works for single digit HTTP versions. : */
- http_version_len = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP);
- if (http_version_len > 7) {
- lws_hdr_copy(wsi, http_version_str,
- sizeof(http_version_str) - 1,
- WSI_TOKEN_HTTP);
- if (http_version_str[5] == '1' &&
- http_version_str[7] == '1')
- request_version = HTTP_VERSION_1_1;
- }
- wsi->http.request_version = request_version;
-
- /* HTTP/1.1 defaults to "keep-alive", 1.0 to "close" */
- if (request_version == HTTP_VERSION_1_1)
- connection_type = HTTP_CONNECTION_KEEP_ALIVE;
- else
- connection_type = HTTP_CONNECTION_CLOSE;
-
- /* Override default if http "Connection:" header: */
- if (lws_hdr_total_length(wsi, WSI_TOKEN_CONNECTION)) {
- lws_hdr_copy(wsi, http_conn_str,
- sizeof(http_conn_str) - 1,
- WSI_TOKEN_CONNECTION);
- http_conn_str[sizeof(http_conn_str) - 1] = '\0';
- if (!strcasecmp(http_conn_str, "keep-alive"))
- connection_type = HTTP_CONNECTION_KEEP_ALIVE;
- else
- if (!strcasecmp(http_conn_str, "close"))
- connection_type = HTTP_CONNECTION_CLOSE;
- }
- wsi->http.connection_type = connection_type;
- }
-
- n = wsi->protocol->callback(wsi, LWS_CALLBACK_FILTER_HTTP_CONNECTION,
- wsi->user_space, uri_ptr, uri_len);
- if (n) {
- lwsl_info("LWS_CALLBACK_HTTP closing\n");
-
- return 1;
- }
- /*
- * if there is content supposed to be coming,
- * put a timeout on it having arrived
- */
- lws_set_timeout(wsi, PENDING_TIMEOUT_HTTP_CONTENT,
- wsi->context->timeout_secs);
-#ifdef LWS_WITH_TLS
- if (wsi->tls.redirect_to_https) {
- /*
- * we accepted http:// only so we could redirect to
- * https://, so issue the redirect. Create the redirection
- * URI from the host: header and ignore the path part
- */
- unsigned char *start = pt->serv_buf + LWS_PRE, *p = start,
- *end = p + 512;
-
- if (!lws_hdr_total_length(wsi, WSI_TOKEN_HOST))
- goto bail_nuke_ah;
-
- n = sprintf((char *)end, "https://%s/",
- lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST));
-
- n = lws_http_redirect(wsi, HTTP_STATUS_MOVED_PERMANENTLY,
- end, n, &p, end);
- if ((int)n < 0)
- goto bail_nuke_ah;
-
- return lws_http_transaction_completed(wsi);
- }
-#endif
-
-#ifdef LWS_WITH_ACCESS_LOG
- lws_prepare_access_log_info(wsi, uri_ptr, meth);
-#endif
-
- /* can we serve it from the mount list? */
-
- hit = lws_find_mount(wsi, uri_ptr, uri_len);
- if (!hit) {
- /* deferred cleanup and reset to protocols[0] */
-
- lwsl_info("no hit\n");
-
- if (lws_bind_protocol(wsi, &wsi->vhost->protocols[0]))
- return 1;
-
- lwsi_set_state(wsi, LRS_DOING_TRANSACTION);
-
- n = wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP,
- wsi->user_space, uri_ptr, uri_len);
-
- goto after;
- }
-
- s = uri_ptr + hit->mountpoint_len;
-
- /*
- * if we have a mountpoint like https://xxx.com/yyy
- * there is an implied / at the end for our purposes since
- * we can only mount on a "directory".
- *
- * But if we just go with that, the browser cannot understand
- * that he is actually looking down one "directory level", so
- * even though we give him /yyy/abc.html he acts like the
- * current directory level is /. So relative urls like "x.png"
- * wrongly look outside the mountpoint.
- *
- * Therefore if we didn't come in on a url with an explicit
- * / at the end, we must redirect to add it so the browser
- * understands he is one "directory level" down.
- */
- if ((hit->mountpoint_len > 1 ||
- (hit->origin_protocol == LWSMPRO_REDIR_HTTP ||
- hit->origin_protocol == LWSMPRO_REDIR_HTTPS)) &&
- (*s != '/' ||
- (hit->origin_protocol == LWSMPRO_REDIR_HTTP ||
- hit->origin_protocol == LWSMPRO_REDIR_HTTPS)) &&
- (hit->origin_protocol != LWSMPRO_CGI &&
- hit->origin_protocol != LWSMPRO_CALLBACK)) {
- unsigned char *start = pt->serv_buf + LWS_PRE,
- *p = start, *end = p + 512;
-
- lwsl_debug("Doing 301 '%s' org %s\n", s, hit->origin);
-
- /* > at start indicates deal with by redirect */
- if (hit->origin_protocol == LWSMPRO_REDIR_HTTP ||
- hit->origin_protocol == LWSMPRO_REDIR_HTTPS)
- n = lws_snprintf((char *)end, 256, "%s%s",
- oprot[hit->origin_protocol & 1],
- hit->origin);
- else {
- if (!lws_hdr_total_length(wsi, WSI_TOKEN_HOST)) {
- if (!lws_hdr_total_length(wsi,
- WSI_TOKEN_HTTP_COLON_AUTHORITY))
- goto bail_nuke_ah;
- n = lws_snprintf((char *)end, 256,
- "%s%s%s/", oprot[!!lws_is_ssl(wsi)],
- lws_hdr_simple_ptr(wsi,
- WSI_TOKEN_HTTP_COLON_AUTHORITY),
- uri_ptr);
- } else
- n = lws_snprintf((char *)end, 256,
- "%s%s%s/", oprot[!!lws_is_ssl(wsi)],
- lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST),
- uri_ptr);
- }
-
- lws_clean_url((char *)end);
- n = lws_http_redirect(wsi, HTTP_STATUS_MOVED_PERMANENTLY,
- end, n, &p, end);
- if ((int)n < 0)
- goto bail_nuke_ah;
-
- return lws_http_transaction_completed(wsi);
- }
-
- /* basic auth? */
-
- if (hit->basic_auth_login_file) {
- char b64[160], plain[(sizeof(b64) * 3) / 4];
- int m;
-
- /* Did he send auth? */
- if (!lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_AUTHORIZATION))
- return lws_unauthorised_basic_auth(wsi);
-
- n = HTTP_STATUS_FORBIDDEN;
-
- m = lws_hdr_copy(wsi, b64, sizeof(b64),
- WSI_TOKEN_HTTP_AUTHORIZATION);
- if (m < 7) {
- lwsl_err("b64 auth too long\n");
- goto transaction_result_n;
- }
-
- b64[5] = '\0';
- if (strcasecmp(b64, "Basic")) {
- lwsl_err("auth missing basic: %s\n", b64);
- goto transaction_result_n;
- }
-
- /* It'll be like Authorization: Basic QWxhZGRpbjpPcGVuU2VzYW1l */
-
- m = lws_b64_decode_string(b64 + 6, plain, sizeof(plain));
- if (m < 0) {
- lwsl_err("plain auth too long\n");
- goto transaction_result_n;
- }
-
- if (!lws_find_string_in_file(hit->basic_auth_login_file,
- plain, m)) {
- lwsl_err("basic auth lookup failed\n");
- return lws_unauthorised_basic_auth(wsi);
- }
-
- lwsl_info("basic auth accepted\n");
-
- /* accept the auth */
- }
-
-#if defined(LWS_WITH_HTTP_PROXY)
- /*
- * The mount is a reverse proxy?
- */
-
- if (hit->origin_protocol == LWSMPRO_HTTPS ||
- hit->origin_protocol == LWSMPRO_HTTP) {
- struct lws_client_connect_info i;
- char ads[96], rpath[256], *pcolon, *pslash, *p;
- int n, na;
-
- memset(&i, 0, sizeof(i));
- i.context = lws_get_context(wsi);
-
- pcolon = strchr(hit->origin, ':');
- pslash = strchr(hit->origin, '/');
- if (!pslash) {
- lwsl_err("Proxy mount origin '%s' must have /\n",
- hit->origin);
- return -1;
- }
- if (pcolon > pslash)
- pcolon = NULL;
-
- if (pcolon)
- n = pcolon - hit->origin;
- else
- n = pslash - hit->origin;
-
- if (n >= (int)sizeof(ads) - 2)
- n = sizeof(ads) - 2;
-
- memcpy(ads, hit->origin, n);
- ads[n] = '\0';
-
- i.address = ads;
- i.port = 80;
- if (hit->origin_protocol == LWSMPRO_HTTPS) {
- i.port = 443;
- i.ssl_connection = 1;
- }
- if (pcolon)
- i.port = atoi(pcolon + 1);
-
- lws_snprintf(rpath, sizeof(rpath) - 1, "/%s/%s", pslash + 1,
- uri_ptr + hit->mountpoint_len);
- lws_clean_url(rpath);
- na = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_URI_ARGS);
- if (na) {
- p = rpath + strlen(rpath);
- *p++ = '?';
- lws_hdr_copy(wsi, p, &rpath[sizeof(rpath) - 1] - p,
- WSI_TOKEN_HTTP_URI_ARGS);
- while (--na) {
- if (*p == '\0')
- *p = '&';
- p++;
- }
- }
-
-
- i.path = rpath;
- i.host = i.address;
- i.origin = NULL;
- i.method = "GET";
- i.parent_wsi = wsi;
- i.uri_replace_from = hit->origin;
- i.uri_replace_to = hit->mountpoint;
-
- lwsl_notice("proxying to %s port %d url %s, ssl %d, "
- "from %s, to %s\n",
- i.address, i.port, i.path, i.ssl_connection,
- i.uri_replace_from, i.uri_replace_to);
-
- if (!lws_client_connect_via_info(&i)) {
- lwsl_err("proxy connect fail\n");
- return 1;
- }
-
- return 0;
- }
-#endif
-
- /*
- * A particular protocol callback is mounted here?
- *
- * For the duration of this http transaction, bind us to the
- * associated protocol
- */
- if (hit->origin_protocol == LWSMPRO_CALLBACK || hit->protocol) {
- const struct lws_protocols *pp;
- const char *name = hit->origin;
- if (hit->protocol)
- name = hit->protocol;
-
- pp = lws_vhost_name_to_protocol(wsi->vhost, name);
- if (!pp) {
- n = -1;
- lwsl_err("Unable to find plugin '%s'\n",
- hit->origin);
- return 1;
- }
-
- if (lws_bind_protocol(wsi, pp))
- return 1;
-
- args.p = uri_ptr;
- args.len = uri_len;
- args.max_len = hit->auth_mask;
- args.final = 0; /* used to signal callback dealt with it */
- args.chunked = 0;
-
- n = wsi->protocol->callback(wsi,
- LWS_CALLBACK_CHECK_ACCESS_RIGHTS,
- wsi->user_space, &args, 0);
- if (n) {
- lws_return_http_status(wsi, HTTP_STATUS_UNAUTHORIZED,
- NULL);
- goto bail_nuke_ah;
- }
- if (args.final) /* callback completely handled it well */
- return 0;
-
- if (hit->cgienv && wsi->protocol->callback(wsi,
- LWS_CALLBACK_HTTP_PMO,
- wsi->user_space, (void *)hit->cgienv, 0))
- return 1;
-
- if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI)) {
- n = wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP,
- wsi->user_space,
- uri_ptr + hit->mountpoint_len,
- uri_len - hit->mountpoint_len);
- goto after;
- }
- }
-
-#ifdef LWS_WITH_CGI
- /* did we hit something with a cgi:// origin? */
- if (hit->origin_protocol == LWSMPRO_CGI) {
- const char *cmd[] = {
- NULL, /* replace with cgi path */
- NULL
- };
-
- lwsl_debug("%s: cgi\n", __func__);
- cmd[0] = hit->origin;
-
- n = 5;
- if (hit->cgi_timeout)
- n = hit->cgi_timeout;
-
- n = lws_cgi(wsi, cmd, hit->mountpoint_len, n,
- hit->cgienv);
- if (n) {
- lwsl_err("%s: cgi failed\n", __func__);
- return -1;
- }
-
- goto deal_body;
- }
-#endif
-
- n = (int)strlen(s);
- if (s[0] == '\0' || (n == 1 && s[n - 1] == '/'))
- s = (char *)hit->def;
- if (!s)
- s = "index.html";
-
- wsi->cache_secs = hit->cache_max_age;
- wsi->cache_reuse = hit->cache_reusable;
- wsi->cache_revalidate = hit->cache_revalidate;
- wsi->cache_intermediaries = hit->cache_intermediaries;
-
- n = 1;
- if (hit->origin_protocol == LWSMPRO_FILE)
- n = lws_http_serve(wsi, s, hit->origin, hit);
- if (n) {
- /*
- * lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL);
- */
- if (hit->protocol) {
- const struct lws_protocols *pp =
- lws_vhost_name_to_protocol(
- wsi->vhost, hit->protocol);
-
- if (lws_bind_protocol(wsi, pp))
- return 1;
-
- n = pp->callback(wsi, LWS_CALLBACK_HTTP,
- wsi->user_space,
- uri_ptr + hit->mountpoint_len,
- uri_len - hit->mountpoint_len);
- } else
- n = wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP,
- wsi->user_space, uri_ptr, uri_len);
- }
-
-after:
- if (n) {
- lwsl_info("LWS_CALLBACK_HTTP closing\n");
-
- return 1;
- }
-
-#ifdef LWS_WITH_CGI
-deal_body:
-#endif
- /*
- * If we're not issuing a file, check for content_length or
- * HTTP keep-alive. No keep-alive header allocation for
- * ISSUING_FILE, as this uses HTTP/1.0.
- *
- * In any case, return 0 and let lws_read decide how to
- * proceed based on state
- */
- if (lwsi_state(wsi) != LRS_ISSUING_FILE) {
- /* Prepare to read body if we have a content length: */
- lwsl_debug("wsi->http.rx_content_length %lld %d %d\n",
- (long long)wsi->http.rx_content_length,
- wsi->upgraded_to_http2, wsi->http2_substream);
- if (wsi->http.rx_content_length > 0) {
- struct lws_tokens ebuf;
- int m;
-
- lwsi_set_state(wsi, LRS_BODY);
- lwsl_info("%s: %p: LRS_BODY state set (0x%x)\n",
- __func__, wsi, wsi->wsistate);
- wsi->http.rx_content_remain =
- wsi->http.rx_content_length;
-
- /*
- * At this point we have transitioned from deferred
- * action to expecting BODY on the stream wsi, if it's
- * in a bundle like h2. So if the stream wsi has its
- * own buflist, we need to deal with that first.
- */
-
- while (1) {
- ebuf.len = (int)lws_buflist_next_segment_len(
- &wsi->buflist, (uint8_t **)&ebuf.token);
- if (!ebuf.len)
- break;
- lwsl_notice("%s: consuming %d\n", __func__, (int)ebuf.len);
- m = lws_read_h1(wsi, (uint8_t *)ebuf.token, ebuf.len);
- if (m < 0)
- return -1;
-
- if (lws_buflist_aware_consume(wsi, &ebuf, m, 1))
- return -1;
- }
- }
- }
-
- return 0;
-
-bail_nuke_ah:
- lws_header_table_detach(wsi, 1);
-
- return 1;
-
-transaction_result_n:
- lws_return_http_status(wsi, n, NULL);
-
- return lws_http_transaction_completed(wsi);
-}
-
-int
-lws_handshake_server(struct lws *wsi, unsigned char **buf, size_t len)
-{
- struct lws_context *context = lws_get_context(wsi);
- unsigned char *obuf = *buf;
-#if defined(LWS_WITH_HTTP2)
- char tbuf[128], *p;
-#endif
- size_t olen = len;
- int n = 0, m, i;
-
- if (len >= 10000000) {
- lwsl_err("%s: assert: len %ld\n", __func__, (long)len);
- assert(0);
- }
-
- if (!wsi->http.ah) {
- lwsl_err("%s: assert: NULL ah\n", __func__);
- assert(0);
- }
-
- while (len) {
- if (!lwsi_role_server(wsi) || !lwsi_role_http(wsi)) {
- lwsl_err("%s: bad wsi role 0x%x\n", __func__,
- lwsi_role(wsi));
- goto bail_nuke_ah;
- }
-
- i = (int)len;
- m = lws_parse(wsi, *buf, &i);
- lwsl_info("%s: parsed count %d\n", __func__, (int)len - i);
- (*buf) += (int)len - i;
- len = i;
- if (m) {
- if (m == 2) {
- /*
- * we are transitioning from http with
- * an AH, to raw. Drop the ah and set
- * the mode.
- */
-raw_transition:
- lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
- lws_bind_protocol(wsi, &wsi->vhost->protocols[
- wsi->vhost->
- raw_protocol_index]);
- lwsl_info("transition to raw vh %s prot %d\n",
- wsi->vhost->name,
- wsi->vhost->raw_protocol_index);
- if ((wsi->protocol->callback)(wsi,
- LWS_CALLBACK_RAW_ADOPT,
- wsi->user_space, NULL, 0))
- goto bail_nuke_ah;
-
- lws_role_transition(wsi, 0, LRS_ESTABLISHED,
- &role_ops_raw_skt);
- lws_header_table_detach(wsi, 1);
-
- if (m == 2 && (wsi->protocol->callback)(wsi,
- LWS_CALLBACK_RAW_RX,
- wsi->user_space, obuf, olen))
- return 1;
-
- return 0;
- }
- lwsl_info("lws_parse failed\n");
- goto bail_nuke_ah;
- }
-
- if (wsi->http.ah->parser_state != WSI_PARSING_COMPLETE)
- continue;
-
- lwsl_parser("%s: lws_parse sees parsing complete\n", __func__);
-
- /* select vhost */
-
- if (lws_hdr_total_length(wsi, WSI_TOKEN_HOST)) {
- struct lws_vhost *vhost = lws_select_vhost(
- context, wsi->vhost->listen_port,
- lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST));
-
- if (vhost)
- wsi->vhost = vhost;
- } else
- lwsl_info("no host\n");
-
- if (!lwsi_role_h2(wsi) || !lwsi_role_server(wsi)) {
- wsi->vhost->conn_stats.h1_trans++;
- if (!wsi->conn_stat_done) {
- wsi->vhost->conn_stats.h1_conn++;
- wsi->conn_stat_done = 1;
- }
- }
-
- /* check for unwelcome guests */
-
- if (wsi->context->reject_service_keywords) {
- const struct lws_protocol_vhost_options *rej =
- wsi->context->reject_service_keywords;
- char ua[384], *msg = NULL;
-
- if (lws_hdr_copy(wsi, ua, sizeof(ua) - 1,
- WSI_TOKEN_HTTP_USER_AGENT) > 0) {
-#ifdef LWS_WITH_ACCESS_LOG
- char *uri_ptr = NULL;
- int meth, uri_len;
-#endif
- ua[sizeof(ua) - 1] = '\0';
- while (rej) {
- if (!strstr(ua, rej->name)) {
- rej = rej->next;
- continue;
- }
-
- msg = strchr(rej->value, ' ');
- if (msg)
- msg++;
- lws_return_http_status(wsi,
- atoi(rej->value), msg);
-#ifdef LWS_WITH_ACCESS_LOG
- meth = lws_http_get_uri_and_method(wsi,
- &uri_ptr, &uri_len);
- if (meth >= 0)
- lws_prepare_access_log_info(wsi,
- uri_ptr, meth);
-
- /* wsi close will do the log */
-#endif
- wsi->vhost->conn_stats.rejected++;
- /*
- * We don't want anything from
- * this rejected guy. Follow
- * the close flow, not the
- * transaction complete flow.
- */
- goto bail_nuke_ah;
- }
- }
- }
-
-
- if (lws_hdr_total_length(wsi, WSI_TOKEN_CONNECT)) {
- lwsl_info("Changing to RAW mode\n");
- m = 0;
- goto raw_transition;
- }
-
- lwsi_set_state(wsi, LRS_PRE_WS_SERVING_ACCEPT);
- lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
-
- /* is this websocket protocol or normal http 1.0? */
-
- if (lws_hdr_total_length(wsi, WSI_TOKEN_UPGRADE)) {
- if (!strcasecmp(lws_hdr_simple_ptr(wsi,
- WSI_TOKEN_UPGRADE),
- "websocket")) {
-#if defined(LWS_ROLE_WS)
- wsi->vhost->conn_stats.ws_upg++;
- lwsl_info("Upgrade to ws\n");
- goto upgrade_ws;
-#endif
- }
-#if defined(LWS_WITH_HTTP2)
- if (!strcasecmp(lws_hdr_simple_ptr(wsi,
- WSI_TOKEN_UPGRADE),
- "h2c")) {
- wsi->vhost->conn_stats.h2_upg++;
- lwsl_info("Upgrade to h2c\n");
- goto upgrade_h2c;
- }
-#endif
- lwsl_info("Unknown upgrade\n");
- /* dunno what he wanted to upgrade to */
- goto bail_nuke_ah;
- }
-
- /* no upgrade ack... he remained as HTTP */
-
- lwsl_info("%s: %p: No upgrade\n", __func__, wsi);
-
- lwsi_set_state(wsi, LRS_ESTABLISHED);
- wsi->http.fop_fd = NULL;
-
- lwsl_debug("%s: wsi %p: ah %p\n", __func__, (void *)wsi,
- (void *)wsi->http.ah);
-
- n = lws_http_action(wsi);
-
- return n;
-
-#if defined(LWS_WITH_HTTP2)
-upgrade_h2c:
- if (!lws_hdr_total_length(wsi, WSI_TOKEN_HTTP2_SETTINGS)) {
- lwsl_info("missing http2_settings\n");
- goto bail_nuke_ah;
- }
-
- lwsl_info("h2c upgrade...\n");
-
- p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP2_SETTINGS);
- /* convert the peer's HTTP-Settings */
- n = lws_b64_decode_string(p, tbuf, sizeof(tbuf));
- if (n < 0) {
- lwsl_parser("HTTP2_SETTINGS too long\n");
- return 1;
- }
-
- /* adopt the header info */
-
- if (!wsi->h2.h2n) {
- wsi->h2.h2n = lws_zalloc(sizeof(*wsi->h2.h2n),
- "h2n");
- if (!wsi->h2.h2n)
- return 1;
- }
-
- lws_h2_init(wsi);
-
- /* HTTP2 union */
-
- lws_h2_settings(wsi, &wsi->h2.h2n->set, (unsigned char *)tbuf, n);
-
- lws_hpack_dynamic_size(wsi, wsi->h2.h2n->set.s[
- H2SET_HEADER_TABLE_SIZE]);
-
- strcpy(tbuf, "HTTP/1.1 101 Switching Protocols\x0d\x0a"
- "Connection: Upgrade\x0d\x0a"
- "Upgrade: h2c\x0d\x0a\x0d\x0a");
- m = (int)strlen(tbuf);
- n = lws_issue_raw(wsi, (unsigned char *)tbuf, m);
- if (n != m) {
- lwsl_debug("http2 switch: ERROR writing to socket\n");
- return 1;
- }
-
- lwsi_set_state(wsi, LRS_H2_AWAIT_PREFACE);
- wsi->upgraded_to_http2 = 1;
-
- return 0;
-#endif
-#if defined(LWS_ROLE_WS)
-upgrade_ws:
- if (lws_process_ws_upgrade(wsi))
- goto bail_nuke_ah;
-
- return 0;
-#endif
- } /* while all chars are handled */
-
- return 0;
-
-bail_nuke_ah:
- /* drop the header info */
- lws_header_table_detach(wsi, 1);
-
- return 1;
-}
-
-
-static int
-lws_get_idlest_tsi(struct lws_context *context)
-{
- unsigned int lowest = ~0;
- int n = 0, hit = -1;
-
- for (; n < context->count_threads; n++) {
- if ((unsigned int)context->pt[n].fds_count !=
- context->fd_limit_per_thread - 1 &&
- (unsigned int)context->pt[n].fds_count < lowest) {
- lowest = context->pt[n].fds_count;
- hit = n;
- }
- }
-
- return hit;
-}
-
-struct lws *
-lws_create_new_server_wsi(struct lws_vhost *vhost, int fixed_tsi)
-{
- struct lws *new_wsi;
- int n = fixed_tsi;
-
- if (n < 0)
- n = lws_get_idlest_tsi(vhost->context);
-
- if (n < 0) {
- lwsl_err("no space for new conn\n");
- return NULL;
- }
-
- new_wsi = lws_zalloc(sizeof(struct lws), "new server wsi");
- if (new_wsi == NULL) {
- lwsl_err("Out of memory for new connection\n");
- return NULL;
- }
-
- new_wsi->tsi = n;
- lwsl_debug("new wsi %p joining vhost %s, tsi %d\n", new_wsi,
- vhost->name, new_wsi->tsi);
-
- new_wsi->vhost = vhost;
- new_wsi->context = vhost->context;
- new_wsi->pending_timeout = NO_PENDING_TIMEOUT;
- new_wsi->rxflow_change_to = LWS_RXFLOW_ALLOW;
-
- /* initialize the instance struct */
-
- lwsi_set_state(new_wsi, LRS_UNCONNECTED);
- new_wsi->hdr_parsing_completed = 0;
-
-#ifdef LWS_WITH_TLS
- new_wsi->tls.use_ssl = LWS_SSL_ENABLED(vhost);
-#endif
-
- /*
- * these can only be set once the protocol is known
- * we set an un-established connection's protocol pointer
- * to the start of the supported list, so it can look
- * for matching ones during the handshake
- */
- new_wsi->protocol = vhost->protocols;
- new_wsi->user_space = NULL;
- new_wsi->desc.sockfd = LWS_SOCK_INVALID;
- new_wsi->position_in_fds_table = LWS_NO_FDS_POS;
-
- vhost->context->count_wsi_allocated++;
-
- /*
- * outermost create notification for wsi
- * no user_space because no protocol selection
- */
- vhost->protocols[0].callback(new_wsi, LWS_CALLBACK_WSI_CREATE,
- NULL, NULL, 0);
-
- return new_wsi;
-}
-
-LWS_VISIBLE int LWS_WARN_UNUSED_RESULT
-lws_http_transaction_completed(struct lws *wsi)
-{
- int n = NO_PENDING_TIMEOUT;
-
- if (wsi->trunc_len) {
- /*
- * ...so he tried to send something large as the http reply,
- * it went as a partial, but he immediately said the
- * transaction was completed.
- *
- * Defer the transaction completed until the last part of the
- * partial is sent.
- */
- lwsl_notice("%s: deferring due to partial\n", __func__);
- wsi->http.deferred_transaction_completed = 1;
-
- return 0;
- }
-
- lwsl_info("%s: wsi %p\n", __func__, wsi);
-
- lws_access_log(wsi);
-
- if (!wsi->hdr_parsing_completed) {
- char peer[64];
- lws_get_peer_simple(wsi, peer, sizeof(peer) - 1);
- peer[sizeof(peer) - 1] = '\0';
- lwsl_notice("%s: (from %s) ignoring, ah parsing incomplete\n",
- __func__, peer);
- return 0;
- }
-
- /* if we can't go back to accept new headers, drop the connection */
- if (wsi->http2_substream)
- return 0;
-
- if (wsi->seen_zero_length_recv)
- return 1;
-
- if (wsi->http.connection_type != HTTP_CONNECTION_KEEP_ALIVE) {
- lwsl_notice("%s: %p: close connection\n", __func__, wsi);
- return 1;
- }
-
- if (lws_bind_protocol(wsi, &wsi->vhost->protocols[0]))
- return 1;
-
- /*
- * otherwise set ourselves up ready to go again, but because we have no
- * idea about the wsi writability, we make put it in a holding state
- * until we can verify POLLOUT. The part of this that confirms POLLOUT
- * with no partials is in lws_server_socket_service() below.
- */
- lwsl_debug("%s: %p: setting DEF_ACT from 0x%x\n", __func__,
- wsi, wsi->wsistate);
- lwsi_set_state(wsi, LRS_DEFERRING_ACTION);
- wsi->http.tx_content_length = 0;
- wsi->http.tx_content_remain = 0;
- wsi->hdr_parsing_completed = 0;
-#ifdef LWS_WITH_ACCESS_LOG
- wsi->http.access_log.sent = 0;
-#endif
-
- if (wsi->vhost->keepalive_timeout)
- n = PENDING_TIMEOUT_HTTP_KEEPALIVE_IDLE;
- lws_set_timeout(wsi, n, wsi->vhost->keepalive_timeout);
-
- /*
- * We already know we are on http1.1 / keepalive and the next thing
- * coming will be another header set.
- *
- * If there is no pending rx and we still have the ah, drop it and
- * reacquire a new ah when the new headers start to arrive. (Otherwise
- * we needlessly hog an ah indefinitely.)
- *
- * However if there is pending rx and we know from the keepalive state
- * that is already at least the start of another header set, simply
- * reset the existing header table and keep it.
- */
- if (wsi->http.ah) {
- // lws_buflist_describe(&wsi->buflist, wsi);
- if (!lws_buflist_next_segment_len(&wsi->buflist, NULL)) {
- lwsl_info("%s: %p: nothing in buflist so detaching ah\n",
- __func__, wsi);
- lws_header_table_detach(wsi, 1);
-#ifdef LWS_WITH_TLS
- /*
- * additionally... if we are hogging an SSL instance
- * with no pending pipelined headers (or ah now), and
- * SSL is scarce, drop this connection without waiting
- */
-
- if (wsi->vhost->tls.use_ssl &&
- wsi->context->simultaneous_ssl_restriction &&
- wsi->context->simultaneous_ssl ==
- wsi->context->simultaneous_ssl_restriction) {
- lwsl_info("%s: simultaneous_ssl_restriction\n",
- __func__);
- return 1;
- }
-#endif
- } else {
- lwsl_info("%s: %p: resetting and keeping ah as pipeline\n",
- __func__, wsi);
- lws_header_table_reset(wsi, 0);
- /*
- * If we kept the ah, we should restrict the amount
- * of time we are willing to keep it. Otherwise it
- * will be bound the whole time the connection remains
- * open.
- */
- lws_set_timeout(wsi, PENDING_TIMEOUT_HOLDING_AH,
- wsi->vhost->keepalive_timeout);
- }
- /* If we're (re)starting on headers, need other implied init */
- if (wsi->http.ah)
- wsi->http.ah->ues = URIES_IDLE;
-
- //lwsi_set_state(wsi, LRS_ESTABLISHED);
- } else
- if (lws_buflist_next_segment_len(&wsi->buflist, NULL))
- if (lws_header_table_attach(wsi, 0))
- lwsl_debug("acquired ah\n");
-
- lwsl_info("%s: %p: keep-alive await new transaction\n", __func__, wsi);
- lws_callback_on_writable(wsi);
-
- return 0;
-}
-
-/* if not a socket, it's a raw, non-ssl file descriptor */
-
-LWS_VISIBLE struct lws *
-lws_adopt_descriptor_vhost(struct lws_vhost *vh, lws_adoption_type type,
- lws_sock_file_fd_type fd, const char *vh_prot_name,
- struct lws *parent)
-{
- struct lws_context *context = vh->context;
- struct lws *new_wsi;
- struct lws_context_per_thread *pt;
- int n, ssl = 0;
-
-#if defined(LWS_WITH_PEER_LIMITS)
- struct lws_peer *peer = NULL;
-
- if (type & LWS_ADOPT_SOCKET && !(type & LWS_ADOPT_WS_PARENTIO)) {
- peer = lws_get_or_create_peer(vh, fd.sockfd);
-
- if (peer && context->ip_limit_wsi &&
- peer->count_wsi >= context->ip_limit_wsi) {
- lwsl_notice("Peer reached wsi limit %d\n",
- context->ip_limit_wsi);
- lws_stats_atomic_bump(context, &context->pt[0],
- LWSSTATS_C_PEER_LIMIT_WSI_DENIED, 1);
- return NULL;
- }
- }
-#endif
-
- n = -1;
- if (parent)
- n = parent->tsi;
- new_wsi = lws_create_new_server_wsi(vh, n);
- if (!new_wsi) {
- if (type & LWS_ADOPT_SOCKET && !(type & LWS_ADOPT_WS_PARENTIO))
- compatible_close(fd.sockfd);
- return NULL;
- }
-#if defined(LWS_WITH_PEER_LIMITS)
- if (peer)
- lws_peer_add_wsi(context, peer, new_wsi);
-#endif
- pt = &context->pt[(int)new_wsi->tsi];
- lws_stats_atomic_bump(context, pt, LWSSTATS_C_CONNECTIONS, 1);
-
- if (parent) {
- new_wsi->parent = parent;
- new_wsi->sibling_list = parent->child_list;
- parent->child_list = new_wsi;
-
- if (type & LWS_ADOPT_WS_PARENTIO)
- new_wsi->parent_carries_io = 1;
- }
-
- new_wsi->desc = fd;
-
- if (vh_prot_name) {
- new_wsi->protocol = lws_vhost_name_to_protocol(new_wsi->vhost,
- vh_prot_name);
- if (!new_wsi->protocol) {
- lwsl_err("Protocol %s not enabled on vhost %s\n",
- vh_prot_name, new_wsi->vhost->name);
- goto bail;
- }
- if (lws_ensure_user_space(new_wsi)) {
- lwsl_notice("OOM trying to get user_space\n");
- goto bail;
- }
-#if defined(LWS_ROLE_WS)
- if (type & LWS_ADOPT_WS_PARENTIO) {
- new_wsi->desc.sockfd = LWS_SOCK_INVALID;
- lwsl_debug("binding to %s\n", new_wsi->protocol->name);
- lws_bind_protocol(new_wsi, new_wsi->protocol);
- lws_role_transition(new_wsi, LWSIFR_SERVER,
- LRS_ESTABLISHED, &role_ops_ws);
- /* allocate the ws struct for the wsi */
- new_wsi->ws = lws_zalloc(sizeof(*new_wsi->ws), "ws struct");
- if (!new_wsi->ws) {
- lwsl_notice("OOM\n");
- goto bail;
- }
- lws_server_init_wsi_for_ws(new_wsi);
-
- return new_wsi;
- }
-#endif
- } else
-#if defined(LWS_ROLE_H1)
- if (type & LWS_ADOPT_HTTP) {/* he will transition later */
- new_wsi->protocol =
- &vh->protocols[vh->default_protocol_index];
- new_wsi->role_ops = &role_ops_h1;
- }
- else
-#endif
- { /* this is the only time he will transition */
- lws_bind_protocol(new_wsi,
- &vh->protocols[vh->raw_protocol_index]);
- lws_role_transition(new_wsi, 0, LRS_ESTABLISHED,
- &role_ops_raw_skt);
- }
-
- if (type & LWS_ADOPT_SOCKET) { /* socket desc */
- lwsl_debug("%s: new wsi %p, sockfd %d\n", __func__, new_wsi,
- (int)(lws_intptr_t)fd.sockfd);
-#if !defined(LWS_WITH_ESP32)
- if (type & LWS_ADOPT_FLAG_UDP)
- /*
- * these can be >128 bytes, so just alloc for UDP
- */
- new_wsi->udp = lws_malloc(sizeof(*new_wsi->udp),
- "udp struct");
-#endif
-
- if (type & LWS_ADOPT_HTTP)
- /* the transport is accepted...
- * give him time to negotiate */
- lws_set_timeout(new_wsi,
- PENDING_TIMEOUT_ESTABLISH_WITH_SERVER,
- context->timeout_secs);
-
- } else /* file desc */
- lwsl_debug("%s: new wsi %p, filefd %d\n", __func__, new_wsi,
- (int)(lws_intptr_t)fd.filefd);
-
- /*
- * A new connection was accepted. Give the user a chance to
- * set properties of the newly created wsi. There's no protocol
- * selected yet so we issue this to the vhosts's default protocol,
- * itself by default protocols[0]
- */
- n = LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED;
- if (!(type & LWS_ADOPT_HTTP)) {
- if (!(type & LWS_ADOPT_SOCKET))
- n = LWS_CALLBACK_RAW_ADOPT_FILE;
- else
- n = LWS_CALLBACK_RAW_ADOPT;
- }
-
- if (!LWS_SSL_ENABLED(new_wsi->vhost) || !(type & LWS_ADOPT_ALLOW_SSL) ||
- !(type & LWS_ADOPT_SOCKET)) {
- /* non-SSL */
- if (!(type & LWS_ADOPT_HTTP)) {
- if (!(type & LWS_ADOPT_SOCKET))
- lws_role_transition(new_wsi, 0, LRS_ESTABLISHED,
- &role_ops_raw_file);
- else
- lws_role_transition(new_wsi, 0, LRS_ESTABLISHED,
- &role_ops_raw_skt);
- }
-#if defined(LWS_ROLE_H1)
- else
- lws_role_transition(new_wsi, LWSIFR_SERVER,
- LRS_HEADERS, &role_ops_h1);
-#endif
- } else {
- /* SSL */
- if (!(type & LWS_ADOPT_HTTP))
- lws_role_transition(new_wsi, 0, LRS_SSL_INIT,
- &role_ops_raw_skt);
-#if defined(LWS_ROLE_H1)
- else
- lws_role_transition(new_wsi, LWSIFR_SERVER,
- LRS_SSL_INIT, &role_ops_h1);
-#endif
- ssl = 1;
- }
-
- lwsl_debug("new wsi wsistate 0x%x\n", new_wsi->wsistate);
-
- if (context->event_loop_ops->accept)
- context->event_loop_ops->accept(new_wsi);
-
- if (!ssl) {
- lws_pt_lock(pt, __func__);
- if (__insert_wsi_socket_into_fds(context, new_wsi)) {
- lws_pt_unlock(pt);
- lwsl_err("%s: fail inserting socket\n", __func__);
- goto fail;
- }
- lws_pt_unlock(pt);
- } else
- if (lws_server_socket_service_ssl(new_wsi, fd.sockfd)) {
- lwsl_info("%s: fail ssl negotiation\n", __func__);
- goto fail;
- }
-
- /*
- * by deferring callback to this point, after insertion to fds,
- * lws_callback_on_writable() can work from the callback
- */
- if ((new_wsi->protocol->callback)(
- new_wsi, n, new_wsi->user_space, NULL, 0))
- goto fail;
-
- if (type & LWS_ADOPT_HTTP) {
- if (!lws_header_table_attach(new_wsi, 0))
- lwsl_debug("Attached ah immediately\n");
- else
- lwsl_info("%s: waiting for ah\n", __func__);
- }
-
- lws_cancel_service_pt(new_wsi);
-
- return new_wsi;
-
-fail:
- if (type & LWS_ADOPT_SOCKET)
- lws_close_free_wsi(new_wsi, LWS_CLOSE_STATUS_NOSTATUS, "adopt skt fail");
-
- return NULL;
-
-bail:
- lwsl_notice("%s: exiting on bail\n", __func__);
- if (parent)
- parent->child_list = new_wsi->sibling_list;
- if (new_wsi->user_space)
- lws_free(new_wsi->user_space);
- lws_free(new_wsi);
- compatible_close(fd.sockfd);
-
- return NULL;
-}
-
-LWS_VISIBLE struct lws *
-lws_adopt_socket_vhost(struct lws_vhost *vh, lws_sockfd_type accept_fd)
-{
- lws_sock_file_fd_type fd;
-
- fd.sockfd = accept_fd;
- return lws_adopt_descriptor_vhost(vh, LWS_ADOPT_SOCKET |
- LWS_ADOPT_HTTP | LWS_ADOPT_ALLOW_SSL, fd, NULL, NULL);
-}
-
-LWS_VISIBLE struct lws *
-lws_adopt_socket(struct lws_context *context, lws_sockfd_type accept_fd)
-{
- return lws_adopt_socket_vhost(context->vhost_list, accept_fd);
-}
-
-/* Common read-buffer adoption for lws_adopt_*_readbuf */
-static struct lws*
-adopt_socket_readbuf(struct lws *wsi, const char *readbuf, size_t len)
-{
- struct lws_context_per_thread *pt;
- struct lws_pollfd *pfd;
- int n;
-
- if (!wsi)
- return NULL;
-
- if (!readbuf || len == 0)
- return wsi;
-
- if (wsi->position_in_fds_table == LWS_NO_FDS_POS)
- return wsi;
-
- pt = &wsi->context->pt[(int)wsi->tsi];
-
- n = lws_buflist_append_segment(&wsi->buflist, (const uint8_t *)readbuf, len);
- if (n < 0)
- goto bail;
- if (n)
- lws_dll_lws_add_front(&wsi->dll_buflist, &pt->dll_head_buflist);
-
- /*
- * we can't process the initial read data until we can attach an ah.
- *
- * if one is available, get it and place the data in his ah rxbuf...
- * wsi with ah that have pending rxbuf get auto-POLLIN service.
- *
- * no autoservice because we didn't get a chance to attach the
- * readbuf data to wsi or ah yet, and we will do it next if we get
- * the ah.
- */
- if (wsi->http.ah || !lws_header_table_attach(wsi, 0)) {
-
- lwsl_notice("%s: calling service on readbuf ah\n", __func__);
-
- /* unlike a normal connect, we have the headers already
- * (or the first part of them anyway).
- * libuv won't come back and service us without a network
- * event, so we need to do the header service right here.
- */
- pfd = &pt->fds[wsi->position_in_fds_table];
- pfd->revents |= LWS_POLLIN;
- lwsl_err("%s: calling service\n", __func__);
- if (lws_service_fd_tsi(wsi->context, pfd, wsi->tsi))
- /* service closed us */
- return NULL;
-
- return wsi;
- }
- lwsl_err("%s: deferring handling ah\n", __func__);
-
- return wsi;
-
-bail:
- lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "adopt skt readbuf fail");
-
- return NULL;
-}
-
-LWS_VISIBLE struct lws *
-lws_adopt_socket_readbuf(struct lws_context *context, lws_sockfd_type accept_fd,
- const char *readbuf, size_t len)
-{
- return adopt_socket_readbuf(lws_adopt_socket(context, accept_fd),
- readbuf, len);
-}
-
-LWS_VISIBLE struct lws *
-lws_adopt_socket_vhost_readbuf(struct lws_vhost *vhost,
- lws_sockfd_type accept_fd,
- const char *readbuf, size_t len)
-{
- return adopt_socket_readbuf(lws_adopt_socket_vhost(vhost, accept_fd),
- readbuf, len);
-}
-
-LWS_VISIBLE int
-lws_serve_http_file(struct lws *wsi, const char *file, const char *content_type,
- const char *other_headers, int other_headers_len)
-{
- static const char * const intermediates[] = { "private", "public" };
- struct lws_context *context = lws_get_context(wsi);
- struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
-#if defined(LWS_WITH_RANGES)
- struct lws_range_parsing *rp = &wsi->http.range;
-#endif
- char cache_control[50], *cc = "no-store";
- unsigned char *response = pt->serv_buf + LWS_PRE;
- unsigned char *p = response;
- unsigned char *end = p + context->pt_serv_buf_size - LWS_PRE;
- lws_filepos_t total_content_length;
- int ret = 0, cclen = 8, n = HTTP_STATUS_OK;
- lws_fop_flags_t fflags = LWS_O_RDONLY;
-#if defined(LWS_WITH_RANGES)
- int ranges;
-#endif
- const struct lws_plat_file_ops *fops;
- const char *vpath;
-
- if (wsi->handling_404)
- n = HTTP_STATUS_NOT_FOUND;
-
- /*
- * We either call the platform fops .open with first arg platform fops,
- * or we call fops_zip .open with first arg platform fops, and fops_zip
- * open will decide whether to switch to fops_zip or stay with fops_def.
- *
- * If wsi->http.fop_fd is already set, the caller already opened it
- */
- if (!wsi->http.fop_fd) {
- fops = lws_vfs_select_fops(wsi->context->fops, file, &vpath);
- fflags |= lws_vfs_prepare_flags(wsi);
- wsi->http.fop_fd = fops->LWS_FOP_OPEN(wsi->context->fops,
- file, vpath, &fflags);
- if (!wsi->http.fop_fd) {
- lwsl_info("%s: Unable to open: '%s': errno %d\n",
- __func__, file, errno);
- if (lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL))
- return -1;
- return !wsi->http2_substream;
- }
- }
- wsi->http.filelen = lws_vfs_get_length(wsi->http.fop_fd);
- total_content_length = wsi->http.filelen;
-
-#if defined(LWS_WITH_RANGES)
- ranges = lws_ranges_init(wsi, rp, wsi->http.filelen);
-
- lwsl_debug("Range count %d\n", ranges);
- /*
- * no ranges -> 200;
- * 1 range -> 206 + Content-Type: normal; Content-Range;
- * more -> 206 + Content-Type: multipart/byteranges
- * Repeat the true Content-Type in each multipart header
- * along with Content-Range
- */
- if (ranges < 0) {
- /* it means he expressed a range in Range:, but it was illegal */
- lws_return_http_status(wsi, HTTP_STATUS_REQ_RANGE_NOT_SATISFIABLE,
- NULL);
- if (lws_http_transaction_completed(wsi))
- return -1; /* <0 means just hang up */
-
- lws_vfs_file_close(&wsi->http.fop_fd);
-
- return 0; /* == 0 means we dealt with the transaction complete */
- }
- if (ranges)
- n = HTTP_STATUS_PARTIAL_CONTENT;
-#endif
-
- if (lws_add_http_header_status(wsi, n, &p, end))
- return -1;
-
- if ((wsi->http.fop_fd->flags & (LWS_FOP_FLAG_COMPR_ACCEPTABLE_GZIP |
- LWS_FOP_FLAG_COMPR_IS_GZIP)) ==
- (LWS_FOP_FLAG_COMPR_ACCEPTABLE_GZIP | LWS_FOP_FLAG_COMPR_IS_GZIP)) {
- if (lws_add_http_header_by_token(wsi,
- WSI_TOKEN_HTTP_CONTENT_ENCODING,
- (unsigned char *)"gzip", 4, &p, end))
- return -1;
- lwsl_info("file is being provided in gzip\n");
- }
-
- if (
-#if defined(LWS_WITH_RANGES)
- ranges < 2 &&
-#endif
- content_type && content_type[0])
- if (lws_add_http_header_by_token(wsi,
- WSI_TOKEN_HTTP_CONTENT_TYPE,
- (unsigned char *)content_type,
- (int)strlen(content_type),
- &p, end))
- return -1;
-
-#if defined(LWS_WITH_RANGES)
- if (ranges >= 2) { /* multipart byteranges */
- lws_strncpy(wsi->http.multipart_content_type, content_type,
- sizeof(wsi->http.multipart_content_type));
-
- if (lws_add_http_header_by_token(wsi,
- WSI_TOKEN_HTTP_CONTENT_TYPE,
- (unsigned char *)
- "multipart/byteranges; "
- "boundary=_lws",
- 20, &p, end))
- return -1;
-
- /*
- * our overall content length has to include
- *
- * - (n + 1) x "_lws\r\n"
- * - n x Content-Type: xxx/xxx\r\n
- * - n x Content-Range: bytes xxx-yyy/zzz\r\n
- * - n x /r/n
- * - the actual payloads (aggregated in rp->agg)
- *
- * Precompute it for the main response header
- */
-
- total_content_length = (lws_filepos_t)rp->agg +
- 6 /* final _lws\r\n */;
-
- lws_ranges_reset(rp);
- while (lws_ranges_next(rp)) {
- n = lws_snprintf(cache_control, sizeof(cache_control),
- "bytes %llu-%llu/%llu",
- rp->start, rp->end, rp->extent);
-
- total_content_length +=
- 6 /* header _lws\r\n */ +
- /* Content-Type: xxx/xxx\r\n */
- 14 + strlen(content_type) + 2 +
- /* Content-Range: xxxx\r\n */
- 15 + n + 2 +
- 2; /* /r/n */
- }
-
- lws_ranges_reset(rp);
- lws_ranges_next(rp);
- }
-
- if (ranges == 1) {
- total_content_length = (lws_filepos_t)rp->agg;
- n = lws_snprintf(cache_control, sizeof(cache_control),
- "bytes %llu-%llu/%llu",
- rp->start, rp->end, rp->extent);
-
- if (lws_add_http_header_by_token(wsi,
- WSI_TOKEN_HTTP_CONTENT_RANGE,
- (unsigned char *)cache_control,
- n, &p, end))
- return -1;
- }
-
- wsi->http.range.inside = 0;
-
- if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_ACCEPT_RANGES,
- (unsigned char *)"bytes", 5, &p, end))
- return -1;
-#endif
-
- if (!wsi->http2_substream) {
- if (!wsi->sending_chunked) {
- if (lws_add_http_header_content_length(wsi,
- total_content_length,
- &p, end))
- return -1;
- } else {
- if (lws_add_http_header_by_token(wsi,
- WSI_TOKEN_HTTP_TRANSFER_ENCODING,
- (unsigned char *)"chunked",
- 7, &p, end))
- return -1;
- }
- }
-
- if (wsi->cache_secs && wsi->cache_reuse) {
- if (wsi->cache_revalidate) {
- cc = cache_control;
- cclen = sprintf(cache_control, "%s max-age: %u",
- intermediates[wsi->cache_intermediaries],
- wsi->cache_secs);
- } else {
- cc = "no-cache";
- cclen = 8;
- }
- }
-
- if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CACHE_CONTROL,
- (unsigned char *)cc, cclen, &p, end))
- return -1;
-
- if (wsi->http.connection_type == HTTP_CONNECTION_KEEP_ALIVE)
- if (lws_add_http_header_by_token(wsi, WSI_TOKEN_CONNECTION,
- (unsigned char *)"keep-alive", 10, &p, end))
- return -1;
-
- if (other_headers) {
- if ((end - p) < other_headers_len)
- return -1;
- memcpy(p, other_headers, other_headers_len);
- p += other_headers_len;
- }
-
- if (lws_finalize_http_header(wsi, &p, end))
- return -1;
-
- ret = lws_write(wsi, response, p - response, LWS_WRITE_HTTP_HEADERS);
- if (ret != (p - response)) {
- lwsl_err("_write returned %d from %ld\n", ret,
- (long)(p - response));
- return -1;
- }
-
- wsi->http.filepos = 0;
- lwsi_set_state(wsi, LRS_ISSUING_FILE);
-
- lws_callback_on_writable(wsi);
-
- return 0;
-}
-
-LWS_VISIBLE int lws_serve_http_file_fragment(struct lws *wsi)
-{
- struct lws_context *context = wsi->context;
- struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
- struct lws_process_html_args args;
- lws_filepos_t amount, poss;
- unsigned char *p, *pstart;
-#if defined(LWS_WITH_RANGES)
- unsigned char finished = 0;
-#endif
- int n, m;
-
- lwsl_debug("wsi->http2_substream %d\n", wsi->http2_substream);
-
- do {
-
- if (wsi->trunc_len) {
- if (lws_issue_raw(wsi, wsi->trunc_alloc +
- wsi->trunc_offset,
- wsi->trunc_len) < 0) {
- lwsl_info("%s: closing\n", __func__);
- goto file_had_it;
- }
- break;
- }
-
- if (wsi->http.filepos == wsi->http.filelen)
- goto all_sent;
-
- n = 0;
-
- pstart = pt->serv_buf + LWS_H2_FRAME_HEADER_LENGTH;
-
- p = pstart;
-
-#if defined(LWS_WITH_RANGES)
- if (wsi->http.range.count_ranges && !wsi->http.range.inside) {
-
- lwsl_notice("%s: doing range start %llu\n", __func__,
- wsi->http.range.start);
-
- if ((long long)lws_vfs_file_seek_cur(wsi->http.fop_fd,
- wsi->http.range.start -
- wsi->http.filepos) < 0)
- goto file_had_it;
-
- wsi->http.filepos = wsi->http.range.start;
-
- if (wsi->http.range.count_ranges > 1) {
- n = lws_snprintf((char *)p,
- context->pt_serv_buf_size -
- LWS_H2_FRAME_HEADER_LENGTH,
- "_lws\x0d\x0a"
- "Content-Type: %s\x0d\x0a"
- "Content-Range: bytes %llu-%llu/%llu\x0d\x0a"
- "\x0d\x0a",
- wsi->http.multipart_content_type,
- wsi->http.range.start,
- wsi->http.range.end,
- wsi->http.range.extent);
- p += n;
- }
-
- wsi->http.range.budget = wsi->http.range.end -
- wsi->http.range.start + 1;
- wsi->http.range.inside = 1;
- }
-#endif
-
- poss = context->pt_serv_buf_size - n - LWS_H2_FRAME_HEADER_LENGTH;
-
- if (wsi->http.tx_content_length)
- if (poss > wsi->http.tx_content_remain)
- poss = wsi->http.tx_content_remain;
-
- /*
- * if there is a hint about how much we will do well to send at
- * one time, restrict ourselves to only trying to send that.
- */
- if (wsi->protocol->tx_packet_size &&
- poss > wsi->protocol->tx_packet_size)
- poss = wsi->protocol->tx_packet_size;
-
- if (wsi->role_ops->tx_credit) {
- lws_filepos_t txc = wsi->role_ops->tx_credit(wsi);
-
- if (!txc) {
- lwsl_info("%s: came here with no tx credit\n",
- __func__);
- return 0;
- }
- if (txc < poss)
- poss = txc;
-
- /*
- * consumption of the actual payload amount sent will be
- * handled when the role data frame is sent
- */
- }
-
-#if defined(LWS_WITH_RANGES)
- if (wsi->http.range.count_ranges) {
- if (wsi->http.range.count_ranges > 1)
- poss -= 7; /* allow for final boundary */
- if (poss > wsi->http.range.budget)
- poss = wsi->http.range.budget;
- }
-#endif
- if (wsi->sending_chunked) {
- /* we need to drop the chunk size in here */
- p += 10;
- /* allow for the chunk to grow by 128 in translation */
- poss -= 10 + 128;
- }
-
- if (lws_vfs_file_read(wsi->http.fop_fd, &amount, p, poss) < 0)
- goto file_had_it; /* caller will close */
-
- if (wsi->sending_chunked)
- n = (int)amount;
- else
- n = lws_ptr_diff(p, pstart) + (int)amount;
-
- lwsl_debug("%s: sending %d\n", __func__, n);
-
- if (n) {
- lws_set_timeout(wsi, PENDING_TIMEOUT_HTTP_CONTENT,
- context->timeout_secs);
-
- if (wsi->interpreting) {
- args.p = (char *)p;
- args.len = n;
- args.max_len = (unsigned int)poss + 128;
- args.final = wsi->http.filepos + n ==
- wsi->http.filelen;
- args.chunked = wsi->sending_chunked;
- if (user_callback_handle_rxflow(
- wsi->vhost->protocols[
- (int)wsi->protocol_interpret_idx].callback,
- wsi, LWS_CALLBACK_PROCESS_HTML,
- wsi->user_space, &args, 0) < 0)
- goto file_had_it;
- n = args.len;
- p = (unsigned char *)args.p;
- } else
- p = pstart;
-
-#if defined(LWS_WITH_RANGES)
- if (wsi->http.range.send_ctr + 1 ==
- wsi->http.range.count_ranges && // last range
- wsi->http.range.count_ranges > 1 && // was 2+ ranges (ie, multipart)
- wsi->http.range.budget - amount == 0) {// final part
- n += lws_snprintf((char *)pstart + n, 6,
- "_lws\x0d\x0a"); // append trailing boundary
- lwsl_debug("added trailing boundary\n");
- }
-#endif
- m = lws_write(wsi, p, n,
- wsi->http.filepos + amount == wsi->http.filelen ?
- LWS_WRITE_HTTP_FINAL :
- LWS_WRITE_HTTP
- );
- if (m < 0)
- goto file_had_it;
-
- wsi->http.filepos += amount;
-
-#if defined(LWS_WITH_RANGES)
- if (wsi->http.range.count_ranges >= 1) {
- wsi->http.range.budget -= amount;
- if (wsi->http.range.budget == 0) {
- lwsl_notice("range budget exhausted\n");
- wsi->http.range.inside = 0;
- wsi->http.range.send_ctr++;
-
- if (lws_ranges_next(&wsi->http.range) < 1) {
- finished = 1;
- goto all_sent;
- }
- }
- }
-#endif
-
- if (m != n) {
- /* adjust for what was not sent */
- if (lws_vfs_file_seek_cur(wsi->http.fop_fd,
- m - n) ==
- (lws_fileofs_t)-1)
- goto file_had_it;
- }
- }
-
-all_sent:
- if ((!wsi->trunc_len && wsi->http.filepos >= wsi->http.filelen)
-#if defined(LWS_WITH_RANGES)
- || finished)
-#else
- )
-#endif
- {
- lwsi_set_state(wsi, LRS_ESTABLISHED);
- /* we might be in keepalive, so close it off here */
- lws_vfs_file_close(&wsi->http.fop_fd);
-
- lwsl_debug("file completed\n");
-
- if (wsi->protocol->callback &&
- user_callback_handle_rxflow(wsi->protocol->callback,
- wsi, LWS_CALLBACK_HTTP_FILE_COMPLETION,
- wsi->user_space, NULL,
- 0) < 0) {
- /*
- * For http/1.x, the choices from
- * transaction_completed are either
- * 0 to use the connection for pipelined
- * or nonzero to hang it up.
- *
- * However for http/2. while we are
- * still interested in hanging up the
- * nwsi if there was a network-level
- * fatal error, simply completing the
- * transaction is a matter of the stream
- * state, not the root connection at the
- * network level
- */
- if (wsi->http2_substream)
- return 1;
- else
- return -1;
- }
-
- return 1; /* >0 indicates completed */
- }
- } while (0); // while (!lws_send_pipe_choked(wsi))
-
- lws_callback_on_writable(wsi);
-
- return 0; /* indicates further processing must be done */
-
-file_had_it:
- lws_vfs_file_close(&wsi->http.fop_fd);
-
- return -1;
-}
-
-
-LWS_VISIBLE void
-lws_server_get_canonical_hostname(struct lws_context *context,
- const struct lws_context_creation_info *info)
-{
- if (lws_check_opt(info->options,
- LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME))
- return;
-#if !defined(LWS_WITH_ESP32)
- /* find canonical hostname */
- gethostname((char *)context->canonical_hostname,
- sizeof(context->canonical_hostname) - 1);
-
- lwsl_info(" canonical_hostname = %s\n", context->canonical_hostname);
-#else
- (void)context;
-#endif
-}
-
-
-LWS_VISIBLE LWS_EXTERN int
-lws_chunked_html_process(struct lws_process_html_args *args,
- struct lws_process_html_state *s)
-{
- char *sp, buffer[32];
- const char *pc;
- int old_len, n;
-
- /* do replacements */
- sp = args->p;
- old_len = args->len;
- args->len = 0;
- s->start = sp;
- while (sp < args->p + old_len) {
-
- if (args->len + 7 >= args->max_len) {
- lwsl_err("Used up interpret padding\n");
- return -1;
- }
-
- if ((!s->pos && *sp == '$') || s->pos) {
- int hits = 0, hit = 0;
-
- if (!s->pos)
- s->start = sp;
- s->swallow[s->pos++] = *sp;
- if (s->pos == sizeof(s->swallow) - 1)
- goto skip;
- for (n = 0; n < s->count_vars; n++)
- if (!strncmp(s->swallow, s->vars[n], s->pos)) {
- hits++;
- hit = n;
- }
- if (!hits) {
-skip:
- s->swallow[s->pos] = '\0';
- memcpy(s->start, s->swallow, s->pos);
- args->len++;
- s->pos = 0;
- sp = s->start + 1;
- continue;
- }
- if (hits == 1 && s->pos == (int)strlen(s->vars[hit])) {
- pc = s->replace(s->data, hit);
- if (!pc)
- pc = "NULL";
- n = (int)strlen(pc);
- s->swallow[s->pos] = '\0';
- if (n != s->pos) {
- memmove(s->start + n,
- s->start + s->pos,
- old_len - (sp - args->p));
- old_len += (n - s->pos) + 1;
- }
- memcpy(s->start, pc, n);
- args->len++;
- sp = s->start + 1;
-
- s->pos = 0;
- }
- sp++;
- continue;
- }
-
- args->len++;
- sp++;
- }
-
- if (args->chunked) {
- /* no space left for final chunk trailer */
- if (args->final && args->len + 7 >= args->max_len)
- return -1;
-
- n = sprintf(buffer, "%X\x0d\x0a", args->len);
-
- args->p -= n;
- memcpy(args->p, buffer, n);
- args->len += n;
-
- if (args->final) {
- sp = args->p + args->len;
- *sp++ = '\x0d';
- *sp++ = '\x0a';
- *sp++ = '0';
- *sp++ = '\x0d';
- *sp++ = '\x0a';
- *sp++ = '\x0d';
- *sp++ = '\x0a';
- args->len += 7;
- } else {
- sp = args->p + args->len;
- *sp++ = '\x0d';
- *sp++ = '\x0a';
- args->len += 2;
- }
- }
-
- return 0;
-}
diff --git a/thirdparty/libwebsockets/roles/listen/ops-listen.c b/thirdparty/libwebsockets/roles/listen/ops-listen.c
deleted file mode 100644
index dbeb9753a2..0000000000
--- a/thirdparty/libwebsockets/roles/listen/ops-listen.c
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010-2018 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- */
-
-#include <core/private.h>
-
-static int
-rops_handle_POLLIN_listen(struct lws_context_per_thread *pt, struct lws *wsi,
- struct lws_pollfd *pollfd)
-{
- struct lws_context *context = wsi->context;
- lws_sockfd_type accept_fd = LWS_SOCK_INVALID;
- lws_sock_file_fd_type fd;
- int opts = LWS_ADOPT_SOCKET | LWS_ADOPT_ALLOW_SSL;
- struct sockaddr_storage cli_addr;
- socklen_t clilen;
-
- /* pollin means a client has connected to us then
- *
- * pollout is a hack on esp32 for background accepts signalling
- * they completed
- */
-
- do {
- struct lws *cwsi;
-
- if (!(pollfd->revents & (LWS_POLLIN | LWS_POLLOUT)) ||
- !(pollfd->events & LWS_POLLIN))
- break;
-
-#if defined(LWS_WITH_TLS)
- /*
- * can we really accept it, with regards to SSL limit?
- * another vhost may also have had POLLIN on his
- * listener this round and used it up already
- */
- if (wsi->vhost->tls.use_ssl &&
- context->simultaneous_ssl_restriction &&
- context->simultaneous_ssl ==
- context->simultaneous_ssl_restriction)
- /*
- * no... ignore it, he won't come again until
- * we are below the simultaneous_ssl_restriction
- * limit and POLLIN is enabled on him again
- */
- break;
-#endif
- /* listen socket got an unencrypted connection... */
-
- clilen = sizeof(cli_addr);
- lws_latency_pre(context, wsi);
-
- /*
- * We cannot identify the peer who is in the listen
- * socket connect queue before we accept it; even if
- * we could, not accepting it due to PEER_LIMITS would
- * block the connect queue for other legit peers.
- */
-
- accept_fd = accept((int)pollfd->fd,
- (struct sockaddr *)&cli_addr, &clilen);
- lws_latency(context, wsi, "listener accept",
- (int)accept_fd, accept_fd != LWS_SOCK_INVALID);
- if (accept_fd == LWS_SOCK_INVALID) {
- if (LWS_ERRNO == LWS_EAGAIN ||
- LWS_ERRNO == LWS_EWOULDBLOCK) {
- break;
- }
- lwsl_err("ERROR on accept: %s\n",
- strerror(LWS_ERRNO));
- break;
- }
-
- lws_plat_set_socket_options(wsi->vhost, accept_fd);
-
-#if defined(LWS_WITH_IPV6)
- lwsl_debug("accepted new conn port %u on fd=%d\n",
- ((cli_addr.ss_family == AF_INET6) ?
- ntohs(((struct sockaddr_in6 *) &cli_addr)->sin6_port) :
- ntohs(((struct sockaddr_in *) &cli_addr)->sin_port)),
- accept_fd);
-#else
- lwsl_debug("accepted new conn port %u on fd=%d\n",
- ntohs(((struct sockaddr_in *) &cli_addr)->sin_port),
- accept_fd);
-#endif
-
- /*
- * look at who we connected to and give user code a
- * chance to reject based on client IP. There's no
- * protocol selected yet so we issue this to
- * protocols[0]
- */
- if ((wsi->vhost->protocols[0].callback)(wsi,
- LWS_CALLBACK_FILTER_NETWORK_CONNECTION,
- NULL,
- (void *)(lws_intptr_t)accept_fd, 0)) {
- lwsl_debug("Callback denied net connection\n");
- compatible_close(accept_fd);
- break;
- }
-
- if (!(wsi->vhost->options & LWS_SERVER_OPTION_ONLY_RAW))
- opts |= LWS_ADOPT_HTTP;
- else
- opts = LWS_ADOPT_SOCKET;
-
- fd.sockfd = accept_fd;
- cwsi = lws_adopt_descriptor_vhost(wsi->vhost, opts, fd,
- NULL, NULL);
- if (!cwsi)
- /* already closed cleanly as necessary */
- return LWS_HPI_RET_WSI_ALREADY_DIED;
-
- if (lws_server_socket_service_ssl(cwsi, accept_fd)) {
- lws_close_free_wsi(cwsi, LWS_CLOSE_STATUS_NOSTATUS,
- "listen svc fail");
- return LWS_HPI_RET_WSI_ALREADY_DIED;
- }
-
- lwsl_info("%s: new wsi %p: wsistate 0x%x, role_ops %s\n",
- __func__, cwsi, cwsi->wsistate, cwsi->role_ops->name);
-
- } while (pt->fds_count < context->fd_limit_per_thread - 1 &&
- wsi->position_in_fds_table != LWS_NO_FDS_POS &&
- lws_poll_listen_fd(&pt->fds[wsi->position_in_fds_table]) > 0);
-
- return LWS_HPI_RET_HANDLED;
-}
-
-int rops_handle_POLLOUT_listen(struct lws *wsi)
-{
- return LWS_HP_RET_USER_SERVICE;
-}
-
-struct lws_role_ops role_ops_listen = {
- /* role name */ "listen",
- /* alpn id */ NULL,
- /* check_upgrades */ NULL,
- /* init_context */ NULL,
- /* init_vhost */ NULL,
- /* destroy_vhost */ NULL,
- /* periodic_checks */ NULL,
- /* service_flag_pending */ NULL,
- /* handle_POLLIN */ rops_handle_POLLIN_listen,
- /* handle_POLLOUT */ rops_handle_POLLOUT_listen,
- /* perform_user_POLLOUT */ NULL,
- /* callback_on_writable */ NULL,
- /* tx_credit */ NULL,
- /* write_role_protocol */ NULL,
- /* encapsulation_parent */ NULL,
- /* alpn_negotiated */ NULL,
- /* close_via_role_protocol */ NULL,
- /* close_role */ NULL,
- /* close_kill_connection */ NULL,
- /* destroy_role */ NULL,
- /* writeable cb clnt, srv */ { 0, 0 },
- /* close cb clnt, srv */ { 0, 0 },
- /* file_handle */ 0,
-};
diff --git a/thirdparty/libwebsockets/roles/pipe/ops-pipe.c b/thirdparty/libwebsockets/roles/pipe/ops-pipe.c
deleted file mode 100644
index b9348d58d7..0000000000
--- a/thirdparty/libwebsockets/roles/pipe/ops-pipe.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010-2018 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- */
-
-#include <core/private.h>
-
-static int
-rops_handle_POLLIN_pipe(struct lws_context_per_thread *pt, struct lws *wsi,
- struct lws_pollfd *pollfd)
-{
-#if !defined(WIN32) && !defined(_WIN32)
- char s[100];
- int n;
-
- /*
- * discard the byte(s) that signaled us
- * We really don't care about the number of bytes, but coverity
- * thinks we should.
- */
- n = read(wsi->desc.sockfd, s, sizeof(s));
- (void)n;
- if (n < 0)
- return LWS_HPI_RET_PLEASE_CLOSE_ME;
-#endif
- /*
- * the poll() wait, or the event loop for libuv etc is a
- * process-wide resource that we interrupted. So let every
- * protocol that may be interested in the pipe event know that
- * it happened.
- */
- if (lws_broadcast(wsi->context, LWS_CALLBACK_EVENT_WAIT_CANCELLED,
- NULL, 0)) {
- lwsl_info("closed in event cancel\n");
- return LWS_HPI_RET_PLEASE_CLOSE_ME;
- }
-
- return LWS_HPI_RET_HANDLED;
-}
-
-struct lws_role_ops role_ops_pipe = {
- /* role name */ "pipe",
- /* alpn id */ NULL,
- /* check_upgrades */ NULL,
- /* init_context */ NULL,
- /* init_vhost */ NULL,
- /* destroy_vhost */ NULL,
- /* periodic_checks */ NULL,
- /* service_flag_pending */ NULL,
- /* handle_POLLIN */ rops_handle_POLLIN_pipe,
- /* handle_POLLOUT */ NULL,
- /* perform_user_POLLOUT */ NULL,
- /* callback_on_writable */ NULL,
- /* tx_credit */ NULL,
- /* write_role_protocol */ NULL,
- /* encapsulation_parent */ NULL,
- /* alpn_negotiated */ NULL,
- /* close_via_role_protocol */ NULL,
- /* close_role */ NULL,
- /* close_kill_connection */ NULL,
- /* destroy_role */ NULL,
- /* writeable cb clnt, srv */ { 0, 0 },
- /* close cb clnt, srv */ { 0, 0 },
- /* file_handle */ 1,
-};
diff --git a/thirdparty/libwebsockets/roles/private.h b/thirdparty/libwebsockets/roles/private.h
deleted file mode 100644
index ae4278b5d3..0000000000
--- a/thirdparty/libwebsockets/roles/private.h
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010 - 2018 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * This is included from core/private.h
- */
-
-typedef uint32_t lws_wsi_state_t;
-
-/*
- * The wsi->role_ops pointer decides almost everything about what role the wsi
- * will play, h2, raw, ws, etc.
- *
- * However there are a few additional flags needed that vary, such as if the
- * role is a client or server side, if it has that concept. And the connection
- * fulfilling the role, has a separate dynamic state.
- *
- * 31 16 15 0
- * [ role flags ] [ state ]
- *
- * The role flags part is generally invariant for the lifetime of the wsi,
- * although it can change if the connection role itself does, eg, if the
- * connection upgrades from H1 -> WS1 the role flags may be changed at that
- * point.
- *
- * The state part reflects the dynamic connection state, and the states are
- * reused between roles.
- *
- * None of the internal role or state representations are made available outside
- * of lws internals. Even for lws internals, if you add stuff here, please keep
- * the constants inside this header only by adding necessary helpers here and
- * use the helpers in the actual code. This is to ease any future refactors.
- *
- * Notice LWSIFR_ENCAP means we have a parent wsi that actually carries our
- * data as a stream inside a different protocol.
- */
-
-#define _RS 16
-
-#define LWSIFR_CLIENT (0x1000 << _RS) /* client side */
-#define LWSIFR_SERVER (0x2000 << _RS) /* server side */
-
-#define LWSIFR_P_ENCAP_H2 (0x0100 << _RS) /* we are encapsulated by h2 */
-
-enum lwsi_role {
- LWSI_ROLE_MASK = (0xffff << _RS),
- LWSI_ROLE_ENCAP_MASK = (0x0f00 << _RS),
-};
-
-#define lwsi_role(wsi) (wsi->wsistate & LWSI_ROLE_MASK)
-#if !defined (_DEBUG)
-#define lwsi_set_role(wsi, role) wsi->wsistate = \
- (wsi->wsistate & (~LWSI_ROLE_MASK)) | role
-#else
-void lwsi_set_role(struct lws *wsi, lws_wsi_state_t role);
-#endif
-
-#define lwsi_role_client(wsi) (!!(wsi->wsistate & LWSIFR_CLIENT))
-#define lwsi_role_server(wsi) (!!(wsi->wsistate & LWSIFR_SERVER))
-#define lwsi_role_h2_ENCAPSULATION(wsi) \
- ((wsi->wsistate & LWSI_ROLE_ENCAP_MASK) == LWSIFR_P_ENCAP_H2)
-
-/* Pollout wants a callback in this state */
-#define LWSIFS_POCB (0x100)
-/* Before any protocol connection was established */
-#define LWSIFS_NOT_EST (0x200)
-
-enum lwsi_state {
-
- /* Phase 1: pre-transport */
-
- LRS_UNCONNECTED = LWSIFS_NOT_EST | 0,
- LRS_WAITING_CONNECT = LWSIFS_NOT_EST | 1,
-
- /* Phase 2: establishing intermediaries on top of transport */
-
- LRS_WAITING_PROXY_REPLY = LWSIFS_NOT_EST | 2,
- LRS_WAITING_SSL = LWSIFS_NOT_EST | 3,
- LRS_WAITING_SOCKS_GREETING_REPLY = LWSIFS_NOT_EST | 4,
- LRS_WAITING_SOCKS_CONNECT_REPLY = LWSIFS_NOT_EST | 5,
- LRS_WAITING_SOCKS_AUTH_REPLY = LWSIFS_NOT_EST | 6,
-
- /* Phase 3: establishing tls tunnel */
-
- LRS_SSL_INIT = LWSIFS_NOT_EST | 7,
- LRS_SSL_ACK_PENDING = LWSIFS_NOT_EST | 8,
- LRS_PRE_WS_SERVING_ACCEPT = LWSIFS_NOT_EST | 9,
-
- /* Phase 4: connected */
-
- LRS_WAITING_SERVER_REPLY = LWSIFS_NOT_EST | 10,
- LRS_H2_AWAIT_PREFACE = LWSIFS_NOT_EST | 11,
- LRS_H2_AWAIT_SETTINGS = LWSIFS_NOT_EST |
- LWSIFS_POCB | 12,
-
- /* Phase 5: protocol logically established */
-
- LRS_H2_CLIENT_SEND_SETTINGS = LWSIFS_POCB | 13,
- LRS_H2_WAITING_TO_SEND_HEADERS = LWSIFS_POCB | 14,
- LRS_DEFERRING_ACTION = LWSIFS_POCB | 15,
- LRS_IDLING = 16,
- LRS_H1C_ISSUE_HANDSHAKE = 17,
- LRS_H1C_ISSUE_HANDSHAKE2 = 18,
- LRS_ISSUE_HTTP_BODY = 19,
- LRS_ISSUING_FILE = 20,
- LRS_HEADERS = 21,
- LRS_BODY = 22,
- LRS_ESTABLISHED = LWSIFS_POCB | 23,
- /* we are established, but we have embarked on serving a single
- * transaction. Other transaction input may be pending, but we will
- * not service it while we are busy dealing with the current
- * transaction.
- *
- * When we complete the current transaction, we would reset our state
- * back to ESTABLISHED and start to process the next transaction.
- */
- LRS_DOING_TRANSACTION = LWSIFS_POCB | 24,
-
- /* Phase 6: finishing */
-
- LRS_WAITING_TO_SEND_CLOSE = LWSIFS_POCB | 25,
- LRS_RETURNED_CLOSE = LWSIFS_POCB | 26,
- LRS_AWAITING_CLOSE_ACK = LWSIFS_POCB | 27,
- LRS_FLUSHING_BEFORE_CLOSE = LWSIFS_POCB | 28,
- LRS_SHUTDOWN = 29,
-
- /* Phase 7: dead */
-
- LRS_DEAD_SOCKET = 30,
-
- LRS_MASK = 0xffff
-};
-
-#define lwsi_state(wsi) ((enum lwsi_state)(wsi->wsistate & LRS_MASK))
-#define lwsi_state_PRE_CLOSE(wsi) ((enum lwsi_state)(wsi->wsistate_pre_close & LRS_MASK))
-#define lwsi_state_est(wsi) (!(wsi->wsistate & LWSIFS_NOT_EST))
-#define lwsi_state_est_PRE_CLOSE(wsi) (!(wsi->wsistate_pre_close & LWSIFS_NOT_EST))
-#define lwsi_state_can_handle_POLLOUT(wsi) (wsi->wsistate & LWSIFS_POCB)
-#if !defined (_DEBUG)
-#define lwsi_set_state(wsi, lrs) wsi->wsistate = \
- (wsi->wsistate & (~LRS_MASK)) | lrs
-#else
-void lwsi_set_state(struct lws *wsi, lws_wsi_state_t lrs);
-#endif
-
-/*
- * internal role-specific ops
- */
-struct lws_context_per_thread;
-struct lws_role_ops {
- const char *name;
- const char *alpn;
- /*
- * After http headers have parsed, this is the last chance for a role
- * to upgrade the connection to something else using the headers.
- * ws-over-h2 is upgraded from h2 like this.
- */
- int (*check_upgrades)(struct lws *wsi);
- /* role-specific context init during context creation */
- int (*init_context)(struct lws_context *context,
- const struct lws_context_creation_info *info);
- /* role-specific per-vhost init during vhost creation */
- int (*init_vhost)(struct lws_vhost *vh,
- const struct lws_context_creation_info *info);
- /* role-specific per-vhost destructor during vhost destroy */
- int (*destroy_vhost)(struct lws_vhost *vh);
- /* generic 1Hz callback for the role itself */
- int (*periodic_checks)(struct lws_context *context, int tsi,
- time_t now);
- /* chance for the role to force POLLIN without network activity */
- int (*service_flag_pending)(struct lws_context *context, int tsi);
- /* an fd using this role has POLLIN signalled */
- int (*handle_POLLIN)(struct lws_context_per_thread *pt, struct lws *wsi,
- struct lws_pollfd *pollfd);
- /* an fd using the role wanted a POLLOUT callback and now has it */
- int (*handle_POLLOUT)(struct lws *wsi);
- /* perform user pollout */
- int (*perform_user_POLLOUT)(struct lws *wsi);
- /* do effective callback on writeable */
- int (*callback_on_writable)(struct lws *wsi);
- /* connection-specific tx credit in bytes */
- lws_fileofs_t (*tx_credit)(struct lws *wsi);
- /* role-specific write formatting */
- int (*write_role_protocol)(struct lws *wsi, unsigned char *buf,
- size_t len, enum lws_write_protocol *wp);
-
- /* get encapsulation parent */
- struct lws * (*encapsulation_parent)(struct lws *wsi);
-
- /* role-specific destructor */
- int (*alpn_negotiated)(struct lws *wsi, const char *alpn);
-
- /* chance for the role to handle close in the protocol */
- int (*close_via_role_protocol)(struct lws *wsi,
- enum lws_close_status reason);
- /* role-specific close processing */
- int (*close_role)(struct lws_context_per_thread *pt, struct lws *wsi);
- /* role-specific connection close processing */
- int (*close_kill_connection)(struct lws *wsi,
- enum lws_close_status reason);
- /* role-specific destructor */
- int (*destroy_role)(struct lws *wsi);
-
- /*
- * the callback reasons for WRITEABLE for client, server
- * (just client applies if no concept of client or server)
- */
- uint16_t writeable_cb[2];
- /*
- * the callback reasons for CLOSE for client, server
- * (just client applies if no concept of client or server)
- */
- uint16_t close_cb[2];
-
- unsigned int file_handle:1; /* role operates on files not sockets */
-};
-
-/* core roles */
-extern struct lws_role_ops role_ops_raw_skt, role_ops_raw_file, role_ops_listen,
- role_ops_pipe;
-
-/* bring in role private declarations */
-
-#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
- #include "roles/http/private.h"
-#else
- #define lwsi_role_http(wsi) (0)
-#endif
-
-#if defined(LWS_ROLE_H1)
- #include "roles/h1/private.h"
-#else
- #define lwsi_role_h1(wsi) (0)
-#endif
-
-#if defined(LWS_ROLE_H2)
- #include "roles/h2/private.h"
-#else
- #define lwsi_role_h2(wsi) (0)
-#endif
-
-#if defined(LWS_ROLE_WS)
- #include "roles/ws/private.h"
-#else
- #define lwsi_role_ws(wsi) (0)
-#endif
-
-#if defined(LWS_ROLE_CGI)
- #include "roles/cgi/private.h"
-#else
- #define lwsi_role_cgi(wsi) (0)
-#endif
-
-enum {
- LWS_HP_RET_BAIL_OK,
- LWS_HP_RET_BAIL_DIE,
- LWS_HP_RET_USER_SERVICE,
-
- LWS_HPI_RET_WSI_ALREADY_DIED, /* we closed it */
- LWS_HPI_RET_HANDLED, /* no probs */
- LWS_HPI_RET_PLEASE_CLOSE_ME, /* close it for us */
-
- LWS_UPG_RET_DONE,
- LWS_UPG_RET_CONTINUE,
- LWS_UPG_RET_BAIL
-};
diff --git a/thirdparty/libwebsockets/roles/raw/ops-raw.c b/thirdparty/libwebsockets/roles/raw/ops-raw.c
deleted file mode 100644
index 68b52bded6..0000000000
--- a/thirdparty/libwebsockets/roles/raw/ops-raw.c
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010-2018 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- */
-
-#include <core/private.h>
-
-static int
-rops_handle_POLLIN_raw_skt(struct lws_context_per_thread *pt, struct lws *wsi,
- struct lws_pollfd *pollfd)
-{
- struct lws_tokens ebuf;
- int n, buffered;
-
- /* pending truncated sends have uber priority */
-
- if (wsi->trunc_len) {
- if (!(pollfd->revents & LWS_POLLOUT))
- return LWS_HPI_RET_HANDLED;
-
- if (lws_issue_raw(wsi, wsi->trunc_alloc + wsi->trunc_offset,
- wsi->trunc_len) < 0)
- goto fail;
- /*
- * we can't afford to allow input processing to send
- * something new, so spin around he event loop until
- * he doesn't have any partials
- */
- return LWS_HPI_RET_HANDLED;
- }
-
- if ((pollfd->revents & pollfd->events & LWS_POLLIN) &&
- /* any tunnel has to have been established... */
- lwsi_state(wsi) != LRS_SSL_ACK_PENDING &&
- !(wsi->favoured_pollin &&
- (pollfd->revents & pollfd->events & LWS_POLLOUT))) {
-
- buffered = lws_buflist_aware_read(pt, wsi, &ebuf);
- switch (ebuf.len) {
- case 0:
- lwsl_info("%s: read 0 len\n", __func__);
- wsi->seen_zero_length_recv = 1;
- lws_change_pollfd(wsi, LWS_POLLIN, 0);
-
- /*
- * we need to go to fail here, since it's the only
- * chance we get to understand that the socket has
- * closed
- */
- // goto try_pollout;
- goto fail;
-
- case LWS_SSL_CAPABLE_ERROR:
- goto fail;
- case LWS_SSL_CAPABLE_MORE_SERVICE:
- goto try_pollout;
- }
-
- n = user_callback_handle_rxflow(wsi->protocol->callback,
- wsi, LWS_CALLBACK_RAW_RX,
- wsi->user_space, ebuf.token,
- ebuf.len);
- if (n < 0) {
- lwsl_info("LWS_CALLBACK_RAW_RX_fail\n");
- goto fail;
- }
-
- if (lws_buflist_aware_consume(wsi, &ebuf, ebuf.len, buffered))
- return LWS_HPI_RET_PLEASE_CLOSE_ME;
- } else
- if (wsi->favoured_pollin &&
- (pollfd->revents & pollfd->events & LWS_POLLOUT))
- /* we balanced the last favouring of pollin */
- wsi->favoured_pollin = 0;
-
-try_pollout:
-
- /* this handles POLLOUT for http serving fragments */
-
- if (!(pollfd->revents & LWS_POLLOUT))
- return LWS_HPI_RET_HANDLED;
-
- /* one shot */
- if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) {
- lwsl_notice("%s a\n", __func__);
- goto fail;
- }
-
- /* clear back-to-back write detection */
- wsi->could_have_pending = 0;
-
- lws_stats_atomic_bump(wsi->context, pt,
- LWSSTATS_C_WRITEABLE_CB, 1);
-#if defined(LWS_WITH_STATS)
- if (wsi->active_writable_req_us) {
- uint64_t ul = time_in_microseconds() -
- wsi->active_writable_req_us;
-
- lws_stats_atomic_bump(wsi->context, pt,
- LWSSTATS_MS_WRITABLE_DELAY, ul);
- lws_stats_atomic_max(wsi->context, pt,
- LWSSTATS_MS_WORST_WRITABLE_DELAY, ul);
- wsi->active_writable_req_us = 0;
- }
-#endif
- n = user_callback_handle_rxflow(wsi->protocol->callback,
- wsi, LWS_CALLBACK_RAW_WRITEABLE,
- wsi->user_space, NULL, 0);
- if (n < 0) {
- lwsl_info("writeable_fail\n");
- goto fail;
- }
-
- return LWS_HPI_RET_HANDLED;
-
-fail:
- lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "raw svc fail");
-
- return LWS_HPI_RET_WSI_ALREADY_DIED;
-}
-
-
-static int
-rops_handle_POLLIN_raw_file(struct lws_context_per_thread *pt, struct lws *wsi,
- struct lws_pollfd *pollfd)
-{
- int n;
-
- if (pollfd->revents & LWS_POLLOUT) {
- n = lws_callback_as_writeable(wsi);
- if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) {
- lwsl_info("failed at set pollfd\n");
- return LWS_HPI_RET_WSI_ALREADY_DIED;
- }
- if (n)
- return LWS_HPI_RET_PLEASE_CLOSE_ME;
- }
-
- if (pollfd->revents & LWS_POLLIN) {
- if (user_callback_handle_rxflow(wsi->protocol->callback,
- wsi, LWS_CALLBACK_RAW_RX_FILE,
- wsi->user_space, NULL, 0)) {
- lwsl_debug("raw rx callback closed it\n");
- return LWS_HPI_RET_PLEASE_CLOSE_ME;
- }
- }
-
- if (pollfd->revents & LWS_POLLHUP)
- return LWS_HPI_RET_PLEASE_CLOSE_ME;
-
- return LWS_HPI_RET_HANDLED;
-}
-
-
-struct lws_role_ops role_ops_raw_skt = {
- /* role name */ "raw-skt",
- /* alpn id */ NULL,
- /* check_upgrades */ NULL,
- /* init_context */ NULL,
- /* init_vhost */ NULL,
- /* destroy_vhost */ NULL,
- /* periodic_checks */ NULL,
- /* service_flag_pending */ NULL,
- /* handle_POLLIN */ rops_handle_POLLIN_raw_skt,
- /* handle_POLLOUT */ NULL,
- /* perform_user_POLLOUT */ NULL,
- /* callback_on_writable */ NULL,
- /* tx_credit */ NULL,
- /* write_role_protocol */ NULL,
- /* encapsulation_parent */ NULL,
- /* alpn_negotiated */ NULL,
- /* close_via_role_protocol */ NULL,
- /* close_role */ NULL,
- /* close_kill_connection */ NULL,
- /* destroy_role */ NULL,
- /* writeable cb clnt, srv */ { LWS_CALLBACK_RAW_WRITEABLE, 0 },
- /* close cb clnt, srv */ { LWS_CALLBACK_RAW_CLOSE, 0 },
- /* file_handle */ 0,
-};
-
-
-
-struct lws_role_ops role_ops_raw_file = {
- /* role name */ "raw-file",
- /* alpn id */ NULL,
- /* check_upgrades */ NULL,
- /* init_context */ NULL,
- /* init_vhost */ NULL,
- /* destroy_vhost */ NULL,
- /* periodic_checks */ NULL,
- /* service_flag_pending */ NULL,
- /* handle_POLLIN */ rops_handle_POLLIN_raw_file,
- /* handle_POLLOUT */ NULL,
- /* perform_user_POLLOUT */ NULL,
- /* callback_on_writable */ NULL,
- /* tx_credit */ NULL,
- /* write_role_protocol */ NULL,
- /* encapsulation_parent */ NULL,
- /* alpn_negotiated */ NULL,
- /* close_via_role_protocol */ NULL,
- /* close_role */ NULL,
- /* close_kill_connection */ NULL,
- /* destroy_role */ NULL,
- /* writeable cb clnt, srv */ { LWS_CALLBACK_RAW_WRITEABLE_FILE, 0 },
- /* close cb clnt, srv */ { LWS_CALLBACK_RAW_CLOSE_FILE, 0 },
- /* file_handle */ 1,
-};
diff --git a/thirdparty/libwebsockets/roles/ws/client-parser-ws.c b/thirdparty/libwebsockets/roles/ws/client-parser-ws.c
deleted file mode 100644
index 7287fb1590..0000000000
--- a/thirdparty/libwebsockets/roles/ws/client-parser-ws.c
+++ /dev/null
@@ -1,605 +0,0 @@
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010-2017 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- */
-
-#include "core/private.h"
-
-/*
- * parsers.c: lws_ws_rx_sm() needs to be roughly kept in
- * sync with changes here, esp related to ext draining
- */
-
-int lws_ws_client_rx_sm(struct lws *wsi, unsigned char c)
-{
- int callback_action = LWS_CALLBACK_CLIENT_RECEIVE;
- int handled, m;
- unsigned short close_code;
- struct lws_tokens ebuf;
- unsigned char *pp;
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- int rx_draining_ext = 0, n;
-#endif
-
- ebuf.token = NULL;
- ebuf.len = 0;
-
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- if (wsi->ws->rx_draining_ext) {
- assert(!c);
-
- lws_remove_wsi_from_draining_ext_list(wsi);
- rx_draining_ext = 1;
- lwsl_debug("%s: doing draining flow\n", __func__);
-
- goto drain_extension;
- }
-#endif
-
- if (wsi->socket_is_permanently_unusable)
- return -1;
-
- switch (wsi->lws_rx_parse_state) {
- case LWS_RXPS_NEW:
- /* control frames (PING) may interrupt checkable sequences */
- wsi->ws->defeat_check_utf8 = 0;
-
- switch (wsi->ws->ietf_spec_revision) {
- case 13:
- wsi->ws->opcode = c & 0xf;
- /* revisit if an extension wants them... */
- switch (wsi->ws->opcode) {
- case LWSWSOPC_TEXT_FRAME:
- wsi->ws->rsv_first_msg = (c & 0x70);
- wsi->ws->continuation_possible = 1;
- wsi->ws->check_utf8 = lws_check_opt(
- wsi->context->options,
- LWS_SERVER_OPTION_VALIDATE_UTF8);
- wsi->ws->utf8 = 0;
- wsi->ws->first_fragment = 1;
- break;
- case LWSWSOPC_BINARY_FRAME:
- wsi->ws->rsv_first_msg = (c & 0x70);
- wsi->ws->check_utf8 = 0;
- wsi->ws->continuation_possible = 1;
- wsi->ws->first_fragment = 1;
- break;
- case LWSWSOPC_CONTINUATION:
- if (!wsi->ws->continuation_possible) {
- lwsl_info("disordered continuation\n");
- return -1;
- }
- wsi->ws->first_fragment = 0;
- break;
- case LWSWSOPC_CLOSE:
- wsi->ws->check_utf8 = 0;
- wsi->ws->utf8 = 0;
- break;
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
- case 0xb:
- case 0xc:
- case 0xd:
- case 0xe:
- case 0xf:
- lwsl_info("illegal opcode\n");
- return -1;
- default:
- wsi->ws->defeat_check_utf8 = 1;
- break;
- }
- wsi->ws->rsv = (c & 0x70);
- /* revisit if an extension wants them... */
- if (
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- !wsi->ws->count_act_ext &&
-#endif
- wsi->ws->rsv) {
- lwsl_info("illegal rsv bits set\n");
- return -1;
- }
- wsi->ws->final = !!((c >> 7) & 1);
- lwsl_ext("%s: This RX frame Final %d\n", __func__,
- wsi->ws->final);
-
- if (wsi->ws->owed_a_fin &&
- (wsi->ws->opcode == LWSWSOPC_TEXT_FRAME ||
- wsi->ws->opcode == LWSWSOPC_BINARY_FRAME)) {
- lwsl_info("hey you owed us a FIN\n");
- return -1;
- }
- if ((!(wsi->ws->opcode & 8)) && wsi->ws->final) {
- wsi->ws->continuation_possible = 0;
- wsi->ws->owed_a_fin = 0;
- }
-
- if ((wsi->ws->opcode & 8) && !wsi->ws->final) {
- lwsl_info("control msg can't be fragmented\n");
- return -1;
- }
- if (!wsi->ws->final)
- wsi->ws->owed_a_fin = 1;
-
- switch (wsi->ws->opcode) {
- case LWSWSOPC_TEXT_FRAME:
- case LWSWSOPC_BINARY_FRAME:
- wsi->ws->frame_is_binary = wsi->ws->opcode ==
- LWSWSOPC_BINARY_FRAME;
- break;
- }
- wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN;
- break;
-
- default:
- lwsl_err("unknown spec version %02d\n",
- wsi->ws->ietf_spec_revision);
- break;
- }
- break;
-
- case LWS_RXPS_04_FRAME_HDR_LEN:
-
- wsi->ws->this_frame_masked = !!(c & 0x80);
-
- switch (c & 0x7f) {
- case 126:
- /* control frames are not allowed to have big lengths */
- if (wsi->ws->opcode & 8)
- goto illegal_ctl_length;
- wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_2;
- break;
- case 127:
- /* control frames are not allowed to have big lengths */
- if (wsi->ws->opcode & 8)
- goto illegal_ctl_length;
- wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_8;
- break;
- default:
- wsi->ws->rx_packet_length = c & 0x7f;
- if (wsi->ws->this_frame_masked)
- wsi->lws_rx_parse_state =
- LWS_RXPS_07_COLLECT_FRAME_KEY_1;
- else {
- if (wsi->ws->rx_packet_length) {
- wsi->lws_rx_parse_state =
- LWS_RXPS_WS_FRAME_PAYLOAD;
- } else {
- wsi->lws_rx_parse_state = LWS_RXPS_NEW;
- goto spill;
- }
- }
- break;
- }
- break;
-
- case LWS_RXPS_04_FRAME_HDR_LEN16_2:
- wsi->ws->rx_packet_length = c << 8;
- wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_1;
- break;
-
- case LWS_RXPS_04_FRAME_HDR_LEN16_1:
- wsi->ws->rx_packet_length |= c;
- if (wsi->ws->this_frame_masked)
- wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_1;
- else {
- if (wsi->ws->rx_packet_length)
- wsi->lws_rx_parse_state =
- LWS_RXPS_WS_FRAME_PAYLOAD;
- else {
- wsi->lws_rx_parse_state = LWS_RXPS_NEW;
- goto spill;
- }
- }
- break;
-
- case LWS_RXPS_04_FRAME_HDR_LEN64_8:
- if (c & 0x80) {
- lwsl_warn("b63 of length must be zero\n");
- /* kill the connection */
- return -1;
- }
-#if defined __LP64__
- wsi->ws->rx_packet_length = ((size_t)c) << 56;
-#else
- wsi->ws->rx_packet_length = 0;
-#endif
- wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_7;
- break;
-
- case LWS_RXPS_04_FRAME_HDR_LEN64_7:
-#if defined __LP64__
- wsi->ws->rx_packet_length |= ((size_t)c) << 48;
-#endif
- wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_6;
- break;
-
- case LWS_RXPS_04_FRAME_HDR_LEN64_6:
-#if defined __LP64__
- wsi->ws->rx_packet_length |= ((size_t)c) << 40;
-#endif
- wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_5;
- break;
-
- case LWS_RXPS_04_FRAME_HDR_LEN64_5:
-#if defined __LP64__
- wsi->ws->rx_packet_length |= ((size_t)c) << 32;
-#endif
- wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_4;
- break;
-
- case LWS_RXPS_04_FRAME_HDR_LEN64_4:
- wsi->ws->rx_packet_length |= ((size_t)c) << 24;
- wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_3;
- break;
-
- case LWS_RXPS_04_FRAME_HDR_LEN64_3:
- wsi->ws->rx_packet_length |= ((size_t)c) << 16;
- wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_2;
- break;
-
- case LWS_RXPS_04_FRAME_HDR_LEN64_2:
- wsi->ws->rx_packet_length |= ((size_t)c) << 8;
- wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_1;
- break;
-
- case LWS_RXPS_04_FRAME_HDR_LEN64_1:
- wsi->ws->rx_packet_length |= (size_t)c;
- if (wsi->ws->this_frame_masked)
- wsi->lws_rx_parse_state =
- LWS_RXPS_07_COLLECT_FRAME_KEY_1;
- else {
- if (wsi->ws->rx_packet_length)
- wsi->lws_rx_parse_state =
- LWS_RXPS_WS_FRAME_PAYLOAD;
- else {
- wsi->lws_rx_parse_state = LWS_RXPS_NEW;
- goto spill;
- }
- }
- break;
-
- case LWS_RXPS_07_COLLECT_FRAME_KEY_1:
- wsi->ws->mask[0] = c;
- if (c)
- wsi->ws->all_zero_nonce = 0;
- wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_2;
- break;
-
- case LWS_RXPS_07_COLLECT_FRAME_KEY_2:
- wsi->ws->mask[1] = c;
- if (c)
- wsi->ws->all_zero_nonce = 0;
- wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_3;
- break;
-
- case LWS_RXPS_07_COLLECT_FRAME_KEY_3:
- wsi->ws->mask[2] = c;
- if (c)
- wsi->ws->all_zero_nonce = 0;
- wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_4;
- break;
-
- case LWS_RXPS_07_COLLECT_FRAME_KEY_4:
- wsi->ws->mask[3] = c;
- if (c)
- wsi->ws->all_zero_nonce = 0;
-
- if (wsi->ws->rx_packet_length)
- wsi->lws_rx_parse_state =
- LWS_RXPS_WS_FRAME_PAYLOAD;
- else {
- wsi->lws_rx_parse_state = LWS_RXPS_NEW;
- goto spill;
- }
- break;
-
- case LWS_RXPS_WS_FRAME_PAYLOAD:
-
- assert(wsi->ws->rx_ubuf);
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- if (wsi->ws->rx_draining_ext)
- goto drain_extension;
-#endif
- if (wsi->ws->this_frame_masked && !wsi->ws->all_zero_nonce)
- c ^= wsi->ws->mask[(wsi->ws->mask_idx++) & 3];
-
- wsi->ws->rx_ubuf[LWS_PRE + (wsi->ws->rx_ubuf_head++)] = c;
-
- if (--wsi->ws->rx_packet_length == 0) {
- /* spill because we have the whole frame */
- wsi->lws_rx_parse_state = LWS_RXPS_NEW;
- goto spill;
- }
-
- /*
- * if there's no protocol max frame size given, we are
- * supposed to default to context->pt_serv_buf_size
- */
- if (!wsi->protocol->rx_buffer_size &&
- wsi->ws->rx_ubuf_head != wsi->context->pt_serv_buf_size)
- break;
-
- if (wsi->protocol->rx_buffer_size &&
- wsi->ws->rx_ubuf_head != wsi->protocol->rx_buffer_size)
- break;
-
- /* spill because we filled our rx buffer */
-spill:
-
- handled = 0;
-
- /*
- * is this frame a control packet we should take care of at this
- * layer? If so service it and hide it from the user callback
- */
-
- switch (wsi->ws->opcode) {
- case LWSWSOPC_CLOSE:
- pp = (unsigned char *)&wsi->ws->rx_ubuf[LWS_PRE];
- if (lws_check_opt(wsi->context->options,
- LWS_SERVER_OPTION_VALIDATE_UTF8) &&
- wsi->ws->rx_ubuf_head > 2 &&
- lws_check_utf8(&wsi->ws->utf8, pp + 2,
- wsi->ws->rx_ubuf_head - 2))
- goto utf8_fail;
-
- /* is this an acknowledgment of our close? */
- if (lwsi_state(wsi) == LRS_AWAITING_CLOSE_ACK) {
- /*
- * fine he has told us he is closing too, let's
- * finish our close
- */
- lwsl_parser("seen server's close ack\n");
- return -1;
- }
-
- lwsl_parser("client sees server close len = %d\n",
- wsi->ws->rx_ubuf_head);
- if (wsi->ws->rx_ubuf_head >= 2) {
- close_code = (pp[0] << 8) | pp[1];
- if (close_code < 1000 ||
- close_code == 1004 ||
- close_code == 1005 ||
- close_code == 1006 ||
- close_code == 1012 ||
- close_code == 1013 ||
- close_code == 1014 ||
- close_code == 1015 ||
- (close_code >= 1016 && close_code < 3000)
- ) {
- pp[0] = (LWS_CLOSE_STATUS_PROTOCOL_ERR >> 8) & 0xff;
- pp[1] = LWS_CLOSE_STATUS_PROTOCOL_ERR & 0xff;
- }
- }
- if (user_callback_handle_rxflow(
- wsi->protocol->callback, wsi,
- LWS_CALLBACK_WS_PEER_INITIATED_CLOSE,
- wsi->user_space, pp,
- wsi->ws->rx_ubuf_head))
- return -1;
-
- memcpy(wsi->ws->ping_payload_buf + LWS_PRE, pp,
- wsi->ws->rx_ubuf_head);
- wsi->ws->close_in_ping_buffer_len = wsi->ws->rx_ubuf_head;
-
- lwsl_info("%s: scheduling return close as ack\n", __func__);
- __lws_change_pollfd(wsi, LWS_POLLIN, 0);
- lws_set_timeout(wsi, PENDING_TIMEOUT_CLOSE_SEND, 3);
- wsi->waiting_to_send_close_frame = 1;
- wsi->close_needs_ack = 0;
- lwsi_set_state(wsi, LRS_WAITING_TO_SEND_CLOSE);
- lws_callback_on_writable(wsi);
- handled = 1;
- break;
-
- case LWSWSOPC_PING:
- lwsl_info("received %d byte ping, sending pong\n",
- wsi->ws->rx_ubuf_head);
-
- /* he set a close reason on this guy, ignore PING */
- if (wsi->ws->close_in_ping_buffer_len)
- goto ping_drop;
-
- if (wsi->ws->ping_pending_flag) {
- /*
- * there is already a pending ping payload
- * we should just log and drop
- */
- lwsl_parser("DROP PING since one pending\n");
- goto ping_drop;
- }
-
- /* control packets can only be < 128 bytes long */
- if (wsi->ws->rx_ubuf_head > 128 - 3) {
- lwsl_parser("DROP PING payload too large\n");
- goto ping_drop;
- }
-
- /* stash the pong payload */
- memcpy(wsi->ws->ping_payload_buf + LWS_PRE,
- &wsi->ws->rx_ubuf[LWS_PRE],
- wsi->ws->rx_ubuf_head);
-
- wsi->ws->ping_payload_len = wsi->ws->rx_ubuf_head;
- wsi->ws->ping_pending_flag = 1;
-
- /* get it sent as soon as possible */
- lws_callback_on_writable(wsi);
-ping_drop:
- wsi->ws->rx_ubuf_head = 0;
- handled = 1;
- break;
-
- case LWSWSOPC_PONG:
- lwsl_info("client received pong\n");
- lwsl_hexdump(&wsi->ws->rx_ubuf[LWS_PRE],
- wsi->ws->rx_ubuf_head);
-
- if (wsi->pending_timeout ==
- PENDING_TIMEOUT_WS_PONG_CHECK_GET_PONG) {
- lwsl_info("%p: received expected PONG\n", wsi);
- lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
- }
-
- /* issue it */
- callback_action = LWS_CALLBACK_CLIENT_RECEIVE_PONG;
- break;
-
- case LWSWSOPC_CONTINUATION:
- case LWSWSOPC_TEXT_FRAME:
- case LWSWSOPC_BINARY_FRAME:
- break;
-
- default:
- /* not handled or failed */
- lwsl_ext("Unhandled ext opc 0x%x\n", wsi->ws->opcode);
- wsi->ws->rx_ubuf_head = 0;
-
- return -1;
- }
-
- /*
- * No it's real payload, pass it up to the user callback.
- * It's nicely buffered with the pre-padding taken care of
- * so it can be sent straight out again using lws_write
- */
- if (handled)
- goto already_done;
-
- ebuf.token = &wsi->ws->rx_ubuf[LWS_PRE];
- ebuf.len = wsi->ws->rx_ubuf_head;
-
-#if !defined(LWS_WITHOUT_EXTENSIONS)
-drain_extension:
- lwsl_ext("%s: passing %d to ext\n", __func__, ebuf.len);
-
- n = lws_ext_cb_active(wsi, LWS_EXT_CB_PAYLOAD_RX, &ebuf, 0);
- lwsl_ext("Ext RX returned %d\n", n);
- if (n < 0) {
- wsi->socket_is_permanently_unusable = 1;
- return -1;
- }
-#endif
- lwsl_debug("post inflate ebuf len %d\n", ebuf.len);
-
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- if (rx_draining_ext && !ebuf.len) {
- lwsl_debug(" --- ending drain on 0 read result\n");
- goto already_done;
- }
-#endif
-
- if (wsi->ws->check_utf8 && !wsi->ws->defeat_check_utf8) {
- if (lws_check_utf8(&wsi->ws->utf8,
- (unsigned char *)ebuf.token,
- ebuf.len)) {
- lws_close_reason(wsi,
- LWS_CLOSE_STATUS_INVALID_PAYLOAD,
- (uint8_t *)"bad utf8", 8);
- goto utf8_fail;
- }
-
- /* we are ending partway through utf-8 character? */
- if (!wsi->ws->rx_packet_length && wsi->ws->final &&
- wsi->ws->utf8
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- && !n
-#endif
- ) {
- lwsl_info("FINAL utf8 error\n");
- lws_close_reason(wsi,
- LWS_CLOSE_STATUS_INVALID_PAYLOAD,
- (uint8_t *)"partial utf8", 12);
-utf8_fail:
- lwsl_info("utf8 error\n");
- lwsl_hexdump_info(ebuf.token, ebuf.len);
-
- return -1;
- }
- }
-
- if (ebuf.len < 0 &&
- callback_action != LWS_CALLBACK_CLIENT_RECEIVE_PONG)
- goto already_done;
-
- if (!ebuf.token)
- goto already_done;
-
- ebuf.token[ebuf.len] = '\0';
-
- if (!wsi->protocol->callback)
- goto already_done;
-
- if (callback_action == LWS_CALLBACK_CLIENT_RECEIVE_PONG)
- lwsl_info("Client doing pong callback\n");
-
- if (
- /* coverity says dead code otherwise */
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- n &&
-#endif
- ebuf.len)
- /* extension had more... main loop will come back
- * we want callback to be done with this set, if so,
- * because lws_is_final() hides it was final until the
- * last chunk
- */
- lws_add_wsi_to_draining_ext_list(wsi);
- else
- lws_remove_wsi_from_draining_ext_list(wsi);
-
- if (lwsi_state(wsi) == LRS_RETURNED_CLOSE ||
- lwsi_state(wsi) == LRS_WAITING_TO_SEND_CLOSE ||
- lwsi_state(wsi) == LRS_AWAITING_CLOSE_ACK)
- goto already_done;
-
- m = wsi->protocol->callback(wsi,
- (enum lws_callback_reasons)callback_action,
- wsi->user_space, ebuf.token, ebuf.len);
-
- wsi->ws->first_fragment = 0;
-
- // lwsl_notice("%s: bulk ws rx: input used %d, output %d\n",
- // __func__, wsi->ws->rx_ubuf_head, ebuf.len);
-
- /* if user code wants to close, let caller know */
- if (m)
- return 1;
-
-already_done:
- wsi->ws->rx_ubuf_head = 0;
- break;
- default:
- lwsl_err("client rx illegal state\n");
- return 1;
- }
-
- return 0;
-
-illegal_ctl_length:
- lwsl_warn("Control frame asking for extended length is illegal\n");
-
- /* kill the connection */
- return -1;
-}
-
-
diff --git a/thirdparty/libwebsockets/roles/ws/client-ws.c b/thirdparty/libwebsockets/roles/ws/client-ws.c
deleted file mode 100644
index fd6cf42551..0000000000
--- a/thirdparty/libwebsockets/roles/ws/client-ws.c
+++ /dev/null
@@ -1,629 +0,0 @@
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010-2018 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- */
-
-#include <core/private.h>
-
-/*
- * In-place str to lower case
- */
-
-static void
-strtolower(char *s)
-{
- while (*s) {
-#ifdef LWS_PLAT_OPTEE
- int tolower_optee(int c);
- *s = tolower_optee((int)*s);
-#else
- *s = tolower((int)*s);
-#endif
- s++;
- }
-}
-
-int
-lws_create_client_ws_object(struct lws_client_connect_info *i, struct lws *wsi)
-{
- int v = SPEC_LATEST_SUPPORTED;
-
- /* allocate the ws struct for the wsi */
- wsi->ws = lws_zalloc(sizeof(*wsi->ws), "client ws struct");
- if (!wsi->ws) {
- lwsl_notice("OOM\n");
- return 1;
- }
-
- /* -1 means just use latest supported */
- if (i->ietf_version_or_minus_one != -1 &&
- i->ietf_version_or_minus_one)
- v = i->ietf_version_or_minus_one;
-
- wsi->ws->ietf_spec_revision = v;
-
- return 0;
-}
-
-#if !defined(LWS_NO_CLIENT)
-int
-lws_ws_handshake_client(struct lws *wsi, unsigned char **buf, size_t len)
-{
- if ((lwsi_state(wsi) != LRS_WAITING_PROXY_REPLY) &&
- (lwsi_state(wsi) != LRS_H1C_ISSUE_HANDSHAKE) &&
- (lwsi_state(wsi) != LRS_WAITING_SERVER_REPLY) &&
- !lwsi_role_client(wsi))
- return 0;
-
- // lwsl_notice("%s: hs client gets %d in\n", __func__, (int)len);
-
- while (len) {
- /*
- * we were accepting input but now we stopped doing so
- */
- if (lws_is_flowcontrolled(wsi)) {
- //lwsl_notice("%s: caching %ld\n", __func__, (long)len);
- lws_rxflow_cache(wsi, *buf, 0, (int)len);
- *buf += len;
- return 0;
- }
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- if (wsi->ws->rx_draining_ext) {
- int m;
-
- //lwsl_notice("%s: draining ext\n", __func__);
- if (lwsi_role_client(wsi))
- m = lws_ws_client_rx_sm(wsi, 0);
- else
- m = lws_ws_rx_sm(wsi, 0, 0);
- if (m < 0)
- return -1;
- continue;
- }
-#endif
- /* caller will account for buflist usage */
-
- if (lws_ws_client_rx_sm(wsi, *(*buf)++)) {
- lwsl_notice("%s: client_rx_sm exited, DROPPING %d\n",
- __func__, (int)len);
- return -1;
- }
- len--;
- }
- // lwsl_notice("%s: finished with %ld\n", __func__, (long)len);
-
- return 0;
-}
-#endif
-
-char *
-lws_generate_client_ws_handshake(struct lws *wsi, char *p)
-{
- char buf[128], hash[20], key_b64[40];
- int n;
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- const struct lws_extension *ext;
- int ext_count = 0;
-#endif
-
- /*
- * create the random key
- */
- n = lws_get_random(wsi->context, hash, 16);
- if (n != 16) {
- lwsl_err("Unable to read from random dev %s\n",
- SYSTEM_RANDOM_FILEPATH);
- return NULL;
- }
-
- lws_b64_encode_string(hash, 16, key_b64, sizeof(key_b64));
-
- p += sprintf(p, "Upgrade: websocket\x0d\x0a"
- "Connection: Upgrade\x0d\x0a"
- "Sec-WebSocket-Key: ");
- strcpy(p, key_b64);
- p += strlen(key_b64);
- p += sprintf(p, "\x0d\x0a");
- if (lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS))
- p += sprintf(p, "Sec-WebSocket-Protocol: %s\x0d\x0a",
- lws_hdr_simple_ptr(wsi,
- _WSI_TOKEN_CLIENT_SENT_PROTOCOLS));
-
- /* tell the server what extensions we could support */
-
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- ext = wsi->vhost->ws.extensions;
- while (ext && ext->callback) {
-
- n = wsi->vhost->protocols[0].callback(wsi,
- LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED,
- wsi->user_space, (char *)ext->name, 0);
-
- /*
- * zero return from callback means go ahead and allow
- * the extension, it's what we get if the callback is
- * unhandled
- */
-
- if (n) {
- ext++;
- continue;
- }
-
- /* apply it */
-
- if (ext_count)
- *p++ = ',';
- else
- p += sprintf(p, "Sec-WebSocket-Extensions: ");
- p += sprintf(p, "%s", ext->client_offer);
- ext_count++;
-
- ext++;
- }
- if (ext_count)
- p += sprintf(p, "\x0d\x0a");
-#endif
-
- if (wsi->ws->ietf_spec_revision)
- p += sprintf(p, "Sec-WebSocket-Version: %d\x0d\x0a",
- wsi->ws->ietf_spec_revision);
-
- /* prepare the expected server accept response */
-
- key_b64[39] = '\0'; /* enforce composed length below buf sizeof */
- n = sprintf(buf, "%s258EAFA5-E914-47DA-95CA-C5AB0DC85B11",
- key_b64);
-
- lws_SHA1((unsigned char *)buf, n, (unsigned char *)hash);
-
- lws_b64_encode_string(hash, 20,
- wsi->http.ah->initial_handshake_hash_base64,
- sizeof(wsi->http.ah->initial_handshake_hash_base64));
-
- return p;
-}
-
-int
-lws_client_ws_upgrade(struct lws *wsi, const char **cce)
-{
- int n, len, okay = 0;
- struct lws_context *context = wsi->context;
- const char *pc;
- char *p;
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
- char *sb = (char *)&pt->serv_buf[0];
- const struct lws_ext_options *opts;
- const struct lws_extension *ext;
- char ext_name[128];
- const char *c, *a;
- char ignore;
- int more = 1;
-#endif
-
- if (wsi->client_h2_substream) {/* !!! client ws-over-h2 not there yet */
- lwsl_warn("%s: client ws-over-h2 upgrade not supported yet\n",
- __func__);
- *cce = "HS: h2 / ws upgrade unsupported";
- goto bail3;
- }
-
- if (wsi->http.ah->http_response == 401) {
- lwsl_warn(
- "lws_client_handshake: got bad HTTP response '%d'\n",
- wsi->http.ah->http_response);
- *cce = "HS: ws upgrade unauthorized";
- goto bail3;
- }
-
- if (wsi->http.ah->http_response != 101) {
- lwsl_warn(
- "lws_client_handshake: got bad HTTP response '%d'\n",
- wsi->http.ah->http_response);
- *cce = "HS: ws upgrade response not 101";
- goto bail3;
- }
-
- if (lws_hdr_total_length(wsi, WSI_TOKEN_ACCEPT) == 0) {
- lwsl_info("no ACCEPT\n");
- *cce = "HS: ACCEPT missing";
- goto bail3;
- }
-
- p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_UPGRADE);
- if (!p) {
- lwsl_info("no UPGRADE\n");
- *cce = "HS: UPGRADE missing";
- goto bail3;
- }
- strtolower(p);
- if (strcmp(p, "websocket")) {
- lwsl_warn(
- "lws_client_handshake: got bad Upgrade header '%s'\n", p);
- *cce = "HS: Upgrade to something other than websocket";
- goto bail3;
- }
-
- p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_CONNECTION);
- if (!p) {
- lwsl_info("no Connection hdr\n");
- *cce = "HS: CONNECTION missing";
- goto bail3;
- }
- strtolower(p);
- if (strcmp(p, "upgrade")) {
- lwsl_warn("lws_client_int_s_hs: bad header %s\n", p);
- *cce = "HS: UPGRADE malformed";
- goto bail3;
- }
-
- pc = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS);
- if (!pc) {
- lwsl_parser("lws_client_int_s_hs: no protocol list\n");
- } else
- lwsl_parser("lws_client_int_s_hs: protocol list '%s'\n", pc);
-
- /*
- * confirm the protocol the server wants to talk was in the list
- * of protocols we offered
- */
-
- len = lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL);
- if (!len) {
- lwsl_info("%s: WSI_TOKEN_PROTOCOL is null\n", __func__);
- /*
- * no protocol name to work from,
- * default to first protocol
- */
- n = 0;
- wsi->protocol = &wsi->vhost->protocols[0];
- goto check_extensions;
- }
-
- p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL);
- len = (int)strlen(p);
-
- while (pc && *pc && !okay) {
- if (!strncmp(pc, p, len) &&
- (pc[len] == ',' || pc[len] == '\0')) {
- okay = 1;
- continue;
- }
- while (*pc && *pc++ != ',')
- ;
- while (*pc && *pc == ' ')
- pc++;
- }
-
- if (!okay) {
- lwsl_info("%s: got bad protocol %s\n", __func__, p);
- *cce = "HS: PROTOCOL malformed";
- goto bail2;
- }
-
- /*
- * identify the selected protocol struct and set it
- */
- n = 0;
- /* keep client connection pre-bound protocol */
- if (!lwsi_role_client(wsi))
- wsi->protocol = NULL;
-
- while (wsi->vhost->protocols[n].callback) {
- if (!wsi->protocol &&
- strcmp(p, wsi->vhost->protocols[n].name) == 0) {
- wsi->protocol = &wsi->vhost->protocols[n];
- break;
- }
- n++;
- }
-
- if (!wsi->vhost->protocols[n].callback) { /* no match */
- /* if server, that's already fatal */
- if (!lwsi_role_client(wsi)) {
- lwsl_info("%s: fail protocol %s\n", __func__, p);
- *cce = "HS: Cannot match protocol";
- goto bail2;
- }
-
- /* for client, find the index of our pre-bound protocol */
-
- n = 0;
- while (wsi->vhost->protocols[n].callback) {
- if (wsi->protocol && strcmp(wsi->protocol->name,
- wsi->vhost->protocols[n].name) == 0) {
- wsi->protocol = &wsi->vhost->protocols[n];
- break;
- }
- n++;
- }
-
- if (!wsi->vhost->protocols[n].callback) {
- if (wsi->protocol)
- lwsl_err("Failed to match protocol %s\n",
- wsi->protocol->name);
- else
- lwsl_err("No protocol on client\n");
- goto bail2;
- }
- }
-
- lwsl_debug("Selected protocol %s\n", wsi->protocol->name);
-
-check_extensions:
- /*
- * stitch protocol choice into the vh protocol linked list
- * We always insert ourselves at the start of the list
- *
- * X <-> B
- * X <-> pAn <-> pB
- */
-
- lws_vhost_lock(wsi->vhost);
-
- wsi->same_vh_protocol_prev = /* guy who points to us */
- &wsi->vhost->same_vh_protocol_list[n];
- wsi->same_vh_protocol_next = /* old first guy is our next */
- wsi->vhost->same_vh_protocol_list[n];
- /* we become the new first guy */
- wsi->vhost->same_vh_protocol_list[n] = wsi;
-
- if (wsi->same_vh_protocol_next)
- /* old first guy points back to us now */
- wsi->same_vh_protocol_next->same_vh_protocol_prev =
- &wsi->same_vh_protocol_next;
- wsi->on_same_vh_list = 1;
-
- lws_vhost_unlock(wsi->vhost);
-
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- /* instantiate the accepted extensions */
-
- if (!lws_hdr_total_length(wsi, WSI_TOKEN_EXTENSIONS)) {
- lwsl_ext("no client extensions allowed by server\n");
- goto check_accept;
- }
-
- /*
- * break down the list of server accepted extensions
- * and go through matching them or identifying bogons
- */
-
- if (lws_hdr_copy(wsi, sb, context->pt_serv_buf_size,
- WSI_TOKEN_EXTENSIONS) < 0) {
- lwsl_warn("ext list from server failed to copy\n");
- *cce = "HS: EXT: list too big";
- goto bail2;
- }
-
- c = sb;
- n = 0;
- ignore = 0;
- a = NULL;
- while (more) {
-
- if (*c && (*c != ',' && *c != '\t')) {
- if (*c == ';') {
- ignore = 1;
- if (!a)
- a = c + 1;
- }
- if (ignore || *c == ' ') {
- c++;
- continue;
- }
-
- ext_name[n] = *c++;
- if (n < (int)sizeof(ext_name) - 1)
- n++;
- continue;
- }
- ext_name[n] = '\0';
- ignore = 0;
- if (!*c)
- more = 0;
- else {
- c++;
- if (!n)
- continue;
- }
-
- /* check we actually support it */
-
- lwsl_notice("checking client ext %s\n", ext_name);
-
- n = 0;
- ext = wsi->vhost->ws.extensions;
- while (ext && ext->callback) {
- if (strcmp(ext_name, ext->name)) {
- ext++;
- continue;
- }
-
- n = 1;
- lwsl_notice("instantiating client ext %s\n", ext_name);
-
- /* instantiate the extension on this conn */
-
- wsi->ws->active_extensions[wsi->ws->count_act_ext] = ext;
-
- /* allow him to construct his ext instance */
-
- if (ext->callback(lws_get_context(wsi), ext, wsi,
- LWS_EXT_CB_CLIENT_CONSTRUCT,
- (void *)&wsi->ws->act_ext_user[wsi->ws->count_act_ext],
- (void *)&opts, 0)) {
- lwsl_info(" ext %s failed construction\n",
- ext_name);
- ext++;
- continue;
- }
-
- /*
- * allow the user code to override ext defaults if it
- * wants to
- */
- ext_name[0] = '\0';
- if (user_callback_handle_rxflow(wsi->protocol->callback,
- wsi, LWS_CALLBACK_WS_EXT_DEFAULTS,
- (char *)ext->name, ext_name,
- sizeof(ext_name))) {
- *cce = "HS: EXT: failed setting defaults";
- goto bail2;
- }
-
- if (ext_name[0] &&
- lws_ext_parse_options(ext, wsi, wsi->ws->act_ext_user[
- wsi->ws->count_act_ext], opts, ext_name,
- (int)strlen(ext_name))) {
- lwsl_err("%s: unable to parse user defaults '%s'",
- __func__, ext_name);
- *cce = "HS: EXT: failed parsing defaults";
- goto bail2;
- }
-
- /*
- * give the extension the server options
- */
- if (a && lws_ext_parse_options(ext, wsi,
- wsi->ws->act_ext_user[wsi->ws->count_act_ext],
- opts, a, lws_ptr_diff(c, a))) {
- lwsl_err("%s: unable to parse remote def '%s'",
- __func__, a);
- *cce = "HS: EXT: failed parsing options";
- goto bail2;
- }
-
- if (ext->callback(lws_get_context(wsi), ext, wsi,
- LWS_EXT_CB_OPTION_CONFIRM,
- wsi->ws->act_ext_user[wsi->ws->count_act_ext],
- NULL, 0)) {
- lwsl_err("%s: ext %s rejects server options %s",
- __func__, ext->name, a);
- *cce = "HS: EXT: Rejects server options";
- goto bail2;
- }
-
- wsi->ws->count_act_ext++;
-
- ext++;
- }
-
- if (n == 0) {
- lwsl_warn("Unknown ext '%s'!\n", ext_name);
- *cce = "HS: EXT: unknown ext";
- goto bail2;
- }
-
- a = NULL;
- n = 0;
- }
-
-check_accept:
-#endif
-
- /*
- * Confirm his accept token is the one we precomputed
- */
-
- p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_ACCEPT);
- if (strcmp(p, wsi->http.ah->initial_handshake_hash_base64)) {
- lwsl_warn("lws_client_int_s_hs: accept '%s' wrong vs '%s'\n", p,
- wsi->http.ah->initial_handshake_hash_base64);
- *cce = "HS: Accept hash wrong";
- goto bail2;
- }
-
- /* allocate the per-connection user memory (if any) */
- if (lws_ensure_user_space(wsi)) {
- lwsl_err("Problem allocating wsi user mem\n");
- *cce = "HS: OOM";
- goto bail2;
- }
-
- /*
- * we seem to be good to go, give client last chance to check
- * headers and OK it
- */
- if (wsi->protocol->callback(wsi,
- LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH,
- wsi->user_space, NULL, 0)) {
- *cce = "HS: Rejected by filter cb";
- goto bail2;
- }
-
- /* clear his proxy connection timeout */
- lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
-
- /* free up his parsing allocations */
- lws_header_table_detach(wsi, 0);
-
- lws_role_transition(wsi, LWSIFR_CLIENT, LRS_ESTABLISHED,
- &role_ops_ws);
- lws_restart_ws_ping_pong_timer(wsi);
-
- wsi->rxflow_change_to = LWS_RXFLOW_ALLOW;
-
- /*
- * create the frame buffer for this connection according to the
- * size mentioned in the protocol definition. If 0 there, then
- * use a big default for compatibility
- */
- n = (int)wsi->protocol->rx_buffer_size;
- if (!n)
- n = context->pt_serv_buf_size;
- n += LWS_PRE;
- wsi->ws->rx_ubuf = lws_malloc(n + 4 /* 0x0000ffff zlib */,
- "client frame buffer");
- if (!wsi->ws->rx_ubuf) {
- lwsl_err("Out of Mem allocating rx buffer %d\n", n);
- *cce = "HS: OOM";
- goto bail2;
- }
- wsi->ws->rx_ubuf_alloc = n;
- lwsl_info("Allocating client RX buffer %d\n", n);
-
-#if !defined(LWS_WITH_ESP32)
- if (setsockopt(wsi->desc.sockfd, SOL_SOCKET, SO_SNDBUF,
- (const char *)&n, sizeof n)) {
- lwsl_warn("Failed to set SNDBUF to %d", n);
- *cce = "HS: SO_SNDBUF failed";
- goto bail3;
- }
-#endif
-
- lwsl_debug("handshake OK for protocol %s\n", wsi->protocol->name);
-
- /* call him back to inform him he is up */
-
- if (wsi->protocol->callback(wsi, LWS_CALLBACK_CLIENT_ESTABLISHED,
- wsi->user_space, NULL, 0)) {
- *cce = "HS: Rejected at CLIENT_ESTABLISHED";
- goto bail3;
- }
-
- return 0;
-
-bail3:
- return 3;
-
-bail2:
- return 2;
-}
diff --git a/thirdparty/libwebsockets/roles/ws/ops-ws.c b/thirdparty/libwebsockets/roles/ws/ops-ws.c
deleted file mode 100644
index 665b2c9b74..0000000000
--- a/thirdparty/libwebsockets/roles/ws/ops-ws.c
+++ /dev/null
@@ -1,1994 +0,0 @@
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010-2018 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- */
-
-#include <core/private.h>
-
-#define LWS_CPYAPP(ptr, str) { strcpy(ptr, str); ptr += strlen(str); }
-
-/*
- * client-parser.c: lws_ws_client_rx_sm() needs to be roughly kept in
- * sync with changes here, esp related to ext draining
- */
-
-int
-lws_ws_rx_sm(struct lws *wsi, char already_processed, unsigned char c)
-{
- int callback_action = LWS_CALLBACK_RECEIVE;
- int ret = 0;
- unsigned short close_code;
- struct lws_tokens ebuf;
- unsigned char *pp;
- int n = 0;
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- int rx_draining_ext = 0;
- int lin;
-#endif
-
- ebuf.token = NULL;
- ebuf.len = 0;
- if (wsi->socket_is_permanently_unusable)
- return -1;
-
- switch (wsi->lws_rx_parse_state) {
- case LWS_RXPS_NEW:
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- if (wsi->ws->rx_draining_ext) {
- ebuf.token = NULL;
- ebuf.len = 0;
- lws_remove_wsi_from_draining_ext_list(wsi);
- rx_draining_ext = 1;
- lwsl_debug("%s: doing draining flow\n", __func__);
-
- goto drain_extension;
- }
-#endif
- switch (wsi->ws->ietf_spec_revision) {
- case 13:
- /*
- * no prepended frame key any more
- */
- wsi->ws->all_zero_nonce = 1;
- goto handle_first;
-
- default:
- lwsl_warn("lws_ws_rx_sm: unknown spec version %d\n",
- wsi->ws->ietf_spec_revision);
- break;
- }
- break;
- case LWS_RXPS_04_mask_1:
- wsi->ws->mask[1] = c;
- if (c)
- wsi->ws->all_zero_nonce = 0;
- wsi->lws_rx_parse_state = LWS_RXPS_04_mask_2;
- break;
- case LWS_RXPS_04_mask_2:
- wsi->ws->mask[2] = c;
- if (c)
- wsi->ws->all_zero_nonce = 0;
- wsi->lws_rx_parse_state = LWS_RXPS_04_mask_3;
- break;
- case LWS_RXPS_04_mask_3:
- wsi->ws->mask[3] = c;
- if (c)
- wsi->ws->all_zero_nonce = 0;
-
- /*
- * start from the zero'th byte in the XOR key buffer since
- * this is the start of a frame with a new key
- */
-
- wsi->ws->mask_idx = 0;
-
- wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_1;
- break;
-
- /*
- * 04 logical framing from the spec (all this is masked when incoming
- * and has to be unmasked)
- *
- * We ignore the possibility of extension data because we don't
- * negotiate any extensions at the moment.
- *
- * 0 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-------+-+-------------+-------------------------------+
- * |F|R|R|R| opcode|R| Payload len | Extended payload length |
- * |I|S|S|S| (4) |S| (7) | (16/63) |
- * |N|V|V|V| |V| | (if payload len==126/127) |
- * | |1|2|3| |4| | |
- * +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
- * | Extended payload length continued, if payload len == 127 |
- * + - - - - - - - - - - - - - - - +-------------------------------+
- * | | Extension data |
- * +-------------------------------+ - - - - - - - - - - - - - - - +
- * : :
- * +---------------------------------------------------------------+
- * : Application data :
- * +---------------------------------------------------------------+
- *
- * We pass payload through to userland as soon as we get it, ignoring
- * FIN. It's up to userland to buffer it up if it wants to see a
- * whole unfragmented block of the original size (which may be up to
- * 2^63 long!)
- */
-
- case LWS_RXPS_04_FRAME_HDR_1:
-handle_first:
-
- wsi->ws->opcode = c & 0xf;
- wsi->ws->rsv = c & 0x70;
- wsi->ws->final = !!((c >> 7) & 1);
- wsi->ws->defeat_check_utf8 = 0;
-
- if (((wsi->ws->opcode) & 8) && !wsi->ws->final) {
- lws_close_reason(wsi, LWS_CLOSE_STATUS_PROTOCOL_ERR,
- (uint8_t *)"frag ctl", 8);
- return -1;
- }
-
- switch (wsi->ws->opcode) {
- case LWSWSOPC_TEXT_FRAME:
- wsi->ws->check_utf8 = lws_check_opt(
- wsi->context->options,
- LWS_SERVER_OPTION_VALIDATE_UTF8);
- /* fallthru */
- case LWSWSOPC_BINARY_FRAME:
- if (wsi->ws->opcode == LWSWSOPC_BINARY_FRAME)
- wsi->ws->check_utf8 = 0;
- if (wsi->ws->continuation_possible) {
- lws_close_reason(wsi, LWS_CLOSE_STATUS_PROTOCOL_ERR, (uint8_t *)"bad cont", 8);
- return -1;
- }
- wsi->ws->rsv_first_msg = (c & 0x70);
- wsi->ws->frame_is_binary =
- wsi->ws->opcode == LWSWSOPC_BINARY_FRAME;
- wsi->ws->first_fragment = 1;
- wsi->ws->continuation_possible = !wsi->ws->final;
- break;
- case LWSWSOPC_CONTINUATION:
- if (!wsi->ws->continuation_possible) {
- lws_close_reason(wsi, LWS_CLOSE_STATUS_PROTOCOL_ERR, (uint8_t *)"bad cont", 8);
- return -1;
- }
- break;
- case LWSWSOPC_CLOSE:
- wsi->ws->check_utf8 = 0;
- wsi->ws->utf8 = 0;
- break;
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
- case 0xb:
- case 0xc:
- case 0xd:
- case 0xe:
- case 0xf:
- lws_close_reason(wsi, LWS_CLOSE_STATUS_PROTOCOL_ERR, (uint8_t *)"bad opc", 7);
- lwsl_info("illegal opcode\n");
- return -1;
- }
-
- if (wsi->ws->owed_a_fin &&
- (wsi->ws->opcode == LWSWSOPC_TEXT_FRAME ||
- wsi->ws->opcode == LWSWSOPC_BINARY_FRAME)) {
- lwsl_info("hey you owed us a FIN\n");
- lws_close_reason(wsi, LWS_CLOSE_STATUS_PROTOCOL_ERR, (uint8_t *)"bad fin", 7);
- return -1;
- }
- if ((!(wsi->ws->opcode & 8)) && wsi->ws->final) {
- wsi->ws->continuation_possible = 0;
- wsi->ws->owed_a_fin = 0;
- }
-
- if (!wsi->ws->final)
- wsi->ws->owed_a_fin = 1;
-
- wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN;
- if (wsi->ws->rsv &&
- (
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- !wsi->ws->count_act_ext ||
-#endif
- (wsi->ws->rsv & ~0x40))) {
- lws_close_reason(wsi, LWS_CLOSE_STATUS_PROTOCOL_ERR,
- (uint8_t *)"rsv bits", 8);
- return -1;
- }
- break;
-
- case LWS_RXPS_04_FRAME_HDR_LEN:
-
- wsi->ws->this_frame_masked = !!(c & 0x80);
-
- switch (c & 0x7f) {
- case 126:
- /* control frames are not allowed to have big lengths */
- if (wsi->ws->opcode & 8)
- goto illegal_ctl_length;
-
- wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_2;
- break;
- case 127:
- /* control frames are not allowed to have big lengths */
- if (wsi->ws->opcode & 8)
- goto illegal_ctl_length;
-
- wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_8;
- break;
- default:
- wsi->ws->rx_packet_length = c & 0x7f;
-
-
- if (wsi->ws->this_frame_masked)
- wsi->lws_rx_parse_state =
- LWS_RXPS_07_COLLECT_FRAME_KEY_1;
- else
- if (wsi->ws->rx_packet_length) {
- wsi->lws_rx_parse_state =
- LWS_RXPS_WS_FRAME_PAYLOAD;
- } else {
- wsi->lws_rx_parse_state = LWS_RXPS_NEW;
- goto spill;
- }
- break;
- }
- break;
-
- case LWS_RXPS_04_FRAME_HDR_LEN16_2:
- wsi->ws->rx_packet_length = c << 8;
- wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_1;
- break;
-
- case LWS_RXPS_04_FRAME_HDR_LEN16_1:
- wsi->ws->rx_packet_length |= c;
- if (wsi->ws->this_frame_masked)
- wsi->lws_rx_parse_state =
- LWS_RXPS_07_COLLECT_FRAME_KEY_1;
- else {
- wsi->lws_rx_parse_state =
- LWS_RXPS_WS_FRAME_PAYLOAD;
- }
- break;
-
- case LWS_RXPS_04_FRAME_HDR_LEN64_8:
- if (c & 0x80) {
- lwsl_warn("b63 of length must be zero\n");
- /* kill the connection */
- return -1;
- }
-#if defined __LP64__
- wsi->ws->rx_packet_length = ((size_t)c) << 56;
-#else
- wsi->ws->rx_packet_length = 0;
-#endif
- wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_7;
- break;
-
- case LWS_RXPS_04_FRAME_HDR_LEN64_7:
-#if defined __LP64__
- wsi->ws->rx_packet_length |= ((size_t)c) << 48;
-#endif
- wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_6;
- break;
-
- case LWS_RXPS_04_FRAME_HDR_LEN64_6:
-#if defined __LP64__
- wsi->ws->rx_packet_length |= ((size_t)c) << 40;
-#endif
- wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_5;
- break;
-
- case LWS_RXPS_04_FRAME_HDR_LEN64_5:
-#if defined __LP64__
- wsi->ws->rx_packet_length |= ((size_t)c) << 32;
-#endif
- wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_4;
- break;
-
- case LWS_RXPS_04_FRAME_HDR_LEN64_4:
- wsi->ws->rx_packet_length |= ((size_t)c) << 24;
- wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_3;
- break;
-
- case LWS_RXPS_04_FRAME_HDR_LEN64_3:
- wsi->ws->rx_packet_length |= ((size_t)c) << 16;
- wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_2;
- break;
-
- case LWS_RXPS_04_FRAME_HDR_LEN64_2:
- wsi->ws->rx_packet_length |= ((size_t)c) << 8;
- wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_1;
- break;
-
- case LWS_RXPS_04_FRAME_HDR_LEN64_1:
- wsi->ws->rx_packet_length |= ((size_t)c);
- if (wsi->ws->this_frame_masked)
- wsi->lws_rx_parse_state =
- LWS_RXPS_07_COLLECT_FRAME_KEY_1;
- else
- wsi->lws_rx_parse_state = LWS_RXPS_WS_FRAME_PAYLOAD;
- break;
-
- case LWS_RXPS_07_COLLECT_FRAME_KEY_1:
- wsi->ws->mask[0] = c;
- if (c)
- wsi->ws->all_zero_nonce = 0;
- wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_2;
- break;
-
- case LWS_RXPS_07_COLLECT_FRAME_KEY_2:
- wsi->ws->mask[1] = c;
- if (c)
- wsi->ws->all_zero_nonce = 0;
- wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_3;
- break;
-
- case LWS_RXPS_07_COLLECT_FRAME_KEY_3:
- wsi->ws->mask[2] = c;
- if (c)
- wsi->ws->all_zero_nonce = 0;
- wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_4;
- break;
-
- case LWS_RXPS_07_COLLECT_FRAME_KEY_4:
- wsi->ws->mask[3] = c;
- if (c)
- wsi->ws->all_zero_nonce = 0;
- wsi->lws_rx_parse_state = LWS_RXPS_WS_FRAME_PAYLOAD;
- wsi->ws->mask_idx = 0;
- if (wsi->ws->rx_packet_length == 0) {
- wsi->lws_rx_parse_state = LWS_RXPS_NEW;
- goto spill;
- }
- break;
-
-
- case LWS_RXPS_WS_FRAME_PAYLOAD:
- assert(wsi->ws->rx_ubuf);
-
- if (wsi->ws->rx_ubuf_head + LWS_PRE >= wsi->ws->rx_ubuf_alloc) {
- lwsl_err("Attempted overflow \n");
- return -1;
- }
- if (!(already_processed & ALREADY_PROCESSED_IGNORE_CHAR)) {
- if (wsi->ws->all_zero_nonce)
- wsi->ws->rx_ubuf[LWS_PRE + (wsi->ws->rx_ubuf_head++)] =
- c;
- else
- wsi->ws->rx_ubuf[LWS_PRE + (wsi->ws->rx_ubuf_head++)] =
- c ^ wsi->ws->mask[(wsi->ws->mask_idx++) & 3];
-
- --wsi->ws->rx_packet_length;
- }
-
- if (!wsi->ws->rx_packet_length) {
- lwsl_debug("%s: ws fragment length exhausted\n", __func__);
- /* spill because we have the whole frame */
- wsi->lws_rx_parse_state = LWS_RXPS_NEW;
- goto spill;
- }
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- if (wsi->ws->rx_draining_ext) {
- lwsl_debug("%s: UNTIL_EXHAUSTED draining\n", __func__);
- goto drain_extension;
- }
-#endif
- /*
- * if there's no protocol max frame size given, we are
- * supposed to default to context->pt_serv_buf_size
- */
- if (!wsi->protocol->rx_buffer_size &&
- wsi->ws->rx_ubuf_head != wsi->context->pt_serv_buf_size)
- break;
-
- if (wsi->protocol->rx_buffer_size &&
- wsi->ws->rx_ubuf_head != wsi->protocol->rx_buffer_size)
- break;
-
- /* spill because we filled our rx buffer */
-spill:
- /*
- * is this frame a control packet we should take care of at this
- * layer? If so service it and hide it from the user callback
- */
-
- lwsl_parser("spill on %s\n", wsi->protocol->name);
-
- switch (wsi->ws->opcode) {
- case LWSWSOPC_CLOSE:
-
- if (wsi->ws->peer_has_sent_close)
- break;
-
- wsi->ws->peer_has_sent_close = 1;
-
- pp = (unsigned char *)&wsi->ws->rx_ubuf[LWS_PRE];
- if (lws_check_opt(wsi->context->options,
- LWS_SERVER_OPTION_VALIDATE_UTF8) &&
- wsi->ws->rx_ubuf_head > 2 &&
- lws_check_utf8(&wsi->ws->utf8, pp + 2,
- wsi->ws->rx_ubuf_head - 2))
- goto utf8_fail;
-
- /* is this an acknowledgment of our close? */
- if (lwsi_state(wsi) == LRS_AWAITING_CLOSE_ACK) {
- /*
- * fine he has told us he is closing too, let's
- * finish our close
- */
- lwsl_parser("seen client close ack\n");
- return -1;
- }
- if (lwsi_state(wsi) == LRS_RETURNED_CLOSE)
- /* if he sends us 2 CLOSE, kill him */
- return -1;
-
- if (lws_partial_buffered(wsi)) {
- /*
- * if we're in the middle of something,
- * we can't do a normal close response and
- * have to just close our end.
- */
- wsi->socket_is_permanently_unusable = 1;
- lwsl_parser("Closing on peer close due to Pending tx\n");
- return -1;
- }
-
- if (wsi->ws->rx_ubuf_head >= 2) {
- close_code = (pp[0] << 8) | pp[1];
- if (close_code < 1000 ||
- close_code == 1004 ||
- close_code == 1005 ||
- close_code == 1006 ||
- close_code == 1012 ||
- close_code == 1013 ||
- close_code == 1014 ||
- close_code == 1015 ||
- (close_code >= 1016 && close_code < 3000)
- ) {
- pp[0] = (LWS_CLOSE_STATUS_PROTOCOL_ERR >> 8) & 0xff;
- pp[1] = LWS_CLOSE_STATUS_PROTOCOL_ERR & 0xff;
- }
- }
-
- if (user_callback_handle_rxflow(
- wsi->protocol->callback, wsi,
- LWS_CALLBACK_WS_PEER_INITIATED_CLOSE,
- wsi->user_space,
- &wsi->ws->rx_ubuf[LWS_PRE],
- wsi->ws->rx_ubuf_head))
- return -1;
-
- lwsl_parser("server sees client close packet\n");
- lwsi_set_state(wsi, LRS_RETURNED_CLOSE);
- /* deal with the close packet contents as a PONG */
- wsi->ws->payload_is_close = 1;
- goto process_as_ping;
-
- case LWSWSOPC_PING:
- lwsl_info("received %d byte ping, sending pong\n",
- wsi->ws->rx_ubuf_head);
-
- if (wsi->ws->ping_pending_flag) {
- /*
- * there is already a pending ping payload
- * we should just log and drop
- */
- lwsl_parser("DROP PING since one pending\n");
- goto ping_drop;
- }
-process_as_ping:
- /* control packets can only be < 128 bytes long */
- if (wsi->ws->rx_ubuf_head > 128 - 3) {
- lwsl_parser("DROP PING payload too large\n");
- goto ping_drop;
- }
-
- /* stash the pong payload */
- memcpy(wsi->ws->ping_payload_buf + LWS_PRE,
- &wsi->ws->rx_ubuf[LWS_PRE],
- wsi->ws->rx_ubuf_head);
-
- wsi->ws->ping_payload_len = wsi->ws->rx_ubuf_head;
- wsi->ws->ping_pending_flag = 1;
-
- /* get it sent as soon as possible */
- lws_callback_on_writable(wsi);
-ping_drop:
- wsi->ws->rx_ubuf_head = 0;
- return 0;
-
- case LWSWSOPC_PONG:
- lwsl_info("received pong\n");
- lwsl_hexdump(&wsi->ws->rx_ubuf[LWS_PRE],
- wsi->ws->rx_ubuf_head);
-
- if (wsi->pending_timeout ==
- PENDING_TIMEOUT_WS_PONG_CHECK_GET_PONG) {
- lwsl_info("received expected PONG on wsi %p\n",
- wsi);
- lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
- }
-
- /* issue it */
- callback_action = LWS_CALLBACK_RECEIVE_PONG;
- break;
-
- case LWSWSOPC_TEXT_FRAME:
- case LWSWSOPC_BINARY_FRAME:
- case LWSWSOPC_CONTINUATION:
- break;
-
- default:
- lwsl_parser("unknown opc %x\n", wsi->ws->opcode);
-
- return -1;
- }
-
- /*
- * No it's real payload, pass it up to the user callback.
- * It's nicely buffered with the pre-padding taken care of
- * so it can be sent straight out again using lws_write
- */
-
- ebuf.token = &wsi->ws->rx_ubuf[LWS_PRE];
- ebuf.len = wsi->ws->rx_ubuf_head;
-
- if (wsi->ws->opcode == LWSWSOPC_PONG && !ebuf.len)
- goto already_done;
-#if !defined(LWS_WITHOUT_EXTENSIONS)
-drain_extension:
-#endif
- // lwsl_notice("%s: passing %d to ext\n", __func__, ebuf.len);
-
- if (lwsi_state(wsi) == LRS_RETURNED_CLOSE ||
- lwsi_state(wsi) == LRS_AWAITING_CLOSE_ACK)
- goto already_done;
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- lin = ebuf.len;
- //if (lin)
- // lwsl_hexdump_notice(ebuf.token, ebuf.len);
- n = lws_ext_cb_active(wsi, LWS_EXT_CB_PAYLOAD_RX, &ebuf, 0);
- lwsl_debug("%s: ext says %d / ebuf.len %d\n", __func__, n, ebuf.len);
- if (wsi->ws->rx_draining_ext)
- already_processed &= ~ALREADY_PROCESSED_NO_CB;
-#endif
- /*
- * ebuf may be pointing somewhere completely different now,
- * it's the output
- */
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- if (n < 0) {
- /*
- * we may rely on this to get RX, just drop connection
- */
- wsi->socket_is_permanently_unusable = 1;
- return -1;
- }
-#endif
- if (
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- rx_draining_ext &&
-#endif
- ebuf.len == 0)
- goto already_done;
-
- if (
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- n &&
-#endif
- ebuf.len)
- /* extension had more... main loop will come back */
- lws_add_wsi_to_draining_ext_list(wsi);
- else
- lws_remove_wsi_from_draining_ext_list(wsi);
-
- if (wsi->ws->check_utf8 && !wsi->ws->defeat_check_utf8) {
- if (lws_check_utf8(&wsi->ws->utf8,
- (unsigned char *)ebuf.token,
- ebuf.len)) {
- lws_close_reason(wsi,
- LWS_CLOSE_STATUS_INVALID_PAYLOAD,
- (uint8_t *)"bad utf8", 8);
- goto utf8_fail;
- }
-
- /* we are ending partway through utf-8 character? */
- if (!wsi->ws->rx_packet_length && wsi->ws->final &&
- wsi->ws->utf8 && !n) {
- lwsl_info("FINAL utf8 error\n");
- lws_close_reason(wsi,
- LWS_CLOSE_STATUS_INVALID_PAYLOAD,
- (uint8_t *)"partial utf8", 12);
-utf8_fail:
- lwsl_notice("utf8 error\n");
- lwsl_hexdump_notice(ebuf.token, ebuf.len);
-
- return -1;
- }
- }
-
- if (!wsi->wsistate_pre_close && (ebuf.len >= 0 ||
- callback_action == LWS_CALLBACK_RECEIVE_PONG)) {
- if (ebuf.len)
- ebuf.token[ebuf.len] = '\0';
-
- if (wsi->protocol->callback &&
- !(already_processed & ALREADY_PROCESSED_NO_CB)) {
- if (callback_action == LWS_CALLBACK_RECEIVE_PONG)
- lwsl_info("Doing pong callback\n");
-
- ret = user_callback_handle_rxflow(
- wsi->protocol->callback,
- wsi, (enum lws_callback_reasons)
- callback_action,
- wsi->user_space,
- ebuf.token,
- ebuf.len);
- }
- wsi->ws->first_fragment = 0;
- }
-
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- if (!lin)
- break;
-#endif
-
-already_done:
- wsi->ws->rx_ubuf_head = 0;
- break;
- }
-
- return ret;
-
-illegal_ctl_length:
-
- lwsl_warn("Control frame with xtended length is illegal\n");
- /* kill the connection */
- return -1;
-}
-
-
-LWS_VISIBLE size_t
-lws_remaining_packet_payload(struct lws *wsi)
-{
- return wsi->ws->rx_packet_length;
-}
-
-LWS_VISIBLE int lws_frame_is_binary(struct lws *wsi)
-{
- return wsi->ws->frame_is_binary;
-}
-
-void
-lws_add_wsi_to_draining_ext_list(struct lws *wsi)
-{
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
-
- if (wsi->ws->rx_draining_ext)
- return;
-
- lwsl_debug("%s: RX EXT DRAINING: Adding to list\n", __func__);
-
- wsi->ws->rx_draining_ext = 1;
- wsi->ws->rx_draining_ext_list = pt->ws.rx_draining_ext_list;
- pt->ws.rx_draining_ext_list = wsi;
-#endif
-}
-
-void
-lws_remove_wsi_from_draining_ext_list(struct lws *wsi)
-{
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
- struct lws **w = &pt->ws.rx_draining_ext_list;
-
- if (!wsi->ws->rx_draining_ext)
- return;
-
- lwsl_debug("%s: RX EXT DRAINING: Removing from list\n", __func__);
-
- wsi->ws->rx_draining_ext = 0;
-
- /* remove us from context draining ext list */
- while (*w) {
- if (*w == wsi) {
- /* if us, point it instead to who we were pointing to */
- *w = wsi->ws->rx_draining_ext_list;
- break;
- }
- w = &((*w)->ws->rx_draining_ext_list);
- }
- wsi->ws->rx_draining_ext_list = NULL;
-#endif
-}
-
-LWS_EXTERN void
-lws_restart_ws_ping_pong_timer(struct lws *wsi)
-{
- if (!wsi->context->ws_ping_pong_interval ||
- !lwsi_role_ws(wsi))
- return;
-
- wsi->ws->time_next_ping_check = (time_t)lws_now_secs();
-}
-
-static int
-lws_0405_frame_mask_generate(struct lws *wsi)
-{
- int n;
- /* fetch the per-frame nonce */
-
- n = lws_get_random(lws_get_context(wsi), wsi->ws->mask, 4);
- if (n != 4) {
- lwsl_parser("Unable to read from random device %s %d\n",
- SYSTEM_RANDOM_FILEPATH, n);
- return 1;
- }
-
- /* start masking from first byte of masking key buffer */
- wsi->ws->mask_idx = 0;
-
- return 0;
-}
-
-int
-lws_server_init_wsi_for_ws(struct lws *wsi)
-{
- int n;
-
- lwsi_set_state(wsi, LRS_ESTABLISHED);
- lws_restart_ws_ping_pong_timer(wsi);
-
- /*
- * create the frame buffer for this connection according to the
- * size mentioned in the protocol definition. If 0 there, use
- * a big default for compatibility
- */
-
- n = (int)wsi->protocol->rx_buffer_size;
- if (!n)
- n = wsi->context->pt_serv_buf_size;
- n += LWS_PRE;
- wsi->ws->rx_ubuf = lws_malloc(n + 4 /* 0x0000ffff zlib */, "rx_ubuf");
- if (!wsi->ws->rx_ubuf) {
- lwsl_err("Out of Mem allocating rx buffer %d\n", n);
- return 1;
- }
- wsi->ws->rx_ubuf_alloc = n;
- lwsl_debug("Allocating RX buffer %d\n", n);
-
-#if !defined(LWS_WITH_ESP32)
- if (!wsi->parent_carries_io &&
- !wsi->h2_stream_carries_ws)
- if (setsockopt(wsi->desc.sockfd, SOL_SOCKET, SO_SNDBUF,
- (const char *)&n, sizeof n)) {
- lwsl_warn("Failed to set SNDBUF to %d", n);
- return 1;
- }
-#endif
-
- /* notify user code that we're ready to roll */
-
- if (wsi->protocol->callback)
- if (wsi->protocol->callback(wsi, LWS_CALLBACK_ESTABLISHED,
- wsi->user_space,
-#ifdef LWS_WITH_TLS
- wsi->tls.ssl,
-#else
- NULL,
-#endif
- wsi->h2_stream_carries_ws))
- return 1;
-
- lwsl_debug("ws established\n");
-
- return 0;
-}
-
-
-
-LWS_VISIBLE int
-lws_is_final_fragment(struct lws *wsi)
-{
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- lwsl_debug("%s: final %d, rx pk length %ld, draining %ld\n", __func__,
- wsi->ws->final, (long)wsi->ws->rx_packet_length,
- (long)wsi->ws->rx_draining_ext);
- return wsi->ws->final && !wsi->ws->rx_packet_length &&
- !wsi->ws->rx_draining_ext;
-#else
- return wsi->ws->final && !wsi->ws->rx_packet_length;
-#endif
-}
-
-LWS_VISIBLE int
-lws_is_first_fragment(struct lws *wsi)
-{
- return wsi->ws->first_fragment;
-}
-
-LWS_VISIBLE unsigned char
-lws_get_reserved_bits(struct lws *wsi)
-{
- return wsi->ws->rsv;
-}
-
-LWS_VISIBLE LWS_EXTERN int
-lws_get_close_length(struct lws *wsi)
-{
- return wsi->ws->close_in_ping_buffer_len;
-}
-
-LWS_VISIBLE LWS_EXTERN unsigned char *
-lws_get_close_payload(struct lws *wsi)
-{
- return &wsi->ws->ping_payload_buf[LWS_PRE];
-}
-
-LWS_VISIBLE LWS_EXTERN void
-lws_close_reason(struct lws *wsi, enum lws_close_status status,
- unsigned char *buf, size_t len)
-{
- unsigned char *p, *start;
- int budget = sizeof(wsi->ws->ping_payload_buf) - LWS_PRE;
-
- assert(lwsi_role_ws(wsi));
-
- start = p = &wsi->ws->ping_payload_buf[LWS_PRE];
-
- *p++ = (((int)status) >> 8) & 0xff;
- *p++ = ((int)status) & 0xff;
-
- if (buf)
- while (len-- && p < start + budget)
- *p++ = *buf++;
-
- wsi->ws->close_in_ping_buffer_len = lws_ptr_diff(p, start);
-}
-
-static int
-lws_is_ws_with_ext(struct lws *wsi)
-{
-#if defined(LWS_WITHOUT_EXTENSIONS)
- return 0;
-#else
- return lwsi_role_ws(wsi) && !!wsi->ws->count_act_ext;
-#endif
-}
-
-static int
-rops_handle_POLLIN_ws(struct lws_context_per_thread *pt, struct lws *wsi,
- struct lws_pollfd *pollfd)
-{
- struct lws_tokens ebuf;
- unsigned int pending = 0;
- char buffered = 0;
- int n = 0, m;
-#if defined(LWS_WITH_HTTP2)
- struct lws *wsi1;
-#endif
-
- if (!wsi->ws) {
- lwsl_err("ws role wsi with no ws\n");
- return 1;
- }
-
- // lwsl_notice("%s: %s\n", __func__, wsi->protocol->name);
-
- //lwsl_info("%s: wsistate 0x%x, pollout %d\n", __func__,
- // wsi->wsistate, pollfd->revents & LWS_POLLOUT);
-
- /*
- * something went wrong with parsing the handshake, and
- * we ended up back in the event loop without completing it
- */
- if (lwsi_state(wsi) == LRS_PRE_WS_SERVING_ACCEPT) {
- wsi->socket_is_permanently_unusable = 1;
- return LWS_HPI_RET_PLEASE_CLOSE_ME;
- }
-
- ebuf.token = NULL;
- ebuf.len = 0;
-
- if (lwsi_state(wsi) == LRS_WAITING_CONNECT) {
-#if !defined(LWS_NO_CLIENT)
- if ((pollfd->revents & LWS_POLLOUT) &&
- lws_handle_POLLOUT_event(wsi, pollfd)) {
- lwsl_debug("POLLOUT event closed it\n");
- return LWS_HPI_RET_PLEASE_CLOSE_ME;
- }
-
- n = lws_client_socket_service(wsi, pollfd, NULL);
- if (n)
- return LWS_HPI_RET_WSI_ALREADY_DIED;
-#endif
- return LWS_HPI_RET_HANDLED;
- }
-
- //lwsl_notice("%s: wsi->ws->tx_draining_ext %d revents 0x%x 0x%x %d\n", __func__, wsi->ws->tx_draining_ext, pollfd->revents, wsi->wsistate, lwsi_state_can_handle_POLLOUT(wsi));
-
- /* 1: something requested a callback when it was OK to write */
-
- if ((pollfd->revents & LWS_POLLOUT) &&
- lwsi_state_can_handle_POLLOUT(wsi) &&
- lws_handle_POLLOUT_event(wsi, pollfd)) {
- if (lwsi_state(wsi) == LRS_RETURNED_CLOSE)
- lwsi_set_state(wsi, LRS_FLUSHING_BEFORE_CLOSE);
-
- return LWS_HPI_RET_PLEASE_CLOSE_ME;
- }
-
- if (lwsi_state(wsi) == LRS_RETURNED_CLOSE ||
- lwsi_state(wsi) == LRS_WAITING_TO_SEND_CLOSE) {
- /*
- * we stopped caring about anything except control
- * packets. Force flow control off, defeat tx
- * draining.
- */
- lws_rx_flow_control(wsi, 1);
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- if (wsi->ws)
- wsi->ws->tx_draining_ext = 0;
-#endif
- }
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- if (wsi->ws->tx_draining_ext)
- /*
- * We cannot deal with new RX until the TX ext path has
- * been drained. It's because new rx will, eg, crap on
- * the wsi rx buf that may be needed to retain state.
- *
- * TX ext drain path MUST go through event loop to avoid
- * blocking.
- */
- return LWS_HPI_RET_HANDLED;
-#endif
- if (lws_is_flowcontrolled(wsi)) {
- /* We cannot deal with any kind of new RX because we are
- * RX-flowcontrolled.
- */
- lwsl_info("flowcontrolled\n");
- return LWS_HPI_RET_HANDLED;
- }
-
-#if defined(LWS_WITH_HTTP2)
- if (wsi->http2_substream || wsi->upgraded_to_http2) {
- wsi1 = lws_get_network_wsi(wsi);
- if (wsi1 && wsi1->trunc_len)
- /* We cannot deal with any kind of new RX
- * because we are dealing with a partial send
- * (new RX may trigger new http_action() that
- * expect to be able to send)
- */
- return LWS_HPI_RET_HANDLED;
- }
-#endif
-
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- /* 2: RX Extension needs to be drained
- */
-
- if (wsi->ws->rx_draining_ext) {
-
- lwsl_debug("%s: RX EXT DRAINING: Service\n", __func__);
-#ifndef LWS_NO_CLIENT
- if (lwsi_role_client(wsi)) {
- n = lws_ws_client_rx_sm(wsi, 0);
- if (n < 0)
- /* we closed wsi */
- return LWS_HPI_RET_PLEASE_CLOSE_ME;
- } else
-#endif
- n = lws_ws_rx_sm(wsi, ALREADY_PROCESSED_IGNORE_CHAR, 0);
-
- return LWS_HPI_RET_HANDLED;
- }
-
- if (wsi->ws->rx_draining_ext)
- /*
- * We have RX EXT content to drain, but can't do it
- * right now. That means we cannot do anything lower
- * priority either.
- */
- return LWS_HPI_RET_HANDLED;
-#endif
-
- /* 3: buflist needs to be drained
- */
-read:
- //lws_buflist_describe(&wsi->buflist, wsi);
- ebuf.len = (int)lws_buflist_next_segment_len(&wsi->buflist,
- (uint8_t **)&ebuf.token);
- if (ebuf.len) {
- lwsl_info("draining buflist (len %d)\n", ebuf.len);
- buffered = 1;
- goto drain;
- }
-
- if (!(pollfd->revents & pollfd->events & LWS_POLLIN) && !wsi->http.ah)
- return LWS_HPI_RET_HANDLED;
-
- if (lws_is_flowcontrolled(wsi)) {
- lwsl_info("%s: %p should be rxflow (bm 0x%x)..\n",
- __func__, wsi, wsi->rxflow_bitmap);
- return LWS_HPI_RET_HANDLED;
- }
-
- if (!(lwsi_role_client(wsi) &&
- (lwsi_state(wsi) != LRS_ESTABLISHED &&
- lwsi_state(wsi) != LRS_AWAITING_CLOSE_ACK &&
- lwsi_state(wsi) != LRS_H2_WAITING_TO_SEND_HEADERS))) {
- /*
- * In case we are going to react to this rx by scheduling
- * writes, we need to restrict the amount of rx to the size
- * the protocol reported for rx buffer.
- *
- * Otherwise we get a situation we have to absorb possibly a
- * lot of reads before we get a chance to drain them by writing
- * them, eg, with echo type tests in autobahn.
- */
-
- buffered = 0;
- ebuf.token = (char *)pt->serv_buf;
- if (lwsi_role_ws(wsi))
- ebuf.len = wsi->ws->rx_ubuf_alloc;
- else
- ebuf.len = wsi->context->pt_serv_buf_size;
-
- if ((unsigned int)ebuf.len > wsi->context->pt_serv_buf_size)
- ebuf.len = wsi->context->pt_serv_buf_size;
-
- if ((int)pending > ebuf.len)
- pending = ebuf.len;
-
- ebuf.len = lws_ssl_capable_read(wsi, (uint8_t *)ebuf.token,
- pending ? (int)pending :
- ebuf.len);
- switch (ebuf.len) {
- case 0:
- lwsl_info("%s: zero length read\n",
- __func__);
- return LWS_HPI_RET_PLEASE_CLOSE_ME;
- case LWS_SSL_CAPABLE_MORE_SERVICE:
- lwsl_info("SSL Capable more service\n");
- return LWS_HPI_RET_HANDLED;
- case LWS_SSL_CAPABLE_ERROR:
- lwsl_info("%s: LWS_SSL_CAPABLE_ERROR\n",
- __func__);
- return LWS_HPI_RET_PLEASE_CLOSE_ME;
- }
- // lwsl_notice("Actual RX %d\n", ebuf.len);
-
- lws_restart_ws_ping_pong_timer(wsi);
-
- /*
- * coverity thinks ssl_capable_read() may read over
- * 2GB. Dissuade it...
- */
- ebuf.len &= 0x7fffffff;
- }
-
-drain:
-
- /*
- * give any active extensions a chance to munge the buffer
- * before parse. We pass in a pointer to an lws_tokens struct
- * prepared with the default buffer and content length that's in
- * there. Rather than rewrite the default buffer, extensions
- * that expect to grow the buffer can adapt .token to
- * point to their own per-connection buffer in the extension
- * user allocation. By default with no extensions or no
- * extension callback handling, just the normal input buffer is
- * used then so it is efficient.
- */
- m = 0;
- do {
-
- /* service incoming data */
- //lws_buflist_describe(&wsi->buflist, wsi);
- if (ebuf.len) {
-#if defined(LWS_ROLE_H2)
- if (lwsi_role_h2(wsi) && lwsi_state(wsi) != LRS_BODY)
- n = lws_read_h2(wsi, (unsigned char *)ebuf.token,
- ebuf.len);
- else
-#endif
- n = lws_read_h1(wsi, (unsigned char *)ebuf.token,
- ebuf.len);
-
- if (n < 0) {
- /* we closed wsi */
- n = 0;
- return LWS_HPI_RET_WSI_ALREADY_DIED;
- }
- //lws_buflist_describe(&wsi->buflist, wsi);
- //lwsl_notice("%s: consuming %d / %d\n", __func__, n, ebuf.len);
- if (lws_buflist_aware_consume(wsi, &ebuf, n, buffered))
- return LWS_HPI_RET_PLEASE_CLOSE_ME;
- }
-
- ebuf.token = NULL;
- ebuf.len = 0;
- } while (m);
-
- if (wsi->http.ah
-#if !defined(LWS_NO_CLIENT)
- && !wsi->client_h2_alpn
-#endif
- ) {
- lwsl_info("%s: %p: detaching ah\n", __func__, wsi);
- lws_header_table_detach(wsi, 0);
- }
-
- pending = lws_ssl_pending(wsi);
- if (pending) {
- if (lws_is_ws_with_ext(wsi))
- pending = pending > wsi->ws->rx_ubuf_alloc ?
- wsi->ws->rx_ubuf_alloc : pending;
- else
- pending = pending > wsi->context->pt_serv_buf_size ?
- wsi->context->pt_serv_buf_size : pending;
- goto read;
- }
-
- if (buffered && /* were draining, now nothing left */
- !lws_buflist_next_segment_len(&wsi->buflist, NULL)) {
- lwsl_info("%s: %p flow buf: drained\n", __func__, wsi);
- /* having drained the rxflow buffer, can rearm POLLIN */
-#ifdef LWS_NO_SERVER
- n =
-#endif
- __lws_rx_flow_control(wsi);
- /* n ignored, needed for NO_SERVER case */
- }
-
- /* n = 0 */
- return LWS_HPI_RET_HANDLED;
-}
-
-
-int rops_handle_POLLOUT_ws(struct lws *wsi)
-{
- int write_type = LWS_WRITE_PONG;
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- struct lws_tokens ebuf;
- int ret, m;
-#endif
- int n;
-
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- lwsl_debug("%s: %s: wsi->ws->tx_draining_ext %d\n", __func__,
- wsi->protocol->name, wsi->ws->tx_draining_ext);
-#endif
-
- /* Priority 3: pending control packets (pong or close)
- *
- * 3a: close notification packet requested from close api
- */
-
- if (lwsi_state(wsi) == LRS_WAITING_TO_SEND_CLOSE) {
- lwsl_debug("sending close packet\n");
- lwsl_hexdump_debug(&wsi->ws->ping_payload_buf[LWS_PRE],
- wsi->ws->close_in_ping_buffer_len);
- wsi->waiting_to_send_close_frame = 0;
- n = lws_write(wsi, &wsi->ws->ping_payload_buf[LWS_PRE],
- wsi->ws->close_in_ping_buffer_len,
- LWS_WRITE_CLOSE);
- if (n >= 0) {
- if (wsi->close_needs_ack) {
- lwsi_set_state(wsi, LRS_AWAITING_CLOSE_ACK);
- lws_set_timeout(wsi, PENDING_TIMEOUT_CLOSE_ACK, 5);
- lwsl_debug("sent close indication, awaiting ack\n");
-
- return LWS_HP_RET_BAIL_OK;
- }
- wsi->close_needs_ack = 0;
- lwsi_set_state(wsi, LRS_RETURNED_CLOSE);
- }
-
- return LWS_HP_RET_BAIL_DIE;
- }
-
- /* else, the send failed and we should just hang up */
-
- if ((lwsi_role_ws(wsi) && wsi->ws->ping_pending_flag) ||
- (lwsi_state(wsi) == LRS_RETURNED_CLOSE &&
- wsi->ws->payload_is_close)) {
-
- if (wsi->ws->payload_is_close)
- write_type = LWS_WRITE_CLOSE;
- else {
- if (wsi->wsistate_pre_close) {
- /* we started close flow, forget pong */
- wsi->ws->ping_pending_flag = 0;
- return LWS_HP_RET_BAIL_OK;
- }
- lwsl_info("issuing pong %d on wsi %p\n", wsi->ws->ping_payload_len, wsi);
- }
-
- n = lws_write(wsi, &wsi->ws->ping_payload_buf[LWS_PRE],
- wsi->ws->ping_payload_len, write_type);
- if (n < 0)
- return LWS_HP_RET_BAIL_DIE;
-
- /* well he is sent, mark him done */
- wsi->ws->ping_pending_flag = 0;
- if (wsi->ws->payload_is_close) {
- // assert(0);
- /* oh... a close frame was it... then we are done */
- return LWS_HP_RET_BAIL_DIE;
- }
-
- /* otherwise for PING, leave POLLOUT active either way */
- return LWS_HP_RET_BAIL_OK;
- }
-
- if (!wsi->socket_is_permanently_unusable && wsi->ws->send_check_ping) {
-
- lwsl_info("issuing ping on wsi %p\n", wsi);
- wsi->ws->send_check_ping = 0;
- n = lws_write(wsi, &wsi->ws->ping_payload_buf[LWS_PRE],
- 0, LWS_WRITE_PING);
- if (n < 0)
- return LWS_HP_RET_BAIL_DIE;
-
- /*
- * we apparently were able to send the PING in a reasonable time
- * now reset the clock on our peer to be able to send the
- * PONG in a reasonable time.
- */
-
- lws_set_timeout(wsi, PENDING_TIMEOUT_WS_PONG_CHECK_GET_PONG,
- wsi->context->timeout_secs);
-
- return LWS_HP_RET_BAIL_OK;
- }
-
- /* Priority 4: if we are closing, not allowed to send more data frags
- * which means user callback or tx ext flush banned now
- */
- if (lwsi_state(wsi) == LRS_RETURNED_CLOSE)
- return LWS_HP_RET_USER_SERVICE;
-
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- /* Priority 5: Tx path extension with more to send
- *
- * These are handled as new fragments each time around
- * So while we must block new writeable callback to enforce
- * payload ordering, but since they are always complete
- * fragments control packets can interleave OK.
- */
- if (wsi->ws->tx_draining_ext) {
- lwsl_ext("SERVICING TX EXT DRAINING\n");
- if (lws_write(wsi, NULL, 0, LWS_WRITE_CONTINUATION) < 0)
- return LWS_HP_RET_BAIL_DIE;
- /* leave POLLOUT active */
- return LWS_HP_RET_BAIL_OK;
- }
-
- /* Priority 6: extensions
- */
- if (!wsi->ws->extension_data_pending && !wsi->ws->tx_draining_ext) {
- lwsl_ext("%s: !wsi->ws->extension_data_pending\n", __func__);
- return LWS_HP_RET_USER_SERVICE;
- }
-
- /*
- * check in on the active extensions, see if they
- * had pending stuff to spill... they need to get the
- * first look-in otherwise sequence will be disordered
- *
- * NULL, zero-length ebuf means just spill pending
- */
-
- ret = 1;
- if (wsi->role_ops == &role_ops_raw_skt ||
- wsi->role_ops == &role_ops_raw_file)
- ret = 0;
-
- while (ret == 1) {
-
- /* default to nobody has more to spill */
-
- ret = 0;
- ebuf.token = NULL;
- ebuf.len = 0;
-
- /* give every extension a chance to spill */
-
- m = lws_ext_cb_active(wsi, LWS_EXT_CB_PACKET_TX_PRESEND,
- &ebuf, 0);
- if (m < 0) {
- lwsl_err("ext reports fatal error\n");
- return LWS_HP_RET_BAIL_DIE;
- }
- if (m)
- /*
- * at least one extension told us he has more
- * to spill, so we will go around again after
- */
- ret = 1;
-
- /* assuming they gave us something to send, send it */
-
- if (ebuf.len) {
- n = lws_issue_raw(wsi, (unsigned char *)ebuf.token,
- ebuf.len);
- if (n < 0) {
- lwsl_info("closing from POLLOUT spill\n");
- return LWS_HP_RET_BAIL_DIE;
- }
- /*
- * Keep amount spilled small to minimize chance of this
- */
- if (n != ebuf.len) {
- lwsl_err("Unable to spill ext %d vs %d\n",
- ebuf.len, n);
- return LWS_HP_RET_BAIL_DIE;
- }
- } else
- continue;
-
- /* no extension has more to spill */
-
- if (!ret)
- continue;
-
- /*
- * There's more to spill from an extension, but we just sent
- * something... did that leave the pipe choked?
- */
-
- if (!lws_send_pipe_choked(wsi))
- /* no we could add more */
- continue;
-
- lwsl_info("choked in POLLOUT service\n");
-
- /*
- * Yes, he's choked. Leave the POLLOUT masked on so we will
- * come back here when he is unchoked. Don't call the user
- * callback to enforce ordering of spilling, he'll get called
- * when we come back here and there's nothing more to spill.
- */
-
- return LWS_HP_RET_BAIL_OK;
- }
-
- wsi->ws->extension_data_pending = 0;
-#endif
-
- return LWS_HP_RET_USER_SERVICE;
-}
-
-static int
-rops_periodic_checks_ws(struct lws_context *context, int tsi, time_t now)
-{
- struct lws_vhost *vh;
-
- if (!context->ws_ping_pong_interval ||
- context->last_ws_ping_pong_check_s >= now + 10)
- return 0;
-
- vh = context->vhost_list;
- context->last_ws_ping_pong_check_s = now;
-
- while (vh) {
- int n;
-
- lws_vhost_lock(vh);
-
- for (n = 0; n < vh->count_protocols; n++) {
- struct lws *wsi = vh->same_vh_protocol_list[n];
-
- while (wsi) {
- if (lwsi_role_ws(wsi) &&
- !wsi->socket_is_permanently_unusable &&
- !wsi->ws->send_check_ping &&
- wsi->ws->time_next_ping_check &&
- lws_compare_time_t(context, now,
- wsi->ws->time_next_ping_check) >
- context->ws_ping_pong_interval) {
-
- lwsl_info("req pp on wsi %p\n", wsi);
- wsi->ws->send_check_ping = 1;
- lws_set_timeout(wsi,
- PENDING_TIMEOUT_WS_PONG_CHECK_SEND_PING,
- context->timeout_secs);
- lws_callback_on_writable(wsi);
- wsi->ws->time_next_ping_check = now;
- }
- wsi = wsi->same_vh_protocol_next;
- }
- }
-
- lws_vhost_unlock(vh);
- vh = vh->vhost_next;
- }
-
- return 0;
-}
-
-static int
-rops_service_flag_pending_ws(struct lws_context *context, int tsi)
-{
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- struct lws_context_per_thread *pt = &context->pt[tsi];
- struct lws *wsi;
- int forced = 0;
-
- /* POLLIN faking (the pt lock is taken by the parent) */
-
- /*
- * 1) For all guys with already-available ext data to drain, if they are
- * not flowcontrolled, fake their POLLIN status
- */
- wsi = pt->ws.rx_draining_ext_list;
- while (wsi && wsi->position_in_fds_table != LWS_NO_FDS_POS) {
- pt->fds[wsi->position_in_fds_table].revents |=
- pt->fds[wsi->position_in_fds_table].events & LWS_POLLIN;
- if (pt->fds[wsi->position_in_fds_table].revents & LWS_POLLIN)
- forced = 1;
-
- wsi = wsi->ws->rx_draining_ext_list;
- }
-
- return forced;
-#else
- return 0;
-#endif
-}
-
-static int
-rops_close_via_role_protocol_ws(struct lws *wsi, enum lws_close_status reason)
-{
- if (!wsi->ws)
- return 0;
-
- if (!wsi->ws->close_in_ping_buffer_len && /* already a reason */
- (reason == LWS_CLOSE_STATUS_NOSTATUS ||
- reason == LWS_CLOSE_STATUS_NOSTATUS_CONTEXT_DESTROY))
- return 0;
-
- lwsl_debug("%s: sending close indication...\n", __func__);
-
- /* if no prepared close reason, use 1000 and no aux data */
-
- if (!wsi->ws->close_in_ping_buffer_len) {
- wsi->ws->close_in_ping_buffer_len = 2;
- wsi->ws->ping_payload_buf[LWS_PRE] = (reason >> 8) & 0xff;
- wsi->ws->ping_payload_buf[LWS_PRE + 1] = reason & 0xff;
- }
-
- wsi->waiting_to_send_close_frame = 1;
- wsi->close_needs_ack = 1;
- lwsi_set_state(wsi, LRS_WAITING_TO_SEND_CLOSE);
- __lws_set_timeout(wsi, PENDING_TIMEOUT_CLOSE_SEND, 5);
-
- lws_callback_on_writable(wsi);
-
- return 1;
-}
-
-static int
-rops_close_role_ws(struct lws_context_per_thread *pt, struct lws *wsi)
-{
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- if (wsi->ws->rx_draining_ext) {
- struct lws **w = &pt->ws.rx_draining_ext_list;
-
- wsi->ws->rx_draining_ext = 0;
- /* remove us from context draining ext list */
- while (*w) {
- if (*w == wsi) {
- *w = wsi->ws->rx_draining_ext_list;
- break;
- }
- w = &((*w)->ws->rx_draining_ext_list);
- }
- wsi->ws->rx_draining_ext_list = NULL;
- }
-
- if (wsi->ws->tx_draining_ext) {
- struct lws **w = &pt->ws.tx_draining_ext_list;
- lwsl_ext("%s: CLEARING tx_draining_ext\n", __func__);
- wsi->ws->tx_draining_ext = 0;
- /* remove us from context draining ext list */
- while (*w) {
- if (*w == wsi) {
- *w = wsi->ws->tx_draining_ext_list;
- break;
- }
- w = &((*w)->ws->tx_draining_ext_list);
- }
- wsi->ws->tx_draining_ext_list = NULL;
- }
-#endif
- lws_free_set_NULL(wsi->ws->rx_ubuf);
-
- if (wsi->trunc_alloc)
- /* not going to be completed... nuke it */
- lws_free_set_NULL(wsi->trunc_alloc);
-
- wsi->ws->ping_payload_len = 0;
- wsi->ws->ping_pending_flag = 0;
-
- /* deallocate any active extension contexts */
-
- if (lws_ext_cb_active(wsi, LWS_EXT_CB_DESTROY, NULL, 0) < 0)
- lwsl_warn("extension destruction failed\n");
-
- return 0;
-}
-
-static int
-rops_write_role_protocol_ws(struct lws *wsi, unsigned char *buf, size_t len,
- enum lws_write_protocol *wp)
-{
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
- enum lws_write_protocol wpt;
-#endif
- int masked7 = lwsi_role_client(wsi);
- unsigned char is_masked_bit = 0;
- unsigned char *dropmask = NULL;
- struct lws_tokens ebuf;
- size_t orig_len = len;
- int pre = 0, n = 0;
-
- // lwsl_err("%s: wp 0x%x len %d\n", __func__, *wp, (int)len);
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- if (wsi->ws->tx_draining_ext) {
- /* remove us from the list */
- struct lws **w = &pt->ws.tx_draining_ext_list;
-
- lwsl_ext("%s: CLEARING tx_draining_ext\n", __func__);
- wsi->ws->tx_draining_ext = 0;
- /* remove us from context draining ext list */
- while (*w) {
- if (*w == wsi) {
- *w = wsi->ws->tx_draining_ext_list;
- break;
- }
- w = &((*w)->ws->tx_draining_ext_list);
- }
- wsi->ws->tx_draining_ext_list = NULL;
-
- wpt = *wp;
- *wp = (wsi->ws->tx_draining_stashed_wp & 0xc0)|
- LWS_WRITE_CONTINUATION;
-
- /*
- * When we are just flushing (len == 0), we can trust the
- * stashed wp info completely. Otherwise adjust it to the
- * FIN status of the incoming packet.
- */
-
- if (!(wpt & LWS_WRITE_NO_FIN) && len)
- *wp &= ~LWS_WRITE_NO_FIN;
-
- lwsl_ext("FORCED draining wp to 0x%02X (stashed 0x%02X, incoming 0x%02X)\n", *wp,
- wsi->ws->tx_draining_stashed_wp, wpt);
- // assert(0);
- }
-#endif
- lws_restart_ws_ping_pong_timer(wsi);
-
- if (((*wp) & 0x1f) == LWS_WRITE_HTTP ||
- ((*wp) & 0x1f) == LWS_WRITE_HTTP_FINAL ||
- ((*wp) & 0x1f) == LWS_WRITE_HTTP_HEADERS_CONTINUATION ||
- ((*wp) & 0x1f) == LWS_WRITE_HTTP_HEADERS)
- goto send_raw;
-
-
-
- /* if we are continuing a frame that already had its header done */
-
- if (wsi->ws->inside_frame) {
- lwsl_debug("INSIDE FRAME\n");
- goto do_more_inside_frame;
- }
-
- wsi->ws->clean_buffer = 1;
-
- /*
- * give a chance to the extensions to modify payload
- * the extension may decide to produce unlimited payload erratically
- * (eg, compression extension), so we require only that if he produces
- * something, it will be a complete fragment of the length known at
- * the time (just the fragment length known), and if he has
- * more we will come back next time he is writeable and allow him to
- * produce more fragments until he's drained.
- *
- * This allows what is sent each time it is writeable to be limited to
- * a size that can be sent without partial sends or blocking, allows
- * interleaving of control frames and other connection service.
- */
- ebuf.token = (char *)buf;
- ebuf.len = (int)len;
-
- switch ((int)*wp) {
- case LWS_WRITE_PING:
- case LWS_WRITE_PONG:
- case LWS_WRITE_CLOSE:
- break;
- default:
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- // lwsl_notice("LWS_EXT_CB_PAYLOAD_TX\n");
- // m = (int)ebuf.len;
- /* returns 0 if no more tx pending, 1 if more pending */
- n = lws_ext_cb_active(wsi, LWS_EXT_CB_PAYLOAD_TX, &ebuf, *wp);
- if (n < 0)
- return -1;
- // lwsl_notice("ext processed %d plaintext into %d compressed (wp 0x%x)\n", m, (int)ebuf.len, *wp);
-
- if (n && ebuf.len) {
- lwsl_ext("write drain len %d (wp 0x%x) SETTING tx_draining_ext\n", (int)ebuf.len, *wp);
- /* extension requires further draining */
- wsi->ws->tx_draining_ext = 1;
- wsi->ws->tx_draining_ext_list = pt->ws.tx_draining_ext_list;
- pt->ws.tx_draining_ext_list = wsi;
- /* we must come back to do more */
- lws_callback_on_writable(wsi);
- /*
- * keep a copy of the write type for the overall
- * action that has provoked generation of these
- * fragments, so the last guy can use its FIN state.
- */
- wsi->ws->tx_draining_stashed_wp = *wp;
- /* this is definitely not actually the last fragment
- * because the extension asserted he has more coming
- * So make sure this intermediate one doesn't go out
- * with a FIN.
- */
- *wp |= LWS_WRITE_NO_FIN;
- }
-#endif
- if (ebuf.len && wsi->ws->stashed_write_pending) {
- wsi->ws->stashed_write_pending = 0;
- *wp = ((*wp) & 0xc0) | (int)wsi->ws->stashed_write_type;
- }
- }
-
- /*
- * an extension did something we need to keep... for example, if
- * compression extension, it has already updated its state according
- * to this being issued
- */
- if ((char *)buf != ebuf.token) {
- /*
- * ext might eat it, but not have anything to issue yet.
- * In that case we have to follow his lead, but stash and
- * replace the write type that was lost here the first time.
- */
- if (len && !ebuf.len) {
- if (!wsi->ws->stashed_write_pending)
- wsi->ws->stashed_write_type = (char)(*wp) & 0x3f;
- wsi->ws->stashed_write_pending = 1;
- return (int)len;
- }
- /*
- * extension recreated it:
- * need to buffer this if not all sent
- */
- wsi->ws->clean_buffer = 0;
- }
-
- buf = (unsigned char *)ebuf.token;
- len = ebuf.len;
-
- if (!buf) {
- lwsl_err("null buf (%d)\n", (int)len);
- return -1;
- }
-
- switch (wsi->ws->ietf_spec_revision) {
- case 13:
- if (masked7) {
- pre += 4;
- dropmask = &buf[0 - pre];
- is_masked_bit = 0x80;
- }
-
- switch ((*wp) & 0xf) {
- case LWS_WRITE_TEXT:
- n = LWSWSOPC_TEXT_FRAME;
- break;
- case LWS_WRITE_BINARY:
- n = LWSWSOPC_BINARY_FRAME;
- break;
- case LWS_WRITE_CONTINUATION:
- n = LWSWSOPC_CONTINUATION;
- break;
-
- case LWS_WRITE_CLOSE:
- n = LWSWSOPC_CLOSE;
- break;
- case LWS_WRITE_PING:
- n = LWSWSOPC_PING;
- break;
- case LWS_WRITE_PONG:
- n = LWSWSOPC_PONG;
- break;
- default:
- lwsl_warn("lws_write: unknown write opc / wp\n");
- return -1;
- }
-
- if (!((*wp) & LWS_WRITE_NO_FIN))
- n |= 1 << 7;
-
- if (len < 126) {
- pre += 2;
- buf[-pre] = n;
- buf[-pre + 1] = (unsigned char)(len | is_masked_bit);
- } else {
- if (len < 65536) {
- pre += 4;
- buf[-pre] = n;
- buf[-pre + 1] = 126 | is_masked_bit;
- buf[-pre + 2] = (unsigned char)(len >> 8);
- buf[-pre + 3] = (unsigned char)len;
- } else {
- pre += 10;
- buf[-pre] = n;
- buf[-pre + 1] = 127 | is_masked_bit;
-#if defined __LP64__
- buf[-pre + 2] = (len >> 56) & 0x7f;
- buf[-pre + 3] = len >> 48;
- buf[-pre + 4] = len >> 40;
- buf[-pre + 5] = len >> 32;
-#else
- buf[-pre + 2] = 0;
- buf[-pre + 3] = 0;
- buf[-pre + 4] = 0;
- buf[-pre + 5] = 0;
-#endif
- buf[-pre + 6] = (unsigned char)(len >> 24);
- buf[-pre + 7] = (unsigned char)(len >> 16);
- buf[-pre + 8] = (unsigned char)(len >> 8);
- buf[-pre + 9] = (unsigned char)len;
- }
- }
- break;
- }
-
-do_more_inside_frame:
-
- /*
- * Deal with masking if we are in client -> server direction and
- * the wp demands it
- */
-
- if (masked7) {
- if (!wsi->ws->inside_frame)
- if (lws_0405_frame_mask_generate(wsi)) {
- lwsl_err("frame mask generation failed\n");
- return -1;
- }
-
- /*
- * in v7, just mask the payload
- */
- if (dropmask) { /* never set if already inside frame */
- for (n = 4; n < (int)len + 4; n++)
- dropmask[n] = dropmask[n] ^ wsi->ws->mask[
- (wsi->ws->mask_idx++) & 3];
-
- /* copy the frame nonce into place */
- memcpy(dropmask, wsi->ws->mask, 4);
- }
- }
-
- if (lwsi_role_h2_ENCAPSULATION(wsi)) {
- struct lws *encap = lws_get_network_wsi(wsi);
-
- assert(encap != wsi);
- return encap->role_ops->write_role_protocol(wsi, buf - pre,
- len + pre, wp);
- }
-
- switch ((*wp) & 0x1f) {
- case LWS_WRITE_TEXT:
- case LWS_WRITE_BINARY:
- case LWS_WRITE_CONTINUATION:
- if (!wsi->h2_stream_carries_ws) {
-
- /*
- * give any active extensions a chance to munge the
- * buffer before send. We pass in a pointer to an
- * lws_tokens struct prepared with the default buffer
- * and content length that's in there. Rather than
- * rewrite the default buffer, extensions that expect
- * to grow the buffer can adapt .token to point to their
- * own per-connection buffer in the extension user
- * allocation. By default with no extensions or no
- * extension callback handling, just the normal input
- * buffer is used then so it is efficient.
- *
- * callback returns 1 in case it wants to spill more
- * buffers
- *
- * This takes care of holding the buffer if send is
- * incomplete, ie, if wsi->ws->clean_buffer is 0
- * (meaning an extension meddled with the buffer). If
- * wsi->ws->clean_buffer is 1, it will instead return
- * to the user code how much OF THE USER BUFFER was
- * consumed.
- */
-
- n = lws_issue_raw_ext_access(wsi, buf - pre, len + pre);
- wsi->ws->inside_frame = 1;
- if (n <= 0)
- return n;
-
- if (n == (int)len + pre) {
- /* everything in the buffer was handled
- * (or rebuffered...) */
- wsi->ws->inside_frame = 0;
- return (int)orig_len;
- }
-
- /*
- * it is how many bytes of user buffer got sent... may
- * be < orig_len in which case callback when writable
- * has already been arranged and user code can call
- * lws_write() again with the rest later.
- */
-
- return n - pre;
- }
- break;
- default:
- break;
- }
-
-send_raw:
- return lws_issue_raw(wsi, (unsigned char *)buf - pre, len + pre);
-}
-
-static int
-rops_close_kill_connection_ws(struct lws *wsi, enum lws_close_status reason)
-{
- /* deal with ws encapsulation in h2 */
-#if defined(LWS_WITH_HTTP2)
- if (wsi->http2_substream && wsi->h2_stream_carries_ws)
- return role_ops_h2.close_kill_connection(wsi, reason);
-
- return 0;
-#else
- return 0;
-#endif
-}
-
-static int
-rops_callback_on_writable_ws(struct lws *wsi)
-{
-#if defined(LWS_WITH_HTTP2)
- if (lwsi_role_h2_ENCAPSULATION(wsi)) {
- /* we know then that it has an h2 parent */
- struct lws *enc = role_ops_h2.encapsulation_parent(wsi);
-
- assert(enc);
- if (enc->role_ops->callback_on_writable(wsi))
- return 1;
- }
-#endif
- return 0;
-}
-
-static int
-rops_init_vhost_ws(struct lws_vhost *vh,
- const struct lws_context_creation_info *info)
-{
-#if !defined(LWS_WITHOUT_EXTENSIONS)
-#ifdef LWS_WITH_PLUGINS
- struct lws_plugin *plugin = vh->context->plugin_list;
- int m;
-
- if (vh->context->plugin_extension_count) {
-
- m = 0;
- while (info->extensions && info->extensions[m].callback)
- m++;
-
- /*
- * give the vhost a unified list of extensions including the
- * ones that came from plugins
- */
- vh->ws.extensions = lws_zalloc(sizeof(struct lws_extension) *
- (m + vh->context->plugin_extension_count + 1),
- "extensions");
- if (!vh->ws.extensions)
- return 1;
-
- memcpy((struct lws_extension *)vh->ws.extensions, info->extensions,
- sizeof(struct lws_extension) * m);
- plugin = vh->context->plugin_list;
- while (plugin) {
- memcpy((struct lws_extension *)&vh->ws.extensions[m],
- plugin->caps.extensions,
- sizeof(struct lws_extension) *
- plugin->caps.count_extensions);
- m += plugin->caps.count_extensions;
- plugin = plugin->list;
- }
- } else
-#endif
- vh->ws.extensions = info->extensions;
-#endif
-
- return 0;
-}
-
-static int
-rops_destroy_vhost_ws(struct lws_vhost *vh)
-{
-#ifdef LWS_WITH_PLUGINS
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- if (vh->context->plugin_extension_count)
- lws_free((void *)vh->ws.extensions);
-#endif
-#endif
-
- return 0;
-}
-
-static int
-rops_destroy_role_ws(struct lws *wsi)
-{
- lws_free_set_NULL(wsi->ws);
-
- return 0;
-}
-
-struct lws_role_ops role_ops_ws = {
- /* role name */ "ws",
- /* alpn id */ NULL,
- /* check_upgrades */ NULL,
- /* init_context */ NULL,
- /* init_vhost */ rops_init_vhost_ws,
- /* destroy_vhost */ rops_destroy_vhost_ws,
- /* periodic_checks */ rops_periodic_checks_ws,
- /* service_flag_pending */ rops_service_flag_pending_ws,
- /* handle_POLLIN */ rops_handle_POLLIN_ws,
- /* handle_POLLOUT */ rops_handle_POLLOUT_ws,
- /* perform_user_POLLOUT */ NULL,
- /* callback_on_writable */ rops_callback_on_writable_ws,
- /* tx_credit */ NULL,
- /* write_role_protocol */ rops_write_role_protocol_ws,
- /* encapsulation_parent */ NULL,
- /* alpn_negotiated */ NULL,
- /* close_via_role_protocol */ rops_close_via_role_protocol_ws,
- /* close_role */ rops_close_role_ws,
- /* close_kill_connection */ rops_close_kill_connection_ws,
- /* destroy_role */ rops_destroy_role_ws,
- /* writeable cb clnt, srv */ { LWS_CALLBACK_CLIENT_WRITEABLE,
- LWS_CALLBACK_SERVER_WRITEABLE },
- /* close cb clnt, srv */ { LWS_CALLBACK_CLIENT_CLOSED,
- LWS_CALLBACK_CLOSED },
- /* file handles */ 0
-};
diff --git a/thirdparty/libwebsockets/roles/ws/private.h b/thirdparty/libwebsockets/roles/ws/private.h
deleted file mode 100644
index 71ffcaea96..0000000000
--- a/thirdparty/libwebsockets/roles/ws/private.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010 - 2018 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * This is included from core/private.h if LWS_ROLE_WS
- */
-
-extern struct lws_role_ops role_ops_ws;
-
-#define lwsi_role_ws(wsi) (wsi->role_ops == &role_ops_ws)
-
-enum lws_rx_parse_state {
- LWS_RXPS_NEW,
-
- LWS_RXPS_04_mask_1,
- LWS_RXPS_04_mask_2,
- LWS_RXPS_04_mask_3,
-
- LWS_RXPS_04_FRAME_HDR_1,
- LWS_RXPS_04_FRAME_HDR_LEN,
- LWS_RXPS_04_FRAME_HDR_LEN16_2,
- LWS_RXPS_04_FRAME_HDR_LEN16_1,
- LWS_RXPS_04_FRAME_HDR_LEN64_8,
- LWS_RXPS_04_FRAME_HDR_LEN64_7,
- LWS_RXPS_04_FRAME_HDR_LEN64_6,
- LWS_RXPS_04_FRAME_HDR_LEN64_5,
- LWS_RXPS_04_FRAME_HDR_LEN64_4,
- LWS_RXPS_04_FRAME_HDR_LEN64_3,
- LWS_RXPS_04_FRAME_HDR_LEN64_2,
- LWS_RXPS_04_FRAME_HDR_LEN64_1,
-
- LWS_RXPS_07_COLLECT_FRAME_KEY_1,
- LWS_RXPS_07_COLLECT_FRAME_KEY_2,
- LWS_RXPS_07_COLLECT_FRAME_KEY_3,
- LWS_RXPS_07_COLLECT_FRAME_KEY_4,
-
- LWS_RXPS_WS_FRAME_PAYLOAD
-};
-
-enum lws_websocket_opcodes_07 {
- LWSWSOPC_CONTINUATION = 0,
- LWSWSOPC_TEXT_FRAME = 1,
- LWSWSOPC_BINARY_FRAME = 2,
-
- LWSWSOPC_NOSPEC__MUX = 7,
-
- /* control extensions 8+ */
-
- LWSWSOPC_CLOSE = 8,
- LWSWSOPC_PING = 9,
- LWSWSOPC_PONG = 0xa,
-};
-
-/* this is not usable directly by user code any more, lws_close_reason() */
-#define LWS_WRITE_CLOSE 4
-
-#define ALREADY_PROCESSED_IGNORE_CHAR 1
-#define ALREADY_PROCESSED_NO_CB 2
-
-#if !defined(LWS_WITHOUT_EXTENSIONS)
-struct lws_vhost_role_ws {
- const struct lws_extension *extensions;
-};
-
-struct lws_pt_role_ws {
- struct lws *rx_draining_ext_list;
- struct lws *tx_draining_ext_list;
-};
-#endif
-
-struct _lws_websocket_related {
- char *rx_ubuf;
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- const struct lws_extension *active_extensions[LWS_MAX_EXTENSIONS_ACTIVE];
- void *act_ext_user[LWS_MAX_EXTENSIONS_ACTIVE];
- struct lws *rx_draining_ext_list;
- struct lws *tx_draining_ext_list;
-#endif
- /* Also used for close content... control opcode == < 128 */
- uint8_t ping_payload_buf[128 - 3 + LWS_PRE];
- uint8_t mask[4];
-
- time_t time_next_ping_check;
- size_t rx_packet_length;
- uint32_t rx_ubuf_head;
- uint32_t rx_ubuf_alloc;
-
- uint8_t ping_payload_len;
- uint8_t mask_idx;
- uint8_t opcode;
- uint8_t rsv;
- uint8_t rsv_first_msg;
- /* zero if no info, or length including 2-byte close code */
- uint8_t close_in_ping_buffer_len;
- uint8_t utf8;
- uint8_t stashed_write_type;
- uint8_t tx_draining_stashed_wp;
- uint8_t ietf_spec_revision;
-
- unsigned int final:1;
- unsigned int frame_is_binary:1;
- unsigned int all_zero_nonce:1;
- unsigned int this_frame_masked:1;
- unsigned int inside_frame:1; /* next write will be more of frame */
- unsigned int clean_buffer:1; /* buffer not rewritten by extension */
- unsigned int payload_is_close:1; /* process as PONG, but it is close */
- unsigned int ping_pending_flag:1;
- unsigned int continuation_possible:1;
- unsigned int owed_a_fin:1;
- unsigned int check_utf8:1;
- unsigned int defeat_check_utf8:1;
- unsigned int stashed_write_pending:1;
- unsigned int send_check_ping:1;
- unsigned int first_fragment:1;
- unsigned int peer_has_sent_close:1;
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- unsigned int extension_data_pending:1;
- unsigned int rx_draining_ext:1;
- unsigned int tx_draining_ext:1;
-
- uint8_t count_act_ext;
-#endif
-};
-
-int
-lws_ws_handshake_client(struct lws *wsi, unsigned char **buf, size_t len);
-
-#if !defined(LWS_WITHOUT_EXTENSIONS)
-LWS_VISIBLE void
-lws_context_init_extensions(const struct lws_context_creation_info *info,
- struct lws_context *context);
-LWS_EXTERN int
-lws_any_extension_handled(struct lws *wsi, enum lws_extension_callback_reasons r,
- void *v, size_t len);
-
-LWS_EXTERN int
-lws_ext_cb_active(struct lws *wsi, int reason, void *buf, int len);
-LWS_EXTERN int
-lws_ext_cb_all_exts(struct lws_context *context, struct lws *wsi, int reason,
- void *arg, int len);
-#endif
-
-int
-handshake_0405(struct lws_context *context, struct lws *wsi);
-int
-lws_process_ws_upgrade(struct lws *wsi);
-int
-lws_server_init_wsi_for_ws(struct lws *wsi);
diff --git a/thirdparty/libwebsockets/roles/ws/server-ws.c b/thirdparty/libwebsockets/roles/ws/server-ws.c
deleted file mode 100644
index 62bcd8524f..0000000000
--- a/thirdparty/libwebsockets/roles/ws/server-ws.c
+++ /dev/null
@@ -1,836 +0,0 @@
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010-2018 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- */
-
-#include <core/private.h>
-
-#define LWS_CPYAPP(ptr, str) { strcpy(ptr, str); ptr += strlen(str); }
-
-#if !defined(LWS_WITHOUT_EXTENSIONS)
-static int
-lws_extension_server_handshake(struct lws *wsi, char **p, int budget)
-{
- struct lws_context *context = wsi->context;
- struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
- char ext_name[64], *args, *end = (*p) + budget - 1;
- const struct lws_ext_options *opts, *po;
- const struct lws_extension *ext;
- struct lws_ext_option_arg oa;
- int n, m, more = 1;
- int ext_count = 0;
- char ignore;
- char *c;
-
- /*
- * Figure out which extensions the client has that we want to
- * enable on this connection, and give him back the list
- */
- if (!lws_hdr_total_length(wsi, WSI_TOKEN_EXTENSIONS))
- return 0;
-
- /*
- * break down the list of client extensions
- * and go through them
- */
-
- if (lws_hdr_copy(wsi, (char *)pt->serv_buf, context->pt_serv_buf_size,
- WSI_TOKEN_EXTENSIONS) < 0)
- return 1;
-
- c = (char *)pt->serv_buf;
- lwsl_parser("WSI_TOKEN_EXTENSIONS = '%s'\n", c);
- wsi->ws->count_act_ext = 0;
- ignore = 0;
- n = 0;
- args = NULL;
-
- /*
- * We may get a simple request
- *
- * Sec-WebSocket-Extensions: permessage-deflate
- *
- * or an elaborated one with requested options
- *
- * Sec-WebSocket-Extensions: permessage-deflate; \
- * server_no_context_takeover; \
- * client_no_context_takeover
- */
-
- while (more) {
-
- if (c >= (char *)pt->serv_buf + 255)
- return -1;
-
- if (*c && (*c != ',' && *c != '\t')) {
- if (*c == ';') {
- ignore = 1;
- if (!args)
- args = c + 1;
- }
- if (ignore || *c == ' ') {
- c++;
- continue;
- }
- ext_name[n] = *c++;
- if (n < (int)sizeof(ext_name) - 1)
- n++;
- continue;
- }
- ext_name[n] = '\0';
-
- ignore = 0;
- if (!*c)
- more = 0;
- else {
- c++;
- if (!n)
- continue;
- }
-
- while (args && *args && *args == ' ')
- args++;
-
- /* check a client's extension against our support */
-
- ext = wsi->vhost->ws.extensions;
-
- while (ext && ext->callback) {
-
- if (strcmp(ext_name, ext->name)) {
- ext++;
- continue;
- }
-
- /*
- * oh, we do support this one he asked for... but let's
- * confirm he only gave it once
- */
- for (m = 0; m < wsi->ws->count_act_ext; m++)
- if (wsi->ws->active_extensions[m] == ext) {
- lwsl_info("extension mentioned twice\n");
- return 1; /* shenanigans */
- }
-
- /*
- * ask user code if it's OK to apply it on this
- * particular connection + protocol
- */
- m = (wsi->protocol->callback)(wsi,
- LWS_CALLBACK_CONFIRM_EXTENSION_OKAY,
- wsi->user_space, ext_name, 0);
-
- /*
- * zero return from callback means go ahead and allow
- * the extension, it's what we get if the callback is
- * unhandled
- */
- if (m) {
- ext++;
- continue;
- }
-
- /* apply it */
-
- ext_count++;
-
- /* instantiate the extension on this conn */
-
- wsi->ws->active_extensions[wsi->ws->count_act_ext] = ext;
-
- /* allow him to construct his context */
-
- if (ext->callback(lws_get_context(wsi), ext, wsi,
- LWS_EXT_CB_CONSTRUCT,
- (void *)&wsi->ws->act_ext_user[
- wsi->ws->count_act_ext],
- (void *)&opts, 0)) {
- lwsl_info("ext %s failed construction\n",
- ext_name);
- ext_count--;
- ext++;
-
- continue;
- }
-
- if (ext_count > 1)
- *(*p)++ = ',';
- else
- LWS_CPYAPP(*p,
- "\x0d\x0aSec-WebSocket-Extensions: ");
- *p += lws_snprintf(*p, (end - *p), "%s", ext_name);
-
- /*
- * The client may send a bunch of different option
- * sets for the same extension, we are supposed to
- * pick one we like the look of. The option sets are
- * separated by comma.
- *
- * Actually we just either accept the first one or
- * nothing.
- *
- * Go through the options trying to apply the
- * recognized ones
- */
-
- lwsl_info("ext args %s\n", args);
-
- while (args && *args && *args != ',') {
- while (*args == ' ')
- args++;
- po = opts;
- while (po->name) {
- /* only support arg-less options... */
- if (po->type != EXTARG_NONE ||
- strncmp(args, po->name,
- strlen(po->name))) {
- po++;
- continue;
- }
- oa.option_name = NULL;
- oa.option_index = (int)(po - opts);
- oa.start = NULL;
- oa.len = 0;
- lwsl_info("setting '%s'\n", po->name);
- if (!ext->callback(lws_get_context(wsi),
- ext, wsi,
- LWS_EXT_CB_OPTION_SET,
- wsi->ws->act_ext_user[
- wsi->ws->count_act_ext],
- &oa, (end - *p))) {
-
- *p += lws_snprintf(*p, (end - *p),
- "; %s", po->name);
- lwsl_debug("adding option %s\n",
- po->name);
- }
- po++;
- }
- while (*args && *args != ',' && *args != ';')
- args++;
-
- if (*args == ';')
- args++;
- }
-
- wsi->ws->count_act_ext++;
- lwsl_parser("cnt_act_ext <- %d\n", wsi->ws->count_act_ext);
-
- if (args && *args == ',')
- more = 0;
-
- ext++;
- }
-
- n = 0;
- args = NULL;
- }
-
- return 0;
-}
-#endif
-
-
-
-int
-lws_process_ws_upgrade(struct lws *wsi)
-{
- struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
- char protocol_list[128], protocol_name[64], *p;
- int protocol_len, hit, n = 0, non_space_char_found = 0;
-
- if (!wsi->protocol)
- lwsl_err("NULL protocol at lws_read\n");
-
- /*
- * It's either websocket or h2->websocket
- *
- * Select the first protocol we support from the list
- * the client sent us.
- *
- * Copy it to remove header fragmentation
- */
-
- if (lws_hdr_copy(wsi, protocol_list, sizeof(protocol_list) - 1,
- WSI_TOKEN_PROTOCOL) < 0) {
- lwsl_err("protocol list too long");
- return 1;
- }
-
- protocol_len = lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL);
- protocol_list[protocol_len] = '\0';
- p = protocol_list;
- hit = 0;
-
- while (*p && !hit) {
- n = 0;
- non_space_char_found = 0;
- while (n < (int)sizeof(protocol_name) - 1 &&
- *p && *p != ',') {
- /* ignore leading spaces */
- if (!non_space_char_found && *p == ' ') {
- n++;
- continue;
- }
- non_space_char_found = 1;
- protocol_name[n++] = *p++;
- }
- protocol_name[n] = '\0';
- if (*p)
- p++;
-
- lwsl_debug("checking %s\n", protocol_name);
-
- n = 0;
- while (wsi->vhost->protocols[n].callback) {
- lwsl_debug("try %s\n",
- wsi->vhost->protocols[n].name);
-
- if (wsi->vhost->protocols[n].name &&
- !strcmp(wsi->vhost->protocols[n].name,
- protocol_name)) {
- wsi->protocol = &wsi->vhost->protocols[n];
- hit = 1;
- break;
- }
-
- n++;
- }
- }
-
- /* we didn't find a protocol he wanted? */
-
- if (!hit) {
- if (lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL)) {
- lwsl_notice("No protocol from \"%s\" supported\n",
- protocol_list);
- return 1;
- }
- /*
- * some clients only have one protocol and
- * do not send the protocol list header...
- * allow it and match to the vhost's default
- * protocol (which itself defaults to zero)
- */
- lwsl_info("defaulting to prot handler %d\n",
- wsi->vhost->default_protocol_index);
- n = wsi->vhost->default_protocol_index;
- wsi->protocol = &wsi->vhost->protocols[
- (int)wsi->vhost->default_protocol_index];
- }
-
- /* allocate the ws struct for the wsi */
- wsi->ws = lws_zalloc(sizeof(*wsi->ws), "ws struct");
- if (!wsi->ws) {
- lwsl_notice("OOM\n");
- return 1;
- }
-
- if (lws_hdr_total_length(wsi, WSI_TOKEN_VERSION))
- wsi->ws->ietf_spec_revision =
- atoi(lws_hdr_simple_ptr(wsi, WSI_TOKEN_VERSION));
-
- /* allocate wsi->user storage */
- if (lws_ensure_user_space(wsi)) {
- lwsl_notice("problem with user space\n");
- return 1;
- }
-
- /*
- * Give the user code a chance to study the request and
- * have the opportunity to deny it
- */
- if ((wsi->protocol->callback)(wsi,
- LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION,
- wsi->user_space,
- lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL), 0)) {
- lwsl_warn("User code denied connection\n");
- return 1;
- }
-
- /*
- * Perform the handshake according to the protocol version the
- * client announced
- */
-
- switch (wsi->ws->ietf_spec_revision) {
- default:
- lwsl_notice("Unknown client spec version %d\n",
- wsi->ws->ietf_spec_revision);
- wsi->ws->ietf_spec_revision = 13;
- //return 1;
- /* fallthru */
- case 13:
-#if defined(LWS_WITH_HTTP2)
- if (wsi->h2_stream_carries_ws) {
- if (lws_h2_ws_handshake(wsi)) {
- lwsl_notice("h2 ws handshake failed\n");
- return 1;
- }
- } else
-#endif
- {
- lwsl_parser("lws_parse calling handshake_04\n");
- if (handshake_0405(wsi->context, wsi)) {
- lwsl_notice("hs0405 has failed the connection\n");
- return 1;
- }
- }
- break;
- }
-
- lws_same_vh_protocol_insert(wsi, n);
-
- /*
- * We are upgrading to ws, so http/1.1 + h2 and keepalive + pipelined
- * header considerations about keeping the ah around no longer apply.
- *
- * However it's common for the first ws protocol data to have been
- * coalesced with the browser upgrade request and to already be in the
- * ah rx buffer.
- */
-
- lws_pt_lock(pt, __func__);
-
- if (wsi->h2_stream_carries_ws)
- lws_role_transition(wsi, LWSIFR_SERVER | LWSIFR_P_ENCAP_H2,
- LRS_ESTABLISHED, &role_ops_ws);
- else
- lws_role_transition(wsi, LWSIFR_SERVER, LRS_ESTABLISHED,
- &role_ops_ws);
-
- lws_pt_unlock(pt);
-
- lws_server_init_wsi_for_ws(wsi);
- lwsl_parser("accepted v%02d connection\n", wsi->ws->ietf_spec_revision);
-
- lwsl_info("%s: %p: dropping ah on ws upgrade\n", __func__, wsi);
- lws_header_table_detach(wsi, 1);
-
- return 0;
-}
-
-int
-handshake_0405(struct lws_context *context, struct lws *wsi)
-{
- struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
- struct lws_process_html_args args;
- unsigned char hash[20];
- int n, accept_len;
- char *response;
- char *p;
-
- if (!lws_hdr_total_length(wsi, WSI_TOKEN_HOST) ||
- !lws_hdr_total_length(wsi, WSI_TOKEN_KEY)) {
- lwsl_info("handshake_04 missing pieces\n");
- /* completed header processing, but missing some bits */
- goto bail;
- }
-
- if (lws_hdr_total_length(wsi, WSI_TOKEN_KEY) >= MAX_WEBSOCKET_04_KEY_LEN) {
- lwsl_warn("Client key too long %d\n", MAX_WEBSOCKET_04_KEY_LEN);
- goto bail;
- }
-
- /*
- * since key length is restricted above (currently 128), cannot
- * overflow
- */
- n = sprintf((char *)pt->serv_buf,
- "%s258EAFA5-E914-47DA-95CA-C5AB0DC85B11",
- lws_hdr_simple_ptr(wsi, WSI_TOKEN_KEY));
-
- lws_SHA1(pt->serv_buf, n, hash);
-
- accept_len = lws_b64_encode_string((char *)hash, 20,
- (char *)pt->serv_buf, context->pt_serv_buf_size);
- if (accept_len < 0) {
- lwsl_warn("Base64 encoded hash too long\n");
- goto bail;
- }
-
- /* allocate the per-connection user memory (if any) */
- if (lws_ensure_user_space(wsi))
- goto bail;
-
- /* create the response packet */
-
- /* make a buffer big enough for everything */
-
- response = (char *)pt->serv_buf + MAX_WEBSOCKET_04_KEY_LEN + 256 + LWS_PRE;
- p = response;
- LWS_CPYAPP(p, "HTTP/1.1 101 Switching Protocols\x0d\x0a"
- "Upgrade: WebSocket\x0d\x0a"
- "Connection: Upgrade\x0d\x0a"
- "Sec-WebSocket-Accept: ");
- strcpy(p, (char *)pt->serv_buf);
- p += accept_len;
-
- /* we can only return the protocol header if:
- * - one came in, and ... */
- if (lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL) &&
- /* - it is not an empty string */
- wsi->protocol->name &&
- wsi->protocol->name[0]) {
- LWS_CPYAPP(p, "\x0d\x0aSec-WebSocket-Protocol: ");
- p += lws_snprintf(p, 128, "%s", wsi->protocol->name);
- }
-
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- /*
- * Figure out which extensions the client has that we want to
- * enable on this connection, and give him back the list.
- *
- * Give him a limited write bugdet
- */
- if (lws_extension_server_handshake(wsi, &p, 192))
- goto bail;
-#endif
- LWS_CPYAPP(p, "\x0d\x0a");
-
- args.p = p;
- args.max_len = lws_ptr_diff((char *)pt->serv_buf +
- context->pt_serv_buf_size, p);
- if (user_callback_handle_rxflow(wsi->protocol->callback, wsi,
- LWS_CALLBACK_ADD_HEADERS,
- wsi->user_space, &args, 0))
- goto bail;
-
- p = args.p;
-
- /* end of response packet */
-
- LWS_CPYAPP(p, "\x0d\x0a");
-
- /* okay send the handshake response accepting the connection */
-
- lwsl_parser("issuing resp pkt %d len\n",
- lws_ptr_diff(p, response));
-#if defined(DEBUG)
- fwrite(response, 1, p - response, stderr);
-#endif
- n = lws_write(wsi, (unsigned char *)response, p - response,
- LWS_WRITE_HTTP_HEADERS);
- if (n != (p - response)) {
- lwsl_info("%s: ERROR writing to socket %d\n", __func__, n);
- goto bail;
- }
-
- /* alright clean up and set ourselves into established state */
-
- lwsi_set_state(wsi, LRS_ESTABLISHED);
- wsi->lws_rx_parse_state = LWS_RXPS_NEW;
-
- {
- const char * uri_ptr =
- lws_hdr_simple_ptr(wsi, WSI_TOKEN_GET_URI);
- int uri_len = lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI);
- const struct lws_http_mount *hit =
- lws_find_mount(wsi, uri_ptr, uri_len);
- if (hit && hit->cgienv &&
- wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP_PMO,
- wsi->user_space, (void *)hit->cgienv, 0))
- return 1;
- }
-
- return 0;
-
-bail:
- /* caller will free up his parsing allocations */
- return -1;
-}
-
-
-
-/*
- * Once we reach LWS_RXPS_WS_FRAME_PAYLOAD, we know how much
- * to expect in that state and can deal with it in bulk more efficiently.
- */
-
-static int
-lws_ws_frame_rest_is_payload(struct lws *wsi, uint8_t **buf, size_t len)
-{
- uint8_t *buffer = *buf, mask[4];
- struct lws_tokens ebuf;
- unsigned int avail = (unsigned int)len;
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- unsigned int old_packet_length = (int)wsi->ws->rx_packet_length;
-#endif
- int n = 0;
-
- /*
- * With zlib, we can give it as much input as we like. The pmd
- * extension will draw it down in chunks (default 1024).
- *
- * If we try to restrict how much we give it, because we must go
- * back to the event loop each time, we will drop the remainder...
- */
-
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- if (!wsi->ws->count_act_ext)
-#endif
- {
- if (wsi->protocol->rx_buffer_size)
- avail = (int)wsi->protocol->rx_buffer_size;
- else
- avail = wsi->context->pt_serv_buf_size;
- }
-
- /* do not consume more than we should */
- if (avail > wsi->ws->rx_packet_length)
- avail = (unsigned int)wsi->ws->rx_packet_length;
-
- /* do not consume more than what is in the buffer */
- if (avail > len)
- avail = (unsigned int)len;
-
- if (avail <= 0)
- return 0;
-
- ebuf.token = (char *)buffer;
- ebuf.len = avail;
-
- //lwsl_hexdump_notice(ebuf.token, ebuf.len);
-
- if (!wsi->ws->all_zero_nonce) {
-
- for (n = 0; n < 4; n++)
- mask[n] = wsi->ws->mask[(wsi->ws->mask_idx + n) & 3];
-
- /* deal with 4-byte chunks using unwrapped loop */
- n = avail >> 2;
- while (n--) {
- *(buffer) = *(buffer) ^ mask[0];
- buffer++;
- *(buffer) = *(buffer) ^ mask[1];
- buffer++;
- *(buffer) = *(buffer) ^ mask[2];
- buffer++;
- *(buffer) = *(buffer) ^ mask[3];
- buffer++;
- }
- /* and the remaining bytes bytewise */
- for (n = 0; n < (int)(avail & 3); n++) {
- *(buffer) = *(buffer) ^ mask[n];
- buffer++;
- }
-
- wsi->ws->mask_idx = (wsi->ws->mask_idx + avail) & 3;
- }
-
- lwsl_info("%s: using %d of raw input (total %d on offer)\n", __func__,
- avail, (int)len);
-
- (*buf) += avail;
- len -= avail;
-
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- n = lws_ext_cb_active(wsi, LWS_EXT_CB_PAYLOAD_RX, &ebuf, 0);
- lwsl_info("%s: ext says %d / ebuf.len %d\n", __func__, n, ebuf.len);
-#endif
- /*
- * ebuf may be pointing somewhere completely different now,
- * it's the output
- */
-
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- if (n < 0) {
- /*
- * we may rely on this to get RX, just drop connection
- */
- lwsl_notice("%s: LWS_EXT_CB_PAYLOAD_RX blew out\n", __func__);
- wsi->socket_is_permanently_unusable = 1;
- return -1;
- }
-#endif
-
- wsi->ws->rx_packet_length -= avail;
-
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- /*
- * if we had an rx fragment right at the last compressed byte of the
- * message, we can get a zero length inflated output, where no prior
- * rx inflated output marked themselves with FIN, since there was
- * raw ws payload still to drain at that time.
- *
- * Then we need to generate a zero length ws rx that can be understood
- * as the message completion.
- */
-
- if (!ebuf.len && /* zero-length inflation output */
- !n && /* nothing left to drain from the inflator */
- wsi->ws->count_act_ext && /* we are using pmd */
- old_packet_length && /* we gave the inflator new input */
- !wsi->ws->rx_packet_length && /* raw ws packet payload all gone */
- wsi->ws->final && /* the raw ws packet is a FIN guy */
- wsi->protocol->callback &&
- !wsi->wsistate_pre_close) {
-
- if (user_callback_handle_rxflow(wsi->protocol->callback, wsi,
- LWS_CALLBACK_RECEIVE,
- wsi->user_space, NULL, 0))
- return -1;
-
- return avail;
- }
-#endif
-
- if (!ebuf.len)
- return avail;
-
- if (
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- n &&
-#endif
- ebuf.len)
- /* extension had more... main loop will come back */
- lws_add_wsi_to_draining_ext_list(wsi);
- else
- lws_remove_wsi_from_draining_ext_list(wsi);
-
- if (wsi->ws->check_utf8 && !wsi->ws->defeat_check_utf8) {
- if (lws_check_utf8(&wsi->ws->utf8,
- (unsigned char *)ebuf.token, ebuf.len)) {
- lws_close_reason(wsi, LWS_CLOSE_STATUS_INVALID_PAYLOAD,
- (uint8_t *)"bad utf8", 8);
- goto utf8_fail;
- }
-
- /* we are ending partway through utf-8 character? */
- if (!wsi->ws->rx_packet_length && wsi->ws->final &&
- wsi->ws->utf8 && !n) {
- lwsl_info("FINAL utf8 error\n");
- lws_close_reason(wsi, LWS_CLOSE_STATUS_INVALID_PAYLOAD,
- (uint8_t *)"partial utf8", 12);
-
-utf8_fail:
- lwsl_info("utf8 error\n");
- lwsl_hexdump_info(ebuf.token, ebuf.len);
-
- return -1;
- }
- }
-
- if (wsi->protocol->callback && !wsi->wsistate_pre_close)
- if (user_callback_handle_rxflow(wsi->protocol->callback, wsi,
- LWS_CALLBACK_RECEIVE,
- wsi->user_space,
- ebuf.token, ebuf.len))
- return -1;
-
- wsi->ws->first_fragment = 0;
-
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- lwsl_info("%s: input used %d, output %d, rem len %d, rx_draining_ext %d\n",
- __func__, avail, ebuf.len, (int)len, wsi->ws->rx_draining_ext);
-#endif
-
- return avail; /* how much we used from the input */
-}
-
-
-int
-lws_parse_ws(struct lws *wsi, unsigned char **buf, size_t len)
-{
- int m, bulk = 0;
-
- lwsl_debug("%s: received %d byte packet\n", __func__, (int)len);
-
- //lwsl_hexdump_notice(*buf, len);
-
- /* let the rx protocol state machine have as much as it needs */
-
- while (len) {
- /*
- * we were accepting input but now we stopped doing so
- */
- if (wsi->rxflow_bitmap) {
- lwsl_info("%s: doing rxflow\n", __func__);
- lws_rxflow_cache(wsi, *buf, 0, (int)len);
- lwsl_parser("%s: cached %ld\n", __func__, (long)len);
- *buf += len; /* stashing it is taking care of it */
- return 1;
- }
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- if (wsi->ws->rx_draining_ext) {
- lwsl_debug("%s: draining rx ext\n", __func__);
- m = lws_ws_rx_sm(wsi, ALREADY_PROCESSED_IGNORE_CHAR, 0);
- if (m < 0)
- return -1;
- continue;
- }
-#endif
-
- /* consume payload bytes efficiently */
- while (wsi->lws_rx_parse_state == LWS_RXPS_WS_FRAME_PAYLOAD &&
- (wsi->ws->opcode == LWSWSOPC_TEXT_FRAME ||
- wsi->ws->opcode == LWSWSOPC_BINARY_FRAME ||
- wsi->ws->opcode == LWSWSOPC_CONTINUATION) &&
- len) {
- uint8_t *bin = *buf;
-
- bulk = 1;
- m = lws_ws_frame_rest_is_payload(wsi, buf, len);
- assert((int)lws_ptr_diff(*buf, bin) <= (int)len);
- len -= lws_ptr_diff(*buf, bin);
-
- if (!m) {
-
- break;
- }
- if (m < 0) {
- lwsl_info("%s: rest_is_payload bailed\n",
- __func__);
- return -1;
- }
- }
-
- if (!bulk) {
- /* process the byte */
- m = lws_ws_rx_sm(wsi, 0, *(*buf)++);
- len--;
- } else {
- /*
- * We already handled this byte in bulk, just deal
- * with the ramifications
- */
-#if !defined(LWS_WITHOUT_EXTENSIONS)
- lwsl_debug("%s: coming out of bulk with len %d, "
- "wsi->ws->rx_draining_ext %d\n",
- __func__, (int)len,
- wsi->ws->rx_draining_ext);
-#endif
- m = lws_ws_rx_sm(wsi, ALREADY_PROCESSED_IGNORE_CHAR |
- ALREADY_PROCESSED_NO_CB, 0);
- }
-
- if (m < 0) {
- lwsl_info("%s: lws_ws_rx_sm bailed %d\n", __func__,
- bulk);
-
- return -1;
- }
-
- bulk = 0;
- }
-
- lwsl_debug("%s: exit with %d unused\n", __func__, (int)len);
-
- return 0;
-}
diff --git a/thirdparty/libwebsockets/tls/mbedtls/lws-genhash.c b/thirdparty/libwebsockets/tls/mbedtls/lws-genhash.c
deleted file mode 100644
index ce4ee6e382..0000000000
--- a/thirdparty/libwebsockets/tls/mbedtls/lws-genhash.c
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * libwebsockets - generic hash and HMAC api hiding the backend
- *
- * Copyright (C) 2017 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * lws_genhash provides a hash / hmac abstraction api in lws that works the
- * same whether you are using openssl or mbedtls hash functions underneath.
- */
-#include "libwebsockets.h"
-#include <mbedtls/version.h>
-
-#if (MBEDTLS_VERSION_NUMBER >= 0x02070000)
-#define MBA(fn) fn##_ret
-#else
-#define MBA(fn) fn
-#endif
-
-size_t
-lws_genhash_size(enum lws_genhash_types type)
-{
- switch(type) {
- case LWS_GENHASH_TYPE_SHA1:
- return 20;
- case LWS_GENHASH_TYPE_SHA256:
- return 32;
- case LWS_GENHASH_TYPE_SHA384:
- return 48;
- case LWS_GENHASH_TYPE_SHA512:
- return 64;
- }
-
- return 0;
-}
-
-int
-lws_genhash_init(struct lws_genhash_ctx *ctx, enum lws_genhash_types type)
-{
- ctx->type = type;
-
- switch (ctx->type) {
- case LWS_GENHASH_TYPE_SHA1:
- mbedtls_sha1_init(&ctx->u.sha1);
- MBA(mbedtls_sha1_starts)(&ctx->u.sha1);
- break;
- case LWS_GENHASH_TYPE_SHA256:
- mbedtls_sha256_init(&ctx->u.sha256);
- MBA(mbedtls_sha256_starts)(&ctx->u.sha256, 0);
- break;
- case LWS_GENHASH_TYPE_SHA384:
- mbedtls_sha512_init(&ctx->u.sha512);
- MBA(mbedtls_sha512_starts)(&ctx->u.sha512, 1 /* is384 */);
- break;
- case LWS_GENHASH_TYPE_SHA512:
- mbedtls_sha512_init(&ctx->u.sha512);
- MBA(mbedtls_sha512_starts)(&ctx->u.sha512, 0);
- break;
- default:
- return 1;
- }
-
- return 0;
-}
-
-int
-lws_genhash_update(struct lws_genhash_ctx *ctx, const void *in, size_t len)
-{
- switch (ctx->type) {
- case LWS_GENHASH_TYPE_SHA1:
- MBA(mbedtls_sha1_update)(&ctx->u.sha1, in, len);
- break;
- case LWS_GENHASH_TYPE_SHA256:
- MBA(mbedtls_sha256_update)(&ctx->u.sha256, in, len);
- break;
- case LWS_GENHASH_TYPE_SHA384:
- MBA(mbedtls_sha512_update)(&ctx->u.sha512, in, len);
- break;
- case LWS_GENHASH_TYPE_SHA512:
- MBA(mbedtls_sha512_update)(&ctx->u.sha512, in, len);
- break;
- }
-
- return 0;
-}
-
-int
-lws_genhash_destroy(struct lws_genhash_ctx *ctx, void *result)
-{
- switch (ctx->type) {
- case LWS_GENHASH_TYPE_SHA1:
- MBA(mbedtls_sha1_finish)(&ctx->u.sha1, result);
- mbedtls_sha1_free(&ctx->u.sha1);
- break;
- case LWS_GENHASH_TYPE_SHA256:
- MBA(mbedtls_sha256_finish)(&ctx->u.sha256, result);
- mbedtls_sha256_free(&ctx->u.sha256);
- break;
- case LWS_GENHASH_TYPE_SHA384:
- MBA(mbedtls_sha512_finish)(&ctx->u.sha512, result);
- mbedtls_sha512_free(&ctx->u.sha512);
- break;
- case LWS_GENHASH_TYPE_SHA512:
- MBA(mbedtls_sha512_finish)(&ctx->u.sha512, result);
- mbedtls_sha512_free(&ctx->u.sha512);
- break;
- }
-
- return 0;
-}
-
-size_t
-lws_genhmac_size(enum lws_genhmac_types type)
-{
- switch(type) {
- case LWS_GENHMAC_TYPE_SHA256:
- return 32;
- case LWS_GENHMAC_TYPE_SHA384:
- return 48;
- case LWS_GENHMAC_TYPE_SHA512:
- return 64;
- }
-
- return 0;
-}
-
-int
-lws_genhmac_init(struct lws_genhmac_ctx *ctx, enum lws_genhmac_types type,
- const uint8_t *key, size_t key_len)
-{
- int t;
-
- ctx->type = type;
-
- switch (type) {
- case LWS_GENHMAC_TYPE_SHA256:
- t = MBEDTLS_MD_SHA256;
- break;
- case LWS_GENHMAC_TYPE_SHA384:
- t = MBEDTLS_MD_SHA384;
- break;
- case LWS_GENHMAC_TYPE_SHA512:
- t = MBEDTLS_MD_SHA512;
- break;
- default:
- return -1;
- }
-
- ctx->hmac = mbedtls_md_info_from_type(t);
- if (!ctx->hmac)
- return -1;
-
- if (mbedtls_md_init_ctx(&ctx->ctx, ctx->hmac))
- return -1;
-
- if (mbedtls_md_hmac_starts(&ctx->ctx, key, key_len)) {
- mbedtls_md_free(&ctx->ctx);
- ctx->hmac = NULL;
-
- return -1;
- }
-
- return 0;
-}
-
-int
-lws_genhmac_update(struct lws_genhmac_ctx *ctx, const void *in, size_t len)
-{
- if (mbedtls_md_hmac_update(&ctx->ctx, in, len))
- return -1;
-
- return 0;
-}
-
-int
-lws_genhmac_destroy(struct lws_genhmac_ctx *ctx, void *result)
-{
- int n = 0;
-
- if (result)
- n = mbedtls_md_hmac_finish(&ctx->ctx, result);
-
- mbedtls_md_free(&ctx->ctx);
- ctx->hmac = NULL;
- if (n)
- return -1;
-
- return 0;
-}
diff --git a/thirdparty/libwebsockets/tls/mbedtls/lws-genrsa.c b/thirdparty/libwebsockets/tls/mbedtls/lws-genrsa.c
deleted file mode 100644
index 70a9fcf42c..0000000000
--- a/thirdparty/libwebsockets/tls/mbedtls/lws-genrsa.c
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * libwebsockets - generic RSA api hiding the backend
- *
- * Copyright (C) 2017 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * lws_genhash provides a hash / hmac abstraction api in lws that works the
- * same whether you are using openssl or mbedtls hash functions underneath.
- */
-#include "core/private.h"
-
-LWS_VISIBLE void
-lws_jwk_destroy_genrsa_elements(struct lws_genrsa_elements *el)
-{
- int n;
-
- for (n = 0; n < LWS_COUNT_RSA_ELEMENTS; n++)
- if (el->e[n].buf)
- lws_free_set_NULL(el->e[n].buf);
-}
-
-LWS_VISIBLE int
-lws_genrsa_create(struct lws_genrsa_ctx *ctx, struct lws_genrsa_elements *el)
-{
- int n;
-
- memset(ctx, 0, sizeof(*ctx));
- ctx->ctx = lws_zalloc(sizeof(*ctx->ctx), "genrsa");
- if (!ctx->ctx)
- return 1;
-
- mbedtls_rsa_init(ctx->ctx, MBEDTLS_RSA_PKCS_V15, 0);
-
- {
- mbedtls_mpi *mpi[LWS_COUNT_RSA_ELEMENTS] = {
- &ctx->ctx->E, &ctx->ctx->N, &ctx->ctx->D, &ctx->ctx->P,
- &ctx->ctx->Q, &ctx->ctx->DP, &ctx->ctx->DQ,
- &ctx->ctx->QP,
- };
-
- for (n = 0; n < LWS_COUNT_RSA_ELEMENTS; n++)
- if (el->e[n].buf &&
- mbedtls_mpi_read_binary(mpi[n], el->e[n].buf,
- el->e[n].len)) {
- lwsl_notice("mpi load failed\n");
- lws_free_set_NULL(ctx->ctx);
-
- return -1;
- }
- }
-
- ctx->ctx->len = el->e[JWK_KEY_N].len;
-
- return 0;
-}
-
-static int
-_rngf(void *context, unsigned char *buf, size_t len)
-{
- if ((size_t)lws_get_random(context, buf, len) == len)
- return 0;
-
- return -1;
-}
-
-LWS_VISIBLE int
-lws_genrsa_new_keypair(struct lws_context *context, struct lws_genrsa_ctx *ctx,
- struct lws_genrsa_elements *el, int bits)
-{
- int n;
-
- memset(ctx, 0, sizeof(*ctx));
- ctx->ctx = lws_zalloc(sizeof(*ctx->ctx), "genrsa");
- if (!ctx->ctx)
- return -1;
-
- mbedtls_rsa_init(ctx->ctx, MBEDTLS_RSA_PKCS_V15, 0);
-
- n = mbedtls_rsa_gen_key(ctx->ctx, _rngf, context, bits, 65537);
- if (n) {
- lwsl_err("mbedtls_rsa_gen_key failed 0x%x\n", -n);
- goto cleanup_1;
- }
-
- {
- mbedtls_mpi *mpi[LWS_COUNT_RSA_ELEMENTS] = {
- &ctx->ctx->E, &ctx->ctx->N, &ctx->ctx->D, &ctx->ctx->P,
- &ctx->ctx->Q, &ctx->ctx->DP, &ctx->ctx->DQ,
- &ctx->ctx->QP,
- };
-
- for (n = 0; n < LWS_COUNT_RSA_ELEMENTS; n++)
- if (mbedtls_mpi_size(mpi[n])) {
- el->e[n].buf = lws_malloc(
- mbedtls_mpi_size(mpi[n]), "genrsakey");
- if (!el->e[n].buf)
- goto cleanup;
- el->e[n].len = mbedtls_mpi_size(mpi[n]);
- mbedtls_mpi_write_binary(mpi[n], el->e[n].buf,
- el->e[n].len);
- }
- }
-
- return 0;
-
-cleanup:
- for (n = 0; n < LWS_COUNT_RSA_ELEMENTS; n++)
- if (el->e[n].buf)
- lws_free_set_NULL(el->e[n].buf);
-cleanup_1:
- lws_free(ctx->ctx);
-
- return -1;
-}
-
-LWS_VISIBLE int
-lws_genrsa_public_decrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in,
- size_t in_len, uint8_t *out, size_t out_max)
-{
- size_t olen = 0;
- int n;
-
- ctx->ctx->len = in_len;
- n = mbedtls_rsa_rsaes_pkcs1_v15_decrypt(ctx->ctx, NULL, NULL,
- MBEDTLS_RSA_PUBLIC,
- &olen, in, out, out_max);
- if (n) {
- lwsl_notice("%s: -0x%x\n", __func__, -n);
-
- return -1;
- }
-
- return olen;
-}
-
-LWS_VISIBLE int
-lws_genrsa_public_encrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in,
- size_t in_len, uint8_t *out)
-{
- int n;
-
- ctx->ctx->len = in_len;
- n = mbedtls_rsa_rsaes_pkcs1_v15_encrypt(ctx->ctx, NULL, NULL,
- MBEDTLS_RSA_PRIVATE,
- in_len, in, out);
- if (n) {
- lwsl_notice("%s: -0x%x\n", __func__, -n);
-
- return -1;
- }
-
- return 0;
-}
-
-static int
-lws_genrsa_genrsa_hash_to_mbed_hash(enum lws_genhash_types hash_type)
-{
- int h = -1;
-
- switch (hash_type) {
- case LWS_GENHASH_TYPE_SHA1:
- h = MBEDTLS_MD_SHA1;
- break;
- case LWS_GENHASH_TYPE_SHA256:
- h = MBEDTLS_MD_SHA256;
- break;
- case LWS_GENHASH_TYPE_SHA384:
- h = MBEDTLS_MD_SHA384;
- break;
- case LWS_GENHASH_TYPE_SHA512:
- h = MBEDTLS_MD_SHA512;
- break;
- }
-
- return h;
-}
-
-LWS_VISIBLE int
-lws_genrsa_public_verify(struct lws_genrsa_ctx *ctx, const uint8_t *in,
- enum lws_genhash_types hash_type, const uint8_t *sig,
- size_t sig_len)
-{
- int n, h = lws_genrsa_genrsa_hash_to_mbed_hash(hash_type);
-
- if (h < 0)
- return -1;
-
- n = mbedtls_rsa_rsassa_pkcs1_v15_verify(ctx->ctx, NULL, NULL,
- MBEDTLS_RSA_PUBLIC,
- h, 0, in, sig);
- if (n < 0) {
- lwsl_notice("%s: -0x%x\n", __func__, -n);
-
- return -1;
- }
-
- return n;
-}
-
-LWS_VISIBLE int
-lws_genrsa_public_sign(struct lws_genrsa_ctx *ctx, const uint8_t *in,
- enum lws_genhash_types hash_type, uint8_t *sig,
- size_t sig_len)
-{
- int n, h = lws_genrsa_genrsa_hash_to_mbed_hash(hash_type);
-
- if (h < 0)
- return -1;
-
- /*
- * The "sig" buffer must be as large as the size of ctx->N
- * (eg. 128 bytes if RSA-1024 is used).
- */
- if (sig_len < ctx->ctx->len)
- return -1;
-
- n = mbedtls_rsa_rsassa_pkcs1_v15_sign(ctx->ctx, NULL, NULL,
- MBEDTLS_RSA_PRIVATE, h, 0, in,
- sig);
- if (n < 0) {
- lwsl_notice("%s: -0x%x\n", __func__, -n);
-
- return -1;
- }
-
- return ctx->ctx->len;
-}
-
-LWS_VISIBLE int
-lws_genrsa_render_pkey_asn1(struct lws_genrsa_ctx *ctx, int _private,
- uint8_t *pkey_asn1, size_t pkey_asn1_len)
-{
- uint8_t *p = pkey_asn1, *totlen, *end = pkey_asn1 + pkey_asn1_len - 1;
- mbedtls_mpi *mpi[LWS_COUNT_RSA_ELEMENTS] = {
- &ctx->ctx->N, &ctx->ctx->E, &ctx->ctx->D, &ctx->ctx->P,
- &ctx->ctx->Q, &ctx->ctx->DP, &ctx->ctx->DQ,
- &ctx->ctx->QP,
- };
- int n;
-
- /* 30 82 - sequence
- * 09 29 <-- length(0x0929) less 4 bytes
- * 02 01 <- length (1)
- * 00
- * 02 82
- * 02 01 <- length (513) N
- * ...
- *
- * 02 03 <- length (3) E
- * 01 00 01
- *
- * 02 82
- * 02 00 <- length (512) D P Q EXP1 EXP2 COEFF
- *
- * */
-
- *p++ = 0x30;
- *p++ = 0x82;
- totlen = p;
- p += 2;
-
- *p++ = 0x02;
- *p++ = 0x01;
- *p++ = 0x00;
-
- for (n = 0; n < LWS_COUNT_RSA_ELEMENTS; n++) {
- int m = mbedtls_mpi_size(mpi[n]);
- uint8_t *elen;
-
- *p++ = 0x02;
- elen = p;
- if (m < 0x7f)
- *p++ = m;
- else {
- *p++ = 0x82;
- *p++ = m >> 8;
- *p++ = m & 0xff;
- }
-
- if (p + m > end)
- return -1;
-
- mbedtls_mpi_write_binary(mpi[n], p, m);
- if (p[0] & 0x80) {
- p[0] = 0x00;
- mbedtls_mpi_write_binary(mpi[n], &p[1], m);
- m++;
- }
- if (m < 0x7f)
- *elen = m;
- else {
- *elen++ = 0x82;
- *elen++ = m >> 8;
- *elen = m & 0xff;
- }
- p += m;
- }
-
- n = lws_ptr_diff(p, pkey_asn1);
-
- *totlen++ = (n - 4) >> 8;
- *totlen = (n - 4) & 0xff;
-
- return n;
-}
-
-LWS_VISIBLE void
-lws_genrsa_destroy(struct lws_genrsa_ctx *ctx)
-{
- if (!ctx->ctx)
- return;
- mbedtls_rsa_free(ctx->ctx);
- lws_free(ctx->ctx);
- ctx->ctx = NULL;
-}
diff --git a/thirdparty/libwebsockets/tls/mbedtls/mbedtls-client.c b/thirdparty/libwebsockets/tls/mbedtls/mbedtls-client.c
deleted file mode 100644
index a7864ab790..0000000000
--- a/thirdparty/libwebsockets/tls/mbedtls/mbedtls-client.c
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * libwebsockets - mbedtls-specific client TLS code
- *
- * Copyright (C) 2010-2017 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- */
-
-#include "core/private.h"
-
-static int
-OpenSSL_client_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
-{
- return 0;
-}
-
-int
-lws_ssl_client_bio_create(struct lws *wsi)
-{
- X509_VERIFY_PARAM *param;
- char hostname[128], *p;
- const char *alpn_comma = wsi->context->tls.alpn_default;
- struct alpn_ctx protos;
-
- if (lws_hdr_copy(wsi, hostname, sizeof(hostname),
- _WSI_TOKEN_CLIENT_HOST) <= 0) {
- lwsl_err("%s: Unable to get hostname\n", __func__);
-
- return -1;
- }
-
- /*
- * remove any :port part on the hostname... necessary for network
- * connection but typical certificates do not contain it
- */
- p = hostname;
- while (*p) {
- if (*p == ':') {
- *p = '\0';
- break;
- }
- p++;
- }
-
- wsi->tls.ssl = SSL_new(wsi->vhost->tls.ssl_client_ctx);
- if (!wsi->tls.ssl)
- return -1;
-
- if (wsi->vhost->tls.ssl_info_event_mask)
- SSL_set_info_callback(wsi->tls.ssl, lws_ssl_info_callback);
-
- if (!(wsi->tls.use_ssl & LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK)) {
- param = SSL_get0_param(wsi->tls.ssl);
- /* Enable automatic hostname checks */
- // X509_VERIFY_PARAM_set_hostflags(param,
- // X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
- X509_VERIFY_PARAM_set1_host(param, hostname, 0);
- }
-
- if (wsi->vhost->tls.alpn)
- alpn_comma = wsi->vhost->tls.alpn;
-
- if (lws_hdr_copy(wsi, hostname, sizeof(hostname),
- _WSI_TOKEN_CLIENT_ALPN) > 0)
- alpn_comma = hostname;
-
- lwsl_info("%s: %p: client conn sending ALPN list '%s'\n",
- __func__, wsi, alpn_comma);
-
- protos.len = lws_alpn_comma_to_openssl(alpn_comma, protos.data,
- sizeof(protos.data) - 1);
-
- /* with mbedtls, protos is not pointed to after exit from this call */
- SSL_set_alpn_select_cb(wsi->tls.ssl, &protos);
-
- /*
- * use server name indication (SNI), if supported,
- * when establishing connection
- */
- SSL_set_verify(wsi->tls.ssl, SSL_VERIFY_PEER,
- OpenSSL_client_verify_callback);
-
- SSL_set_fd(wsi->tls.ssl, wsi->desc.sockfd);
-
- return 0;
-}
-
-int ERR_get_error(void)
-{
- return 0;
-}
-
-enum lws_ssl_capable_status
-lws_tls_client_connect(struct lws *wsi)
-{
- int m, n = SSL_connect(wsi->tls.ssl);
- const unsigned char *prot;
- unsigned int len;
-
- if (n == 1) {
- SSL_get0_alpn_selected(wsi->tls.ssl, &prot, &len);
- lws_role_call_alpn_negotiated(wsi, (const char *)prot);
- lwsl_info("client connect OK\n");
- return LWS_SSL_CAPABLE_DONE;
- }
-
- m = SSL_get_error(wsi->tls.ssl, n);
-
- if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->tls.ssl))
- return LWS_SSL_CAPABLE_MORE_SERVICE_READ;
-
- if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl))
- return LWS_SSL_CAPABLE_MORE_SERVICE_WRITE;
-
- if (!n) /* we don't know what he wants, but he says to retry */
- return LWS_SSL_CAPABLE_MORE_SERVICE;
-
- return LWS_SSL_CAPABLE_ERROR;
-}
-
-int
-lws_tls_client_confirm_peer_cert(struct lws *wsi, char *ebuf, int ebuf_len)
-{
- int n;
- X509 *peer = SSL_get_peer_certificate(wsi->tls.ssl);
- struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
- char *sb = (char *)&pt->serv_buf[0];
-
- if (!peer) {
- lwsl_info("peer did not provide cert\n");
-
- return -1;
- }
- lwsl_info("peer provided cert\n");
-
- n = SSL_get_verify_result(wsi->tls.ssl);
- lws_latency(wsi->context, wsi,
- "SSL_get_verify_result LWS_CONNMODE..HANDSHAKE", n, n > 0);
-
- lwsl_debug("get_verify says %d\n", n);
-
- if (n == X509_V_OK)
- return 0;
-
- if (n == X509_V_ERR_HOSTNAME_MISMATCH &&
- (wsi->tls.use_ssl & LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK)) {
- lwsl_info("accepting certificate for invalid hostname\n");
- return 0;
- }
-
- if (n == X509_V_ERR_INVALID_CA &&
- (wsi->tls.use_ssl & LCCSCF_ALLOW_SELFSIGNED)) {
- lwsl_info("accepting certificate from untrusted CA\n");
- return 0;
- }
-
- if ((n == X509_V_ERR_CERT_NOT_YET_VALID ||
- n == X509_V_ERR_CERT_HAS_EXPIRED) &&
- (wsi->tls.use_ssl & LCCSCF_ALLOW_EXPIRED)) {
- lwsl_info("accepting expired or not yet valid certificate\n");
-
- return 0;
- }
- lws_snprintf(ebuf, ebuf_len,
- "server's cert didn't look good, X509_V_ERR = %d: %s\n",
- n, ERR_error_string(n, sb));
- lwsl_info("%s\n", ebuf);
- lws_ssl_elaborate_error();
-
- return -1;
-}
-
-int
-lws_tls_client_create_vhost_context(struct lws_vhost *vh,
- const struct lws_context_creation_info *info,
- const char *cipher_list,
- const char *ca_filepath,
- const char *cert_filepath,
- const char *private_key_filepath)
-{
- X509 *d2i_X509(X509 **cert, const unsigned char *buffer, long len);
- SSL_METHOD *method = (SSL_METHOD *)TLS_client_method();
- unsigned long error;
- lws_filepos_t len;
- uint8_t *buf;
-
- if (!method) {
- error = ERR_get_error();
- lwsl_err("problem creating ssl method %lu: %s\n",
- error, ERR_error_string(error,
- (char *)vh->context->pt[0].serv_buf));
- return 1;
- }
- /* create context */
- vh->tls.ssl_client_ctx = SSL_CTX_new(method);
- if (!vh->tls.ssl_client_ctx) {
- error = ERR_get_error();
- lwsl_err("problem creating ssl context %lu: %s\n",
- error, ERR_error_string(error,
- (char *)vh->context->pt[0].serv_buf));
- return 1;
- }
-
- if (!ca_filepath)
- return 0;
-
- if (alloc_file(vh->context, ca_filepath, &buf, &len)) {
- lwsl_err("Load CA cert file %s failed\n", ca_filepath);
- return 1;
- }
-
- vh->tls.x509_client_CA = d2i_X509(NULL, buf, len);
- free(buf);
- if (!vh->tls.x509_client_CA) {
- lwsl_err("client CA: x509 parse failed\n");
- return 1;
- }
-
- if (!vh->tls.ssl_ctx)
- SSL_CTX_add_client_CA(vh->tls.ssl_client_ctx, vh->tls.x509_client_CA);
- else
- SSL_CTX_add_client_CA(vh->tls.ssl_ctx, vh->tls.x509_client_CA);
-
- lwsl_notice("client loaded CA for verification %s\n", ca_filepath);
-
- return 0;
-}
diff --git a/thirdparty/libwebsockets/tls/mbedtls/mbedtls-server.c b/thirdparty/libwebsockets/tls/mbedtls/mbedtls-server.c
deleted file mode 100644
index f17c7e5494..0000000000
--- a/thirdparty/libwebsockets/tls/mbedtls/mbedtls-server.c
+++ /dev/null
@@ -1,694 +0,0 @@
-/*
- * libwebsockets - mbedTLS-specific server functions
- *
- * Copyright (C) 2010-2017 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- */
-
-#include "core/private.h"
-#include <mbedtls/x509_csr.h>
-
-int
-lws_tls_server_client_cert_verify_config(struct lws_vhost *vh)
-{
- int verify_options = SSL_VERIFY_PEER;
-
- /* as a server, are we requiring clients to identify themselves? */
- if (!lws_check_opt(vh->options,
- LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT)) {
- lwsl_notice("no client cert required\n");
- return 0;
- }
-
- /*
- * The wrapper has this messed-up mapping:
- *
- * else if (ctx->verify_mode == SSL_VERIFY_FAIL_IF_NO_PEER_CERT)
- * mode = MBEDTLS_SSL_VERIFY_OPTIONAL;
- *
- * ie the meaning is inverted. So where we should test for ! we don't
- */
- if (lws_check_opt(vh->options, LWS_SERVER_OPTION_PEER_CERT_NOT_REQUIRED))
- verify_options = SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
-
- lwsl_notice("%s: vh %s requires client cert %d\n", __func__, vh->name,
- verify_options);
-
- SSL_CTX_set_verify(vh->tls.ssl_ctx, verify_options, NULL);
-
- return 0;
-}
-
-static int
-lws_mbedtls_sni_cb(void *arg, mbedtls_ssl_context *mbedtls_ctx,
- const unsigned char *servername, size_t len)
-{
- SSL *ssl = SSL_SSL_from_mbedtls_ssl_context(mbedtls_ctx);
- struct lws_context *context = (struct lws_context *)arg;
- struct lws_vhost *vhost, *vh;
-
- lwsl_notice("%s: %s\n", __func__, servername);
-
- /*
- * We can only get ssl accepted connections by using a vhost's ssl_ctx
- * find out which listening one took us and only match vhosts on the
- * same port.
- */
- vh = context->vhost_list;
- while (vh) {
- if (!vh->being_destroyed &&
- vh->tls.ssl_ctx == SSL_get_SSL_CTX(ssl))
- break;
- vh = vh->vhost_next;
- }
-
- if (!vh) {
- assert(vh); /* can't match the incoming vh? */
- return 0;
- }
-
- vhost = lws_select_vhost(context, vh->listen_port,
- (const char *)servername);
- if (!vhost) {
- lwsl_info("SNI: none: %s:%d\n", servername, vh->listen_port);
-
- return 0;
- }
-
- lwsl_info("SNI: Found: %s:%d at vhost '%s'\n", servername,
- vh->listen_port, vhost->name);
-
- /* select the ssl ctx from the selected vhost for this conn */
- SSL_set_SSL_CTX(ssl, vhost->tls.ssl_ctx);
-
- return 0;
-}
-
-int
-lws_tls_server_certs_load(struct lws_vhost *vhost, struct lws *wsi,
- const char *cert, const char *private_key,
- const char *mem_cert, size_t len_mem_cert,
- const char *mem_privkey, size_t mem_privkey_len)
-{
- int n, f = 0;
- const char *filepath = private_key;
- uint8_t *mem = NULL, *p = NULL;
- size_t mem_len = 0;
- lws_filepos_t flen;
- long err;
-
- if ((!cert || !private_key) && (!mem_cert || !mem_privkey)) {
- lwsl_notice("%s: no usable input\n", __func__);
- return 0;
- }
-
- n = lws_tls_generic_cert_checks(vhost, cert, private_key);
-
- if (n == LWS_TLS_EXTANT_NO && (!mem_cert || !mem_privkey))
- return 0;
-
- /*
- * we can't read the root-privs files. But if mem_cert is provided,
- * we should use that.
- */
- if (n == LWS_TLS_EXTANT_NO)
- n = LWS_TLS_EXTANT_ALTERNATIVE;
-
- if (n == LWS_TLS_EXTANT_ALTERNATIVE && (!mem_cert || !mem_privkey))
- return 1; /* no alternative */
-
- if (n == LWS_TLS_EXTANT_ALTERNATIVE) {
- /*
- * Although we have prepared update certs, we no longer have
- * the rights to read our own cert + key we saved.
- *
- * If we were passed copies in memory buffers, use those
- * instead.
- *
- * The passed memory-buffer cert image is in DER, and the
- * memory-buffer private key image is PEM.
- */
- /* mem cert is already DER */
- p = (uint8_t *)mem_cert;
- flen = len_mem_cert;
- /* mem private key is PEM, so go through the motions */
- mem = (uint8_t *)mem_privkey;
- mem_len = mem_privkey_len;
- filepath = NULL;
- } else {
- if (lws_tls_alloc_pem_to_der_file(vhost->context, cert, NULL,
- 0, &p, &flen)) {
- lwsl_err("couldn't find cert file %s\n", cert);
-
- return 1;
- }
- f = 1;
- }
- err = SSL_CTX_use_certificate_ASN1(vhost->tls.ssl_ctx, flen, p);
- if (!err) {
- free(p);
- lwsl_err("Problem loading cert\n");
- return 1;
- }
-
- if (f)
- free(p);
- p = NULL;
-
- if (private_key || n == LWS_TLS_EXTANT_ALTERNATIVE) {
- if (lws_tls_alloc_pem_to_der_file(vhost->context, filepath,
- (char *)mem, mem_len, &p,
- &flen)) {
- lwsl_err("couldn't find private key file %s\n",
- private_key);
-
- return 1;
- }
- err = SSL_CTX_use_PrivateKey_ASN1(0, vhost->tls.ssl_ctx, p, flen);
- if (!err) {
- free(p);
- lwsl_err("Problem loading key\n");
-
- return 1;
- }
- }
-
- if (p && !mem_privkey) {
- free(p);
- p = NULL;
- }
-
- if (!private_key && !mem_privkey &&
- vhost->protocols[0].callback(wsi,
- LWS_CALLBACK_OPENSSL_CONTEXT_REQUIRES_PRIVATE_KEY,
- vhost->tls.ssl_ctx, NULL, 0)) {
- lwsl_err("ssl private key not set\n");
-
- return 1;
- }
-
- vhost->tls.skipped_certs = 0;
-
- return 0;
-}
-
-int
-lws_tls_server_vhost_backend_init(const struct lws_context_creation_info *info,
- struct lws_vhost *vhost, struct lws *wsi)
-{
- const SSL_METHOD *method = TLS_server_method();
- uint8_t *p;
- lws_filepos_t flen;
- int n;
-
- vhost->tls.ssl_ctx = SSL_CTX_new(method); /* create context */
- if (!vhost->tls.ssl_ctx) {
- lwsl_err("problem creating ssl context\n");
- return 1;
- }
-
- if (!vhost->tls.use_ssl || !info->ssl_cert_filepath)
- return 0;
-
- if (info->ssl_ca_filepath) {
- lwsl_notice("%s: vh %s: loading CA filepath %s\n", __func__,
- vhost->name, info->ssl_ca_filepath);
- if (lws_tls_alloc_pem_to_der_file(vhost->context,
- info->ssl_ca_filepath, NULL, 0, &p, &flen)) {
- lwsl_err("couldn't find client CA file %s\n",
- info->ssl_ca_filepath);
-
- return 1;
- }
-
- if (SSL_CTX_add_client_CA_ASN1(vhost->tls.ssl_ctx, (int)flen, p) != 1) {
- lwsl_err("%s: SSL_CTX_add_client_CA_ASN1 unhappy\n",
- __func__);
- free(p);
- return 1;
- }
- free(p);
- }
-
- n = lws_tls_server_certs_load(vhost, wsi, info->ssl_cert_filepath,
- info->ssl_private_key_filepath, NULL,
- 0, NULL, 0);
- if (n)
- return n;
-
- return 0;
-}
-
-int
-lws_tls_server_new_nonblocking(struct lws *wsi, lws_sockfd_type accept_fd)
-{
- errno = 0;
- wsi->tls.ssl = SSL_new(wsi->vhost->tls.ssl_ctx);
- if (wsi->tls.ssl == NULL) {
- lwsl_err("SSL_new failed: errno %d\n", errno);
-
- lws_ssl_elaborate_error();
- return 1;
- }
-
- SSL_set_fd(wsi->tls.ssl, accept_fd);
-
- if (wsi->vhost->tls.ssl_info_event_mask)
- SSL_set_info_callback(wsi->tls.ssl, lws_ssl_info_callback);
-
- SSL_set_sni_callback(wsi->tls.ssl, lws_mbedtls_sni_cb, wsi->context);
-
- return 0;
-}
-
-int
-lws_tls_server_abort_connection(struct lws *wsi)
-{
- __lws_tls_shutdown(wsi);
- SSL_free(wsi->tls.ssl);
-
- return 0;
-}
-
-enum lws_ssl_capable_status
-lws_tls_server_accept(struct lws *wsi)
-{
- union lws_tls_cert_info_results ir;
- int m, n;
-
- n = SSL_accept(wsi->tls.ssl);
- if (n == 1) {
-
- if (strstr(wsi->vhost->name, ".invalid")) {
- lwsl_notice("%s: vhost has .invalid, rejecting accept\n", __func__);
-
- return LWS_SSL_CAPABLE_ERROR;
- }
-
- n = lws_tls_peer_cert_info(wsi, LWS_TLS_CERT_INFO_COMMON_NAME, &ir,
- sizeof(ir.ns.name));
- if (!n)
- lwsl_notice("%s: client cert CN '%s'\n",
- __func__, ir.ns.name);
- else
- lwsl_info("%s: couldn't get client cert CN\n", __func__);
- return LWS_SSL_CAPABLE_DONE;
- }
-
- m = SSL_get_error(wsi->tls.ssl, n);
- lwsl_debug("%s: %p: accept SSL_get_error %d errno %d\n", __func__,
- wsi, m, errno);
-
- // mbedtls wrapper only
- if (m == SSL_ERROR_SYSCALL && errno == 11)
- return LWS_SSL_CAPABLE_MORE_SERVICE_READ;
-
- if (m == SSL_ERROR_SYSCALL || m == SSL_ERROR_SSL)
- return LWS_SSL_CAPABLE_ERROR;
-
- if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->tls.ssl)) {
- if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) {
- lwsl_info("%s: WANT_READ change_pollfd failed\n", __func__);
- return LWS_SSL_CAPABLE_ERROR;
- }
-
- lwsl_info("SSL_ERROR_WANT_READ\n");
- return LWS_SSL_CAPABLE_MORE_SERVICE_READ;
- }
- if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl)) {
- lwsl_debug("%s: WANT_WRITE\n", __func__);
-
- if (lws_change_pollfd(wsi, 0, LWS_POLLOUT)) {
- lwsl_info("%s: WANT_WRITE change_pollfd failed\n", __func__);
- return LWS_SSL_CAPABLE_ERROR;
- }
- return LWS_SSL_CAPABLE_MORE_SERVICE_WRITE;
- }
-
- return LWS_SSL_CAPABLE_ERROR;
-}
-
-#if defined(LWS_WITH_ACME)
-/*
- * mbedtls doesn't support SAN for cert creation. So we use a known-good
- * tls-sni-01 cert from OpenSSL that worked on Let's Encrypt, and just replace
- * the pubkey n part and the signature part.
- *
- * This will need redoing for tls-sni-02...
- */
-
-static uint8_t ss_cert_leadin[] = {
- 0x30, 0x82,
- 0x05, 0x56, /* total length: LEN1 (+2 / +3) (correct for 513 + 512)*/
-
- 0x30, 0x82, /* length: LEN2 (+6 / +7) (correct for 513) */
- 0x03, 0x3e,
-
- /* addition: v3 cert (+5 bytes)*/
- 0xa0, 0x03,
- 0x02, 0x01, 0x02,
-
- 0x02, 0x01, 0x01,
- 0x30, 0x0d, 0x06, 0x09, 0x2a,
- 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x3f,
- 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47,
- 0x42, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b,
- 0x73, 0x6f, 0x6d, 0x65, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x31,
- 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x74, 0x65,
- 0x6d, 0x70, 0x2e, 0x61, 0x63, 0x6d, 0x65, 0x2e, 0x69, 0x6e, 0x76, 0x61,
- 0x6c, 0x69, 0x64, 0x30, 0x1e, 0x17, 0x0d,
-
- /* from 2017-10-29 ... */
- 0x31, 0x37, 0x31, 0x30, 0x32, 0x39, 0x31, 0x31, 0x34, 0x39, 0x34, 0x35,
- 0x5a, 0x17, 0x0d,
-
- /* thru 2049-10-29 we immediately discard the private key, no worries */
- 0x34, 0x39, 0x31, 0x30, 0x32, 0x39, 0x31, 0x32, 0x34, 0x39, 0x34, 0x35,
- 0x5a,
-
- 0x30, 0x3f, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
- 0x02, 0x47, 0x42, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a,
- 0x0c, 0x0b, 0x73, 0x6f, 0x6d, 0x65, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e,
- 0x79, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11,
- 0x74, 0x65, 0x6d, 0x70, 0x2e, 0x61, 0x63, 0x6d, 0x65, 0x2e, 0x69, 0x6e,
- 0x76, 0x61, 0x6c, 0x69, 0x64, 0x30,
-
- 0x82,
- 0x02, 0x22, /* LEN3 (+C3 / C4) */
- 0x30, 0x0d, 0x06,
- 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00,
- 0x03,
-
- 0x82,
- 0x02, 0x0f, /* LEN4 (+D6 / D7) */
-
- 0x00, 0x30, 0x82,
-
- 0x02, 0x0a, /* LEN5 (+ DB / DC) */
-
- 0x02, 0x82,
-
- //0x02, 0x01, /* length of n in bytes (including leading 00 if any) */
- },
-
- /* 1 + (keybits / 8) bytes N */
-
- ss_cert_san_leadin[] = {
- /* e - fixed */
- 0x02, 0x03, 0x01, 0x00, 0x01,
-
- 0xa3, 0x5d, 0x30, 0x5b, 0x30, 0x59, 0x06, 0x03, 0x55, 0x1d,
- 0x11, 0x04, 0x52, 0x30, 0x50, /* <-- SAN length + 2 */
-
- 0x82, 0x4e, /* <-- SAN length */
- },
-
- /* 78 bytes of SAN (tls-sni-01)
- 0x61, 0x64, 0x34, 0x31, 0x61, 0x66, 0x62, 0x65, 0x30, 0x63, 0x61, 0x34,
- 0x36, 0x34, 0x32, 0x66, 0x30, 0x61, 0x34, 0x34, 0x39, 0x64, 0x39, 0x63,
- 0x61, 0x37, 0x36, 0x65, 0x62, 0x61, 0x61, 0x62, 0x2e, 0x32, 0x38, 0x39,
- 0x34, 0x64, 0x34, 0x31, 0x36, 0x63, 0x39, 0x38, 0x33, 0x66, 0x31, 0x32,
- 0x65, 0x64, 0x37, 0x33, 0x31, 0x61, 0x33, 0x30, 0x66, 0x35, 0x63, 0x34,
- 0x34, 0x37, 0x37, 0x66, 0x65, 0x2e, 0x61, 0x63, 0x6d, 0x65, 0x2e, 0x69,
- 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, */
-
- /* end of LEN2 area */
-
- ss_cert_sig_leadin[] = {
- /* it's saying that the signature is SHA256 + RSA */
- 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
- 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03,
-
- 0x82,
- 0x02, 0x01,
- 0x00,
- };
-
- /* (keybits / 8) bytes signature to end of LEN1 area */
-
-#define SAN_A_LENGTH 78
-
-LWS_VISIBLE int
-lws_tls_acme_sni_cert_create(struct lws_vhost *vhost, const char *san_a,
- const char *san_b)
-{
- int buflen = 0x560;
- uint8_t *buf = lws_malloc(buflen, "tmp cert buf"), *p = buf, *pkey_asn1;
- struct lws_genrsa_ctx ctx;
- struct lws_genrsa_elements el;
- uint8_t digest[32];
- struct lws_genhash_ctx hash_ctx;
- int pkey_asn1_len = 3 * 1024;
- int n, m, keybits = lws_plat_recommended_rsa_bits(), adj;
-
- if (!buf)
- return 1;
-
- n = lws_genrsa_new_keypair(vhost->context, &ctx, &el, keybits);
- if (n < 0) {
- lws_jwk_destroy_genrsa_elements(&el);
- goto bail1;
- }
-
- n = sizeof(ss_cert_leadin);
- memcpy(p, ss_cert_leadin, n);
- p += n;
-
- adj = (0x0556 - 0x401) + (keybits / 4) + 1;
- buf[2] = adj >> 8;
- buf[3] = adj & 0xff;
-
- adj = (0x033e - 0x201) + (keybits / 8) + 1;
- buf[6] = adj >> 8;
- buf[7] = adj & 0xff;
-
- adj = (0x0222 - 0x201) + (keybits / 8) + 1;
- buf[0xc3] = adj >> 8;
- buf[0xc4] = adj & 0xff;
-
- adj = (0x020f - 0x201) + (keybits / 8) + 1;
- buf[0xd6] = adj >> 8;
- buf[0xd7] = adj & 0xff;
-
- adj = (0x020a - 0x201) + (keybits / 8) + 1;
- buf[0xdb] = adj >> 8;
- buf[0xdc] = adj & 0xff;
-
- *p++ = ((keybits / 8) + 1) >> 8;
- *p++ = ((keybits / 8) + 1) & 0xff;
-
- /* we need to drop 1 + (keybits / 8) bytes of n in here, 00 + key */
-
- *p++ = 0x00;
- memcpy(p, el.e[JWK_KEY_N].buf, el.e[JWK_KEY_N].len);
- p += el.e[JWK_KEY_N].len;
-
- memcpy(p, ss_cert_san_leadin, sizeof(ss_cert_san_leadin));
- p += sizeof(ss_cert_san_leadin);
-
- /* drop in 78 bytes of san_a */
-
- memcpy(p, san_a, SAN_A_LENGTH);
- p += SAN_A_LENGTH;
- memcpy(p, ss_cert_sig_leadin, sizeof(ss_cert_sig_leadin));
-
- p[17] = ((keybits / 8) + 1) >> 8;
- p[18] = ((keybits / 8) + 1) & 0xff;
-
- p += sizeof(ss_cert_sig_leadin);
-
- /* hash the cert plaintext */
-
- if (lws_genhash_init(&hash_ctx, LWS_GENHASH_TYPE_SHA256))
- goto bail2;
-
- if (lws_genhash_update(&hash_ctx, buf, lws_ptr_diff(p, buf))) {
- lws_genhash_destroy(&hash_ctx, NULL);
-
- goto bail2;
- }
- if (lws_genhash_destroy(&hash_ctx, digest))
- goto bail2;
-
- /* sign the hash */
-
- n = lws_genrsa_public_sign(&ctx, digest, LWS_GENHASH_TYPE_SHA256, p,
- buflen - lws_ptr_diff(p, buf));
- if (n < 0)
- goto bail2;
- p += n;
-
- pkey_asn1 = lws_malloc(pkey_asn1_len, "mbed crt tmp");
- if (!pkey_asn1)
- goto bail2;
-
- m = lws_genrsa_render_pkey_asn1(&ctx, 1, pkey_asn1, pkey_asn1_len);
- if (m < 0) {
- lws_free(pkey_asn1);
- goto bail2;
- }
-
-// lwsl_hexdump_level(LLL_DEBUG, buf, lws_ptr_diff(p, buf));
- n = SSL_CTX_use_certificate_ASN1(vhost->tls.ssl_ctx,
- lws_ptr_diff(p, buf), buf);
- if (n != 1) {
- lws_free(pkey_asn1);
- lwsl_err("%s: generated cert failed to load 0x%x\n",
- __func__, -n);
- } else {
- //lwsl_debug("private key\n");
- //lwsl_hexdump_level(LLL_DEBUG, pkey_asn1, n);
-
- /* and to use our generated private key */
- n = SSL_CTX_use_PrivateKey_ASN1(0, vhost->tls.ssl_ctx, pkey_asn1, m);
- lws_free(pkey_asn1);
- if (n != 1) {
- lwsl_err("%s: SSL_CTX_use_PrivateKey_ASN1 failed\n",
- __func__);
- }
- }
-
- lws_genrsa_destroy(&ctx);
- lws_jwk_destroy_genrsa_elements(&el);
-
- lws_free(buf);
-
- return n != 1;
-
-bail2:
- lws_genrsa_destroy(&ctx);
- lws_jwk_destroy_genrsa_elements(&el);
-bail1:
- lws_free(buf);
-
- return -1;
-}
-
-void
-lws_tls_acme_sni_cert_destroy(struct lws_vhost *vhost)
-{
-}
-
-#if defined(LWS_WITH_JWS)
-static int
-_rngf(void *context, unsigned char *buf, size_t len)
-{
- if ((size_t)lws_get_random(context, buf, len) == len)
- return 0;
-
- return -1;
-}
-
-static const char *x5[] = { "C", "ST", "L", "O", "CN" };
-
-/*
- * CSR is output formatted as b64url(DER)
- * Private key is output as a PEM in memory
- */
-LWS_VISIBLE LWS_EXTERN int
-lws_tls_acme_sni_csr_create(struct lws_context *context, const char *elements[],
- uint8_t *dcsr, size_t csr_len, char **privkey_pem,
- size_t *privkey_len)
-{
- mbedtls_x509write_csr csr;
- mbedtls_pk_context mpk;
- int buf_size = 4096, n;
- char subject[200], *p = subject, *end = p + sizeof(subject) - 1;
- uint8_t *buf = malloc(buf_size); /* malloc because given to user code */
-
- if (!buf)
- return -1;
-
- mbedtls_x509write_csr_init(&csr);
-
- mbedtls_pk_init(&mpk);
- if (mbedtls_pk_setup(&mpk, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA))) {
- lwsl_notice("%s: pk_setup failed\n", __func__);
- goto fail;
- }
-
- n = mbedtls_rsa_gen_key(mbedtls_pk_rsa(mpk), _rngf, context,
- lws_plat_recommended_rsa_bits(), 65537);
- if (n) {
- lwsl_notice("%s: failed to generate keys\n", __func__);
-
- goto fail1;
- }
-
- /* subject must be formatted like "C=TW,O=warmcat,CN=myserver" */
-
- for (n = 0; n < (int)LWS_ARRAY_SIZE(x5); n++) {
- if (p != subject)
- *p++ = ',';
- if (elements[n])
- p += lws_snprintf(p, end - p, "%s=%s", x5[n],
- elements[n]);
- }
-
- if (mbedtls_x509write_csr_set_subject_name(&csr, subject))
- goto fail1;
-
- mbedtls_x509write_csr_set_key(&csr, &mpk);
- mbedtls_x509write_csr_set_md_alg(&csr, MBEDTLS_MD_SHA256);
-
- /*
- * data is written at the end of the buffer! Use the
- * return value to determine where you should start
- * using the buffer
- */
- n = mbedtls_x509write_csr_der(&csr, buf, buf_size, _rngf, context);
- if (n < 0) {
- lwsl_notice("%s: write csr der failed\n", __func__);
- goto fail1;
- }
-
- /* we have it in DER, we need it in b64URL */
-
- n = lws_jws_base64_enc((char *)(buf + buf_size) - n, n,
- (char *)dcsr, csr_len);
- if (n < 0)
- goto fail1;
-
- /*
- * okay, the CSR is done, last we need the private key in PEM
- * re-use the DER CSR buf as the result buffer since we cn do it in
- * one step
- */
-
- if (mbedtls_pk_write_key_pem(&mpk, buf, buf_size)) {
- lwsl_notice("write key pem failed\n");
- goto fail1;
- }
-
- *privkey_pem = (char *)buf;
- *privkey_len = strlen((const char *)buf);
-
- mbedtls_pk_free(&mpk);
- mbedtls_x509write_csr_free(&csr);
-
- return n;
-
-fail1:
- mbedtls_pk_free(&mpk);
-fail:
- mbedtls_x509write_csr_free(&csr);
- free(buf);
-
- return -1;
-}
-#endif
-#endif
diff --git a/thirdparty/libwebsockets/tls/mbedtls/ssl.c b/thirdparty/libwebsockets/tls/mbedtls/ssl.c
deleted file mode 100644
index f311ef50e3..0000000000
--- a/thirdparty/libwebsockets/tls/mbedtls/ssl.c
+++ /dev/null
@@ -1,518 +0,0 @@
-/*
- * libwebsockets - mbedTLS-specific lws apis
- *
- * Copyright (C) 2010-2017 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- */
-
-#include "core/private.h"
-#include <mbedtls/oid.h>
-
-void
-lws_ssl_elaborate_error(void)
-{
-}
-
-int
-lws_context_init_ssl_library(const struct lws_context_creation_info *info)
-{
- lwsl_info(" Compiled with MbedTLS support\n");
-
- if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT))
- lwsl_info(" SSL disabled: no LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT\n");
-
- return 0;
-}
-
-LWS_VISIBLE void
-lws_ssl_destroy(struct lws_vhost *vhost)
-{
- if (!lws_check_opt(vhost->context->options,
- LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT))
- return;
-
- if (vhost->tls.ssl_ctx)
- SSL_CTX_free(vhost->tls.ssl_ctx);
- if (!vhost->tls.user_supplied_ssl_ctx && vhost->tls.ssl_client_ctx)
- SSL_CTX_free(vhost->tls.ssl_client_ctx);
-
- if (vhost->tls.x509_client_CA)
- X509_free(vhost->tls.x509_client_CA);
-}
-
-LWS_VISIBLE int
-lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, int len)
-{
- struct lws_context *context = wsi->context;
- struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
- int n = 0, m;
-
- if (!wsi->tls.ssl)
- return lws_ssl_capable_read_no_ssl(wsi, buf, len);
-
- lws_stats_atomic_bump(context, pt, LWSSTATS_C_API_READ, 1);
-
- errno = 0;
- n = SSL_read(wsi->tls.ssl, buf, len);
-#if defined(LWS_WITH_ESP32)
- if (!n && errno == ENOTCONN) {
- lwsl_debug("%p: SSL_read ENOTCONN\n", wsi);
- return LWS_SSL_CAPABLE_ERROR;
- }
-#endif
-#if defined(LWS_WITH_STATS)
- if (!wsi->seen_rx) {
- lws_stats_atomic_bump(wsi->context, pt,
- LWSSTATS_MS_SSL_RX_DELAY,
- time_in_microseconds() - wsi->accept_start_us);
- lws_stats_atomic_bump(wsi->context, pt,
- LWSSTATS_C_SSL_CONNS_HAD_RX, 1);
- wsi->seen_rx = 1;
- }
-#endif
-
-
- lwsl_debug("%p: SSL_read says %d\n", wsi, n);
- /* manpage: returning 0 means connection shut down */
- if (!n) {
- wsi->socket_is_permanently_unusable = 1;
-
- return LWS_SSL_CAPABLE_ERROR;
- }
-
- if (n < 0) {
- m = SSL_get_error(wsi->tls.ssl, n);
- lwsl_debug("%p: ssl err %d errno %d\n", wsi, m, errno);
- if (m == SSL_ERROR_ZERO_RETURN ||
- m == SSL_ERROR_SYSCALL)
- return LWS_SSL_CAPABLE_ERROR;
-
- if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->tls.ssl)) {
- lwsl_debug("%s: WANT_READ\n", __func__);
- lwsl_debug("%p: LWS_SSL_CAPABLE_MORE_SERVICE\n", wsi);
- return LWS_SSL_CAPABLE_MORE_SERVICE;
- }
- if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl)) {
- lwsl_debug("%s: WANT_WRITE\n", __func__);
- lwsl_debug("%p: LWS_SSL_CAPABLE_MORE_SERVICE\n", wsi);
- return LWS_SSL_CAPABLE_MORE_SERVICE;
- }
- wsi->socket_is_permanently_unusable = 1;
-
- return LWS_SSL_CAPABLE_ERROR;
- }
-
- lws_stats_atomic_bump(context, pt, LWSSTATS_B_READ, n);
-
- if (wsi->vhost)
- wsi->vhost->conn_stats.rx += n;
-
- /*
- * if it was our buffer that limited what we read,
- * check if SSL has additional data pending inside SSL buffers.
- *
- * Because these won't signal at the network layer with POLLIN
- * and if we don't realize, this data will sit there forever
- */
- if (n != len)
- goto bail;
- if (!wsi->tls.ssl)
- goto bail;
-
- if (!SSL_pending(wsi->tls.ssl))
- goto bail;
-
- if (wsi->tls.pending_read_list_next)
- return n;
- if (wsi->tls.pending_read_list_prev)
- return n;
- if (pt->tls.pending_read_list == wsi)
- return n;
-
- /* add us to the linked list of guys with pending ssl */
- if (pt->tls.pending_read_list)
- pt->tls.pending_read_list->tls.pending_read_list_prev = wsi;
-
- wsi->tls.pending_read_list_next = pt->tls.pending_read_list;
- wsi->tls.pending_read_list_prev = NULL;
- pt->tls.pending_read_list = wsi;
-
- return n;
-bail:
- lws_ssl_remove_wsi_from_buffered_list(wsi);
-
- return n;
-}
-
-LWS_VISIBLE int
-lws_ssl_pending(struct lws *wsi)
-{
- if (!wsi->tls.ssl)
- return 0;
-
- return SSL_pending(wsi->tls.ssl);
-}
-
-LWS_VISIBLE int
-lws_ssl_capable_write(struct lws *wsi, unsigned char *buf, int len)
-{
- int n, m;
-
- if (!wsi->tls.ssl)
- return lws_ssl_capable_write_no_ssl(wsi, buf, len);
-
- n = SSL_write(wsi->tls.ssl, buf, len);
- if (n > 0)
- return n;
-
- m = SSL_get_error(wsi->tls.ssl, n);
- if (m != SSL_ERROR_SYSCALL) {
- if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->tls.ssl)) {
- lwsl_notice("%s: want read\n", __func__);
-
- return LWS_SSL_CAPABLE_MORE_SERVICE;
- }
-
- if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl)) {
- lws_set_blocking_send(wsi);
- lwsl_notice("%s: want write\n", __func__);
-
- return LWS_SSL_CAPABLE_MORE_SERVICE;
- }
- }
-
- lwsl_debug("%s failed: %d\n",__func__, m);
- wsi->socket_is_permanently_unusable = 1;
-
- return LWS_SSL_CAPABLE_ERROR;
-}
-
-int openssl_SSL_CTX_private_data_index;
-
-void
-lws_ssl_info_callback(const SSL *ssl, int where, int ret)
-{
- struct lws *wsi;
- struct lws_context *context;
- struct lws_ssl_info si;
-
- context = (struct lws_context *)SSL_CTX_get_ex_data(
- SSL_get_SSL_CTX(ssl),
- openssl_SSL_CTX_private_data_index);
- if (!context)
- return;
- wsi = wsi_from_fd(context, SSL_get_fd(ssl));
- if (!wsi)
- return;
-
- if (!(where & wsi->vhost->tls.ssl_info_event_mask))
- return;
-
- si.where = where;
- si.ret = ret;
-
- if (user_callback_handle_rxflow(wsi->protocol->callback,
- wsi, LWS_CALLBACK_SSL_INFO,
- wsi->user_space, &si, 0))
- lws_set_timeout(wsi, PENDING_TIMEOUT_KILLED_BY_SSL_INFO, -1);
-}
-
-
-LWS_VISIBLE int
-lws_ssl_close(struct lws *wsi)
-{
- lws_sockfd_type n;
-
- if (!wsi->tls.ssl)
- return 0; /* not handled */
-
-#if defined (LWS_HAVE_SSL_SET_INFO_CALLBACK)
- /* kill ssl callbacks, becausse we will remove the fd from the
- * table linking it to the wsi
- */
- if (wsi->vhost->tls.ssl_info_event_mask)
- SSL_set_info_callback(wsi->tls.ssl, NULL);
-#endif
-
- n = SSL_get_fd(wsi->tls.ssl);
- if (!wsi->socket_is_permanently_unusable)
- SSL_shutdown(wsi->tls.ssl);
- compatible_close(n);
- SSL_free(wsi->tls.ssl);
- wsi->tls.ssl = NULL;
-
- if (!lwsi_role_client(wsi) &&
- wsi->context->simultaneous_ssl_restriction &&
- wsi->context->simultaneous_ssl-- ==
- wsi->context->simultaneous_ssl_restriction)
- /* we made space and can do an accept */
- lws_gate_accepts(wsi->context, 1);
-
-#if defined(LWS_WITH_STATS)
- wsi->context->updated = 1;
-#endif
-
- return 1; /* handled */
-}
-
-void
-lws_ssl_SSL_CTX_destroy(struct lws_vhost *vhost)
-{
- if (vhost->tls.ssl_ctx)
- SSL_CTX_free(vhost->tls.ssl_ctx);
-
- if (!vhost->tls.user_supplied_ssl_ctx && vhost->tls.ssl_client_ctx)
- SSL_CTX_free(vhost->tls.ssl_client_ctx);
-#if defined(LWS_WITH_ACME)
- lws_tls_acme_sni_cert_destroy(vhost);
-#endif
-}
-
-void
-lws_ssl_context_destroy(struct lws_context *context)
-{
-}
-
-lws_tls_ctx *
-lws_tls_ctx_from_wsi(struct lws *wsi)
-{
- if (!wsi->tls.ssl)
- return NULL;
-
- return SSL_get_SSL_CTX(wsi->tls.ssl);
-}
-
-enum lws_ssl_capable_status
-__lws_tls_shutdown(struct lws *wsi)
-{
- int n = SSL_shutdown(wsi->tls.ssl);
-
- lwsl_debug("SSL_shutdown=%d for fd %d\n", n, wsi->desc.sockfd);
-
- switch (n) {
- case 1: /* successful completion */
- n = shutdown(wsi->desc.sockfd, SHUT_WR);
- return LWS_SSL_CAPABLE_DONE;
-
- case 0: /* needs a retry */
- __lws_change_pollfd(wsi, 0, LWS_POLLIN);
- return LWS_SSL_CAPABLE_MORE_SERVICE;
-
- default: /* fatal error, or WANT */
- n = SSL_get_error(wsi->tls.ssl, n);
- if (n != SSL_ERROR_SYSCALL && n != SSL_ERROR_SSL) {
- if (SSL_want_read(wsi->tls.ssl)) {
- lwsl_debug("(wants read)\n");
- __lws_change_pollfd(wsi, 0, LWS_POLLIN);
- return LWS_SSL_CAPABLE_MORE_SERVICE_READ;
- }
- if (SSL_want_write(wsi->tls.ssl)) {
- lwsl_debug("(wants write)\n");
- __lws_change_pollfd(wsi, 0, LWS_POLLOUT);
- return LWS_SSL_CAPABLE_MORE_SERVICE_WRITE;
- }
- }
- return LWS_SSL_CAPABLE_ERROR;
- }
-}
-
-static time_t
-lws_tls_mbedtls_time_to_unix(mbedtls_x509_time *xtime)
-{
- struct tm t;
-
- if (!xtime || !xtime->year || xtime->year < 0)
- return (time_t)(long long)-1;
-
- memset(&t, 0, sizeof(t));
-
- t.tm_year = xtime->year - 1900;
- t.tm_mon = xtime->mon - 1; /* mbedtls months are 1+, tm are 0+ */
- t.tm_mday = xtime->day - 1; /* mbedtls days are 1+, tm are 0+ */
- t.tm_hour = xtime->hour;
- t.tm_min = xtime->min;
- t.tm_sec = xtime->sec;
- t.tm_isdst = -1;
-
- return mktime(&t);
-}
-
-static int
-lws_tls_mbedtls_get_x509_name(mbedtls_x509_name *name,
- union lws_tls_cert_info_results *buf, size_t len)
-{
- while (name) {
- if (MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid)) {
- name = name->next;
- continue;
- }
-
- if (len - 1 < name->val.len)
- return -1;
-
- memcpy(&buf->ns.name[0], name->val.p, name->val.len);
- buf->ns.name[name->val.len] = '\0';
- buf->ns.len = name->val.len;
-
- return 0;
- }
-
- return -1;
-}
-
-static int
-lws_tls_mbedtls_cert_info(mbedtls_x509_crt *x509, enum lws_tls_cert_info type,
- union lws_tls_cert_info_results *buf, size_t len)
-{
- if (!x509)
- return -1;
-
- switch (type) {
- case LWS_TLS_CERT_INFO_VALIDITY_FROM:
- buf->time = lws_tls_mbedtls_time_to_unix(&x509->valid_from);
- if (buf->time == (time_t)(long long)-1)
- return -1;
- break;
-
- case LWS_TLS_CERT_INFO_VALIDITY_TO:
- buf->time = lws_tls_mbedtls_time_to_unix(&x509->valid_to);
- if (buf->time == (time_t)(long long)-1)
- return -1;
- break;
-
- case LWS_TLS_CERT_INFO_COMMON_NAME:
- return lws_tls_mbedtls_get_x509_name(&x509->subject, buf, len);
-
- case LWS_TLS_CERT_INFO_ISSUER_NAME:
- return lws_tls_mbedtls_get_x509_name(&x509->issuer, buf, len);
-
- case LWS_TLS_CERT_INFO_USAGE:
- buf->usage = x509->key_usage;
- break;
-
- case LWS_TLS_CERT_INFO_OPAQUE_PUBLIC_KEY:
- {
- char *p = buf->ns.name;
- size_t r = len, u;
-
- switch (mbedtls_pk_get_type(&x509->pk)) {
- case MBEDTLS_PK_RSA:
- {
- mbedtls_rsa_context *rsa = mbedtls_pk_rsa(x509->pk);
-
- if (mbedtls_mpi_write_string(&rsa->N, 16, p, r, &u))
- return -1;
- r -= u;
- p += u;
- if (mbedtls_mpi_write_string(&rsa->E, 16, p, r, &u))
- return -1;
-
- p += u;
- buf->ns.len = lws_ptr_diff(p, buf->ns.name);
- break;
- }
- case MBEDTLS_PK_ECKEY:
- {
- mbedtls_ecp_keypair *ecp = mbedtls_pk_ec(x509->pk);
-
- if (mbedtls_mpi_write_string(&ecp->Q.X, 16, p, r, &u))
- return -1;
- r -= u;
- p += u;
- if (mbedtls_mpi_write_string(&ecp->Q.Y, 16, p, r, &u))
- return -1;
- r -= u;
- p += u;
- if (mbedtls_mpi_write_string(&ecp->Q.Z, 16, p, r, &u))
- return -1;
- p += u;
- buf->ns.len = lws_ptr_diff(p, buf->ns.name);
- break;
- }
- default:
- lwsl_notice("%s: x509 has unsupported pubkey type %d\n",
- __func__,
- mbedtls_pk_get_type(&x509->pk));
-
- return -1;
- }
- break;
- }
-
- default:
- return -1;
- }
-
- return 0;
-}
-
-LWS_VISIBLE LWS_EXTERN int
-lws_tls_vhost_cert_info(struct lws_vhost *vhost, enum lws_tls_cert_info type,
- union lws_tls_cert_info_results *buf, size_t len)
-{
- mbedtls_x509_crt *x509 = ssl_ctx_get_mbedtls_x509_crt(vhost->tls.ssl_ctx);
-
- return lws_tls_mbedtls_cert_info(x509, type, buf, len);
-}
-
-LWS_VISIBLE int
-lws_tls_peer_cert_info(struct lws *wsi, enum lws_tls_cert_info type,
- union lws_tls_cert_info_results *buf, size_t len)
-{
- mbedtls_x509_crt *x509;
-
- wsi = lws_get_network_wsi(wsi);
-
- x509 = ssl_get_peer_mbedtls_x509_crt(wsi->tls.ssl);
-
- if (!x509)
- return -1;
-
- switch (type) {
- case LWS_TLS_CERT_INFO_VERIFIED:
- buf->verified = SSL_get_verify_result(wsi->tls.ssl) == X509_V_OK;
- return 0;
- default:
- return lws_tls_mbedtls_cert_info(x509, type, buf, len);
- }
-
- return -1;
-}
-
-static int
-tops_fake_POLLIN_for_buffered_mbedtls(struct lws_context_per_thread *pt)
-{
- return lws_tls_fake_POLLIN_for_buffered(pt);
-}
-
-static int
-tops_periodic_housekeeping_mbedtls(struct lws_context *context, time_t now)
-{
- int n;
-
- n = lws_compare_time_t(context, now, context->tls.last_cert_check_s);
- if ((!context->tls.last_cert_check_s || n > (24 * 60 * 60)) &&
- !lws_tls_check_all_cert_lifetimes(context))
- context->tls.last_cert_check_s = now;
-
- return 0;
-}
-
-const struct lws_tls_ops tls_ops_mbedtls = {
- /* fake_POLLIN_for_buffered */ tops_fake_POLLIN_for_buffered_mbedtls,
- /* periodic_housekeeping */ tops_periodic_housekeeping_mbedtls,
-};
diff --git a/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl3.h b/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl3.h
deleted file mode 100644
index 007b392f3e..0000000000
--- a/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl3.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef _SSL3_H_
-#define _SSL3_H_
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-# define SSL3_AD_CLOSE_NOTIFY 0
-# define SSL3_AD_UNEXPECTED_MESSAGE 10/* fatal */
-# define SSL3_AD_BAD_RECORD_MAC 20/* fatal */
-# define SSL3_AD_DECOMPRESSION_FAILURE 30/* fatal */
-# define SSL3_AD_HANDSHAKE_FAILURE 40/* fatal */
-# define SSL3_AD_NO_CERTIFICATE 41
-# define SSL3_AD_BAD_CERTIFICATE 42
-# define SSL3_AD_UNSUPPORTED_CERTIFICATE 43
-# define SSL3_AD_CERTIFICATE_REVOKED 44
-# define SSL3_AD_CERTIFICATE_EXPIRED 45
-# define SSL3_AD_CERTIFICATE_UNKNOWN 46
-# define SSL3_AD_ILLEGAL_PARAMETER 47/* fatal */
-
-# define SSL3_AL_WARNING 1
-# define SSL3_AL_FATAL 2
-
-#define SSL3_VERSION 0x0300
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_cert.h b/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_cert.h
deleted file mode 100644
index 86cf31ad51..0000000000
--- a/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_cert.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef _SSL_CERT_H_
-#define _SSL_CERT_H_
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-#include "ssl_types.h"
-
-/**
- * @brief create a certification object include private key object according to input certification
- *
- * @param ic - input certification point
- *
- * @return certification object point
- */
-CERT *__ssl_cert_new(CERT *ic);
-
-/**
- * @brief create a certification object include private key object
- *
- * @param none
- *
- * @return certification object point
- */
-CERT* ssl_cert_new(void);
-
-/**
- * @brief free a certification object
- *
- * @param cert - certification object point
- *
- * @return none
- */
-void ssl_cert_free(CERT *cert);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_code.h b/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_code.h
deleted file mode 100644
index 80fdbb20f3..0000000000
--- a/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_code.h
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef _SSL_CODE_H_
-#define _SSL_CODE_H_
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-#include "ssl3.h"
-#include "tls1.h"
-#include "x509_vfy.h"
-
-/* Used in SSL_set_shutdown()/SSL_get_shutdown(); */
-# define SSL_SENT_SHUTDOWN 1
-# define SSL_RECEIVED_SHUTDOWN 2
-
-# define SSL_VERIFY_NONE 0x00
-# define SSL_VERIFY_PEER 0x01
-# define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02
-# define SSL_VERIFY_CLIENT_ONCE 0x04
-
-/*
- * The following 3 states are kept in ssl->rlayer.rstate when reads fail, you
- * should not need these
- */
-# define SSL_ST_READ_HEADER 0xF0
-# define SSL_ST_READ_BODY 0xF1
-# define SSL_ST_READ_DONE 0xF2
-
-# define SSL_NOTHING 1
-# define SSL_WRITING 2
-# define SSL_READING 3
-# define SSL_X509_LOOKUP 4
-# define SSL_ASYNC_PAUSED 5
-# define SSL_ASYNC_NO_JOBS 6
-
-
-# define SSL_ERROR_NONE 0
-# define SSL_ERROR_SSL 1
-# define SSL_ERROR_WANT_READ 2
-# define SSL_ERROR_WANT_WRITE 3
-# define SSL_ERROR_WANT_X509_LOOKUP 4
-# define SSL_ERROR_SYSCALL 5/* look at error stack/return value/errno */
-# define SSL_ERROR_ZERO_RETURN 6
-# define SSL_ERROR_WANT_CONNECT 7
-# define SSL_ERROR_WANT_ACCEPT 8
-# define SSL_ERROR_WANT_ASYNC 9
-# define SSL_ERROR_WANT_ASYNC_JOB 10
-
-/* Message flow states */
-typedef enum {
- /* No handshake in progress */
- MSG_FLOW_UNINITED,
- /* A permanent error with this connection */
- MSG_FLOW_ERROR,
- /* We are about to renegotiate */
- MSG_FLOW_RENEGOTIATE,
- /* We are reading messages */
- MSG_FLOW_READING,
- /* We are writing messages */
- MSG_FLOW_WRITING,
- /* Handshake has finished */
- MSG_FLOW_FINISHED
-} MSG_FLOW_STATE;
-
-/* SSL subsystem states */
-typedef enum {
- TLS_ST_BEFORE,
- TLS_ST_OK,
- DTLS_ST_CR_HELLO_VERIFY_REQUEST,
- TLS_ST_CR_SRVR_HELLO,
- TLS_ST_CR_CERT,
- TLS_ST_CR_CERT_STATUS,
- TLS_ST_CR_KEY_EXCH,
- TLS_ST_CR_CERT_REQ,
- TLS_ST_CR_SRVR_DONE,
- TLS_ST_CR_SESSION_TICKET,
- TLS_ST_CR_CHANGE,
- TLS_ST_CR_FINISHED,
- TLS_ST_CW_CLNT_HELLO,
- TLS_ST_CW_CERT,
- TLS_ST_CW_KEY_EXCH,
- TLS_ST_CW_CERT_VRFY,
- TLS_ST_CW_CHANGE,
- TLS_ST_CW_NEXT_PROTO,
- TLS_ST_CW_FINISHED,
- TLS_ST_SW_HELLO_REQ,
- TLS_ST_SR_CLNT_HELLO,
- DTLS_ST_SW_HELLO_VERIFY_REQUEST,
- TLS_ST_SW_SRVR_HELLO,
- TLS_ST_SW_CERT,
- TLS_ST_SW_KEY_EXCH,
- TLS_ST_SW_CERT_REQ,
- TLS_ST_SW_SRVR_DONE,
- TLS_ST_SR_CERT,
- TLS_ST_SR_KEY_EXCH,
- TLS_ST_SR_CERT_VRFY,
- TLS_ST_SR_NEXT_PROTO,
- TLS_ST_SR_CHANGE,
- TLS_ST_SR_FINISHED,
- TLS_ST_SW_SESSION_TICKET,
- TLS_ST_SW_CERT_STATUS,
- TLS_ST_SW_CHANGE,
- TLS_ST_SW_FINISHED
-} OSSL_HANDSHAKE_STATE;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_dbg.h b/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_dbg.h
deleted file mode 100644
index ad32cb92ff..0000000000
--- a/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_dbg.h
+++ /dev/null
@@ -1,190 +0,0 @@
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef _SSL_DEBUG_H_
-#define _SSL_DEBUG_H_
-
-#include "platform/ssl_port.h"
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-#ifdef CONFIG_OPENSSL_DEBUG_LEVEL
- #define SSL_DEBUG_LEVEL CONFIG_OPENSSL_DEBUG_LEVEL
-#else
- #define SSL_DEBUG_LEVEL 0
-#endif
-
-#define SSL_DEBUG_ON (SSL_DEBUG_LEVEL + 1)
-#define SSL_DEBUG_OFF (SSL_DEBUG_LEVEL - 1)
-
-#ifdef CONFIG_OPENSSL_DEBUG
- #ifndef SSL_DEBUG_LOG
- #error "SSL_DEBUG_LOG is not defined"
- #endif
-
- #ifndef SSL_DEBUG_FL
- #define SSL_DEBUG_FL "\n"
- #endif
-
- #define SSL_SHOW_LOCATION() \
- SSL_DEBUG_LOG("SSL assert : %s %d\n", \
- __FILE__, __LINE__)
-
- #define SSL_DEBUG(level, fmt, ...) \
- { \
- if (level > SSL_DEBUG_LEVEL) { \
- SSL_DEBUG_LOG(fmt SSL_DEBUG_FL, ##__VA_ARGS__); \
- } \
- }
-#else /* CONFIG_OPENSSL_DEBUG */
- #define SSL_SHOW_LOCATION()
-
- #define SSL_DEBUG(level, fmt, ...)
-#endif /* CONFIG_OPENSSL_DEBUG */
-
-/**
- * OpenSSL assert function
- *
- * if select "CONFIG_OPENSSL_ASSERT_DEBUG", SSL_ASSERT* will show error file name and line
- * if select "CONFIG_OPENSSL_ASSERT_EXIT", SSL_ASSERT* will just return error code.
- * if select "CONFIG_OPENSSL_ASSERT_DEBUG_EXIT" SSL_ASSERT* will show error file name and line,
- * then return error code.
- * if select "CONFIG_OPENSSL_ASSERT_DEBUG_BLOCK", SSL_ASSERT* will show error file name and line,
- * then block here with "while (1)"
- *
- * SSL_ASSERT1 may will return "-1", so function's return argument is integer.
- * SSL_ASSERT2 may will return "NULL", so function's return argument is a point.
- * SSL_ASSERT2 may will return nothing, so function's return argument is "void".
- */
-#if defined(CONFIG_OPENSSL_ASSERT_DEBUG)
- #define SSL_ASSERT1(s) \
- { \
- if (!(s)) { \
- SSL_SHOW_LOCATION(); \
- } \
- }
-
- #define SSL_ASSERT2(s) \
- { \
- if (!(s)) { \
- SSL_SHOW_LOCATION(); \
- } \
- }
-
- #define SSL_ASSERT3(s) \
- { \
- if (!(s)) { \
- SSL_SHOW_LOCATION(); \
- } \
- }
-#elif defined(CONFIG_OPENSSL_ASSERT_EXIT)
- #define SSL_ASSERT1(s) \
- { \
- if (!(s)) { \
- return -1; \
- } \
- }
-
- #define SSL_ASSERT2(s) \
- { \
- if (!(s)) { \
- return NULL; \
- } \
- }
-
- #define SSL_ASSERT3(s) \
- { \
- if (!(s)) { \
- return ; \
- } \
- }
-#elif defined(CONFIG_OPENSSL_ASSERT_DEBUG_EXIT)
- #define SSL_ASSERT1(s) \
- { \
- if (!(s)) { \
- SSL_SHOW_LOCATION(); \
- return -1; \
- } \
- }
-
- #define SSL_ASSERT2(s) \
- { \
- if (!(s)) { \
- SSL_SHOW_LOCATION(); \
- return NULL; \
- } \
- }
-
- #define SSL_ASSERT3(s) \
- { \
- if (!(s)) { \
- SSL_SHOW_LOCATION(); \
- return ; \
- } \
- }
-#elif defined(CONFIG_OPENSSL_ASSERT_DEBUG_BLOCK)
- #define SSL_ASSERT1(s) \
- { \
- if (!(s)) { \
- SSL_SHOW_LOCATION(); \
- while (1); \
- } \
- }
-
- #define SSL_ASSERT2(s) \
- { \
- if (!(s)) { \
- SSL_SHOW_LOCATION(); \
- while (1); \
- } \
- }
-
- #define SSL_ASSERT3(s) \
- { \
- if (!(s)) { \
- SSL_SHOW_LOCATION(); \
- while (1); \
- } \
- }
-#else
- #define SSL_ASSERT1(s)
- #define SSL_ASSERT2(s)
- #define SSL_ASSERT3(s)
-#endif
-
-#define SSL_PLATFORM_DEBUG_LEVEL SSL_DEBUG_OFF
-#define SSL_PLATFORM_ERROR_LEVEL SSL_DEBUG_ON
-
-#define SSL_CERT_DEBUG_LEVEL SSL_DEBUG_OFF
-#define SSL_CERT_ERROR_LEVEL SSL_DEBUG_ON
-
-#define SSL_PKEY_DEBUG_LEVEL SSL_DEBUG_OFF
-#define SSL_PKEY_ERROR_LEVEL SSL_DEBUG_ON
-
-#define SSL_X509_DEBUG_LEVEL SSL_DEBUG_OFF
-#define SSL_X509_ERROR_LEVEL SSL_DEBUG_ON
-
-#define SSL_LIB_DEBUG_LEVEL SSL_DEBUG_OFF
-#define SSL_LIB_ERROR_LEVEL SSL_DEBUG_ON
-
-#define SSL_STACK_DEBUG_LEVEL SSL_DEBUG_OFF
-#define SSL_STACK_ERROR_LEVEL SSL_DEBUG_ON
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif
diff --git a/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_lib.h b/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_lib.h
deleted file mode 100644
index 42b2de7501..0000000000
--- a/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_lib.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef _SSL_LIB_H_
-#define _SSL_LIB_H_
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-#include "ssl_types.h"
-
- void _ssl_set_alpn_list(const SSL *ssl);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_methods.h b/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_methods.h
deleted file mode 100644
index cd2f8c0533..0000000000
--- a/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_methods.h
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef _SSL_METHODS_H_
-#define _SSL_METHODS_H_
-
-#include "ssl_types.h"
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-/**
- * TLS method function implement
- */
-#define IMPLEMENT_TLS_METHOD_FUNC(func_name, \
- new, free, \
- handshake, shutdown, clear, \
- read, send, pending, \
- set_fd, get_fd, \
- set_bufflen, \
- get_verify_result, \
- get_state) \
- static const SSL_METHOD_FUNC func_name LOCAL_ATRR = { \
- new, \
- free, \
- handshake, \
- shutdown, \
- clear, \
- read, \
- send, \
- pending, \
- set_fd, \
- get_fd, \
- set_bufflen, \
- get_verify_result, \
- get_state \
- };
-
-#define IMPLEMENT_TLS_METHOD(ver, mode, fun, func_name) \
- const SSL_METHOD* func_name(void) { \
- static const SSL_METHOD func_name##_data LOCAL_ATRR = { \
- ver, \
- mode, \
- &(fun), \
- }; \
- return &func_name##_data; \
- }
-
-#define IMPLEMENT_SSL_METHOD(ver, mode, fun, func_name) \
- const SSL_METHOD* func_name(void) { \
- static const SSL_METHOD func_name##_data LOCAL_ATRR = { \
- ver, \
- mode, \
- &(fun), \
- }; \
- return &func_name##_data; \
- }
-
-#define IMPLEMENT_X509_METHOD(func_name, \
- new, \
- free, \
- load, \
- show_info) \
- const X509_METHOD* func_name(void) { \
- static const X509_METHOD func_name##_data LOCAL_ATRR = { \
- new, \
- free, \
- load, \
- show_info \
- }; \
- return &func_name##_data; \
- }
-
-#define IMPLEMENT_PKEY_METHOD(func_name, \
- new, \
- free, \
- load) \
- const PKEY_METHOD* func_name(void) { \
- static const PKEY_METHOD func_name##_data LOCAL_ATRR = { \
- new, \
- free, \
- load \
- }; \
- return &func_name##_data; \
- }
-
-/**
- * @brief get X509 object method
- *
- * @param none
- *
- * @return X509 object method point
- */
-const X509_METHOD* X509_method(void);
-
-/**
- * @brief get private key object method
- *
- * @param none
- *
- * @return private key object method point
- */
-const PKEY_METHOD* EVP_PKEY_method(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_pkey.h b/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_pkey.h
deleted file mode 100644
index e790fcc995..0000000000
--- a/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_pkey.h
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef _SSL_PKEY_H_
-#define _SSL_PKEY_H_
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-#include "ssl_types.h"
-
-/**
- * @brief create a private key object according to input private key
- *
- * @param ipk - input private key point
- *
- * @return new private key object point
- */
-EVP_PKEY* __EVP_PKEY_new(EVP_PKEY *ipk);
-
-/**
- * @brief create a private key object
- *
- * @param none
- *
- * @return private key object point
- */
-EVP_PKEY* EVP_PKEY_new(void);
-
-/**
- * @brief load a character key context into system context. If '*a' is pointed to the
- * private key, then load key into it. Or create a new private key object
- *
- * @param type - private key type
- * @param a - a point pointed to a private key point
- * @param pp - a point pointed to the key context memory point
- * @param length - key bytes
- *
- * @return private key object point
- */
-EVP_PKEY* d2i_PrivateKey(int type,
- EVP_PKEY **a,
- const unsigned char **pp,
- long length);
-
-/**
- * @brief free a private key object
- *
- * @param pkey - private key object point
- *
- * @return none
- */
-void EVP_PKEY_free(EVP_PKEY *x);
-
-/**
- * @brief load private key into the SSL
- *
- * @param type - private key type
- * @param ssl - SSL point
- * @param len - data bytes
- * @param d - data point
- *
- * @return result
- * 0 : failed
- * 1 : OK
- */
- int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const unsigned char *d, long len);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_stack.h b/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_stack.h
deleted file mode 100644
index 7a7051a026..0000000000
--- a/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_stack.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#ifndef _SSL_STACK_H_
-#define _SSL_STACK_H_
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-#include "ssl_types.h"
-
-#define STACK_OF(type) struct stack_st_##type
-
-#define SKM_DEFINE_STACK_OF(t1, t2, t3) \
- STACK_OF(t1); \
- static ossl_inline STACK_OF(t1) *sk_##t1##_new_null(void) \
- { \
- return (STACK_OF(t1) *)OPENSSL_sk_new_null(); \
- } \
-
-#define DEFINE_STACK_OF(t) SKM_DEFINE_STACK_OF(t, t, t)
-
-/**
- * @brief create a openssl stack object
- *
- * @param c - stack function
- *
- * @return openssl stack object point
- */
-OPENSSL_STACK* OPENSSL_sk_new(OPENSSL_sk_compfunc c);
-
-/**
- * @brief create a NULL function openssl stack object
- *
- * @param none
- *
- * @return openssl stack object point
- */
-OPENSSL_STACK *OPENSSL_sk_new_null(void);
-
-/**
- * @brief free openssl stack object
- *
- * @param openssl stack object point
- *
- * @return none
- */
-void OPENSSL_sk_free(OPENSSL_STACK *stack);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_types.h b/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_types.h
deleted file mode 100644
index 68ac748a28..0000000000
--- a/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_types.h
+++ /dev/null
@@ -1,303 +0,0 @@
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef _SSL_TYPES_H_
-#define _SSL_TYPES_H_
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-#include <lws_config.h>
-#if defined(LWS_WITH_ESP32)
-#undef MBEDTLS_CONFIG_FILE
-#define MBEDTLS_CONFIG_FILE <mbedtls/esp_config.h>
-#endif
-
-#include "ssl_code.h"
-
-typedef void SSL_CIPHER;
-
-typedef void X509_STORE_CTX;
-typedef void X509_STORE;
-
-typedef void RSA;
-
-typedef void STACK;
-typedef void BIO;
-
-#if defined(WIN32) || defined(_WIN32)
-#define ossl_inline __inline
-#else
-#define ossl_inline inline
-#endif
-
-#define SSL_METHOD_CALL(f, s, ...) s->method->func->ssl_##f(s, ##__VA_ARGS__)
-#define X509_METHOD_CALL(f, x, ...) x->method->x509_##f(x, ##__VA_ARGS__)
-#define EVP_PKEY_METHOD_CALL(f, k, ...) k->method->pkey_##f(k, ##__VA_ARGS__)
-
-typedef int (*OPENSSL_sk_compfunc)(const void *, const void *);
-
-struct stack_st;
-typedef struct stack_st OPENSSL_STACK;
-
-struct ssl_method_st;
-typedef struct ssl_method_st SSL_METHOD;
-
-struct ssl_method_func_st;
-typedef struct ssl_method_func_st SSL_METHOD_FUNC;
-
-struct record_layer_st;
-typedef struct record_layer_st RECORD_LAYER;
-
-struct ossl_statem_st;
-typedef struct ossl_statem_st OSSL_STATEM;
-
-struct ssl_session_st;
-typedef struct ssl_session_st SSL_SESSION;
-
-struct ssl_ctx_st;
-typedef struct ssl_ctx_st SSL_CTX;
-
-struct ssl_st;
-typedef struct ssl_st SSL;
-
-struct cert_st;
-typedef struct cert_st CERT;
-
-struct x509_st;
-typedef struct x509_st X509;
-
-struct X509_VERIFY_PARAM_st;
-typedef struct X509_VERIFY_PARAM_st X509_VERIFY_PARAM;
-
-struct evp_pkey_st;
-typedef struct evp_pkey_st EVP_PKEY;
-
-struct x509_method_st;
-typedef struct x509_method_st X509_METHOD;
-
-struct pkey_method_st;
-typedef struct pkey_method_st PKEY_METHOD;
-
-struct stack_st {
-
- char **data;
-
- int num_alloc;
-
- OPENSSL_sk_compfunc c;
-};
-
-struct evp_pkey_st {
-
- void *pkey_pm;
-
- const PKEY_METHOD *method;
-};
-
-struct x509_st {
-
- /* X509 certification platform private point */
- void *x509_pm;
-
- const X509_METHOD *method;
-};
-
-struct cert_st {
-
- int sec_level;
-
- X509 *x509;
-
- EVP_PKEY *pkey;
-
-};
-
-struct ossl_statem_st {
-
- MSG_FLOW_STATE state;
-
- int hand_state;
-};
-
-struct record_layer_st {
-
- int rstate;
-
- int read_ahead;
-};
-
-struct ssl_session_st {
-
- long timeout;
-
- long time;
-
- X509 *peer;
-};
-
-struct X509_VERIFY_PARAM_st {
-
- int depth;
-
-};
-
-typedef int (*next_proto_cb)(SSL *ssl, unsigned char **out,
- unsigned char *outlen, const unsigned char *in,
- unsigned int inlen, void *arg);
-
-struct ssl_ctx_st
-{
- int version;
-
- int references;
-
- unsigned long options;
-
- const SSL_METHOD *method;
-
- CERT *cert;
-
- X509 *client_CA;
-
- const char **alpn_protos;
-
- next_proto_cb alpn_cb;
-
- int verify_mode;
-
- int (*default_verify_callback) (int ok, X509_STORE_CTX *ctx);
-
- long session_timeout;
-
- int read_ahead;
-
- int read_buffer_len;
-
- X509_VERIFY_PARAM param;
-};
-
-struct ssl_st
-{
- /* protocol version(one of SSL3.0, TLS1.0, etc.) */
- int version;
-
- unsigned long options;
-
- /* shut things down(0x01 : sent, 0x02 : received) */
- int shutdown;
-
- CERT *cert;
-
- X509 *client_CA;
-
- SSL_CTX *ctx;
-
- const SSL_METHOD *method;
-
- const char **alpn_protos;
-
- RECORD_LAYER rlayer;
-
- /* where we are */
- OSSL_STATEM statem;
-
- SSL_SESSION *session;
-
- int verify_mode;
-
- int (*verify_callback) (int ok, X509_STORE_CTX *ctx);
-
- int rwstate;
- int interrupted_remaining_write;
-
- long verify_result;
-
- X509_VERIFY_PARAM param;
-
- int err;
-
- void (*info_callback) (const SSL *ssl, int type, int val);
-
- /* SSL low-level system arch point */
- void *ssl_pm;
-};
-
-struct ssl_method_st {
- /* protocol version(one of SSL3.0, TLS1.0, etc.) */
- int version;
-
- /* SSL mode(client(0) , server(1), not known(-1)) */
- int endpoint;
-
- const SSL_METHOD_FUNC *func;
-};
-
-struct ssl_method_func_st {
-
- int (*ssl_new)(SSL *ssl);
-
- void (*ssl_free)(SSL *ssl);
-
- int (*ssl_handshake)(SSL *ssl);
-
- int (*ssl_shutdown)(SSL *ssl);
-
- int (*ssl_clear)(SSL *ssl);
-
- int (*ssl_read)(SSL *ssl, void *buffer, int len);
-
- int (*ssl_send)(SSL *ssl, const void *buffer, int len);
-
- int (*ssl_pending)(const SSL *ssl);
-
- void (*ssl_set_fd)(SSL *ssl, int fd, int mode);
-
- int (*ssl_get_fd)(const SSL *ssl, int mode);
-
- void (*ssl_set_bufflen)(SSL *ssl, int len);
-
- long (*ssl_get_verify_result)(const SSL *ssl);
-
- OSSL_HANDSHAKE_STATE (*ssl_get_state)(const SSL *ssl);
-};
-
-struct x509_method_st {
-
- int (*x509_new)(X509 *x, X509 *m_x);
-
- void (*x509_free)(X509 *x);
-
- int (*x509_load)(X509 *x, const unsigned char *buf, int len);
-
- int (*x509_show_info)(X509 *x);
-};
-
-struct pkey_method_st {
-
- int (*pkey_new)(EVP_PKEY *pkey, EVP_PKEY *m_pkey);
-
- void (*pkey_free)(EVP_PKEY *pkey);
-
- int (*pkey_load)(EVP_PKEY *pkey, const unsigned char *buf, int len);
-};
-
-#define OPENSSL_NPN_NEGOTIATED 1
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_x509.h b/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_x509.h
deleted file mode 100644
index 7594d064b4..0000000000
--- a/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/ssl_x509.h
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef _SSL_X509_H_
-#define _SSL_X509_H_
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-#include "ssl_types.h"
-#include "ssl_stack.h"
-
-DEFINE_STACK_OF(X509_NAME)
-
-/**
- * @brief create a X509 certification object according to input X509 certification
- *
- * @param ix - input X509 certification point
- *
- * @return new X509 certification object point
- */
-X509* __X509_new(X509 *ix);
-
-/**
- * @brief create a X509 certification object
- *
- * @param none
- *
- * @return X509 certification object point
- */
-X509* X509_new(void);
-
-/**
- * @brief load a character certification context into system context. If '*cert' is pointed to the
- * certification, then load certification into it. Or create a new X509 certification object
- *
- * @param cert - a point pointed to X509 certification
- * @param buffer - a point pointed to the certification context memory point
- * @param length - certification bytes
- *
- * @return X509 certification object point
- */
-X509* d2i_X509(X509 **cert, const unsigned char *buffer, long len);
-
-/**
- * @brief free a X509 certification object
- *
- * @param x - X509 certification object point
- *
- * @return none
- */
-void X509_free(X509 *x);
-
-/**
- * @brief set SSL context client CA certification
- *
- * @param ctx - SSL context point
- * @param x - X509 certification point
- *
- * @return result
- * 0 : failed
- * 1 : OK
- */
-int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x);
-
-/**
- * @brief add CA client certification into the SSL
- *
- * @param ssl - SSL point
- * @param x - X509 certification point
- *
- * @return result
- * 0 : failed
- * 1 : OK
- */
-int SSL_add_client_CA(SSL *ssl, X509 *x);
-
-/**
- * @brief load certification into the SSL
- *
- * @param ssl - SSL point
- * @param len - data bytes
- * @param d - data point
- *
- * @return result
- * 0 : failed
- * 1 : OK
- *
- */
-int SSL_use_certificate_ASN1(SSL *ssl, int len, const unsigned char *d);
-
-const char *X509_verify_cert_error_string(long n);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/tls1.h b/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/tls1.h
deleted file mode 100644
index 7af1b0157d..0000000000
--- a/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/tls1.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef _TLS1_H_
-#define _TLS1_H_
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-# define TLS1_AD_DECRYPTION_FAILED 21
-# define TLS1_AD_RECORD_OVERFLOW 22
-# define TLS1_AD_UNKNOWN_CA 48/* fatal */
-# define TLS1_AD_ACCESS_DENIED 49/* fatal */
-# define TLS1_AD_DECODE_ERROR 50/* fatal */
-# define TLS1_AD_DECRYPT_ERROR 51
-# define TLS1_AD_EXPORT_RESTRICTION 60/* fatal */
-# define TLS1_AD_PROTOCOL_VERSION 70/* fatal */
-# define TLS1_AD_INSUFFICIENT_SECURITY 71/* fatal */
-# define TLS1_AD_INTERNAL_ERROR 80/* fatal */
-# define TLS1_AD_INAPPROPRIATE_FALLBACK 86/* fatal */
-# define TLS1_AD_USER_CANCELLED 90
-# define TLS1_AD_NO_RENEGOTIATION 100
-/* codes 110-114 are from RFC3546 */
-# define TLS1_AD_UNSUPPORTED_EXTENSION 110
-# define TLS1_AD_CERTIFICATE_UNOBTAINABLE 111
-# define TLS1_AD_UNRECOGNIZED_NAME 112
-# define TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE 113
-# define TLS1_AD_BAD_CERTIFICATE_HASH_VALUE 114
-# define TLS1_AD_UNKNOWN_PSK_IDENTITY 115/* fatal */
-# define TLS1_AD_NO_APPLICATION_PROTOCOL 120 /* fatal */
-
-/* Special value for method supporting multiple versions */
-#define TLS_ANY_VERSION 0x10000
-
-#define TLS1_VERSION 0x0301
-#define TLS1_1_VERSION 0x0302
-#define TLS1_2_VERSION 0x0303
-
-#define SSL_TLSEXT_ERR_OK 0
-#define SSL_TLSEXT_ERR_NOACK 3
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/x509_vfy.h b/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/x509_vfy.h
deleted file mode 100644
index 26bf6c88a8..0000000000
--- a/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/internal/x509_vfy.h
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef _X509_VFY_H_
-#define _X509_VFY_H_
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-#define X509_V_OK 0
-#define X509_V_ERR_UNSPECIFIED 1
-#define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT 2
-#define X509_V_ERR_UNABLE_TO_GET_CRL 3
-#define X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE 4
-#define X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE 5
-#define X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY 6
-#define X509_V_ERR_CERT_SIGNATURE_FAILURE 7
-#define X509_V_ERR_CRL_SIGNATURE_FAILURE 8
-#define X509_V_ERR_CERT_NOT_YET_VALID 9
-#define X509_V_ERR_CERT_HAS_EXPIRED 10
-#define X509_V_ERR_CRL_NOT_YET_VALID 11
-#define X509_V_ERR_CRL_HAS_EXPIRED 12
-#define X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD 13
-#define X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD 14
-#define X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD 15
-#define X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD 16
-#define X509_V_ERR_OUT_OF_MEM 17
-#define X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT 18
-#define X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN 19
-#define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY 20
-#define X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE 21
-#define X509_V_ERR_CERT_CHAIN_TOO_LONG 22
-#define X509_V_ERR_CERT_REVOKED 23
-#define X509_V_ERR_INVALID_CA 24
-#define X509_V_ERR_PATH_LENGTH_EXCEEDED 25
-#define X509_V_ERR_INVALID_PURPOSE 26
-#define X509_V_ERR_CERT_UNTRUSTED 27
-#define X509_V_ERR_CERT_REJECTED 28
-/* These are 'informational' when looking for issuer cert */
-#define X509_V_ERR_SUBJECT_ISSUER_MISMATCH 29
-#define X509_V_ERR_AKID_SKID_MISMATCH 30
-#define X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH 31
-#define X509_V_ERR_KEYUSAGE_NO_CERTSIGN 32
-#define X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER 33
-#define X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION 34
-#define X509_V_ERR_KEYUSAGE_NO_CRL_SIGN 35
-#define X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION 36
-#define X509_V_ERR_INVALID_NON_CA 37
-#define X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED 38
-#define X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE 39
-#define X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED 40
-#define X509_V_ERR_INVALID_EXTENSION 41
-#define X509_V_ERR_INVALID_POLICY_EXTENSION 42
-#define X509_V_ERR_NO_EXPLICIT_POLICY 43
-#define X509_V_ERR_DIFFERENT_CRL_SCOPE 44
-#define X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE 45
-#define X509_V_ERR_UNNESTED_RESOURCE 46
-#define X509_V_ERR_PERMITTED_VIOLATION 47
-#define X509_V_ERR_EXCLUDED_VIOLATION 48
-#define X509_V_ERR_SUBTREE_MINMAX 49
-/* The application is not happy */
-#define X509_V_ERR_APPLICATION_VERIFICATION 50
-#define X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE 51
-#define X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX 52
-#define X509_V_ERR_UNSUPPORTED_NAME_SYNTAX 53
-#define X509_V_ERR_CRL_PATH_VALIDATION_ERROR 54
-/* Another issuer check debug option */
-#define X509_V_ERR_PATH_LOOP 55
-/* Suite B mode algorithm violation */
-#define X509_V_ERR_SUITE_B_INVALID_VERSION 56
-#define X509_V_ERR_SUITE_B_INVALID_ALGORITHM 57
-#define X509_V_ERR_SUITE_B_INVALID_CURVE 58
-#define X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM 59
-#define X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED 60
-#define X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256 61
-/* Host, email and IP check errors */
-#define X509_V_ERR_HOSTNAME_MISMATCH 62
-#define X509_V_ERR_EMAIL_MISMATCH 63
-#define X509_V_ERR_IP_ADDRESS_MISMATCH 64
-/* DANE TLSA errors */
-#define X509_V_ERR_DANE_NO_MATCH 65
-/* security level errors */
-#define X509_V_ERR_EE_KEY_TOO_SMALL 66
-#define X509_V_ERR_CA_KEY_TOO_SMALL 67
-#define X509_V_ERR_CA_MD_TOO_WEAK 68
-/* Caller error */
-#define X509_V_ERR_INVALID_CALL 69
-/* Issuer lookup error */
-#define X509_V_ERR_STORE_LOOKUP 70
-/* Certificate transparency */
-#define X509_V_ERR_NO_VALID_SCTS 71
-
-#define X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION 72
-
-typedef void X509_STORE_CTX;
-int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx);
-int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/openssl/ssl.h b/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/openssl/ssl.h
deleted file mode 100755
index e2b74fc6af..0000000000
--- a/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/openssl/ssl.h
+++ /dev/null
@@ -1,1833 +0,0 @@
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef _SSL_H_
-#define _SSL_H_
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-#include <stdlib.h>
-#include "internal/ssl_x509.h"
-#include "internal/ssl_pkey.h"
-
-/*
-{
-*/
-
-#define SSL_CB_ALERT 0x4000
-
-#define X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT (1 << 0)
-#define X509_CHECK_FLAG_NO_WILDCARDS (1 << 1)
-#define X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS (1 << 2)
-#define X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS (1 << 3)
-#define X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS (1 << 4)
-
- mbedtls_x509_crt *
- ssl_ctx_get_mbedtls_x509_crt(SSL_CTX *ssl_ctx);
-
- mbedtls_x509_crt *
- ssl_get_peer_mbedtls_x509_crt(SSL *ssl);
-
- int SSL_set_sni_callback(SSL *ssl, int(*cb)(void *, mbedtls_ssl_context *,
- const unsigned char *, size_t), void *param);
-
- void SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx);
-
- int SSL_CTX_add_client_CA_ASN1(SSL_CTX *ssl, int len,
- const unsigned char *d);
-
- SSL *SSL_SSL_from_mbedtls_ssl_context(mbedtls_ssl_context *msc);
-
-/**
- * @brief create a SSL context
- *
- * @param method - the SSL context method point
- *
- * @return the context point
- */
-SSL_CTX* SSL_CTX_new(const SSL_METHOD *method);
-
-/**
- * @brief free a SSL context
- *
- * @param method - the SSL context point
- *
- * @return none
- */
-void SSL_CTX_free(SSL_CTX *ctx);
-
-/**
- * @brief create a SSL
- *
- * @param ctx - the SSL context point
- *
- * @return the SSL point
- */
-SSL* SSL_new(SSL_CTX *ctx);
-
-/**
- * @brief free the SSL
- *
- * @param ssl - the SSL point
- *
- * @return none
- */
-void SSL_free(SSL *ssl);
-
-/**
- * @brief connect to the remote SSL server
- *
- * @param ssl - the SSL point
- *
- * @return result
- * 1 : OK
- * -1 : failed
- */
-int SSL_connect(SSL *ssl);
-
-/**
- * @brief accept the remote connection
- *
- * @param ssl - the SSL point
- *
- * @return result
- * 1 : OK
- * -1 : failed
- */
-int SSL_accept(SSL *ssl);
-
-/**
- * @brief read data from to remote
- *
- * @param ssl - the SSL point which has been connected
- * @param buffer - the received data buffer point
- * @param len - the received data length
- *
- * @return result
- * > 0 : OK, and return received data bytes
- * = 0 : connection is closed
- * < 0 : an error catch
- */
-int SSL_read(SSL *ssl, void *buffer, int len);
-
-/**
- * @brief send the data to remote
- *
- * @param ssl - the SSL point which has been connected
- * @param buffer - the send data buffer point
- * @param len - the send data length
- *
- * @return result
- * > 0 : OK, and return sent data bytes
- * = 0 : connection is closed
- * < 0 : an error catch
- */
-int SSL_write(SSL *ssl, const void *buffer, int len);
-
-/**
- * @brief get the verifying result of the SSL certification
- *
- * @param ssl - the SSL point
- *
- * @return the result of verifying
- */
-long SSL_get_verify_result(const SSL *ssl);
-
-/**
- * @brief shutdown the connection
- *
- * @param ssl - the SSL point
- *
- * @return result
- * 1 : OK
- * 0 : shutdown is not finished
- * -1 : an error catch
- */
-int SSL_shutdown(SSL *ssl);
-
-/**
- * @brief bind the socket file description into the SSL
- *
- * @param ssl - the SSL point
- * @param fd - socket handle
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_set_fd(SSL *ssl, int fd);
-
-/**
- * @brief These functions load the private key into the SSL_CTX or SSL object
- *
- * @param ctx - the SSL context point
- * @param pkey - private key object point
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey);
-
-/**
- * @brief These functions load the certification into the SSL_CTX or SSL object
- *
- * @param ctx - the SSL context point
- * @param pkey - certification object point
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x);
-
-/**
- * @brief create the target SSL context client method
- *
- * @param none
- *
- * @return the SSLV2.3 version SSL context client method
- */
-const SSL_METHOD* SSLv23_client_method(void);
-
-/**
- * @brief create the target SSL context client method
- *
- * @param none
- *
- * @return the TLSV1.0 version SSL context client method
- */
-const SSL_METHOD* TLSv1_client_method(void);
-
-/**
- * @brief create the target SSL context client method
- *
- * @param none
- *
- * @return the SSLV1.0 version SSL context client method
- */
-const SSL_METHOD* SSLv3_client_method(void);
-
-/**
- * @brief create the target SSL context client method
- *
- * @param none
- *
- * @return the TLSV1.1 version SSL context client method
- */
-const SSL_METHOD* TLSv1_1_client_method(void);
-
-/**
- * @brief create the target SSL context client method
- *
- * @param none
- *
- * @return the TLSV1.2 version SSL context client method
- */
-const SSL_METHOD* TLSv1_2_client_method(void);
-
-/**
- * @brief create the target SSL context server method
- *
- * @param none
- *
- * @return the TLS any version SSL context client method
- */
-const SSL_METHOD* TLS_client_method(void);
-
-/**
- * @brief create the target SSL context server method
- *
- * @param none
- *
- * @return the SSLV2.3 version SSL context server method
- */
-const SSL_METHOD* SSLv23_server_method(void);
-
-/**
- * @brief create the target SSL context server method
- *
- * @param none
- *
- * @return the TLSV1.1 version SSL context server method
- */
-const SSL_METHOD* TLSv1_1_server_method(void);
-
-/**
- * @brief create the target SSL context server method
- *
- * @param none
- *
- * @return the TLSV1.2 version SSL context server method
- */
-const SSL_METHOD* TLSv1_2_server_method(void);
-
-/**
- * @brief create the target SSL context server method
- *
- * @param none
- *
- * @return the TLSV1.0 version SSL context server method
- */
-const SSL_METHOD* TLSv1_server_method(void);
-
-/**
- * @brief create the target SSL context server method
- *
- * @param none
- *
- * @return the SSLV3.0 version SSL context server method
- */
-const SSL_METHOD* SSLv3_server_method(void);
-
-/**
- * @brief create the target SSL context server method
- *
- * @param none
- *
- * @return the TLS any version SSL context server method
- */
-const SSL_METHOD* TLS_server_method(void);
-
-
-/**
- * @brief set the SSL context ALPN select callback function
- *
- * @param ctx - SSL context point
- * @param cb - ALPN select callback function
- * @param arg - ALPN select callback function entry private data point
- *
- * @return none
- */
-void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx,
- int (*cb) (SSL *ssl,
- const unsigned char **out,
- unsigned char *outlen,
- const unsigned char *in,
- unsigned int inlen,
- void *arg),
- void *arg);
-
-void SSL_set_alpn_select_cb(SSL *ssl, void *arg);
-
-/**
- * @brief set the SSL context ALPN select protocol
- *
- * @param ctx - SSL context point
- * @param protos - ALPN protocol name
- * @param protos_len - ALPN protocol name bytes
- *
- * @return result
- * 0 : OK
- * 1 : failed
- */
-int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const unsigned char *protos, unsigned int protos_len);
-
-/**
- * @brief set the SSL context next ALPN select callback function
- *
- * @param ctx - SSL context point
- * @param cb - ALPN select callback function
- * @param arg - ALPN select callback function entry private data point
- *
- * @return none
- */
-void SSL_CTX_set_next_proto_select_cb(SSL_CTX *ctx,
- int (*cb) (SSL *ssl,
- unsigned char **out,
- unsigned char *outlen,
- const unsigned char *in,
- unsigned int inlen,
- void *arg),
- void *arg);
-
-void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data,
- unsigned int *len);
-
-void _ssl_set_alpn_list(const SSL *ssl);
-
-/**
- * @brief get SSL error code
- *
- * @param ssl - SSL point
- * @param ret_code - SSL return code
- *
- * @return SSL error number
- */
-int SSL_get_error(const SSL *ssl, int ret_code);
-
-/**
- * @brief clear the SSL error code
- *
- * @param none
- *
- * @return none
- */
-void ERR_clear_error(void);
-
-/**
- * @brief get the current SSL error code
- *
- * @param none
- *
- * @return current SSL error number
- */
-int ERR_get_error(void);
-
-/**
- * @brief register the SSL error strings
- *
- * @param none
- *
- * @return none
- */
-void ERR_load_SSL_strings(void);
-
-/**
- * @brief initialize the SSL library
- *
- * @param none
- *
- * @return none
- */
-void SSL_library_init(void);
-
-/**
- * @brief generates a human-readable string representing the error code e
- * and store it into the "ret" point memory
- *
- * @param e - error code
- * @param ret - memory point to store the string
- *
- * @return the result string point
- */
-char *ERR_error_string(unsigned long e, char *ret);
-
-/**
- * @brief add the SSL context option
- *
- * @param ctx - SSL context point
- * @param opt - new SSL context option
- *
- * @return the SSL context option
- */
-unsigned long SSL_CTX_set_options(SSL_CTX *ctx, unsigned long opt);
-
-/**
- * @brief add the SSL context mode
- *
- * @param ctx - SSL context point
- * @param mod - new SSL context mod
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_CTX_set_mode(SSL_CTX *ctx, int mod);
-
-/*
-}
-*/
-
-/**
- * @brief perform the SSL handshake
- *
- * @param ssl - SSL point
- *
- * @return result
- * 1 : OK
- * 0 : failed
- * -1 : a error catch
- */
-int SSL_do_handshake(SSL *ssl);
-
-/**
- * @brief get the SSL current version
- *
- * @param ssl - SSL point
- *
- * @return the version string
- */
-const char *SSL_get_version(const SSL *ssl);
-
-/**
- * @brief set the SSL context version
- *
- * @param ctx - SSL context point
- * @param meth - SSL method point
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_CTX_set_ssl_version(SSL_CTX *ctx, const SSL_METHOD *meth);
-
-/**
- * @brief get the bytes numbers which are to be read
- *
- * @param ssl - SSL point
- *
- * @return bytes number
- */
-int SSL_pending(const SSL *ssl);
-
-/**
- * @brief check if SSL want nothing
- *
- * @param ssl - SSL point
- *
- * @return result
- * 0 : false
- * 1 : true
- */
-int SSL_want_nothing(const SSL *ssl);
-
-/**
- * @brief check if SSL want to read
- *
- * @param ssl - SSL point
- *
- * @return result
- * 0 : false
- * 1 : true
- */
-int SSL_want_read(const SSL *ssl);
-
-/**
- * @brief check if SSL want to write
- *
- * @param ssl - SSL point
- *
- * @return result
- * 0 : false
- * 1 : true
- */
-int SSL_want_write(const SSL *ssl);
-
-/**
- * @brief get the SSL context current method
- *
- * @param ctx - SSL context point
- *
- * @return the SSL context current method
- */
-const SSL_METHOD *SSL_CTX_get_ssl_method(SSL_CTX *ctx);
-
-/**
- * @brief get the SSL current method
- *
- * @param ssl - SSL point
- *
- * @return the SSL current method
- */
-const SSL_METHOD *SSL_get_ssl_method(SSL *ssl);
-
-/**
- * @brief set the SSL method
- *
- * @param ssl - SSL point
- * @param meth - SSL method point
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_set_ssl_method(SSL *ssl, const SSL_METHOD *method);
-
-/**
- * @brief add CA client certification into the SSL
- *
- * @param ssl - SSL point
- * @param x - CA certification point
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_add_client_CA(SSL *ssl, X509 *x);
-
-/**
- * @brief add CA client certification into the SSL context
- *
- * @param ctx - SSL context point
- * @param x - CA certification point
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x);
-
-/**
- * @brief set the SSL CA certification list
- *
- * @param ssl - SSL point
- * @param name_list - CA certification list
- *
- * @return none
- */
-void SSL_set_client_CA_list(SSL *ssl, STACK_OF(X509_NAME) *name_list);
-
-/**
- * @brief set the SSL context CA certification list
- *
- * @param ctx - SSL context point
- * @param name_list - CA certification list
- *
- * @return none
- */
-void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list);
-
-/**
- * @briefget the SSL CA certification list
- *
- * @param ssl - SSL point
- *
- * @return CA certification list
- */
-STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *ssl);
-
-/**
- * @brief get the SSL context CA certification list
- *
- * @param ctx - SSL context point
- *
- * @return CA certification list
- */
-STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *ctx);
-
-/**
- * @brief get the SSL certification point
- *
- * @param ssl - SSL point
- *
- * @return SSL certification point
- */
-X509 *SSL_get_certificate(const SSL *ssl);
-
-/**
- * @brief get the SSL private key point
- *
- * @param ssl - SSL point
- *
- * @return SSL private key point
- */
-EVP_PKEY *SSL_get_privatekey(const SSL *ssl);
-
-/**
- * @brief set the SSL information callback function
- *
- * @param ssl - SSL point
- * @param cb - information callback function
- *
- * @return none
- */
-void SSL_set_info_callback(SSL *ssl, void (*cb) (const SSL *ssl, int type, int val));
-
-/**
- * @brief get the SSL state
- *
- * @param ssl - SSL point
- *
- * @return SSL state
- */
-OSSL_HANDSHAKE_STATE SSL_get_state(const SSL *ssl);
-
-/**
- * @brief set the SSL context read buffer length
- *
- * @param ctx - SSL context point
- * @param len - read buffer length
- *
- * @return none
- */
-void SSL_CTX_set_default_read_buffer_len(SSL_CTX *ctx, size_t len);
-
-/**
- * @brief set the SSL read buffer length
- *
- * @param ssl - SSL point
- * @param len - read buffer length
- *
- * @return none
- */
-void SSL_set_default_read_buffer_len(SSL *ssl, size_t len);
-
-/**
- * @brief set the SSL security level
- *
- * @param ssl - SSL point
- * @param level - security level
- *
- * @return none
- */
-void SSL_set_security_level(SSL *ssl, int level);
-
-/**
- * @brief get the SSL security level
- *
- * @param ssl - SSL point
- *
- * @return security level
- */
-int SSL_get_security_level(const SSL *ssl);
-
-/**
- * @brief get the SSL verifying mode of the SSL context
- *
- * @param ctx - SSL context point
- *
- * @return verifying mode
- */
-int SSL_CTX_get_verify_mode(const SSL_CTX *ctx);
-
-/**
- * @brief get the SSL verifying depth of the SSL context
- *
- * @param ctx - SSL context point
- *
- * @return verifying depth
- */
-int SSL_CTX_get_verify_depth(const SSL_CTX *ctx);
-
-/**
- * @brief set the SSL context verifying of the SSL context
- *
- * @param ctx - SSL context point
- * @param mode - verifying mode
- * @param verify_callback - verifying callback function
- *
- * @return none
- */
-void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, int (*verify_callback)(int, X509_STORE_CTX *));
-
-/**
- * @brief set the SSL verifying of the SSL context
- *
- * @param ctx - SSL point
- * @param mode - verifying mode
- * @param verify_callback - verifying callback function
- *
- * @return none
- */
-void SSL_set_verify(SSL *s, int mode, int (*verify_callback)(int, X509_STORE_CTX *));
-
-/**
- * @brief set the SSL verify depth of the SSL context
- *
- * @param ctx - SSL context point
- * @param depth - verifying depth
- *
- * @return none
- */
-void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth);
-
-/**
- * @brief certification verifying callback function
- *
- * @param preverify_ok - verifying result
- * @param x509_ctx - X509 certification point
- *
- * @return verifying result
- */
-int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx);
-
-/**
- * @brief set the session timeout time
- *
- * @param ctx - SSL context point
- * @param t - new session timeout time
- *
- * @return old session timeout time
- */
-long SSL_CTX_set_timeout(SSL_CTX *ctx, long t);
-
-/**
- * @brief get the session timeout time
- *
- * @param ctx - SSL context point
- *
- * @return current session timeout time
- */
-long SSL_CTX_get_timeout(const SSL_CTX *ctx);
-
-/**
- * @brief set the SSL context cipher through the list string
- *
- * @param ctx - SSL context point
- * @param str - cipher controller list string
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str);
-
-/**
- * @brief set the SSL cipher through the list string
- *
- * @param ssl - SSL point
- * @param str - cipher controller list string
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_set_cipher_list(SSL *ssl, const char *str);
-
-/**
- * @brief get the SSL cipher list string
- *
- * @param ssl - SSL point
- *
- * @return cipher controller list string
- */
-const char *SSL_get_cipher_list(const SSL *ssl, int n);
-
-/**
- * @brief get the SSL cipher
- *
- * @param ssl - SSL point
- *
- * @return current cipher
- */
-const SSL_CIPHER *SSL_get_current_cipher(const SSL *ssl);
-
-/**
- * @brief get the SSL cipher string
- *
- * @param ssl - SSL point
- *
- * @return cipher string
- */
-const char *SSL_get_cipher(const SSL *ssl);
-
-/**
- * @brief get the SSL context object X509 certification storage
- *
- * @param ctx - SSL context point
- *
- * @return x509 certification storage
- */
-X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *ctx);
-
-/**
- * @brief set the SSL context object X509 certification store
- *
- * @param ctx - SSL context point
- * @param store - X509 certification store
- *
- * @return none
- */
-void SSL_CTX_set_cert_store(SSL_CTX *ctx, X509_STORE *store);
-
-/**
- * @brief get the SSL specifical statement
- *
- * @param ssl - SSL point
- *
- * @return specifical statement
- */
-int SSL_want(const SSL *ssl);
-
-/**
- * @brief check if the SSL is SSL_X509_LOOKUP state
- *
- * @param ssl - SSL point
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_want_x509_lookup(const SSL *ssl);
-
-/**
- * @brief reset the SSL
- *
- * @param ssl - SSL point
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_clear(SSL *ssl);
-
-/**
- * @brief get the socket handle of the SSL
- *
- * @param ssl - SSL point
- *
- * @return result
- * >= 0 : yes, and return socket handle
- * < 0 : a error catch
- */
-int SSL_get_fd(const SSL *ssl);
-
-/**
- * @brief get the read only socket handle of the SSL
- *
- * @param ssl - SSL point
- *
- * @return result
- * >= 0 : yes, and return socket handle
- * < 0 : a error catch
- */
-int SSL_get_rfd(const SSL *ssl);
-
-/**
- * @brief get the write only socket handle of the SSL
- *
- * @param ssl - SSL point
- *
- * @return result
- * >= 0 : yes, and return socket handle
- * < 0 : a error catch
- */
-int SSL_get_wfd(const SSL *ssl);
-
-/**
- * @brief set the SSL if we can read as many as data
- *
- * @param ssl - SSL point
- * @param yes - enable the function
- *
- * @return none
- */
-void SSL_set_read_ahead(SSL *s, int yes);
-
-/**
- * @brief set the SSL context if we can read as many as data
- *
- * @param ctx - SSL context point
- * @param yes - enbale the function
- *
- * @return none
- */
-void SSL_CTX_set_read_ahead(SSL_CTX *ctx, int yes);
-
-/**
- * @brief get the SSL ahead signal if we can read as many as data
- *
- * @param ssl - SSL point
- *
- * @return SSL context ahead signal
- */
-int SSL_get_read_ahead(const SSL *ssl);
-
-/**
- * @brief get the SSL context ahead signal if we can read as many as data
- *
- * @param ctx - SSL context point
- *
- * @return SSL context ahead signal
- */
-long SSL_CTX_get_read_ahead(SSL_CTX *ctx);
-
-/**
- * @brief check if some data can be read
- *
- * @param ssl - SSL point
- *
- * @return
- * 1 : there are bytes to be read
- * 0 : no data
- */
-int SSL_has_pending(const SSL *ssl);
-
-/**
- * @brief load the X509 certification into SSL context
- *
- * @param ctx - SSL context point
- * @param x - X509 certification point
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x);//loads the certificate x into ctx
-
-/**
- * @brief load the ASN1 certification into SSL context
- *
- * @param ctx - SSL context point
- * @param len - certification length
- * @param d - data point
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const unsigned char *d);
-
-/**
- * @brief load the certification file into SSL context
- *
- * @param ctx - SSL context point
- * @param file - certification file name
- * @param type - certification encoding type
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type);
-
-/**
- * @brief load the certification chain file into SSL context
- *
- * @param ctx - SSL context point
- * @param file - certification chain file name
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file);
-
-
-/**
- * @brief load the ASN1 private key into SSL context
- *
- * @param ctx - SSL context point
- * @param d - data point
- * @param len - private key length
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_CTX_use_PrivateKey_ASN1(int pk, SSL_CTX *ctx, const unsigned char *d, long len);//adds the private key of type pk stored at memory location d (length len) to ctx
-
-/**
- * @brief load the private key file into SSL context
- *
- * @param ctx - SSL context point
- * @param file - private key file name
- * @param type - private key encoding type
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type);
-
-/**
- * @brief load the RSA private key into SSL context
- *
- * @param ctx - SSL context point
- * @param x - RSA private key point
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa);
-
-/**
- * @brief load the RSA ASN1 private key into SSL context
- *
- * @param ctx - SSL context point
- * @param d - data point
- * @param len - RSA private key length
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d, long len);
-
-/**
- * @brief load the RSA private key file into SSL context
- *
- * @param ctx - SSL context point
- * @param file - RSA private key file name
- * @param type - private key encoding type
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type);
-
-
-/**
- * @brief check if the private key and certification is matched
- *
- * @param ctx - SSL context point
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_CTX_check_private_key(const SSL_CTX *ctx);
-
-/**
- * @brief set the SSL context server information
- *
- * @param ctx - SSL context point
- * @param serverinfo - server information string
- * @param serverinfo_length - server information length
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_CTX_use_serverinfo(SSL_CTX *ctx, const unsigned char *serverinfo, size_t serverinfo_length);
-
-/**
- * @brief load the SSL context server infomation file into SSL context
- *
- * @param ctx - SSL context point
- * @param file - server information file
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file);
-
-/**
- * @brief SSL select next function
- *
- * @param out - point of output data point
- * @param outlen - output data length
- * @param in - input data
- * @param inlen - input data length
- * @param client - client data point
- * @param client_len -client data length
- *
- * @return NPN state
- * OPENSSL_NPN_UNSUPPORTED : not support
- * OPENSSL_NPN_NEGOTIATED : negotiated
- * OPENSSL_NPN_NO_OVERLAP : no overlap
- */
-int SSL_select_next_proto(unsigned char **out, unsigned char *outlen,
- const unsigned char *in, unsigned int inlen,
- const unsigned char *client, unsigned int client_len);
-
-/**
- * @brief load the extra certification chain into the SSL context
- *
- * @param ctx - SSL context point
- * @param x509 - X509 certification
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-long SSL_CTX_add_extra_chain_cert(SSL_CTX *ctx, X509 *);
-
-/**
- * @brief control the SSL context
- *
- * @param ctx - SSL context point
- * @param cmd - command
- * @param larg - parameter length
- * @param parg - parameter point
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, char *parg);
-
-/**
- * @brief get the SSL context cipher
- *
- * @param ctx - SSL context point
- *
- * @return SSL context cipher
- */
-STACK *SSL_CTX_get_ciphers(const SSL_CTX *ctx);
-
-/**
- * @brief check if the SSL context can read as many as data
- *
- * @param ctx - SSL context point
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-long SSL_CTX_get_default_read_ahead(SSL_CTX *ctx);
-
-/**
- * @brief get the SSL context extra data
- *
- * @param ctx - SSL context point
- * @param idx - index
- *
- * @return data point
- */
-char *SSL_CTX_get_ex_data(const SSL_CTX *ctx, int idx);
-
-/**
- * @brief get the SSL context quiet shutdown option
- *
- * @param ctx - SSL context point
- *
- * @return quiet shutdown option
- */
-int SSL_CTX_get_quiet_shutdown(const SSL_CTX *ctx);
-
-/**
- * @brief load the SSL context CA file
- *
- * @param ctx - SSL context point
- * @param CAfile - CA certification file
- * @param CApath - CA certification file path
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, const char *CApath);
-
-/**
- * @brief add SSL context reference count by '1'
- *
- * @param ctx - SSL context point
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_CTX_up_ref(SSL_CTX *ctx);
-
-/**
- * @brief set SSL context application private data
- *
- * @param ctx - SSL context point
- * @param arg - private data
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_CTX_set_app_data(SSL_CTX *ctx, void *arg);
-
-/**
- * @brief set SSL context client certification callback function
- *
- * @param ctx - SSL context point
- * @param cb - callback function
- *
- * @return none
- */
-void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, int (*cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey));
-
-/**
- * @brief set the SSL context if we can read as many as data
- *
- * @param ctx - SSL context point
- * @param m - enable the fuction
- *
- * @return none
- */
-void SSL_CTX_set_default_read_ahead(SSL_CTX *ctx, int m);
-
-/**
- * @brief set SSL context default verifying path
- *
- * @param ctx - SSL context point
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx);
-
-/**
- * @brief set SSL context default verifying directory
- *
- * @param ctx - SSL context point
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_CTX_set_default_verify_dir(SSL_CTX *ctx);
-
-/**
- * @brief set SSL context default verifying file
- *
- * @param ctx - SSL context point
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_CTX_set_default_verify_file(SSL_CTX *ctx);
-
-/**
- * @brief set SSL context extra data
- *
- * @param ctx - SSL context point
- * @param idx - data index
- * @param arg - data point
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_CTX_set_ex_data(SSL_CTX *s, int idx, char *arg);
-
-/**
- * @brief clear the SSL context option bit of "op"
- *
- * @param ctx - SSL context point
- * @param op - option
- *
- * @return SSL context option
- */
-unsigned long SSL_CTX_clear_options(SSL_CTX *ctx, unsigned long op);
-
-/**
- * @brief get the SSL context option
- *
- * @param ctx - SSL context point
- * @param op - option
- *
- * @return SSL context option
- */
-unsigned long SSL_CTX_get_options(SSL_CTX *ctx);
-
-/**
- * @brief set the SSL context quiet shutdown mode
- *
- * @param ctx - SSL context point
- * @param mode - mode
- *
- * @return none
- */
-void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx, int mode);
-
-/**
- * @brief get the SSL context X509 certification
- *
- * @param ctx - SSL context point
- *
- * @return X509 certification
- */
-X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx);
-
-/**
- * @brief get the SSL context private key
- *
- * @param ctx - SSL context point
- *
- * @return private key
- */
-EVP_PKEY *SSL_CTX_get0_privatekey(const SSL_CTX *ctx);
-
-/**
- * @brief set SSL context PSK identity hint
- *
- * @param ctx - SSL context point
- * @param hint - PSK identity hint
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *hint);
-
-/**
- * @brief set SSL context PSK server callback function
- *
- * @param ctx - SSL context point
- * @param callback - callback function
- *
- * @return none
- */
-void SSL_CTX_set_psk_server_callback(SSL_CTX *ctx,
- unsigned int (*callback)(SSL *ssl,
- const char *identity,
- unsigned char *psk,
- int max_psk_len));
-/**
- * @brief get alert description string
- *
- * @param value - alert value
- *
- * @return alert description string
- */
-const char *SSL_alert_desc_string(int value);
-
-/**
- * @brief get alert description long string
- *
- * @param value - alert value
- *
- * @return alert description long string
- */
-const char *SSL_alert_desc_string_long(int value);
-
-/**
- * @brief get alert type string
- *
- * @param value - alert value
- *
- * @return alert type string
- */
-const char *SSL_alert_type_string(int value);
-
-/**
- * @brief get alert type long string
- *
- * @param value - alert value
- *
- * @return alert type long string
- */
-const char *SSL_alert_type_string_long(int value);
-
-/**
- * @brief get SSL context of the SSL
- *
- * @param ssl - SSL point
- *
- * @return SSL context
- */
-SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl);
-
-/**
- * @brief get SSL application data
- *
- * @param ssl - SSL point
- *
- * @return application data
- */
-char *SSL_get_app_data(SSL *ssl);
-
-/**
- * @brief get SSL cipher bits
- *
- * @param ssl - SSL point
- * @param alg_bits - algorithm bits
- *
- * @return strength bits
- */
-int SSL_get_cipher_bits(const SSL *ssl, int *alg_bits);
-
-/**
- * @brief get SSL cipher name
- *
- * @param ssl - SSL point
- *
- * @return SSL cipher name
- */
-char *SSL_get_cipher_name(const SSL *ssl);
-
-/**
- * @brief get SSL cipher version
- *
- * @param ssl - SSL point
- *
- * @return SSL cipher version
- */
-char *SSL_get_cipher_version(const SSL *ssl);
-
-/**
- * @brief get SSL extra data
- *
- * @param ssl - SSL point
- * @param idx - data index
- *
- * @return extra data
- */
-char *SSL_get_ex_data(const SSL *ssl, int idx);
-
-/**
- * @brief get index of the SSL extra data X509 storage context
- *
- * @param none
- *
- * @return data index
- */
-int SSL_get_ex_data_X509_STORE_CTX_idx(void);
-
-/**
- * @brief get peer certification chain
- *
- * @param ssl - SSL point
- *
- * @return certification chain
- */
-STACK *SSL_get_peer_cert_chain(const SSL *ssl);
-
-/**
- * @brief get peer certification
- *
- * @param ssl - SSL point
- *
- * @return certification
- */
-X509 *SSL_get_peer_certificate(const SSL *ssl);
-
-/**
- * @brief get SSL quiet shutdown mode
- *
- * @param ssl - SSL point
- *
- * @return quiet shutdown mode
- */
-int SSL_get_quiet_shutdown(const SSL *ssl);
-
-/**
- * @brief get SSL read only IO handle
- *
- * @param ssl - SSL point
- *
- * @return IO handle
- */
-BIO *SSL_get_rbio(const SSL *ssl);
-
-/**
- * @brief get SSL shared ciphers
- *
- * @param ssl - SSL point
- * @param buf - buffer to store the ciphers
- * @param len - buffer len
- *
- * @return shared ciphers
- */
-char *SSL_get_shared_ciphers(const SSL *ssl, char *buf, int len);
-
-/**
- * @brief get SSL shutdown mode
- *
- * @param ssl - SSL point
- *
- * @return shutdown mode
- */
-int SSL_get_shutdown(const SSL *ssl);
-
-/**
- * @brief get SSL session time
- *
- * @param ssl - SSL point
- *
- * @return session time
- */
-long SSL_get_time(const SSL *ssl);
-
-/**
- * @brief get SSL session timeout time
- *
- * @param ssl - SSL point
- *
- * @return session timeout time
- */
-long SSL_get_timeout(const SSL *ssl);
-
-/**
- * @brief get SSL verifying mode
- *
- * @param ssl - SSL point
- *
- * @return verifying mode
- */
-int SSL_get_verify_mode(const SSL *ssl);
-
-/**
- * @brief get SSL verify parameters
- *
- * @param ssl - SSL point
- *
- * @return verify parameters
- */
-X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl);
-
-/**
- * @brief set expected hostname the peer cert CN should have
- *
- * @param param - verify parameters from SSL_get0_param()
- *
- * @param name - the expected hostname
- *
- * @param namelen - the length of the hostname, or 0 if NUL terminated
- *
- * @return verify parameters
- */
-int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param,
- const char *name, size_t namelen);
-
-/**
- * @brief set parameters for X509 host verify action
- *
- * @param param -verify parameters from SSL_get0_param()
- *
- * @param flags - bitfield of X509_CHECK_FLAG_... parameters to set
- *
- * @return 1 for success, 0 for failure
- */
-int X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param,
- unsigned long flags);
-
-/**
- * @brief clear parameters for X509 host verify action
- *
- * @param param -verify parameters from SSL_get0_param()
- *
- * @param flags - bitfield of X509_CHECK_FLAG_... parameters to clear
- *
- * @return 1 for success, 0 for failure
- */
-int X509_VERIFY_PARAM_clear_hostflags(X509_VERIFY_PARAM *param,
- unsigned long flags);
-
-/**
- * @brief get SSL write only IO handle
- *
- * @param ssl - SSL point
- *
- * @return IO handle
- */
-BIO *SSL_get_wbio(const SSL *ssl);
-
-/**
- * @brief load SSL client CA certification file
- *
- * @param file - file name
- *
- * @return certification loading object
- */
-STACK *SSL_load_client_CA_file(const char *file);
-
-/**
- * @brief add SSL reference by '1'
- *
- * @param ssl - SSL point
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_up_ref(SSL *ssl);
-
-/**
- * @brief read and put data into buf, but not clear the SSL low-level storage
- *
- * @param ssl - SSL point
- * @param buf - storage buffer point
- * @param num - data bytes
- *
- * @return result
- * > 0 : OK, and return read bytes
- * = 0 : connect is closed
- * < 0 : a error catch
- */
-int SSL_peek(SSL *ssl, void *buf, int num);
-
-/**
- * @brief make SSL renegotiate
- *
- * @param ssl - SSL point
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_renegotiate(SSL *ssl);
-
-/**
- * @brief get the state string where SSL is reading
- *
- * @param ssl - SSL point
- *
- * @return state string
- */
-const char *SSL_rstate_string(SSL *ssl);
-
-/**
- * @brief get the statement long string where SSL is reading
- *
- * @param ssl - SSL point
- *
- * @return statement long string
- */
-const char *SSL_rstate_string_long(SSL *ssl);
-
-/**
- * @brief set SSL accept statement
- *
- * @param ssl - SSL point
- *
- * @return none
- */
-void SSL_set_accept_state(SSL *ssl);
-
-/**
- * @brief set SSL application data
- *
- * @param ssl - SSL point
- * @param arg - SSL application data point
- *
- * @return none
- */
-void SSL_set_app_data(SSL *ssl, char *arg);
-
-/**
- * @brief set SSL BIO
- *
- * @param ssl - SSL point
- * @param rbio - read only IO
- * @param wbio - write only IO
- *
- * @return none
- */
-void SSL_set_bio(SSL *ssl, BIO *rbio, BIO *wbio);
-
-/**
- * @brief clear SSL option
- *
- * @param ssl - SSL point
- * @param op - clear option
- *
- * @return SSL option
- */
-unsigned long SSL_clear_options(SSL *ssl, unsigned long op);
-
-/**
- * @brief get SSL option
- *
- * @param ssl - SSL point
- *
- * @return SSL option
- */
-unsigned long SSL_get_options(SSL *ssl);
-
-/**
- * @brief clear SSL option
- *
- * @param ssl - SSL point
- * @param op - setting option
- *
- * @return SSL option
- */
-unsigned long SSL_set_options(SSL *ssl, unsigned long op);
-
-/**
- * @brief set SSL quiet shutdown mode
- *
- * @param ssl - SSL point
- * @param mode - quiet shutdown mode
- *
- * @return none
- */
-void SSL_set_quiet_shutdown(SSL *ssl, int mode);
-
-/**
- * @brief set SSL shutdown mode
- *
- * @param ssl - SSL point
- * @param mode - shutdown mode
- *
- * @return none
- */
-void SSL_set_shutdown(SSL *ssl, int mode);
-
-/**
- * @brief set SSL session time
- *
- * @param ssl - SSL point
- * @param t - session time
- *
- * @return session time
- */
-void SSL_set_time(SSL *ssl, long t);
-
-/**
- * @brief set SSL session timeout time
- *
- * @param ssl - SSL point
- * @param t - session timeout time
- *
- * @return session timeout time
- */
-void SSL_set_timeout(SSL *ssl, long t);
-
-/**
- * @brief get SSL statement string
- *
- * @param ssl - SSL point
- *
- * @return SSL statement string
- */
-char *SSL_state_string(const SSL *ssl);
-
-/**
- * @brief get SSL statement long string
- *
- * @param ssl - SSL point
- *
- * @return SSL statement long string
- */
-char *SSL_state_string_long(const SSL *ssl);
-
-/**
- * @brief get SSL renegotiation count
- *
- * @param ssl - SSL point
- *
- * @return renegotiation count
- */
-long SSL_total_renegotiations(SSL *ssl);
-
-/**
- * @brief get SSL version
- *
- * @param ssl - SSL point
- *
- * @return SSL version
- */
-int SSL_version(const SSL *ssl);
-
-/**
- * @brief set SSL PSK identity hint
- *
- * @param ssl - SSL point
- * @param hint - identity hint
- *
- * @return result
- * 1 : OK
- * 0 : failed
- */
-int SSL_use_psk_identity_hint(SSL *ssl, const char *hint);
-
-/**
- * @brief get SSL PSK identity hint
- *
- * @param ssl - SSL point
- *
- * @return identity hint
- */
-const char *SSL_get_psk_identity_hint(SSL *ssl);
-
-/**
- * @brief get SSL PSK identity
- *
- * @param ssl - SSL point
- *
- * @return identity
- */
-const char *SSL_get_psk_identity(SSL *ssl);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/platform/ssl_pm.h b/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/platform/ssl_pm.h
deleted file mode 100644
index cbbe3aa3a2..0000000000
--- a/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/platform/ssl_pm.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef _SSL_PM_H_
-#define _SSL_PM_H_
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-#include <string.h>
-#include "ssl_types.h"
-#include "ssl_port.h"
-
-#define LOCAL_ATRR
-
-int ssl_pm_new(SSL *ssl);
-void ssl_pm_free(SSL *ssl);
-
-int ssl_pm_handshake(SSL *ssl);
-int ssl_pm_shutdown(SSL *ssl);
-int ssl_pm_clear(SSL *ssl);
-
-int ssl_pm_read(SSL *ssl, void *buffer, int len);
-int ssl_pm_send(SSL *ssl, const void *buffer, int len);
-int ssl_pm_pending(const SSL *ssl);
-
-void ssl_pm_set_fd(SSL *ssl, int fd, int mode);
-int ssl_pm_get_fd(const SSL *ssl, int mode);
-
-OSSL_HANDSHAKE_STATE ssl_pm_get_state(const SSL *ssl);
-
-void ssl_pm_set_bufflen(SSL *ssl, int len);
-
-int x509_pm_show_info(X509 *x);
-int x509_pm_new(X509 *x, X509 *m_x);
-void x509_pm_free(X509 *x);
-int x509_pm_load(X509 *x, const unsigned char *buffer, int len);
-
-int pkey_pm_new(EVP_PKEY *pk, EVP_PKEY *m_pk);
-void pkey_pm_free(EVP_PKEY *pk);
-int pkey_pm_load(EVP_PKEY *pk, const unsigned char *buffer, int len);
-
-long ssl_pm_get_verify_result(const SSL *ssl);
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif
diff --git a/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/platform/ssl_port.h b/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/platform/ssl_port.h
deleted file mode 100644
index 74c7634355..0000000000
--- a/thirdparty/libwebsockets/tls/mbedtls/wrapper/include/platform/ssl_port.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef _SSL_PORT_H_
-#define _SSL_PORT_H_
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-#include "string.h"
-#include "stdlib.h"
-#if defined(LWS_HAVE_MALLOC_H)
-#include "malloc.h"
-#endif
-
-void *ssl_mem_zalloc(size_t size);
-
-#define ssl_mem_malloc malloc
-#define ssl_mem_free free
-
-#define ssl_memcpy memcpy
-#define ssl_strlen strlen
-
-#define ssl_speed_up_enter()
-#define ssl_speed_up_exit()
-
-#define SSL_DEBUG_FL
-#define SSL_DEBUG_LOG(fmt, ...) ESP_LOGI("openssl", fmt, ##__VA_ARGS__)
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif
diff --git a/thirdparty/libwebsockets/tls/mbedtls/wrapper/library/ssl_cert.c b/thirdparty/libwebsockets/tls/mbedtls/wrapper/library/ssl_cert.c
deleted file mode 100644
index 5c608125ac..0000000000
--- a/thirdparty/libwebsockets/tls/mbedtls/wrapper/library/ssl_cert.c
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "ssl_cert.h"
-#include "ssl_pkey.h"
-#include "ssl_x509.h"
-#include "ssl_dbg.h"
-#include "ssl_port.h"
-
-/**
- * @brief create a certification object according to input certification
- */
-CERT *__ssl_cert_new(CERT *ic)
-{
- CERT *cert;
-
- X509 *ix;
- EVP_PKEY *ipk;
-
- cert = ssl_mem_zalloc(sizeof(CERT));
- if (!cert) {
- SSL_DEBUG(SSL_CERT_ERROR_LEVEL, "no enough memory > (cert)");
- goto no_mem;
- }
-
- if (ic) {
- ipk = ic->pkey;
- ix = ic->x509;
- } else {
- ipk = NULL;
- ix = NULL;
- }
-
- cert->pkey = __EVP_PKEY_new(ipk);
- if (!cert->pkey) {
- SSL_DEBUG(SSL_CERT_ERROR_LEVEL, "__EVP_PKEY_new() return NULL");
- goto pkey_err;
- }
-
- cert->x509 = __X509_new(ix);
- if (!cert->x509) {
- SSL_DEBUG(SSL_CERT_ERROR_LEVEL, "__X509_new() return NULL");
- goto x509_err;
- }
-
- return cert;
-
-x509_err:
- EVP_PKEY_free(cert->pkey);
-pkey_err:
- ssl_mem_free(cert);
-no_mem:
- return NULL;
-}
-
-/**
- * @brief create a certification object include private key object
- */
-CERT *ssl_cert_new(void)
-{
- return __ssl_cert_new(NULL);
-}
-
-/**
- * @brief free a certification object
- */
-void ssl_cert_free(CERT *cert)
-{
- SSL_ASSERT3(cert);
-
- X509_free(cert->x509);
-
- EVP_PKEY_free(cert->pkey);
-
- ssl_mem_free(cert);
-}
diff --git a/thirdparty/libwebsockets/tls/mbedtls/wrapper/library/ssl_lib.c b/thirdparty/libwebsockets/tls/mbedtls/wrapper/library/ssl_lib.c
deleted file mode 100644
index 2f688ca9ef..0000000000
--- a/thirdparty/libwebsockets/tls/mbedtls/wrapper/library/ssl_lib.c
+++ /dev/null
@@ -1,1736 +0,0 @@
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "ssl_lib.h"
-#include "ssl_pkey.h"
-#include "ssl_x509.h"
-#include "ssl_cert.h"
-#include "ssl_dbg.h"
-#include "ssl_port.h"
-
-char *
-lws_strncpy(char *dest, const char *src, size_t size);
-
-#define SSL_SEND_DATA_MAX_LENGTH 1460
-
-/**
- * @brief create a new SSL session object
- */
-static SSL_SESSION* SSL_SESSION_new(void)
-{
- SSL_SESSION *session;
-
- session = ssl_mem_zalloc(sizeof(SSL_SESSION));
- if (!session) {
- SSL_DEBUG(SSL_LIB_ERROR_LEVEL, "no enough memory > (session)");
- goto failed1;
- }
-
- session->peer = X509_new();
- if (!session->peer) {
- SSL_DEBUG(SSL_LIB_ERROR_LEVEL, "X509_new() return NULL");
- goto failed2;
- }
-
- return session;
-
-failed2:
- ssl_mem_free(session);
-failed1:
- return NULL;
-}
-
-/**
- * @brief free a new SSL session object
- */
-static void SSL_SESSION_free(SSL_SESSION *session)
-{
- X509_free(session->peer);
- ssl_mem_free(session);
-}
-
-/**
- * @brief Discover whether the current connection is in the error state
- */
-int ossl_statem_in_error(const SSL *ssl)
-{
- SSL_ASSERT1(ssl);
-
- if (ssl->statem.state == MSG_FLOW_ERROR)
- return 1;
-
- return 0;
-}
-
-/**
- * @brief get the SSL specifical statement
- */
-int SSL_want(const SSL *ssl)
-{
- SSL_ASSERT1(ssl);
-
- return ssl->rwstate;
-}
-
-/**
- * @brief check if SSL want nothing
- */
-int SSL_want_nothing(const SSL *ssl)
-{
- SSL_ASSERT1(ssl);
-
- if (ssl->err)
- return 1;
-
- return (SSL_want(ssl) == SSL_NOTHING);
-}
-
-/**
- * @brief check if SSL want to read
- */
-int SSL_want_read(const SSL *ssl)
-{
- SSL_ASSERT1(ssl);
-
- if (ssl->err)
- return 0;
-
- return (SSL_want(ssl) == SSL_READING);
-}
-
-/**
- * @brief check if SSL want to write
- */
-int SSL_want_write(const SSL *ssl)
-{
- SSL_ASSERT1(ssl);
-
- if (ssl->err)
- return 0;
-
- return (SSL_want(ssl) == SSL_WRITING);
-}
-
-/**
- * @brief check if SSL want to lookup X509 certification
- */
-int SSL_want_x509_lookup(const SSL *ssl)
-{
- SSL_ASSERT1(ssl);
-
- return (SSL_want(ssl) == SSL_WRITING);
-}
-
-/**
- * @brief get SSL error code
- */
-int SSL_get_error(const SSL *ssl, int ret_code)
-{
- int ret = SSL_ERROR_SYSCALL;
-
- SSL_ASSERT1(ssl);
-
- if (ret_code > 0)
- ret = SSL_ERROR_NONE;
- else if (ret_code < 0)
- {
- if (ssl->err == SSL_ERROR_WANT_READ || SSL_want_read(ssl))
- ret = SSL_ERROR_WANT_READ;
- else if (ssl->err == SSL_ERROR_WANT_WRITE || SSL_want_write(ssl))
- ret = SSL_ERROR_WANT_WRITE;
- else
- ret = SSL_ERROR_SYSCALL; //unknown
- }
- else // ret_code == 0
- {
- if (ssl->shutdown & SSL_RECEIVED_SHUTDOWN)
- ret = SSL_ERROR_ZERO_RETURN;
- else
- ret = SSL_ERROR_SYSCALL;
- }
-
- return ret;
-}
-
-/**
- * @brief get the SSL state
- */
-OSSL_HANDSHAKE_STATE SSL_get_state(const SSL *ssl)
-{
- OSSL_HANDSHAKE_STATE state;
-
- SSL_ASSERT1(ssl);
-
- state = SSL_METHOD_CALL(get_state, ssl);
-
- return state;
-}
-
-/**
- * @brief create a SSL context
- */
-SSL_CTX* SSL_CTX_new(const SSL_METHOD *method)
-{
- SSL_CTX *ctx;
- CERT *cert;
- X509 *client_ca;
-
- if (!method) {
- SSL_DEBUG(SSL_LIB_ERROR_LEVEL, "no no_method");
- return NULL;
- }
-
- client_ca = X509_new();
- if (!client_ca) {
- SSL_DEBUG(SSL_LIB_ERROR_LEVEL, "X509_new() return NULL");
- goto failed1;
- }
-
- cert = ssl_cert_new();
- if (!cert) {
- SSL_DEBUG(SSL_LIB_ERROR_LEVEL, "ssl_cert_new() return NULL");
- goto failed2;
- }
-
- ctx = (SSL_CTX *)ssl_mem_zalloc(sizeof(SSL_CTX));
- if (!ctx) {
- SSL_DEBUG(SSL_LIB_ERROR_LEVEL, "no enough memory > (ctx)");
- goto failed3;
- }
-
- ctx->method = method;
- ctx->client_CA = client_ca;
- ctx->cert = cert;
-
- ctx->version = method->version;
-
- return ctx;
-
-failed3:
- ssl_cert_free(cert);
-failed2:
- X509_free(client_ca);
-failed1:
- return NULL;
-}
-
-/**
- * @brief free a SSL context
- */
-void SSL_CTX_free(SSL_CTX* ctx)
-{
- SSL_ASSERT3(ctx);
-
- ssl_cert_free(ctx->cert);
-
- X509_free(ctx->client_CA);
-
- if (ctx->alpn_protos)
- ssl_mem_free(ctx->alpn_protos);
-
- ssl_mem_free(ctx);
-}
-
-/**
- * @brief set the SSL context version
- */
-int SSL_CTX_set_ssl_version(SSL_CTX *ctx, const SSL_METHOD *meth)
-{
- SSL_ASSERT1(ctx);
- SSL_ASSERT1(meth);
-
- ctx->method = meth;
-
- ctx->version = meth->version;
-
- return 1;
-}
-
-/**
- * @brief get the SSL context current method
- */
-const SSL_METHOD *SSL_CTX_get_ssl_method(SSL_CTX *ctx)
-{
- SSL_ASSERT2(ctx);
-
- return ctx->method;
-}
-
-/**
- * @brief create a SSL
- */
-SSL *SSL_new(SSL_CTX *ctx)
-{
- int ret = 0;
- SSL *ssl;
-
- if (!ctx) {
- SSL_DEBUG(SSL_LIB_ERROR_LEVEL, "no ctx");
- return NULL;
- }
-
- ssl = (SSL *)ssl_mem_zalloc(sizeof(SSL));
- if (!ssl) {
- SSL_DEBUG(SSL_LIB_ERROR_LEVEL, "no enough memory > (ssl)");
- goto failed1;
- }
-
- ssl->session = SSL_SESSION_new();
- if (!ssl->session) {
- SSL_DEBUG(SSL_LIB_ERROR_LEVEL, "SSL_SESSION_new() return NULL");
- goto failed2;
- }
-
- ssl->cert = __ssl_cert_new(ctx->cert);
- if (!ssl->cert) {
- SSL_DEBUG(SSL_LIB_ERROR_LEVEL, "__ssl_cert_new() return NULL");
- goto failed3;
- }
-
- ssl->client_CA = __X509_new(ctx->client_CA);
- if (!ssl->client_CA) {
- SSL_DEBUG(SSL_LIB_ERROR_LEVEL, "__X509_new() return NULL");
- goto failed4;
- }
-
- ssl->ctx = ctx;
- ssl->method = ctx->method;
-
- ssl->version = ctx->version;
- ssl->options = ctx->options;
-
- ssl->verify_mode = ctx->verify_mode;
-
- ret = SSL_METHOD_CALL(new, ssl);
- if (ret) {
- SSL_DEBUG(SSL_LIB_ERROR_LEVEL, "SSL_METHOD_CALL(new) return %d", ret);
- goto failed5;
- }
-
- _ssl_set_alpn_list(ssl);
-
- ssl->rwstate = SSL_NOTHING;
-
- return ssl;
-
-failed5:
- X509_free(ssl->client_CA);
-failed4:
- ssl_cert_free(ssl->cert);
-failed3:
- SSL_SESSION_free(ssl->session);
-failed2:
- ssl_mem_free(ssl);
-failed1:
- return NULL;
-}
-
-/**
- * @brief free the SSL
- */
-void SSL_free(SSL *ssl)
-{
- SSL_ASSERT3(ssl);
-
- SSL_METHOD_CALL(free, ssl);
-
- X509_free(ssl->client_CA);
-
- ssl_cert_free(ssl->cert);
-
- SSL_SESSION_free(ssl->session);
-
- if (ssl->alpn_protos)
- ssl_mem_free(ssl->alpn_protos);
-
- ssl_mem_free(ssl);
-}
-
-/**
- * @brief perform the SSL handshake
- */
-int SSL_do_handshake(SSL *ssl)
-{
- int ret;
-
- SSL_ASSERT1(ssl);
-
- ret = SSL_METHOD_CALL(handshake, ssl);
-
- return ret;
-}
-
-/**
- * @brief connect to the remote SSL server
- */
-int SSL_connect(SSL *ssl)
-{
- SSL_ASSERT1(ssl);
-
- return SSL_do_handshake(ssl);
-}
-
-/**
- * @brief accept the remote connection
- */
-int SSL_accept(SSL *ssl)
-{
- SSL_ASSERT1(ssl);
-
- return SSL_do_handshake(ssl);
-}
-
-/**
- * @brief shutdown the connection
- */
-int SSL_shutdown(SSL *ssl)
-{
- int ret;
-
- SSL_ASSERT1(ssl);
-
- if (SSL_get_state(ssl) != TLS_ST_OK) return 1;
-
- ret = SSL_METHOD_CALL(shutdown, ssl);
-
- return ret;
-}
-
-/**
- * @brief reset the SSL
- */
-int SSL_clear(SSL *ssl)
-{
- int ret;
-
- SSL_ASSERT1(ssl);
-
- ret = SSL_shutdown(ssl);
- if (1 != ret) {
- SSL_DEBUG(SSL_LIB_ERROR_LEVEL, "SSL_shutdown return %d", ret);
- goto failed1;
- }
-
- SSL_METHOD_CALL(free, ssl);
-
- ret = SSL_METHOD_CALL(new, ssl);
- if (!ret) {
- SSL_DEBUG(SSL_LIB_ERROR_LEVEL, "SSL_METHOD_CALL(new) return %d", ret);
- goto failed1;
- }
-
- return 1;
-
-failed1:
- return ret;
-}
-
-/**
- * @brief read data from to remote
- */
-int SSL_read(SSL *ssl, void *buffer, int len)
-{
- int ret;
-
- SSL_ASSERT1(ssl);
- SSL_ASSERT1(buffer);
- SSL_ASSERT1(len);
-
- ssl->rwstate = SSL_READING;
-
- ret = SSL_METHOD_CALL(read, ssl, buffer, len);
-
- if (ret == len)
- ssl->rwstate = SSL_NOTHING;
-
- return ret;
-}
-
-/**
- * @brief send the data to remote
- */
-int SSL_write(SSL *ssl, const void *buffer, int len)
-{
- int ret;
- int send_bytes, bytes;
- const unsigned char *pbuf;
-
- SSL_ASSERT1(ssl);
- SSL_ASSERT1(buffer);
- SSL_ASSERT1(len);
-
- ssl->rwstate = SSL_WRITING;
-
- send_bytes = len;
- pbuf = (const unsigned char *)buffer;
-
- do {
- if (send_bytes > SSL_SEND_DATA_MAX_LENGTH)
- bytes = SSL_SEND_DATA_MAX_LENGTH;
- else
- bytes = send_bytes;
-
- if (ssl->interrupted_remaining_write) {
- bytes = ssl->interrupted_remaining_write;
- ssl->interrupted_remaining_write = 0;
- }
-
- ret = SSL_METHOD_CALL(send, ssl, pbuf, bytes);
- //printf("%s: ssl_pm said %d for %d requested (cum %d)\n", __func__, ret, bytes, len -send_bytes);
- /* the return is a NEGATIVE OpenSSL error code, or the length sent */
- if (ret > 0) {
- pbuf += ret;
- send_bytes -= ret;
- } else
- ssl->interrupted_remaining_write = bytes;
- } while (ret > 0 && send_bytes && ret == bytes);
-
- if (ret >= 0) {
- ret = len - send_bytes;
- if (!ret)
- ssl->rwstate = SSL_NOTHING;
- } else {
- if (send_bytes == len)
- ret = -1;
- else
- ret = len - send_bytes;
- }
-
- return ret;
-}
-
-/**
- * @brief get SSL context of the SSL
- */
-SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl)
-{
- SSL_ASSERT2(ssl);
-
- return ssl->ctx;
-}
-
-/**
- * @brief get the SSL current method
- */
-const SSL_METHOD *SSL_get_ssl_method(SSL *ssl)
-{
- SSL_ASSERT2(ssl);
-
- return ssl->method;
-}
-
-/**
- * @brief set the SSL method
- */
-int SSL_set_ssl_method(SSL *ssl, const SSL_METHOD *method)
-{
- int ret;
-
- SSL_ASSERT1(ssl);
- SSL_ASSERT1(method);
-
- if (ssl->version != method->version) {
-
- ret = SSL_shutdown(ssl);
- if (1 != ret) {
- SSL_DEBUG(SSL_LIB_ERROR_LEVEL, "SSL_shutdown return %d", ret);
- goto failed1;
- }
-
- SSL_METHOD_CALL(free, ssl);
-
- ssl->method = method;
-
- ret = SSL_METHOD_CALL(new, ssl);
- if (!ret) {
- SSL_DEBUG(SSL_LIB_ERROR_LEVEL, "SSL_METHOD_CALL(new) return %d", ret);
- goto failed1;
- }
- } else {
- ssl->method = method;
- }
-
-
- return 1;
-
-failed1:
- return ret;
-}
-
-/**
- * @brief get SSL shutdown mode
- */
-int SSL_get_shutdown(const SSL *ssl)
-{
- SSL_ASSERT1(ssl);
-
- return ssl->shutdown;
-}
-
-/**
- * @brief set SSL shutdown mode
- */
-void SSL_set_shutdown(SSL *ssl, int mode)
-{
- SSL_ASSERT3(ssl);
-
- ssl->shutdown = mode;
-}
-
-
-/**
- * @brief get the number of the bytes to be read
- */
-int SSL_pending(const SSL *ssl)
-{
- int ret;
-
- SSL_ASSERT1(ssl);
-
- ret = SSL_METHOD_CALL(pending, ssl);
-
- return ret;
-}
-
-/**
- * @brief check if some data can be read
- */
-int SSL_has_pending(const SSL *ssl)
-{
- int ret;
-
- SSL_ASSERT1(ssl);
-
- if (SSL_pending(ssl))
- ret = 1;
- else
- ret = 0;
-
- return ret;
-}
-
-/**
- * @brief clear the SSL context option bit of "op"
- */
-unsigned long SSL_CTX_clear_options(SSL_CTX *ctx, unsigned long op)
-{
- SSL_ASSERT1(ctx);
-
- return ctx->options &= ~op;
-}
-
-/**
- * @brief get the SSL context option
- */
-unsigned long SSL_CTX_get_options(SSL_CTX *ctx)
-{
- SSL_ASSERT1(ctx);
-
- return ctx->options;
-}
-
-/**
- * @brief set the option of the SSL context
- */
-unsigned long SSL_CTX_set_options(SSL_CTX *ctx, unsigned long opt)
-{
- SSL_ASSERT1(ctx);
-
- return ctx->options |= opt;
-}
-
-/**
- * @brief clear SSL option
- */
-unsigned long SSL_clear_options(SSL *ssl, unsigned long op)
-{
- SSL_ASSERT1(ssl);
-
- return ssl->options & ~op;
-}
-
-/**
- * @brief get SSL option
- */
-unsigned long SSL_get_options(SSL *ssl)
-{
- SSL_ASSERT1(ssl);
-
- return ssl->options;
-}
-
-/**
- * @brief clear SSL option
- */
-unsigned long SSL_set_options(SSL *ssl, unsigned long op)
-{
- SSL_ASSERT1(ssl);
-
- return ssl->options |= op;
-}
-
-/**
- * @brief get the socket handle of the SSL
- */
-int SSL_get_fd(const SSL *ssl)
-{
- int ret;
-
- SSL_ASSERT1(ssl);
-
- ret = SSL_METHOD_CALL(get_fd, ssl, 0);
-
- return ret;
-}
-
-/**
- * @brief get the read only socket handle of the SSL
- */
-int SSL_get_rfd(const SSL *ssl)
-{
- int ret;
-
- SSL_ASSERT1(ssl);
-
- ret = SSL_METHOD_CALL(get_fd, ssl, 0);
-
- return ret;
-}
-
-/**
- * @brief get the write only socket handle of the SSL
- */
-int SSL_get_wfd(const SSL *ssl)
-{
- int ret;
-
- SSL_ASSERT1(ssl);
-
- ret = SSL_METHOD_CALL(get_fd, ssl, 0);
-
- return ret;
-}
-
-/**
- * @brief bind the socket file description into the SSL
- */
-int SSL_set_fd(SSL *ssl, int fd)
-{
- SSL_ASSERT1(ssl);
- SSL_ASSERT1(fd >= 0);
-
- SSL_METHOD_CALL(set_fd, ssl, fd, 0);
-
- return 1;
-}
-
-/**
- * @brief bind the read only socket file description into the SSL
- */
-int SSL_set_rfd(SSL *ssl, int fd)
-{
- SSL_ASSERT1(ssl);
- SSL_ASSERT1(fd >= 0);
-
- SSL_METHOD_CALL(set_fd, ssl, fd, 0);
-
- return 1;
-}
-
-/**
- * @brief bind the write only socket file description into the SSL
- */
-int SSL_set_wfd(SSL *ssl, int fd)
-{
- SSL_ASSERT1(ssl);
- SSL_ASSERT1(fd >= 0);
-
- SSL_METHOD_CALL(set_fd, ssl, fd, 0);
-
- return 1;
-}
-
-/**
- * @brief get SSL version
- */
-int SSL_version(const SSL *ssl)
-{
- SSL_ASSERT1(ssl);
-
- return ssl->version;
-}
-
-/**
- * @brief get the SSL version string
- */
-static const char* ssl_protocol_to_string(int version)
-{
- const char *str;
-
- if (version == TLS1_2_VERSION)
- str = "TLSv1.2";
- else if (version == TLS1_1_VERSION)
- str = "TLSv1.1";
- else if (version == TLS1_VERSION)
- str = "TLSv1";
- else if (version == SSL3_VERSION)
- str = "SSLv3";
- else
- str = "unknown";
-
- return str;
-}
-
-/**
- * @brief get the SSL current version
- */
-const char *SSL_get_version(const SSL *ssl)
-{
- SSL_ASSERT2(ssl);
-
- return ssl_protocol_to_string(SSL_version(ssl));
-}
-
-/**
- * @brief get alert description string
- */
-const char* SSL_alert_desc_string(int value)
-{
- const char *str;
-
- switch (value & 0xff)
- {
- case SSL3_AD_CLOSE_NOTIFY:
- str = "CN";
- break;
- case SSL3_AD_UNEXPECTED_MESSAGE:
- str = "UM";
- break;
- case SSL3_AD_BAD_RECORD_MAC:
- str = "BM";
- break;
- case SSL3_AD_DECOMPRESSION_FAILURE:
- str = "DF";
- break;
- case SSL3_AD_HANDSHAKE_FAILURE:
- str = "HF";
- break;
- case SSL3_AD_NO_CERTIFICATE:
- str = "NC";
- break;
- case SSL3_AD_BAD_CERTIFICATE:
- str = "BC";
- break;
- case SSL3_AD_UNSUPPORTED_CERTIFICATE:
- str = "UC";
- break;
- case SSL3_AD_CERTIFICATE_REVOKED:
- str = "CR";
- break;
- case SSL3_AD_CERTIFICATE_EXPIRED:
- str = "CE";
- break;
- case SSL3_AD_CERTIFICATE_UNKNOWN:
- str = "CU";
- break;
- case SSL3_AD_ILLEGAL_PARAMETER:
- str = "IP";
- break;
- case TLS1_AD_DECRYPTION_FAILED:
- str = "DC";
- break;
- case TLS1_AD_RECORD_OVERFLOW:
- str = "RO";
- break;
- case TLS1_AD_UNKNOWN_CA:
- str = "CA";
- break;
- case TLS1_AD_ACCESS_DENIED:
- str = "AD";
- break;
- case TLS1_AD_DECODE_ERROR:
- str = "DE";
- break;
- case TLS1_AD_DECRYPT_ERROR:
- str = "CY";
- break;
- case TLS1_AD_EXPORT_RESTRICTION:
- str = "ER";
- break;
- case TLS1_AD_PROTOCOL_VERSION:
- str = "PV";
- break;
- case TLS1_AD_INSUFFICIENT_SECURITY:
- str = "IS";
- break;
- case TLS1_AD_INTERNAL_ERROR:
- str = "IE";
- break;
- case TLS1_AD_USER_CANCELLED:
- str = "US";
- break;
- case TLS1_AD_NO_RENEGOTIATION:
- str = "NR";
- break;
- case TLS1_AD_UNSUPPORTED_EXTENSION:
- str = "UE";
- break;
- case TLS1_AD_CERTIFICATE_UNOBTAINABLE:
- str = "CO";
- break;
- case TLS1_AD_UNRECOGNIZED_NAME:
- str = "UN";
- break;
- case TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE:
- str = "BR";
- break;
- case TLS1_AD_BAD_CERTIFICATE_HASH_VALUE:
- str = "BH";
- break;
- case TLS1_AD_UNKNOWN_PSK_IDENTITY:
- str = "UP";
- break;
- default:
- str = "UK";
- break;
- }
-
- return str;
-}
-
-/**
- * @brief get alert description long string
- */
-const char* SSL_alert_desc_string_long(int value)
-{
- const char *str;
-
- switch (value & 0xff)
- {
- case SSL3_AD_CLOSE_NOTIFY:
- str = "close notify";
- break;
- case SSL3_AD_UNEXPECTED_MESSAGE:
- str = "unexpected_message";
- break;
- case SSL3_AD_BAD_RECORD_MAC:
- str = "bad record mac";
- break;
- case SSL3_AD_DECOMPRESSION_FAILURE:
- str = "decompression failure";
- break;
- case SSL3_AD_HANDSHAKE_FAILURE:
- str = "handshake failure";
- break;
- case SSL3_AD_NO_CERTIFICATE:
- str = "no certificate";
- break;
- case SSL3_AD_BAD_CERTIFICATE:
- str = "bad certificate";
- break;
- case SSL3_AD_UNSUPPORTED_CERTIFICATE:
- str = "unsupported certificate";
- break;
- case SSL3_AD_CERTIFICATE_REVOKED:
- str = "certificate revoked";
- break;
- case SSL3_AD_CERTIFICATE_EXPIRED:
- str = "certificate expired";
- break;
- case SSL3_AD_CERTIFICATE_UNKNOWN:
- str = "certificate unknown";
- break;
- case SSL3_AD_ILLEGAL_PARAMETER:
- str = "illegal parameter";
- break;
- case TLS1_AD_DECRYPTION_FAILED:
- str = "decryption failed";
- break;
- case TLS1_AD_RECORD_OVERFLOW:
- str = "record overflow";
- break;
- case TLS1_AD_UNKNOWN_CA:
- str = "unknown CA";
- break;
- case TLS1_AD_ACCESS_DENIED:
- str = "access denied";
- break;
- case TLS1_AD_DECODE_ERROR:
- str = "decode error";
- break;
- case TLS1_AD_DECRYPT_ERROR:
- str = "decrypt error";
- break;
- case TLS1_AD_EXPORT_RESTRICTION:
- str = "export restriction";
- break;
- case TLS1_AD_PROTOCOL_VERSION:
- str = "protocol version";
- break;
- case TLS1_AD_INSUFFICIENT_SECURITY:
- str = "insufficient security";
- break;
- case TLS1_AD_INTERNAL_ERROR:
- str = "internal error";
- break;
- case TLS1_AD_USER_CANCELLED:
- str = "user canceled";
- break;
- case TLS1_AD_NO_RENEGOTIATION:
- str = "no renegotiation";
- break;
- case TLS1_AD_UNSUPPORTED_EXTENSION:
- str = "unsupported extension";
- break;
- case TLS1_AD_CERTIFICATE_UNOBTAINABLE:
- str = "certificate unobtainable";
- break;
- case TLS1_AD_UNRECOGNIZED_NAME:
- str = "unrecognized name";
- break;
- case TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE:
- str = "bad certificate status response";
- break;
- case TLS1_AD_BAD_CERTIFICATE_HASH_VALUE:
- str = "bad certificate hash value";
- break;
- case TLS1_AD_UNKNOWN_PSK_IDENTITY:
- str = "unknown PSK identity";
- break;
- default:
- str = "unknown";
- break;
- }
-
- return str;
-}
-
-/**
- * @brief get alert type string
- */
-const char *SSL_alert_type_string(int value)
-{
- const char *str;
-
- switch (value >> 8)
- {
- case SSL3_AL_WARNING:
- str = "W";
- break;
- case SSL3_AL_FATAL:
- str = "F";
- break;
- default:
- str = "U";
- break;
- }
-
- return str;
-}
-
-/**
- * @brief get alert type long string
- */
-const char *SSL_alert_type_string_long(int value)
-{
- const char *str;
-
- switch (value >> 8)
- {
- case SSL3_AL_WARNING:
- str = "warning";
- break;
- case SSL3_AL_FATAL:
- str = "fatal";
- break;
- default:
- str = "unknown";
- break;
- }
-
- return str;
-}
-
-/**
- * @brief get the state string where SSL is reading
- */
-const char *SSL_rstate_string(SSL *ssl)
-{
- const char *str;
-
- SSL_ASSERT2(ssl);
-
- switch (ssl->rlayer.rstate)
- {
- case SSL_ST_READ_HEADER:
- str = "RH";
- break;
- case SSL_ST_READ_BODY:
- str = "RB";
- break;
- case SSL_ST_READ_DONE:
- str = "RD";
- break;
- default:
- str = "unknown";
- break;
- }
-
- return str;
-}
-
-/**
- * @brief get the statement long string where SSL is reading
- */
-const char *SSL_rstate_string_long(SSL *ssl)
-{
- const char *str = "unknown";
-
- SSL_ASSERT2(ssl);
-
- switch (ssl->rlayer.rstate)
- {
- case SSL_ST_READ_HEADER:
- str = "read header";
- break;
- case SSL_ST_READ_BODY:
- str = "read body";
- break;
- case SSL_ST_READ_DONE:
- str = "read done";
- break;
- default:
- break;
- }
-
- return str;
-}
-
-/**
- * @brief get SSL statement string
- */
-char *SSL_state_string(const SSL *ssl)
-{
- char *str = "UNKWN ";
-
- SSL_ASSERT2(ssl);
-
- if (ossl_statem_in_error(ssl))
- str = "SSLERR";
- else
- {
- switch (SSL_get_state(ssl))
- {
- case TLS_ST_BEFORE:
- str = "PINIT ";
- break;
- case TLS_ST_OK:
- str = "SSLOK ";
- break;
- case TLS_ST_CW_CLNT_HELLO:
- str = "TWCH";
- break;
- case TLS_ST_CR_SRVR_HELLO:
- str = "TRSH";
- break;
- case TLS_ST_CR_CERT:
- str = "TRSC";
- break;
- case TLS_ST_CR_KEY_EXCH:
- str = "TRSKE";
- break;
- case TLS_ST_CR_CERT_REQ:
- str = "TRCR";
- break;
- case TLS_ST_CR_SRVR_DONE:
- str = "TRSD";
- break;
- case TLS_ST_CW_CERT:
- str = "TWCC";
- break;
- case TLS_ST_CW_KEY_EXCH:
- str = "TWCKE";
- break;
- case TLS_ST_CW_CERT_VRFY:
- str = "TWCV";
- break;
- case TLS_ST_SW_CHANGE:
- case TLS_ST_CW_CHANGE:
- str = "TWCCS";
- break;
- case TLS_ST_SW_FINISHED:
- case TLS_ST_CW_FINISHED:
- str = "TWFIN";
- break;
- case TLS_ST_SR_CHANGE:
- case TLS_ST_CR_CHANGE:
- str = "TRCCS";
- break;
- case TLS_ST_SR_FINISHED:
- case TLS_ST_CR_FINISHED:
- str = "TRFIN";
- break;
- case TLS_ST_SW_HELLO_REQ:
- str = "TWHR";
- break;
- case TLS_ST_SR_CLNT_HELLO:
- str = "TRCH";
- break;
- case TLS_ST_SW_SRVR_HELLO:
- str = "TWSH";
- break;
- case TLS_ST_SW_CERT:
- str = "TWSC";
- break;
- case TLS_ST_SW_KEY_EXCH:
- str = "TWSKE";
- break;
- case TLS_ST_SW_CERT_REQ:
- str = "TWCR";
- break;
- case TLS_ST_SW_SRVR_DONE:
- str = "TWSD";
- break;
- case TLS_ST_SR_CERT:
- str = "TRCC";
- break;
- case TLS_ST_SR_KEY_EXCH:
- str = "TRCKE";
- break;
- case TLS_ST_SR_CERT_VRFY:
- str = "TRCV";
- break;
- case DTLS_ST_CR_HELLO_VERIFY_REQUEST:
- str = "DRCHV";
- break;
- case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
- str = "DWCHV";
- break;
- default:
- break;
- }
- }
-
- return str;
-}
-
-/**
- * @brief get SSL statement long string
- */
-char *SSL_state_string_long(const SSL *ssl)
-{
- char *str = "UNKWN ";
-
- SSL_ASSERT2(ssl);
-
- if (ossl_statem_in_error(ssl))
- str = "SSLERR";
- else
- {
- switch (SSL_get_state(ssl))
- {
- case TLS_ST_BEFORE:
- str = "before SSL initialization";
- break;
- case TLS_ST_OK:
- str = "SSL negotiation finished successfully";
- break;
- case TLS_ST_CW_CLNT_HELLO:
- str = "SSLv3/TLS write client hello";
- break;
- case TLS_ST_CR_SRVR_HELLO:
- str = "SSLv3/TLS read server hello";
- break;
- case TLS_ST_CR_CERT:
- str = "SSLv3/TLS read server certificate";
- break;
- case TLS_ST_CR_KEY_EXCH:
- str = "SSLv3/TLS read server key exchange";
- break;
- case TLS_ST_CR_CERT_REQ:
- str = "SSLv3/TLS read server certificate request";
- break;
- case TLS_ST_CR_SESSION_TICKET:
- str = "SSLv3/TLS read server session ticket";
- break;
- case TLS_ST_CR_SRVR_DONE:
- str = "SSLv3/TLS read server done";
- break;
- case TLS_ST_CW_CERT:
- str = "SSLv3/TLS write client certificate";
- break;
- case TLS_ST_CW_KEY_EXCH:
- str = "SSLv3/TLS write client key exchange";
- break;
- case TLS_ST_CW_CERT_VRFY:
- str = "SSLv3/TLS write certificate verify";
- break;
- case TLS_ST_CW_CHANGE:
- case TLS_ST_SW_CHANGE:
- str = "SSLv3/TLS write change cipher spec";
- break;
- case TLS_ST_CW_FINISHED:
- case TLS_ST_SW_FINISHED:
- str = "SSLv3/TLS write finished";
- break;
- case TLS_ST_CR_CHANGE:
- case TLS_ST_SR_CHANGE:
- str = "SSLv3/TLS read change cipher spec";
- break;
- case TLS_ST_CR_FINISHED:
- case TLS_ST_SR_FINISHED:
- str = "SSLv3/TLS read finished";
- break;
- case TLS_ST_SR_CLNT_HELLO:
- str = "SSLv3/TLS read client hello";
- break;
- case TLS_ST_SW_HELLO_REQ:
- str = "SSLv3/TLS write hello request";
- break;
- case TLS_ST_SW_SRVR_HELLO:
- str = "SSLv3/TLS write server hello";
- break;
- case TLS_ST_SW_CERT:
- str = "SSLv3/TLS write certificate";
- break;
- case TLS_ST_SW_KEY_EXCH:
- str = "SSLv3/TLS write key exchange";
- break;
- case TLS_ST_SW_CERT_REQ:
- str = "SSLv3/TLS write certificate request";
- break;
- case TLS_ST_SW_SESSION_TICKET:
- str = "SSLv3/TLS write session ticket";
- break;
- case TLS_ST_SW_SRVR_DONE:
- str = "SSLv3/TLS write server done";
- break;
- case TLS_ST_SR_CERT:
- str = "SSLv3/TLS read client certificate";
- break;
- case TLS_ST_SR_KEY_EXCH:
- str = "SSLv3/TLS read client key exchange";
- break;
- case TLS_ST_SR_CERT_VRFY:
- str = "SSLv3/TLS read certificate verify";
- break;
- case DTLS_ST_CR_HELLO_VERIFY_REQUEST:
- str = "DTLS1 read hello verify request";
- break;
- case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
- str = "DTLS1 write hello verify request";
- break;
- default:
- break;
- }
- }
-
- return str;
-}
-
-/**
- * @brief set the SSL context read buffer length
- */
-void SSL_CTX_set_default_read_buffer_len(SSL_CTX *ctx, size_t len)
-{
- SSL_ASSERT3(ctx);
-
- ctx->read_buffer_len = len;
-}
-
-/**
- * @brief set the SSL read buffer length
- */
-void SSL_set_default_read_buffer_len(SSL *ssl, size_t len)
-{
- SSL_ASSERT3(ssl);
- SSL_ASSERT3(len);
-
- SSL_METHOD_CALL(set_bufflen, ssl, len);
-}
-
-/**
- * @brief set the SSL information callback function
- */
-void SSL_set_info_callback(SSL *ssl, void (*cb) (const SSL *ssl, int type, int val))
-{
- SSL_ASSERT3(ssl);
-
- ssl->info_callback = cb;
-}
-
-/**
- * @brief add SSL context reference count by '1'
- */
-int SSL_CTX_up_ref(SSL_CTX *ctx)
-{
- SSL_ASSERT1(ctx);
-
- /**
- * no support multi-thread SSL here
- */
- ctx->references++;
-
- return 1;
-}
-
-/**
- * @brief set the SSL security level
- */
-void SSL_set_security_level(SSL *ssl, int level)
-{
- SSL_ASSERT3(ssl);
-
- ssl->cert->sec_level = level;
-}
-
-/**
- * @brief get the SSL security level
- */
-int SSL_get_security_level(const SSL *ssl)
-{
- SSL_ASSERT1(ssl);
-
- return ssl->cert->sec_level;
-}
-
-/**
- * @brief get the SSL verifying mode of the SSL context
- */
-int SSL_CTX_get_verify_mode(const SSL_CTX *ctx)
-{
- SSL_ASSERT1(ctx);
-
- return ctx->verify_mode;
-}
-
-/**
- * @brief set the session timeout time
- */
-long SSL_CTX_set_timeout(SSL_CTX *ctx, long t)
-{
- long l;
-
- SSL_ASSERT1(ctx);
-
- l = ctx->session_timeout;
- ctx->session_timeout = t;
-
- return l;
-}
-
-/**
- * @brief get the session timeout time
- */
-long SSL_CTX_get_timeout(const SSL_CTX *ctx)
-{
- SSL_ASSERT1(ctx);
-
- return ctx->session_timeout;
-}
-
-/**
- * @brief set the SSL if we can read as many as data
- */
-void SSL_set_read_ahead(SSL *ssl, int yes)
-{
- SSL_ASSERT3(ssl);
-
- ssl->rlayer.read_ahead = yes;
-}
-
-/**
- * @brief set the SSL context if we can read as many as data
- */
-void SSL_CTX_set_read_ahead(SSL_CTX *ctx, int yes)
-{
- SSL_ASSERT3(ctx);
-
- ctx->read_ahead = yes;
-}
-
-/**
- * @brief get the SSL ahead signal if we can read as many as data
- */
-int SSL_get_read_ahead(const SSL *ssl)
-{
- SSL_ASSERT1(ssl);
-
- return ssl->rlayer.read_ahead;
-}
-
-/**
- * @brief get the SSL context ahead signal if we can read as many as data
- */
-long SSL_CTX_get_read_ahead(SSL_CTX *ctx)
-{
- SSL_ASSERT1(ctx);
-
- return ctx->read_ahead;
-}
-
-/**
- * @brief check if the SSL context can read as many as data
- */
-long SSL_CTX_get_default_read_ahead(SSL_CTX *ctx)
-{
- SSL_ASSERT1(ctx);
-
- return ctx->read_ahead;
-}
-
-/**
- * @brief set SSL session time
- */
-long SSL_set_time(SSL *ssl, long t)
-{
- SSL_ASSERT1(ssl);
-
- ssl->session->time = t;
-
- return t;
-}
-
-/**
- * @brief set SSL session timeout time
- */
-long SSL_set_timeout(SSL *ssl, long t)
-{
- SSL_ASSERT1(ssl);
-
- ssl->session->timeout = t;
-
- return t;
-}
-
-/**
- * @brief get the verifying result of the SSL certification
- */
-long SSL_get_verify_result(const SSL *ssl)
-{
- SSL_ASSERT1(ssl);
-
- return SSL_METHOD_CALL(get_verify_result, ssl);
-}
-
-/**
- * @brief get the SSL verifying depth of the SSL context
- */
-int SSL_CTX_get_verify_depth(const SSL_CTX *ctx)
-{
- SSL_ASSERT1(ctx);
-
- return ctx->param.depth;
-}
-
-/**
- * @brief set the SSL verify depth of the SSL context
- */
-void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth)
-{
- SSL_ASSERT3(ctx);
-
- ctx->param.depth = depth;
-}
-
-/**
- * @brief get the SSL verifying depth of the SSL
- */
-int SSL_get_verify_depth(const SSL *ssl)
-{
- SSL_ASSERT1(ssl);
-
- return ssl->param.depth;
-}
-
-/**
- * @brief set the SSL verify depth of the SSL
- */
-void SSL_set_verify_depth(SSL *ssl, int depth)
-{
- SSL_ASSERT3(ssl);
-
- ssl->param.depth = depth;
-}
-
-/**
- * @brief set the SSL context verifying of the SSL context
- */
-void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, int (*verify_callback)(int, X509_STORE_CTX *))
-{
- SSL_ASSERT3(ctx);
-
- ctx->verify_mode = mode;
- ctx->default_verify_callback = verify_callback;
-}
-
-/**
- * @brief set the SSL verifying of the SSL context
- */
-void SSL_set_verify(SSL *ssl, int mode, int (*verify_callback)(int, X509_STORE_CTX *))
-{
- SSL_ASSERT3(ssl);
-
- ssl->verify_mode = mode;
- ssl->verify_callback = verify_callback;
-}
-
-void ERR_error_string_n(unsigned long e, char *buf, size_t len)
-{
- lws_strncpy(buf, "unknown", len);
-}
-
-void ERR_free_strings(void)
-{
-}
-
-char *ERR_error_string(unsigned long e, char *buf)
-{
- if (!buf)
- return "unknown";
-
- switch(e) {
- case X509_V_ERR_INVALID_CA:
- strcpy(buf, "CA is not trusted");
- break;
- case X509_V_ERR_HOSTNAME_MISMATCH:
- strcpy(buf, "Hostname mismatch");
- break;
- case X509_V_ERR_CA_KEY_TOO_SMALL:
- strcpy(buf, "CA key too small");
- break;
- case X509_V_ERR_CA_MD_TOO_WEAK:
- strcpy(buf, "MD key too weak");
- break;
- case X509_V_ERR_CERT_NOT_YET_VALID:
- strcpy(buf, "Cert from the future");
- break;
- case X509_V_ERR_CERT_HAS_EXPIRED:
- strcpy(buf, "Cert expired");
- break;
- default:
- strcpy(buf, "unknown");
- break;
- }
-
- return buf;
-}
-
-void *SSL_CTX_get_ex_data(const SSL_CTX *ctx, int idx)
-{
- return NULL;
-}
-
-/*
- * Openssl wants the valid protocol names supplied like this:
- *
- * (unsigned char *)"\x02h2\x08http/1.1", 6 + 9
- *
- * Mbedtls wants this:
- *
- * Pointer to a NULL-terminated list of supported protocols, in decreasing
- * preference order. The pointer to the list is recorded by the library for
- * later reference as required, so the lifetime of the table must be at least
- * as long as the lifetime of the SSL configuration structure.
- *
- * So accept the OpenSSL style and convert to mbedtls style
- */
-
-struct alpn_ctx {
- unsigned char data[23];
- unsigned char len;
-};
-
-static void
-_openssl_alpn_to_mbedtls(struct alpn_ctx *ac, char ***palpn_protos)
-{
- unsigned char *p = ac->data, *q;
- unsigned char len;
- char **alpn_protos;
- int count = 0;
-
- /* find out how many entries he gave us */
-
- len = *p++;
- while (p - ac->data < ac->len) {
- if (len--) {
- p++;
- continue;
- }
- count++;
- len = *p++;
- if (!len)
- break;
- }
-
- if (!len)
- count++;
-
- if (!count)
- return;
-
- /* allocate space for count + 1 pointers and the data afterwards */
-
- alpn_protos = ssl_mem_zalloc((count + 1) * sizeof(char *) + ac->len + 1);
- if (!alpn_protos)
- return;
-
- *palpn_protos = alpn_protos;
-
- /* convert to mbedtls format */
-
- q = (unsigned char *)alpn_protos + (count + 1) * sizeof(char *);
- p = ac->data;
- count = 0;
-
- len = *p++;
- alpn_protos[count] = (char *)q;
- while (p - ac->data < ac->len) {
- if (len--) {
- *q++ = *p++;
- continue;
- }
- *q++ = '\0';
- count++;
- len = *p++;
- alpn_protos[count] = (char *)q;
- if (!len)
- break;
- }
- if (!len) {
- *q++ = '\0';
- count++;
- len = *p++;
- alpn_protos[count] = (char *)q;
- }
- alpn_protos[count] = NULL; /* last pointer ends list with NULL */
-}
-
-void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx, next_proto_cb cb, void *arg)
-{
- struct alpn_ctx *ac = arg;
-
- ctx->alpn_cb = cb;
-
- _openssl_alpn_to_mbedtls(ac, (char ***)&ctx->alpn_protos);
-}
-
-void SSL_set_alpn_select_cb(SSL *ssl, void *arg)
-{
- struct alpn_ctx *ac = arg;
-
- _openssl_alpn_to_mbedtls(ac, (char ***)&ssl->alpn_protos);
-
- _ssl_set_alpn_list(ssl);
-}
diff --git a/thirdparty/libwebsockets/tls/mbedtls/wrapper/library/ssl_methods.c b/thirdparty/libwebsockets/tls/mbedtls/wrapper/library/ssl_methods.c
deleted file mode 100644
index 0002360846..0000000000
--- a/thirdparty/libwebsockets/tls/mbedtls/wrapper/library/ssl_methods.c
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "ssl_methods.h"
-#include "ssl_pm.h"
-
-/**
- * TLS method function collection
- */
-IMPLEMENT_TLS_METHOD_FUNC(TLS_method_func,
- ssl_pm_new, ssl_pm_free,
- ssl_pm_handshake, ssl_pm_shutdown, ssl_pm_clear,
- ssl_pm_read, ssl_pm_send, ssl_pm_pending,
- ssl_pm_set_fd, ssl_pm_get_fd,
- ssl_pm_set_bufflen,
- ssl_pm_get_verify_result,
- ssl_pm_get_state);
-
-/**
- * TLS or SSL client method collection
- */
-IMPLEMENT_TLS_METHOD(TLS_ANY_VERSION, 0, TLS_method_func, TLS_client_method);
-
-IMPLEMENT_TLS_METHOD(TLS1_2_VERSION, 0, TLS_method_func, TLSv1_2_client_method);
-
-IMPLEMENT_TLS_METHOD(TLS1_1_VERSION, 0, TLS_method_func, TLSv1_1_client_method);
-
-IMPLEMENT_TLS_METHOD(TLS1_VERSION, 0, TLS_method_func, TLSv1_client_method);
-
-IMPLEMENT_SSL_METHOD(SSL3_VERSION, 0, TLS_method_func, SSLv3_client_method);
-
-/**
- * TLS or SSL server method collection
- */
-IMPLEMENT_TLS_METHOD(TLS_ANY_VERSION, 1, TLS_method_func, TLS_server_method);
-
-IMPLEMENT_TLS_METHOD(TLS1_1_VERSION, 1, TLS_method_func, TLSv1_1_server_method);
-
-IMPLEMENT_TLS_METHOD(TLS1_2_VERSION, 1, TLS_method_func, TLSv1_2_server_method);
-
-IMPLEMENT_TLS_METHOD(TLS1_VERSION, 0, TLS_method_func, TLSv1_server_method);
-
-IMPLEMENT_SSL_METHOD(SSL3_VERSION, 1, TLS_method_func, SSLv3_server_method);
-
-/**
- * TLS or SSL method collection
- */
-IMPLEMENT_TLS_METHOD(TLS_ANY_VERSION, -1, TLS_method_func, TLS_method);
-
-IMPLEMENT_SSL_METHOD(TLS1_2_VERSION, -1, TLS_method_func, TLSv1_2_method);
-
-IMPLEMENT_SSL_METHOD(TLS1_1_VERSION, -1, TLS_method_func, TLSv1_1_method);
-
-IMPLEMENT_SSL_METHOD(TLS1_VERSION, -1, TLS_method_func, TLSv1_method);
-
-IMPLEMENT_SSL_METHOD(SSL3_VERSION, -1, TLS_method_func, SSLv3_method);
-
-/**
- * @brief get X509 object method
- */
-IMPLEMENT_X509_METHOD(X509_method,
- x509_pm_new, x509_pm_free,
- x509_pm_load, x509_pm_show_info);
-
-/**
- * @brief get private key object method
- */
-IMPLEMENT_PKEY_METHOD(EVP_PKEY_method,
- pkey_pm_new, pkey_pm_free,
- pkey_pm_load);
diff --git a/thirdparty/libwebsockets/tls/mbedtls/wrapper/library/ssl_pkey.c b/thirdparty/libwebsockets/tls/mbedtls/wrapper/library/ssl_pkey.c
deleted file mode 100644
index 567a33e2c2..0000000000
--- a/thirdparty/libwebsockets/tls/mbedtls/wrapper/library/ssl_pkey.c
+++ /dev/null
@@ -1,239 +0,0 @@
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "ssl_pkey.h"
-#include "ssl_methods.h"
-#include "ssl_dbg.h"
-#include "ssl_port.h"
-
-/**
- * @brief create a private key object according to input private key
- */
-EVP_PKEY* __EVP_PKEY_new(EVP_PKEY *ipk)
-{
- int ret;
- EVP_PKEY *pkey;
-
- pkey = ssl_mem_zalloc(sizeof(EVP_PKEY));
- if (!pkey) {
- SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "no enough memory > (pkey)");
- goto no_mem;
- }
-
- if (ipk) {
- pkey->method = ipk->method;
- } else {
- pkey->method = EVP_PKEY_method();
- }
-
- ret = EVP_PKEY_METHOD_CALL(new, pkey, ipk);
- if (ret) {
- SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "EVP_PKEY_METHOD_CALL(new) return %d", ret);
- goto failed;
- }
-
- return pkey;
-
-failed:
- ssl_mem_free(pkey);
-no_mem:
- return NULL;
-}
-
-/**
- * @brief create a private key object
- */
-EVP_PKEY* EVP_PKEY_new(void)
-{
- return __EVP_PKEY_new(NULL);
-}
-
-/**
- * @brief free a private key object
- */
-void EVP_PKEY_free(EVP_PKEY *pkey)
-{
- SSL_ASSERT3(pkey);
-
- EVP_PKEY_METHOD_CALL(free, pkey);
-
- ssl_mem_free(pkey);
-}
-
-/**
- * @brief load a character key context into system context. If '*a' is pointed to the
- * private key, then load key into it. Or create a new private key object
- */
-EVP_PKEY *d2i_PrivateKey(int type,
- EVP_PKEY **a,
- const unsigned char **pp,
- long length)
-{
- int m = 0;
- int ret;
- EVP_PKEY *pkey;
-
- SSL_ASSERT2(pp);
- SSL_ASSERT2(*pp);
- SSL_ASSERT2(length);
-
- if (a && *a) {
- pkey = *a;
- } else {
- pkey = EVP_PKEY_new();;
- if (!pkey) {
- SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "EVP_PKEY_new() return NULL");
- goto failed1;
- }
-
- m = 1;
- }
-
- ret = EVP_PKEY_METHOD_CALL(load, pkey, *pp, length);
- if (ret) {
- SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "EVP_PKEY_METHOD_CALL(load) return %d", ret);
- goto failed2;
- }
-
- if (a)
- *a = pkey;
-
- return pkey;
-
-failed2:
- if (m)
- EVP_PKEY_free(pkey);
-failed1:
- return NULL;
-}
-
-/**
- * @brief set the SSL context private key
- */
-int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey)
-{
- SSL_ASSERT1(ctx);
- SSL_ASSERT1(pkey);
-
- if (ctx->cert->pkey == pkey)
- return 1;
-
- if (ctx->cert->pkey)
- EVP_PKEY_free(ctx->cert->pkey);
-
- ctx->cert->pkey = pkey;
-
- return 1;
-}
-
-/**
- * @brief set the SSL private key
- */
-int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey)
-{
- SSL_ASSERT1(ssl);
- SSL_ASSERT1(pkey);
-
- if (ssl->cert->pkey == pkey)
- return 1;
-
- if (ssl->cert->pkey)
- EVP_PKEY_free(ssl->cert->pkey);
-
- ssl->cert->pkey = pkey;
-
- return 1;
-}
-
-/**
- * @brief load private key into the SSL context
- */
-int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx,
- const unsigned char *d, long len)
-{
- int ret;
- EVP_PKEY *pk;
-
- pk = d2i_PrivateKey(0, NULL, &d, len);
- if (!pk) {
- SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "d2i_PrivateKey() return NULL");
- goto failed1;
- }
-
- ret = SSL_CTX_use_PrivateKey(ctx, pk);
- if (!ret) {
- SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "SSL_CTX_use_PrivateKey() return %d", ret);
- goto failed2;
- }
-
- return 1;
-
-failed2:
- EVP_PKEY_free(pk);
-failed1:
- return 0;
-}
-
-/**
- * @brief load private key into the SSL
- */
-int SSL_use_PrivateKey_ASN1(int type, SSL *ssl,
- const unsigned char *d, long len)
-{
- int ret;
- EVP_PKEY *pk;
-
- pk = d2i_PrivateKey(0, NULL, &d, len);
- if (!pk) {
- SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "d2i_PrivateKey() return NULL");
- goto failed1;
- }
-
- ret = SSL_use_PrivateKey(ssl, pk);
- if (!ret) {
- SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "SSL_use_PrivateKey() return %d", ret);
- goto failed2;
- }
-
- return 1;
-
-failed2:
- EVP_PKEY_free(pk);
-failed1:
- return 0;
-}
-
-/**
- * @brief load the private key file into SSL context
- */
-int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type)
-{
- return 0;
-}
-
-/**
- * @brief load the private key file into SSL
- */
-int SSL_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type)
-{
- return 0;
-}
-
-/**
- * @brief load the RSA ASN1 private key into SSL context
- */
-int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d, long len)
-{
- return SSL_CTX_use_PrivateKey_ASN1(0, ctx, d, len);
-}
diff --git a/thirdparty/libwebsockets/tls/mbedtls/wrapper/library/ssl_stack.c b/thirdparty/libwebsockets/tls/mbedtls/wrapper/library/ssl_stack.c
deleted file mode 100644
index da836daf9c..0000000000
--- a/thirdparty/libwebsockets/tls/mbedtls/wrapper/library/ssl_stack.c
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "ssl_stack.h"
-#include "ssl_dbg.h"
-#include "ssl_port.h"
-
-#ifndef CONFIG_MIN_NODES
- #define MIN_NODES 4
-#else
- #define MIN_NODES CONFIG_MIN_NODES
-#endif
-
-/**
- * @brief create a openssl stack object
- */
-OPENSSL_STACK* OPENSSL_sk_new(OPENSSL_sk_compfunc c)
-{
- OPENSSL_STACK *stack;
- char **data;
-
- stack = ssl_mem_zalloc(sizeof(OPENSSL_STACK));
- if (!stack) {
- SSL_DEBUG(SSL_STACK_ERROR_LEVEL, "no enough memory > (stack)");
- goto no_mem1;
- }
-
- data = ssl_mem_zalloc(sizeof(*data) * MIN_NODES);
- if (!data) {
- SSL_DEBUG(SSL_STACK_ERROR_LEVEL, "no enough memory > (data)");
- goto no_mem2;
- }
-
- stack->data = data;
- stack->num_alloc = MIN_NODES;
- stack->c = c;
-
- return stack;
-
-no_mem2:
- ssl_mem_free(stack);
-no_mem1:
- return NULL;
-}
-
-/**
- * @brief create a NULL function openssl stack object
- */
-OPENSSL_STACK *OPENSSL_sk_new_null(void)
-{
- return OPENSSL_sk_new((OPENSSL_sk_compfunc)NULL);
-}
-
-/**
- * @brief free openssl stack object
- */
-void OPENSSL_sk_free(OPENSSL_STACK *stack)
-{
- SSL_ASSERT3(stack);
-
- ssl_mem_free(stack->data);
- ssl_mem_free(stack);
-}
diff --git a/thirdparty/libwebsockets/tls/mbedtls/wrapper/library/ssl_x509.c b/thirdparty/libwebsockets/tls/mbedtls/wrapper/library/ssl_x509.c
deleted file mode 100644
index ed79150831..0000000000
--- a/thirdparty/libwebsockets/tls/mbedtls/wrapper/library/ssl_x509.c
+++ /dev/null
@@ -1,354 +0,0 @@
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "ssl_x509.h"
-#include "ssl_methods.h"
-#include "ssl_dbg.h"
-#include "ssl_port.h"
-
-#include <assert.h>
-
-/**
- * @brief show X509 certification information
- */
-int __X509_show_info(X509 *x)
-{
- return X509_METHOD_CALL(show_info, x);
-}
-
-/**
- * @brief create a X509 certification object according to input X509 certification
- */
-X509* __X509_new(X509 *ix)
-{
- int ret;
- X509 *x;
-
- x = ssl_mem_zalloc(sizeof(X509));
- if (!x) {
- SSL_DEBUG(SSL_X509_ERROR_LEVEL, "no enough memory > (x)");
- goto no_mem;
- }
-
- if (ix)
- x->method = ix->method;
- else
- x->method = X509_method();
-
- ret = X509_METHOD_CALL(new, x, ix);
- if (ret) {
- SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "X509_METHOD_CALL(new) return %d", ret);
- goto failed;
- }
-
- return x;
-
-failed:
- ssl_mem_free(x);
-no_mem:
- return NULL;
-}
-
-/**
- * @brief create a X509 certification object
- */
-X509* X509_new(void)
-{
- return __X509_new(NULL);
-}
-
-/**
- * @brief free a X509 certification object
- */
-void X509_free(X509 *x)
-{
- SSL_ASSERT3(x);
-
- X509_METHOD_CALL(free, x);
-
- ssl_mem_free(x);
-};
-
-/**
- * @brief load a character certification context into system context. If '*cert' is pointed to the
- * certification, then load certification into it. Or create a new X509 certification object
- */
-X509* d2i_X509(X509 **cert, const unsigned char *buffer, long len)
-{
- int m = 0;
- int ret;
- X509 *x;
-
- SSL_ASSERT2(buffer);
- SSL_ASSERT2(len);
-
- if (cert && *cert) {
- x = *cert;
- } else {
- x = X509_new();
- if (!x) {
- SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "X509_new() return NULL");
- goto failed1;
- }
- m = 1;
- }
-
- ret = X509_METHOD_CALL(load, x, buffer, len);
- if (ret) {
- SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "X509_METHOD_CALL(load) return %d", ret);
- goto failed2;
- }
-
- return x;
-
-failed2:
- if (m)
- X509_free(x);
-failed1:
- return NULL;
-}
-
-/**
- * @brief return SSL X509 verify parameters
- */
-
-X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl)
-{
- return &ssl->param;
-}
-
-/**
- * @brief set X509 host verification flags
- */
-
-int X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param,
- unsigned long flags)
-{
- /* flags not supported yet */
- return 0;
-}
-
-/**
- * @brief clear X509 host verification flags
- */
-
-int X509_VERIFY_PARAM_clear_hostflags(X509_VERIFY_PARAM *param,
- unsigned long flags)
-{
- /* flags not supported yet */
- return 0;
-}
-
-/**
- * @brief set SSL context client CA certification
- */
-int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x)
-{
- SSL_ASSERT1(ctx);
- SSL_ASSERT1(x);
- assert(ctx);
- if (ctx->client_CA == x)
- return 1;
-
- X509_free(ctx->client_CA);
-
- ctx->client_CA = x;
-
- return 1;
-}
-
-/**
- * @brief add CA client certification into the SSL
- */
-int SSL_CTX_add_client_CA_ASN1(SSL_CTX *ctx, int len,
- const unsigned char *d)
-{
- X509 *x;
-
- x = d2i_X509(NULL, d, len);
- if (!x) {
- SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "d2i_X509() return NULL");
- return 0;
- }
- SSL_ASSERT1(ctx);
-
- X509_free(ctx->client_CA);
-
- ctx->client_CA = x;
-
- return 1;
-}
-
-/**
- * @brief add CA client certification into the SSL
- */
-int SSL_add_client_CA(SSL *ssl, X509 *x)
-{
- SSL_ASSERT1(ssl);
- SSL_ASSERT1(x);
-
- if (ssl->client_CA == x)
- return 1;
-
- X509_free(ssl->client_CA);
-
- ssl->client_CA = x;
-
- return 1;
-}
-
-/**
- * @brief set the SSL context certification
- */
-int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x)
-{
- SSL_ASSERT1(ctx);
- SSL_ASSERT1(x);
-
- if (ctx->cert->x509 == x)
- return 1;
-
- X509_free(ctx->cert->x509);
-
- ctx->cert->x509 = x;
-
- return 1;
-}
-
-/**
- * @brief set the SSL certification
- */
-int SSL_use_certificate(SSL *ssl, X509 *x)
-{
- SSL_ASSERT1(ssl);
- SSL_ASSERT1(x);
-
- if (ssl->cert->x509 == x)
- return 1;
-
- X509_free(ssl->cert->x509);
-
- ssl->cert->x509 = x;
-
- return 1;
-}
-
-/**
- * @brief get the SSL certification point
- */
-X509 *SSL_get_certificate(const SSL *ssl)
-{
- SSL_ASSERT2(ssl);
-
- return ssl->cert->x509;
-}
-
-/**
- * @brief load certification into the SSL context
- */
-int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len,
- const unsigned char *d)
-{
- int ret;
- X509 *x;
-
- x = d2i_X509(NULL, d, len);
- if (!x) {
- SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "d2i_X509() return NULL");
- goto failed1;
- }
-
- ret = SSL_CTX_use_certificate(ctx, x);
- if (!ret) {
- SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "SSL_CTX_use_certificate() return %d", ret);
- goto failed2;
- }
-
- return 1;
-
-failed2:
- X509_free(x);
-failed1:
- return 0;
-}
-
-/**
- * @brief load certification into the SSL
- */
-int SSL_use_certificate_ASN1(SSL *ssl, int len,
- const unsigned char *d)
-{
- int ret;
- X509 *x;
-
- x = d2i_X509(NULL, d, len);
- if (!x) {
- SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "d2i_X509() return NULL");
- goto failed1;
- }
-
- ret = SSL_use_certificate(ssl, x);
- if (!ret) {
- SSL_DEBUG(SSL_PKEY_ERROR_LEVEL, "SSL_use_certificate() return %d", ret);
- goto failed2;
- }
-
- return 1;
-
-failed2:
- X509_free(x);
-failed1:
- return 0;
-}
-
-/**
- * @brief load the certification file into SSL context
- */
-int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type)
-{
- return 0;
-}
-
-/**
- * @brief load the certification file into SSL
- */
-int SSL_use_certificate_file(SSL *ssl, const char *file, int type)
-{
- return 0;
-}
-
-/**
- * @brief get peer certification
- */
-X509 *SSL_get_peer_certificate(const SSL *ssl)
-{
- SSL_ASSERT2(ssl);
-
- return ssl->session->peer;
-}
-
-int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx)
-{
- return X509_V_ERR_UNSPECIFIED;
-}
-
-int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx)
-{
- return 0;
-}
-
-const char *X509_verify_cert_error_string(long n)
-{
- return "unknown";
-}
diff --git a/thirdparty/libwebsockets/tls/mbedtls/wrapper/platform/ssl_pm.c b/thirdparty/libwebsockets/tls/mbedtls/wrapper/platform/ssl_pm.c
deleted file mode 100755
index 4716c1ff56..0000000000
--- a/thirdparty/libwebsockets/tls/mbedtls/wrapper/platform/ssl_pm.c
+++ /dev/null
@@ -1,907 +0,0 @@
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "ssl_pm.h"
-#include "ssl_port.h"
-#include "ssl_dbg.h"
-
-/* mbedtls include */
-#include "mbedtls/platform.h"
-#include "mbedtls/net_sockets.h"
-#include "mbedtls/debug.h"
-#include "mbedtls/entropy.h"
-#include "mbedtls/ctr_drbg.h"
-#include "mbedtls/error.h"
-#include "mbedtls/certs.h"
-
-#include <libwebsockets.h>
-
-#define X509_INFO_STRING_LENGTH 8192
-
-struct ssl_pm
-{
- /* local socket file description */
- mbedtls_net_context fd;
- /* remote client socket file description */
- mbedtls_net_context cl_fd;
-
- mbedtls_ssl_config conf;
-
- mbedtls_ctr_drbg_context ctr_drbg;
-
- mbedtls_ssl_context ssl;
-
- mbedtls_entropy_context entropy;
-
- SSL *owner;
-};
-
-struct x509_pm
-{
- mbedtls_x509_crt *x509_crt;
-
- mbedtls_x509_crt *ex_crt;
-};
-
-struct pkey_pm
-{
- mbedtls_pk_context *pkey;
-
- mbedtls_pk_context *ex_pkey;
-};
-
-unsigned int max_content_len;
-
-/*********************************************************************************************/
-/************************************ SSL arch interface *************************************/
-
-//#ifdef CONFIG_OPENSSL_LOWLEVEL_DEBUG
-
-/* mbedtls debug level */
-#define MBEDTLS_DEBUG_LEVEL 4
-
-/**
- * @brief mbedtls debug function
- */
-static void ssl_platform_debug(void *ctx, int level,
- const char *file, int line,
- const char *str)
-{
- /* Shorten 'file' from the whole file path to just the filename
-
- This is a bit wasteful because the macros are compiled in with
- the full _FILE_ path in each case.
- */
-// char *file_sep = rindex(file, '/');
- // if(file_sep)
- // file = file_sep + 1;
-
- printf("%s:%d %s", file, line, str);
-}
-//#endif
-
-/**
- * @brief create SSL low-level object
- */
-int ssl_pm_new(SSL *ssl)
-{
- struct ssl_pm *ssl_pm;
- int ret;
-
- const unsigned char pers[] = "OpenSSL PM";
- size_t pers_len = sizeof(pers);
-
- int endpoint;
- int version;
-
- const SSL_METHOD *method = ssl->method;
-
- ssl_pm = ssl_mem_zalloc(sizeof(struct ssl_pm));
- if (!ssl_pm) {
- SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL, "no enough memory > (ssl_pm)");
- goto no_mem;
- }
-
- ssl_pm->owner = ssl;
-
- if (!ssl->ctx->read_buffer_len)
- ssl->ctx->read_buffer_len = 2048;
-
- max_content_len = ssl->ctx->read_buffer_len;
- // printf("ssl->ctx->read_buffer_len = %d ++++++++++++++++++++\n", ssl->ctx->read_buffer_len);
-
- mbedtls_net_init(&ssl_pm->fd);
- mbedtls_net_init(&ssl_pm->cl_fd);
-
- mbedtls_ssl_config_init(&ssl_pm->conf);
- mbedtls_ctr_drbg_init(&ssl_pm->ctr_drbg);
- mbedtls_entropy_init(&ssl_pm->entropy);
- mbedtls_ssl_init(&ssl_pm->ssl);
-
- ret = mbedtls_ctr_drbg_seed(&ssl_pm->ctr_drbg, mbedtls_entropy_func, &ssl_pm->entropy, pers, pers_len);
- if (ret) {
- SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL, "mbedtls_ctr_drbg_seed() return -0x%x", -ret);
- goto mbedtls_err1;
- }
-
- if (method->endpoint) {
- endpoint = MBEDTLS_SSL_IS_SERVER;
- } else {
- endpoint = MBEDTLS_SSL_IS_CLIENT;
- }
- ret = mbedtls_ssl_config_defaults(&ssl_pm->conf, endpoint, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT);
- if (ret) {
- SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL, "mbedtls_ssl_config_defaults() return -0x%x", -ret);
- goto mbedtls_err2;
- }
-
- if (TLS_ANY_VERSION != ssl->version) {
- if (TLS1_2_VERSION == ssl->version)
- version = MBEDTLS_SSL_MINOR_VERSION_3;
- else if (TLS1_1_VERSION == ssl->version)
- version = MBEDTLS_SSL_MINOR_VERSION_2;
- else if (TLS1_VERSION == ssl->version)
- version = MBEDTLS_SSL_MINOR_VERSION_1;
- else
- version = MBEDTLS_SSL_MINOR_VERSION_0;
-
- mbedtls_ssl_conf_max_version(&ssl_pm->conf, MBEDTLS_SSL_MAJOR_VERSION_3, version);
- mbedtls_ssl_conf_min_version(&ssl_pm->conf, MBEDTLS_SSL_MAJOR_VERSION_3, version);
- } else {
- mbedtls_ssl_conf_max_version(&ssl_pm->conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3);
- mbedtls_ssl_conf_min_version(&ssl_pm->conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0);
- }
-
- mbedtls_ssl_conf_rng(&ssl_pm->conf, mbedtls_ctr_drbg_random, &ssl_pm->ctr_drbg);
-
-//#ifdef CONFIG_OPENSSL_LOWLEVEL_DEBUG
- // mbedtls_debug_set_threshold(MBEDTLS_DEBUG_LEVEL);
-// mbedtls_ssl_conf_dbg(&ssl_pm->conf, ssl_platform_debug, NULL);
-//#else
- mbedtls_ssl_conf_dbg(&ssl_pm->conf, ssl_platform_debug, NULL);
-//#endif
-
- ret = mbedtls_ssl_setup(&ssl_pm->ssl, &ssl_pm->conf);
- if (ret) {
- SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL, "mbedtls_ssl_setup() return -0x%x", -ret);
- goto mbedtls_err2;
- }
-
- mbedtls_ssl_set_bio(&ssl_pm->ssl, &ssl_pm->fd, mbedtls_net_send, mbedtls_net_recv, NULL);
-
- ssl->ssl_pm = ssl_pm;
-
- return 0;
-
-mbedtls_err2:
- mbedtls_ssl_config_free(&ssl_pm->conf);
- mbedtls_ctr_drbg_free(&ssl_pm->ctr_drbg);
-mbedtls_err1:
- mbedtls_entropy_free(&ssl_pm->entropy);
- ssl_mem_free(ssl_pm);
-no_mem:
- return -1;
-}
-
-/**
- * @brief free SSL low-level object
- */
-void ssl_pm_free(SSL *ssl)
-{
- struct ssl_pm *ssl_pm = (struct ssl_pm *)ssl->ssl_pm;
-
- mbedtls_ctr_drbg_free(&ssl_pm->ctr_drbg);
- mbedtls_entropy_free(&ssl_pm->entropy);
- mbedtls_ssl_config_free(&ssl_pm->conf);
- mbedtls_ssl_free(&ssl_pm->ssl);
-
- ssl_mem_free(ssl_pm);
- ssl->ssl_pm = NULL;
-}
-
-/**
- * @brief reload SSL low-level certification object
- */
-static int ssl_pm_reload_crt(SSL *ssl)
-{
- int ret;
- int mode;
- struct ssl_pm *ssl_pm = ssl->ssl_pm;
- struct x509_pm *ca_pm = (struct x509_pm *)ssl->client_CA->x509_pm;
-
- struct pkey_pm *pkey_pm = (struct pkey_pm *)ssl->cert->pkey->pkey_pm;
- struct x509_pm *crt_pm = (struct x509_pm *)ssl->cert->x509->x509_pm;
-
- if (ssl->verify_mode == SSL_VERIFY_PEER)
- mode = MBEDTLS_SSL_VERIFY_OPTIONAL;
- else if (ssl->verify_mode == SSL_VERIFY_FAIL_IF_NO_PEER_CERT)
- mode = MBEDTLS_SSL_VERIFY_OPTIONAL;
- else if (ssl->verify_mode == SSL_VERIFY_CLIENT_ONCE)
- mode = MBEDTLS_SSL_VERIFY_UNSET;
- else
- mode = MBEDTLS_SSL_VERIFY_NONE;
-
- mbedtls_ssl_conf_authmode(&ssl_pm->conf, mode);
-
- if (ca_pm->x509_crt) {
- mbedtls_ssl_conf_ca_chain(&ssl_pm->conf, ca_pm->x509_crt, NULL);
- } else if (ca_pm->ex_crt) {
- mbedtls_ssl_conf_ca_chain(&ssl_pm->conf, ca_pm->ex_crt, NULL);
- }
-
- if (crt_pm->x509_crt && pkey_pm->pkey) {
- ret = mbedtls_ssl_conf_own_cert(&ssl_pm->conf, crt_pm->x509_crt, pkey_pm->pkey);
- } else if (crt_pm->ex_crt && pkey_pm->ex_pkey) {
- ret = mbedtls_ssl_conf_own_cert(&ssl_pm->conf, crt_pm->ex_crt, pkey_pm->ex_pkey);
- } else {
- ret = 0;
- }
-
- if (ret) {
- SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL, "mbedtls_ssl_conf_own_cert() return -0x%x", -ret);
- ret = -1;
- }
-
- return ret;
-}
-
-/*
- * Perform the mbedtls SSL handshake instead of mbedtls_ssl_handshake.
- * We can add debug here.
- */
-static int mbedtls_handshake( mbedtls_ssl_context *ssl )
-{
- int ret = 0;
-
- while (ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER) {
- ret = mbedtls_ssl_handshake_step(ssl);
-
- lwsl_info("%s: ssl ret -%x state %d\n", __func__, -ret, ssl->state);
-
- if (ret != 0)
- break;
- }
-
- return ret;
-}
-
-#include <errno.h>
-
-int ssl_pm_handshake(SSL *ssl)
-{
- int ret;
- struct ssl_pm *ssl_pm = (struct ssl_pm *)ssl->ssl_pm;
-
- ssl->err = 0;
- errno = 0;
-
- ret = ssl_pm_reload_crt(ssl);
- if (ret) {
- printf("%s: cert reload failed\n", __func__);
- return 0;
- }
-
- if (ssl_pm->ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER) {
- ssl_speed_up_enter();
-
- /* mbedtls return codes
- * 0 = successful, or MBEDTLS_ERR_SSL_WANT_READ/WRITE
- * anything else = death
- */
- ret = mbedtls_handshake(&ssl_pm->ssl);
- ssl_speed_up_exit();
- } else
- ret = 0;
-
- /*
- * OpenSSL return codes:
- * 0 = did not complete, but may be retried
- * 1 = successfully completed
- * <0 = death
- */
- if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
- ssl->err = ret;
- SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL, "mbedtls_ssl_handshake() return -0x%x", -ret);
- return 0; /* OpenSSL: did not complete but may be retried */
- }
-
- if (ret == 0) { /* successful */
- struct x509_pm *x509_pm = (struct x509_pm *)ssl->session->peer->x509_pm;
-
- x509_pm->ex_crt = (mbedtls_x509_crt *)mbedtls_ssl_get_peer_cert(&ssl_pm->ssl);
- return 1; /* openssl successful */
- }
-
- if (errno == 11) {
- ssl->err = ret == MBEDTLS_ERR_SSL_WANT_READ;
-
- return 0;
- }
-
- printf("%s: mbedtls_ssl_handshake() returned -0x%x\n", __func__, -ret);
-
- /* it's had it */
-
- ssl->err = SSL_ERROR_SYSCALL;
-
- return -1; /* openssl death */
-}
-
-mbedtls_x509_crt *
-ssl_ctx_get_mbedtls_x509_crt(SSL_CTX *ssl_ctx)
-{
- struct x509_pm *x509_pm = (struct x509_pm *)ssl_ctx->cert->x509->x509_pm;
-
- if (!x509_pm)
- return NULL;
-
- return x509_pm->x509_crt;
-}
-
-mbedtls_x509_crt *
-ssl_get_peer_mbedtls_x509_crt(SSL *ssl)
-{
- struct x509_pm *x509_pm = (struct x509_pm *)ssl->session->peer->x509_pm;
-
- if (!x509_pm)
- return NULL;
-
- return x509_pm->ex_crt;
-}
-
-int ssl_pm_shutdown(SSL *ssl)
-{
- int ret;
- struct ssl_pm *ssl_pm = (struct ssl_pm *)ssl->ssl_pm;
-
- ret = mbedtls_ssl_close_notify(&ssl_pm->ssl);
- if (ret) {
- SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL, "mbedtls_ssl_close_notify() return -0x%x", -ret);
- if (ret == MBEDTLS_ERR_NET_CONN_RESET)
- ssl->err = SSL_ERROR_SYSCALL;
- ret = -1; /* OpenSSL: "Call SSL_get_error with the return value to find the reason */
- } else {
- struct x509_pm *x509_pm = (struct x509_pm *)ssl->session->peer->x509_pm;
-
- x509_pm->ex_crt = NULL;
- ret = 1; /* OpenSSL: "The shutdown was successfully completed"
- ...0 means retry */
- }
-
- return ret;
-}
-
-int ssl_pm_clear(SSL *ssl)
-{
- return ssl_pm_shutdown(ssl);
-}
-
-
-int ssl_pm_read(SSL *ssl, void *buffer, int len)
-{
- int ret;
- struct ssl_pm *ssl_pm = (struct ssl_pm *)ssl->ssl_pm;
-
- ret = mbedtls_ssl_read(&ssl_pm->ssl, buffer, len);
- if (ret < 0) {
- // lwsl_notice("%s: mbedtls_ssl_read says -0x%x\n", __func__, -ret);
- SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL, "mbedtls_ssl_read() return -0x%x", -ret);
- if (ret == MBEDTLS_ERR_NET_CONN_RESET ||
- ret <= MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE) /* fatal errors */
- ssl->err = SSL_ERROR_SYSCALL;
- ret = -1;
- }
-
- return ret;
-}
-
-/*
- * This returns -1, or the length sent.
- * If -1, then you need to find out if the error was
- * fatal or recoverable using SSL_get_error()
- */
-int ssl_pm_send(SSL *ssl, const void *buffer, int len)
-{
- int ret;
- struct ssl_pm *ssl_pm = (struct ssl_pm *)ssl->ssl_pm;
-
- ret = mbedtls_ssl_write(&ssl_pm->ssl, buffer, len);
- /*
- * We can get a positive number, which may be less than len... that
- * much was sent successfully and you can call again to send more.
- *
- * We can get a negative mbedtls error code... if WANT_WRITE or WANT_READ,
- * it's nonfatal and means it should be retried as-is. If something else,
- * it's fatal actually.
- *
- * If this function returns something other than a positive value or
- * MBEDTLS_ERR_SSL_WANT_READ/WRITE, the ssl context becomes unusable, and
- * you should either free it or call mbedtls_ssl_session_reset() on it
- * before re-using it for a new connection; the current connection must
- * be closed.
- *
- * When this function returns MBEDTLS_ERR_SSL_WANT_WRITE/READ, it must be
- * called later with the same arguments, until it returns a positive value.
- */
-
- if (ret < 0) {
- SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL, "mbedtls_ssl_write() return -0x%x", -ret);
- switch (ret) {
- case MBEDTLS_ERR_NET_SEND_FAILED:
- case MBEDTLS_ERR_NET_CONN_RESET:
- ssl->err = SSL_ERROR_SYSCALL;
- break;
- case MBEDTLS_ERR_SSL_WANT_WRITE:
- ssl->err = SSL_ERROR_WANT_WRITE;
- break;
- case MBEDTLS_ERR_SSL_WANT_READ:
- ssl->err = SSL_ERROR_WANT_READ;
- break;
- default:
- break;
- }
-
- ret = -1;
- }
-
- return ret;
-}
-
-int ssl_pm_pending(const SSL *ssl)
-{
- struct ssl_pm *ssl_pm = (struct ssl_pm *)ssl->ssl_pm;
-
- return mbedtls_ssl_get_bytes_avail(&ssl_pm->ssl);
-}
-
-void ssl_pm_set_fd(SSL *ssl, int fd, int mode)
-{
- struct ssl_pm *ssl_pm = (struct ssl_pm *)ssl->ssl_pm;
-
- ssl_pm->fd.fd = fd;
-}
-
-int ssl_pm_get_fd(const SSL *ssl, int mode)
-{
- struct ssl_pm *ssl_pm = (struct ssl_pm *)ssl->ssl_pm;
-
- return ssl_pm->fd.fd;
-}
-
-OSSL_HANDSHAKE_STATE ssl_pm_get_state(const SSL *ssl)
-{
- OSSL_HANDSHAKE_STATE state;
-
- struct ssl_pm *ssl_pm = (struct ssl_pm *)ssl->ssl_pm;
-
- switch (ssl_pm->ssl.state)
- {
- case MBEDTLS_SSL_CLIENT_HELLO:
- state = TLS_ST_CW_CLNT_HELLO;
- break;
- case MBEDTLS_SSL_SERVER_HELLO:
- state = TLS_ST_SW_SRVR_HELLO;
- break;
- case MBEDTLS_SSL_SERVER_CERTIFICATE:
- state = TLS_ST_SW_CERT;
- break;
- case MBEDTLS_SSL_SERVER_HELLO_DONE:
- state = TLS_ST_SW_SRVR_DONE;
- break;
- case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE:
- state = TLS_ST_CW_KEY_EXCH;
- break;
- case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC:
- state = TLS_ST_CW_CHANGE;
- break;
- case MBEDTLS_SSL_CLIENT_FINISHED:
- state = TLS_ST_CW_FINISHED;
- break;
- case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC:
- state = TLS_ST_SW_CHANGE;
- break;
- case MBEDTLS_SSL_SERVER_FINISHED:
- state = TLS_ST_SW_FINISHED;
- break;
- case MBEDTLS_SSL_CLIENT_CERTIFICATE:
- state = TLS_ST_CW_CERT;
- break;
- case MBEDTLS_SSL_SERVER_KEY_EXCHANGE:
- state = TLS_ST_SR_KEY_EXCH;
- break;
- case MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET:
- state = TLS_ST_SW_SESSION_TICKET;
- break;
- case MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT:
- state = TLS_ST_SW_CERT_REQ;
- break;
- case MBEDTLS_SSL_HANDSHAKE_OVER:
- state = TLS_ST_OK;
- break;
- default :
- state = TLS_ST_BEFORE;
- break;
- }
-
- return state;
-}
-
-int x509_pm_show_info(X509 *x)
-{
- int ret;
- char *buf;
- mbedtls_x509_crt *x509_crt;
- struct x509_pm *x509_pm = x->x509_pm;
-
- if (x509_pm->x509_crt)
- x509_crt = x509_pm->x509_crt;
- else if (x509_pm->ex_crt)
- x509_crt = x509_pm->ex_crt;
- else
- x509_crt = NULL;
-
- if (!x509_crt)
- return -1;
-
- buf = ssl_mem_malloc(X509_INFO_STRING_LENGTH);
- if (!buf) {
- SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL, "no enough memory > (buf)");
- goto no_mem;
- }
-
- ret = mbedtls_x509_crt_info(buf, X509_INFO_STRING_LENGTH - 1, "", x509_crt);
- if (ret <= 0) {
- SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL, "mbedtls_x509_crt_info() return -0x%x", -ret);
- goto mbedtls_err1;
- }
-
- buf[ret] = 0;
-
- ssl_mem_free(buf);
-
- SSL_DEBUG(SSL_DEBUG_ON, "%s", buf);
-
- return 0;
-
-mbedtls_err1:
- ssl_mem_free(buf);
-no_mem:
- return -1;
-}
-
-int x509_pm_new(X509 *x, X509 *m_x)
-{
- struct x509_pm *x509_pm;
-
- x509_pm = ssl_mem_zalloc(sizeof(struct x509_pm));
- if (!x509_pm) {
- SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL, "no enough memory > (x509_pm)");
- goto failed1;
- }
-
- x->x509_pm = x509_pm;
-
- if (m_x) {
- struct x509_pm *m_x509_pm = (struct x509_pm *)m_x->x509_pm;
-
- x509_pm->ex_crt = m_x509_pm->x509_crt;
- }
-
- return 0;
-
-failed1:
- return -1;
-}
-
-void x509_pm_free(X509 *x)
-{
- struct x509_pm *x509_pm = (struct x509_pm *)x->x509_pm;
-
- if (x509_pm->x509_crt) {
- mbedtls_x509_crt_free(x509_pm->x509_crt);
-
- ssl_mem_free(x509_pm->x509_crt);
- x509_pm->x509_crt = NULL;
- }
-
- ssl_mem_free(x->x509_pm);
- x->x509_pm = NULL;
-}
-
-int x509_pm_load(X509 *x, const unsigned char *buffer, int len)
-{
- int ret;
- unsigned char *load_buf;
- struct x509_pm *x509_pm = (struct x509_pm *)x->x509_pm;
-
- if (x509_pm->x509_crt)
- mbedtls_x509_crt_free(x509_pm->x509_crt);
-
- if (!x509_pm->x509_crt) {
- x509_pm->x509_crt = ssl_mem_malloc(sizeof(mbedtls_x509_crt));
- if (!x509_pm->x509_crt) {
- SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL, "no enough memory > (x509_pm->x509_crt)");
- goto no_mem;
- }
- }
-
- mbedtls_x509_crt_init(x509_pm->x509_crt);
- if (buffer[0] != 0x30) {
- load_buf = ssl_mem_malloc(len + 1);
- if (!load_buf) {
- SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL, "no enough memory > (load_buf)");
- goto failed;
- }
-
- ssl_memcpy(load_buf, buffer, len);
- load_buf[len] = '\0';
-
- ret = mbedtls_x509_crt_parse(x509_pm->x509_crt, load_buf, len + 1);
- ssl_mem_free(load_buf);
- } else {
- printf("parsing as der\n");
-
- ret = mbedtls_x509_crt_parse_der(x509_pm->x509_crt, buffer, len);
- }
-
- if (ret) {
- printf("mbedtls_x509_crt_parse return -0x%x", -ret);
- goto failed;
- }
-
- return 0;
-
-failed:
- mbedtls_x509_crt_free(x509_pm->x509_crt);
- ssl_mem_free(x509_pm->x509_crt);
- x509_pm->x509_crt = NULL;
-no_mem:
- return -1;
-}
-
-int pkey_pm_new(EVP_PKEY *pk, EVP_PKEY *m_pkey)
-{
- struct pkey_pm *pkey_pm;
-
- pkey_pm = ssl_mem_zalloc(sizeof(struct pkey_pm));
- if (!pkey_pm)
- return -1;
-
- pk->pkey_pm = pkey_pm;
-
- if (m_pkey) {
- struct pkey_pm *m_pkey_pm = (struct pkey_pm *)m_pkey->pkey_pm;
-
- pkey_pm->ex_pkey = m_pkey_pm->pkey;
- }
-
- return 0;
-}
-
-void pkey_pm_free(EVP_PKEY *pk)
-{
- struct pkey_pm *pkey_pm = (struct pkey_pm *)pk->pkey_pm;
-
- if (pkey_pm->pkey) {
- mbedtls_pk_free(pkey_pm->pkey);
-
- ssl_mem_free(pkey_pm->pkey);
- pkey_pm->pkey = NULL;
- }
-
- ssl_mem_free(pk->pkey_pm);
- pk->pkey_pm = NULL;
-}
-
-int pkey_pm_load(EVP_PKEY *pk, const unsigned char *buffer, int len)
-{
- int ret;
- unsigned char *load_buf;
- struct pkey_pm *pkey_pm = (struct pkey_pm *)pk->pkey_pm;
-
- if (pkey_pm->pkey)
- mbedtls_pk_free(pkey_pm->pkey);
-
- if (!pkey_pm->pkey) {
- pkey_pm->pkey = ssl_mem_malloc(sizeof(mbedtls_pk_context));
- if (!pkey_pm->pkey) {
- SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL, "no enough memory > (pkey_pm->pkey)");
- goto no_mem;
- }
- }
-
- load_buf = ssl_mem_malloc(len + 1);
- if (!load_buf) {
- SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL, "no enough memory > (load_buf)");
- goto failed;
- }
-
- ssl_memcpy(load_buf, buffer, len);
- load_buf[len] = '\0';
-
- mbedtls_pk_init(pkey_pm->pkey);
-
- ret = mbedtls_pk_parse_key(pkey_pm->pkey, load_buf, len + 1, NULL, 0);
- ssl_mem_free(load_buf);
-
- if (ret) {
- SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL, "mbedtls_pk_parse_key return -0x%x", -ret);
- goto failed;
- }
-
- return 0;
-
-failed:
- mbedtls_pk_free(pkey_pm->pkey);
- ssl_mem_free(pkey_pm->pkey);
- pkey_pm->pkey = NULL;
-no_mem:
- return -1;
-}
-
-
-
-void ssl_pm_set_bufflen(SSL *ssl, int len)
-{
- max_content_len = len;
-}
-
-long ssl_pm_get_verify_result(const SSL *ssl)
-{
- uint32_t ret;
- long verify_result;
- struct ssl_pm *ssl_pm = (struct ssl_pm *)ssl->ssl_pm;
-
- ret = mbedtls_ssl_get_verify_result(&ssl_pm->ssl);
- if (!ret)
- return X509_V_OK;
-
- if (ret & MBEDTLS_X509_BADCERT_NOT_TRUSTED ||
- (ret & MBEDTLS_X509_BADCRL_NOT_TRUSTED))
- verify_result = X509_V_ERR_INVALID_CA;
-
- else if (ret & MBEDTLS_X509_BADCERT_CN_MISMATCH)
- verify_result = X509_V_ERR_HOSTNAME_MISMATCH;
-
- else if ((ret & MBEDTLS_X509_BADCERT_BAD_KEY) ||
- (ret & MBEDTLS_X509_BADCRL_BAD_KEY))
- verify_result = X509_V_ERR_CA_KEY_TOO_SMALL;
-
- else if ((ret & MBEDTLS_X509_BADCERT_BAD_MD) ||
- (ret & MBEDTLS_X509_BADCRL_BAD_MD))
- verify_result = X509_V_ERR_CA_MD_TOO_WEAK;
-
- else if ((ret & MBEDTLS_X509_BADCERT_FUTURE) ||
- (ret & MBEDTLS_X509_BADCRL_FUTURE))
- verify_result = X509_V_ERR_CERT_NOT_YET_VALID;
-
- else if ((ret & MBEDTLS_X509_BADCERT_EXPIRED) ||
- (ret & MBEDTLS_X509_BADCRL_EXPIRED))
- verify_result = X509_V_ERR_CERT_HAS_EXPIRED;
-
- else
- verify_result = X509_V_ERR_UNSPECIFIED;
-
- SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL,
- "mbedtls_ssl_get_verify_result() return 0x%x", ret);
-
- return verify_result;
-}
-
-/**
- * @brief set expected hostname on peer cert CN
- */
-
-int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param,
- const char *name, size_t namelen)
-{
- SSL *ssl = (SSL *)((char *)param - offsetof(SSL, param));
- struct ssl_pm *ssl_pm = (struct ssl_pm *)ssl->ssl_pm;
- char *name_cstr = NULL;
-
- if (namelen) {
- name_cstr = malloc(namelen + 1);
- if (!name_cstr)
- return 0;
- memcpy(name_cstr, name, namelen);
- name_cstr[namelen] = '\0';
- name = name_cstr;
- }
-
- mbedtls_ssl_set_hostname(&ssl_pm->ssl, name);
-
- if (namelen)
- free(name_cstr);
-
- return 1;
-}
-
-void _ssl_set_alpn_list(const SSL *ssl)
-{
- if (ssl->alpn_protos) {
- if (mbedtls_ssl_conf_alpn_protocols(&((struct ssl_pm *)(ssl->ssl_pm))->conf, ssl->alpn_protos))
- fprintf(stderr, "mbedtls_ssl_conf_alpn_protocols failed\n");
-
- return;
- }
- if (!ssl->ctx->alpn_protos)
- return;
- if (mbedtls_ssl_conf_alpn_protocols(&((struct ssl_pm *)(ssl->ssl_pm))->conf, ssl->ctx->alpn_protos))
- fprintf(stderr, "mbedtls_ssl_conf_alpn_protocols failed\n");
-}
-
-void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data,
- unsigned int *len)
-{
- const char *alp = mbedtls_ssl_get_alpn_protocol(&((struct ssl_pm *)(ssl->ssl_pm))->ssl);
-
- *data = (const unsigned char *)alp;
- if (alp)
- *len = strlen(alp);
- else
- *len = 0;
-}
-
-int SSL_set_sni_callback(SSL *ssl, int(*cb)(void *, mbedtls_ssl_context *,
- const unsigned char *, size_t), void *param)
-{
- struct ssl_pm *ssl_pm = (struct ssl_pm *)ssl->ssl_pm;
-
- mbedtls_ssl_conf_sni(&ssl_pm->conf, cb, param);
-
- return 0;
-}
-
-SSL *SSL_SSL_from_mbedtls_ssl_context(mbedtls_ssl_context *msc)
-{
- struct ssl_pm *ssl_pm = (struct ssl_pm *)((char *)msc - offsetof(struct ssl_pm, ssl));
-
- return ssl_pm->owner;
-}
-
-#include "ssl_cert.h"
-
-void SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx)
-{
- struct ssl_pm *ssl_pm = ssl->ssl_pm;
- struct x509_pm *x509_pm = (struct x509_pm *)ctx->cert->x509->x509_pm;
- struct x509_pm *x509_pm_ca = (struct x509_pm *)ctx->client_CA->x509_pm;
-
- struct pkey_pm *pkey_pm = (struct pkey_pm *)ctx->cert->pkey->pkey_pm;
- int mode;
-
- if (ssl->cert)
- ssl_cert_free(ssl->cert);
- ssl->ctx = ctx;
- ssl->cert = __ssl_cert_new(ctx->cert);
-
- if (ctx->verify_mode == SSL_VERIFY_PEER)
- mode = MBEDTLS_SSL_VERIFY_OPTIONAL;
- else if (ctx->verify_mode == SSL_VERIFY_FAIL_IF_NO_PEER_CERT)
- mode = MBEDTLS_SSL_VERIFY_OPTIONAL;
- else if (ctx->verify_mode == SSL_VERIFY_CLIENT_ONCE)
- mode = MBEDTLS_SSL_VERIFY_UNSET;
- else
- mode = MBEDTLS_SSL_VERIFY_NONE;
-
- // printf("ssl: %p, client ca x509_crt %p, mbedtls mode %d\n", ssl, x509_pm_ca->x509_crt, mode);
-
- /* apply new ctx cert to ssl */
-
- ssl->verify_mode = ctx->verify_mode;
-
- mbedtls_ssl_set_hs_ca_chain(&ssl_pm->ssl, x509_pm_ca->x509_crt, NULL);
- mbedtls_ssl_set_hs_own_cert(&ssl_pm->ssl, x509_pm->x509_crt, pkey_pm->pkey);
- mbedtls_ssl_set_hs_authmode(&ssl_pm->ssl, mode);
-}
diff --git a/thirdparty/libwebsockets/tls/mbedtls/wrapper/platform/ssl_port.c b/thirdparty/libwebsockets/tls/mbedtls/wrapper/platform/ssl_port.c
deleted file mode 100644
index 8c7a31338b..0000000000
--- a/thirdparty/libwebsockets/tls/mbedtls/wrapper/platform/ssl_port.c
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "ssl_port.h"
-
-/*********************************************************************************************/
-/********************************* SSL general interface *************************************/
-
-void *ssl_mem_zalloc(size_t size)
-{
- void *p = malloc(size);
-
- if (p)
- memset(p, 0, size);
-
- return p;
-}
-
diff --git a/thirdparty/libwebsockets/tls/private.h b/thirdparty/libwebsockets/tls/private.h
deleted file mode 100644
index 606e2574dc..0000000000
--- a/thirdparty/libwebsockets/tls/private.h
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010 - 2018 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * This is included from core/private.h if LWS_WITH_TLS
- */
-
-#if defined(LWS_WITH_TLS)
-
-#if defined(USE_WOLFSSL)
- #if defined(USE_OLD_CYASSL)
- #if defined(_WIN32)
- #include <IDE/WIN/user_settings.h>
- #include <cyassl/ctaocrypt/settings.h>
- #else
- #include <cyassl/options.h>
- #endif
- #include <cyassl/openssl/ssl.h>
- #include <cyassl/error-ssl.h>
- #else
- #if defined(_WIN32)
- #include <IDE/WIN/user_settings.h>
- #include <wolfssl/wolfcrypt/settings.h>
- #else
- #include <wolfssl/options.h>
- #endif
- #include <wolfssl/openssl/ssl.h>
- #include <wolfssl/error-ssl.h>
- #define OPENSSL_NO_TLSEXT
- #endif /* not USE_OLD_CYASSL */
-#else /* WOLFSSL */
- #if defined(LWS_WITH_ESP32)
- #define OPENSSL_NO_TLSEXT
- #undef MBEDTLS_CONFIG_FILE
- #define MBEDTLS_CONFIG_FILE <mbedtls/esp_config.h>
- #include <mbedtls/ssl.h>
- #include <mbedtls/x509_crt.h>
- #include "tls/mbedtls/wrapper/include/openssl/ssl.h" /* wrapper !!!! */
- #else /* not esp32 */
- #if defined(LWS_WITH_MBEDTLS)
- #include <mbedtls/ssl.h>
- #include <mbedtls/x509_crt.h>
- #include <mbedtls/x509_csr.h>
- #include "tls/mbedtls/wrapper/include/openssl/ssl.h" /* wrapper !!!! */
- #else
- #include <openssl/ssl.h>
- #include <openssl/evp.h>
- #include <openssl/err.h>
- #include <openssl/md5.h>
- #include <openssl/sha.h>
- #ifdef LWS_HAVE_OPENSSL_ECDH_H
- #include <openssl/ecdh.h>
- #endif
- #include <openssl/x509v3.h>
- #endif /* not mbedtls */
- #if defined(OPENSSL_VERSION_NUMBER)
- #if (OPENSSL_VERSION_NUMBER < 0x0009080afL)
-/* later openssl defines this to negate the presence of tlsext... but it was only
- * introduced at 0.9.8j. Earlier versions don't know it exists so don't
- * define it... making it look like the feature exists...
- */
- #define OPENSSL_NO_TLSEXT
- #endif
- #endif
- #endif /* not ESP32 */
-#endif /* not USE_WOLFSSL */
-
-#endif /* LWS_WITH_TLS */
-
-enum lws_tls_extant {
- LWS_TLS_EXTANT_NO,
- LWS_TLS_EXTANT_YES,
- LWS_TLS_EXTANT_ALTERNATIVE
-};
-
-struct lws_context_per_thread;
-
-struct lws_tls_ops {
- int (*fake_POLLIN_for_buffered)(struct lws_context_per_thread *pt);
- int (*periodic_housekeeping)(struct lws_context *context, time_t now);
-};
-
-#if defined(LWS_WITH_TLS)
-
-typedef SSL lws_tls_conn;
-typedef SSL_CTX lws_tls_ctx;
-typedef BIO lws_tls_bio;
-typedef X509 lws_tls_x509;
-
-
-#define LWS_SSL_ENABLED(context) (context->tls.use_ssl)
-
-extern const struct lws_tls_ops tls_ops_openssl, tls_ops_mbedtls;
-
-struct lws_context_tls {
- char alpn_discovered[32];
- const char *alpn_default;
- time_t last_cert_check_s;
-};
-
-struct lws_pt_tls {
- struct lws *pending_read_list; /* linked list */
-};
-
-struct lws_tls_ss_pieces;
-
-struct alpn_ctx {
- uint8_t data[23];
- uint8_t len;
-};
-
-struct lws_vhost_tls {
- lws_tls_ctx *ssl_ctx;
- lws_tls_ctx *ssl_client_ctx;
- const char *alpn;
- struct lws_tls_ss_pieces *ss; /* for acme tls certs */
- char *alloc_cert_path;
- char *key_path;
-#if defined(LWS_WITH_MBEDTLS)
- lws_tls_x509 *x509_client_CA;
-#endif
- char ecdh_curve[16];
- struct alpn_ctx alpn_ctx;
-
- int use_ssl;
- int allow_non_ssl_on_ssl_port;
- int ssl_info_event_mask;
-
- unsigned int user_supplied_ssl_ctx:1;
- unsigned int skipped_certs:1;
-};
-
-struct lws_lws_tls {
- lws_tls_conn *ssl;
- lws_tls_bio *client_bio;
- struct lws *pending_read_list_prev, *pending_read_list_next;
- unsigned int use_ssl;
- unsigned int redirect_to_https:1;
-};
-
-LWS_EXTERN void
-lws_context_init_alpn(struct lws_vhost *vhost);
-LWS_EXTERN enum lws_tls_extant
-lws_tls_use_any_upgrade_check_extant(const char *name);
-LWS_EXTERN int openssl_websocket_private_data_index;
-LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, int len);
-LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_ssl_capable_write(struct lws *wsi, unsigned char *buf, int len);
-LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_ssl_pending(struct lws *wsi);
-LWS_EXTERN int
-lws_context_init_ssl_library(const struct lws_context_creation_info *info);
-LWS_EXTERN int LWS_WARN_UNUSED_RESULT
-lws_server_socket_service_ssl(struct lws *new_wsi, lws_sockfd_type accept_fd);
-LWS_EXTERN int
-lws_ssl_close(struct lws *wsi);
-LWS_EXTERN void
-lws_ssl_SSL_CTX_destroy(struct lws_vhost *vhost);
-LWS_EXTERN void
-lws_ssl_context_destroy(struct lws_context *context);
-void
-__lws_ssl_remove_wsi_from_buffered_list(struct lws *wsi);
-LWS_VISIBLE void
-lws_ssl_remove_wsi_from_buffered_list(struct lws *wsi);
-LWS_EXTERN int
-lws_ssl_client_bio_create(struct lws *wsi);
-LWS_EXTERN int
-lws_ssl_client_connect1(struct lws *wsi);
-LWS_EXTERN int
-lws_ssl_client_connect2(struct lws *wsi, char *errbuf, int len);
-LWS_EXTERN void
-lws_ssl_elaborate_error(void);
-LWS_EXTERN int
-lws_tls_fake_POLLIN_for_buffered(struct lws_context_per_thread *pt);
-LWS_EXTERN int
-lws_gate_accepts(struct lws_context *context, int on);
-LWS_EXTERN void
-lws_ssl_bind_passphrase(lws_tls_ctx *ssl_ctx,
- const struct lws_context_creation_info *info);
-LWS_EXTERN void
-lws_ssl_info_callback(const lws_tls_conn *ssl, int where, int ret);
-LWS_EXTERN int
-lws_tls_openssl_cert_info(X509 *x509, enum lws_tls_cert_info type,
- union lws_tls_cert_info_results *buf, size_t len);
-LWS_EXTERN int
-lws_tls_check_all_cert_lifetimes(struct lws_context *context);
-LWS_EXTERN int
-lws_tls_server_certs_load(struct lws_vhost *vhost, struct lws *wsi,
- const char *cert, const char *private_key,
- const char *mem_cert, size_t len_mem_cert,
- const char *mem_privkey, size_t mem_privkey_len);
-LWS_EXTERN enum lws_tls_extant
-lws_tls_generic_cert_checks(struct lws_vhost *vhost, const char *cert,
- const char *private_key);
-LWS_EXTERN int
-lws_tls_alloc_pem_to_der_file(struct lws_context *context, const char *filename,
- const char *inbuf, lws_filepos_t inlen,
- uint8_t **buf, lws_filepos_t *amount);
-
-#if !defined(LWS_NO_SERVER)
- LWS_EXTERN int
- lws_context_init_server_ssl(const struct lws_context_creation_info *info,
- struct lws_vhost *vhost);
- void
- lws_tls_acme_sni_cert_destroy(struct lws_vhost *vhost);
-#else
- #define lws_context_init_server_ssl(_a, _b) (0)
- #define lws_tls_acme_sni_cert_destroy(_a)
-#endif
-
-LWS_EXTERN void
-lws_ssl_destroy(struct lws_vhost *vhost);
-LWS_EXTERN char *
-lws_ssl_get_error_string(int status, int ret, char *buf, size_t len);
-
-/*
- * lws_tls_ abstract backend implementations
- */
-
-LWS_EXTERN int
-lws_tls_server_client_cert_verify_config(struct lws_vhost *vh);
-LWS_EXTERN int
-lws_tls_server_vhost_backend_init(const struct lws_context_creation_info *info,
- struct lws_vhost *vhost, struct lws *wsi);
-LWS_EXTERN int
-lws_tls_server_new_nonblocking(struct lws *wsi, lws_sockfd_type accept_fd);
-
-LWS_EXTERN enum lws_ssl_capable_status
-lws_tls_server_accept(struct lws *wsi);
-
-LWS_EXTERN enum lws_ssl_capable_status
-lws_tls_server_abort_connection(struct lws *wsi);
-
-LWS_EXTERN enum lws_ssl_capable_status
-__lws_tls_shutdown(struct lws *wsi);
-
-LWS_EXTERN enum lws_ssl_capable_status
-lws_tls_client_connect(struct lws *wsi);
-LWS_EXTERN int
-lws_tls_client_confirm_peer_cert(struct lws *wsi, char *ebuf, int ebuf_len);
-LWS_EXTERN int
-lws_tls_client_create_vhost_context(struct lws_vhost *vh,
- const struct lws_context_creation_info *info,
- const char *cipher_list,
- const char *ca_filepath,
- const char *cert_filepath,
- const char *private_key_filepath);
-
-LWS_EXTERN lws_tls_ctx *
-lws_tls_ctx_from_wsi(struct lws *wsi);
-LWS_EXTERN int
-lws_ssl_get_error(struct lws *wsi, int n);
-
-LWS_EXTERN int
-lws_context_init_client_ssl(const struct lws_context_creation_info *info,
- struct lws_vhost *vhost);
-
-LWS_EXTERN void
-lws_ssl_info_callback(const lws_tls_conn *ssl, int where, int ret);
-
-int
-lws_tls_fake_POLLIN_for_buffered(struct lws_context_per_thread *pt);
-
-#endif \ No newline at end of file
diff --git a/thirdparty/libwebsockets/tls/tls-client.c b/thirdparty/libwebsockets/tls/tls-client.c
deleted file mode 100644
index 70eb6f6078..0000000000
--- a/thirdparty/libwebsockets/tls/tls-client.c
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * libwebsockets - client-related ssl code independent of backend
- *
- * Copyright (C) 2010-2017 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- */
-
-#include "core/private.h"
-
-int
-lws_ssl_client_connect1(struct lws *wsi)
-{
- struct lws_context *context = wsi->context;
- int n = 0;
-
- lws_latency_pre(context, wsi);
- n = lws_tls_client_connect(wsi);
- lws_latency(context, wsi, "SSL_connect hs", n, n > 0);
-
- switch (n) {
- case LWS_SSL_CAPABLE_ERROR:
- return -1;
- case LWS_SSL_CAPABLE_DONE:
- return 1; /* connected */
- case LWS_SSL_CAPABLE_MORE_SERVICE_WRITE:
- lws_callback_on_writable(wsi);
- /* fallthru */
- case LWS_SSL_CAPABLE_MORE_SERVICE_READ:
- lwsi_set_state(wsi, LRS_WAITING_SSL);
- break;
- case LWS_SSL_CAPABLE_MORE_SERVICE:
- break;
- }
-
- return 0; /* retry */
-}
-
-int
-lws_ssl_client_connect2(struct lws *wsi, char *errbuf, int len)
-{
- int n = 0;
-
- if (lwsi_state(wsi) == LRS_WAITING_SSL) {
- lws_latency_pre(wsi->context, wsi);
-
- n = lws_tls_client_connect(wsi);
- lwsl_debug("%s: SSL_connect says %d\n", __func__, n);
- lws_latency(wsi->context, wsi,
- "SSL_connect LRS_WAITING_SSL", n, n > 0);
-
- switch (n) {
- case LWS_SSL_CAPABLE_ERROR:
- lws_snprintf(errbuf, len, "client connect failed");
- return -1;
- case LWS_SSL_CAPABLE_DONE:
- break; /* connected */
- case LWS_SSL_CAPABLE_MORE_SERVICE_WRITE:
- lws_callback_on_writable(wsi);
- /* fallthru */
- case LWS_SSL_CAPABLE_MORE_SERVICE_READ:
- lwsi_set_state(wsi, LRS_WAITING_SSL);
- /* fallthru */
- case LWS_SSL_CAPABLE_MORE_SERVICE:
- return 0;
- }
- }
-
- if (lws_tls_client_confirm_peer_cert(wsi, errbuf, len))
- return -1;
-
- return 1;
-}
-
-
-int lws_context_init_client_ssl(const struct lws_context_creation_info *info,
- struct lws_vhost *vhost)
-{
- const char *ca_filepath = info->ssl_ca_filepath;
- const char *cipher_list = info->ssl_cipher_list;
- const char *private_key_filepath = info->ssl_private_key_filepath;
- const char *cert_filepath = info->ssl_cert_filepath;
- struct lws wsi;
-
- if (vhost->options & LWS_SERVER_OPTION_ONLY_RAW)
- return 0;
-
- /*
- * for backwards-compatibility default to using ssl_... members, but
- * if the newer client-specific ones are given, use those
- */
- if (info->client_ssl_cipher_list)
- cipher_list = info->client_ssl_cipher_list;
- if (info->client_ssl_cert_filepath)
- cert_filepath = info->client_ssl_cert_filepath;
- if (info->client_ssl_private_key_filepath)
- private_key_filepath = info->client_ssl_private_key_filepath;
-
- if (info->client_ssl_ca_filepath)
- ca_filepath = info->client_ssl_ca_filepath;
-
- if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT))
- return 0;
-
- if (vhost->tls.ssl_client_ctx)
- return 0;
-
- if (info->provided_client_ssl_ctx) {
- /* use the provided OpenSSL context if given one */
- vhost->tls.ssl_client_ctx = info->provided_client_ssl_ctx;
- /* nothing for lib to delete */
- vhost->tls.user_supplied_ssl_ctx = 1;
-
- return 0;
- }
-
- if (lws_tls_client_create_vhost_context(vhost, info, cipher_list,
- ca_filepath, cert_filepath,
- private_key_filepath))
- return 1;
-
- lwsl_notice("created client ssl context for %s\n", vhost->name);
-
- /*
- * give him a fake wsi with context set, so he can use
- * lws_get_context() in the callback
- */
- memset(&wsi, 0, sizeof(wsi));
- wsi.vhost = vhost;
- wsi.context = vhost->context;
-
- vhost->protocols[0].callback(&wsi,
- LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS,
- vhost->tls.ssl_client_ctx, NULL, 0);
-
- return 0;
-}
diff --git a/thirdparty/libwebsockets/tls/tls-server.c b/thirdparty/libwebsockets/tls/tls-server.c
deleted file mode 100644
index 440e790660..0000000000
--- a/thirdparty/libwebsockets/tls/tls-server.c
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010-2018 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- */
-
-#include "core/private.h"
-
-#if defined(LWS_WITH_MBEDTLS) || (defined(OPENSSL_VERSION_NUMBER) && \
- OPENSSL_VERSION_NUMBER >= 0x10002000L)
-static int
-alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen,
- const unsigned char *in, unsigned int inlen, void *arg)
-{
-#if !defined(LWS_WITH_MBEDTLS)
- struct alpn_ctx *alpn_ctx = (struct alpn_ctx *)arg;
-
- if (SSL_select_next_proto((unsigned char **)out, outlen, alpn_ctx->data,
- alpn_ctx->len, in, inlen) !=
- OPENSSL_NPN_NEGOTIATED)
- return SSL_TLSEXT_ERR_NOACK;
-#endif
-
- return SSL_TLSEXT_ERR_OK;
-}
-#endif
-
-void
-lws_context_init_alpn(struct lws_vhost *vhost)
-{
-#if defined(LWS_WITH_MBEDTLS) || (defined(OPENSSL_VERSION_NUMBER) && \
- OPENSSL_VERSION_NUMBER >= 0x10002000L)
- const char *alpn_comma = vhost->context->tls.alpn_default;
-
- if (vhost->tls.alpn)
- alpn_comma = vhost->tls.alpn;
-
- lwsl_info(" Server '%s' advertising ALPN: %s\n",
- vhost->name, alpn_comma);
- vhost->tls.alpn_ctx.len = lws_alpn_comma_to_openssl(alpn_comma,
- vhost->tls.alpn_ctx.data,
- sizeof(vhost->tls.alpn_ctx.data) - 1);
-
- SSL_CTX_set_alpn_select_cb(vhost->tls.ssl_ctx, alpn_cb, &vhost->tls.alpn_ctx);
-#else
- lwsl_err(
- " HTTP2 / ALPN configured but not supported by OpenSSL 0x%lx\n",
- OPENSSL_VERSION_NUMBER);
-#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
-}
-
-int
-lws_tls_server_conn_alpn(struct lws *wsi)
-{
-#if defined(LWS_WITH_MBEDTLS) || (defined(OPENSSL_VERSION_NUMBER) && \
- OPENSSL_VERSION_NUMBER >= 0x10002000L)
- const unsigned char *name = NULL;
- char cstr[10];
- unsigned len;
-
- SSL_get0_alpn_selected(wsi->tls.ssl, &name, &len);
- if (!len) {
- lwsl_info("no ALPN upgrade\n");
- return 0;
- }
-
- if (len > sizeof(cstr) - 1)
- len = sizeof(cstr) - 1;
-
- memcpy(cstr, name, len);
- cstr[len] = '\0';
-
- lwsl_info("negotiated '%s' using ALPN\n", cstr);
- wsi->tls.use_ssl |= LCCSCF_USE_SSL;
-
- return lws_role_call_alpn_negotiated(wsi, (const char *)cstr);
-#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
-
- return 0;
-}
-
-LWS_VISIBLE int
-lws_context_init_server_ssl(const struct lws_context_creation_info *info,
- struct lws_vhost *vhost)
-{
- struct lws_context *context = vhost->context;
- struct lws wsi;
-
- if (!lws_check_opt(info->options,
- LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT)) {
- vhost->tls.use_ssl = 0;
-
- return 0;
- }
-
- /*
- * If he is giving a cert filepath, take it as a sign he wants to use
- * it on this vhost. User code can leave the cert filepath NULL and
- * set the LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX option itself, in
- * which case he's expected to set up the cert himself at
- * LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS, which
- * provides the vhost SSL_CTX * in the user parameter.
- */
- if (info->ssl_cert_filepath)
- vhost->options |= LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX;
-
- if (info->port != CONTEXT_PORT_NO_LISTEN) {
-
- vhost->tls.use_ssl = lws_check_opt(vhost->options,
- LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX);
-
- if (vhost->tls.use_ssl && info->ssl_cipher_list)
- lwsl_notice(" SSL ciphers: '%s'\n",
- info->ssl_cipher_list);
-
- if (vhost->tls.use_ssl)
- lwsl_notice(" Using SSL mode\n");
- else
- lwsl_notice(" Using non-SSL mode\n");
- }
-
- /*
- * give him a fake wsi with context + vhost set, so he can use
- * lws_get_context() in the callback
- */
- memset(&wsi, 0, sizeof(wsi));
- wsi.vhost = vhost;
- wsi.context = context;
-
- /*
- * as a server, if we are requiring clients to identify themselves
- * then set the backend up for it
- */
- if (lws_check_opt(info->options,
- LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT))
- /* Normally SSL listener rejects non-ssl, optionally allow */
- vhost->tls.allow_non_ssl_on_ssl_port = 1;
-
- /*
- * give user code a chance to load certs into the server
- * allowing it to verify incoming client certs
- */
- if (vhost->tls.use_ssl) {
- if (lws_tls_server_vhost_backend_init(info, vhost, &wsi))
- return -1;
-
- lws_tls_server_client_cert_verify_config(vhost);
-
- if (vhost->protocols[0].callback(&wsi,
- LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS,
- vhost->tls.ssl_ctx, vhost, 0))
- return -1;
- }
-
- if (vhost->tls.use_ssl)
- lws_context_init_alpn(vhost);
-
- return 0;
-}
-
-LWS_VISIBLE int
-lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd)
-{
- struct lws_context *context = wsi->context;
- struct lws_vhost *vh;
- struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
- int n;
- char buf[256];
-
- (void)buf;
-
- if (!LWS_SSL_ENABLED(wsi->vhost))
- return 0;
-
- switch (lwsi_state(wsi)) {
- case LRS_SSL_INIT:
-
- if (wsi->tls.ssl)
- lwsl_err("%s: leaking ssl\n", __func__);
- if (accept_fd == LWS_SOCK_INVALID)
- assert(0);
- if (context->simultaneous_ssl_restriction &&
- context->simultaneous_ssl >=
- context->simultaneous_ssl_restriction) {
- lwsl_notice("unable to deal with SSL connection\n");
- return 1;
- }
-
- if (lws_tls_server_new_nonblocking(wsi, accept_fd)) {
- if (accept_fd != LWS_SOCK_INVALID)
- compatible_close(accept_fd);
- goto fail;
- }
-
- if (context->simultaneous_ssl_restriction &&
- ++context->simultaneous_ssl ==
- context->simultaneous_ssl_restriction)
- /* that was the last allowed SSL connection */
- lws_gate_accepts(context, 0);
-
-#if defined(LWS_WITH_STATS)
- context->updated = 1;
-#endif
- /*
- * we are not accepted yet, but we need to enter ourselves
- * as a live connection. That way we can retry when more
- * pieces come if we're not sorted yet
- */
- lwsi_set_state(wsi, LRS_SSL_ACK_PENDING);
-
- lws_pt_lock(pt, __func__);
- if (__insert_wsi_socket_into_fds(context, wsi)) {
- lwsl_err("%s: failed to insert into fds\n", __func__);
- goto fail;
- }
- lws_pt_unlock(pt);
-
- lws_set_timeout(wsi, PENDING_TIMEOUT_SSL_ACCEPT,
- context->timeout_secs);
-
- lwsl_debug("inserted SSL accept into fds, trying SSL_accept\n");
-
- /* fallthru */
-
- case LRS_SSL_ACK_PENDING:
-
- if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) {
- lwsl_err("%s: lws_change_pollfd failed\n", __func__);
- goto fail;
- }
-
- lws_latency_pre(context, wsi);
-
- if (wsi->vhost->tls.allow_non_ssl_on_ssl_port) {
-
- n = recv(wsi->desc.sockfd, (char *)pt->serv_buf,
- context->pt_serv_buf_size, MSG_PEEK);
-
- /*
- * optionally allow non-SSL connect on SSL listening socket
- * This is disabled by default, if enabled it goes around any
- * SSL-level access control (eg, client-side certs) so leave
- * it disabled unless you know it's not a problem for you
- */
- if (n >= 1 && pt->serv_buf[0] >= ' ') {
- /*
- * TLS content-type for Handshake is 0x16, and
- * for ChangeCipherSpec Record, it's 0x14
- *
- * A non-ssl session will start with the HTTP
- * method in ASCII. If we see it's not a legit
- * SSL handshake kill the SSL for this
- * connection and try to handle as a HTTP
- * connection upgrade directly.
- */
- wsi->tls.use_ssl = 0;
-
- lws_tls_server_abort_connection(wsi);
- /*
- * care... this creates wsi with no ssl
- * when ssl is enabled and normally
- * mandatory
- */
- wsi->tls.ssl = NULL;
- if (lws_check_opt(context->options,
- LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS))
- wsi->tls.redirect_to_https = 1;
- lwsl_debug("accepted as non-ssl\n");
- goto accepted;
- }
- if (!n) {
- /*
- * connection is gone, fail out
- */
- lwsl_debug("PEEKed 0\n");
- goto fail;
- }
- if (n < 0 && (LWS_ERRNO == LWS_EAGAIN ||
- LWS_ERRNO == LWS_EWOULDBLOCK)) {
- /*
- * well, we get no way to know ssl or not
- * so go around again waiting for something
- * to come and give us a hint, or timeout the
- * connection.
- */
- if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) {
- lwsl_info("%s: change_pollfd failed\n",
- __func__);
- return -1;
- }
-
- lwsl_info("SSL_ERROR_WANT_READ\n");
- return 0;
- }
- }
-
- /* normal SSL connection processing path */
-
-#if defined(LWS_WITH_STATS)
- if (!wsi->accept_start_us)
- wsi->accept_start_us = time_in_microseconds();
-#endif
- errno = 0;
- lws_stats_atomic_bump(wsi->context, pt,
- LWSSTATS_C_SSL_CONNECTIONS_ACCEPT_SPIN, 1);
- n = lws_tls_server_accept(wsi);
- lws_latency(context, wsi,
- "SSL_accept LRS_SSL_ACK_PENDING\n", n, n == 1);
- lwsl_info("SSL_accept says %d\n", n);
- switch (n) {
- case LWS_SSL_CAPABLE_DONE:
- break;
- case LWS_SSL_CAPABLE_ERROR:
- lws_stats_atomic_bump(wsi->context, pt,
- LWSSTATS_C_SSL_CONNECTIONS_FAILED, 1);
- lwsl_info("SSL_accept failed socket %u: %d\n",
- wsi->desc.sockfd, n);
- wsi->socket_is_permanently_unusable = 1;
- goto fail;
-
- default: /* MORE_SERVICE */
- return 0;
- }
-
- lws_stats_atomic_bump(wsi->context, pt,
- LWSSTATS_C_SSL_CONNECTIONS_ACCEPTED, 1);
-#if defined(LWS_WITH_STATS)
- lws_stats_atomic_bump(wsi->context, pt,
- LWSSTATS_MS_SSL_CONNECTIONS_ACCEPTED_DELAY,
- time_in_microseconds() - wsi->accept_start_us);
- wsi->accept_start_us = time_in_microseconds();
-#endif
-
-accepted:
-
- /* adapt our vhost to match the SNI SSL_CTX that was chosen */
- vh = context->vhost_list;
- while (vh) {
- if (!vh->being_destroyed && wsi->tls.ssl &&
- vh->tls.ssl_ctx == lws_tls_ctx_from_wsi(wsi)) {
- lwsl_info("setting wsi to vh %s\n", vh->name);
- wsi->vhost = vh;
- break;
- }
- vh = vh->vhost_next;
- }
-
- /* OK, we are accepted... give him some time to negotiate */
- lws_set_timeout(wsi, PENDING_TIMEOUT_ESTABLISH_WITH_SERVER,
- context->timeout_secs);
-
- lwsi_set_state(wsi, LRS_ESTABLISHED);
- if (lws_tls_server_conn_alpn(wsi))
- goto fail;
- lwsl_debug("accepted new SSL conn\n");
- break;
-
- default:
- break;
- }
-
- return 0;
-
-fail:
- return 1;
-}
-
diff --git a/thirdparty/libwebsockets/tls/tls.c b/thirdparty/libwebsockets/tls/tls.c
deleted file mode 100644
index 92b7c5593c..0000000000
--- a/thirdparty/libwebsockets/tls/tls.c
+++ /dev/null
@@ -1,522 +0,0 @@
-/*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010-2017 Andy Green <andy@warmcat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation:
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- */
-
-#include "core/private.h"
-
-/*
- * fakes POLLIN on all tls guys with buffered rx
- *
- * returns nonzero if any tls guys had POLLIN faked
- */
-
-int
-lws_tls_fake_POLLIN_for_buffered(struct lws_context_per_thread *pt)
-{
- struct lws *wsi, *wsi_next;
- int ret = 0;
-
- wsi = pt->tls.pending_read_list;
- while (wsi && wsi->position_in_fds_table != LWS_NO_FDS_POS) {
- wsi_next = wsi->tls.pending_read_list_next;
- pt->fds[wsi->position_in_fds_table].revents |=
- pt->fds[wsi->position_in_fds_table].events & LWS_POLLIN;
- ret |= pt->fds[wsi->position_in_fds_table].revents & LWS_POLLIN;
-
- wsi = wsi_next;
- }
-
- return !!ret;
-}
-
-void
-__lws_ssl_remove_wsi_from_buffered_list(struct lws *wsi)
-{
- struct lws_context *context = wsi->context;
- struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
-
- if (!wsi->tls.pending_read_list_prev &&
- !wsi->tls.pending_read_list_next &&
- pt->tls.pending_read_list != wsi)
- /* we are not on the list */
- return;
-
- /* point previous guy's next to our next */
- if (!wsi->tls.pending_read_list_prev)
- pt->tls.pending_read_list = wsi->tls.pending_read_list_next;
- else
- wsi->tls.pending_read_list_prev->tls.pending_read_list_next =
- wsi->tls.pending_read_list_next;
-
- /* point next guy's previous to our previous */
- if (wsi->tls.pending_read_list_next)
- wsi->tls.pending_read_list_next->tls.pending_read_list_prev =
- wsi->tls.pending_read_list_prev;
-
- wsi->tls.pending_read_list_prev = NULL;
- wsi->tls.pending_read_list_next = NULL;
-}
-
-void
-lws_ssl_remove_wsi_from_buffered_list(struct lws *wsi)
-{
- struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
-
- lws_pt_lock(pt, __func__);
- __lws_ssl_remove_wsi_from_buffered_list(wsi);
- lws_pt_unlock(pt);
-}
-
-#if defined(LWS_WITH_ESP32)
-int alloc_file(struct lws_context *context, const char *filename, uint8_t **buf,
- lws_filepos_t *amount)
-{
- nvs_handle nvh;
- size_t s;
- int n = 0;
-
- ESP_ERROR_CHECK(nvs_open("lws-station", NVS_READWRITE, &nvh));
- if (nvs_get_blob(nvh, filename, NULL, &s) != ESP_OK) {
- n = 1;
- goto bail;
- }
- *buf = lws_malloc(s + 1, "alloc_file");
- if (!*buf) {
- n = 2;
- goto bail;
- }
- if (nvs_get_blob(nvh, filename, (char *)*buf, &s) != ESP_OK) {
- lws_free(*buf);
- n = 1;
- goto bail;
- }
-
- *amount = s;
- (*buf)[s] = '\0';
-
- lwsl_notice("%s: nvs: read %s, %d bytes\n", __func__, filename, (int)s);
-
-bail:
- nvs_close(nvh);
-
- return n;
-}
-#else
-int alloc_file(struct lws_context *context, const char *filename, uint8_t **buf,
- lws_filepos_t *amount)
-{
- FILE *f;
- size_t s;
- int n = 0;
-
- f = fopen(filename, "rb");
- if (f == NULL) {
- n = 1;
- goto bail;
- }
-
- if (fseek(f, 0, SEEK_END) != 0) {
- n = 1;
- goto bail;
- }
-
- s = ftell(f);
- if (s == (size_t)-1) {
- n = 1;
- goto bail;
- }
-
- if (fseek(f, 0, SEEK_SET) != 0) {
- n = 1;
- goto bail;
- }
-
- *buf = lws_malloc(s, "alloc_file");
- if (!*buf) {
- n = 2;
- goto bail;
- }
-
- if (fread(*buf, s, 1, f) != 1) {
- lws_free(*buf);
- n = 1;
- goto bail;
- }
-
- *amount = s;
-
-bail:
- if (f)
- fclose(f);
-
- return n;
-
-}
-#endif
-
-int
-lws_tls_alloc_pem_to_der_file(struct lws_context *context, const char *filename,
- const char *inbuf, lws_filepos_t inlen,
- uint8_t **buf, lws_filepos_t *amount)
-{
- const uint8_t *pem, *p, *end;
- uint8_t *q;
- lws_filepos_t len;
- int n;
-
- if (filename) {
- n = alloc_file(context, filename, (uint8_t **)&pem, &len);
- if (n)
- return n;
- } else {
- pem = (const uint8_t *)inbuf;
- len = inlen;
- }
-
- /* trim the first line */
-
- p = pem;
- end = p + len;
- if (strncmp((char *)p, "-----", 5))
- goto bail;
- p += 5;
- while (p < end && *p != '\n' && *p != '-')
- p++;
-
- if (*p != '-')
- goto bail;
-
- while (p < end && *p != '\n')
- p++;
-
- if (p >= end)
- goto bail;
-
- p++;
-
- /* trim the last line */
-
- q = (uint8_t *)end - 2;
-
- while (q > pem && *q != '\n')
- q--;
-
- if (*q != '\n')
- goto bail;
-
- *q = '\0';
-
- *amount = lws_b64_decode_string((char *)p, (char *)pem,
- (int)(long long)len);
- *buf = (uint8_t *)pem;
-
- return 0;
-
-bail:
- lws_free((uint8_t *)pem);
-
- return 4;
-}
-
-int
-lws_tls_check_cert_lifetime(struct lws_vhost *v)
-{
- union lws_tls_cert_info_results ir;
- time_t now = (time_t)lws_now_secs(), life = 0;
- struct lws_acme_cert_aging_args caa;
- int n;
-
- if (v->tls.ssl_ctx && !v->tls.skipped_certs) {
-
- if (now < 1464083026) /* May 2016 */
- /* our clock is wrong and we can't judge the certs */
- return -1;
-
- n = lws_tls_vhost_cert_info(v, LWS_TLS_CERT_INFO_VALIDITY_TO, &ir, 0);
- if (n)
- return 1;
-
- life = (ir.time - now) / (24 * 3600);
- lwsl_notice(" vhost %s: cert expiry: %dd\n", v->name, (int)life);
- } else
- lwsl_notice(" vhost %s: no cert\n", v->name);
-
- memset(&caa, 0, sizeof(caa));
- caa.vh = v;
- lws_broadcast(v->context, LWS_CALLBACK_VHOST_CERT_AGING, (void *)&caa,
- (size_t)(ssize_t)life);
-
- return 0;
-}
-
-int
-lws_tls_check_all_cert_lifetimes(struct lws_context *context)
-{
- struct lws_vhost *v = context->vhost_list;
-
- while (v) {
- if (lws_tls_check_cert_lifetime(v) < 0)
- return -1;
- v = v->vhost_next;
- }
-
- return 0;
-}
-#if !defined(LWS_WITH_ESP32) && !defined(LWS_PLAT_OPTEE)
-static int
-lws_tls_extant(const char *name)
-{
- /* it exists if we can open it... */
- int fd = open(name, O_RDONLY), n;
- char buf[1];
-
- if (fd < 0)
- return 1;
-
- /* and we can read at least one byte out of it */
- n = read(fd, buf, 1);
- close(fd);
-
- return n != 1;
-}
-#endif
-/*
- * Returns 0 if the filepath "name" exists and can be read from.
- *
- * In addition, if "name".upd exists, backup "name" to "name.old.1"
- * and rename "name".upd to "name" before reporting its existence.
- *
- * There are four situations and three results possible:
- *
- * 1) LWS_TLS_EXTANT_NO: There are no certs at all (we are waiting for them to
- * be provisioned). We also feel like this if we need privs we don't have
- * any more to look in the directory.
- *
- * 2) There are provisioned certs written (xxx.upd) and we still have root
- * privs... in this case we rename any existing cert to have a backup name
- * and move the upd cert into place with the correct name. This then becomes
- * situation 4 for the caller.
- *
- * 3) LWS_TLS_EXTANT_ALTERNATIVE: There are provisioned certs written (xxx.upd)
- * but we no longer have the privs needed to read or rename them. In this
- * case, indicate that the caller should use temp copies if any we do have
- * rights to access. This is normal after we have updated the cert.
- *
- * But if we dropped privs, we can't detect the provisioned xxx.upd cert +
- * key, because we can't see in the dir. So we have to upgrade NO to
- * ALTERNATIVE when we actually have the in-memory alternative.
- *
- * 4) LWS_TLS_EXTANT_YES: The certs are present with the correct name and we
- * have the rights to read them.
- */
-enum lws_tls_extant
-lws_tls_use_any_upgrade_check_extant(const char *name)
-{
-#if !defined(LWS_PLAT_OPTEE)
-
- int n;
-
-#if !defined(LWS_WITH_ESP32)
- char buf[256];
-
- lws_snprintf(buf, sizeof(buf) - 1, "%s.upd", name);
- if (!lws_tls_extant(buf)) {
- /* ah there is an updated file... how about the desired file? */
- if (!lws_tls_extant(name)) {
- /* rename the desired file */
- for (n = 0; n < 50; n++) {
- lws_snprintf(buf, sizeof(buf) - 1,
- "%s.old.%d", name, n);
- if (!rename(name, buf))
- break;
- }
- if (n == 50) {
- lwsl_notice("unable to rename %s\n", name);
-
- return LWS_TLS_EXTANT_ALTERNATIVE;
- }
- lws_snprintf(buf, sizeof(buf) - 1, "%s.upd", name);
- }
- /* desired file is out of the way, rename the updated file */
- if (rename(buf, name)) {
- lwsl_notice("unable to rename %s to %s\n", buf, name);
-
- return LWS_TLS_EXTANT_ALTERNATIVE;
- }
- }
-
- if (lws_tls_extant(name))
- return LWS_TLS_EXTANT_NO;
-#else
- nvs_handle nvh;
- size_t s = 8192;
-
- if (nvs_open("lws-station", NVS_READWRITE, &nvh)) {
- lwsl_notice("%s: can't open nvs\n", __func__);
- return LWS_TLS_EXTANT_NO;
- }
-
- n = nvs_get_blob(nvh, name, NULL, &s);
- nvs_close(nvh);
-
- if (n)
- return LWS_TLS_EXTANT_NO;
-#endif
-#endif
- return LWS_TLS_EXTANT_YES;
-}
-
-/*
- * LWS_TLS_EXTANT_NO : skip adding the cert
- * LWS_TLS_EXTANT_YES : use the cert and private key paths normally
- * LWS_TLS_EXTANT_ALTERNATIVE: normal paths not usable, try alternate if poss
- */
-enum lws_tls_extant
-lws_tls_generic_cert_checks(struct lws_vhost *vhost, const char *cert,
- const char *private_key)
-{
- int n, m;
-
- /*
- * The user code can choose to either pass the cert and
- * key filepaths using the info members like this, or it can
- * leave them NULL; force the vhost SSL_CTX init using the info
- * options flag LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX; and
- * set up the cert himself using the user callback
- * LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS, which
- * happened just above and has the vhost SSL_CTX * in the user
- * parameter.
- */
-
- if (!cert || !private_key)
- return LWS_TLS_EXTANT_NO;
-
- n = lws_tls_use_any_upgrade_check_extant(cert);
- if (n == LWS_TLS_EXTANT_ALTERNATIVE)
- return LWS_TLS_EXTANT_ALTERNATIVE;
- m = lws_tls_use_any_upgrade_check_extant(private_key);
- if (m == LWS_TLS_EXTANT_ALTERNATIVE)
- return LWS_TLS_EXTANT_ALTERNATIVE;
-
- if ((n == LWS_TLS_EXTANT_NO || m == LWS_TLS_EXTANT_NO) &&
- (vhost->options & LWS_SERVER_OPTION_IGNORE_MISSING_CERT)) {
- lwsl_notice("Ignoring missing %s or %s\n", cert, private_key);
- vhost->tls.skipped_certs = 1;
-
- return LWS_TLS_EXTANT_NO;
- }
-
- /*
- * the cert + key exist
- */
-
- return LWS_TLS_EXTANT_YES;
-}
-
-#if !defined(LWS_NO_SERVER)
-/*
- * update the cert for every vhost using the given path
- */
-
-LWS_VISIBLE int
-lws_tls_cert_updated(struct lws_context *context, const char *certpath,
- const char *keypath,
- const char *mem_cert, size_t len_mem_cert,
- const char *mem_privkey, size_t len_mem_privkey)
-{
- struct lws wsi;
-
- wsi.context = context;
-
- lws_start_foreach_ll(struct lws_vhost *, v, context->vhost_list) {
- wsi.vhost = v;
- if (v->tls.alloc_cert_path && v->tls.key_path &&
- !strcmp(v->tls.alloc_cert_path, certpath) &&
- !strcmp(v->tls.key_path, keypath)) {
- lws_tls_server_certs_load(v, &wsi, certpath, keypath,
- mem_cert, len_mem_cert,
- mem_privkey, len_mem_privkey);
-
- if (v->tls.skipped_certs)
- lwsl_notice("%s: vhost %s: cert unset\n",
- __func__, v->name);
- }
- } lws_end_foreach_ll(v, vhost_next);
-
- return 0;
-}
-#endif
-
-int
-lws_gate_accepts(struct lws_context *context, int on)
-{
- struct lws_vhost *v = context->vhost_list;
-
- lwsl_notice("%s: on = %d\n", __func__, on);
-
-#if defined(LWS_WITH_STATS)
- context->updated = 1;
-#endif
-
- while (v) {
- if (v->tls.use_ssl && v->lserv_wsi &&
- lws_change_pollfd(v->lserv_wsi, (LWS_POLLIN) * !on,
- (LWS_POLLIN) * on))
- lwsl_notice("Unable to set accept POLLIN %d\n", on);
-
- v = v->vhost_next;
- }
-
- return 0;
-}
-
-/* comma-separated alpn list, like "h2,http/1.1" to openssl alpn format */
-
-int
-lws_alpn_comma_to_openssl(const char *comma, uint8_t *os, int len)
-{
- uint8_t *oos = os, *plen = NULL;
-
- while (*comma && len > 1) {
- if (!plen && *comma == ' ') {
- comma++;
- continue;
- }
- if (!plen) {
- plen = os++;
- len--;
- }
-
- if (*comma == ',') {
- *plen = lws_ptr_diff(os, plen + 1);
- plen = NULL;
- comma++;
- } else {
- *os++ = *comma++;
- len--;
- }
- }
-
- if (plen)
- *plen = lws_ptr_diff(os, plen + 1);
-
- return lws_ptr_diff(os, oos);
-}
-
diff --git a/thirdparty/libwebsockets/uwp_fixes.diff b/thirdparty/libwebsockets/uwp_fixes.diff
deleted file mode 100644
index 21c3275bba..0000000000
--- a/thirdparty/libwebsockets/uwp_fixes.diff
+++ /dev/null
@@ -1,47 +0,0 @@
-diff --git a/thirdparty/libwebsockets/plat/lws-plat-win.c b/thirdparty/libwebsockets/plat/lws-plat-win.c
-index bd513b494..1850b6425 100644
---- a/thirdparty/libwebsockets/plat/lws-plat-win.c
-+++ b/thirdparty/libwebsockets/plat/lws-plat-win.c
-@@ -641,9 +641,20 @@ _lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename,
- HANDLE ret;
- WCHAR buf[MAX_PATH];
- lws_fop_fd_t fop_fd;
-- LARGE_INTEGER llFileSize = {0};
-+ FILE_STANDARD_INFO fInfo = {0};
-
- MultiByteToWideChar(CP_UTF8, 0, filename, -1, buf, LWS_ARRAY_SIZE(buf));
-+
-+#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0602 // Windows 8 (minimum when UWP_ENABLED, but can be used in Windows builds)
-+ CREATEFILE2_EXTENDED_PARAMETERS extParams = {0};
-+ extParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
-+
-+ if (((*flags) & 7) == _O_RDONLY) {
-+ ret = CreateFile2(buf, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, &extParams);
-+ } else {
-+ ret = CreateFile2(buf, GENERIC_WRITE, 0, CREATE_ALWAYS, &extParams);
-+ }
-+#else
- if (((*flags) & 7) == _O_RDONLY) {
- ret = CreateFileW(buf, GENERIC_READ, FILE_SHARE_READ,
- NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-@@ -651,6 +662,7 @@ _lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename,
- ret = CreateFileW(buf, GENERIC_WRITE, 0, NULL,
- CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
- }
-+#endif
-
- if (ret == LWS_INVALID_FILE)
- goto bail;
-@@ -663,9 +675,9 @@ _lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename,
- fop_fd->fd = ret;
- fop_fd->filesystem_priv = NULL; /* we don't use it */
- fop_fd->flags = *flags;
-- fop_fd->len = GetFileSize(ret, NULL);
-- if(GetFileSizeEx(ret, &llFileSize))
-- fop_fd->len = llFileSize.QuadPart;
-+ fop_fd->len = 0;
-+ if(GetFileInformationByHandleEx(ret, FileStandardInfo, &fInfo, sizeof(fInfo)))
-+ fop_fd->len = fInfo.EndOfFile.QuadPart;
-
- fop_fd->pos = 0;
-
diff --git a/thirdparty/libwebsockets/win32helpers/getopt.c b/thirdparty/libwebsockets/win32helpers/getopt.c
deleted file mode 100644
index 3bb21f6f28..0000000000
--- a/thirdparty/libwebsockets/win32helpers/getopt.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/* $NetBSD: getopt.c,v 1.16 1999/12/02 13:15:56 kleink Exp $ */
-
-/*
- * Copyright (c) 1987, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if 0
-static char sccsid[] = "@(#)getopt.c 8.3 (Berkeley) 4/27/95";
-#endif
-
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-
-#define __P(x) x
-#define _DIAGASSERT(x) assert(x)
-
-#ifdef __weak_alias
-__weak_alias(getopt,_getopt);
-#endif
-
-
-int opterr = 1, /* if error message should be printed */
- optind = 1, /* index into parent argv vector */
- optopt, /* character checked for validity */
- optreset; /* reset getopt */
-char *optarg; /* argument associated with option */
-
-static char * _progname __P((char *));
-int getopt_internal __P((int, char * const *, const char *));
-
-static char *
-_progname(nargv0)
- char * nargv0;
-{
- char * tmp;
-
- _DIAGASSERT(nargv0 != NULL);
-
- tmp = strrchr(nargv0, '/');
- if (tmp)
- tmp++;
- else
- tmp = nargv0;
- return(tmp);
-}
-
-#define BADCH (int)'?'
-#define BADARG (int)':'
-#define EMSG ""
-
-/*
- * getopt --
- * Parse argc/argv argument vector.
- */
-int
-getopt(nargc, nargv, ostr)
- int nargc;
- char * const nargv[];
- const char *ostr;
-{
- static char *__progname = 0;
- static char *place = EMSG; /* option letter processing */
- char *oli; /* option letter list index */
- __progname = __progname?__progname:_progname(*nargv);
-
- _DIAGASSERT(nargv != NULL);
- _DIAGASSERT(ostr != NULL);
-
- if (optreset || !*place) { /* update scanning pointer */
- optreset = 0;
- if (optind >= nargc || *(place = nargv[optind]) != '-') {
- place = EMSG;
- return (-1);
- }
- if (place[1] && *++place == '-' /* found "--" */
- && place[1] == '\0') {
- ++optind;
- place = EMSG;
- return (-1);
- }
- } /* option letter okay? */
- if ((optopt = (int)*place++) == (int)':' ||
- !(oli = strchr(ostr, optopt))) {
- /*
- * if the user didn't specify '-' as an option,
- * assume it means -1.
- */
- if (optopt == (int)'-')
- return (-1);
- if (!*place)
- ++optind;
- if (opterr && *ostr != ':')
- (void)fprintf(stderr,
- "%s: illegal option -- %c\n", __progname, optopt);
- return (BADCH);
- }
- if (*++oli != ':') { /* don't need argument */
- optarg = NULL;
- if (!*place)
- ++optind;
- }
- else { /* need an argument */
- if (*place) /* no white space */
- optarg = place;
- else if (nargc <= ++optind) { /* no arg */
- place = EMSG;
- if (*ostr == ':')
- return (BADARG);
- if (opterr)
- (void)fprintf(stderr,
- "%s: option requires an argument -- %c\n",
- __progname, optopt);
- return (BADCH);
- }
- else /* white space */
- optarg = nargv[optind];
- place = EMSG;
- ++optind;
- }
- return (optopt); /* dump back option letter */
-}
-
diff --git a/thirdparty/libwebsockets/win32helpers/getopt.h b/thirdparty/libwebsockets/win32helpers/getopt.h
deleted file mode 100644
index 7137f0379c..0000000000
--- a/thirdparty/libwebsockets/win32helpers/getopt.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef __GETOPT_H__
-#define __GETOPT_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern int opterr; /* if error message should be printed */
-extern int optind; /* index into parent argv vector */
-extern int optopt; /* character checked for validity */
-extern int optreset; /* reset getopt */
-extern char *optarg; /* argument associated with option */
-
-struct option
-{
- const char *name;
- int has_arg;
- int *flag;
- int val;
-};
-
-#define no_argument 0
-#define required_argument 1
-#define optional_argument 2
-
-int getopt(int, char**, char*);
-int getopt_long(int, char**, char*, struct option*, int*);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __GETOPT_H__ */
diff --git a/thirdparty/libwebsockets/win32helpers/getopt_long.c b/thirdparty/libwebsockets/win32helpers/getopt_long.c
deleted file mode 100644
index 6dfccf367d..0000000000
--- a/thirdparty/libwebsockets/win32helpers/getopt_long.c
+++ /dev/null
@@ -1,240 +0,0 @@
-
-/*
- * Copyright (c) 1987, 1993, 1994, 1996
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "getopt.h"
-
-#define lws_ptr_diff(head, tail) \
- ((int)((char *)(head) - (char *)(tail)))
-
-extern int opterr; /* if error message should be printed */
-extern int optind; /* index into parent argv vector */
-extern int optopt; /* character checked for validity */
-extern int optreset; /* reset getopt */
-extern char *optarg; /* argument associated with option */
-
-#define __P(x) x
-#define _DIAGASSERT(x) assert(x)
-
-static char * __progname __P((char *));
-int getopt_internal __P((int, char * const *, const char *));
-
-static char *
-__progname(nargv0)
- char * nargv0;
-{
- char * tmp;
-
- _DIAGASSERT(nargv0 != NULL);
-
- tmp = strrchr(nargv0, '/');
- if (tmp)
- tmp++;
- else
- tmp = nargv0;
- return(tmp);
-}
-
-#define BADCH (int)'?'
-#define BADARG (int)':'
-#define EMSG ""
-
-/*
- * getopt --
- * Parse argc/argv argument vector.
- */
-int
-getopt_internal(nargc, nargv, ostr)
- int nargc;
- char * const *nargv;
- const char *ostr;
-{
- static char *place = EMSG; /* option letter processing */
- char *oli; /* option letter list index */
-
- _DIAGASSERT(nargv != NULL);
- _DIAGASSERT(ostr != NULL);
-
- if (optreset || !*place) { /* update scanning pointer */
- optreset = 0;
- if (optind >= nargc || *(place = nargv[optind]) != '-') {
- place = EMSG;
- return (-1);
- }
- if (place[1] && *++place == '-') { /* found "--" */
- /* ++optind; */
- place = EMSG;
- return (-2);
- }
- } /* option letter okay? */
- if ((optopt = (int)*place++) == (int)':' ||
- !(oli = strchr(ostr, optopt))) {
- /*
- * if the user didn't specify '-' as an option,
- * assume it means -1.
- */
- if (optopt == (int)'-')
- return (-1);
- if (!*place)
- ++optind;
- if (opterr && *ostr != ':')
- (void)fprintf(stderr,
- "%s: illegal option -- %c\n", __progname(nargv[0]), optopt);
- return (BADCH);
- }
- if (*++oli != ':') { /* don't need argument */
- optarg = NULL;
- if (!*place)
- ++optind;
- } else { /* need an argument */
- if (*place) /* no white space */
- optarg = place;
- else if (nargc <= ++optind) { /* no arg */
- place = EMSG;
- if ((opterr) && (*ostr != ':'))
- (void)fprintf(stderr,
- "%s: option requires an argument -- %c\n",
- __progname(nargv[0]), optopt);
- return (BADARG);
- } else /* white space */
- optarg = nargv[optind];
- place = EMSG;
- ++optind;
- }
- return (optopt); /* dump back option letter */
-}
-
-#if 0
-/*
- * getopt --
- * Parse argc/argv argument vector.
- */
-int
-getopt2(nargc, nargv, ostr)
- int nargc;
- char * const *nargv;
- const char *ostr;
-{
- int retval;
-
- if ((retval = getopt_internal(nargc, nargv, ostr)) == -2) {
- retval = -1;
- ++optind;
- }
- return(retval);
-}
-#endif
-
-/*
- * getopt_long --
- * Parse argc/argv argument vector.
- */
-int
-getopt_long(nargc, nargv, options, long_options, index)
- int nargc;
- char ** nargv;
- char * options;
- struct option * long_options;
- int * index;
-{
- int retval;
-
- _DIAGASSERT(nargv != NULL);
- _DIAGASSERT(options != NULL);
- _DIAGASSERT(long_options != NULL);
- /* index may be NULL */
-
- if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
- char *current_argv = nargv[optind++] + 2, *has_equal;
- int i, current_argv_len, match = -1;
-
- if (*current_argv == '\0') {
- return(-1);
- }
- if ((has_equal = strchr(current_argv, '=')) != NULL) {
- current_argv_len = lws_ptr_diff(has_equal, current_argv);
- has_equal++;
- } else
- current_argv_len = (int)strlen(current_argv);
-
- for (i = 0; long_options[i].name; i++) {
- if (strncmp(current_argv, long_options[i].name, current_argv_len))
- continue;
-
- if (strlen(long_options[i].name) == (unsigned)current_argv_len) {
- match = i;
- break;
- }
- if (match == -1)
- match = i;
- }
- if (match != -1) {
- if (long_options[match].has_arg == required_argument ||
- long_options[match].has_arg == optional_argument) {
- if (has_equal)
- optarg = has_equal;
- else
- optarg = nargv[optind++];
- }
- if ((long_options[match].has_arg == required_argument)
- && (optarg == NULL)) {
- /*
- * Missing argument, leading :
- * indicates no error should be generated
- */
- if ((opterr) && (*options != ':'))
- (void)fprintf(stderr,
- "%s: option requires an argument -- %s\n",
- __progname(nargv[0]), current_argv);
- return (BADARG);
- }
- } else { /* No matching argument */
- if ((opterr) && (*options != ':'))
- (void)fprintf(stderr,
- "%s: illegal option -- %s\n", __progname(nargv[0]), current_argv);
- return (BADCH);
- }
- if (long_options[match].flag) {
- *long_options[match].flag = long_options[match].val;
- retval = 0;
- } else
- retval = long_options[match].val;
- if (index)
- *index = match;
- }
- return(retval);
-}
diff --git a/thirdparty/libwebsockets/win32helpers/gettimeofday.c b/thirdparty/libwebsockets/win32helpers/gettimeofday.c
deleted file mode 100644
index 35dd73531d..0000000000
--- a/thirdparty/libwebsockets/win32helpers/gettimeofday.c
+++ /dev/null
@@ -1,36 +0,0 @@
-#include <time.h>
-#include <windows.h> //I've omitted context line
-
-#include "gettimeofday.h"
-
-int gettimeofday(struct timeval *tv, struct timezone *tz)
-{
- FILETIME ft;
- unsigned __int64 tmpres = 0;
- static int tzflag;
-
- if (NULL != tv) {
- GetSystemTimeAsFileTime(&ft);
-
- tmpres |= ft.dwHighDateTime;
- tmpres <<= 32;
- tmpres |= ft.dwLowDateTime;
-
- /*converting file time to unix epoch*/
- tmpres /= 10; /*convert into microseconds*/
- tmpres -= DELTA_EPOCH_IN_MICROSECS;
- tv->tv_sec = (long)(tmpres / 1000000UL);
- tv->tv_usec = (long)(tmpres % 1000000UL);
- }
-
- if (NULL != tz) {
- if (!tzflag) {
- _tzset();
- tzflag++;
- }
- tz->tz_minuteswest = _timezone / 60;
- tz->tz_dsttime = _daylight;
- }
-
- return 0;
-}
diff --git a/thirdparty/libwebsockets/win32helpers/gettimeofday.h b/thirdparty/libwebsockets/win32helpers/gettimeofday.h
deleted file mode 100644
index 33e7a750fe..0000000000
--- a/thirdparty/libwebsockets/win32helpers/gettimeofday.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef _GET_TIME_OF_DAY_H
-#define _GET_TIME_OF_DAY_H
-
-#include <time.h>
-
-#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
- #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
-#else
- #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
-#endif
-
-#ifdef LWS_MINGW_SUPPORT
- #include <winsock2.h>
-#endif
-
-#ifndef _TIMEZONE_DEFINED
-struct timezone
-{
- int tz_minuteswest; /* minutes W of Greenwich */
- int tz_dsttime; /* type of dst correction */
-};
-
-#endif
-
-int gettimeofday(struct timeval *tv, struct timezone *tz);
-
-#endif
diff --git a/thirdparty/wslay/COPYING b/thirdparty/wslay/COPYING
new file mode 100644
index 0000000000..6080330303
--- /dev/null
+++ b/thirdparty/wslay/COPYING
@@ -0,0 +1,22 @@
+The MIT License
+
+Copyright (c) 2011, 2012, 2015 Tatsuhiro Tsujikawa
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/thirdparty/wslay/includes/config.h b/thirdparty/wslay/includes/config.h
new file mode 100644
index 0000000000..771ad12528
--- /dev/null
+++ b/thirdparty/wslay/includes/config.h
@@ -0,0 +1,8 @@
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#ifdef BIG_ENDIAN_ENABLED
+#define WORDS_BIGENDIAN
+#endif
+
+#endif /* CONFIG_H */
diff --git a/thirdparty/wslay/includes/wslay/wslay.h b/thirdparty/wslay/includes/wslay/wslay.h
new file mode 100644
index 0000000000..9c751b05b7
--- /dev/null
+++ b/thirdparty/wslay/includes/wslay/wslay.h
@@ -0,0 +1,778 @@
+/*
+ * Wslay - The WebSocket Library
+ *
+ * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef WSLAY_H
+#define WSLAY_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+/* GODOT ADDITTION */
+#if defined(_MSC_VER)
+#include <BaseTsd.h>
+typedef SSIZE_T ssize_t;
+#endif
+/* GODOT END */
+
+/*
+ * wslay/wslayver.h is generated from wslay/wslayver.h.in by
+ * configure. The projects which do not use autotools can set
+ * WSLAY_VERSION macro from outside to avoid to generating wslayver.h
+ */
+#ifndef WSLAY_VERSION
+# include <wslay/wslayver.h>
+#endif /* WSLAY_VERSION */
+
+enum wslay_error {
+ WSLAY_ERR_WANT_READ = -100,
+ WSLAY_ERR_WANT_WRITE = -101,
+ WSLAY_ERR_PROTO = -200,
+ WSLAY_ERR_INVALID_ARGUMENT = -300,
+ WSLAY_ERR_INVALID_CALLBACK = -301,
+ WSLAY_ERR_NO_MORE_MSG = -302,
+ WSLAY_ERR_CALLBACK_FAILURE = -400,
+ WSLAY_ERR_WOULDBLOCK = -401,
+ WSLAY_ERR_NOMEM = -500
+};
+
+/*
+ * Status codes defined in RFC6455
+ */
+enum wslay_status_code {
+ WSLAY_CODE_NORMAL_CLOSURE = 1000,
+ WSLAY_CODE_GOING_AWAY = 1001,
+ WSLAY_CODE_PROTOCOL_ERROR = 1002,
+ WSLAY_CODE_UNSUPPORTED_DATA = 1003,
+ WSLAY_CODE_NO_STATUS_RCVD = 1005,
+ WSLAY_CODE_ABNORMAL_CLOSURE = 1006,
+ WSLAY_CODE_INVALID_FRAME_PAYLOAD_DATA = 1007,
+ WSLAY_CODE_POLICY_VIOLATION = 1008,
+ WSLAY_CODE_MESSAGE_TOO_BIG = 1009,
+ WSLAY_CODE_MANDATORY_EXT = 1010,
+ WSLAY_CODE_INTERNAL_SERVER_ERROR = 1011,
+ WSLAY_CODE_TLS_HANDSHAKE = 1015
+};
+
+enum wslay_io_flags {
+ /*
+ * There is more data to send.
+ */
+ WSLAY_MSG_MORE = 1
+};
+
+/*
+ * Callback function used by wslay_frame_send() function when it needs
+ * to send data. The implementation of this function must send at most
+ * len bytes of data in data. flags is the bitwise OR of zero or more
+ * of the following flag:
+ *
+ * WSLAY_MSG_MORE
+ * There is more data to send
+ *
+ * It provides some hints to tune performance and behaviour. user_data
+ * is one given in wslay_frame_context_init() function. The
+ * implementation of this function must return the number of bytes
+ * sent. If there is an error, return -1. The return value 0 is also
+ * treated an error by the library.
+ */
+typedef ssize_t (*wslay_frame_send_callback)(const uint8_t *data, size_t len,
+ int flags, void *user_data);
+/*
+ * Callback function used by wslay_frame_recv() function when it needs
+ * more data. The implementation of this function must fill at most
+ * len bytes of data into buf. The memory area of buf is allocated by
+ * library and not be freed by the application code. flags is always 0
+ * in this version. user_data is one given in
+ * wslay_frame_context_init() function. The implementation of this
+ * function must return the number of bytes filled. If there is an
+ * error, return -1. The return value 0 is also treated an error by
+ * the library.
+ */
+typedef ssize_t (*wslay_frame_recv_callback)(uint8_t *buf, size_t len,
+ int flags, void *user_data);
+/*
+ * Callback function used by wslay_frame_send() function when it needs
+ * new mask key. The implementation of this function must write
+ * exactly len bytes of mask key to buf. user_data is one given in
+ * wslay_frame_context_init() function. The implementation of this
+ * function return 0 on success. If there is an error, return -1.
+ */
+typedef int (*wslay_frame_genmask_callback)(uint8_t *buf, size_t len,
+ void *user_data);
+
+struct wslay_frame_callbacks {
+ wslay_frame_send_callback send_callback;
+ wslay_frame_recv_callback recv_callback;
+ wslay_frame_genmask_callback genmask_callback;
+};
+
+/*
+ * The opcode defined in RFC6455.
+ */
+enum wslay_opcode {
+ WSLAY_CONTINUATION_FRAME = 0x0u,
+ WSLAY_TEXT_FRAME = 0x1u,
+ WSLAY_BINARY_FRAME = 0x2u,
+ WSLAY_CONNECTION_CLOSE = 0x8u,
+ WSLAY_PING = 0x9u,
+ WSLAY_PONG = 0xau
+};
+
+/*
+ * Macro that returns 1 if opcode is control frame opcode, otherwise
+ * returns 0.
+ */
+#define wslay_is_ctrl_frame(opcode) ((opcode >> 3) & 1)
+
+/*
+ * Macros that represent and return reserved bits: RSV1, RSV2, RSV3.
+ * These macros assume that rsv is constructed by ((RSV1 << 2) |
+ * (RSV2 << 1) | RSV3)
+ */
+#define WSLAY_RSV_NONE ((uint8_t) 0)
+#define WSLAY_RSV1_BIT (((uint8_t) 1) << 2)
+#define WSLAY_RSV2_BIT (((uint8_t) 1) << 1)
+#define WSLAY_RSV3_BIT (((uint8_t) 1) << 0)
+
+#define wslay_get_rsv1(rsv) ((rsv >> 2) & 1)
+#define wslay_get_rsv2(rsv) ((rsv >> 1) & 1)
+#define wslay_get_rsv3(rsv) (rsv & 1)
+
+struct wslay_frame_iocb {
+ /* 1 for fragmented final frame, 0 for otherwise */
+ uint8_t fin;
+ /*
+ * reserved 3 bits. rsv = ((RSV1 << 2) | (RSV << 1) | RSV3).
+ * RFC6455 requires 0 unless extensions are negotiated.
+ */
+ uint8_t rsv;
+ /* 4 bit opcode */
+ uint8_t opcode;
+ /* payload length [0, 2**63-1] */
+ uint64_t payload_length;
+ /* 1 for masked frame, 0 for unmasked */
+ uint8_t mask;
+ /* part of payload data */
+ const uint8_t *data;
+ /* bytes of data defined above */
+ size_t data_length;
+};
+
+struct wslay_frame_context;
+typedef struct wslay_frame_context *wslay_frame_context_ptr;
+
+/*
+ * Initializes ctx using given callbacks and user_data. This function
+ * allocates memory for struct wslay_frame_context and stores the
+ * result to *ctx. The callback functions specified in callbacks are
+ * copied to ctx. user_data is stored in ctx and it will be passed to
+ * callback functions. When the user code finished using ctx, it must
+ * call wslay_frame_context_free to deallocate memory.
+ */
+int wslay_frame_context_init(wslay_frame_context_ptr *ctx,
+ const struct wslay_frame_callbacks *callbacks,
+ void *user_data);
+
+/*
+ * Deallocates memory pointed by ctx.
+ */
+void wslay_frame_context_free(wslay_frame_context_ptr ctx);
+
+/*
+ * Send WebSocket frame specified in iocb. ctx must be initialized
+ * using wslay_frame_context_init() function. iocb->fin must be 1 if
+ * this is a fin frame, otherwise 0. iocb->rsv is reserved bits.
+ * iocb->opcode must be the opcode of this frame. iocb->mask must be
+ * 1 if this is masked frame, otherwise 0. iocb->payload_length is
+ * the payload_length of this frame. iocb->data must point to the
+ * payload data to be sent. iocb->data_length must be the length of
+ * the data. This function calls send_callback function if it needs
+ * to send bytes. This function calls gen_mask_callback function if
+ * it needs new mask key. This function returns the number of payload
+ * bytes sent. Please note that it does not include any number of
+ * header bytes. If it cannot send any single bytes of payload, it
+ * returns WSLAY_ERR_WANT_WRITE. If the library detects error in iocb,
+ * this function returns WSLAY_ERR_INVALID_ARGUMENT. If callback
+ * functions report a failure, this function returns
+ * WSLAY_ERR_INVALID_CALLBACK. This function does not always send all
+ * given data in iocb. If there are remaining data to be sent, adjust
+ * data and data_length in iocb accordingly and call this function
+ * again.
+ */
+ssize_t wslay_frame_send(wslay_frame_context_ptr ctx,
+ struct wslay_frame_iocb *iocb);
+
+/*
+ * Receives WebSocket frame and stores it in iocb. This function
+ * returns the number of payload bytes received. This does not
+ * include header bytes. In this case, iocb will be populated as
+ * follows: iocb->fin is 1 if received frame is fin frame, otherwise
+ * 0. iocb->rsv is reserved bits of received frame. iocb->opcode is
+ * opcode of received frame. iocb->mask is 1 if received frame is
+ * masked, otherwise 0. iocb->payload_length is the payload length of
+ * received frame. iocb->data is pointed to the buffer containing
+ * received payload data. This buffer is allocated by the library and
+ * must be read-only. iocb->data_length is the number of payload
+ * bytes recieved. This function calls recv_callback if it needs to
+ * receive additional bytes. If it cannot receive any single bytes of
+ * payload, it returns WSLAY_ERR_WANT_READ. If the library detects
+ * protocol violation in a received frame, this function returns
+ * WSLAY_ERR_PROTO. If callback functions report a failure, this
+ * function returns WSLAY_ERR_INVALID_CALLBACK. This function does
+ * not always receive whole frame in a single call. If there are
+ * remaining data to be received, call this function again. This
+ * function ensures frame alignment.
+ */
+ssize_t wslay_frame_recv(wslay_frame_context_ptr ctx,
+ struct wslay_frame_iocb *iocb);
+
+struct wslay_event_context;
+/* Pointer to the event-based API context */
+typedef struct wslay_event_context *wslay_event_context_ptr;
+
+struct wslay_event_on_msg_recv_arg {
+ /* reserved bits: rsv = (RSV1 << 2) | (RSV2 << 1) | RSV3 */
+ uint8_t rsv;
+ /* opcode */
+ uint8_t opcode;
+ /* received message */
+ const uint8_t *msg;
+ /* message length */
+ size_t msg_length;
+ /*
+ * Status code iff opcode == WSLAY_CONNECTION_CLOSE. If no status
+ * code is included in the close control frame, it is set to 0.
+ */
+ uint16_t status_code;
+};
+
+/*
+ * Callback function invoked by wslay_event_recv() when a message is
+ * completely received.
+ */
+typedef void (*wslay_event_on_msg_recv_callback)
+(wslay_event_context_ptr ctx,
+ const struct wslay_event_on_msg_recv_arg *arg, void *user_data);
+
+struct wslay_event_on_frame_recv_start_arg {
+ /* fin bit; 1 for final frame, or 0. */
+ uint8_t fin;
+ /* reserved bits: rsv = (RSV1 << 2) | (RSV2 << 1) | RSV3 */
+ uint8_t rsv;
+ /* opcode of the frame */
+ uint8_t opcode;
+ /* payload length of ths frame */
+ uint64_t payload_length;
+};
+
+/*
+ * Callback function invoked by wslay_event_recv() when a new frame
+ * starts to be received. This callback function is only invoked once
+ * for each frame.
+ */
+typedef void (*wslay_event_on_frame_recv_start_callback)
+(wslay_event_context_ptr ctx,
+ const struct wslay_event_on_frame_recv_start_arg *arg, void *user_data);
+
+struct wslay_event_on_frame_recv_chunk_arg {
+ /* chunk of payload data */
+ const uint8_t *data;
+ /* length of data */
+ size_t data_length;
+};
+
+/*
+ * Callback function invoked by wslay_event_recv() when a chunk of
+ * frame payload is received.
+ */
+typedef void (*wslay_event_on_frame_recv_chunk_callback)
+(wslay_event_context_ptr ctx,
+ const struct wslay_event_on_frame_recv_chunk_arg *arg, void *user_data);
+
+/*
+ * Callback function invoked by wslay_event_recv() when a frame is
+ * completely received.
+ */
+typedef void (*wslay_event_on_frame_recv_end_callback)
+(wslay_event_context_ptr ctx, void *user_data);
+
+/*
+ * Callback function invoked by wslay_event_recv() when it wants to
+ * receive more data from peer. The implementation of this callback
+ * function must read data at most len bytes from peer and store them
+ * in buf and return the number of bytes read. flags is always 0 in
+ * this version.
+ *
+ * If there is an error, return -1 and set error code
+ * WSLAY_ERR_CALLBACK_FAILURE using wslay_event_set_error(). Wslay
+ * event-based API on the whole assumes non-blocking I/O. If the cause
+ * of error is EAGAIN or EWOULDBLOCK, set WSLAY_ERR_WOULDBLOCK
+ * instead. This is important because it tells wslay_event_recv() to
+ * stop receiving further data and return.
+ */
+typedef ssize_t (*wslay_event_recv_callback)(wslay_event_context_ptr ctx,
+ uint8_t *buf, size_t len,
+ int flags, void *user_data);
+
+/*
+ * Callback function invoked by wslay_event_send() when it wants to
+ * send more data to peer. The implementation of this callback
+ * function must send data at most len bytes to peer and return the
+ * number of bytes sent. flags is the bitwise OR of zero or more of
+ * the following flag:
+ *
+ * WSLAY_MSG_MORE
+ * There is more data to send
+ *
+ * It provides some hints to tune performance and behaviour.
+ *
+ * If there is an error, return -1 and set error code
+ * WSLAY_ERR_CALLBACK_FAILURE using wslay_event_set_error(). Wslay
+ * event-based API on the whole assumes non-blocking I/O. If the cause
+ * of error is EAGAIN or EWOULDBLOCK, set WSLAY_ERR_WOULDBLOCK
+ * instead. This is important because it tells wslay_event_send() to
+ * stop sending data and return.
+ */
+typedef ssize_t (*wslay_event_send_callback)(wslay_event_context_ptr ctx,
+ const uint8_t *data, size_t len,
+ int flags, void *user_data);
+
+/*
+ * Callback function invoked by wslay_event_send() when it wants new
+ * mask key. As described in RFC6455, only the traffic from WebSocket
+ * client is masked, so this callback function is only needed if an
+ * event-based API is initialized for WebSocket client use.
+ */
+typedef int (*wslay_event_genmask_callback)(wslay_event_context_ptr ctx,
+ uint8_t *buf, size_t len,
+ void *user_data);
+
+struct wslay_event_callbacks {
+ wslay_event_recv_callback recv_callback;
+ wslay_event_send_callback send_callback;
+ wslay_event_genmask_callback genmask_callback;
+ wslay_event_on_frame_recv_start_callback on_frame_recv_start_callback;
+ wslay_event_on_frame_recv_chunk_callback on_frame_recv_chunk_callback;
+ wslay_event_on_frame_recv_end_callback on_frame_recv_end_callback;
+ wslay_event_on_msg_recv_callback on_msg_recv_callback;
+};
+
+/*
+ * Initializes ctx as WebSocket Server. user_data is an arbitrary
+ * pointer, which is directly passed to each callback functions as
+ * user_data argument.
+ *
+ * On success, returns 0. On error, returns one of following negative
+ * values:
+ *
+ * WSLAY_ERR_NOMEM
+ * Out of memory.
+ */
+int wslay_event_context_server_init
+(wslay_event_context_ptr *ctx,
+ const struct wslay_event_callbacks *callbacks, void *user_data);
+
+/*
+ * Initializes ctx as WebSocket client. user_data is an arbitrary
+ * pointer, which is directly passed to each callback functions as
+ * user_data argument.
+ *
+ * On success, returns 0. On error, returns one of following negative
+ * values:
+ *
+ * WSLAY_ERR_NOMEM
+ * Out of memory.
+ */
+int wslay_event_context_client_init
+(wslay_event_context_ptr *ctx,
+ const struct wslay_event_callbacks *callbacks, void *user_data);
+
+/*
+ * Releases allocated resources for ctx.
+ */
+void wslay_event_context_free(wslay_event_context_ptr ctx);
+
+/*
+ * Sets a bit mask of allowed reserved bits.
+ * Currently only permitted values are WSLAY_RSV1_BIT to allow PMCE
+ * extension (see RFC-7692) or WSLAY_RSV_NONE to disable.
+ *
+ * Default: WSLAY_RSV_NONE
+ */
+void wslay_event_config_set_allowed_rsv_bits(wslay_event_context_ptr ctx,
+ uint8_t rsv);
+
+/*
+ * Enables or disables buffering of an entire message for non-control
+ * frames. If val is 0, buffering is enabled. Otherwise, buffering is
+ * disabled. If wslay_event_on_msg_recv_callback is invoked when
+ * buffering is disabled, the msg_length member of struct
+ * wslay_event_on_msg_recv_arg is set to 0.
+ *
+ * The control frames are always buffered regardless of this function call.
+ *
+ * This function must not be used after the first invocation of
+ * wslay_event_recv() function.
+ */
+void wslay_event_config_set_no_buffering(wslay_event_context_ptr ctx, int val);
+
+/*
+ * Sets maximum length of a message that can be received. The length
+ * of message is checked by wslay_event_recv() function. If the length
+ * of a message is larger than this value, reading operation is
+ * disabled (same effect with wslay_event_shutdown_read() call) and
+ * close control frame with WSLAY_CODE_MESSAGE_TOO_BIG is queued. If
+ * buffering for non-control frames is disabled, the library checks
+ * each frame payload length and does not check length of entire
+ * message.
+ *
+ * The default value is (1u << 31)-1.
+ */
+void wslay_event_config_set_max_recv_msg_length(wslay_event_context_ptr ctx,
+ uint64_t val);
+
+/*
+ * Sets callbacks to ctx. The callbacks previouly set by this function
+ * or wslay_event_context_server_init() or
+ * wslay_event_context_client_init() are replaced with callbacks.
+ */
+void wslay_event_config_set_callbacks
+(wslay_event_context_ptr ctx, const struct wslay_event_callbacks *callbacks);
+
+/*
+ * Receives messages from peer. When receiving
+ * messages, it uses wslay_event_recv_callback function. Single call
+ * of this function receives multiple messages until
+ * wslay_event_recv_callback function sets error code
+ * WSLAY_ERR_WOULDBLOCK.
+ *
+ * When close control frame is received, this function automatically
+ * queues close control frame. Also this function calls
+ * wslay_event_set_read_enabled() with second argument 0 to disable
+ * further read from peer.
+ *
+ * When ping control frame is received, this function automatically
+ * queues pong control frame.
+ *
+ * In case of a fatal errror which leads to negative return code, this
+ * function calls wslay_event_set_read_enabled() with second argument
+ * 0 to disable further read from peer.
+ *
+ * wslay_event_recv() returns 0 if it succeeds, or one of the
+ * following negative error codes:
+ *
+ * WSLAY_ERR_CALLBACK_FAILURE
+ * User defined callback function is failed.
+ *
+ * WSLAY_ERR_NOMEM
+ * Out of memory.
+ *
+ * When negative error code is returned, application must not make any
+ * further call of wslay_event_recv() and must close WebSocket
+ * connection.
+ */
+int wslay_event_recv(wslay_event_context_ptr ctx);
+
+/*
+ * Sends queued messages to peer. When sending a
+ * message, it uses wslay_event_send_callback function. Single call of
+ * wslay_event_send() sends multiple messages until
+ * wslay_event_send_callback sets error code WSLAY_ERR_WOULDBLOCK.
+ *
+ * If ctx is initialized for WebSocket client use, wslay_event_send()
+ * uses wslay_event_genmask_callback to get new mask key.
+ *
+ * When a message queued using wslay_event_queue_fragmented_msg() is
+ * sent, wslay_event_send() invokes
+ * wslay_event_fragmented_msg_callback for that message.
+ *
+ * After close control frame is sent, this function calls
+ * wslay_event_set_write_enabled() with second argument 0 to disable
+ * further transmission to peer.
+ *
+ * If there are any pending messages, wslay_event_want_write() returns
+ * 1, otherwise returns 0.
+ *
+ * In case of a fatal errror which leads to negative return code, this
+ * function calls wslay_event_set_write_enabled() with second argument
+ * 0 to disable further transmission to peer.
+ *
+ * wslay_event_send() returns 0 if it succeeds, or one of the
+ * following negative error codes:
+ *
+ * WSLAY_ERR_CALLBACK_FAILURE
+ * User defined callback function is failed.
+ *
+ * WSLAY_ERR_NOMEM
+ * Out of memory.
+ *
+ * When negative error code is returned, application must not make any
+ * further call of wslay_event_send() and must close WebSocket
+ * connection.
+ */
+int wslay_event_send(wslay_event_context_ptr ctx);
+
+struct wslay_event_msg {
+ uint8_t opcode;
+ const uint8_t *msg;
+ size_t msg_length;
+};
+
+/*
+ * Queues message specified in arg.
+ *
+ * This function supports both control and non-control messages and
+ * the given message is sent without fragmentation. If fragmentation
+ * is needed, use wslay_event_queue_fragmented_msg() function instead.
+ *
+ * This function just queues a message and does not send
+ * it. wslay_event_send() function call sends these queued messages.
+ *
+ * wslay_event_queue_msg() returns 0 if it succeeds, or returns the
+ * following negative error codes:
+ *
+ * WSLAY_ERR_NO_MORE_MSG
+ * Could not queue given message. The one of possible reason is that
+ * close control frame has been queued/sent and no further queueing
+ * message is not allowed.
+ *
+ * WSLAY_ERR_INVALID_ARGUMENT
+ * The given message is invalid.
+ *
+ * WSLAY_ERR_NOMEM
+ * Out of memory.
+ */
+int wslay_event_queue_msg(wslay_event_context_ptr ctx,
+ const struct wslay_event_msg *arg);
+
+/*
+ * Extended version of wslay_event_queue_msg which allows to set reserved bits.
+ */
+int wslay_event_queue_msg_ex(wslay_event_context_ptr ctx,
+ const struct wslay_event_msg *arg, uint8_t rsv);
+
+/*
+ * Specify "source" to generate message.
+ */
+union wslay_event_msg_source {
+ int fd;
+ void *data;
+};
+
+/*
+ * Callback function called by wslay_event_send() to read message data
+ * from source. The implementation of
+ * wslay_event_fragmented_msg_callback must store at most len bytes of
+ * data to buf and return the number of stored bytes. If all data is
+ * read (i.e., EOF), set *eof to 1. If no data can be generated at the
+ * moment, return 0. If there is an error, return -1 and set error
+ * code WSLAY_ERR_CALLBACK_FAILURE using wslay_event_set_error().
+ */
+typedef ssize_t (*wslay_event_fragmented_msg_callback)
+(wslay_event_context_ptr ctx,
+ uint8_t *buf, size_t len, const union wslay_event_msg_source *source,
+ int *eof, void *user_data);
+
+struct wslay_event_fragmented_msg {
+ /* opcode */
+ uint8_t opcode;
+ /* "source" to generate message data */
+ union wslay_event_msg_source source;
+ /* Callback function to read message data from source. */
+ wslay_event_fragmented_msg_callback read_callback;
+};
+
+/*
+ * Queues a fragmented message specified in arg.
+ *
+ * This function supports non-control messages only. For control frames,
+ * use wslay_event_queue_msg() or wslay_event_queue_close().
+ *
+ * This function just queues a message and does not send
+ * it. wslay_event_send() function call sends these queued messages.
+ *
+ * wslay_event_queue_fragmented_msg() returns 0 if it succeeds, or
+ * returns the following negative error codes:
+ *
+ * WSLAY_ERR_NO_MORE_MSG
+ * Could not queue given message. The one of possible reason is that
+ * close control frame has been queued/sent and no further queueing
+ * message is not allowed.
+ *
+ * WSLAY_ERR_INVALID_ARGUMENT
+ * The given message is invalid.
+ *
+ * WSLAY_ERR_NOMEM
+ * Out of memory.
+ */
+int wslay_event_queue_fragmented_msg
+(wslay_event_context_ptr ctx, const struct wslay_event_fragmented_msg *arg);
+
+/*
+ * Extended version of wslay_event_queue_fragmented_msg which allows to set
+ * reserved bits.
+ */
+int wslay_event_queue_fragmented_msg_ex(wslay_event_context_ptr ctx,
+ const struct wslay_event_fragmented_msg *arg, uint8_t rsv);
+
+/*
+ * Queues close control frame. This function is provided just for
+ * convenience. wslay_event_queue_msg() can queue a close control
+ * frame as well. status_code is the status code of close control
+ * frame. reason is the close reason encoded in UTF-8. reason_length
+ * is the length of reason in bytes. reason_length must be less than
+ * 123 bytes.
+ *
+ * If status_code is 0, reason and reason_length is not used and close
+ * control frame with zero-length payload will be queued.
+ *
+ * This function just queues a message and does not send
+ * it. wslay_event_send() function call sends these queued messages.
+ *
+ * wslay_event_queue_close() returns 0 if it succeeds, or returns the
+ * following negative error codes:
+ *
+ * WSLAY_ERR_NO_MORE_MSG
+ * Could not queue given message. The one of possible reason is that
+ * close control frame has been queued/sent and no further queueing
+ * message is not allowed.
+ *
+ * WSLAY_ERR_INVALID_ARGUMENT
+ * The given message is invalid.
+ *
+ * WSLAY_ERR_NOMEM
+ * Out of memory.
+ */
+int wslay_event_queue_close(wslay_event_context_ptr ctx,
+ uint16_t status_code,
+ const uint8_t *reason, size_t reason_length);
+
+/*
+ * Sets error code to tell the library there is an error. This
+ * function is typically used in user defined callback functions. See
+ * the description of callback function to know which error code
+ * should be used.
+ */
+void wslay_event_set_error(wslay_event_context_ptr ctx, int val);
+
+/*
+ * Query whehter the library want to read more data from peer.
+ *
+ * wslay_event_want_read() returns 1 if the library want to read more
+ * data from peer, or returns 0.
+ */
+int wslay_event_want_read(wslay_event_context_ptr ctx);
+
+/*
+ * Query whehter the library want to send more data to peer.
+ *
+ * wslay_event_want_write() returns 1 if the library want to send more
+ * data to peer, or returns 0.
+ */
+int wslay_event_want_write(wslay_event_context_ptr ctx);
+
+/*
+ * Prevents the event-based API context from reading any further data
+ * from peer.
+ *
+ * This function may be used with wslay_event_queue_close() if the
+ * application detects error in the data received and wants to fail
+ * WebSocket connection.
+ */
+void wslay_event_shutdown_read(wslay_event_context_ptr ctx);
+
+/*
+ * Prevents the event-based API context from sending any further data
+ * to peer.
+ */
+void wslay_event_shutdown_write(wslay_event_context_ptr ctx);
+
+/*
+ * Returns 1 if the event-based API context allows read operation, or
+ * return 0.
+ *
+ * After wslay_event_shutdown_read() is called,
+ * wslay_event_get_read_enabled() returns 0.
+ */
+int wslay_event_get_read_enabled(wslay_event_context_ptr ctx);
+
+/*
+ * Returns 1 if the event-based API context allows write operation, or
+ * return 0.
+ *
+ * After wslay_event_shutdown_write() is called,
+ * wslay_event_get_write_enabled() returns 0.
+ */
+int wslay_event_get_write_enabled(wslay_event_context_ptr ctx);
+
+/*
+ * Returns 1 if a close control frame has been received from peer, or
+ * returns 0.
+ */
+int wslay_event_get_close_received(wslay_event_context_ptr ctx);
+
+/*
+ * Returns 1 if a close control frame has been sent to peer, or
+ * returns 0.
+ */
+int wslay_event_get_close_sent(wslay_event_context_ptr ctx);
+
+/*
+ * Returns status code received in close control frame. If no close
+ * control frame has not been received, returns
+ * WSLAY_CODE_ABNORMAL_CLOSURE. If received close control frame has no
+ * status code, returns WSLAY_CODE_NO_STATUS_RCVD.
+ */
+uint16_t wslay_event_get_status_code_received(wslay_event_context_ptr ctx);
+
+/*
+ * Returns status code sent in close control frame. If no close
+ * control frame has not been sent, returns
+ * WSLAY_CODE_ABNORMAL_CLOSURE. If sent close control frame has no
+ * status code, returns WSLAY_CODE_NO_STATUS_RCVD.
+ */
+uint16_t wslay_event_get_status_code_sent(wslay_event_context_ptr ctx);
+
+/*
+ * Returns the number of queued messages.
+ */
+size_t wslay_event_get_queued_msg_count(wslay_event_context_ptr ctx);
+
+/*
+ * Returns the sum of queued message length. It only counts the
+ * message length queued using wslay_event_queue_msg() or
+ * wslay_event_queue_close().
+ */
+size_t wslay_event_get_queued_msg_length(wslay_event_context_ptr ctx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WSLAY_H */
diff --git a/thirdparty/wslay/includes/wslay/wslayver.h b/thirdparty/wslay/includes/wslay/wslayver.h
new file mode 100644
index 0000000000..2c3e282e9d
--- /dev/null
+++ b/thirdparty/wslay/includes/wslay/wslayver.h
@@ -0,0 +1,31 @@
+/*
+ * Wslay - The WebSocket Library
+ *
+ * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef WSLAYVER_H
+#define WSLAYVER_H
+
+/* Version number of wslay release */
+#define WSLAY_VERSION "1.1.0"
+
+#endif /* WSLAYVER_H */
diff --git a/thirdparty/wslay/msvcfix.diff b/thirdparty/wslay/msvcfix.diff
new file mode 100644
index 0000000000..28721844f4
--- /dev/null
+++ b/thirdparty/wslay/msvcfix.diff
@@ -0,0 +1,17 @@
+diff --git a/thirdparty/wslay/includes/wslay/wslay.h b/thirdparty/wslay/includes/wslay/wslay.h
+index 2fde81a4e..9c751b05b 100644
+--- a/thirdparty/wslay/includes/wslay/wslay.h
++++ b/thirdparty/wslay/includes/wslay/wslay.h
+@@ -33,6 +33,12 @@ extern "C" {
+ #include <stdlib.h>
+ #include <sys/types.h>
+
++/* GODOT ADDITTION */
++#if defined(_MSC_VER)
++#include <BaseTsd.h>
++typedef SSIZE_T ssize_t;
++#endif
++/* GODOT END */
+
+ /*
+ * wslay/wslayver.h is generated from wslay/wslayver.h.in by
diff --git a/thirdparty/wslay/wslay_event.c b/thirdparty/wslay/wslay_event.c
new file mode 100644
index 0000000000..57415c51e0
--- /dev/null
+++ b/thirdparty/wslay/wslay_event.c
@@ -0,0 +1,1027 @@
+/*
+ * Wslay - The WebSocket Library
+ *
+ * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "wslay_event.h"
+
+#include <string.h>
+#include <assert.h>
+#include <stdio.h>
+
+#include "wslay_queue.h"
+#include "wslay_frame.h"
+#include "wslay_net.h"
+/* Start of utf8 dfa */
+/* Copyright (c) 2008-2010 Bjoern Hoehrmann <bjoern@hoehrmann.de>
+ * See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details.
+ *
+ * Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#define UTF8_ACCEPT 0
+#define UTF8_REJECT 12
+
+static const uint8_t utf8d[] = {
+ /*
+ * The first part of the table maps bytes to character classes that
+ * to reduce the size of the transition table and create bitmasks.
+ */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+ 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
+
+ /*
+ * The second part is a transition table that maps a combination
+ * of a state of the automaton and a character class to a state.
+ */
+ 0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12,
+ 12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12,
+ 12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12,
+ 12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12,
+ 12,36,12,12,12,12,12,12,12,12,12,12,
+};
+
+static uint32_t
+decode(uint32_t* state, uint32_t* codep, uint32_t byte) {
+ uint32_t type = utf8d[byte];
+
+ *codep = (*state != UTF8_ACCEPT) ?
+ (byte & 0x3fu) | (*codep << 6) :
+ (0xff >> type) & (byte);
+
+ *state = utf8d[256 + *state + type];
+ return *state;
+}
+
+/* End of utf8 dfa */
+
+static ssize_t wslay_event_frame_recv_callback(uint8_t *buf, size_t len,
+ int flags, void *user_data)
+{
+ struct wslay_event_frame_user_data *e =
+ (struct wslay_event_frame_user_data*)user_data;
+ return e->ctx->callbacks.recv_callback(e->ctx, buf, len, flags, e->user_data);
+}
+
+static ssize_t wslay_event_frame_send_callback(const uint8_t *data, size_t len,
+ int flags, void *user_data)
+{
+ struct wslay_event_frame_user_data *e =
+ (struct wslay_event_frame_user_data*)user_data;
+ return e->ctx->callbacks.send_callback(e->ctx, data, len, flags,
+ e->user_data);
+}
+
+static int wslay_event_frame_genmask_callback(uint8_t *buf, size_t len,
+ void *user_data)
+{
+ struct wslay_event_frame_user_data *e =
+ (struct wslay_event_frame_user_data*)user_data;
+ return e->ctx->callbacks.genmask_callback(e->ctx, buf, len, e->user_data);
+}
+
+static int wslay_event_byte_chunk_init
+(struct wslay_event_byte_chunk **chunk, size_t len)
+{
+ *chunk = (struct wslay_event_byte_chunk*)malloc
+ (sizeof(struct wslay_event_byte_chunk));
+ if(*chunk == NULL) {
+ return WSLAY_ERR_NOMEM;
+ }
+ memset(*chunk, 0, sizeof(struct wslay_event_byte_chunk));
+ if(len) {
+ (*chunk)->data = (uint8_t*)malloc(len);
+ if((*chunk)->data == NULL) {
+ free(*chunk);
+ return WSLAY_ERR_NOMEM;
+ }
+ (*chunk)->data_length = len;
+ }
+ return 0;
+}
+
+static void wslay_event_byte_chunk_free(struct wslay_event_byte_chunk *c)
+{
+ if(!c) {
+ return;
+ }
+ free(c->data);
+ free(c);
+}
+
+static void wslay_event_byte_chunk_copy(struct wslay_event_byte_chunk *c,
+ size_t off,
+ const uint8_t *data, size_t data_length)
+{
+ memcpy(c->data+off, data, data_length);
+}
+
+static void wslay_event_imsg_set(struct wslay_event_imsg *m,
+ uint8_t fin, uint8_t rsv, uint8_t opcode)
+{
+ m->fin = fin;
+ m->rsv = rsv;
+ m->opcode = opcode;
+ m->msg_length = 0;
+}
+
+static void wslay_event_imsg_chunks_free(struct wslay_event_imsg *m)
+{
+ if(!m->chunks) {
+ return;
+ }
+ while(!wslay_queue_empty(m->chunks)) {
+ wslay_event_byte_chunk_free(wslay_queue_top(m->chunks));
+ wslay_queue_pop(m->chunks);
+ }
+}
+
+static void wslay_event_imsg_reset(struct wslay_event_imsg *m)
+{
+ m->opcode = 0xffu;
+ m->utf8state = UTF8_ACCEPT;
+ wslay_event_imsg_chunks_free(m);
+}
+
+static int wslay_event_imsg_append_chunk(struct wslay_event_imsg *m, size_t len)
+{
+ if(len == 0) {
+ return 0;
+ } else {
+ int r;
+ struct wslay_event_byte_chunk *chunk;
+ if((r = wslay_event_byte_chunk_init(&chunk, len)) != 0) {
+ return r;
+ }
+ if((r = wslay_queue_push(m->chunks, chunk)) != 0) {
+ return r;
+ }
+ m->msg_length += len;
+ return 0;
+ }
+}
+
+static int wslay_event_omsg_non_fragmented_init
+(struct wslay_event_omsg **m, uint8_t opcode, uint8_t rsv,
+ const uint8_t *msg, size_t msg_length)
+{
+ *m = (struct wslay_event_omsg*)malloc(sizeof(struct wslay_event_omsg));
+ if(!*m) {
+ return WSLAY_ERR_NOMEM;
+ }
+ memset(*m, 0, sizeof(struct wslay_event_omsg));
+ (*m)->fin = 1;
+ (*m)->opcode = opcode;
+ (*m)->rsv = rsv;
+ (*m)->type = WSLAY_NON_FRAGMENTED;
+ if(msg_length) {
+ (*m)->data = (uint8_t*)malloc(msg_length);
+ if(!(*m)->data) {
+ free(*m);
+ return WSLAY_ERR_NOMEM;
+ }
+ memcpy((*m)->data, msg, msg_length);
+ (*m)->data_length = msg_length;
+ }
+ return 0;
+}
+
+static int wslay_event_omsg_fragmented_init
+(struct wslay_event_omsg **m, uint8_t opcode, uint8_t rsv,
+ const union wslay_event_msg_source source,
+ wslay_event_fragmented_msg_callback read_callback)
+{
+ *m = (struct wslay_event_omsg*)malloc(sizeof(struct wslay_event_omsg));
+ if(!*m) {
+ return WSLAY_ERR_NOMEM;
+ }
+ memset(*m, 0, sizeof(struct wslay_event_omsg));
+ (*m)->opcode = opcode;
+ (*m)->rsv = rsv;
+ (*m)->type = WSLAY_FRAGMENTED;
+ (*m)->source = source;
+ (*m)->read_callback = read_callback;
+ return 0;
+}
+
+static void wslay_event_omsg_free(struct wslay_event_omsg *m)
+{
+ if(!m) {
+ return;
+ }
+ free(m->data);
+ free(m);
+}
+
+static uint8_t* wslay_event_flatten_queue(struct wslay_queue *queue, size_t len)
+{
+ if(len == 0) {
+ return NULL;
+ } else {
+ size_t off = 0;
+ uint8_t *buf = (uint8_t*)malloc(len);
+ if(!buf) {
+ return NULL;
+ }
+ while(!wslay_queue_empty(queue)) {
+ struct wslay_event_byte_chunk *chunk = wslay_queue_top(queue);
+ memcpy(buf+off, chunk->data, chunk->data_length);
+ off += chunk->data_length;
+ wslay_event_byte_chunk_free(chunk);
+ wslay_queue_pop(queue);
+ assert(off <= len);
+ }
+ assert(len == off);
+ return buf;
+ }
+}
+
+static int wslay_event_is_msg_queueable(wslay_event_context_ptr ctx)
+{
+ return ctx->write_enabled && (ctx->close_status & WSLAY_CLOSE_QUEUED) == 0;
+}
+
+int wslay_event_queue_close(wslay_event_context_ptr ctx, uint16_t status_code,
+ const uint8_t *reason, size_t reason_length)
+{
+ if(!wslay_event_is_msg_queueable(ctx)) {
+ return WSLAY_ERR_NO_MORE_MSG;
+ } else if(reason_length > 123) {
+ return WSLAY_ERR_INVALID_ARGUMENT;
+ } else {
+ uint8_t msg[128];
+ size_t msg_length;
+ struct wslay_event_msg arg;
+ uint16_t ncode;
+ int r;
+ if(status_code == 0) {
+ msg_length = 0;
+ } else {
+ ncode = htons(status_code);
+ memcpy(msg, &ncode, 2);
+ if(reason_length) {
+ memcpy(msg+2, reason, reason_length);
+ }
+ msg_length = reason_length+2;
+ }
+ arg.opcode = WSLAY_CONNECTION_CLOSE;
+ arg.msg = msg;
+ arg.msg_length = msg_length;
+ r = wslay_event_queue_msg(ctx, &arg);
+ if(r == 0) {
+ ctx->close_status |= WSLAY_CLOSE_QUEUED;
+ }
+ return r;
+ }
+}
+
+static int wslay_event_queue_close_wrapper
+(wslay_event_context_ptr ctx, uint16_t status_code,
+ const uint8_t *reason, size_t reason_length)
+{
+ int r;
+ ctx->read_enabled = 0;
+ if((r = wslay_event_queue_close(ctx, status_code, reason, reason_length)) &&
+ r != WSLAY_ERR_NO_MORE_MSG) {
+ return r;
+ }
+ return 0;
+}
+
+static int wslay_event_verify_rsv_bits(wslay_event_context_ptr ctx, uint8_t rsv)
+{
+ return ((rsv & ~ctx->allowed_rsv_bits) == 0);
+}
+
+int wslay_event_queue_msg(wslay_event_context_ptr ctx,
+ const struct wslay_event_msg *arg)
+{
+ return wslay_event_queue_msg_ex(ctx, arg, WSLAY_RSV_NONE);
+}
+
+int wslay_event_queue_msg_ex(wslay_event_context_ptr ctx,
+ const struct wslay_event_msg *arg, uint8_t rsv)
+{
+ int r;
+ struct wslay_event_omsg *omsg;
+ if(!wslay_event_is_msg_queueable(ctx)) {
+ return WSLAY_ERR_NO_MORE_MSG;
+ }
+ /* RSV1 is not allowed for control frames */
+ if((wslay_is_ctrl_frame(arg->opcode) &&
+ (arg->msg_length > 125 || wslay_get_rsv1(rsv)))
+ || !wslay_event_verify_rsv_bits(ctx, rsv)) {
+ return WSLAY_ERR_INVALID_ARGUMENT;
+ }
+ if((r = wslay_event_omsg_non_fragmented_init
+ (&omsg, arg->opcode, rsv, arg->msg, arg->msg_length)) != 0) {
+ return r;
+ }
+ if(wslay_is_ctrl_frame(arg->opcode)) {
+ if((r = wslay_queue_push(ctx->send_ctrl_queue, omsg)) != 0) {
+ return r;
+ }
+ } else {
+ if((r = wslay_queue_push(ctx->send_queue, omsg)) != 0) {
+ return r;
+ }
+ }
+ ++ctx->queued_msg_count;
+ ctx->queued_msg_length += arg->msg_length;
+ return 0;
+}
+
+int wslay_event_queue_fragmented_msg
+(wslay_event_context_ptr ctx, const struct wslay_event_fragmented_msg *arg)
+{
+ return wslay_event_queue_fragmented_msg_ex(ctx, arg, WSLAY_RSV_NONE);
+}
+
+int wslay_event_queue_fragmented_msg_ex(wslay_event_context_ptr ctx,
+ const struct wslay_event_fragmented_msg *arg, uint8_t rsv)
+{
+ int r;
+ struct wslay_event_omsg *omsg;
+ if(!wslay_event_is_msg_queueable(ctx)) {
+ return WSLAY_ERR_NO_MORE_MSG;
+ }
+ if(wslay_is_ctrl_frame(arg->opcode) ||
+ !wslay_event_verify_rsv_bits(ctx, rsv)) {
+ return WSLAY_ERR_INVALID_ARGUMENT;
+ }
+ if((r = wslay_event_omsg_fragmented_init
+ (&omsg, arg->opcode, rsv, arg->source, arg->read_callback)) != 0) {
+ return r;
+ }
+ if((r = wslay_queue_push(ctx->send_queue, omsg)) != 0) {
+ return r;
+ }
+ ++ctx->queued_msg_count;
+ return 0;
+}
+
+void wslay_event_config_set_callbacks
+(wslay_event_context_ptr ctx, const struct wslay_event_callbacks *callbacks)
+{
+ ctx->callbacks = *callbacks;
+}
+
+static int wslay_event_context_init
+(wslay_event_context_ptr *ctx,
+ const struct wslay_event_callbacks *callbacks,
+ void *user_data)
+{
+ int i, r;
+ struct wslay_frame_callbacks frame_callbacks = {
+ wslay_event_frame_send_callback,
+ wslay_event_frame_recv_callback,
+ wslay_event_frame_genmask_callback
+ };
+ *ctx = (wslay_event_context_ptr)malloc(sizeof(struct wslay_event_context));
+ if(!*ctx) {
+ return WSLAY_ERR_NOMEM;
+ }
+ memset(*ctx, 0, sizeof(struct wslay_event_context));
+ wslay_event_config_set_callbacks(*ctx, callbacks);
+ (*ctx)->user_data = user_data;
+ (*ctx)->frame_user_data.ctx = *ctx;
+ (*ctx)->frame_user_data.user_data = user_data;
+ if((r = wslay_frame_context_init(&(*ctx)->frame_ctx, &frame_callbacks,
+ &(*ctx)->frame_user_data)) != 0) {
+ wslay_event_context_free(*ctx);
+ return r;
+ }
+ (*ctx)->read_enabled = (*ctx)->write_enabled = 1;
+ (*ctx)->send_queue = wslay_queue_new();
+ if(!(*ctx)->send_queue) {
+ wslay_event_context_free(*ctx);
+ return WSLAY_ERR_NOMEM;
+ }
+ (*ctx)->send_ctrl_queue = wslay_queue_new();
+ if(!(*ctx)->send_ctrl_queue) {
+ wslay_event_context_free(*ctx);
+ return WSLAY_ERR_NOMEM;
+ }
+ (*ctx)->queued_msg_count = 0;
+ (*ctx)->queued_msg_length = 0;
+ for(i = 0; i < 2; ++i) {
+ wslay_event_imsg_reset(&(*ctx)->imsgs[i]);
+ (*ctx)->imsgs[i].chunks = wslay_queue_new();
+ if(!(*ctx)->imsgs[i].chunks) {
+ wslay_event_context_free(*ctx);
+ return WSLAY_ERR_NOMEM;
+ }
+ }
+ (*ctx)->imsg = &(*ctx)->imsgs[0];
+ (*ctx)->obufmark = (*ctx)->obuflimit = (*ctx)->obuf;
+ (*ctx)->status_code_sent = WSLAY_CODE_ABNORMAL_CLOSURE;
+ (*ctx)->status_code_recv = WSLAY_CODE_ABNORMAL_CLOSURE;
+ (*ctx)->max_recv_msg_length = (1u << 31)-1;
+ return 0;
+}
+
+int wslay_event_context_server_init
+(wslay_event_context_ptr *ctx,
+ const struct wslay_event_callbacks *callbacks,
+ void *user_data)
+{
+ int r;
+ if((r = wslay_event_context_init(ctx, callbacks, user_data)) != 0) {
+ return r;
+ }
+ (*ctx)->server = 1;
+ return 0;
+}
+
+int wslay_event_context_client_init
+(wslay_event_context_ptr *ctx,
+ const struct wslay_event_callbacks *callbacks,
+ void *user_data)
+{
+ int r;
+ if((r = wslay_event_context_init(ctx, callbacks, user_data)) != 0) {
+ return r;
+ }
+ (*ctx)->server = 0;
+ return 0;
+}
+
+void wslay_event_context_free(wslay_event_context_ptr ctx)
+{
+ int i;
+ if(!ctx) {
+ return;
+ }
+ for(i = 0; i < 2; ++i) {
+ wslay_event_imsg_chunks_free(&ctx->imsgs[i]);
+ wslay_queue_free(ctx->imsgs[i].chunks);
+ }
+ if(ctx->send_queue) {
+ while(!wslay_queue_empty(ctx->send_queue)) {
+ wslay_event_omsg_free(wslay_queue_top(ctx->send_queue));
+ wslay_queue_pop(ctx->send_queue);
+ }
+ wslay_queue_free(ctx->send_queue);
+ }
+ if(ctx->send_ctrl_queue) {
+ while(!wslay_queue_empty(ctx->send_ctrl_queue)) {
+ wslay_event_omsg_free(wslay_queue_top(ctx->send_ctrl_queue));
+ wslay_queue_pop(ctx->send_ctrl_queue);
+ }
+ wslay_queue_free(ctx->send_ctrl_queue);
+ }
+ wslay_frame_context_free(ctx->frame_ctx);
+ wslay_event_omsg_free(ctx->omsg);
+ free(ctx);
+}
+
+static void wslay_event_call_on_frame_recv_start_callback
+(wslay_event_context_ptr ctx, const struct wslay_frame_iocb *iocb)
+{
+ if(ctx->callbacks.on_frame_recv_start_callback) {
+ struct wslay_event_on_frame_recv_start_arg arg;
+ arg.fin = iocb->fin;
+ arg.rsv = iocb->rsv;
+ arg.opcode = iocb->opcode;
+ arg.payload_length = iocb->payload_length;
+ ctx->callbacks.on_frame_recv_start_callback(ctx, &arg, ctx->user_data);
+ }
+}
+
+static void wslay_event_call_on_frame_recv_chunk_callback
+(wslay_event_context_ptr ctx, const struct wslay_frame_iocb *iocb)
+{
+ if(ctx->callbacks.on_frame_recv_chunk_callback) {
+ struct wslay_event_on_frame_recv_chunk_arg arg;
+ arg.data = iocb->data;
+ arg.data_length = iocb->data_length;
+ ctx->callbacks.on_frame_recv_chunk_callback(ctx, &arg, ctx->user_data);
+ }
+}
+
+static void wslay_event_call_on_frame_recv_end_callback
+(wslay_event_context_ptr ctx)
+{
+ if(ctx->callbacks.on_frame_recv_end_callback) {
+ ctx->callbacks.on_frame_recv_end_callback(ctx, ctx->user_data);
+ }
+}
+
+static int wslay_event_is_valid_status_code(uint16_t status_code)
+{
+ return (1000 <= status_code && status_code <= 1011 &&
+ status_code != 1004 && status_code != 1005 && status_code != 1006) ||
+ (3000 <= status_code && status_code <= 4999);
+}
+
+static int wslay_event_config_get_no_buffering(wslay_event_context_ptr ctx)
+{
+ return (ctx->config & WSLAY_CONFIG_NO_BUFFERING) > 0;
+}
+
+int wslay_event_recv(wslay_event_context_ptr ctx)
+{
+ struct wslay_frame_iocb iocb;
+ ssize_t r;
+ while(ctx->read_enabled) {
+ memset(&iocb, 0, sizeof(iocb));
+ r = wslay_frame_recv(ctx->frame_ctx, &iocb);
+ if(r >= 0) {
+ int new_frame = 0;
+ /* RSV1 is not allowed on control and continuation frames */
+ if((!wslay_event_verify_rsv_bits(ctx, iocb.rsv)) ||
+ (wslay_get_rsv1(iocb.rsv) && (wslay_is_ctrl_frame(iocb.opcode) ||
+ iocb.opcode == WSLAY_CONTINUATION_FRAME)) ||
+ (ctx->server && !iocb.mask) || (!ctx->server && iocb.mask)) {
+ if((r = wslay_event_queue_close_wrapper
+ (ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) {
+ return r;
+ }
+ break;
+ }
+ if(ctx->imsg->opcode == 0xffu) {
+ if(iocb.opcode == WSLAY_TEXT_FRAME ||
+ iocb.opcode == WSLAY_BINARY_FRAME ||
+ iocb.opcode == WSLAY_CONNECTION_CLOSE ||
+ iocb.opcode == WSLAY_PING ||
+ iocb.opcode == WSLAY_PONG) {
+ wslay_event_imsg_set(ctx->imsg, iocb.fin, iocb.rsv, iocb.opcode);
+ new_frame = 1;
+ } else {
+ if((r = wslay_event_queue_close_wrapper
+ (ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) {
+ return r;
+ }
+ break;
+ }
+ } else if(ctx->ipayloadlen == 0 && ctx->ipayloadoff == 0) {
+ if(iocb.opcode == WSLAY_CONTINUATION_FRAME) {
+ ctx->imsg->fin = iocb.fin;
+ } else if(iocb.opcode == WSLAY_CONNECTION_CLOSE ||
+ iocb.opcode == WSLAY_PING ||
+ iocb.opcode == WSLAY_PONG) {
+ ctx->imsg = &ctx->imsgs[1];
+ wslay_event_imsg_set(ctx->imsg, iocb.fin, iocb.rsv, iocb.opcode);
+ } else {
+ if((r = wslay_event_queue_close_wrapper
+ (ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) {
+ return r;
+ }
+ break;
+ }
+ new_frame = 1;
+ }
+ if(new_frame) {
+ if(ctx->imsg->msg_length+iocb.payload_length >
+ ctx->max_recv_msg_length) {
+ if((r = wslay_event_queue_close_wrapper
+ (ctx, WSLAY_CODE_MESSAGE_TOO_BIG, NULL, 0)) != 0) {
+ return r;
+ }
+ break;
+ }
+ ctx->ipayloadlen = iocb.payload_length;
+ wslay_event_call_on_frame_recv_start_callback(ctx, &iocb);
+ if(!wslay_event_config_get_no_buffering(ctx) ||
+ wslay_is_ctrl_frame(iocb.opcode)) {
+ if((r = wslay_event_imsg_append_chunk(ctx->imsg,
+ iocb.payload_length)) != 0) {
+ ctx->read_enabled = 0;
+ return r;
+ }
+ }
+ }
+ /* If RSV1 bit is set then it is too early for utf-8 validation */
+ if((!wslay_get_rsv1(ctx->imsg->rsv) &&
+ ctx->imsg->opcode == WSLAY_TEXT_FRAME) ||
+ ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) {
+ size_t i;
+ if(ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) {
+ i = 2;
+ } else {
+ i = 0;
+ }
+ for(; i < iocb.data_length; ++i) {
+ uint32_t codep;
+ if(decode(&ctx->imsg->utf8state, &codep,
+ iocb.data[i]) == UTF8_REJECT) {
+ if((r = wslay_event_queue_close_wrapper
+ (ctx, WSLAY_CODE_INVALID_FRAME_PAYLOAD_DATA, NULL, 0)) != 0) {
+ return r;
+ }
+ break;
+ }
+ }
+ }
+ if(ctx->imsg->utf8state == UTF8_REJECT) {
+ break;
+ }
+ wslay_event_call_on_frame_recv_chunk_callback(ctx, &iocb);
+ if(iocb.data_length > 0) {
+ if(!wslay_event_config_get_no_buffering(ctx) ||
+ wslay_is_ctrl_frame(iocb.opcode)) {
+ struct wslay_event_byte_chunk *chunk;
+ chunk = wslay_queue_tail(ctx->imsg->chunks);
+ wslay_event_byte_chunk_copy(chunk, ctx->ipayloadoff,
+ iocb.data, iocb.data_length);
+ }
+ ctx->ipayloadoff += iocb.data_length;
+ }
+ if(ctx->ipayloadoff == ctx->ipayloadlen) {
+ if(ctx->imsg->fin &&
+ (ctx->imsg->opcode == WSLAY_TEXT_FRAME ||
+ ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) &&
+ ctx->imsg->utf8state != UTF8_ACCEPT) {
+ if((r = wslay_event_queue_close_wrapper
+ (ctx, WSLAY_CODE_INVALID_FRAME_PAYLOAD_DATA, NULL, 0)) != 0) {
+ return r;
+ }
+ break;
+ }
+ wslay_event_call_on_frame_recv_end_callback(ctx);
+ if(ctx->imsg->fin) {
+ if(ctx->callbacks.on_msg_recv_callback ||
+ ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE ||
+ ctx->imsg->opcode == WSLAY_PING) {
+ struct wslay_event_on_msg_recv_arg arg;
+ uint16_t status_code = 0;
+ uint8_t *msg = NULL;
+ size_t msg_length = 0;
+ if(!wslay_event_config_get_no_buffering(ctx) ||
+ wslay_is_ctrl_frame(iocb.opcode)) {
+ msg = wslay_event_flatten_queue(ctx->imsg->chunks,
+ ctx->imsg->msg_length);
+ if(ctx->imsg->msg_length && !msg) {
+ ctx->read_enabled = 0;
+ return WSLAY_ERR_NOMEM;
+ }
+ msg_length = ctx->imsg->msg_length;
+ }
+ if(ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) {
+ const uint8_t *reason;
+ size_t reason_length;
+ if(ctx->imsg->msg_length >= 2) {
+ memcpy(&status_code, msg, 2);
+ status_code = ntohs(status_code);
+ if(!wslay_event_is_valid_status_code(status_code)) {
+ free(msg);
+ if((r = wslay_event_queue_close_wrapper
+ (ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) {
+ return r;
+ }
+ break;
+ }
+ reason = msg+2;
+ reason_length = ctx->imsg->msg_length-2;
+ } else {
+ reason = NULL;
+ reason_length = 0;
+ }
+ ctx->close_status |= WSLAY_CLOSE_RECEIVED;
+ ctx->status_code_recv =
+ status_code == 0 ? WSLAY_CODE_NO_STATUS_RCVD : status_code;
+ if((r = wslay_event_queue_close_wrapper
+ (ctx, status_code, reason, reason_length)) != 0) {
+ free(msg);
+ return r;
+ }
+ } else if(ctx->imsg->opcode == WSLAY_PING) {
+ struct wslay_event_msg arg;
+ arg.opcode = WSLAY_PONG;
+ arg.msg = msg;
+ arg.msg_length = ctx->imsg->msg_length;
+ if((r = wslay_event_queue_msg(ctx, &arg)) &&
+ r != WSLAY_ERR_NO_MORE_MSG) {
+ ctx->read_enabled = 0;
+ free(msg);
+ return r;
+ }
+ }
+ if(ctx->callbacks.on_msg_recv_callback) {
+ arg.rsv = ctx->imsg->rsv;
+ arg.opcode = ctx->imsg->opcode;
+ arg.msg = msg;
+ arg.msg_length = msg_length;
+ arg.status_code = status_code;
+ ctx->error = 0;
+ ctx->callbacks.on_msg_recv_callback(ctx, &arg, ctx->user_data);
+ }
+ free(msg);
+ }
+ wslay_event_imsg_reset(ctx->imsg);
+ if(ctx->imsg == &ctx->imsgs[1]) {
+ ctx->imsg = &ctx->imsgs[0];
+ }
+ }
+ ctx->ipayloadlen = ctx->ipayloadoff = 0;
+ }
+ } else {
+ if(r != WSLAY_ERR_WANT_READ ||
+ (ctx->error != WSLAY_ERR_WOULDBLOCK && ctx->error != 0)) {
+ if((r = wslay_event_queue_close_wrapper(ctx, 0, NULL, 0)) != 0) {
+ return r;
+ }
+ return WSLAY_ERR_CALLBACK_FAILURE;
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+static void wslay_event_on_non_fragmented_msg_popped
+(wslay_event_context_ptr ctx)
+{
+ ctx->omsg->fin = 1;
+ ctx->opayloadlen = ctx->omsg->data_length;
+ ctx->opayloadoff = 0;
+}
+
+static struct wslay_event_omsg* wslay_event_send_ctrl_queue_pop
+(wslay_event_context_ptr ctx)
+{
+ /*
+ * If Close control frame is queued, we don't send any control frame
+ * other than Close.
+ */
+ if(ctx->close_status & WSLAY_CLOSE_QUEUED) {
+ while(!wslay_queue_empty(ctx->send_ctrl_queue)) {
+ struct wslay_event_omsg *msg = wslay_queue_top(ctx->send_ctrl_queue);
+ wslay_queue_pop(ctx->send_ctrl_queue);
+ if(msg->opcode == WSLAY_CONNECTION_CLOSE) {
+ return msg;
+ } else {
+ wslay_event_omsg_free(msg);
+ }
+ }
+ return NULL;
+ } else {
+ struct wslay_event_omsg *msg = wslay_queue_top(ctx->send_ctrl_queue);
+ wslay_queue_pop(ctx->send_ctrl_queue);
+ return msg;
+ }
+}
+
+int wslay_event_send(wslay_event_context_ptr ctx)
+{
+ struct wslay_frame_iocb iocb;
+ ssize_t r;
+ while(ctx->write_enabled &&
+ (!wslay_queue_empty(ctx->send_queue) ||
+ !wslay_queue_empty(ctx->send_ctrl_queue) || ctx->omsg)) {
+ if(!ctx->omsg) {
+ if(wslay_queue_empty(ctx->send_ctrl_queue)) {
+ ctx->omsg = wslay_queue_top(ctx->send_queue);
+ wslay_queue_pop(ctx->send_queue);
+ } else {
+ ctx->omsg = wslay_event_send_ctrl_queue_pop(ctx);
+ if(ctx->omsg == NULL) {
+ break;
+ }
+ }
+ if(ctx->omsg->type == WSLAY_NON_FRAGMENTED) {
+ wslay_event_on_non_fragmented_msg_popped(ctx);
+ }
+ } else if(!wslay_is_ctrl_frame(ctx->omsg->opcode) &&
+ ctx->frame_ctx->ostate == PREP_HEADER &&
+ !wslay_queue_empty(ctx->send_ctrl_queue)) {
+ if((r = wslay_queue_push_front(ctx->send_queue, ctx->omsg)) != 0) {
+ ctx->write_enabled = 0;
+ return r;
+ }
+ ctx->omsg = wslay_event_send_ctrl_queue_pop(ctx);
+ if(ctx->omsg == NULL) {
+ break;
+ }
+ /* ctrl message has WSLAY_NON_FRAGMENTED */
+ wslay_event_on_non_fragmented_msg_popped(ctx);
+ }
+ if(ctx->omsg->type == WSLAY_NON_FRAGMENTED) {
+ memset(&iocb, 0, sizeof(iocb));
+ iocb.fin = 1;
+ iocb.opcode = ctx->omsg->opcode;
+ iocb.rsv = ctx->omsg->rsv;
+ iocb.mask = ctx->server^1;
+ iocb.data = ctx->omsg->data+ctx->opayloadoff;
+ iocb.data_length = ctx->opayloadlen-ctx->opayloadoff;
+ iocb.payload_length = ctx->opayloadlen;
+ r = wslay_frame_send(ctx->frame_ctx, &iocb);
+ if(r >= 0) {
+ ctx->opayloadoff += r;
+ if(ctx->opayloadoff == ctx->opayloadlen) {
+ --ctx->queued_msg_count;
+ ctx->queued_msg_length -= ctx->omsg->data_length;
+ if(ctx->omsg->opcode == WSLAY_CONNECTION_CLOSE) {
+ uint16_t status_code = 0;
+ ctx->write_enabled = 0;
+ ctx->close_status |= WSLAY_CLOSE_SENT;
+ if(ctx->omsg->data_length >= 2) {
+ memcpy(&status_code, ctx->omsg->data, 2);
+ status_code = ntohs(status_code);
+ }
+ ctx->status_code_sent =
+ status_code == 0 ? WSLAY_CODE_NO_STATUS_RCVD : status_code;
+ }
+ wslay_event_omsg_free(ctx->omsg);
+ ctx->omsg = NULL;
+ } else {
+ break;
+ }
+ } else {
+ if(r != WSLAY_ERR_WANT_WRITE ||
+ (ctx->error != WSLAY_ERR_WOULDBLOCK && ctx->error != 0)) {
+ ctx->write_enabled = 0;
+ return WSLAY_ERR_CALLBACK_FAILURE;
+ }
+ break;
+ }
+ } else {
+ if(ctx->omsg->fin == 0 && ctx->obuflimit == ctx->obufmark) {
+ int eof = 0;
+ r = ctx->omsg->read_callback(ctx, ctx->obuf, sizeof(ctx->obuf),
+ &ctx->omsg->source,
+ &eof, ctx->user_data);
+ if(r == 0) {
+ break;
+ } else if(r < 0) {
+ ctx->write_enabled = 0;
+ return WSLAY_ERR_CALLBACK_FAILURE;
+ }
+ ctx->obuflimit = ctx->obuf+r;
+ if(eof) {
+ ctx->omsg->fin = 1;
+ }
+ ctx->opayloadlen = r;
+ ctx->opayloadoff = 0;
+ }
+ memset(&iocb, 0, sizeof(iocb));
+ iocb.fin = ctx->omsg->fin;
+ iocb.opcode = ctx->omsg->opcode;
+ iocb.rsv = ctx->omsg->rsv;
+ iocb.mask = ctx->server ? 0 : 1;
+ iocb.data = ctx->obufmark;
+ iocb.data_length = ctx->obuflimit-ctx->obufmark;
+ iocb.payload_length = ctx->opayloadlen;
+ r = wslay_frame_send(ctx->frame_ctx, &iocb);
+ if(r >= 0) {
+ ctx->obufmark += r;
+ if(ctx->obufmark == ctx->obuflimit) {
+ ctx->obufmark = ctx->obuflimit = ctx->obuf;
+ if(ctx->omsg->fin) {
+ --ctx->queued_msg_count;
+ wslay_event_omsg_free(ctx->omsg);
+ ctx->omsg = NULL;
+ } else {
+ ctx->omsg->opcode = WSLAY_CONTINUATION_FRAME;
+ /* RSV1 is not set on continuation frames */
+ ctx->omsg->rsv = ctx->omsg->rsv & ~WSLAY_RSV1_BIT;
+ }
+ } else {
+ break;
+ }
+ } else {
+ if(r != WSLAY_ERR_WANT_WRITE ||
+ (ctx->error != WSLAY_ERR_WOULDBLOCK &&
+ ctx->error != 0)) {
+ ctx->write_enabled = 0;
+ return WSLAY_ERR_CALLBACK_FAILURE;
+ }
+ break;
+ }
+ }
+ }
+ return 0;
+}
+
+void wslay_event_set_error(wslay_event_context_ptr ctx, int val)
+{
+ ctx->error = val;
+}
+
+int wslay_event_want_read(wslay_event_context_ptr ctx)
+{
+ return ctx->read_enabled;
+}
+
+int wslay_event_want_write(wslay_event_context_ptr ctx)
+{
+ return ctx->write_enabled &&
+ (!wslay_queue_empty(ctx->send_queue) ||
+ !wslay_queue_empty(ctx->send_ctrl_queue) || ctx->omsg);
+}
+
+void wslay_event_shutdown_read(wslay_event_context_ptr ctx)
+{
+ ctx->read_enabled = 0;
+}
+
+void wslay_event_shutdown_write(wslay_event_context_ptr ctx)
+{
+ ctx->write_enabled = 0;
+}
+
+int wslay_event_get_read_enabled(wslay_event_context_ptr ctx)
+{
+ return ctx->read_enabled;
+}
+
+int wslay_event_get_write_enabled(wslay_event_context_ptr ctx)
+{
+ return ctx->write_enabled;
+}
+
+int wslay_event_get_close_received(wslay_event_context_ptr ctx)
+{
+ return (ctx->close_status & WSLAY_CLOSE_RECEIVED) > 0;
+}
+
+int wslay_event_get_close_sent(wslay_event_context_ptr ctx)
+{
+ return (ctx->close_status & WSLAY_CLOSE_SENT) > 0;
+}
+
+void wslay_event_config_set_allowed_rsv_bits(wslay_event_context_ptr ctx,
+ uint8_t rsv)
+{
+ /* We currently only allow WSLAY_RSV1_BIT or WSLAY_RSV_NONE */
+ ctx->allowed_rsv_bits = rsv & WSLAY_RSV1_BIT;
+}
+
+void wslay_event_config_set_no_buffering(wslay_event_context_ptr ctx, int val)
+{
+ if(val) {
+ ctx->config |= WSLAY_CONFIG_NO_BUFFERING;
+ } else {
+ ctx->config &= ~WSLAY_CONFIG_NO_BUFFERING;
+ }
+}
+
+void wslay_event_config_set_max_recv_msg_length(wslay_event_context_ptr ctx,
+ uint64_t val)
+{
+ ctx->max_recv_msg_length = val;
+}
+
+uint16_t wslay_event_get_status_code_received(wslay_event_context_ptr ctx)
+{
+ return ctx->status_code_recv;
+}
+
+uint16_t wslay_event_get_status_code_sent(wslay_event_context_ptr ctx)
+{
+ return ctx->status_code_sent;
+}
+
+size_t wslay_event_get_queued_msg_count(wslay_event_context_ptr ctx)
+{
+ return ctx->queued_msg_count;
+}
+
+size_t wslay_event_get_queued_msg_length(wslay_event_context_ptr ctx)
+{
+ return ctx->queued_msg_length;
+}
diff --git a/thirdparty/wslay/wslay_event.h b/thirdparty/wslay/wslay_event.h
new file mode 100644
index 0000000000..36feb9036d
--- /dev/null
+++ b/thirdparty/wslay/wslay_event.h
@@ -0,0 +1,142 @@
+/*
+ * Wslay - The WebSocket Library
+ *
+ * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef WSLAY_EVENT_H
+#define WSLAY_EVENT_H
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <wslay/wslay.h>
+
+struct wslay_stack;
+struct wslay_queue;
+
+struct wslay_event_byte_chunk {
+ uint8_t *data;
+ size_t data_length;
+};
+
+struct wslay_event_imsg {
+ uint8_t fin;
+ uint8_t rsv;
+ uint8_t opcode;
+ uint32_t utf8state;
+ struct wslay_queue *chunks;
+ size_t msg_length;
+};
+
+enum wslay_event_msg_type {
+ WSLAY_NON_FRAGMENTED,
+ WSLAY_FRAGMENTED
+};
+
+struct wslay_event_omsg {
+ uint8_t fin;
+ uint8_t opcode;
+ uint8_t rsv;
+ enum wslay_event_msg_type type;
+
+ uint8_t *data;
+ size_t data_length;
+
+ union wslay_event_msg_source source;
+ wslay_event_fragmented_msg_callback read_callback;
+};
+
+struct wslay_event_frame_user_data {
+ wslay_event_context_ptr ctx;
+ void *user_data;
+};
+
+enum wslay_event_close_status {
+ WSLAY_CLOSE_RECEIVED = 1 << 0,
+ WSLAY_CLOSE_QUEUED = 1 << 1,
+ WSLAY_CLOSE_SENT = 1 << 2
+};
+
+enum wslay_event_config {
+ WSLAY_CONFIG_NO_BUFFERING = 1 << 0
+};
+
+struct wslay_event_context {
+ /* config status, bitwise OR of enum wslay_event_config values*/
+ uint32_t config;
+ /* maximum message length that can be received */
+ uint64_t max_recv_msg_length;
+ /* 1 if initialized for server, otherwise 0 */
+ uint8_t server;
+ /* bitwise OR of enum wslay_event_close_status values */
+ uint8_t close_status;
+ /* status code in received close control frame */
+ uint16_t status_code_recv;
+ /* status code in sent close control frame */
+ uint16_t status_code_sent;
+ wslay_frame_context_ptr frame_ctx;
+ /* 1 if reading is enabled, otherwise 0. Upon receiving close
+ control frame this value set to 0. If any errors in read
+ operation will also set this value to 0. */
+ uint8_t read_enabled;
+ /* 1 if writing is enabled, otherwise 0 Upon completing sending
+ close control frame, this value set to 0. If any errors in write
+ opration will also set this value to 0. */
+ uint8_t write_enabled;
+ /* imsg buffer to allow interleaved control frame between
+ non-control frames. */
+ struct wslay_event_imsg imsgs[2];
+ /* Pointer to imsgs to indicate current used buffer. */
+ struct wslay_event_imsg *imsg;
+ /* payload length of frame currently being received. */
+ uint64_t ipayloadlen;
+ /* next byte offset of payload currently being received. */
+ uint64_t ipayloadoff;
+ /* error value set by user callback */
+ int error;
+ /* Pointer to the message currently being sent. NULL if no message
+ is currently sent. */
+ struct wslay_event_omsg *omsg;
+ /* Queue for non-control frames */
+ struct wslay_queue/*<wslay_omsg*>*/ *send_queue;
+ /* Queue for control frames */
+ struct wslay_queue/*<wslay_omsg*>*/ *send_ctrl_queue;
+ /* Size of send_queue + size of send_ctrl_queue */
+ size_t queued_msg_count;
+ /* The sum of message length in send_queue */
+ size_t queued_msg_length;
+ /* Buffer used for fragmented messages */
+ uint8_t obuf[4096];
+ uint8_t *obuflimit;
+ uint8_t *obufmark;
+ /* payload length of frame currently being sent. */
+ uint64_t opayloadlen;
+ /* next byte offset of payload currently being sent. */
+ uint64_t opayloadoff;
+ struct wslay_event_callbacks callbacks;
+ struct wslay_event_frame_user_data frame_user_data;
+ void *user_data;
+ uint8_t allowed_rsv_bits;
+};
+
+#endif /* WSLAY_EVENT_H */
diff --git a/thirdparty/wslay/wslay_frame.c b/thirdparty/wslay/wslay_frame.c
new file mode 100644
index 0000000000..445e750ca5
--- /dev/null
+++ b/thirdparty/wslay/wslay_frame.c
@@ -0,0 +1,340 @@
+/*
+ * Wslay - The WebSocket Library
+ *
+ * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "wslay_frame.h"
+
+#include <stddef.h>
+#include <string.h>
+#include <assert.h>
+
+#include "wslay_net.h"
+
+#define wslay_min(A, B) (((A) < (B)) ? (A) : (B))
+
+int wslay_frame_context_init(wslay_frame_context_ptr *ctx,
+ const struct wslay_frame_callbacks *callbacks,
+ void *user_data)
+{
+ *ctx = (wslay_frame_context_ptr)malloc(sizeof(struct wslay_frame_context));
+ if(*ctx == NULL) {
+ return -1;
+ }
+ memset(*ctx, 0, sizeof(struct wslay_frame_context));
+ (*ctx)->istate = RECV_HEADER1;
+ (*ctx)->ireqread = 2;
+ (*ctx)->ostate = PREP_HEADER;
+ (*ctx)->user_data = user_data;
+ (*ctx)->ibufmark = (*ctx)->ibuflimit = (*ctx)->ibuf;
+ (*ctx)->callbacks = *callbacks;
+ return 0;
+}
+
+void wslay_frame_context_free(wslay_frame_context_ptr ctx)
+{
+ free(ctx);
+}
+
+ssize_t wslay_frame_send(wslay_frame_context_ptr ctx,
+ struct wslay_frame_iocb *iocb)
+{
+ if(iocb->data_length > iocb->payload_length) {
+ return WSLAY_ERR_INVALID_ARGUMENT;
+ }
+ if(ctx->ostate == PREP_HEADER) {
+ uint8_t *hdptr = ctx->oheader;
+ memset(ctx->oheader, 0, sizeof(ctx->oheader));
+ *hdptr |= (iocb->fin << 7) & 0x80u;
+ *hdptr |= (iocb->rsv << 4) & 0x70u;
+ *hdptr |= iocb->opcode & 0xfu;
+ ++hdptr;
+ *hdptr |= (iocb->mask << 7) & 0x80u;
+ if(wslay_is_ctrl_frame(iocb->opcode) && iocb->payload_length > 125) {
+ return WSLAY_ERR_INVALID_ARGUMENT;
+ }
+ if(iocb->payload_length < 126) {
+ *hdptr |= iocb->payload_length;
+ ++hdptr;
+ } else if(iocb->payload_length < (1 << 16)) {
+ uint16_t len = htons(iocb->payload_length);
+ *hdptr |= 126;
+ ++hdptr;
+ memcpy(hdptr, &len, 2);
+ hdptr += 2;
+ } else if(iocb->payload_length < (1ull << 63)) {
+ uint64_t len = hton64(iocb->payload_length);
+ *hdptr |= 127;
+ ++hdptr;
+ memcpy(hdptr, &len, 8);
+ hdptr += 8;
+ } else {
+ /* Too large payload length */
+ return WSLAY_ERR_INVALID_ARGUMENT;
+ }
+ if(iocb->mask) {
+ if(ctx->callbacks.genmask_callback(ctx->omaskkey, 4,
+ ctx->user_data) != 0) {
+ return WSLAY_ERR_INVALID_CALLBACK;
+ } else {
+ ctx->omask = 1;
+ memcpy(hdptr, ctx->omaskkey, 4);
+ hdptr += 4;
+ }
+ }
+ ctx->ostate = SEND_HEADER;
+ ctx->oheadermark = ctx->oheader;
+ ctx->oheaderlimit = hdptr;
+ ctx->opayloadlen = iocb->payload_length;
+ ctx->opayloadoff = 0;
+ }
+ if(ctx->ostate == SEND_HEADER) {
+ ptrdiff_t len = ctx->oheaderlimit-ctx->oheadermark;
+ ssize_t r;
+ int flags = 0;
+ if(iocb->data_length > 0) {
+ flags |= WSLAY_MSG_MORE;
+ };
+ r = ctx->callbacks.send_callback(ctx->oheadermark, len, flags,
+ ctx->user_data);
+ if(r > 0) {
+ if(r > len) {
+ return WSLAY_ERR_INVALID_CALLBACK;
+ } else {
+ ctx->oheadermark += r;
+ if(ctx->oheadermark == ctx->oheaderlimit) {
+ ctx->ostate = SEND_PAYLOAD;
+ } else {
+ return WSLAY_ERR_WANT_WRITE;
+ }
+ }
+ } else {
+ return WSLAY_ERR_WANT_WRITE;
+ }
+ }
+ if(ctx->ostate == SEND_PAYLOAD) {
+ size_t totallen = 0;
+ if(iocb->data_length > 0) {
+ if(ctx->omask) {
+ uint8_t temp[4096];
+ const uint8_t *datamark = iocb->data,
+ *datalimit = iocb->data+iocb->data_length;
+ while(datamark < datalimit) {
+ size_t datalen = datalimit - datamark;
+ const uint8_t *writelimit = datamark+
+ wslay_min(sizeof(temp), datalen);
+ size_t writelen = writelimit-datamark;
+ ssize_t r;
+ size_t i;
+ for(i = 0; i < writelen; ++i) {
+ temp[i] = datamark[i]^ctx->omaskkey[(ctx->opayloadoff+i)%4];
+ }
+ r = ctx->callbacks.send_callback(temp, writelen, 0, ctx->user_data);
+ if(r > 0) {
+ if((size_t)r > writelen) {
+ return WSLAY_ERR_INVALID_CALLBACK;
+ } else {
+ datamark += r;
+ ctx->opayloadoff += r;
+ totallen += r;
+ }
+ } else {
+ if(totallen > 0) {
+ break;
+ } else {
+ return WSLAY_ERR_WANT_WRITE;
+ }
+ }
+ }
+ } else {
+ ssize_t r;
+ r = ctx->callbacks.send_callback(iocb->data, iocb->data_length, 0,
+ ctx->user_data);
+ if(r > 0) {
+ if((size_t)r > iocb->data_length) {
+ return WSLAY_ERR_INVALID_CALLBACK;
+ } else {
+ ctx->opayloadoff += r;
+ totallen = r;
+ }
+ } else {
+ return WSLAY_ERR_WANT_WRITE;
+ }
+ }
+ }
+ if(ctx->opayloadoff == ctx->opayloadlen) {
+ ctx->ostate = PREP_HEADER;
+ }
+ return totallen;
+ }
+ return WSLAY_ERR_INVALID_ARGUMENT;
+}
+
+static void wslay_shift_ibuf(wslay_frame_context_ptr ctx)
+{
+ ptrdiff_t len = ctx->ibuflimit-ctx->ibufmark;
+ memmove(ctx->ibuf, ctx->ibufmark, len);
+ ctx->ibuflimit = ctx->ibuf+len;
+ ctx->ibufmark = ctx->ibuf;
+}
+
+static ssize_t wslay_recv(wslay_frame_context_ptr ctx)
+{
+ ssize_t r;
+ if(ctx->ibufmark != ctx->ibuf) {
+ wslay_shift_ibuf(ctx);
+ }
+ r = ctx->callbacks.recv_callback
+ (ctx->ibuflimit, ctx->ibuf+sizeof(ctx->ibuf)-ctx->ibuflimit,
+ 0, ctx->user_data);
+ if(r > 0) {
+ ctx->ibuflimit += r;
+ } else {
+ r = WSLAY_ERR_WANT_READ;
+ }
+ return r;
+}
+
+#define WSLAY_AVAIL_IBUF(ctx) ((size_t)(ctx->ibuflimit - ctx->ibufmark))
+
+ssize_t wslay_frame_recv(wslay_frame_context_ptr ctx,
+ struct wslay_frame_iocb *iocb)
+{
+ ssize_t r;
+ if(ctx->istate == RECV_HEADER1) {
+ uint8_t fin, opcode, rsv, payloadlen;
+ if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) {
+ if((r = wslay_recv(ctx)) <= 0) {
+ return r;
+ }
+ }
+ if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) {
+ return WSLAY_ERR_WANT_READ;
+ }
+ fin = (ctx->ibufmark[0] >> 7) & 1;
+ rsv = (ctx->ibufmark[0] >> 4) & 7;
+ opcode = ctx->ibufmark[0] & 0xfu;
+ ctx->iom.opcode = opcode;
+ ctx->iom.fin = fin;
+ ctx->iom.rsv = rsv;
+ ++ctx->ibufmark;
+ ctx->imask = (ctx->ibufmark[0] >> 7) & 1;
+ payloadlen = ctx->ibufmark[0] & 0x7fu;
+ ++ctx->ibufmark;
+ if(wslay_is_ctrl_frame(opcode) && (payloadlen > 125 || !fin)) {
+ return WSLAY_ERR_PROTO;
+ }
+ if(payloadlen == 126) {
+ ctx->istate = RECV_EXT_PAYLOADLEN;
+ ctx->ireqread = 2;
+ } else if(payloadlen == 127) {
+ ctx->istate = RECV_EXT_PAYLOADLEN;
+ ctx->ireqread = 8;
+ } else {
+ ctx->ipayloadlen = payloadlen;
+ ctx->ipayloadoff = 0;
+ if(ctx->imask) {
+ ctx->istate = RECV_MASKKEY;
+ ctx->ireqread = 4;
+ } else {
+ ctx->istate = RECV_PAYLOAD;
+ }
+ }
+ }
+ if(ctx->istate == RECV_EXT_PAYLOADLEN) {
+ if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) {
+ if((r = wslay_recv(ctx)) <= 0) {
+ return r;
+ }
+ if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) {
+ return WSLAY_ERR_WANT_READ;
+ }
+ }
+ ctx->ipayloadlen = 0;
+ ctx->ipayloadoff = 0;
+ memcpy((uint8_t*)&ctx->ipayloadlen+(8-ctx->ireqread),
+ ctx->ibufmark, ctx->ireqread);
+ ctx->ipayloadlen = ntoh64(ctx->ipayloadlen);
+ ctx->ibufmark += ctx->ireqread;
+ if(ctx->ireqread == 8) {
+ if(ctx->ipayloadlen < (1 << 16) ||
+ ctx->ipayloadlen & (1ull << 63)) {
+ return WSLAY_ERR_PROTO;
+ }
+ } else if(ctx->ipayloadlen < 126) {
+ return WSLAY_ERR_PROTO;
+ }
+ if(ctx->imask) {
+ ctx->istate = RECV_MASKKEY;
+ ctx->ireqread = 4;
+ } else {
+ ctx->istate = RECV_PAYLOAD;
+ }
+ }
+ if(ctx->istate == RECV_MASKKEY) {
+ if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) {
+ if((r = wslay_recv(ctx)) <= 0) {
+ return r;
+ }
+ if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) {
+ return WSLAY_ERR_WANT_READ;
+ }
+ }
+ memcpy(ctx->imaskkey, ctx->ibufmark, 4);
+ ctx->ibufmark += 4;
+ ctx->istate = RECV_PAYLOAD;
+ }
+ if(ctx->istate == RECV_PAYLOAD) {
+ uint8_t *readlimit, *readmark;
+ uint64_t rempayloadlen = ctx->ipayloadlen-ctx->ipayloadoff;
+ if(WSLAY_AVAIL_IBUF(ctx) == 0 && rempayloadlen > 0) {
+ if((r = wslay_recv(ctx)) <= 0) {
+ return r;
+ }
+ }
+ readmark = ctx->ibufmark;
+ readlimit = WSLAY_AVAIL_IBUF(ctx) < rempayloadlen ?
+ ctx->ibuflimit : ctx->ibufmark+rempayloadlen;
+ if(ctx->imask) {
+ for(; ctx->ibufmark != readlimit;
+ ++ctx->ibufmark, ++ctx->ipayloadoff) {
+ ctx->ibufmark[0] ^= ctx->imaskkey[ctx->ipayloadoff % 4];
+ }
+ } else {
+ ctx->ibufmark = readlimit;
+ ctx->ipayloadoff += readlimit-readmark;
+ }
+ iocb->fin = ctx->iom.fin;
+ iocb->rsv = ctx->iom.rsv;
+ iocb->opcode = ctx->iom.opcode;
+ iocb->payload_length = ctx->ipayloadlen;
+ iocb->mask = ctx->imask;
+ iocb->data = readmark;
+ iocb->data_length = ctx->ibufmark-readmark;
+ if(ctx->ipayloadlen == ctx->ipayloadoff) {
+ ctx->istate = RECV_HEADER1;
+ ctx->ireqread = 2;
+ }
+ return iocb->data_length;
+ }
+ return WSLAY_ERR_INVALID_ARGUMENT;
+}
diff --git a/thirdparty/wslay/wslay_frame.h b/thirdparty/wslay/wslay_frame.h
new file mode 100644
index 0000000000..6a75858cc7
--- /dev/null
+++ b/thirdparty/wslay/wslay_frame.h
@@ -0,0 +1,76 @@
+/*
+ * Wslay - The WebSocket Library
+ *
+ * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef WSLAY_FRAME_H
+#define WSLAY_FRAME_H
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <wslay/wslay.h>
+
+enum wslay_frame_state {
+ PREP_HEADER,
+ SEND_HEADER,
+ SEND_PAYLOAD,
+ RECV_HEADER1,
+ RECV_PAYLOADLEN,
+ RECV_EXT_PAYLOADLEN,
+ RECV_MASKKEY,
+ RECV_PAYLOAD
+};
+
+struct wslay_frame_opcode_memo {
+ uint8_t fin;
+ uint8_t opcode;
+ uint8_t rsv;
+};
+
+struct wslay_frame_context {
+ uint8_t ibuf[4096];
+ uint8_t *ibufmark;
+ uint8_t *ibuflimit;
+ struct wslay_frame_opcode_memo iom;
+ uint64_t ipayloadlen;
+ uint64_t ipayloadoff;
+ uint8_t imask;
+ uint8_t imaskkey[4];
+ enum wslay_frame_state istate;
+ size_t ireqread;
+
+ uint8_t oheader[14];
+ uint8_t *oheadermark;
+ uint8_t *oheaderlimit;
+ uint64_t opayloadlen;
+ uint64_t opayloadoff;
+ uint8_t omask;
+ uint8_t omaskkey[4];
+ enum wslay_frame_state ostate;
+
+ struct wslay_frame_callbacks callbacks;
+ void *user_data;
+};
+
+#endif /* WSLAY_FRAME_H */
diff --git a/thirdparty/wslay/wslay_net.c b/thirdparty/wslay/wslay_net.c
new file mode 100644
index 0000000000..d3867c21fb
--- /dev/null
+++ b/thirdparty/wslay/wslay_net.c
@@ -0,0 +1,36 @@
+/*
+ * Wslay - The WebSocket Library
+ *
+ * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "wslay_net.h"
+
+#ifndef WORDS_BIGENDIAN
+
+uint64_t wslay_byteswap64(uint64_t x)
+{
+ uint64_t u = ntohl(x & 0xffffffffllu);
+ uint64_t l = ntohl(x >> 32);
+ return (u << 32) | l;
+}
+
+#endif /* !WORDS_BIGENDIAN */
diff --git a/thirdparty/wslay/wslay_net.h b/thirdparty/wslay/wslay_net.h
new file mode 100644
index 0000000000..2310870156
--- /dev/null
+++ b/thirdparty/wslay/wslay_net.h
@@ -0,0 +1,54 @@
+/*
+ * Wslay - The WebSocket Library
+ *
+ * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef WSLAY_NET_H
+#define WSLAY_NET_H
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <wslay/wslay.h>
+
+#ifdef HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif /* HAVE_ARPA_INET_H */
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif /* HAVE_NETINET_IN_H */
+/* For Mingw build */
+#ifdef HAVE_WINSOCK2_H
+# include <winsock2.h>
+#endif /* HAVE_WINSOCK2_H */
+
+#ifdef WORDS_BIGENDIAN
+# define ntoh64(x) (x)
+# define hton64(x) (x)
+#else /* !WORDS_BIGENDIAN */
+uint64_t wslay_byteswap64(uint64_t x);
+# define ntoh64(x) wslay_byteswap64(x)
+# define hton64(x) wslay_byteswap64(x)
+#endif /* !WORDS_BIGENDIAN */
+
+#endif /* WSLAY_NET_H */
diff --git a/thirdparty/wslay/wslay_queue.c b/thirdparty/wslay/wslay_queue.c
new file mode 100644
index 0000000000..8d2669687d
--- /dev/null
+++ b/thirdparty/wslay/wslay_queue.c
@@ -0,0 +1,117 @@
+/*
+ * Wslay - The WebSocket Library
+ *
+ * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "wslay_queue.h"
+
+#include <string.h>
+#include <assert.h>
+
+struct wslay_queue* wslay_queue_new(void)
+{
+ struct wslay_queue *queue = (struct wslay_queue*)malloc
+ (sizeof(struct wslay_queue));
+ if(!queue) {
+ return NULL;
+ }
+ queue->top = queue->tail = NULL;
+ return queue;
+}
+
+void wslay_queue_free(struct wslay_queue *queue)
+{
+ if(!queue) {
+ return;
+ } else {
+ struct wslay_queue_cell *p = queue->top;
+ while(p) {
+ struct wslay_queue_cell *next = p->next;
+ free(p);
+ p = next;
+ }
+ free(queue);
+ }
+}
+
+int wslay_queue_push(struct wslay_queue *queue, void *data)
+{
+ struct wslay_queue_cell *new_cell = (struct wslay_queue_cell*)malloc
+ (sizeof(struct wslay_queue_cell));
+ if(!new_cell) {
+ return WSLAY_ERR_NOMEM;
+ }
+ new_cell->data = data;
+ new_cell->next = NULL;
+ if(queue->tail) {
+ queue->tail->next = new_cell;
+ queue->tail = new_cell;
+
+ } else {
+ queue->top = queue->tail = new_cell;
+ }
+ return 0;
+}
+
+int wslay_queue_push_front(struct wslay_queue *queue, void *data)
+{
+ struct wslay_queue_cell *new_cell = (struct wslay_queue_cell*)malloc
+ (sizeof(struct wslay_queue_cell));
+ if(!new_cell) {
+ return WSLAY_ERR_NOMEM;
+ }
+ new_cell->data = data;
+ new_cell->next = queue->top;
+ queue->top = new_cell;
+ if(!queue->tail) {
+ queue->tail = queue->top;
+ }
+ return 0;
+}
+
+void wslay_queue_pop(struct wslay_queue *queue)
+{
+ struct wslay_queue_cell *top = queue->top;
+ assert(top);
+ queue->top = top->next;
+ if(top == queue->tail) {
+ queue->tail = NULL;
+ }
+ free(top);
+}
+
+void* wslay_queue_top(struct wslay_queue *queue)
+{
+ assert(queue->top);
+ return queue->top->data;
+}
+
+void* wslay_queue_tail(struct wslay_queue *queue)
+{
+ assert(queue->tail);
+ return queue->tail->data;
+}
+
+int wslay_queue_empty(struct wslay_queue *queue)
+{
+ return queue->top == NULL;
+}
diff --git a/thirdparty/wslay/wslay_queue.h b/thirdparty/wslay/wslay_queue.h
new file mode 100644
index 0000000000..55e78a042e
--- /dev/null
+++ b/thirdparty/wslay/wslay_queue.h
@@ -0,0 +1,53 @@
+/*
+ * Wslay - The WebSocket Library
+ *
+ * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef WSLAY_QUEUE_H
+#define WSLAY_QUEUE_H
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include <wslay/wslay.h>
+
+struct wslay_queue_cell {
+ void *data;
+ struct wslay_queue_cell *next;
+};
+
+struct wslay_queue {
+ struct wslay_queue_cell *top;
+ struct wslay_queue_cell *tail;
+};
+
+struct wslay_queue* wslay_queue_new(void);
+void wslay_queue_free(struct wslay_queue *queue);
+int wslay_queue_push(struct wslay_queue *queue, void *data);
+int wslay_queue_push_front(struct wslay_queue *queue, void *data);
+void wslay_queue_pop(struct wslay_queue *queue);
+void* wslay_queue_top(struct wslay_queue *queue);
+void* wslay_queue_tail(struct wslay_queue *queue);
+int wslay_queue_empty(struct wslay_queue *queue);
+
+#endif /* WSLAY_QUEUE_H */
diff --git a/thirdparty/wslay/wslay_stack.c b/thirdparty/wslay/wslay_stack.c
new file mode 100644
index 0000000000..0e05d74031
--- /dev/null
+++ b/thirdparty/wslay/wslay_stack.c
@@ -0,0 +1,86 @@
+/*
+ * Wslay - The WebSocket Library
+ *
+ * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "wslay_stack.h"
+
+#include <string.h>
+#include <assert.h>
+
+struct wslay_stack* wslay_stack_new()
+{
+ struct wslay_stack *stack = (struct wslay_stack*)malloc
+ (sizeof(struct wslay_stack));
+ if(!stack) {
+ return NULL;
+ }
+ stack->top = NULL;
+ return stack;
+}
+
+void wslay_stack_free(struct wslay_stack *stack)
+{
+ struct wslay_stack_cell *p;
+ if(!stack) {
+ return;
+ }
+ p = stack->top;
+ while(p) {
+ struct wslay_stack_cell *next = p->next;
+ free(p);
+ p = next;
+ }
+ free(stack);
+}
+
+int wslay_stack_push(struct wslay_stack *stack, void *data)
+{
+ struct wslay_stack_cell *new_cell = (struct wslay_stack_cell*)malloc
+ (sizeof(struct wslay_stack_cell));
+ if(!new_cell) {
+ return WSLAY_ERR_NOMEM;
+ }
+ new_cell->data = data;
+ new_cell->next = stack->top;
+ stack->top = new_cell;
+ return 0;
+}
+
+void wslay_stack_pop(struct wslay_stack *stack)
+{
+ struct wslay_stack_cell *top = stack->top;
+ assert(top);
+ stack->top = top->next;
+ free(top);
+}
+
+void* wslay_stack_top(struct wslay_stack *stack)
+{
+ assert(stack->top);
+ return stack->top->data;
+}
+
+int wslay_stack_empty(struct wslay_stack *stack)
+{
+ return stack->top == NULL;
+}
diff --git a/thirdparty/wslay/wslay_stack.h b/thirdparty/wslay/wslay_stack.h
new file mode 100644
index 0000000000..16e4e968eb
--- /dev/null
+++ b/thirdparty/wslay/wslay_stack.h
@@ -0,0 +1,50 @@
+/*
+ * Wslay - The WebSocket Library
+ *
+ * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef WSLAY_STACK_H
+#define WSLAY_STACK_H
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include <wslay/wslay.h>
+
+struct wslay_stack_cell {
+ void *data;
+ struct wslay_stack_cell *next;
+};
+
+struct wslay_stack {
+ struct wslay_stack_cell *top;
+};
+
+struct wslay_stack* wslay_stack_new();
+void wslay_stack_free(struct wslay_stack *stack);
+int wslay_stack_push(struct wslay_stack *stack, void *data);
+void wslay_stack_pop(struct wslay_stack *stack);
+void* wslay_stack_top(struct wslay_stack *stack);
+int wslay_stack_empty(struct wslay_stack *stack);
+
+#endif /* WSLAY_STACK_H */