mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-25 10:01:30 +00:00
Changed websockets lib, protocol not finalized at all
This commit is contained in:
parent
4109b0b88d
commit
e0bc0e2e5c
@ -320,7 +320,7 @@ IF(EQEMU_BUILD_LUA)
|
||||
ENDIF(EQEMU_SANITIZE_LUA_LIBS)
|
||||
ENDIF(EQEMU_BUILD_LUA)
|
||||
|
||||
INCLUDE_DIRECTORIES("${ZLIB_INCLUDE_DIRS}" "${MySQL_INCLUDE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/common/glm/glm")
|
||||
INCLUDE_DIRECTORIES("${ZLIB_INCLUDE_DIRS}" "${MySQL_INCLUDE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/common/glm/glm" "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libwebsockets")
|
||||
|
||||
IF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS)
|
||||
ADD_SUBDIRECTORY(common)
|
||||
|
||||
3
dependencies/.gitignore
vendored
3
dependencies/.gitignore
vendored
@ -5,4 +5,5 @@ mysql_x86/
|
||||
mysql_x64/
|
||||
zlib_x86/
|
||||
zlib_x64/
|
||||
cyassl/
|
||||
cyassl/
|
||||
websocketpp/
|
||||
1
dependencies/CMakeLists.txt
vendored
1
dependencies/CMakeLists.txt
vendored
@ -4,3 +4,4 @@ IF(EQEMU_BUILD_LUA)
|
||||
ADD_SUBDIRECTORY(luabind)
|
||||
ENDIF(EQEMU_BUILD_LUA)
|
||||
|
||||
ADD_SUBDIRECTORY(libwebsockets)
|
||||
38
dependencies/libwebsockets/.gitignore
vendored
Normal file
38
dependencies/libwebsockets/.gitignore
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
#Ignore build files
|
||||
Makefile
|
||||
config.h
|
||||
config.log
|
||||
config.status
|
||||
libtool
|
||||
stamp-h1
|
||||
output/
|
||||
win32port/ipch/
|
||||
win32port/Debug*/
|
||||
win32port/Release*/
|
||||
win32port/server/Debug*/
|
||||
win32port/server/Release*/
|
||||
win32port/client/Debug*/
|
||||
win32port/client/Release*/
|
||||
win32port/libwebsocketswin32/Debug*/
|
||||
win32port/libwebsocketswin32/Release*/
|
||||
win32port/zlib/Debug*/
|
||||
win32port/zlib/Release*/
|
||||
*.vcxproj.user
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.suo
|
||||
*.su
|
||||
*.m4
|
||||
missing
|
||||
depcomp
|
||||
install-sh
|
||||
configure
|
||||
compile
|
||||
config.guess
|
||||
*~
|
||||
*.orig
|
||||
autom4te.cache/
|
||||
ltmain.sh
|
||||
config.sub
|
||||
ar-lib
|
||||
libwebsockets.pc
|
||||
29
dependencies/libwebsockets/Android.mk
vendored
Normal file
29
dependencies/libwebsockets/Android.mk
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
# example Android Native Library makefile
|
||||
# contributed by Gregory Junker <ggjunker@gmail.com>
|
||||
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := libwebsockets
|
||||
LOCAL_CFLAGS := -DLWS_BUILTIN_GETIFADDRS
|
||||
LWS_LIB_PATH := ../../../shared/libwebsockets/lib
|
||||
LOCAL_C_INCLUDES:= $(LOCAL_PATH)/$(LWS_LIB_PATH)
|
||||
LOCAL_SRC_FILES := \
|
||||
$(LWS_LIB_PATH)/base64-decode.c \
|
||||
$(LWS_LIB_PATH)/client.c \
|
||||
$(LWS_LIB_PATH)/client-handshake.c \
|
||||
$(LWS_LIB_PATH)/client-parser.c \
|
||||
$(LWS_LIB_PATH)/daemonize.c \
|
||||
$(LWS_LIB_PATH)/extension.c \
|
||||
$(LWS_LIB_PATH)/extension-deflate-frame.c \
|
||||
$(LWS_LIB_PATH)/extension-deflate-stream.c \
|
||||
$(LWS_LIB_PATH)/getifaddrs.c \
|
||||
$(LWS_LIB_PATH)/handshake.c \
|
||||
$(LWS_LIB_PATH)/libwebsockets.c \
|
||||
$(LWS_LIB_PATH)/md5.c \
|
||||
$(LWS_LIB_PATH)/output.c \
|
||||
$(LWS_LIB_PATH)/parsers.c \
|
||||
$(LWS_LIB_PATH)/sha-1.c
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
914
dependencies/libwebsockets/CMakeLists.txt
vendored
Normal file
914
dependencies/libwebsockets/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,914 @@
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
project(libwebsockets)
|
||||
|
||||
set(PACKAGE "libwebsockets")
|
||||
set(CPACK_PACKAGE_NAME "${PACKAGE}")
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR "1")
|
||||
set(CPACK_PACKAGE_VERSION_MINOR "3")
|
||||
set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}")
|
||||
set(CPACK_PACKAGE_VENDOR "andy@warmcat.com")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PACKAGE} ${PACKAGE_VERSION}")
|
||||
set(SOVERSION "4.0.0")
|
||||
set(CPACK_SOURCE_GENERATOR "TGZ")
|
||||
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
|
||||
set(VERSION "${CPACK_PACKAGE_VERSION}")
|
||||
|
||||
set(LWS_LIBRARY_VERSION ${CPACK_PACKAGE_VERSION})
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/")
|
||||
|
||||
message(STATUS "CMAKE_TOOLCHAIN_FILE='${CMAKE_TOOLCHAIN_FILE}'")
|
||||
|
||||
# Try to find the current Git hash.
|
||||
find_package(Git)
|
||||
if(GIT_EXECUTABLE)
|
||||
execute_process(
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
COMMAND "${GIT_EXECUTABLE}" log -n 1 --pretty=%h
|
||||
OUTPUT_VARIABLE GIT_HASH
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
set(LWS_BUILD_HASH ${GIT_HASH})
|
||||
message("Git commit hash: ${LWS_BUILD_HASH}")
|
||||
endif()
|
||||
|
||||
option(LWS_WITH_SSL "Include SSL support (default OpenSSL, CyaSSL if LWS_USE_CYASSL is set)" OFF)
|
||||
option(LWS_SSL_CLIENT_USE_OS_CA_CERTS "SSL support should make use of OS installed CA root certs" ON)
|
||||
option(LWS_USE_EXTERNAL_ZLIB "Search the system for ZLib instead of using the included one (on Windows)" OFF)
|
||||
option(LWS_USE_CYASSL "Use CyaSSL replacement for OpenSSL. When settings this, you also need to specify LWS_CYASSL_LIB and LWS_CYASSL_INCLUDE_DIRS" OFF)
|
||||
option(LWS_WITHOUT_BUILTIN_GETIFADDRS "Don't use BSD getifaddrs implementation from libwebsockets if it is missing (this will result in a compilation error) ... Default is your libc provides it. On some systems such as uclibc it doesn't exist." OFF)
|
||||
option(LWS_WITHOUT_CLIENT "Don't build the client part of the library" ON)
|
||||
option(LWS_WITHOUT_SERVER "Don't build the server part of the library" OFF)
|
||||
option(LWS_LINK_TESTAPPS_DYNAMIC "Link the test apps to the shared version of the library. Default is to link statically" ON)
|
||||
option(LWS_WITHOUT_TESTAPPS "Don't build the libwebsocket-test-apps" ON)
|
||||
option(LWS_WITHOUT_TEST_SERVER "Don't build the test server" ON)
|
||||
option(LWS_WITHOUT_TEST_SERVER_EXTPOLL "Don't build the test server version that uses external poll" ON)
|
||||
option(LWS_WITHOUT_TEST_PING "Don't build the ping test application" ON)
|
||||
option(LWS_WITHOUT_TEST_CLIENT "Don't build the client test application" ON)
|
||||
option(LWS_WITHOUT_TEST_FRAGGLE "Don't build the ping test application" ON)
|
||||
option(LWS_WITHOUT_DEBUG "Don't compile debug related code" OFF)
|
||||
option(LWS_WITHOUT_EXTENSIONS "Don't compile with extensions" OFF)
|
||||
option(LWS_WITH_LATENCY "Build latency measuring code into the library" OFF)
|
||||
option(LWS_WITHOUT_DAEMONIZE "Don't build the daemonization api" OFF)
|
||||
option(LWS_WITH_LIBEV "Compile with support for libev" OFF)
|
||||
option(LWS_IPV6 "Compile with support for ipv6" ON)
|
||||
option(LWS_WITH_HTTP2 "Compile with support for http2" OFF)
|
||||
|
||||
# Allow the user to override installation directories.
|
||||
set(LWS_INSTALL_LIB_DIR lib CACHE PATH "Installation directory for libraries")
|
||||
set(LWS_INSTALL_BIN_DIR "." CACHE PATH "Installation directory for executables")
|
||||
set(LWS_INSTALL_INCLUDE_DIR include CACHE PATH "Installation directory for header files")
|
||||
set(LWS_INSTALL_EXAMPLES_DIR "." CACHE PATH "Installation directory for example files")
|
||||
|
||||
if (LWS_WITHOUT_CLIENT AND LWS_WITHOUT_SERVER)
|
||||
message(FATAL_ERROR "Makes no sense to compile without both client or server.")
|
||||
endif()
|
||||
|
||||
# The base dir where the test-apps look for the SSL certs.
|
||||
set(LWS_OPENSSL_CLIENT_CERTS ../share CACHE PATH "Server SSL certificate directory")
|
||||
if (WIN32)
|
||||
set(LWS_OPENSSL_CLIENT_CERTS . CACHE PATH "Client SSL certificate directory")
|
||||
|
||||
if (LWS_IPV6)
|
||||
set(LWS_IPV6 OFF)
|
||||
message(WARNING "IPv6 does currently not work on Windows!")
|
||||
endif()
|
||||
else()
|
||||
set(LWS_OPENSSL_CLIENT_CERTS /etc/pki/tls/certs/ CACHE PATH "Client SSL certificate directory")
|
||||
endif()
|
||||
|
||||
set(LWS_CYASSL_LIB CACHE PATH "Path to the CyaSSL library")
|
||||
set(LWS_CYASSL_INCLUDE_DIRS CACHE PATH "Path to the CyaSSL include directory")
|
||||
|
||||
if (LWS_USE_CYASSL)
|
||||
if ("${LWS_CYASSL_LIB}" STREQUAL "" OR "${LWS_CYASSL_INCLUDE_DIRS}" STREQUAL "")
|
||||
message(FATAL_ERROR "You must set LWS_CYASSL_LIB and LWS_CYASSL_INCLUDE_DIRS when LWS_USE_CYASSL is turned on")
|
||||
endif()
|
||||
set(USE_CYASSL 1)
|
||||
endif()
|
||||
|
||||
if (LWS_WITHOUT_EXTENSIONS)
|
||||
set(LWS_NO_EXTENSIONS 1)
|
||||
endif()
|
||||
|
||||
if (LWS_WITH_SSL)
|
||||
set(LWS_OPENSSL_SUPPORT 1)
|
||||
endif()
|
||||
|
||||
if (LWS_SSL_CLIENT_USE_OS_CA_CERTS)
|
||||
set(LWS_SSL_CLIENT_USE_OS_CA_CERTS 1)
|
||||
endif()
|
||||
|
||||
if (LWS_WITH_LATENCY)
|
||||
set(LWS_LATENCY 1)
|
||||
endif()
|
||||
|
||||
if (LWS_WITHOUT_DAEMONIZE OR WIN32)
|
||||
set(LWS_NO_DAEMONIZE 1)
|
||||
endif()
|
||||
|
||||
if (LWS_WITHOUT_SERVER)
|
||||
set(LWS_NO_SERVER 1)
|
||||
endif()
|
||||
|
||||
if (LWS_WITHOUT_CLIENT)
|
||||
set(LWS_NO_CLIENT 1)
|
||||
endif()
|
||||
|
||||
if (LWS_WITHOUT_DEBUG)
|
||||
set(_DEBUG 0)
|
||||
else()
|
||||
set(_DEBUG 1)
|
||||
endif()
|
||||
|
||||
if (LWS_WITH_LIBEV)
|
||||
set(LWS_USE_LIBEV 1)
|
||||
set(LWS_NO_EXTERNAL_POLL 1)
|
||||
endif()
|
||||
|
||||
if (LWS_IPV6)
|
||||
set(LWS_USE_IPV6 1)
|
||||
endif()
|
||||
|
||||
if (LWS_WITH_HTTP2)
|
||||
set(LWS_USE_HTTP2 1)
|
||||
endif()
|
||||
|
||||
if (MINGW)
|
||||
set(LWS_MINGW_SUPPORT 1)
|
||||
endif()
|
||||
|
||||
include_directories("${PROJECT_BINARY_DIR}")
|
||||
|
||||
include(CheckCSourceCompiles)
|
||||
|
||||
# Check for different inline keyword versions.
|
||||
foreach(KEYWORD "inline" "__inline__" "__inline")
|
||||
set(CMAKE_REQUIRED_DEFINITIONS "-DKEYWORD=${KEYWORD}")
|
||||
CHECK_C_SOURCE_COMPILES(
|
||||
"
|
||||
#include <stdio.h>
|
||||
KEYWORD void a() {}
|
||||
int main(int argc, char **argv) { a(); return 0; }
|
||||
" HAVE_${KEYWORD})
|
||||
endforeach()
|
||||
|
||||
if (NOT HAVE_inline)
|
||||
if (HAVE___inline__)
|
||||
set(inline __inline__)
|
||||
elseif(HAVE___inline)
|
||||
set(inline __inline)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Put the libaries and binaries that get built into directories at the
|
||||
# top of the build tree rather than in hard-to-find leaf directories.
|
||||
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin")
|
||||
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
|
||||
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
|
||||
|
||||
# Put absolute path of dynamic libraries into the object code. Some
|
||||
# architectures, notably Mac OS X, need this.
|
||||
SET(CMAKE_INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/${LWS_INSTALL_LIB_DIR}${LIB_SUFFIX}")
|
||||
|
||||
# So we can include the CMake generated config file only when
|
||||
# building with CMAKE.
|
||||
add_definitions(-DCMAKE_BUILD)
|
||||
|
||||
include(CheckFunctionExists)
|
||||
include(CheckIncludeFile)
|
||||
include(CheckIncludeFiles)
|
||||
include(CheckLibraryExists)
|
||||
include(CheckTypeSize)
|
||||
|
||||
CHECK_FUNCTION_EXISTS(bzero HAVE_BZERO)
|
||||
CHECK_FUNCTION_EXISTS(fork HAVE_FORK)
|
||||
CHECK_FUNCTION_EXISTS(getenv HAVE_GETENV)
|
||||
CHECK_FUNCTION_EXISTS(malloc HAVE_MALLOC)
|
||||
CHECK_FUNCTION_EXISTS(memset HAVE_MEMSET)
|
||||
CHECK_FUNCTION_EXISTS(realloc HAVE_REALLOC)
|
||||
CHECK_FUNCTION_EXISTS(socket HAVE_SOCKET)
|
||||
CHECK_FUNCTION_EXISTS(strerror HAVE_STRERROR)
|
||||
CHECK_FUNCTION_EXISTS(vfork HAVE_VFORK)
|
||||
CHECK_FUNCTION_EXISTS(getifaddrs HAVE_GETIFADDRS)
|
||||
|
||||
if (NOT HAVE_GETIFADDRS)
|
||||
if (LWS_WITHOUT_BUILTIN_GETIFADDRS)
|
||||
message(FATAL_ERROR "No getifaddrs was found on the system. Turn off the LWS_WITHOUT_BUILTIN_GETIFADDRS compile option to use the supplied BSD version.")
|
||||
endif()
|
||||
|
||||
set(LWS_BUILTIN_GETIFADDRS 1)
|
||||
endif()
|
||||
|
||||
CHECK_INCLUDE_FILE(dlfcn.h HAVE_DLFCN_H)
|
||||
CHECK_INCLUDE_FILE(fcntl.h HAVE_FCNTL_H)
|
||||
CHECK_INCLUDE_FILE(in6addr.h HAVE_IN6ADDR_H)
|
||||
CHECK_INCLUDE_FILE(inttypes.h HAVE_INTTYPES_H)
|
||||
CHECK_INCLUDE_FILE(memory.h HAVE_MEMORY_H)
|
||||
CHECK_INCLUDE_FILE(netinet/in.h HAVE_NETINET_IN_H)
|
||||
CHECK_INCLUDE_FILE(stdint.h HAVE_STDINT_H)
|
||||
CHECK_INCLUDE_FILE(stdlib.h HAVE_STDLIB_H)
|
||||
CHECK_INCLUDE_FILE(strings.h HAVE_STRINGS_H)
|
||||
CHECK_INCLUDE_FILE(string.h HAVE_STRING_H)
|
||||
CHECK_INCLUDE_FILE(sys/prctl.h HAVE_SYS_PRCTL_H)
|
||||
CHECK_INCLUDE_FILE(sys/socket.h HAVE_SYS_SOCKET_H)
|
||||
CHECK_INCLUDE_FILE(sys/stat.h HAVE_SYS_STAT_H)
|
||||
CHECK_INCLUDE_FILE(sys/types.h HAVE_SYS_TYPES_H)
|
||||
CHECK_INCLUDE_FILE(unistd.h HAVE_UNISTD_H)
|
||||
CHECK_INCLUDE_FILE(vfork.h HAVE_VFORK_H)
|
||||
CHECK_INCLUDE_FILE(zlib.h HAVE_ZLIB_H)
|
||||
|
||||
# TODO: These can be tested if they actually work also...
|
||||
set(HAVE_WORKING_FORK HAVE_FORK)
|
||||
set(HAVE_WORKING_VFORK HAVE_VFORK)
|
||||
|
||||
CHECK_INCLUDE_FILES("stdlib.h;stdarg.h;string.h;float.h" STDC_HEADERS)
|
||||
|
||||
CHECK_TYPE_SIZE(pid_t PID_T_SIZE)
|
||||
CHECK_TYPE_SIZE(size_t SIZE_T_SIZE)
|
||||
|
||||
if (NOT PID_T_SIZE)
|
||||
set(pid_t int)
|
||||
endif()
|
||||
|
||||
if (NOT SIZE_T_SIZE)
|
||||
set(size_t "unsigned int")
|
||||
endif()
|
||||
|
||||
if (NOT HAVE_MALLOC)
|
||||
set(malloc rpl_malloc)
|
||||
endif()
|
||||
|
||||
if (NOT HAVE_REALLOC)
|
||||
set(realloc rpl_realloc)
|
||||
endif()
|
||||
|
||||
# Generate the config.h that includes all the compilation settings.
|
||||
configure_file(
|
||||
"${PROJECT_SOURCE_DIR}/config.h.cmake"
|
||||
"${PROJECT_BINARY_DIR}/lws_config.h")
|
||||
|
||||
if (MSVC)
|
||||
# Turn off stupid microsoft security warnings.
|
||||
add_definitions(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE)
|
||||
endif(MSVC)
|
||||
|
||||
include_directories("${PROJECT_SOURCE_DIR}/lib")
|
||||
|
||||
# Group headers and sources.
|
||||
# Some IDEs use this for nicer file structure.
|
||||
set(HDR_PRIVATE
|
||||
lib/private-libwebsockets.h
|
||||
"${PROJECT_BINARY_DIR}/lws_config.h"
|
||||
)
|
||||
|
||||
set(HDR_PUBLIC
|
||||
"${PROJECT_SOURCE_DIR}/lib/libwebsockets.h"
|
||||
)
|
||||
|
||||
set(SOURCES
|
||||
lib/base64-decode.c
|
||||
lib/handshake.c
|
||||
lib/libwebsockets.c
|
||||
lib/service.c
|
||||
lib/pollfd.c
|
||||
lib/output.c
|
||||
lib/parsers.c
|
||||
lib/context.c
|
||||
lib/sha-1.c
|
||||
)
|
||||
|
||||
if (NOT LWS_WITHOUT_CLIENT)
|
||||
list(APPEND SOURCES
|
||||
lib/client.c
|
||||
lib/client-handshake.c
|
||||
lib/client-parser.c
|
||||
)
|
||||
endif()
|
||||
|
||||
if (LWS_WITH_SSL)
|
||||
list(APPEND SOURCES
|
||||
lib/ssl.c
|
||||
)
|
||||
endif()
|
||||
|
||||
if (LWS_WITH_HTTP2)
|
||||
list(APPEND SOURCES
|
||||
lib/ssl-http2.c
|
||||
)
|
||||
endif()
|
||||
# select the active platform files
|
||||
|
||||
if (WIN32)
|
||||
list(APPEND SOURCES
|
||||
lib/lws-plat-win.c
|
||||
)
|
||||
else()
|
||||
list(APPEND SOURCES
|
||||
lib/lws-plat-unix.c
|
||||
)
|
||||
endif()
|
||||
|
||||
if (NOT LWS_WITHOUT_SERVER)
|
||||
list(APPEND SOURCES
|
||||
lib/server.c
|
||||
lib/server-handshake.c
|
||||
)
|
||||
endif()
|
||||
|
||||
if (NOT LWS_WITHOUT_EXTENSIONS)
|
||||
list(APPEND HDR_PRIVATE
|
||||
lib/extension-deflate-frame.h
|
||||
lib/extension-deflate-stream.h
|
||||
)
|
||||
|
||||
list(APPEND SOURCES
|
||||
lib/extension.c
|
||||
lib/extension-deflate-frame.c
|
||||
lib/extension-deflate-stream.c
|
||||
)
|
||||
endif()
|
||||
|
||||
if (LWS_WITH_LIBEV)
|
||||
list(APPEND SOURCES
|
||||
lib/libev.c
|
||||
)
|
||||
endif(LWS_WITH_LIBEV)
|
||||
|
||||
# Add helper files for Windows.
|
||||
if (WIN32)
|
||||
set(WIN32_HELPERS_PATH win32port/win32helpers)
|
||||
include_directories(${WIN32_HELPERS_PATH})
|
||||
else(WIN32)
|
||||
# Unix.
|
||||
if (NOT LWS_WITHOUT_DAEMONIZE)
|
||||
list(APPEND SOURCES
|
||||
lib/daemonize.c
|
||||
)
|
||||
endif()
|
||||
endif(WIN32)
|
||||
|
||||
if (UNIX)
|
||||
if (NOT HAVE_GETIFADDRS)
|
||||
list(APPEND HDR_PRIVATE lib/getifaddrs.h)
|
||||
list(APPEND SOURCES lib/getifaddrs.c)
|
||||
endif()
|
||||
endif(UNIX)
|
||||
|
||||
|
||||
if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
|
||||
if (UNIX)
|
||||
set( CMAKE_C_FLAGS "-Wall -Werror -O4 -fvisibility=hidden ${CMAKE_C_FLAGS}" )
|
||||
else(UNIX)
|
||||
set( CMAKE_C_FLAGS "-Wall -O4 -fvisibility=hidden ${CMAKE_C_FLAGS}" )
|
||||
endif(UNIX)
|
||||
endif ()
|
||||
|
||||
source_group("Headers Private" FILES ${HDR_PRIVATE})
|
||||
source_group("Headers Public" FILES ${HDR_PUBLIC})
|
||||
source_group("Sources" FILES ${SOURCES})
|
||||
|
||||
#
|
||||
# Create the lib.
|
||||
#
|
||||
add_library(websockets STATIC
|
||||
${HDR_PRIVATE}
|
||||
${HDR_PUBLIC}
|
||||
${SOURCES})
|
||||
add_library(websockets_shared SHARED
|
||||
${HDR_PRIVATE}
|
||||
${HDR_PUBLIC}
|
||||
${SOURCES})
|
||||
|
||||
if (WIN32)
|
||||
# On Windows libs have the same file ending (.lib)
|
||||
# for both static and shared libraries, so we
|
||||
# need a unique name for the static one.
|
||||
set_target_properties(websockets
|
||||
PROPERTIES
|
||||
OUTPUT_NAME websockets_static)
|
||||
|
||||
# Compile as DLL (export function declarations)
|
||||
set_property(
|
||||
TARGET websockets_shared
|
||||
PROPERTY COMPILE_DEFINITIONS
|
||||
LWS_DLL
|
||||
LWS_INTERNAL
|
||||
)
|
||||
endif(WIN32)
|
||||
|
||||
# We want the shared lib to be named "libwebsockets"
|
||||
# not "libwebsocket_shared".
|
||||
set_target_properties(websockets_shared
|
||||
PROPERTIES
|
||||
OUTPUT_NAME websockets)
|
||||
|
||||
# Set the so version of the lib.
|
||||
# Equivalent to LDFLAGS=-version-info x:x:x
|
||||
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
|
||||
foreach(lib websockets websockets_shared)
|
||||
set_target_properties(${lib}
|
||||
PROPERTIES
|
||||
SOVERSION ${SOVERSION})
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
set(LIB_LIST)
|
||||
|
||||
#
|
||||
# Find libraries.
|
||||
#
|
||||
|
||||
#
|
||||
# ZLIB (Only needed for deflate extensions).
|
||||
#
|
||||
if (NOT LWS_WITHOUT_EXTENSIONS)
|
||||
if (WIN32 AND NOT LWS_USE_EXTERNAL_ZLIB)
|
||||
message("Using included Zlib version")
|
||||
|
||||
# Compile ZLib if needed.
|
||||
set(WIN32_ZLIB_PATH "win32port/zlib")
|
||||
set(ZLIB_SRCS
|
||||
${WIN32_ZLIB_PATH}/adler32.c
|
||||
${WIN32_ZLIB_PATH}/compress.c
|
||||
${WIN32_ZLIB_PATH}/crc32.c
|
||||
${WIN32_ZLIB_PATH}/deflate.c
|
||||
${WIN32_ZLIB_PATH}/gzclose.c
|
||||
${WIN32_ZLIB_PATH}/gzio.c
|
||||
${WIN32_ZLIB_PATH}/gzlib.c
|
||||
${WIN32_ZLIB_PATH}/gzread.c
|
||||
${WIN32_ZLIB_PATH}/gzwrite.c
|
||||
${WIN32_ZLIB_PATH}/infback.c
|
||||
${WIN32_ZLIB_PATH}/inffast.c
|
||||
${WIN32_ZLIB_PATH}/inflate.c
|
||||
${WIN32_ZLIB_PATH}/inftrees.c
|
||||
${WIN32_ZLIB_PATH}/trees.c
|
||||
${WIN32_ZLIB_PATH}/uncompr.c
|
||||
${WIN32_ZLIB_PATH}/zutil.c
|
||||
)
|
||||
|
||||
# Create the library.
|
||||
add_library(ZLIB STATIC ${ZLIB_SRCS})
|
||||
|
||||
# Set the same variables as find_package would.
|
||||
set(ZLIB_INCLUDE_DIRS ${WIN32_ZLIB_PATH})
|
||||
get_property(ZLIB_LIBRARIES TARGET ZLIB PROPERTY LOCATION)
|
||||
set(ZLIB_FOUND 1)
|
||||
else()
|
||||
find_package(ZLIB REQUIRED)
|
||||
endif()
|
||||
|
||||
# Make sure ZLib is compiled before the libs.
|
||||
foreach (lib websockets websockets_shared)
|
||||
add_dependencies(${lib} ZLIB)
|
||||
endforeach()
|
||||
|
||||
message("ZLib include dirs: ${ZLIB_INCLUDE_DIRS}")
|
||||
message("ZLib libraries: ${ZLIB_LIBRARIES}")
|
||||
include_directories(${ZLIB_INCLUDE_DIRS})
|
||||
list(APPEND LIB_LIST ${ZLIB_LIBRARIES})
|
||||
endif(NOT LWS_WITHOUT_EXTENSIONS)
|
||||
|
||||
#
|
||||
# OpenSSL
|
||||
#
|
||||
if (LWS_WITH_SSL)
|
||||
message("Compiling with SSL support")
|
||||
|
||||
if (LWS_USE_CYASSL)
|
||||
# Use CyaSSL as OpenSSL replacement.
|
||||
# TODO: Add a find_package command for this also.
|
||||
message("CyaSSL include dir: ${LWS_CYASSL_INCLUDE_DIRS}")
|
||||
message("CyaSSL libraries: ${LWS_CYASSL_LIB}")
|
||||
|
||||
# Additional to the root directory we need to include
|
||||
# the cyassl/ subdirectory which contains the OpenSSL
|
||||
# compatability layer headers.
|
||||
foreach(inc ${LWS_CYASSL_INCLUDE_DIRS})
|
||||
include_directories("${inc}" "${inc}/cyassl")
|
||||
endforeach()
|
||||
|
||||
list(APPEND LIB_LIST "${LWS_CYASSL_LIB}")
|
||||
else()
|
||||
# TODO: Add support for STATIC also.
|
||||
find_package(OpenSSL REQUIRED)
|
||||
|
||||
message("OpenSSL include dir: ${OPENSSL_INCLUDE_DIR}")
|
||||
message("OpenSSL libraries: ${OPENSSL_LIBRARIES}")
|
||||
|
||||
include_directories("${OPENSSL_INCLUDE_DIR}")
|
||||
list(APPEND LIB_LIST ${OPENSSL_LIBRARIES})
|
||||
|
||||
# Link against dynamic linking functions.
|
||||
# (Don't link directly to libdl since it is not needed on all platforms, it's now a part of libc).
|
||||
list(APPEND LIB_LIST ${CMAKE_DL_LIBS})
|
||||
endif()
|
||||
endif(LWS_WITH_SSL)
|
||||
|
||||
if (LWS_WITH_LIBEV)
|
||||
list(APPEND LIB_LIST "ev")
|
||||
endif(LWS_WITH_LIBEV)
|
||||
|
||||
#
|
||||
# Platform specific libs.
|
||||
#
|
||||
if (WINCE)
|
||||
list(APPEND LIB_LIST ws2.lib)
|
||||
elseif (WIN32)
|
||||
list(APPEND LIB_LIST ws2_32.lib)
|
||||
endif()
|
||||
|
||||
if (UNIX)
|
||||
list(APPEND LIB_LIST m)
|
||||
endif()
|
||||
|
||||
# Setup the linking for all libs.
|
||||
foreach (lib websockets websockets_shared)
|
||||
target_link_libraries(${lib} ${LIB_LIST})
|
||||
endforeach()
|
||||
|
||||
#
|
||||
# Test applications
|
||||
#
|
||||
set(TEST_APP_LIST)
|
||||
if (NOT LWS_WITHOUT_TESTAPPS)
|
||||
#
|
||||
# Helper function for adding a test app.
|
||||
#
|
||||
macro(create_test_app TEST_NAME MAIN_SRC)
|
||||
|
||||
set(TEST_SRCS ${MAIN_SRC})
|
||||
set(TEST_HDR)
|
||||
|
||||
if (WIN32)
|
||||
list(APPEND TEST_SRCS
|
||||
${WIN32_HELPERS_PATH}/getopt.c
|
||||
${WIN32_HELPERS_PATH}/getopt_long.c
|
||||
${WIN32_HELPERS_PATH}/gettimeofday.c
|
||||
)
|
||||
|
||||
list(APPEND TEST_HDR
|
||||
${WIN32_HELPERS_PATH}/getopt.h
|
||||
${WIN32_HELPERS_PATH}/gettimeofday.h
|
||||
)
|
||||
endif(WIN32)
|
||||
|
||||
source_group("Headers Private" FILES ${TEST_HDR})
|
||||
source_group("Sources" FILES ${TEST_SRCS})
|
||||
add_executable(${TEST_NAME} ${TEST_SRCS} ${TEST_HDR})
|
||||
|
||||
if (LWS_LINK_TESTAPPS_DYNAMIC)
|
||||
target_link_libraries(${TEST_NAME} websockets_shared)
|
||||
add_dependencies(${TEST_NAME} websockets_shared)
|
||||
else(LWS_LINK_TESTAPPS_DYNAMIC)
|
||||
target_link_libraries(${TEST_NAME} websockets)
|
||||
add_dependencies(${TEST_NAME} websockets)
|
||||
endif(LWS_LINK_TESTAPPS_DYNAMIC)
|
||||
|
||||
# Set test app specific defines.
|
||||
set_property(TARGET ${TEST_NAME}
|
||||
PROPERTY COMPILE_DEFINITIONS
|
||||
INSTALL_DATADIR="${CMAKE_INSTALL_PREFIX}/share"
|
||||
)
|
||||
|
||||
# Prefix the binary names with libwebsockets.
|
||||
set_target_properties(${TEST_NAME}
|
||||
PROPERTIES
|
||||
OUTPUT_NAME libwebsockets-${TEST_NAME})
|
||||
|
||||
# Add to the list of tests.
|
||||
list(APPEND TEST_APP_LIST ${TEST_NAME})
|
||||
endmacro()
|
||||
|
||||
if (LWS_WITH_SSL AND NOT LWS_USE_CYASSL)
|
||||
message("Searching for OpenSSL executable and dlls")
|
||||
find_package(OpenSSLbins)
|
||||
message("OpenSSL executable: ${OPENSSL_EXECUTABLE}")
|
||||
endif()
|
||||
|
||||
if (NOT LWS_WITHOUT_SERVER)
|
||||
#
|
||||
# test-server
|
||||
#
|
||||
if (NOT LWS_WITHOUT_TEST_SERVER)
|
||||
create_test_app(test-server "test-server/test-server.c")
|
||||
endif()
|
||||
|
||||
#
|
||||
# test-server-extpoll
|
||||
#
|
||||
if (NOT LWS_WITHOUT_TEST_SERVER_EXTPOLL)
|
||||
create_test_app(test-server-extpoll "test-server/test-server.c")
|
||||
# Set defines for this executable only.
|
||||
set_property(
|
||||
TARGET test-server-extpoll
|
||||
PROPERTY COMPILE_DEFINITIONS
|
||||
EXTERNAL_POLL
|
||||
INSTALL_DATADIR="${CMAKE_INSTALL_PREFIX}/share"
|
||||
)
|
||||
|
||||
# We need to link against winsock code.
|
||||
if (WIN32)
|
||||
target_link_libraries(test-server-extpoll ws2_32.lib)
|
||||
endif(WIN32)
|
||||
endif()
|
||||
|
||||
# Data files for running the test server.
|
||||
set(TEST_SERVER_DATA
|
||||
"${PROJECT_SOURCE_DIR}/test-server/favicon.ico"
|
||||
"${PROJECT_SOURCE_DIR}/test-server/leaf.jpg"
|
||||
"${PROJECT_SOURCE_DIR}/test-server/libwebsockets.org-logo.png"
|
||||
"${PROJECT_SOURCE_DIR}/test-server/test.html")
|
||||
|
||||
# Generate self-signed SSL certs for the test-server.
|
||||
if (LWS_WITH_SSL AND OPENSSL_EXECUTABLE AND NOT LWS_WITHOUT_TEST_SERVER)
|
||||
message("Generating SSL Certificates for the test-server...")
|
||||
|
||||
set(TEST_SERVER_SSL_KEY "${PROJECT_BINARY_DIR}/libwebsockets-test-server.key.pem")
|
||||
set(TEST_SERVER_SSL_CERT "${PROJECT_BINARY_DIR}/libwebsockets-test-server.pem")
|
||||
|
||||
if (WIN32)
|
||||
file(WRITE "${PROJECT_BINARY_DIR}/openssl_input.txt"
|
||||
"GB\n"
|
||||
"Erewhon\n"
|
||||
"All around\n"
|
||||
"libwebsockets-test\n"
|
||||
"localhost\n"
|
||||
"none@invalid.org\n\n"
|
||||
)
|
||||
|
||||
# The "type" command is a bit picky with paths.
|
||||
file(TO_NATIVE_PATH "${PROJECT_BINARY_DIR}/openssl_input.txt" OPENSSL_INPUT_WIN_PATH)
|
||||
message("OPENSSL_INPUT_WIN_PATH = ${OPENSSL_INPUT_WIN_PATH}")
|
||||
message("cmd = \"${OPENSSL_EXECUTABLE}\" req -new -newkey rsa:1024 -days 10000 -nodes -x509 -keyout \"${TEST_SERVER_SSL_KEY}\" -out \"${TEST_SERVER_SSL_CERT}\"")
|
||||
|
||||
execute_process(
|
||||
COMMAND cmd /c type "${OPENSSL_INPUT_WIN_PATH}"
|
||||
COMMAND "${OPENSSL_EXECUTABLE}" req -new -newkey rsa:1024 -days 10000 -nodes -x509 -keyout "${TEST_SERVER_SSL_KEY}" -out "${TEST_SERVER_SSL_CERT}"
|
||||
RESULT_VARIABLE OPENSSL_RETURN_CODE)
|
||||
|
||||
message("\n")
|
||||
|
||||
if (OPENSSL_RETURN_CODE)
|
||||
message(WARNING "!!! Failed to generate SSL certificate for Test Server using cmd.exe !!!:\nOpenSSL return code = ${OPENSSL_RETURN_CODE}")
|
||||
else()
|
||||
message("SUCCSESFULLY generated SSL certificate")
|
||||
endif()
|
||||
else()
|
||||
# Unix.
|
||||
execute_process(
|
||||
COMMAND printf "GB\\nErewhon\\nAll around\\nlibwebsockets-test\\n\\nlocalhost\\nnone@invalid.org\\n"
|
||||
COMMAND "${OPENSSL_EXECUTABLE}"
|
||||
req -new -newkey rsa:1024 -days 10000 -nodes -x509 -keyout "${TEST_SERVER_SSL_KEY}" -out "${TEST_SERVER_SSL_CERT}"
|
||||
RESULT_VARIABLE OPENSSL_RETURN_CODE)
|
||||
|
||||
if (OPENSSL_RETURN_CODE)
|
||||
message(WARNING "!!! Failed to generate SSL certificate for Test Server!!!:\nOpenSSL return code = ${OPENSSL_RETURN_CODE}")
|
||||
else()
|
||||
message("SUCCSESFULLY generated SSL certificate")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
list(APPEND TEST_SERVER_DATA
|
||||
"${TEST_SERVER_SSL_KEY}"
|
||||
"${TEST_SERVER_SSL_CERT}")
|
||||
endif()
|
||||
|
||||
add_custom_command(TARGET test-server
|
||||
POST_BUILD
|
||||
COMMAND "${CMAKE_COMMAND}" -E make_directory "$<TARGET_FILE_DIR:test-server>/../share/libwebsockets-test-server")
|
||||
|
||||
# Copy the file needed to run the server so that the test apps can
|
||||
# reach them from their default output location
|
||||
foreach (TEST_FILE ${TEST_SERVER_DATA})
|
||||
if (EXISTS ${TEST_FILE})
|
||||
add_custom_command(TARGET test-server
|
||||
POST_BUILD
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy "${TEST_FILE}" "$<TARGET_FILE_DIR:test-server>/../share/libwebsockets-test-server" VERBATIM)
|
||||
endif()
|
||||
endforeach()
|
||||
endif(NOT LWS_WITHOUT_SERVER)
|
||||
|
||||
if (NOT LWS_WITHOUT_CLIENT)
|
||||
#
|
||||
# test-client
|
||||
#
|
||||
if (NOT LWS_WITHOUT_TEST_CLIENT)
|
||||
create_test_app(test-client "test-server/test-client.c")
|
||||
endif()
|
||||
|
||||
#
|
||||
# test-fraggle
|
||||
#
|
||||
if (NOT LWS_WITHOUT_TEST_FRAGGLE)
|
||||
create_test_app(test-fraggle "test-server/test-fraggle.c")
|
||||
endif()
|
||||
|
||||
#
|
||||
# test-ping
|
||||
#
|
||||
if (NOT LWS_WITHOUT_TEST_PING)
|
||||
create_test_app(test-ping "test-server/test-ping.c")
|
||||
endif()
|
||||
#
|
||||
# test-echo
|
||||
#
|
||||
if (NOT WITHOUT_TEST_ECHO)
|
||||
create_test_app(test-echo "test-server/test-echo.c")
|
||||
endif()
|
||||
|
||||
endif(NOT LWS_WITHOUT_CLIENT)
|
||||
|
||||
#
|
||||
# Copy OpenSSL dlls to the output directory on Windows.
|
||||
# (Otherwise we'll get an error when trying to run)
|
||||
#
|
||||
if (WIN32 AND LWS_WITH_SSL AND NOT LWS_USE_CYASSL)
|
||||
if(OPENSSL_BIN_FOUND)
|
||||
message("OpenSSL dlls found:")
|
||||
message(" Libeay: ${LIBEAY_BIN}")
|
||||
message(" SSLeay: ${SSLEAY_BIN}")
|
||||
|
||||
foreach(TARGET_BIN ${TEST_APP_LIST})
|
||||
add_custom_command(TARGET ${TARGET_BIN}
|
||||
POST_BUILD
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy "${LIBEAY_BIN}" "$<TARGET_FILE_DIR:${TARGET_BIN}>" VERBATIM)
|
||||
|
||||
add_custom_command(TARGET ${TARGET_BIN}
|
||||
POST_BUILD
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy "${SSLEAY_BIN}" "$<TARGET_FILE_DIR:${TARGET_BIN}>" VERBATIM)
|
||||
endforeach()
|
||||
endif()
|
||||
endif()
|
||||
endif(NOT LWS_WITHOUT_TESTAPPS)
|
||||
|
||||
if (UNIX)
|
||||
# Generate documentation.
|
||||
# TODO: Fix this on Windows.
|
||||
message("Generating API documentation")
|
||||
file(GLOB C_FILES "${PROJECT_SOURCE_DIR}/lib/*.c")
|
||||
execute_process(COMMAND "${CMAKE_COMMAND}" -E make_directory "${PROJECT_BINARY_DIR}/doc/")
|
||||
|
||||
execute_process(
|
||||
COMMAND "${PROJECT_SOURCE_DIR}/scripts/kernel-doc" -html ${C_FILES} ${HDR_PUBLIC}
|
||||
OUTPUT_FILE "${PROJECT_BINARY_DIR}/doc/libwebsockets-api-doc.html"
|
||||
ERROR_QUIET)
|
||||
|
||||
execute_process(
|
||||
COMMAND "${PROJECT_SOURCE_DIR}/scripts/kernel-doc" -text ${C_FILES} ${HDR_PUBLIC}
|
||||
OUTPUT_FILE "${PROJECT_BINARY_DIR}/doc/libwebsockets-api-doc.txt"
|
||||
ERROR_QUIET)
|
||||
|
||||
# Generate and install pkgconfig.
|
||||
# (This is not indented, because the tabs will be part of the output)
|
||||
file(WRITE "${PROJECT_BINARY_DIR}/libwebsockets.pc"
|
||||
"prefix=\"${CMAKE_INSTALL_PREFIX}\"
|
||||
exec_prefix=\${prefix}
|
||||
libdir=\${exec_prefix}/lib${LIB_SUFFIX}
|
||||
includedir=\${prefix}/include
|
||||
|
||||
Name: libwebsockets
|
||||
Description: Websockets server and client library
|
||||
Version: ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}
|
||||
|
||||
Libs: -L\${libdir} -lwebsockets
|
||||
Cflags: -I\${includedir}"
|
||||
)
|
||||
|
||||
install(FILES "${PROJECT_BINARY_DIR}/libwebsockets.pc"
|
||||
DESTINATION lib${LIB_SUFFIX}/pkgconfig)
|
||||
endif(UNIX)
|
||||
|
||||
#
|
||||
# Installation preparations.
|
||||
#
|
||||
|
||||
if(WIN32 AND NOT CYGWIN)
|
||||
set(DEF_INSTALL_CMAKE_DIR cmake)
|
||||
else()
|
||||
set(DEF_INSTALL_CMAKE_DIR lib/cmake/libwebsockets)
|
||||
endif()
|
||||
|
||||
set(LWS_INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH "Installation directory for CMake files")
|
||||
|
||||
# Export targets (This is used for other CMake projects to easily find the libraries and include files).
|
||||
export(TARGETS websockets websockets_shared
|
||||
FILE "${PROJECT_BINARY_DIR}/LibwebsocketsTargets.cmake")
|
||||
export(PACKAGE libwebsockets)
|
||||
|
||||
# Generate the config file for the build-tree.
|
||||
set(LWS__INCLUDE_DIRS
|
||||
"${PROJECT_SOURCE_DIR}/lib"
|
||||
"${PROJECT_BINARY_DIR}")
|
||||
set(LIBWEBSOCKETS_INCLUDE_DIRS ${LWS__INCLUDE_DIRS} CACHE PATH "Libwebsockets include directories")
|
||||
configure_file(${PROJECT_SOURCE_DIR}/cmake/LibwebsocketsConfig.cmake.in
|
||||
${PROJECT_BINARY_DIR}/LibwebsocketsConfig.cmake
|
||||
@ONLY)
|
||||
|
||||
# Generate the config file for the installation tree.
|
||||
get_filename_component(LWS_ABSOLUTE_INSTALL_CMAKE_DIR ${LWS_INSTALL_CMAKE_DIR} ABSOLUTE)
|
||||
get_filename_component(LWS_ABSOLUTE_INSTALL_INCLUDE_DIR ${LWS_INSTALL_INCLUDE_DIR} ABSOLUTE)
|
||||
file(RELATIVE_PATH
|
||||
REL_INCLUDE_DIR
|
||||
"${LWS_ABSOLUTE_INSTALL_CMAKE_DIR}"
|
||||
"${LWS_ABSOLUTE_INSTALL_INCLUDE_DIR}") # Calculate the relative directory from the cmake dir.
|
||||
|
||||
# Note the EVENT_CMAKE_DIR is defined in JanssonConfig.cmake.in,
|
||||
# we escape it here so it's evaluated when it is included instead
|
||||
# so that the include dirs are given relative to where the
|
||||
# config file is located.
|
||||
set(LWS__INCLUDE_DIRS
|
||||
"\${LWS_CMAKE_DIR}/${REL_INCLUDE_DIR}")
|
||||
configure_file(${PROJECT_SOURCE_DIR}/cmake/LibwebsocketsConfig.cmake.in
|
||||
${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/LibwebsocketsConfig.cmake
|
||||
@ONLY)
|
||||
|
||||
# Generate version info for both build-tree and install-tree.
|
||||
configure_file(${PROJECT_SOURCE_DIR}/cmake/LibwebsocketsConfigVersion.cmake.in
|
||||
${PROJECT_BINARY_DIR}/LibwebsocketsConfigVersion.cmake
|
||||
@ONLY)
|
||||
|
||||
set_target_properties(websockets websockets_shared
|
||||
PROPERTIES PUBLIC_HEADER "${HDR_PUBLIC}")
|
||||
|
||||
#
|
||||
# Installation.
|
||||
#
|
||||
|
||||
# Install libs and headers.
|
||||
install(TARGETS websockets websockets_shared
|
||||
EXPORT LibwebsocketsTargets
|
||||
LIBRARY DESTINATION "${LWS_INSTALL_LIB_DIR}${LIB_SUFFIX}" COMPONENT libraries
|
||||
ARCHIVE DESTINATION "${LWS_INSTALL_LIB_DIR}${LIB_SUFFIX}" COMPONENT libraries
|
||||
RUNTIME DESTINATION "${LWS_INSTALL_BIN_DIR}" COMPONENT libraries # Windows DLLs
|
||||
PUBLIC_HEADER DESTINATION "${LWS_INSTALL_INCLUDE_DIR}" COMPONENT dev)
|
||||
set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries")
|
||||
set(CPACK_COMPONENT_DEV_DISPLAY_NAME "Development files")
|
||||
|
||||
# Install test apps.
|
||||
if (NOT LWS_WITHOUT_TESTAPPS AND NOT LWS_WITHOUT_CLIENT)
|
||||
install(TARGETS test-client ${TEST_APP_LIST}
|
||||
RUNTIME DESTINATION ${LWS_INSTALL_EXAMPLES_DIR}
|
||||
COMPONENT examples)
|
||||
set(CPACK_COMPONENT_EXAMPLES_DISPLAY_NAME "Example files")
|
||||
endif()
|
||||
|
||||
# Programs shared files used by the test-server.
|
||||
if (NOT LWS_WITHOUT_TESTAPPS AND NOT LWS_WITHOUT_SERVER)
|
||||
install(FILES ${TEST_SERVER_DATA}
|
||||
DESTINATION share/libwebsockets-test-server
|
||||
COMPONENT examples)
|
||||
endif()
|
||||
|
||||
# Install exports for the install-tree.
|
||||
install(EXPORT LibwebsocketsTargets
|
||||
DESTINATION "${LWS_INSTALL_CMAKE_DIR}" COMPONENT dev)
|
||||
|
||||
# build subdir is not part of sources
|
||||
set(CPACK_SOURCE_IGNORE_FILES $(CPACK_SOURCE_IGNORE_FILES) ".git" "build" "tgz" "tar.gz")
|
||||
|
||||
# Most people are more used to "make dist" compared to "make package_source"
|
||||
add_custom_target(dist COMMAND "${CMAKE_MAKE_PROGRAM}" package_source)
|
||||
|
||||
include(UseRPMTools)
|
||||
if (RPMTools_FOUND)
|
||||
RPMTools_ADD_RPM_TARGETS(libwebsockets libwebsockets.spec)
|
||||
endif()
|
||||
|
||||
message("---------------------------------------------------------------------")
|
||||
message(" Settings: (For more help do cmake -LH <srcpath>")
|
||||
message("---------------------------------------------------------------------")
|
||||
message(" LWS_WITH_SSL = ${LWS_WITH_SSL} (SSL Support)")
|
||||
message(" LWS_SSL_CLIENT_USE_OS_CA_CERTS = ${LWS_SSL_CLIENT_USE_OS_CA_CERTS}")
|
||||
message(" LWS_USE_CYASSL = ${LWS_USE_CYASSL} (CyaSSL replacement for OpenSSL)")
|
||||
if (LWS_USE_CYASSL)
|
||||
message(" LWS_CYASSL_LIB = ${LWS_CYASSL_LIB}")
|
||||
message(" LWS_CYASSL_INCLUDE_DIRS = ${LWS_CYASSL_INCLUDE_DIRS}")
|
||||
endif()
|
||||
message(" LWS_WITHOUT_BUILTIN_GETIFADDRS = ${LWS_WITHOUT_BUILTIN_GETIFADDRS}")
|
||||
message(" LWS_WITHOUT_CLIENT = ${LWS_WITHOUT_CLIENT}")
|
||||
message(" LWS_WITHOUT_SERVER = ${LWS_WITHOUT_SERVER}")
|
||||
message(" LWS_LINK_TESTAPPS_DYNAMIC = ${LWS_LINK_TESTAPPS_DYNAMIC}")
|
||||
message(" LWS_WITHOUT_TESTAPPS = ${LWS_WITHOUT_TESTAPPS}")
|
||||
message(" LWS_WITHOUT_TEST_SERVER = ${LWS_WITHOUT_TEST_SERVER}")
|
||||
message(" LWS_WITHOUT_TEST_SERVER_EXTPOLL = ${LWS_WITHOUT_TEST_SERVER_EXTPOLL}")
|
||||
message(" LWS_WITHOUT_TEST_PING = ${LWS_WITHOUT_TEST_PING}")
|
||||
message(" LWS_WITHOUT_TEST_CLIENT = ${LWS_WITHOUT_TEST_CLIENT}")
|
||||
message(" LWS_WITHOUT_TEST_FRAGGLE = ${LWS_WITHOUT_TEST_FRAGGLE}")
|
||||
message(" LWS_WITHOUT_DEBUG = ${LWS_WITHOUT_DEBUG}")
|
||||
message(" LWS_WITHOUT_EXTENSIONS = ${LWS_WITHOUT_EXTENSIONS}")
|
||||
message(" LWS_WITH_LATENCY = ${LWS_WITH_LATENCY}")
|
||||
message(" LWS_WITHOUT_DAEMONIZE = ${LWS_WITHOUT_DAEMONIZE}")
|
||||
message(" LWS_USE_LIBEV = ${LWS_USE_LIBEV}")
|
||||
message(" LWS_IPV6 = ${LWS_IPV6}")
|
||||
message(" LWS_WITH_HTTP2 = ${LWS_WITH_HTTP2}")
|
||||
message("---------------------------------------------------------------------")
|
||||
|
||||
# These will be available to parent projects including libwebsockets using add_subdirectory()
|
||||
set(LIBWEBSOCKETS_LIBRARIES websocket websockets_shared CACHE STRING "Libwebsocket libraries")
|
||||
set(LIBWEBSOCKETS_LIBRARIES_STATIC websocket CACHE STRING "Libwebsocket static library")
|
||||
set(LIBWEBSOCKETS_LIBRARIES_SHARED websockets_shared CACHE STRING "Libwebsocket shared library")
|
||||
|
||||
# This must always be last!
|
||||
include(CPack)
|
||||
526
dependencies/libwebsockets/LICENSE
vendored
Normal file
526
dependencies/libwebsockets/LICENSE
vendored
Normal file
@ -0,0 +1,526 @@
|
||||
Libwebsockets and included programs are provided under the terms of the GNU
|
||||
Library General Public License (LGPL) 2.1, with the following exceptions:
|
||||
|
||||
1) 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.
|
||||
|
||||
2) 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
|
||||
(http://libwebsockets.org)"
|
||||
|
||||
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!
|
||||
20
dependencies/libwebsockets/README
vendored
Normal file
20
dependencies/libwebsockets/README
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
This is the libwebsockets C library for lightweight websocket clients and
|
||||
servers. For support, visit
|
||||
|
||||
http://libwebsockets.org
|
||||
|
||||
and consider joining the project mailing list at
|
||||
|
||||
http://ml.libwebsockets.org/mailman/listinfo/libwebsockets
|
||||
|
||||
You can get the latest version of the library from git
|
||||
|
||||
http://git.libwebsockets.org
|
||||
https://github.com/warmcat/libwebsockets
|
||||
|
||||
for more information:
|
||||
|
||||
README.build - information on building the library
|
||||
README.coding - information for writing code using the library
|
||||
README.test-apps - information about the test apps built with the library
|
||||
|
||||
225
dependencies/libwebsockets/README.build
vendored
Normal file
225
dependencies/libwebsockets/README.build
vendored
Normal file
@ -0,0 +1,225 @@
|
||||
Introduction to CMake
|
||||
---------------------
|
||||
|
||||
CMake is a multi-platform build tool that can generate build files for many
|
||||
different target platforms. See more info at http://www.cmake.org
|
||||
|
||||
CMake also allows/recommends you to do "out of source"-builds, that is,
|
||||
the build files are separated from your sources, so there is no need to
|
||||
create elaborate clean scripts to get a clean source tree, instead you
|
||||
simply remove your build directory.
|
||||
|
||||
Libwebsockets has been tested to build successfully on the following platforms
|
||||
with SSL support (both OpenSSL/CyaSSL):
|
||||
|
||||
- Windows
|
||||
- Linux (x86 and ARM)
|
||||
- OSX
|
||||
- NetBSD
|
||||
|
||||
Building the library and test apps
|
||||
----------------------------------
|
||||
|
||||
The project settings used by CMake to generate the platform specific build
|
||||
files is called CMakeLists.txt. CMake then uses one of its "Generators" to
|
||||
output a Visual Studio project or Make file for instance. To see a list of
|
||||
the available generators for your platform, simply run the "cmake" command.
|
||||
|
||||
Note that by default OpenSSL will be linked, if you don't want SSL support
|
||||
see below on how to toggle compile options.
|
||||
|
||||
Building on Unix:
|
||||
-----------------
|
||||
|
||||
1. Install CMake 2.6 or greater: http://cmake.org/cmake/resources/software.html
|
||||
(Most Unix distributions comes with a packaged version also)
|
||||
|
||||
2. Install OpenSSL.
|
||||
|
||||
3. Generate the build files (default is Make files):
|
||||
|
||||
cd /path/to/src
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
|
||||
(NOTE: The build/ directory can have any name and be located anywhere
|
||||
on your filesystem, and that the argument ".." given to cmake is simply
|
||||
the source directory of libwebsockets containing the CMakeLists.txt
|
||||
project file. All examples in this file assumes you use "..")
|
||||
|
||||
NOTE2
|
||||
A common option you may want to give is to set the install path, same
|
||||
as --prefix= with autotools. It defaults to /usr/local.
|
||||
You can do this by, eg
|
||||
|
||||
cmake .. -DCMAKE_INSTALL_PREFIX:PATH=/usr
|
||||
|
||||
NOTE3
|
||||
On machines that want libraries in lib64, you can also add the
|
||||
following to the cmake line
|
||||
|
||||
-DLIB_SUFFIX=64
|
||||
|
||||
NOTE4
|
||||
If you are building against a non-distro OpenSSL (eg, in order to get
|
||||
access to ALPN support only in newer OpenSSL versions) the nice way to
|
||||
express that in one cmake command is eg,
|
||||
|
||||
-DOPENSSL_ROOT_DIR=/usr/local/ssl
|
||||
|
||||
4. Finally you can build using the generated Makefile:
|
||||
|
||||
make
|
||||
|
||||
|
||||
Quirk of cmake
|
||||
--------------
|
||||
|
||||
When changing cmake options, for some reason the only way to get it to see the
|
||||
changes sometimes is delete the contents of your build directory and do the
|
||||
cmake from scratch.
|
||||
|
||||
|
||||
Building on Windows (Visual Studio)
|
||||
-----------------------------------
|
||||
1. Install CMake 2.6 or greater: http://cmake.org/cmake/resources/software.html
|
||||
|
||||
2. Install OpenSSL binaries. http://www.openssl.org/related/binaries.html
|
||||
(Preferably in the default location to make it easier for CMake to find them)
|
||||
|
||||
3. Generate the Visual studio project by opening the Visual Studio cmd prompt:
|
||||
|
||||
cd <path to src>
|
||||
md build
|
||||
cd build
|
||||
cmake -G "Visual Studio 10" ..
|
||||
|
||||
(NOTE: There is also a cmake-gui available on Windows if you prefer that)
|
||||
|
||||
4. Now you should have a generated Visual Studio Solution in your
|
||||
<path to src>/build directory, which can be used to build.
|
||||
|
||||
Setting compile options
|
||||
-----------------------
|
||||
|
||||
To set compile time flags you can either use one of the CMake gui applications
|
||||
or do it via command line.
|
||||
|
||||
Command line
|
||||
------------
|
||||
To list avaialable options (ommit the H if you don't want the help text):
|
||||
|
||||
cmake -LH ..
|
||||
|
||||
Then to set an option and build (for example turn off SSL support):
|
||||
|
||||
cmake -DLWS_WITH_SSL=0 ..
|
||||
or
|
||||
cmake -DLWS_WITH_SSL:BOOL=OFF ..
|
||||
|
||||
Unix GUI
|
||||
--------
|
||||
If you have a curses enabled build you simply type:
|
||||
(not all packages include this, my debian install does not for example).
|
||||
|
||||
ccmake
|
||||
|
||||
Windows GUI
|
||||
-----------
|
||||
On windows CMake comes with a gui application:
|
||||
Start -> Programs -> CMake -> CMake (cmake-gui)
|
||||
|
||||
CyaSSL replacement for OpenSSL
|
||||
------------------------------
|
||||
CyaSSL is a lightweight SSL library targeted at embedded system:
|
||||
http://www.yassl.com/yaSSL/Products-cyassl.html
|
||||
|
||||
It contains a OpenSSL compatability layer which makes it possible to pretty
|
||||
much link to it instead of OpenSSL, giving a much smaller footprint.
|
||||
|
||||
NOTE: cyassl needs to be compiled using the --enable-opensslextra flag for
|
||||
this to work.
|
||||
|
||||
Compiling libwebsockets with CyaSSL
|
||||
-----------------------------------
|
||||
|
||||
cmake .. -DLWS_USE_CYASSL=1 \
|
||||
-DLWS_CYASSL_INCLUDE_DIRS=/path/to/cyassl \
|
||||
-DLWS_CYASSL_LIB=/path/to/cyassl/cyassl.a ..
|
||||
|
||||
NOTE: On windows use the .lib file extension for LWS_CYASSL_LIB instead.
|
||||
|
||||
Cross compiling
|
||||
---------------
|
||||
To enable cross compiling libwebsockets using CMake you need to create
|
||||
a "Toolchain file" that you supply to CMake when generating your build files.
|
||||
CMake will then use the cross compilers and build paths specified in this file
|
||||
to look for dependencies and such.
|
||||
|
||||
Libwebsockets includes an example toolchain file cross-arm-linux-gnueabihf.cmake
|
||||
you can use as a starting point.
|
||||
|
||||
The commandline to configure for cross with this would look like
|
||||
|
||||
cmake .. -DCMAKE_INSTALL_PREFIX:PATH=/usr \
|
||||
-DCMAKE_TOOLCHAIN_FILE=../cross-arm-linux-gnueabihf.cmake \
|
||||
-DWITHOUT_EXTENSIONS=1 -DWITH_SSL=0
|
||||
|
||||
The example shows how to build with no external cross lib dependencies, you
|
||||
need to proide the cross libraries otherwise.
|
||||
|
||||
NOTE: start from an EMPTY build directory if you had a non-cross build in there
|
||||
before the settings will be cached and your changes ignored.
|
||||
|
||||
Additional information on cross compilation with CMake:
|
||||
http://www.vtk.org/Wiki/CMake_Cross_Compiling
|
||||
|
||||
|
||||
Memory efficiency
|
||||
-----------------
|
||||
|
||||
Embedded server-only configuration without extensions (ie, no compression
|
||||
on websocket connections), but with full v13 websocket features and http
|
||||
server, built on ARM Cortex-A9:
|
||||
|
||||
Update at 8dac94d (2013-02-18)
|
||||
|
||||
./configure --without-client --without-extensions --disable-debug --without-daemonize
|
||||
|
||||
Context Creation, 1024 fd limit[2]: 16720 (includes 12 bytes per fd)
|
||||
Per-connection [3]: 72 bytes, +1328 during headers
|
||||
|
||||
.text .rodata .data .bss
|
||||
11512 2784 288 4
|
||||
|
||||
This shows the impact of the major configuration with/without options at
|
||||
13ba5bbc633ea962d46d using Ubuntu ARM on a PandaBoard ES.
|
||||
|
||||
These are accounting for static allocations from the library elf, there are
|
||||
additional dynamic allocations via malloc. These are a bit old now but give
|
||||
the right idea for relative "expense" of features.
|
||||
|
||||
Static allocations, ARM9
|
||||
.text .rodata .data .bss
|
||||
All (no without) 35024 9940 336 4104
|
||||
without client 25684 7144 336 4104
|
||||
without client, exts 21652 6288 288 4104
|
||||
without client, exts, debug[1] 19756 3768 288 4104
|
||||
without server 30304 8160 336 4104
|
||||
without server, exts 25382 7204 288 4104
|
||||
without server, exts, debug[1] 23712 4256 288 4104
|
||||
|
||||
[1] --disable-debug only removes messages below lwsl_notice. Since that is
|
||||
the default logging level the impact is not noticable, error, warn and notice
|
||||
logs are all still there.
|
||||
|
||||
[2] 1024 fd per process is the default limit (set by ulimit) in at least Fedora
|
||||
and Ubuntu. You can make significant savings tailoring this to actual expected
|
||||
peak fds, ie, at a limit of 20, context creation allocation reduces to 4432 +
|
||||
240 = 4672)
|
||||
|
||||
[3] known header content is freed after connection establishment
|
||||
|
||||
|
||||
|
||||
267
dependencies/libwebsockets/README.coding
vendored
Normal file
267
dependencies/libwebsockets/README.coding
vendored
Normal file
@ -0,0 +1,267 @@
|
||||
Daemonization
|
||||
-------------
|
||||
|
||||
There's a helper api lws_daemonize built by default that does everything you
|
||||
need to daemonize well, including creating a lock file. If you're making
|
||||
what's basically a daemon, just call this early in your init to fork to a
|
||||
headless background process and exit the starting process.
|
||||
|
||||
Notice stdout, stderr, stdin are all redirected to /dev/null to enforce your
|
||||
daemon is headless, so you'll need to sort out alternative logging, by, eg,
|
||||
syslog.
|
||||
|
||||
|
||||
Maximum number of connections
|
||||
-----------------------------
|
||||
|
||||
The maximum number of connections the library can deal with is decided when
|
||||
it starts by querying the OS to find out how many file descriptors it is
|
||||
allowed to open (1024 on Fedora for example). It then allocates arrays that
|
||||
allow up to that many connections, minus whatever other file descriptors are
|
||||
in use by the user code.
|
||||
|
||||
If you want to restrict that allocation, or increase it, you can use ulimit or
|
||||
similar to change the avaiable number of file descriptors, and when restarted
|
||||
libwebsockets will adapt accordingly.
|
||||
|
||||
|
||||
Libwebsockets is singlethreaded
|
||||
-------------------------------
|
||||
|
||||
Directly performing websocket actions from other threads is not allowed.
|
||||
Aside from the internal data being inconsistent in forked() processes,
|
||||
the scope of a wsi (struct websocket) can end at any time during service
|
||||
with the socket closing and the wsi freed.
|
||||
|
||||
Websocket write activities should only take place in the
|
||||
"LWS_CALLBACK_SERVER_WRITEABLE" callback as described below.
|
||||
|
||||
Only live connections appear in the user callbacks, so this removes any
|
||||
possibility of trying to used closed and freed wsis.
|
||||
|
||||
If you need to service other socket or file descriptors as well as the
|
||||
websocket ones, you can combine them together with the websocket ones
|
||||
in one poll loop, see "External Polling Loop support" below, and
|
||||
still do it all in one thread / process context.
|
||||
|
||||
|
||||
Only send data when socket writeable
|
||||
------------------------------------
|
||||
|
||||
You should only send data on a websocket connection from the user callback
|
||||
"LWS_CALLBACK_SERVER_WRITEABLE" (or "LWS_CALLBACK_CLIENT_WRITEABLE" for
|
||||
clients).
|
||||
|
||||
If you want to send something, do not just send it but request a callback
|
||||
when the socket is writeable using
|
||||
|
||||
- libwebsocket_callback_on_writable(context, wsi) for a specific wsi, or
|
||||
- libwebsocket_callback_on_writable_all_protocol(protocol) for all connections
|
||||
using that protocol to get a callback when next writeable.
|
||||
|
||||
Usually you will get called back immediately next time around the service
|
||||
loop, but if your peer is slow or temporarily inactive the callback will be
|
||||
delayed accordingly. Generating what to write and sending it should be done
|
||||
in the ...WRITEABLE callback.
|
||||
|
||||
See the test server code for an example of how to do this.
|
||||
|
||||
|
||||
Do not rely on only your own WRITEABLE requests appearing
|
||||
---------------------------------------------------------
|
||||
|
||||
Libwebsockets may generate additional LWS_CALLBACK_CLIENT_WRITEABLE events
|
||||
if it met network conditions where it had to buffer your send data internally.
|
||||
|
||||
So your code for LWS_CALLBACK_CLIENT_WRITEABLE needs to own the decision
|
||||
about what to send, it can't assume that just because the writeable callback
|
||||
came it really is time to send something.
|
||||
|
||||
It's quite possible you get an 'extra' writeable callback at any time and
|
||||
just need to return 0 and wait for the expected callback later.
|
||||
|
||||
|
||||
Closing connections from the user side
|
||||
--------------------------------------
|
||||
|
||||
When you want to close a connection, you do it by returning -1 from a
|
||||
callback for that connection.
|
||||
|
||||
You can provoke a callback by calling libwebsocket_callback_on_writable on
|
||||
the wsi, then notice in the callback you want to close it and just return -1.
|
||||
But usually, the decision to close is made in a callback already and returning
|
||||
-1 is simple.
|
||||
|
||||
If the socket knows the connection is dead, because the peer closed or there
|
||||
was an affirmitive network error like a FIN coming, then libwebsockets will
|
||||
take care of closing the connection automatically.
|
||||
|
||||
If you have a silently dead connection, it's possible to enter a state where
|
||||
the send pipe on the connection is choked but no ack will ever come, so the
|
||||
dead connection will never become writeable. To cover that, you can use TCP
|
||||
keepalives (see later in this document)
|
||||
|
||||
|
||||
Fragmented messages
|
||||
-------------------
|
||||
|
||||
To support fragmented messages you need to check for the final
|
||||
frame of a message with libwebsocket_is_final_fragment. This
|
||||
check can be combined with libwebsockets_remaining_packet_payload
|
||||
to gather the whole contents of a message, eg:
|
||||
|
||||
case LWS_CALLBACK_RECEIVE:
|
||||
{
|
||||
Client * const client = (Client *)user;
|
||||
const size_t remaining = libwebsockets_remaining_packet_payload(wsi);
|
||||
|
||||
if (!remaining && libwebsocket_is_final_fragment(wsi)) {
|
||||
if (client->HasFragments()) {
|
||||
client->AppendMessageFragment(in, len, 0);
|
||||
in = (void *)client->GetMessage();
|
||||
len = client->GetMessageLength();
|
||||
}
|
||||
|
||||
client->ProcessMessage((char *)in, len, wsi);
|
||||
client->ResetMessage();
|
||||
} else
|
||||
client->AppendMessageFragment(in, len, remaining);
|
||||
}
|
||||
break;
|
||||
|
||||
The test app llibwebsockets-test-fraggle sources also show how to
|
||||
deal with fragmented messages.
|
||||
|
||||
|
||||
Debug Logging
|
||||
-------------
|
||||
|
||||
Also using lws_set_log_level api you may provide a custom callback to actually
|
||||
emit the log string. By default, this points to an internal emit function
|
||||
that sends to stderr. Setting it to NULL leaves it as it is instead.
|
||||
|
||||
A helper function lwsl_emit_syslog() is exported from the library to simplify
|
||||
logging to syslog. You still need to use setlogmask, openlog and closelog
|
||||
in your user code.
|
||||
|
||||
The logging apis are made available for user code.
|
||||
|
||||
lwsl_err(...)
|
||||
lwsl_warn(...)
|
||||
lwsl_notice(...)
|
||||
lwsl_info(...)
|
||||
lwsl_debug(...)
|
||||
|
||||
The difference between notice and info is that notice will be logged by default
|
||||
whereas info is ignored by default.
|
||||
|
||||
|
||||
External Polling Loop support
|
||||
-----------------------------
|
||||
|
||||
libwebsockets maintains an internal poll() array for all of its
|
||||
sockets, but you can instead integrate the sockets into an
|
||||
external polling array. That's needed if libwebsockets will
|
||||
cooperate with an existing poll array maintained by another
|
||||
server.
|
||||
|
||||
Four callbacks LWS_CALLBACK_ADD_POLL_FD, LWS_CALLBACK_DEL_POLL_FD,
|
||||
LWS_CALLBACK_SET_MODE_POLL_FD and LWS_CALLBACK_CLEAR_MODE_POLL_FD
|
||||
appear in the callback for protocol 0 and allow interface code to
|
||||
manage socket descriptors in other poll loops.
|
||||
|
||||
You can pass all pollfds that need service to libwebsocket_service_fd(), even
|
||||
if the socket or file does not belong to libwebsockets it is safe.
|
||||
|
||||
If libwebsocket handled it, it zeros the pollfd revents field before returning.
|
||||
So you can let libwebsockets try and if pollfd->revents is nonzero on return,
|
||||
you know it needs handling by your code.
|
||||
|
||||
|
||||
Using with in c++ apps
|
||||
----------------------
|
||||
|
||||
The library is ready for use by C++ apps. You can get started quickly by
|
||||
copying the test server
|
||||
|
||||
$ cp test-server/test-server.c test.cpp
|
||||
|
||||
and building it in C++ like this
|
||||
|
||||
$ g++ -DINSTALL_DATADIR=\"/usr/share\" -ocpptest test.cpp -lwebsockets
|
||||
|
||||
INSTALL_DATADIR is only needed because the test server uses it as shipped, if
|
||||
you remove the references to it in your app you don't need to define it on
|
||||
the g++ line either.
|
||||
|
||||
|
||||
Availability of header information
|
||||
----------------------------------
|
||||
|
||||
From v1.2 of the library onwards, the HTTP header content is free()d as soon
|
||||
as the websocket connection is established. For websocket servers, you can
|
||||
copy interesting headers by handling LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION
|
||||
callback, for clients there's a new callback just for this purpose
|
||||
LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH.
|
||||
|
||||
|
||||
TCP Keepalive
|
||||
-------------
|
||||
|
||||
It is possible for a connection which is not being used to send to die
|
||||
silently somewhere between the peer and the side not sending. In this case
|
||||
by default TCP will just not report anything and you will never get any more
|
||||
incoming data or sign the link is dead until you try to send.
|
||||
|
||||
To deal with getting a notification of that situation, you can choose to
|
||||
enable TCP keepalives on all libwebsockets sockets, when you create the
|
||||
context.
|
||||
|
||||
To enable keepalive, set the ka_time member of the context creation parameter
|
||||
struct to a nonzero value (in seconds) at context creation time. You should
|
||||
also fill ka_probes and ka_interval in that case.
|
||||
|
||||
With keepalive enabled, the TCP layer will send control packets that should
|
||||
stimulate a response from the peer without affecting link traffic. If the
|
||||
response is not coming, the socket will announce an error at poll() forcing
|
||||
a close.
|
||||
|
||||
Note that BSDs don't support keepalive time / probes / inteveral per-socket
|
||||
like Linux does. On those systems you can enable keepalive by a nonzero
|
||||
value in ka_time, but the systemwide kernel settings for the time / probes/
|
||||
interval are used, regardless of what nonzero value is in ka_time.
|
||||
|
||||
Optimizing SSL connections
|
||||
--------------------------
|
||||
|
||||
There's a member ssl_cipher_list in the lws_context_creation_info struct
|
||||
which allows the user code to restrict the possible cipher selection at
|
||||
context-creation time.
|
||||
|
||||
You might want to look into that to stop the ssl peers selecting a ciher which
|
||||
is too computationally expensive. To use it, point it to a string like
|
||||
|
||||
"RC4-MD5:RC4-SHA:AES128-SHA:AES256-SHA:HIGH:!DSS:!aNULL"
|
||||
|
||||
if left NULL, then the "DEFAULT" set of ciphers are all possible to select.
|
||||
|
||||
|
||||
Async nature of client connections
|
||||
----------------------------------
|
||||
|
||||
When you call libwebsocket_client_connect(..) and get a wsi back, it does not
|
||||
mean your connection is active. It just mean it started trying to connect.
|
||||
|
||||
Your client connection is actually active only when you receive
|
||||
LWS_CALLBACK_CLIENT_ESTABLISHED for it.
|
||||
|
||||
There's a 5 second timeout for the connection, and it may give up or die for
|
||||
other reasons, if any of that happens you'll get a
|
||||
LWS_CALLBACK_CLIENT_CONNECTION_ERROR callback on protocol 0 instead for the
|
||||
wsi.
|
||||
|
||||
After attempting the connection and getting back a non-NULL wsi you should
|
||||
loop calling libwebsocket_service() until one of the above callbacks occurs.
|
||||
|
||||
As usual, see test-client.c for example code.
|
||||
|
||||
272
dependencies/libwebsockets/README.test-apps
vendored
Normal file
272
dependencies/libwebsockets/README.test-apps
vendored
Normal file
@ -0,0 +1,272 @@
|
||||
Testing server with a browser
|
||||
-----------------------------
|
||||
|
||||
If you run libwebsockets-test-server and point your browser
|
||||
(eg, Chrome) to
|
||||
|
||||
http://127.0.0.1:7681
|
||||
|
||||
It will fetch a script in the form of test.html, and then run the
|
||||
script in there on the browser to open a websocket connection.
|
||||
Incrementing numbers should appear in the browser display.
|
||||
|
||||
By default the test server logs to both stderr and syslog, you can control
|
||||
what is logged using -d <log level>, see later.
|
||||
|
||||
|
||||
Running test server as a Daemon
|
||||
-------------------------------
|
||||
|
||||
You can use the -D option on the test server to have it fork into the
|
||||
background and return immediately. In this daemonized mode all stderr is
|
||||
disabled and logging goes only to syslog, eg, /var/log/messages or similar.
|
||||
|
||||
The server maintains a lockfile at /tmp/.lwsts-lock that contains the pid
|
||||
of the master process, and deletes this file when the master process
|
||||
terminates.
|
||||
|
||||
To stop the daemon, do
|
||||
|
||||
kill `cat /tmp/.lwsts-lock`
|
||||
|
||||
If it finds a stale lock (the pid mentioned in the file does not exist
|
||||
any more) it will delete the lock and create a new one during startup.
|
||||
|
||||
If the lock is valid, the daemon will exit with a note on stderr that
|
||||
it was already running.s
|
||||
|
||||
|
||||
Using SSL on the server side
|
||||
----------------------------
|
||||
|
||||
To test it using SSL/WSS, just run the test server with
|
||||
|
||||
$ libwebsockets-test-server --ssl
|
||||
|
||||
and use the URL
|
||||
|
||||
https://127.0.0.1:7681
|
||||
|
||||
The connection will be entirely encrypted using some generated
|
||||
certificates that your browser will not accept, since they are
|
||||
not signed by any real Certificate Authority. Just accept the
|
||||
certificates in the browser and the connection will proceed
|
||||
in first https and then websocket wss, acting exactly the
|
||||
same.
|
||||
|
||||
test-server.c is all that is needed to use libwebsockets for
|
||||
serving both the script html over http and websockets.
|
||||
|
||||
|
||||
Testing websocket client support
|
||||
--------------------------------
|
||||
|
||||
If you run the test server as described above, you can also
|
||||
connect to it using the test client as well as a browser.
|
||||
|
||||
$ libwebsockets-test-client localhost
|
||||
|
||||
will by default connect to the test server on localhost:7681
|
||||
and print the dumb increment number from the server at the
|
||||
same time as drawing random circles in the mirror protocol;
|
||||
if you connect to the test server using a browser at the
|
||||
same time you will be able to see the circles being drawn.
|
||||
|
||||
|
||||
Testing simple echo
|
||||
-------------------
|
||||
|
||||
You can test against echo.websockets.org as a sanity test like
|
||||
this (the client connects to port 80 by default):
|
||||
|
||||
$ libwebsockets-test-echo --client echo.websocket.org
|
||||
|
||||
This echo test is of limited use though because it doesn't
|
||||
negotiate any protocol. You can run the same test app as a
|
||||
local server, by default on localhost:7681
|
||||
|
||||
$ libwebsockets-test-echo
|
||||
|
||||
and do the echo test against the local echo server
|
||||
|
||||
$ libwebsockets-test-echo --client localhost --port 7681
|
||||
|
||||
If you add the --ssl switch to both the client and server, you can also test
|
||||
with an encrypted link.
|
||||
|
||||
|
||||
Testing SSL on the client side
|
||||
------------------------------
|
||||
|
||||
To test SSL/WSS client action, just run the client test with
|
||||
|
||||
$ libwebsockets-test-client localhost --ssl
|
||||
|
||||
By default the client test applet is set to accept selfsigned
|
||||
certificates used by the test server, this is indicated by the
|
||||
use_ssl var being set to 2. Set it to 1 to reject any server
|
||||
certificate that it doesn't have a trusted CA cert for.
|
||||
|
||||
|
||||
Using the websocket ping utility
|
||||
--------------------------------
|
||||
|
||||
libwebsockets-test-ping connects as a client to a remote
|
||||
websocket server using 04 protocol and pings it like the
|
||||
normal unix ping utility.
|
||||
|
||||
$ libwebsockets-test-ping localhost
|
||||
handshake OK for protocol lws-mirror-protocol
|
||||
Websocket PING localhost.localdomain (127.0.0.1) 64 bytes of data.
|
||||
64 bytes from localhost: req=1 time=0.1ms
|
||||
64 bytes from localhost: req=2 time=0.1ms
|
||||
64 bytes from localhost: req=3 time=0.1ms
|
||||
64 bytes from localhost: req=4 time=0.2ms
|
||||
64 bytes from localhost: req=5 time=0.1ms
|
||||
64 bytes from localhost: req=6 time=0.2ms
|
||||
64 bytes from localhost: req=7 time=0.2ms
|
||||
64 bytes from localhost: req=8 time=0.1ms
|
||||
^C
|
||||
--- localhost.localdomain websocket ping statistics ---
|
||||
8 packets transmitted, 8 received, 0% packet loss, time 7458ms
|
||||
rtt min/avg/max = 0.110/0.185/0.218 ms
|
||||
$
|
||||
|
||||
By default it sends 64 byte payload packets using the 04
|
||||
PING packet opcode type. You can change the payload size
|
||||
using the -s= flag, up to a maximum of 125 mandated by the
|
||||
04 standard.
|
||||
|
||||
Using the lws-mirror protocol that is provided by the test
|
||||
server, libwebsockets-test-ping can also use larger payload
|
||||
sizes up to 4096 is BINARY packets; lws-mirror will copy
|
||||
them back to the client and they appear as a PONG. Use the
|
||||
-m flag to select this operation.
|
||||
|
||||
The default interval between pings is 1s, you can use the -i=
|
||||
flag to set this, including fractions like -i=0.01 for 10ms
|
||||
interval.
|
||||
|
||||
Before you can even use the PING opcode that is part of the
|
||||
standard, you must complete a handshake with a specified
|
||||
protocol. By default lws-mirror-protocol is used which is
|
||||
supported by the test server. But if you are using it on
|
||||
another server, you can specify the protcol to handshake with
|
||||
by --protocol=protocolname
|
||||
|
||||
|
||||
Fraggle test app
|
||||
----------------
|
||||
|
||||
By default it runs in server mode
|
||||
|
||||
$ libwebsockets-test-fraggle
|
||||
libwebsockets test fraggle
|
||||
(C) Copyright 2010-2011 Andy Green <andy@warmcat.com> licensed under LGPL2.1
|
||||
Compiled with SSL support, not using it
|
||||
Listening on port 7681
|
||||
server sees client connect
|
||||
accepted v06 connection
|
||||
Spamming 360 random fragments
|
||||
Spamming session over, len = 371913. sum = 0x2D3C0AE
|
||||
Spamming 895 random fragments
|
||||
Spamming session over, len = 875970. sum = 0x6A74DA1
|
||||
...
|
||||
|
||||
You need to run a second session in client mode, you have to
|
||||
give the -c switch and the server address at least:
|
||||
|
||||
$ libwebsockets-test-fraggle -c localhost
|
||||
libwebsockets test fraggle
|
||||
(C) Copyright 2010-2011 Andy Green <andy@warmcat.com> licensed under LGPL2.1
|
||||
Client mode
|
||||
Connecting to localhost:7681
|
||||
denied deflate-stream extension
|
||||
handshake OK for protocol fraggle-protocol
|
||||
client connects to server
|
||||
EOM received 371913 correctly from 360 fragments
|
||||
EOM received 875970 correctly from 895 fragments
|
||||
EOM received 247140 correctly from 258 fragments
|
||||
EOM received 695451 correctly from 692 fragments
|
||||
...
|
||||
|
||||
The fraggle test sends a random number up to 1024 fragmented websocket frames
|
||||
each of a random size between 1 and 2001 bytes in a single message, then sends
|
||||
a checksum and starts sending a new randomly sized and fragmented message.
|
||||
|
||||
The fraggle test client receives the same message fragments and computes the
|
||||
same checksum using websocket framing to see when the message has ended. It
|
||||
then accepts the server checksum message and compares that to its checksum.
|
||||
|
||||
|
||||
proxy support
|
||||
-------------
|
||||
|
||||
The http_proxy environment variable is respected by the client
|
||||
connection code for both ws:// and wss://. It doesn't support
|
||||
authentication.
|
||||
|
||||
You use it like this
|
||||
|
||||
export http_proxy=myproxy.com:3128
|
||||
libwebsockets-test-client someserver.com
|
||||
|
||||
|
||||
debug logging
|
||||
-------------
|
||||
|
||||
By default logging of severity "notice", "warn" or "err" is enabled to stderr.
|
||||
|
||||
Again by default other logging is comiled in but disabled from printing.
|
||||
|
||||
If you want to eliminate the debug logging below notice in severity, use the
|
||||
--disable-debug configure option to have it removed from the code by the
|
||||
preprocesser.
|
||||
|
||||
If you want to see more detailed debug logs, you can control a bitfield to
|
||||
select which logs types may print using the lws_set_log_level() api, in the
|
||||
test apps you can use -d <number> to control this. The types of logging
|
||||
available are (OR together the numbers to select multiple)
|
||||
|
||||
1 ERR
|
||||
2 WARN
|
||||
4 NOTICE
|
||||
8 INFO
|
||||
16 DEBUG
|
||||
32 PARSER
|
||||
64 HEADER
|
||||
128 EXTENSION
|
||||
256 CLIENT
|
||||
512 LATENCY
|
||||
|
||||
|
||||
Websocket version supported
|
||||
---------------------------
|
||||
|
||||
The final IETF standard is supported for both client and server, protocol
|
||||
version 13.
|
||||
|
||||
|
||||
Latency Tracking
|
||||
----------------
|
||||
|
||||
Since libwebsockets runs using poll() and a single threaded approach, any
|
||||
unexpected latency coming from system calls would be bad news. There's now
|
||||
a latency tracking scheme that can be built in with --with-latency at
|
||||
configure-time, logging the time taken for system calls to complete and if
|
||||
the whole action did complete that time or was deferred.
|
||||
|
||||
You can see the detailed data by enabling logging level 512 (eg, -d 519 on
|
||||
the test server to see that and the usual logs), however even without that
|
||||
the "worst" latency is kept and reported to the logs with NOTICE severity
|
||||
when the context is destroyed.
|
||||
|
||||
Some care is needed interpreting them, if the action completed the first figure
|
||||
(in us) is the time taken for the whole action, which may have retried through
|
||||
the poll loop many times and will depend on network roundtrip times. High
|
||||
figures here don't indicate a problem. The figure in us reported after "lat"
|
||||
in the logging is the time taken by this particular attempt. High figures
|
||||
here may indicate a problem, or if you system is loaded with another app at
|
||||
that time, such as the browser, it may simply indicate the OS gave preferential
|
||||
treatment to the other app during that call.
|
||||
|
||||
621
dependencies/libwebsockets/changelog
vendored
Normal file
621
dependencies/libwebsockets/changelog
vendored
Normal file
@ -0,0 +1,621 @@
|
||||
Changelog
|
||||
---------
|
||||
|
||||
v1.3-chrome37-firefox30
|
||||
=======================
|
||||
|
||||
.gitignore | 1 -
|
||||
CMakeLists.txt | 447 +++--
|
||||
README.build | 35 +-
|
||||
README.coding | 14 +
|
||||
changelog | 66 +
|
||||
cmake/LibwebsocketsConfig.cmake.in | 17 +
|
||||
cmake/LibwebsocketsConfigVersion.cmake.in | 11 +
|
||||
config.h.cmake | 18 +
|
||||
cross-ming.cmake | 31 +
|
||||
cross-openwrt-makefile | 91 +
|
||||
lib/client-handshake.c | 205 ++-
|
||||
lib/client-parser.c | 58 +-
|
||||
lib/client.c | 158 +-
|
||||
lib/context.c | 341 ++++
|
||||
lib/extension-deflate-frame.c | 2 +-
|
||||
lib/extension.c | 178 ++
|
||||
lib/handshake.c | 287 +---
|
||||
lib/lextable.h | 338 ++++
|
||||
lib/libev.c | 175 ++
|
||||
lib/libwebsockets.c | 2089 +++--------------------
|
||||
lib/libwebsockets.h | 253 ++-
|
||||
lib/lws-plat-unix.c | 404 +++++
|
||||
lib/lws-plat-win.c | 358 ++++
|
||||
lib/minilex.c | 530 +++---
|
||||
lib/output.c | 445 ++---
|
||||
lib/parsers.c | 682 ++++----
|
||||
lib/pollfd.c | 239 +++
|
||||
lib/private-libwebsockets.h | 501 +++++-
|
||||
lib/server-handshake.c | 274 +--
|
||||
lib/server.c | 858 ++++++++--
|
||||
lib/service.c | 517 ++++++
|
||||
lib/sha-1.c | 38 +-
|
||||
lib/ssl-http2.c | 78 +
|
||||
lib/ssl.c | 571 +++++++
|
||||
test-server/attack.sh | 101 +-
|
||||
test-server/test-client.c | 9 +-
|
||||
test-server/test-echo.c | 17 +-
|
||||
test-server/test-fraggle.c | 7 -
|
||||
test-server/test-ping.c | 12 +-
|
||||
test-server/test-server.c | 330 ++--
|
||||
test-server/test.html | 4 +-
|
||||
win32port/client/client.vcxproj | 259 ---
|
||||
win32port/client/client.vcxproj.filters | 39 -
|
||||
.../libwebsocketswin32.vcxproj.filters | 93 -
|
||||
win32port/server/server.vcxproj | 276 ---
|
||||
win32port/server/server.vcxproj.filters | 51 -
|
||||
win32port/win32helpers/gettimeofday.h | 59 +-
|
||||
win32port/win32helpers/netdb.h | 1 -
|
||||
win32port/win32helpers/strings.h | 0
|
||||
win32port/win32helpers/sys/time.h | 1 -
|
||||
win32port/win32helpers/unistd.h | 0
|
||||
win32port/win32helpers/websock-w32.c | 104 --
|
||||
win32port/win32helpers/websock-w32.h | 62 -
|
||||
win32port/win32port.sln | 100 --
|
||||
win32port/zlib/gzio.c | 3 +-
|
||||
55 files changed, 6779 insertions(+), 5059 deletions(-)
|
||||
|
||||
|
||||
User api additions
|
||||
------------------
|
||||
|
||||
POST method is supported
|
||||
|
||||
The protocol 0 / HTTP callback can now get two new kinds of callback,
|
||||
LWS_CALLBACK_HTTP_BODY (in and len are a chunk of the body of the HTTP request)
|
||||
and LWS_CALLBACK_HTTP_BODY_COMPLETION (the expected amount of body has arrived
|
||||
and been passed to the user code already). These callbacks are used with the
|
||||
post method (see the test server for details).
|
||||
|
||||
The period between the HTTP header completion and the completion of the body
|
||||
processing is protected by a 5s timeout.
|
||||
|
||||
The chunks are stored in a malloc'd buffer of size protocols[0].rx_buffer_size.
|
||||
|
||||
|
||||
New server option you can enable from user code
|
||||
LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT allows non-SSL connections to
|
||||
also be accepted on an SSL listening port. It's disabled unless you enable
|
||||
it explicitly.
|
||||
|
||||
|
||||
Two new callbacks are added in protocols[0] that are optional for allowing
|
||||
limited thread access to libwebsockets, LWS_CALLBACK_LOCK_POLL and
|
||||
LWS_CALLBACK_UNLOCK_POLL.
|
||||
|
||||
If you use them, they protect internal and external poll list changes, but if
|
||||
you want to use external thread access to libwebsocket_callback_on_writable()
|
||||
you have to implement your locking here even if you don't use external
|
||||
poll support.
|
||||
|
||||
If you will use another thread for this, take a lot of care about managing
|
||||
your list of live wsi by doing it from ESTABLISHED and CLOSED callbacks
|
||||
(with your own locking).
|
||||
|
||||
If you configure cmake with -DLWS_WITH_LIBEV=1 then the code allowing the libev
|
||||
eventloop instead of the default poll() one will also be compiled in. But to
|
||||
use it, you must also set the LWS_SERVER_OPTION_LIBEV flag on the context
|
||||
creation info struct options member.
|
||||
|
||||
IPV6 is supported and enabled by default except for Windows, you can disable
|
||||
the support at build-time by giving -DLWS_IPV6=, and disable use of it even if
|
||||
compiled in by making sure the flag LWS_SERVER_OPTION_DISABLE_IPV6 is set on
|
||||
the context creation info struct options member.
|
||||
|
||||
You can give LWS_SERVER_OPTION_DISABLE_OS_CA_CERTS option flag to
|
||||
guarantee the OS CAs will not be used, even if that support was selected at
|
||||
build-time.
|
||||
|
||||
Optional "token limits" may be enforced by setting the member "token_limits"
|
||||
in struct lws_context_creation_info to point to a struct lws_token_limits.
|
||||
NULL means no token limits used for compatibility.
|
||||
|
||||
|
||||
User api changes
|
||||
----------------
|
||||
|
||||
Extra optional argument to libwebsockets_serve_http_file() allows injecion
|
||||
of HTTP headers into the canned response. Eg, cookies may be added like
|
||||
that without getting involved in having to send the header by hand.
|
||||
|
||||
A new info member http_proxy_address may be used at context creation time to
|
||||
set the http proxy. If non-NULL, it overrides http_proxy environment var.
|
||||
|
||||
Cmake supports LWS_SSL_CLIENT_USE_OS_CA_CERTS defaulting to on, which gets
|
||||
the client to use the OS CA Roots. If you're worried somebody with the
|
||||
ability to forge for force creation of a client cert from the root CA in
|
||||
your OS, you should disable this since your selfsigned $0 cert is a lot safer
|
||||
then...
|
||||
|
||||
|
||||
v1.23-chrome32-firefox24
|
||||
========================
|
||||
|
||||
Android.mk | 29 +
|
||||
CMakeLists.txt | 573 ++++++++----
|
||||
COPYING | 503 -----------
|
||||
INSTALL | 365 --------
|
||||
Makefile.am | 13 -
|
||||
README.build | 371 ++------
|
||||
README.coding | 63 ++
|
||||
autogen.sh | 1578 ---------------------------------
|
||||
changelog | 69 ++
|
||||
cmake/FindGit.cmake | 163 ++++
|
||||
cmake/FindOpenSSLbins.cmake | 15 +-
|
||||
cmake/UseRPMTools.cmake | 176 ++++
|
||||
config.h.cmake | 25 +-
|
||||
configure.ac | 226 -----
|
||||
cross-arm-linux-gnueabihf.cmake | 28 +
|
||||
lib/Makefile.am | 89 --
|
||||
lib/base64-decode.c | 98 +-
|
||||
lib/client-handshake.c | 123 ++-
|
||||
lib/client-parser.c | 19 +-
|
||||
lib/client.c | 145 ++-
|
||||
lib/daemonize.c | 4 +-
|
||||
lib/extension.c | 2 +-
|
||||
lib/getifaddrs.h | 4 +-
|
||||
lib/handshake.c | 76 +-
|
||||
lib/libwebsockets.c | 491 ++++++----
|
||||
lib/libwebsockets.h | 164 ++--
|
||||
lib/output.c | 214 ++++-
|
||||
lib/parsers.c | 102 +--
|
||||
lib/private-libwebsockets.h | 66 +-
|
||||
lib/server-handshake.c | 5 +-
|
||||
lib/server.c | 29 +-
|
||||
lib/sha-1.c | 2 +-
|
||||
libwebsockets-api-doc.html | 249 +++---
|
||||
libwebsockets.pc.in | 11 -
|
||||
libwebsockets.spec | 14 +-
|
||||
m4/ignore-me | 2 -
|
||||
scripts/FindLibWebSockets.cmake | 33 +
|
||||
scripts/kernel-doc | 1 +
|
||||
test-server/Makefile.am | 131 ---
|
||||
test-server/leaf.jpg | Bin 0 -> 2477518 bytes
|
||||
test-server/test-client.c | 78 +-
|
||||
test-server/test-echo.c | 33 +-
|
||||
test-server/test-fraggle.c | 26 +-
|
||||
test-server/test-ping.c | 15 +-
|
||||
test-server/test-server.c | 197 +++-
|
||||
test-server/test.html | 5 +-
|
||||
win32port/win32helpers/gettimeofday.c | 74 +-
|
||||
win32port/win32helpers/websock-w32.h | 6 +-
|
||||
48 files changed, 2493 insertions(+), 4212 deletions(-)
|
||||
|
||||
|
||||
User api additions
|
||||
------------------
|
||||
|
||||
- You can now call libwebsocket_callback_on_writable() on http connectons,
|
||||
and get a LWS_CALLBACK_HTTP_WRITEABLE callback, the same way you can
|
||||
regulate writes with a websocket protocol connection.
|
||||
|
||||
- A new member in the context creation parameter struct "ssl_cipher_list" is
|
||||
added, replacing CIPHERS_LIST_STRING. NULL means use the ssl library
|
||||
default list of ciphers.
|
||||
|
||||
- Not really an api addition, but libwebsocket_service_fd() will now zero
|
||||
the revents field of the pollfd it was called with if it handled the
|
||||
descriptor. So you can tell if it is a non-lws fd by checking revents
|
||||
after the service call... if it's still nonzero, the descriptor
|
||||
belongs to you and you need to take care of it.
|
||||
|
||||
- libwebsocket_rx_flow_allow_all_protocol(protocol) will unthrottle all
|
||||
connections with the established protocol. It's designed to be
|
||||
called from user server code when it sees it can accept more input
|
||||
and may have throttled connections using the server rx flow apis
|
||||
while it was unable to accept any other input The user server code
|
||||
then does not have to try to track while connections it choked, this
|
||||
will free up all of them in one call.
|
||||
|
||||
- there's a new, optional callback LWS_CALLBACK_CLOSED_HTTP which gets
|
||||
called when an HTTP protocol socket closes
|
||||
|
||||
- for LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION callback, the user_space alloc
|
||||
has already been done before the callback happens. That means we can
|
||||
use the user parameter to the callback to contain the user pointer, and
|
||||
move the protocol name to the "in" parameter. The docs for this
|
||||
callback are also updated to reflect how to check headers in there.
|
||||
|
||||
- libwebsocket_client_connect() is now properly nonblocking and async. See
|
||||
README.coding and test-client.c for information on the callbacks you
|
||||
can rely on controlling the async connection period with.
|
||||
|
||||
- if your OS does not support the http_proxy environment variable convention
|
||||
(eg, reportedly OSX), you can use a new api libwebsocket_set_proxy()
|
||||
to set the proxy details inbetween context creation and the connection
|
||||
action. For OSes that support http_proxy, that's used automatically.
|
||||
|
||||
User api changes
|
||||
----------------
|
||||
|
||||
- the external poll callbacks now get the socket descriptor coming from the
|
||||
"in" parameter. The user parameter provides the user_space for the
|
||||
wsi as it normally does on the other callbacks.
|
||||
LWS_CALLBACK_FILTER_NETWORK_CONNECTION also has the socket descriptor
|
||||
delivered by @in now instead of @user.
|
||||
|
||||
- libwebsocket_write() now returns -1 for error, or the amount of data
|
||||
actually accepted for send. Under load, the OS may signal it is
|
||||
ready to send new data on the socket, but have only a restricted
|
||||
amount of memory to buffer the packet compared to usual.
|
||||
|
||||
|
||||
User api removal
|
||||
----------------
|
||||
|
||||
- libwebsocket_ensure_user_space() is removed from the public api, if you
|
||||
were using it to get user_space, you need to adapt your code to only
|
||||
use user_space inside the user callback.
|
||||
|
||||
- CIPHERS_LIST_STRING is removed
|
||||
|
||||
- autotools build has been removed. See README.build for info on how to
|
||||
use CMake for your platform
|
||||
|
||||
|
||||
v1.21-chrome26-firefox18
|
||||
========================
|
||||
|
||||
- Fixes buffer overflow bug in max frame size handling if you used the
|
||||
default protocol buffer size. If you declared rx_buffer_size in your
|
||||
protocol, which is recommended anyway, your code was unaffected.
|
||||
|
||||
v1.2-chrome26-firefox18
|
||||
=======================
|
||||
|
||||
Diffstat
|
||||
--------
|
||||
|
||||
.gitignore | 16 +++
|
||||
CMakeLists.txt | 544 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
LICENSE | 526 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
Makefile.am | 1 +
|
||||
README | 20 +++
|
||||
README.build | 258 ++++++++++++++++++++++++++++++++-----
|
||||
README.coding | 52 ++++++++
|
||||
changelog | 136 ++++++++++++++++++++
|
||||
cmake/FindOpenSSLbins.cmake | 33 +++++
|
||||
config.h.cmake | 173 +++++++++++++++++++++++++
|
||||
configure.ac | 22 +++-
|
||||
lib/Makefile.am | 20 ++-
|
||||
lib/base64-decode.c | 2 +-
|
||||
lib/client-handshake.c | 190 +++++++++++-----------------
|
||||
lib/client-parser.c | 88 +++++++------
|
||||
lib/client.c | 384 ++++++++++++++++++++++++++++++-------------------------
|
||||
lib/daemonize.c | 32 +++--
|
||||
lib/extension-deflate-frame.c | 58 +++++----
|
||||
lib/extension-deflate-stream.c | 19 ++-
|
||||
lib/extension-deflate-stream.h | 4 +-
|
||||
lib/extension.c | 11 +-
|
||||
lib/getifaddrs.c | 315 +++++++++++++++++++++++-----------------------
|
||||
lib/getifaddrs.h | 30 ++---
|
||||
lib/handshake.c | 124 +++++++++++-------
|
||||
lib/libwebsockets.c | 736 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------------------
|
||||
lib/libwebsockets.h | 237 ++++++++++++++++++++++------------
|
||||
lib/output.c | 192 +++++++++++-----------------
|
||||
lib/parsers.c | 966 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------------------------------------------
|
||||
lib/private-libwebsockets.h | 225 +++++++++++++++++++++------------
|
||||
lib/server-handshake.c | 82 ++++++------
|
||||
lib/server.c | 96 +++++++-------
|
||||
libwebsockets-api-doc.html | 189 ++++++++++++++++++----------
|
||||
libwebsockets.spec | 17 +--
|
||||
test-server/attack.sh | 148 ++++++++++++++++++++++
|
||||
test-server/test-client.c | 125 +++++++++---------
|
||||
test-server/test-echo.c | 31 +++--
|
||||
test-server/test-fraggle.c | 32 ++---
|
||||
test-server/test-ping.c | 52 ++++----
|
||||
test-server/test-server.c | 129 ++++++++++++-------
|
||||
win32port/libwebsocketswin32/libwebsocketswin32.vcxproj | 279 ----------------------------------------
|
||||
win32port/libwebsocketswin32/libwebsocketswin32.vcxproj.filters | 23 +++-
|
||||
41 files changed, 4398 insertions(+), 2219 deletions(-)
|
||||
|
||||
|
||||
User api additions
|
||||
------------------
|
||||
|
||||
- lws_get_library_version() returns a const char * with a string like
|
||||
"1.1 9e7f737", representing the library version from configure.ac
|
||||
and the git HEAD hash the library was built from
|
||||
|
||||
- TCP Keepalive can now optionally be applied to all lws sockets, on Linux
|
||||
also with controllable timeout, number of probes and probe interval.
|
||||
(On BSD type OS, you can only use system default settings for the
|
||||
timing and retries, although enabling it is supported by setting
|
||||
ka_time to nonzero, the exact value has no meaning.)
|
||||
This enables detection of idle connections which are logically okay,
|
||||
but are in fact dead, due to network connectivity issues at the server,
|
||||
client, or any intermediary. By default it's not enabled, but you
|
||||
can enable it by setting a non-zero timeout (in seconds) at the new
|
||||
ka_time member at context creation time.
|
||||
|
||||
- Two new optional user callbacks added, LWS_CALLBACK_PROTOCOL_DESTROY which
|
||||
is called one-time per protocol as the context is being destroyed, and
|
||||
LWS_CALLBACK_PROTOCOL_INIT which is called when the context is created
|
||||
and the protocols are added, again it's a one-time affair.
|
||||
This lets you manage per-protocol allocations properly including
|
||||
cleaning up after yourself when the server goes down.
|
||||
|
||||
User api changes
|
||||
----------------
|
||||
|
||||
- libwebsocket_create_context() has changed from taking a ton of parameters
|
||||
to just taking a pointer to a struct containing the parameters. The
|
||||
struct lws_context_creation_info is in libwebsockets.h, the members
|
||||
are in the same order as when they were parameters to the call
|
||||
previously. The test apps are all updated accordingly so you can
|
||||
see example code there.
|
||||
|
||||
- Header tokens are now deleted after the websocket connection is
|
||||
established. Not just the header data is saved, but the pointer and
|
||||
length array is also removed from (union) scope saving several hundred
|
||||
bytes per connection once it is established
|
||||
|
||||
- struct libwebsocket_protocols has a new member rx_buffer_size, this
|
||||
controls rx buffer size per connection of that protocol now. Sources
|
||||
for apps built against older versions of the library won't declare
|
||||
this in their protocols, defaulting it to 0. Zero buffer is legal,
|
||||
it causes a default buffer to be allocated (currently 4096)
|
||||
|
||||
If you want to receive only atomic frames in your user callback, you
|
||||
should set this to greater than your largest frame size. If a frame
|
||||
comes that exceeds that, no error occurs but the callback happens as
|
||||
soon as the buffer limit is reached, and again if it is reached again
|
||||
or the frame completes. You can detect that has happened by seeing
|
||||
there is still frame content pending using
|
||||
libwebsockets_remaining_packet_payload()
|
||||
|
||||
By correctly setting this, you can save a lot of memory when your
|
||||
protocol has small frames (see the test server and client sources).
|
||||
|
||||
- LWS_MAX_HEADER_LEN now defaults to 1024 and is the total amount of known
|
||||
header payload lws can cope with, that includes the GET URL, origin
|
||||
etc. Headers not understood by lws are ignored and their payload
|
||||
not included in this.
|
||||
|
||||
|
||||
User api removals
|
||||
-----------------
|
||||
|
||||
- The configuration-time option MAX_USER_RX_BUFFER has been replaced by a
|
||||
buffer size chosen per-protocol. For compatibility, there's a default
|
||||
of 4096 rx buffer, but user code should set the appropriate size for
|
||||
the protocol frames.
|
||||
|
||||
- LWS_INITIAL_HDR_ALLOC and LWS_ADDITIONAL_HDR_ALLOC are no longer needed
|
||||
and have been removed. There's a new header management scheme that
|
||||
handles them in a much more compact way.
|
||||
|
||||
- libwebsockets_hangup_on_client() is removed. If you want to close the
|
||||
connection you must do so from the user callback and by returning
|
||||
-1 from there.
|
||||
|
||||
- libwebsocket_close_and_free_session() is now private to the library code
|
||||
only and not exposed for user code. If you want to close the
|
||||
connection, you must do so from the user callback by returning -1
|
||||
from there.
|
||||
|
||||
|
||||
New features
|
||||
------------
|
||||
|
||||
- Cmake project file added, aimed initially at Windows support: this replaces
|
||||
the visual studio project files that were in the tree until now.
|
||||
|
||||
- CyaSSL now supported in place of OpenSSL (--use-cyassl on configure)
|
||||
|
||||
- PATH_MAX or MAX_PATH no longer needed
|
||||
|
||||
- cutomizable frame rx buffer size by protocol
|
||||
|
||||
- optional TCP keepalive so dead peers can be detected, can be enabled at
|
||||
context-creation time
|
||||
|
||||
- valgrind-clean: no SSL or CyaSSL: completely clean. With OpenSSL, 88 bytes
|
||||
lost at OpenSSL library init and symptomless reports of uninitialized
|
||||
memory usage... seems to be a known and ignored problem at OpenSSL
|
||||
|
||||
- By default debug is enabled and the library is built for -O0 -g to faclitate
|
||||
that. Use --disable-debug configure option to build instead with -O4
|
||||
and no -g (debug info), obviously providing best performance and
|
||||
reduced binary size.
|
||||
|
||||
- 1.0 introduced some code to try to not deflate small frames, however this
|
||||
seems to break when confronted with a mixture of frames above and
|
||||
below the threshold, so it's removed. Veto the compression extension
|
||||
in your user callback if you will typically have very small frames.
|
||||
|
||||
- There are many memory usage improvements, both a reduction in malloc/
|
||||
realloc and architectural changes. A websocket connection now
|
||||
consumes only 296 bytes with SSL or 272 bytes without on x86_64,
|
||||
during header processing an additional 1262 bytes is allocated in a
|
||||
single malloc, but is freed when the websocket connection starts.
|
||||
The RX frame buffer defined by the protocol in user
|
||||
code is also allocated per connection, this represents the largest
|
||||
frame you can receive atomically in that protocol.
|
||||
|
||||
- On ARM9 build, just http+ws server no extensions or ssl, <12Kbytes .text
|
||||
and 112 bytes per connection (+1328 only during header processing)
|
||||
|
||||
|
||||
v1.1-chrome26-firefox18
|
||||
=======================
|
||||
|
||||
Diffstat
|
||||
--------
|
||||
|
||||
Makefile.am | 4 +
|
||||
README-test-server | 291 ---
|
||||
README.build | 239 ++
|
||||
README.coding | 138 ++
|
||||
README.rst | 72 -
|
||||
README.test-apps | 272 +++
|
||||
configure.ac | 116 +-
|
||||
lib/Makefile.am | 55 +-
|
||||
lib/base64-decode.c | 5 +-
|
||||
lib/client-handshake.c | 121 +-
|
||||
lib/client-parser.c | 394 ++++
|
||||
lib/client.c | 807 +++++++
|
||||
lib/daemonize.c | 212 ++
|
||||
lib/extension-deflate-frame.c | 132 +-
|
||||
lib/extension-deflate-stream.c | 12 +-
|
||||
lib/extension-x-google-mux.c | 1223 ----------
|
||||
lib/extension-x-google-mux.h | 96 -
|
||||
lib/extension.c | 8 -
|
||||
lib/getifaddrs.c | 271 +++
|
||||
lib/getifaddrs.h | 76 +
|
||||
lib/handshake.c | 582 +----
|
||||
lib/libwebsockets.c | 2493 ++++++---------------
|
||||
lib/libwebsockets.h | 115 +-
|
||||
lib/md5.c | 217 --
|
||||
lib/minilex.c | 440 ++++
|
||||
lib/output.c | 628 ++++++
|
||||
lib/parsers.c | 2016 +++++------------
|
||||
lib/private-libwebsockets.h | 284 +--
|
||||
lib/server-handshake.c | 275 +++
|
||||
lib/server.c | 377 ++++
|
||||
libwebsockets-api-doc.html | 300 +--
|
||||
m4/ignore-me | 2 +
|
||||
test-server/Makefile.am | 111 +-
|
||||
test-server/libwebsockets.org-logo.png | Bin 0 -> 7029 bytes
|
||||
test-server/test-client.c | 45 +-
|
||||
test-server/test-echo.c | 330 +++
|
||||
test-server/test-fraggle.c | 20 +-
|
||||
test-server/test-ping.c | 22 +-
|
||||
test-server/test-server-extpoll.c | 554 -----
|
||||
test-server/test-server.c | 349 ++-
|
||||
test-server/test.html | 3 +-
|
||||
win32port/zlib/ZLib.vcxproj | 749 ++++---
|
||||
win32port/zlib/ZLib.vcxproj.filters | 188 +-
|
||||
win32port/zlib/adler32.c | 348 ++-
|
||||
win32port/zlib/compress.c | 160 +-
|
||||
win32port/zlib/crc32.c | 867 ++++----
|
||||
win32port/zlib/crc32.h | 882 ++++----
|
||||
win32port/zlib/deflate.c | 3799 +++++++++++++++-----------------
|
||||
win32port/zlib/deflate.h | 688 +++---
|
||||
win32port/zlib/gzclose.c | 50 +-
|
||||
win32port/zlib/gzguts.h | 325 ++-
|
||||
win32port/zlib/gzlib.c | 1157 +++++-----
|
||||
win32port/zlib/gzread.c | 1242 ++++++-----
|
||||
win32port/zlib/gzwrite.c | 1096 +++++----
|
||||
win32port/zlib/infback.c | 1272 ++++++-----
|
||||
win32port/zlib/inffast.c | 680 +++---
|
||||
win32port/zlib/inffast.h | 22 +-
|
||||
win32port/zlib/inffixed.h | 188 +-
|
||||
win32port/zlib/inflate.c | 2976 +++++++++++++------------
|
||||
win32port/zlib/inflate.h | 244 +-
|
||||
win32port/zlib/inftrees.c | 636 +++---
|
||||
win32port/zlib/inftrees.h | 124 +-
|
||||
win32port/zlib/trees.c | 2468 +++++++++++----------
|
||||
win32port/zlib/trees.h | 256 +--
|
||||
win32port/zlib/uncompr.c | 118 +-
|
||||
win32port/zlib/zconf.h | 934 ++++----
|
||||
win32port/zlib/zlib.h | 3357 ++++++++++++++--------------
|
||||
win32port/zlib/zutil.c | 642 +++---
|
||||
win32port/zlib/zutil.h | 526 ++---
|
||||
69 files changed, 19556 insertions(+), 20145 deletions(-)
|
||||
|
||||
user api changes
|
||||
----------------
|
||||
|
||||
- libwebsockets_serve_http_file() now takes a context as first argument
|
||||
|
||||
- libwebsockets_get_peer_addresses() now takes a context and wsi as first
|
||||
two arguments
|
||||
|
||||
|
||||
user api additions
|
||||
------------------
|
||||
|
||||
- lwsl_...() logging apis, default to stderr but retargetable by user code;
|
||||
may be used also by user code
|
||||
|
||||
- lws_set_log_level() set which logging apis are able to emit (defaults to
|
||||
notice, warn, err severities), optionally set the emit callback
|
||||
|
||||
- lwsl_emit_syslog() helper callback emits to syslog
|
||||
|
||||
- lws_daemonize() helper code that forks the app into a headless daemon
|
||||
properly, maintains a lock file with pid in suitable for sysvinit etc to
|
||||
control lifecycle
|
||||
|
||||
- LWS_CALLBACK_HTTP_FILE_COMPLETION callback added since http file
|
||||
transfer is now asynchronous (see test server code)
|
||||
|
||||
- lws_frame_is_binary() from a wsi pointer, let you know if the received
|
||||
data was sent in BINARY mode
|
||||
|
||||
|
||||
user api removals
|
||||
-----------------
|
||||
|
||||
- libwebsockets_fork_service_loop() - no longer supported (had intractable problems)
|
||||
arrange your code to act from the user callback instead from same
|
||||
process context as the service loop
|
||||
|
||||
- libwebsockets_broadcast() - use libwebsocket_callback_on_writable[_all_protocol]()
|
||||
instead from same process context as the service loop. See the test apps
|
||||
for examples.
|
||||
|
||||
- x-google-mux() removed until someone wants it
|
||||
|
||||
- pre -v13 (ancient) protocol support removed
|
||||
|
||||
|
||||
New features
|
||||
------------
|
||||
|
||||
- echo test server and client compatible with echo.websocket.org added
|
||||
|
||||
- many new configure options (see README.build) to reduce footprint of the
|
||||
library to what you actually need, eg, --without-client and
|
||||
--without-server
|
||||
|
||||
- http + websocket server can build to as little as 12K .text for ARM
|
||||
|
||||
- no more MAX_CLIENTS limitation; adapts to support the max number of fds
|
||||
allowed to the process by ulimit, defaults to 1024 on Fedora and
|
||||
Ubuntu. Use ulimit to control this without needing to configure
|
||||
the library. Code here is smaller and faster.
|
||||
|
||||
- adaptive ratio of listen socket to connection socket service allows
|
||||
good behaviour under Apache ab test load. Tested with thousands
|
||||
of simultaneous connections
|
||||
|
||||
- reduction in per-connection memory footprint by moving to a union to hold
|
||||
mutually-exclusive state for the connection
|
||||
|
||||
- robustness: Out of Memory taken care of for all allocation code now
|
||||
|
||||
- internal getifaddrs option if your toolchain lacks it (some uclibc)
|
||||
|
||||
- configurable memory limit for deflate operations
|
||||
|
||||
- improvements in SSL code nonblocking operation, possible hang solved,
|
||||
some SSL operations broken down into pollable states so there is
|
||||
no library blocking, timeout coverage for SSL_connect
|
||||
|
||||
- extpoll test server merged into single test server source
|
||||
|
||||
- robustness: library should deal with all recoverable socket conditions
|
||||
|
||||
- rx flowcontrol for backpressure notification fixed and implmeneted
|
||||
correctly in the test server
|
||||
|
||||
- optimal lexical parser added for header processing; all headers in a
|
||||
single 276-byte state table
|
||||
|
||||
- latency tracking api added (configure --with-latency)
|
||||
|
||||
- Improved in-tree documentation, REAME.build, README.coding,
|
||||
README.test-apps, changelog
|
||||
|
||||
- Many small fixes
|
||||
|
||||
|
||||
v1.0-chrome25-firefox17 (6cd1ea9b005933f)
|
||||
163
dependencies/libwebsockets/cmake/FindGit.cmake
vendored
Normal file
163
dependencies/libwebsockets/cmake/FindGit.cmake
vendored
Normal file
@ -0,0 +1,163 @@
|
||||
################################################################################
|
||||
#
|
||||
# Program: 3D Slicer
|
||||
#
|
||||
# Copyright (c) Kitware Inc.
|
||||
#
|
||||
# See COPYRIGHT.txt
|
||||
# or http://www.slicer.org/copyright/copyright.txt for details.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# This file was originally developed by Jean-Christophe Fillion-Robin, Kitware Inc.
|
||||
# and was partially funded by NIH grant 3P41RR013218-12S1
|
||||
#
|
||||
# AG 2013-02-18: I got it from here
|
||||
# https://github.com/Slicer/Slicer/blob/master/CMake/FindGit.cmake
|
||||
# license is BSD
|
||||
#
|
||||
################################################################################
|
||||
|
||||
#
|
||||
# The module defines the following variables:
|
||||
# GIT_EXECUTABLE - path to git command line client
|
||||
# GIT_FOUND - true if the command line client was found
|
||||
#
|
||||
# If the command line client executable is found the macro
|
||||
# GIT_WC_INFO(<dir> <var-prefix>)
|
||||
# is defined to extract information of a git working copy at
|
||||
# a given location.
|
||||
#
|
||||
# The macro defines the following variables:
|
||||
# <var-prefix>_WC_REVISION_HASH - Current SHA1 hash
|
||||
# <var-prefix>_WC_REVISION - Current SHA1 hash
|
||||
# <var-prefix>_WC_REVISION_NAME - Name associated with <var-prefix>_WC_REVISION_HASH
|
||||
# <var-prefix>_WC_URL - output of command `git config --get remote.origin.url'
|
||||
# <var-prefix>_WC_ROOT - Same value as working copy URL
|
||||
# <var-prefix>_WC_GITSVN - Set to false
|
||||
#
|
||||
# ... and also the following ones if it's a git-svn repository:
|
||||
# <var-prefix>_WC_GITSVN - Set to True if it is a
|
||||
# <var-prefix>_WC_INFO - output of command `git svn info'
|
||||
# <var-prefix>_WC_URL - url of the associated SVN repository
|
||||
# <var-prefix>_WC_ROOT - root url of the associated SVN repository
|
||||
# <var-prefix>_WC_REVISION - current SVN revision number
|
||||
# <var-prefix>_WC_LAST_CHANGED_AUTHOR - author of last commit
|
||||
# <var-prefix>_WC_LAST_CHANGED_DATE - date of last commit
|
||||
# <var-prefix>_WC_LAST_CHANGED_REV - revision of last commit
|
||||
# <var-prefix>_WC_LAST_CHANGED_LOG - last log of base revision
|
||||
#
|
||||
# Example usage:
|
||||
# find_package(Git)
|
||||
# if(GIT_FOUND)
|
||||
# GIT_WC_INFO(${PROJECT_SOURCE_DIR} Project)
|
||||
# message("Current revision is ${Project_WC_REVISION_HASH}")
|
||||
# message("git found: ${GIT_EXECUTABLE}")
|
||||
# endif()
|
||||
#
|
||||
|
||||
# Look for 'git' or 'eg' (easy git)
|
||||
#
|
||||
set(git_names git eg)
|
||||
|
||||
# Prefer .cmd variants on Windows unless running in a Makefile
|
||||
# in the MSYS shell.
|
||||
#
|
||||
if(WIN32)
|
||||
if(NOT CMAKE_GENERATOR MATCHES "MSYS")
|
||||
# Note: Due to a bug in 'git.cmd' preventing it from returning the exit code of 'git',
|
||||
# we excluded it from the list of executables to search.
|
||||
# See http://code.google.com/p/msysgit/issues/detail?id=428
|
||||
# TODO Check if 'git' exists, get the associated version, if the corresponding version
|
||||
# is known to have a working version of 'git.cmd', use it.
|
||||
set(git_names git eg.cmd eg)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_program(GIT_EXECUTABLE ${git_names}
|
||||
PATHS
|
||||
"C:/Program Files/Git/bin"
|
||||
"C:/Program Files (x86)/Git/bin"
|
||||
DOC "git command line client")
|
||||
mark_as_advanced(GIT_EXECUTABLE)
|
||||
|
||||
if(GIT_EXECUTABLE)
|
||||
macro(GIT_WC_INFO dir prefix)
|
||||
execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse --verify -q --short=7 HEAD
|
||||
WORKING_DIRECTORY ${dir}
|
||||
ERROR_VARIABLE GIT_error
|
||||
OUTPUT_VARIABLE ${prefix}_WC_REVISION_HASH
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
set(${prefix}_WC_REVISION ${${prefix}_WC_REVISION_HASH})
|
||||
if(NOT ${GIT_error} EQUAL 0)
|
||||
message(SEND_ERROR "Command \"${GIT_EXECUTBALE} rev-parse --verify -q --short=7 HEAD\" in directory ${dir} failed with output:\n${GIT_error}")
|
||||
else(NOT ${GIT_error} EQUAL 0)
|
||||
execute_process(COMMAND ${GIT_EXECUTABLE} name-rev ${${prefix}_WC_REVISION_HASH}
|
||||
WORKING_DIRECTORY ${dir}
|
||||
OUTPUT_VARIABLE ${prefix}_WC_REVISION_NAME
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
endif(NOT ${GIT_error} EQUAL 0)
|
||||
|
||||
execute_process(COMMAND ${GIT_EXECUTABLE} config --get remote.origin.url
|
||||
WORKING_DIRECTORY ${dir}
|
||||
OUTPUT_VARIABLE ${prefix}_WC_URL
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
set(${prefix}_WC_GITSVN False)
|
||||
|
||||
# Check if this git is likely to be a git-svn repository
|
||||
execute_process(COMMAND ${GIT_EXECUTABLE} config --get-regexp "^svn-remote"
|
||||
WORKING_DIRECTORY ${dir}
|
||||
OUTPUT_VARIABLE git_config_output
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
if(NOT "${git_config_output}" STREQUAL "")
|
||||
# In case git-svn is used, attempt to extract svn info
|
||||
execute_process(COMMAND ${GIT_EXECUTABLE} svn info
|
||||
WORKING_DIRECTORY ${dir}
|
||||
TIMEOUT 3
|
||||
ERROR_VARIABLE git_svn_info_error
|
||||
OUTPUT_VARIABLE ${prefix}_WC_INFO
|
||||
RESULT_VARIABLE git_svn_info_result
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
if(${git_svn_info_result} EQUAL 0)
|
||||
set(${prefix}_WC_GITSVN True)
|
||||
string(REGEX REPLACE "^(.*\n)?URL: ([^\n]+).*"
|
||||
"\\2" ${prefix}_WC_URL "${${prefix}_WC_INFO}")
|
||||
string(REGEX REPLACE "^(.*\n)?Revision: ([^\n]+).*"
|
||||
"\\2" ${prefix}_WC_REVISION "${${prefix}_WC_INFO}")
|
||||
string(REGEX REPLACE "^(.*\n)?Repository Root: ([^\n]+).*"
|
||||
"\\2" ${prefix}_WC_ROOT "${${prefix}_WC_INFO}")
|
||||
string(REGEX REPLACE "^(.*\n)?Last Changed Author: ([^\n]+).*"
|
||||
"\\2" ${prefix}_WC_LAST_CHANGED_AUTHOR "${${prefix}_WC_INFO}")
|
||||
string(REGEX REPLACE "^(.*\n)?Last Changed Rev: ([^\n]+).*"
|
||||
"\\2" ${prefix}_WC_LAST_CHANGED_REV "${${prefix}_WC_INFO}")
|
||||
string(REGEX REPLACE "^(.*\n)?Last Changed Date: ([^\n]+).*"
|
||||
"\\2" ${prefix}_WC_LAST_CHANGED_DATE "${${prefix}_WC_INFO}")
|
||||
endif(${git_svn_info_result} EQUAL 0)
|
||||
endif(NOT "${git_config_output}" STREQUAL "")
|
||||
|
||||
# If there is no 'remote.origin', default to "NA" value and print a warning message.
|
||||
if(NOT ${prefix}_WC_URL)
|
||||
message(WARNING "No remote origin set for git repository: ${dir}" )
|
||||
set( ${prefix}_WC_URL "NA" )
|
||||
else()
|
||||
set(${prefix}_WC_ROOT ${${prefix}_WC_URL})
|
||||
endif()
|
||||
|
||||
endmacro(GIT_WC_INFO)
|
||||
endif(GIT_EXECUTABLE)
|
||||
|
||||
# Handle the QUIETLY and REQUIRED arguments and set GIT_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Git DEFAULT_MSG GIT_EXECUTABLE)
|
||||
|
||||
|
||||
42
dependencies/libwebsockets/cmake/FindOpenSSLbins.cmake
vendored
Normal file
42
dependencies/libwebsockets/cmake/FindOpenSSLbins.cmake
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
|
||||
if(OPENSSL_FOUND)
|
||||
|
||||
find_program(OPENSSL_EXECUTABLE openssl openssl.exe bin/openssl.exe
|
||||
HINTS ${_OPENSSL_ROOT_HINTS}
|
||||
PATH
|
||||
/usr/bin/
|
||||
bin/
|
||||
DOC "Openssl executable")
|
||||
|
||||
mark_as_advanced(OPENSSL_EXECUTABLE)
|
||||
|
||||
# On Windows, we need to copy the OpenSSL dlls
|
||||
# to the output directory.
|
||||
if(WIN32)
|
||||
set(OPENSSL_BIN_FOUND 0)
|
||||
|
||||
find_file(LIBEAY_BIN
|
||||
NAMES
|
||||
libeay32.dll
|
||||
HINTS
|
||||
${_OPENSSL_ROOT_HINTS}
|
||||
PATH_SUFFIXES
|
||||
bin)
|
||||
|
||||
find_file(SSLEAY_BIN
|
||||
NAMES
|
||||
ssleay32.dll
|
||||
HINTS
|
||||
${_OPENSSL_ROOT_HINTS}
|
||||
PATH_SUFFIXES
|
||||
bin)
|
||||
|
||||
if(LIBEAY_BIN)
|
||||
if(SSLEAY_BIN)
|
||||
set(OPENSSL_BIN_FOUND 1)
|
||||
endif(SSLEAY_BIN)
|
||||
endif(LIBEAY_BIN)
|
||||
endif(WIN32)
|
||||
|
||||
endif(OPENSSL_FOUND)
|
||||
|
||||
17
dependencies/libwebsockets/cmake/LibwebsocketsConfig.cmake.in
vendored
Normal file
17
dependencies/libwebsockets/cmake/LibwebsocketsConfig.cmake.in
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
# - Config file for the Libevent package
|
||||
# It defines the following variables
|
||||
# LIBWEBSOCKETS_INCLUDE_DIRS - include directories for FooBar
|
||||
# LIBWEBSOCKETS_LIBRARIES - libraries to link against
|
||||
|
||||
# Get the path of the current file.
|
||||
get_filename_component(LWS_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
|
||||
|
||||
# Set the include directories.
|
||||
set(LIBWEBSOCKETS_INCLUDE_DIRS "@LWS__INCLUDE_DIRS@")
|
||||
|
||||
# Include the project Targets file, this contains definitions for IMPORTED targets.
|
||||
include(${LWS_CMAKE_DIR}/LibwebsocketsTargets.cmake)
|
||||
|
||||
# IMPORTED targets from LibwebsocketsTargets.cmake
|
||||
set(LIBWEBSOCKETS_LIBRARIES websockets websockets_shared)
|
||||
|
||||
11
dependencies/libwebsockets/cmake/LibwebsocketsConfigVersion.cmake.in
vendored
Normal file
11
dependencies/libwebsockets/cmake/LibwebsocketsConfigVersion.cmake.in
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
set(PACKAGE_VERSION "@CPACK_PACKAGE_VERSION@")
|
||||
|
||||
# Check whether the requested PACKAGE_FIND_VERSION is compatible
|
||||
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
|
||||
set(PACKAGE_VERSION_COMPATIBLE FALSE)
|
||||
else()
|
||||
set(PACKAGE_VERSION_COMPATIBLE TRUE)
|
||||
if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
|
||||
set(PACKAGE_VERSION_EXACT TRUE)
|
||||
endif()
|
||||
endif()
|
||||
176
dependencies/libwebsockets/cmake/UseRPMTools.cmake
vendored
Normal file
176
dependencies/libwebsockets/cmake/UseRPMTools.cmake
vendored
Normal file
@ -0,0 +1,176 @@
|
||||
#
|
||||
# - Find tools needed for building RPM Packages
|
||||
# on Linux systems and defines macro that helps to
|
||||
# build source or binary RPM, the MACRO assumes
|
||||
# CMake 2.4.x which includes CPack support.
|
||||
# CPack is used to build tar.gz source tarball
|
||||
# which may be used by a custom user-made spec file.
|
||||
#
|
||||
# - Define RPMTools_ADD_RPM_TARGETS which defines
|
||||
# two (top-level) CUSTOM targets for building
|
||||
# source and binary RPMs
|
||||
#
|
||||
# Those CMake macros are provided by the TSP Developer Team
|
||||
# https://savannah.nongnu.org/projects/tsp
|
||||
#
|
||||
|
||||
IF (WIN32)
|
||||
MESSAGE(STATUS "RPM tools not available on Win32 systems")
|
||||
ENDIF(WIN32)
|
||||
|
||||
IF (UNIX)
|
||||
# Look for RPM builder executable
|
||||
FIND_PROGRAM(RPMTools_RPMBUILD_EXECUTABLE
|
||||
NAMES rpmbuild
|
||||
PATHS "/usr/bin;/usr/lib/rpm"
|
||||
PATH_SUFFIXES bin
|
||||
DOC "The RPM builder tool")
|
||||
|
||||
IF (RPMTools_RPMBUILD_EXECUTABLE)
|
||||
MESSAGE(STATUS "Looking for RPMTools... - found rpmuild is ${RPMTools_RPMBUILD_EXECUTABLE}")
|
||||
SET(RPMTools_RPMBUILD_FOUND "YES")
|
||||
GET_FILENAME_COMPONENT(RPMTools_BINARY_DIRS ${RPMTools_RPMBUILD_EXECUTABLE} PATH)
|
||||
ELSE (RPMTools_RPMBUILD_EXECUTABLE)
|
||||
SET(RPMTools_RPMBUILD_FOUND "NO")
|
||||
MESSAGE(STATUS "Looking for RPMTools... - rpmbuild NOT FOUND")
|
||||
ENDIF (RPMTools_RPMBUILD_EXECUTABLE)
|
||||
|
||||
# Detect if CPack was included or not
|
||||
IF (NOT DEFINED "CPACK_PACKAGE_NAME")
|
||||
MESSAGE(FATAL_ERROR "CPack was not included, you should include CPack before Using RPMTools")
|
||||
ENDIF (NOT DEFINED "CPACK_PACKAGE_NAME")
|
||||
|
||||
IF (RPMTools_RPMBUILD_FOUND)
|
||||
SET(RPMTools_FOUND TRUE)
|
||||
#
|
||||
# - first arg (ARGV0) is RPM name
|
||||
# - second arg (ARGV1) is the RPM spec file path [optional]
|
||||
# - third arg (ARGV2) is the RPM ROOT DIRECTORY used to build RPMs [optional]
|
||||
#
|
||||
MACRO(RPMTools_ADD_RPM_TARGETS RPMNAME)
|
||||
|
||||
#
|
||||
# If no spec file is provided create a minimal one
|
||||
#
|
||||
IF ("${ARGV1}" STREQUAL "")
|
||||
SET(SPECFILE_PATH "${CMAKE_BINARY_DIR}/${RPMNAME}.spec")
|
||||
ELSE ("${ARGV1}" STREQUAL "")
|
||||
SET(SPECFILE_PATH "${ARGV1}")
|
||||
ENDIF("${ARGV1}" STREQUAL "")
|
||||
|
||||
# Verify whether if RPM_ROOTDIR was provided or not
|
||||
IF("${ARGV2}" STREQUAL "")
|
||||
SET(RPM_ROOTDIR ${CMAKE_BINARY_DIR}/RPM)
|
||||
ELSE ("${ARGV2}" STREQUAL "")
|
||||
SET(RPM_ROOTDIR "${ARGV2}")
|
||||
ENDIF("${ARGV2}" STREQUAL "")
|
||||
MESSAGE(STATUS "RPMTools:: Using RPM_ROOTDIR=${RPM_ROOTDIR}")
|
||||
|
||||
# Prepare RPM build tree
|
||||
FILE(MAKE_DIRECTORY ${RPM_ROOTDIR})
|
||||
FILE(MAKE_DIRECTORY ${RPM_ROOTDIR}/tmp)
|
||||
FILE(MAKE_DIRECTORY ${RPM_ROOTDIR}/BUILD)
|
||||
FILE(MAKE_DIRECTORY ${RPM_ROOTDIR}/RPMS)
|
||||
FILE(MAKE_DIRECTORY ${RPM_ROOTDIR}/SOURCES)
|
||||
FILE(MAKE_DIRECTORY ${RPM_ROOTDIR}/SPECS)
|
||||
FILE(MAKE_DIRECTORY ${RPM_ROOTDIR}/SRPMS)
|
||||
|
||||
#
|
||||
# We check whether if the provided spec file is
|
||||
# to be configure or not.
|
||||
#
|
||||
IF ("${ARGV1}" STREQUAL "")
|
||||
SET(SPECFILE_PATH "${RPM_ROOTDIR}/SPECS/${RPMNAME}.spec")
|
||||
SET(SPECFILE_NAME "${RPMNAME}.spec")
|
||||
MESSAGE(STATUS "No Spec file given generate a minimal one --> ${RPM_ROOTDIR}/SPECS/${RPMNAME}.spec")
|
||||
FILE(WRITE ${RPM_ROOTDIR}/SPECS/${RPMNAME}.spec
|
||||
"# -*- rpm-spec -*-
|
||||
Summary: ${RPMNAME}
|
||||
Name: ${RPMNAME}
|
||||
Version: ${CPACK_PACKAGE_VERSION}
|
||||
Release: 1
|
||||
License: Unknown
|
||||
Group: Unknown
|
||||
Source: ${CPACK_SOURCE_PACKAGE_FILE_NAME}.tar.gz
|
||||
BuildRoot: %{_tmppath}/%{name}-%{CPACK_PACKAGE_VERSION}-1-root
|
||||
BuildRequires: cmake
|
||||
|
||||
%define prefix /opt/${RPMNAME}-%{version}
|
||||
%define rpmprefix $RPM_BUILD_ROOT%{prefix}
|
||||
%define srcdirname %{name}-%{version}
|
||||
|
||||
%description
|
||||
${RPMNAME} : No description for now
|
||||
|
||||
%prep
|
||||
%setup -q -n %{srcdirname}
|
||||
|
||||
%build
|
||||
cd ..
|
||||
rm -rf build_tree
|
||||
mkdir build_tree
|
||||
cd build_tree
|
||||
cmake -DCMAKE_INSTALL_PREFIX=%{rpmprefix} ../%{srcdirname}
|
||||
make
|
||||
|
||||
%install
|
||||
cd ../build_tree
|
||||
make install
|
||||
|
||||
%clean
|
||||
rm -rf %{srcdirname}
|
||||
rm -rf build_tree
|
||||
|
||||
%files
|
||||
%defattr(-,root,root,-)
|
||||
%dir %{prefix}
|
||||
%{prefix}/*
|
||||
|
||||
%changelog
|
||||
* Wed Feb 28 2007 Erk <eric.noulard@gmail.com>
|
||||
Generated by CMake UseRPMTools macros"
|
||||
)
|
||||
|
||||
ELSE ("${ARGV1}" STREQUAL "")
|
||||
SET(SPECFILE_PATH "${ARGV1}")
|
||||
|
||||
GET_FILENAME_COMPONENT(SPECFILE_EXT ${SPECFILE_PATH} EXT)
|
||||
IF ("${SPECFILE_EXT}" STREQUAL ".spec")
|
||||
# This is a 'ready-to-use' spec file which does not need to be CONFIGURED
|
||||
GET_FILENAME_COMPONENT(SPECFILE_NAME ${SPECFILE_PATH} NAME)
|
||||
MESSAGE(STATUS "Simple copy spec file <${SPECFILE_PATH}> --> <${RPM_ROOTDIR}/SPECS/${SPECFILE_NAME}>")
|
||||
CONFIGURE_FILE(
|
||||
${SPECFILE_PATH}
|
||||
${RPM_ROOTDIR}/SPECS/${SPECFILE_NAME}
|
||||
COPYONLY)
|
||||
ELSE ("${SPECFILE_EXT}" STREQUAL ".spec")
|
||||
# This is a to-be-configured spec file
|
||||
GET_FILENAME_COMPONENT(SPECFILE_NAME ${SPECFILE_PATH} NAME_WE)
|
||||
SET(SPECFILE_NAME "${SPECFILE_NAME}.spec")
|
||||
MESSAGE(STATUS "Configuring spec file <${SPECFILE_PATH}> --> <${RPM_ROOTDIR}/SPECS/${SPECFILE_NAME}>")
|
||||
CONFIGURE_FILE(
|
||||
${SPECFILE_PATH}
|
||||
${RPM_ROOTDIR}/SPECS/${SPECFILE_NAME}
|
||||
@ONLY)
|
||||
ENDIF ("${SPECFILE_EXT}" STREQUAL ".spec")
|
||||
ENDIF("${ARGV1}" STREQUAL "")
|
||||
|
||||
ADD_CUSTOM_TARGET(${RPMNAME}_srpm
|
||||
COMMAND cpack -G TGZ --config CPackSourceConfig.cmake
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CPACK_SOURCE_PACKAGE_FILE_NAME}.tar.gz ${RPM_ROOTDIR}/SOURCES
|
||||
COMMAND ${RPMTools_RPMBUILD_EXECUTABLE} -bs --define=\"_topdir ${RPM_ROOTDIR}\" --buildroot=${RPM_ROOTDIR}/tmp ${RPM_ROOTDIR}/SPECS/${SPECFILE_NAME}
|
||||
)
|
||||
|
||||
ADD_CUSTOM_TARGET(${RPMNAME}_rpm
|
||||
COMMAND cpack -G TGZ --config CPackSourceConfig.cmake
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CPACK_SOURCE_PACKAGE_FILE_NAME}.tar.gz ${RPM_ROOTDIR}/SOURCES
|
||||
COMMAND ${RPMTools_RPMBUILD_EXECUTABLE} -bb --define=\"_topdir ${RPM_ROOTDIR}\" --buildroot=${RPM_ROOTDIR}/tmp ${RPM_ROOTDIR}/SPECS/${SPECFILE_NAME}
|
||||
)
|
||||
ENDMACRO(RPMTools_ADD_RPM_TARGETS)
|
||||
|
||||
ELSE (RPMTools_RPMBUILD_FOUND)
|
||||
SET(RPMTools FALSE)
|
||||
ENDIF (RPMTools_RPMBUILD_FOUND)
|
||||
|
||||
ENDIF (UNIX)
|
||||
|
||||
174
dependencies/libwebsockets/config.h.cmake
vendored
Normal file
174
dependencies/libwebsockets/config.h.cmake
vendored
Normal file
@ -0,0 +1,174 @@
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
#ifndef WIN32
|
||||
#cmakedefine _DEBUG
|
||||
#endif
|
||||
|
||||
/* Define to 1 to use CyaSSL as a replacement for OpenSSL.
|
||||
* LWS_OPENSSL_SUPPORT needs to be set also for this to work. */
|
||||
#cmakedefine USE_CYASSL
|
||||
|
||||
/* The Libwebsocket version */
|
||||
#cmakedefine LWS_LIBRARY_VERSION "${LWS_LIBRARY_VERSION}"
|
||||
|
||||
/* The current git commit hash that we're building from */
|
||||
#cmakedefine LWS_BUILD_HASH "${LWS_BUILD_HASH}"
|
||||
|
||||
/* Build with OpenSSL support */
|
||||
#cmakedefine LWS_OPENSSL_SUPPORT
|
||||
|
||||
/* The client should load and trust CA root certs it finds in the OS */
|
||||
#cmakedefine LWS_SSL_CLIENT_USE_OS_CA_CERTS
|
||||
|
||||
/* Sets the path where the client certs should be installed. */
|
||||
#cmakedefine LWS_OPENSSL_CLIENT_CERTS "${LWS_OPENSSL_CLIENT_CERTS}"
|
||||
|
||||
/* Turn off websocket extensions */
|
||||
#cmakedefine LWS_NO_EXTENSIONS
|
||||
|
||||
/* Enable libev io loop */
|
||||
#cmakedefine LWS_USE_LIBEV
|
||||
|
||||
/* Build with support for ipv6 */
|
||||
#cmakedefine LWS_USE_IPV6
|
||||
|
||||
/* Build with support for HTTP2 */
|
||||
#cmakedefine LWS_USE_HTTP2
|
||||
|
||||
/* Turn on latency measuring code */
|
||||
#cmakedefine LWS_LATENCY
|
||||
|
||||
/* Don't build the daemonizeation api */
|
||||
#cmakedefine LWS_NO_DAEMONIZE
|
||||
|
||||
/* Build without server support */
|
||||
#cmakedefine LWS_NO_SERVER
|
||||
|
||||
/* Build without client support */
|
||||
#cmakedefine LWS_NO_CLIENT
|
||||
|
||||
/* If we should compile with MinGW support */
|
||||
#cmakedefine LWS_MINGW_SUPPORT
|
||||
|
||||
/* Use the BSD getifaddrs that comes with libwebsocket, for uclibc support */
|
||||
#cmakedefine LWS_BUILTIN_GETIFADDRS
|
||||
|
||||
/* Define to 1 if you have the `bzero' function. */
|
||||
#cmakedefine HAVE_BZERO
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#cmakedefine HAVE_DLFCN_H
|
||||
|
||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||
#cmakedefine HAVE_FCNTL_H
|
||||
|
||||
/* Define to 1 if you have the `fork' function. */
|
||||
#cmakedefine HAVE_FORK
|
||||
|
||||
/* Define to 1 if you have the `getenv’ function. */
|
||||
#cmakedefine HAVE_GETENV
|
||||
|
||||
/* Define to 1 if you have the <in6addr.h> header file. */
|
||||
#cmakedefine HAVE_IN6ADDR_H
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#cmakedefine HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if you have the `ssl' library (-lssl). */
|
||||
//#cmakedefine HAVE_LIBSSL
|
||||
|
||||
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
|
||||
to 0 otherwise. */
|
||||
#cmakedefine HAVE_MALLOC
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#cmakedefine HAVE_MEMORY_H
|
||||
|
||||
/* Define to 1 if you have the `memset' function. */
|
||||
#cmakedefine HAVE_MEMSET
|
||||
|
||||
/* Define to 1 if you have the <netinet/in.h> header file. */
|
||||
#cmakedefine HAVE_NETINET_IN_H
|
||||
|
||||
/* Define to 1 if your system has a GNU libc compatible `realloc' function,
|
||||
and to 0 otherwise. */
|
||||
#cmakedefine HAVE_REALLOC
|
||||
|
||||
/* Define to 1 if you have the `socket' function. */
|
||||
#cmakedefine HAVE_SOCKET
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#cmakedefine HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#cmakedefine HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the `strerror' function. */
|
||||
#cmakedefine HAVE_STRERROR
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#cmakedefine HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#cmakedefine HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the <sys/prctl.h> header file. */
|
||||
#cmakedefine HAVE_SYS_PRCTL_H
|
||||
|
||||
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||
#cmakedefine HAVE_SYS_SOCKET_H
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#cmakedefine HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#cmakedefine HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#cmakedefine HAVE_UNISTD_H
|
||||
|
||||
/* Define to 1 if you have the `vfork' function. */
|
||||
#cmakedefine HAVE_VFORK
|
||||
|
||||
/* Define to 1 if you have the <vfork.h> header file. */
|
||||
#cmakedefine HAVE_VFORK_H
|
||||
|
||||
/* Define to 1 if `fork' works. */
|
||||
#cmakedefine HAVE_WORKING_FORK
|
||||
|
||||
/* Define to 1 if `vfork' works. */
|
||||
#cmakedefine HAVE_WORKING_VFORK
|
||||
|
||||
/* Define to 1 if you have the <zlib.h> header file. */
|
||||
#cmakedefine HAVE_ZLIB_H
|
||||
|
||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||
*/
|
||||
#undef LT_OBJDIR // We're not using libtool
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#cmakedefine STDC_HEADERS
|
||||
|
||||
/* Version number of package */
|
||||
#cmakedefine VERSION
|
||||
|
||||
/* Define to rpl_malloc if the replacement function should be used. */
|
||||
#cmakedefine malloc
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
#cmakedefine pid_t
|
||||
|
||||
/* Define to rpl_realloc if the replacement function should be used. */
|
||||
#cmakedefine realloc
|
||||
|
||||
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
||||
#cmakedefine size_t
|
||||
|
||||
/* Define to 1 if we have getifaddrs */
|
||||
#cmakedefine HAVE_GETIFADDRS
|
||||
|
||||
/* Define as `fork' if `vfork' does not work. */
|
||||
//#cmakedefine vfork
|
||||
|
||||
/* Define if the inline keyword doesn't exist. */
|
||||
#cmakedefine inline
|
||||
28
dependencies/libwebsockets/cross-arm-linux-gnueabihf.cmake
vendored
Normal file
28
dependencies/libwebsockets/cross-arm-linux-gnueabihf.cmake
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
#
|
||||
# CMake Toolchain file for crosscompiling on ARM.
|
||||
#
|
||||
# This can be used when running cmake in the following way:
|
||||
# cd build/
|
||||
# cmake .. -DCMAKE_TOOLCHAIN_FILE=../cross-arm-linux-gnueabihf.cmake
|
||||
#
|
||||
|
||||
set(CROSS_PATH /opt/gcc-linaro-arm-linux-gnueabihf-4.7-2013.02-01-20130221_linux)
|
||||
|
||||
# Target operating system name.
|
||||
set(CMAKE_SYSTEM_NAME Linux)
|
||||
|
||||
# Name of C compiler.
|
||||
set(CMAKE_C_COMPILER "${CROSS_PATH}/bin/arm-linux-gnueabihf-gcc")
|
||||
set(CMAKE_CXX_COMPILER "${CROSS_PATH}/bin/arm-linux-gnueabihf-g++")
|
||||
|
||||
# Where to look for the target environment. (More paths can be added here)
|
||||
set(CMAKE_FIND_ROOT_PATH "${CROSS_PATH}")
|
||||
|
||||
# Adjust the default behavior of the FIND_XXX() commands:
|
||||
# search programs in the host environment only.
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
|
||||
# Search headers and libraries in the target environment only.
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
|
||||
31
dependencies/libwebsockets/cross-ming.cmake
vendored
Normal file
31
dependencies/libwebsockets/cross-ming.cmake
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
#
|
||||
# CMake Toolchain file for crosscompiling on MingW.
|
||||
#
|
||||
# This can be used when running cmake in the following way:
|
||||
# cd build/
|
||||
# cmake .. -DCMAKE_TOOLCHAIN_FILE=../cross-ming.cmake
|
||||
#
|
||||
|
||||
set(CROSS_PATH /usr/bin)
|
||||
|
||||
# Target operating system name.
|
||||
set(CMAKE_SYSTEM_NAME Windows)
|
||||
set(BUILD_SHARED_LIBS OFF)
|
||||
|
||||
# Name of C compiler.
|
||||
set(CMAKE_C_COMPILER "${CROSS_PATH}/x86_64-w64-mingw32-gcc")
|
||||
#set(CMAKE_CXX_COMPILER "${CROSS_PATH}/x86_64-w64-mingw32-g++")
|
||||
set(CMAKE_RC_COMPILER "${CROSS_PATH}/x86_64-w64-mingw32-windres")
|
||||
set(CMAKE_C_FLAGS "-Wno-error")
|
||||
|
||||
# Where to look for the target environment. (More paths can be added here)
|
||||
set(CMAKE_FIND_ROOT_PATH "${CROSS_PATH}")
|
||||
|
||||
# Adjust the default behavior of the FIND_XXX() commands:
|
||||
# search programs in the host environment only.
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
|
||||
# Search headers and libraries in the target environment only.
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
|
||||
91
dependencies/libwebsockets/cross-openwrt-makefile
vendored
Normal file
91
dependencies/libwebsockets/cross-openwrt-makefile
vendored
Normal file
@ -0,0 +1,91 @@
|
||||
#
|
||||
# libwebsockets makefile for openwrt
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=libwebsockets
|
||||
PKG_VERSION:=2014-03-01
|
||||
PKG_RELEASE=$(PKG_SOURCE_VERSION)
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL:=https://github.com/warmcat/libwebsockets.git
|
||||
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
|
||||
PKG_SOURCE_VERSION:=388dc7d201d8d123841869fb49ec4d94d6dd7f54
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
|
||||
CMAKE_INSTALL:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(INCLUDE_DIR)/cmake.mk
|
||||
|
||||
CMAKE_OPTIONS += -DLWS_OPENSSL_CLIENT_CERTS=/etc/ssl/certs
|
||||
CMAKE_OPTIONS += -DLWS_OPENSSL_SUPPORT=ON
|
||||
CMAKE_OPTIONS += -DLWS_WITH_SSL=ON
|
||||
CMAKE_OPTIONS += -DLWS_WITHOUT_TESTAPPS=$(if $(CONFIG_PACKAGE_libwebsockets-examples),"OFF","ON")
|
||||
|
||||
# for cyassl, define these in addition to LWS_OPENSSL_SUPPORT and
|
||||
# edit package/libs/cyassl/Makefile to include --enable-opensslextra
|
||||
# CMAKE_OPTIONS += -DLWS_USE_CYASSL=ON
|
||||
# CMAKE_OPTIONS += -DLWS_CYASSL_LIB=$(STAGING_DIR)/usr/lib/libcyassl.so
|
||||
# CMAKE_OPTIONS += -DLWS_CYASSL_INCLUDE_DIRS=$(STAGING_DIR)/usr/include
|
||||
|
||||
# other options worth noting
|
||||
# CMAKE_OPTIONS += -DLWS_WITHOUT_EXTENSIONS=ON
|
||||
# CMAKE_OPTIONS += -DLWS_WITHOUT_DAEMONIZE=ON
|
||||
# CMAKE_OPTIONS += -DLWS_WITHOUT_SERVER=ON
|
||||
# CMAKE_OPTIONS += -DLWS_WITHOUT_DEBUG=ON
|
||||
|
||||
|
||||
define Package/libwebsockets/Default
|
||||
SECTION:=libs
|
||||
CATEGORY:=Libraries
|
||||
TITLE:=libwebsockets
|
||||
DEPENDS:=+zlib +libopenssl
|
||||
endef
|
||||
|
||||
define Package/libwebsockets
|
||||
$(call Package/libwebsockets/Default)
|
||||
TITLE+= (libraries)
|
||||
endef
|
||||
|
||||
define Package/libwebsockets/description
|
||||
libwebsockets
|
||||
This package contains libwebsocket libraries
|
||||
endef
|
||||
|
||||
define Package/libwebsockets-examples
|
||||
$(call Package/libwebsockets/Default)
|
||||
DEPENDS:=libwebsockets
|
||||
TITLE+= (examples)
|
||||
endef
|
||||
|
||||
define Package/libwebsockets-examples/description
|
||||
libwebsockets examples
|
||||
This package contains libwebsockets examples
|
||||
endef
|
||||
|
||||
define Package/libwebsockets/install
|
||||
$(INSTALL_DIR) $(1)/usr/lib
|
||||
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libwebsockets.so* $(1)/usr/lib/
|
||||
endef
|
||||
|
||||
define Package/libwebsockets-examples/install
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/libwebsockets-test-client $(1)/usr/bin/
|
||||
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/libwebsockets-test-echo $(1)/usr/bin/
|
||||
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/libwebsockets-test-fraggle $(1)/usr/bin/
|
||||
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/libwebsockets-test-ping $(1)/usr/bin/
|
||||
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/libwebsockets-test-server $(1)/usr/bin/
|
||||
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/libwebsockets-test-server-extpoll $(1)/usr/bin/
|
||||
|
||||
$(INSTALL_DIR) $(1)/usr/share/libwebsockets-test-server
|
||||
$(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/libwebsockets-test-server/favicon.ico $(1)/usr/share/libwebsockets-test-server/
|
||||
$(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/libwebsockets-test-server/leaf.jpg $(1)/usr/share/libwebsockets-test-server/
|
||||
$(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/libwebsockets-test-server/libwebsockets.org-logo.png $(1)/usr/share/libwebsockets-test-server/
|
||||
$(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/libwebsockets-test-server/libwebsockets-test-server.key.pem $(1)/usr/share/libwebsockets-test-server/
|
||||
$(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/libwebsockets-test-server/libwebsockets-test-server.pem $(1)/usr/share/libwebsockets-test-server/
|
||||
$(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/libwebsockets-test-server/test.html $(1)/usr/share/libwebsockets-test-server/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,libwebsockets))
|
||||
$(eval $(call BuildPackage,libwebsockets-examples))
|
||||
8
dependencies/libwebsockets/lib/.gitignore
vendored
Normal file
8
dependencies/libwebsockets/lib/.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
#Ignore build files
|
||||
Makefile
|
||||
*.o
|
||||
*.lo
|
||||
*.la
|
||||
.libs
|
||||
.deps
|
||||
|
||||
93
dependencies/libwebsockets/lib/base64-decode.c
vendored
Normal file
93
dependencies/libwebsockets/lib/base64-decode.c
vendored
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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 like the rest of libwebsockets
|
||||
* since he explictly 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 "private-libwebsockets.h"
|
||||
|
||||
static const char encode[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
static const char decode[] = "|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW"
|
||||
"$$$$$$XYZ[\\]^_`abcdefghijklmnopq";
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_b64_encode_string(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 (!len)
|
||||
continue;
|
||||
|
||||
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;
|
||||
}
|
||||
443
dependencies/libwebsockets/lib/client-handshake.c
vendored
Normal file
443
dependencies/libwebsockets/lib/client-handshake.c
vendored
Normal file
@ -0,0 +1,443 @@
|
||||
#include "private-libwebsockets.h"
|
||||
|
||||
struct libwebsocket *libwebsocket_client_connect_2(
|
||||
struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi
|
||||
) {
|
||||
struct libwebsocket_pollfd pfd;
|
||||
#ifdef LWS_USE_IPV6
|
||||
struct sockaddr_in6 server_addr6;
|
||||
struct sockaddr_in6 client_addr6;
|
||||
struct addrinfo hints, *result;
|
||||
#endif
|
||||
struct sockaddr_in server_addr4;
|
||||
struct sockaddr_in client_addr4;
|
||||
struct hostent *server_hostent;
|
||||
|
||||
struct sockaddr *v;
|
||||
int n;
|
||||
int plen = 0;
|
||||
const char *ads;
|
||||
|
||||
lwsl_client("libwebsocket_client_connect_2\n");
|
||||
|
||||
/*
|
||||
* proxy?
|
||||
*/
|
||||
|
||||
if (context->http_proxy_port) {
|
||||
plen = sprintf((char *)context->service_buffer,
|
||||
"CONNECT %s:%u HTTP/1.0\x0d\x0a"
|
||||
"User-agent: libwebsockets\x0d\x0a"
|
||||
/*Proxy-authorization: basic aGVsbG86d29ybGQ= */
|
||||
"\x0d\x0a",
|
||||
lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS),
|
||||
wsi->u.hdr.ah->c_port);
|
||||
ads = context->http_proxy_address;
|
||||
|
||||
#ifdef LWS_USE_IPV6
|
||||
if (LWS_IPV6_ENABLED(context))
|
||||
server_addr6.sin6_port = htons(context->http_proxy_port);
|
||||
else
|
||||
#endif
|
||||
server_addr4.sin_port = htons(context->http_proxy_port);
|
||||
|
||||
} else {
|
||||
ads = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS);
|
||||
#ifdef LWS_USE_IPV6
|
||||
if (LWS_IPV6_ENABLED(context))
|
||||
server_addr6.sin6_port = htons(wsi->u.hdr.ah->c_port);
|
||||
else
|
||||
#endif
|
||||
server_addr4.sin_port = htons(wsi->u.hdr.ah->c_port);
|
||||
}
|
||||
|
||||
/*
|
||||
* prepare the actual connection (to the proxy, if any)
|
||||
*/
|
||||
lwsl_client("libwebsocket_client_connect_2: address %s\n", ads);
|
||||
|
||||
#ifdef LWS_USE_IPV6
|
||||
if (LWS_IPV6_ENABLED(context)) {
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
n = getaddrinfo(ads, NULL, &hints, &result);
|
||||
if (n) {
|
||||
#ifdef _WIN32
|
||||
lwsl_err("getaddrinfo: %ls\n", gai_strerrorW(n));
|
||||
#else
|
||||
lwsl_err("getaddrinfo: %s\n", gai_strerror(n));
|
||||
#endif
|
||||
goto oom4;
|
||||
}
|
||||
|
||||
server_addr6.sin6_family = AF_INET6;
|
||||
switch (result->ai_family) {
|
||||
case AF_INET:
|
||||
/* map IPv4 to IPv6 */
|
||||
bzero((char *)&server_addr6.sin6_addr,
|
||||
sizeof(struct in6_addr));
|
||||
server_addr6.sin6_addr.s6_addr[10] = 0xff;
|
||||
server_addr6.sin6_addr.s6_addr[11] = 0xff;
|
||||
memcpy(&server_addr6.sin6_addr.s6_addr[12],
|
||||
&((struct sockaddr_in *)result->ai_addr)->sin_addr,
|
||||
sizeof(struct in_addr));
|
||||
break;
|
||||
case AF_INET6:
|
||||
memcpy(&server_addr6.sin6_addr,
|
||||
&((struct sockaddr_in6 *)result->ai_addr)->sin6_addr,
|
||||
sizeof(struct in6_addr));
|
||||
break;
|
||||
default:
|
||||
lwsl_err("Unknown address family\n");
|
||||
freeaddrinfo(result);
|
||||
goto oom4;
|
||||
}
|
||||
|
||||
freeaddrinfo(result);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
server_hostent = gethostbyname(ads);
|
||||
if (!server_hostent) {
|
||||
lwsl_err("Unable to get host name from %s\n", ads);
|
||||
goto oom4;
|
||||
}
|
||||
|
||||
server_addr4.sin_family = AF_INET;
|
||||
server_addr4.sin_addr =
|
||||
*((struct in_addr *)server_hostent->h_addr);
|
||||
bzero(&server_addr4.sin_zero, 8);
|
||||
}
|
||||
|
||||
if (wsi->sock < 0) {
|
||||
|
||||
#ifdef LWS_USE_IPV6
|
||||
if (LWS_IPV6_ENABLED(context))
|
||||
wsi->sock = socket(AF_INET6, SOCK_STREAM, 0);
|
||||
else
|
||||
#endif
|
||||
wsi->sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
if (wsi->sock < 0) {
|
||||
lwsl_warn("Unable to open socket\n");
|
||||
goto oom4;
|
||||
}
|
||||
|
||||
if (lws_plat_set_socket_options(context, wsi->sock)) {
|
||||
lwsl_err("Failed to set wsi socket options\n");
|
||||
compatible_close(wsi->sock);
|
||||
goto oom4;
|
||||
}
|
||||
|
||||
wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_CONNECT;
|
||||
|
||||
insert_wsi_socket_into_fds(context, wsi);
|
||||
|
||||
libwebsocket_set_timeout(wsi,
|
||||
PENDING_TIMEOUT_AWAITING_CONNECT_RESPONSE,
|
||||
AWAITING_TIMEOUT);
|
||||
#ifdef LWS_USE_IPV6
|
||||
if (LWS_IPV6_ENABLED(context)) {
|
||||
v = (struct sockaddr *)&client_addr6;
|
||||
n = sizeof(client_addr6);
|
||||
bzero((char *)v, n);
|
||||
client_addr6.sin6_family = AF_INET6;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
v = (struct sockaddr *)&client_addr4;
|
||||
n = sizeof(client_addr4);
|
||||
bzero((char *)v, n);
|
||||
client_addr4.sin_family = AF_INET;
|
||||
}
|
||||
|
||||
if (context->iface) {
|
||||
if (interface_to_sa(context, context->iface,
|
||||
(struct sockaddr_in *)v, n) < 0) {
|
||||
lwsl_err("Unable to find interface %s\n",
|
||||
context->iface);
|
||||
compatible_close(wsi->sock);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (bind(wsi->sock, v, n) < 0) {
|
||||
lwsl_err("Error binding to interface %s",
|
||||
context->iface);
|
||||
compatible_close(wsi->sock);
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef LWS_USE_IPV6
|
||||
if (LWS_IPV6_ENABLED(context)) {
|
||||
v = (struct sockaddr *)&server_addr6;
|
||||
n = sizeof(struct sockaddr_in6);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
v = (struct sockaddr *)&server_addr4;
|
||||
n = sizeof(struct sockaddr);
|
||||
}
|
||||
|
||||
if (connect(wsi->sock, v, n) == -1 || LWS_ERRNO == LWS_EISCONN) {
|
||||
|
||||
if (LWS_ERRNO == LWS_EALREADY || LWS_ERRNO == LWS_EINPROGRESS
|
||||
|| LWS_ERRNO == LWS_EWOULDBLOCK) {
|
||||
lwsl_client("nonblocking connect retry\n");
|
||||
|
||||
/*
|
||||
* must do specifically a POLLOUT poll to hear
|
||||
* about the connect completion
|
||||
*/
|
||||
if (lws_change_pollfd(wsi, 0, LWS_POLLOUT))
|
||||
goto oom4;
|
||||
|
||||
return wsi;
|
||||
}
|
||||
|
||||
if (LWS_ERRNO != LWS_EISCONN) {
|
||||
lwsl_debug("Connect failed errno=%d\n", LWS_ERRNO);
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
lwsl_client("connected\n");
|
||||
|
||||
/* we are connected to server, or proxy */
|
||||
|
||||
if (context->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,
|
||||
context->http_proxy_address))
|
||||
goto failed;
|
||||
wsi->u.hdr.ah->c_port = context->http_proxy_port;
|
||||
|
||||
n = send(wsi->sock, context->service_buffer, plen, MSG_NOSIGNAL);
|
||||
if (n < 0) {
|
||||
lwsl_debug("ERROR writing to proxy socket\n");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
libwebsocket_set_timeout(wsi,
|
||||
PENDING_TIMEOUT_AWAITING_PROXY_RESPONSE,
|
||||
AWAITING_TIMEOUT);
|
||||
|
||||
wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_PROXY_REPLY;
|
||||
|
||||
return wsi;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 some
|
||||
* many retries from main loop. To stop that becoming endless,
|
||||
* cover with a timeout.
|
||||
*/
|
||||
|
||||
libwebsocket_set_timeout(wsi,
|
||||
PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE, AWAITING_TIMEOUT);
|
||||
|
||||
wsi->mode = LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE;
|
||||
pfd.fd = wsi->sock;
|
||||
pfd.revents = LWS_POLLIN;
|
||||
|
||||
n = libwebsocket_service_fd(context, &pfd);
|
||||
|
||||
if (n < 0)
|
||||
goto failed;
|
||||
|
||||
if (n) /* returns 1 on failure after closing wsi */
|
||||
return NULL;
|
||||
|
||||
return wsi;
|
||||
|
||||
oom4:
|
||||
free(wsi->u.hdr.ah);
|
||||
free(wsi);
|
||||
return NULL;
|
||||
|
||||
failed:
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* libwebsocket_client_connect() - Connect to another websocket server
|
||||
* @context: Websocket context
|
||||
* @address: Remote server address, eg, "myserver.com"
|
||||
* @port: Port to connect to on the remote server, eg, 80
|
||||
* @ssl_connection: 0 = ws://, 1 = wss:// encrypted, 2 = wss:// allow self
|
||||
* signed certs
|
||||
* @path: Websocket path on server
|
||||
* @host: Hostname on server
|
||||
* @origin: Socket origin name
|
||||
* @protocol: Comma-separated list of protocols being asked for from
|
||||
* the server, or just one. The server will pick the one it
|
||||
* likes best.
|
||||
* @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
|
||||
*/
|
||||
|
||||
LWS_VISIBLE struct libwebsocket *
|
||||
libwebsocket_client_connect(struct libwebsocket_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 libwebsocket *wsi;
|
||||
|
||||
wsi = (struct libwebsocket *) malloc(sizeof(struct libwebsocket));
|
||||
if (wsi == NULL)
|
||||
goto bail;
|
||||
|
||||
memset(wsi, 0, sizeof(*wsi));
|
||||
wsi->sock = -1;
|
||||
|
||||
/* -1 means just use latest supported */
|
||||
|
||||
if (ietf_version_or_minus_one == -1)
|
||||
ietf_version_or_minus_one = SPEC_LATEST_SUPPORTED;
|
||||
|
||||
wsi->ietf_spec_revision = ietf_version_or_minus_one;
|
||||
wsi->user_space = NULL;
|
||||
wsi->state = WSI_STATE_CLIENT_UNCONNECTED;
|
||||
wsi->protocol = NULL;
|
||||
wsi->pending_timeout = NO_PENDING_TIMEOUT;
|
||||
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
wsi->use_ssl = ssl_connection;
|
||||
#else
|
||||
if (ssl_connection) {
|
||||
lwsl_err("libwebsockets not configured for ssl\n");
|
||||
goto bail;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (lws_allocate_header_table(wsi))
|
||||
goto bail;
|
||||
|
||||
/*
|
||||
* we're not necessarily in a position to action these right away,
|
||||
* stash them... we only need during connect phase so u.hdr is fine
|
||||
*/
|
||||
wsi->u.hdr.ah->c_port = port;
|
||||
if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS, address))
|
||||
goto bail1;
|
||||
|
||||
/* these only need u.hdr lifetime as well */
|
||||
|
||||
if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_URI, path))
|
||||
goto bail1;
|
||||
|
||||
if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_HOST, host))
|
||||
goto bail1;
|
||||
|
||||
if (origin)
|
||||
if (lws_hdr_simple_create(wsi,
|
||||
_WSI_TOKEN_CLIENT_ORIGIN, 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 (protocol)
|
||||
if (lws_hdr_simple_create(wsi,
|
||||
_WSI_TOKEN_CLIENT_SENT_PROTOCOLS, protocol))
|
||||
goto bail1;
|
||||
|
||||
wsi->protocol = &context->protocols[0];
|
||||
|
||||
/*
|
||||
* Check with each extension if it is able to route and proxy this
|
||||
* connection for us. For example, an extension like x-google-mux
|
||||
* can handle this and then we don't need an actual socket for this
|
||||
* connection.
|
||||
*/
|
||||
|
||||
if (lws_ext_callback_for_each_extension_type(context, wsi,
|
||||
LWS_EXT_CALLBACK_CAN_PROXY_CLIENT_CONNECTION,
|
||||
(void *)address, port) > 0) {
|
||||
lwsl_client("libwebsocket_client_connect: ext handling conn\n");
|
||||
|
||||
libwebsocket_set_timeout(wsi,
|
||||
PENDING_TIMEOUT_AWAITING_EXTENSION_CONNECT_RESPONSE,
|
||||
AWAITING_TIMEOUT);
|
||||
|
||||
wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT;
|
||||
return wsi;
|
||||
}
|
||||
lwsl_client("libwebsocket_client_connect: direct conn\n");
|
||||
|
||||
return libwebsocket_client_connect_2(context, wsi);
|
||||
|
||||
bail1:
|
||||
free(wsi->u.hdr.ah);
|
||||
bail:
|
||||
free(wsi);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* libwebsocket_client_connect_extended() - Connect to another websocket server
|
||||
* @context: Websocket context
|
||||
* @address: Remote server address, eg, "myserver.com"
|
||||
* @port: Port to connect to on the remote server, eg, 80
|
||||
* @ssl_connection: 0 = ws://, 1 = wss:// encrypted, 2 = wss:// allow self
|
||||
* signed certs
|
||||
* @path: Websocket path on server
|
||||
* @host: Hostname on server
|
||||
* @origin: Socket origin name
|
||||
* @protocol: Comma-separated list of protocols being asked for from
|
||||
* the server, or just one. The server will pick the one it
|
||||
* likes best.
|
||||
* @ietf_version_or_minus_one: -1 to ask to connect using the default, latest
|
||||
* protocol supported, or the specific protocol ordinal
|
||||
* @userdata: Pre-allocated user data
|
||||
*
|
||||
* This function creates a connection to a remote server
|
||||
*/
|
||||
|
||||
LWS_VISIBLE struct libwebsocket *
|
||||
libwebsocket_client_connect_extended(struct libwebsocket_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 libwebsocket *ws =
|
||||
libwebsocket_client_connect(context, address, port,
|
||||
ssl_connection, path, host, origin, protocol,
|
||||
ietf_version_or_minus_one);
|
||||
|
||||
if (ws && !ws->user_space && userdata) {
|
||||
ws->user_space_externally_allocated = 1;
|
||||
ws->user_space = userdata ;
|
||||
}
|
||||
|
||||
return ws ;
|
||||
}
|
||||
402
dependencies/libwebsockets/lib/client-parser.c
vendored
Normal file
402
dependencies/libwebsockets/lib/client-parser.c
vendored
Normal file
@ -0,0 +1,402 @@
|
||||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010-2014 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 "private-libwebsockets.h"
|
||||
|
||||
int libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c)
|
||||
{
|
||||
int callback_action = LWS_CALLBACK_CLIENT_RECEIVE;
|
||||
int handled;
|
||||
struct lws_tokens eff_buf;
|
||||
int m;
|
||||
|
||||
switch (wsi->lws_rx_parse_state) {
|
||||
case LWS_RXPS_NEW:
|
||||
|
||||
switch (wsi->ietf_spec_revision) {
|
||||
|
||||
case 13:
|
||||
wsi->u.ws.opcode = c & 0xf;
|
||||
wsi->u.ws.rsv = (c & 0x70);
|
||||
wsi->u.ws.final = !!((c >> 7) & 1);
|
||||
switch (wsi->u.ws.opcode) {
|
||||
case LWS_WS_OPCODE_07__TEXT_FRAME:
|
||||
case LWS_WS_OPCODE_07__BINARY_FRAME:
|
||||
wsi->u.ws.frame_is_binary = wsi->u.ws.opcode ==
|
||||
LWS_WS_OPCODE_07__BINARY_FRAME;
|
||||
break;
|
||||
}
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN;
|
||||
break;
|
||||
|
||||
default:
|
||||
lwsl_err("unknown spec version %02d\n",
|
||||
wsi->ietf_spec_revision);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN:
|
||||
|
||||
wsi->u.ws.this_frame_masked = !!(c & 0x80);
|
||||
|
||||
switch (c & 0x7f) {
|
||||
case 126:
|
||||
/* control frames are not allowed to have big lengths */
|
||||
if (wsi->u.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->u.ws.opcode & 8)
|
||||
goto illegal_ctl_length;
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_8;
|
||||
break;
|
||||
default:
|
||||
wsi->u.ws.rx_packet_length = c;
|
||||
if (wsi->u.ws.this_frame_masked)
|
||||
wsi->lws_rx_parse_state =
|
||||
LWS_RXPS_07_COLLECT_FRAME_KEY_1;
|
||||
else {
|
||||
if (c)
|
||||
wsi->lws_rx_parse_state =
|
||||
LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
|
||||
else {
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_NEW;
|
||||
goto spill;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN16_2:
|
||||
wsi->u.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->u.ws.rx_packet_length |= c;
|
||||
if (wsi->u.ws.this_frame_masked)
|
||||
wsi->lws_rx_parse_state =
|
||||
LWS_RXPS_07_COLLECT_FRAME_KEY_1;
|
||||
else {
|
||||
if (wsi->u.ws.rx_packet_length)
|
||||
wsi->lws_rx_parse_state =
|
||||
LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
|
||||
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->u.ws.rx_packet_length = ((size_t)c) << 56;
|
||||
#else
|
||||
wsi->u.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->u.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->u.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->u.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->u.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->u.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->u.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->u.ws.rx_packet_length |= (size_t)c;
|
||||
if (wsi->u.ws.this_frame_masked)
|
||||
wsi->lws_rx_parse_state =
|
||||
LWS_RXPS_07_COLLECT_FRAME_KEY_1;
|
||||
else {
|
||||
if (wsi->u.ws.rx_packet_length)
|
||||
wsi->lws_rx_parse_state =
|
||||
LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
|
||||
else {
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_NEW;
|
||||
goto spill;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_RXPS_07_COLLECT_FRAME_KEY_1:
|
||||
wsi->u.ws.frame_masking_nonce_04[0] = c;
|
||||
if (c)
|
||||
wsi->u.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->u.ws.frame_masking_nonce_04[1] = c;
|
||||
if (c)
|
||||
wsi->u.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->u.ws.frame_masking_nonce_04[2] = c;
|
||||
if (c)
|
||||
wsi->u.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->u.ws.frame_masking_nonce_04[3] = c;
|
||||
if (c)
|
||||
wsi->u.ws.all_zero_nonce = 0;
|
||||
|
||||
if (wsi->u.ws.rx_packet_length)
|
||||
wsi->lws_rx_parse_state =
|
||||
LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
|
||||
else {
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_NEW;
|
||||
goto spill;
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED:
|
||||
|
||||
if (!wsi->u.ws.rx_user_buffer)
|
||||
lwsl_err("NULL client rx_user_buffer\n");
|
||||
|
||||
if ((!wsi->u.ws.this_frame_masked) || wsi->u.ws.all_zero_nonce)
|
||||
wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING +
|
||||
(wsi->u.ws.rx_user_buffer_head++)] = c;
|
||||
else
|
||||
wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING +
|
||||
(wsi->u.ws.rx_user_buffer_head++)] =
|
||||
c ^ wsi->u.ws.frame_masking_nonce_04[
|
||||
(wsi->u.ws.frame_mask_index++) & 3];
|
||||
|
||||
if (--wsi->u.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 LWS_MAX_SOCKET_IO_BUF
|
||||
*/
|
||||
|
||||
if (!wsi->protocol->rx_buffer_size &&
|
||||
wsi->u.ws.rx_user_buffer_head !=
|
||||
LWS_MAX_SOCKET_IO_BUF)
|
||||
break;
|
||||
else
|
||||
if (wsi->protocol->rx_buffer_size &&
|
||||
wsi->u.ws.rx_user_buffer_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->u.ws.opcode) {
|
||||
case LWS_WS_OPCODE_07__CLOSE:
|
||||
/* is this an acknowledgement of our close? */
|
||||
if (wsi->state == WSI_STATE_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->u.ws.rx_user_buffer_head);
|
||||
/*
|
||||
* parrot the close packet payload back
|
||||
* we do not care about how it went, we are closing
|
||||
* immediately afterwards
|
||||
*/
|
||||
libwebsocket_write(wsi, (unsigned char *)
|
||||
&wsi->u.ws.rx_user_buffer[
|
||||
LWS_SEND_BUFFER_PRE_PADDING],
|
||||
wsi->u.ws.rx_user_buffer_head, LWS_WRITE_CLOSE);
|
||||
wsi->state = WSI_STATE_RETURNED_CLOSE_ALREADY;
|
||||
/* close the connection */
|
||||
return -1;
|
||||
|
||||
case LWS_WS_OPCODE_07__PING:
|
||||
lwsl_info("client received ping, doing pong\n");
|
||||
/*
|
||||
* parrot the ping packet payload back as a pong
|
||||
* !!! this may block or have partial write or fail
|
||||
* !!! very unlikely if the ping size is small
|
||||
*/
|
||||
libwebsocket_write(wsi, (unsigned char *)
|
||||
&wsi->u.ws.rx_user_buffer[
|
||||
LWS_SEND_BUFFER_PRE_PADDING],
|
||||
wsi->u.ws.rx_user_buffer_head,
|
||||
LWS_WRITE_PONG);
|
||||
handled = 1;
|
||||
break;
|
||||
|
||||
case LWS_WS_OPCODE_07__PONG:
|
||||
lwsl_info("client receied pong\n");
|
||||
lwsl_hexdump(&wsi->u.ws.rx_user_buffer[
|
||||
LWS_SEND_BUFFER_PRE_PADDING],
|
||||
wsi->u.ws.rx_user_buffer_head);
|
||||
|
||||
/* issue it */
|
||||
callback_action = LWS_CALLBACK_CLIENT_RECEIVE_PONG;
|
||||
break;
|
||||
|
||||
case LWS_WS_OPCODE_07__CONTINUATION:
|
||||
case LWS_WS_OPCODE_07__TEXT_FRAME:
|
||||
case LWS_WS_OPCODE_07__BINARY_FRAME:
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
lwsl_parser("Reserved opc 0x%2X\n", wsi->u.ws.opcode);
|
||||
|
||||
/*
|
||||
* It's something special we can't understand here.
|
||||
* Pass the payload up to the extension's parsing
|
||||
* state machine.
|
||||
*/
|
||||
|
||||
eff_buf.token = &wsi->u.ws.rx_user_buffer[
|
||||
LWS_SEND_BUFFER_PRE_PADDING];
|
||||
eff_buf.token_len = wsi->u.ws.rx_user_buffer_head;
|
||||
|
||||
if (lws_ext_callback_for_each_active(wsi,
|
||||
LWS_EXT_CALLBACK_EXTENDED_PAYLOAD_RX,
|
||||
&eff_buf, 0) <= 0) { /* not handle or fail */
|
||||
|
||||
lwsl_ext("Unhandled ext opc 0x%x\n",
|
||||
wsi->u.ws.opcode);
|
||||
wsi->u.ws.rx_user_buffer_head = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
handled = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 libwebsocket_write
|
||||
*/
|
||||
if (handled)
|
||||
goto already_done;
|
||||
|
||||
eff_buf.token = &wsi->u.ws.rx_user_buffer[
|
||||
LWS_SEND_BUFFER_PRE_PADDING];
|
||||
eff_buf.token_len = wsi->u.ws.rx_user_buffer_head;
|
||||
|
||||
if (lws_ext_callback_for_each_active(wsi,
|
||||
LWS_EXT_CALLBACK_PAYLOAD_RX,
|
||||
&eff_buf, 0) < 0) /* fail */
|
||||
return -1;
|
||||
|
||||
if (eff_buf.token_len <= 0 &&
|
||||
callback_action != LWS_CALLBACK_CLIENT_RECEIVE_PONG)
|
||||
goto already_done;
|
||||
|
||||
eff_buf.token[eff_buf.token_len] = '\0';
|
||||
|
||||
if (!wsi->protocol->callback)
|
||||
goto already_done;
|
||||
|
||||
if (callback_action == LWS_CALLBACK_CLIENT_RECEIVE_PONG)
|
||||
lwsl_info("Client doing pong callback\n");
|
||||
|
||||
m = wsi->protocol->callback(
|
||||
wsi->protocol->owning_server,
|
||||
wsi,
|
||||
(enum libwebsocket_callback_reasons)callback_action,
|
||||
wsi->user_space,
|
||||
eff_buf.token,
|
||||
eff_buf.token_len);
|
||||
|
||||
/* if user code wants to close, let caller know */
|
||||
if (m)
|
||||
return 1;
|
||||
|
||||
already_done:
|
||||
wsi->u.ws.rx_user_buffer_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;
|
||||
}
|
||||
|
||||
|
||||
958
dependencies/libwebsockets/lib/client.c
vendored
Normal file
958
dependencies/libwebsockets/lib/client.c
vendored
Normal file
@ -0,0 +1,958 @@
|
||||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010-2014 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 "private-libwebsockets.h"
|
||||
|
||||
int lws_handshake_client(struct libwebsocket *wsi, unsigned char **buf, size_t len)
|
||||
{
|
||||
int n;
|
||||
|
||||
switch (wsi->mode) {
|
||||
case LWS_CONNMODE_WS_CLIENT_WAITING_PROXY_REPLY:
|
||||
case LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE:
|
||||
case LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY:
|
||||
case LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT:
|
||||
case LWS_CONNMODE_WS_CLIENT:
|
||||
for (n = 0; n < len; n++)
|
||||
if (libwebsocket_client_rx_sm(wsi, *(*buf)++)) {
|
||||
lwsl_debug("client_rx_sm failed\n");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lws_client_socket_service(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, struct libwebsocket_pollfd *pollfd)
|
||||
{
|
||||
int n;
|
||||
char *p = (char *)&context->service_buffer[0];
|
||||
int len;
|
||||
unsigned char c;
|
||||
|
||||
switch (wsi->mode) {
|
||||
|
||||
case LWS_CONNMODE_WS_CLIENT_WAITING_CONNECT:
|
||||
|
||||
/*
|
||||
* we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE
|
||||
* timeout protection set in client-handshake.c
|
||||
*/
|
||||
|
||||
if (libwebsocket_client_connect_2(context, wsi) == NULL) {
|
||||
/* closed */
|
||||
lwsl_client("closed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* either still pending connection, or changed mode */
|
||||
return 0;
|
||||
|
||||
case LWS_CONNMODE_WS_CLIENT_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);
|
||||
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
n = recv(wsi->sock, context->service_buffer,
|
||||
sizeof(context->service_buffer), 0);
|
||||
if (n < 0) {
|
||||
|
||||
if (LWS_ERRNO == LWS_EAGAIN) {
|
||||
lwsl_debug(
|
||||
"Proxy read returned EAGAIN... retrying\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
lwsl_err("ERROR reading from proxy socket\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
context->service_buffer[13] = '\0';
|
||||
if (strcmp((char *)context->service_buffer, "HTTP/1.0 200 ")) {
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
lwsl_err("ERROR proxy: %s\n", context->service_buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* clear his proxy connection timeout */
|
||||
|
||||
libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
|
||||
|
||||
/* fallthru */
|
||||
|
||||
case LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE:
|
||||
|
||||
/*
|
||||
* we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE
|
||||
* timeout protection set in client-handshake.c
|
||||
*/
|
||||
|
||||
/*
|
||||
* take care of our libwebsocket_callback_on_writable
|
||||
* happening at a time when there's no real connection yet
|
||||
*/
|
||||
if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
|
||||
return -1;
|
||||
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
/* we can retry this... just cook the SSL BIO the first time */
|
||||
|
||||
if (wsi->use_ssl && !wsi->ssl) {
|
||||
#if defined(CYASSL_SNI_HOST_NAME) || defined(SSL_CTRL_SET_TLSEXT_HOSTNAME)
|
||||
const char *hostname = lws_hdr_simple_ptr(wsi,
|
||||
_WSI_TOKEN_CLIENT_PEER_ADDRESS);
|
||||
#endif
|
||||
|
||||
wsi->ssl = SSL_new(context->ssl_client_ctx);
|
||||
#ifndef USE_CYASSL
|
||||
SSL_set_mode(wsi->ssl,
|
||||
SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
|
||||
#endif
|
||||
/*
|
||||
* use server name indication (SNI), if supported,
|
||||
* when establishing connection
|
||||
*/
|
||||
#ifdef USE_CYASSL
|
||||
#ifdef CYASSL_SNI_HOST_NAME
|
||||
CyaSSL_UseSNI(wsi->ssl, CYASSL_SNI_HOST_NAME,
|
||||
hostname, strlen(hostname));
|
||||
#endif
|
||||
#else
|
||||
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
|
||||
SSL_set_tlsext_host_name(wsi->ssl, hostname);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef USE_CYASSL
|
||||
/*
|
||||
* CyaSSL does certificate verification differently
|
||||
* from OpenSSL.
|
||||
* If we should ignore the certificate, we need to set
|
||||
* this before SSL_new and SSL_connect is called.
|
||||
* Otherwise the connect will simply fail with error
|
||||
* code -155
|
||||
*/
|
||||
if (wsi->use_ssl == 2)
|
||||
CyaSSL_set_verify(wsi->ssl,
|
||||
SSL_VERIFY_NONE, NULL);
|
||||
#endif /* USE_CYASSL */
|
||||
|
||||
wsi->client_bio =
|
||||
BIO_new_socket(wsi->sock, BIO_NOCLOSE);
|
||||
SSL_set_bio(wsi->ssl, wsi->client_bio, wsi->client_bio);
|
||||
|
||||
#ifdef USE_CYASSL
|
||||
CyaSSL_set_using_nonblock(wsi->ssl, 1);
|
||||
#else
|
||||
BIO_set_nbio(wsi->client_bio, 1); /* nonblocking */
|
||||
#endif
|
||||
|
||||
SSL_set_ex_data(wsi->ssl,
|
||||
openssl_websocket_private_data_index,
|
||||
context);
|
||||
}
|
||||
|
||||
if (wsi->use_ssl) {
|
||||
lws_latency_pre(context, wsi);
|
||||
n = SSL_connect(wsi->ssl);
|
||||
lws_latency(context, wsi,
|
||||
"SSL_connect LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE",
|
||||
n, n > 0);
|
||||
|
||||
if (n < 0) {
|
||||
n = SSL_get_error(wsi->ssl, n);
|
||||
|
||||
if (n == SSL_ERROR_WANT_READ ||
|
||||
n == SSL_ERROR_WANT_WRITE) {
|
||||
/*
|
||||
* wants us to retry connect due to
|
||||
* state of the underlying ssl layer...
|
||||
* but since it may be stalled on
|
||||
* blocked write, no incoming data may
|
||||
* arrive to trigger the retry.
|
||||
* Force (possibly many times if the SSL
|
||||
* state persists in returning the
|
||||
* condition code, but other sockets
|
||||
* are getting serviced inbetweentimes)
|
||||
* us to get called back when writable.
|
||||
*/
|
||||
|
||||
lwsl_info(
|
||||
"SSL_connect WANT_... retrying\n");
|
||||
libwebsocket_callback_on_writable(
|
||||
context, wsi);
|
||||
|
||||
wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_SSL;
|
||||
|
||||
return 0; /* no error */
|
||||
}
|
||||
n = -1;
|
||||
}
|
||||
|
||||
if (n <= 0) {
|
||||
/*
|
||||
* retry if new data comes until we
|
||||
* run into the connection timeout or win
|
||||
*/
|
||||
|
||||
n = ERR_get_error();
|
||||
if (n != SSL_ERROR_NONE) {
|
||||
lwsl_err("SSL connect error %lu: %s\n",
|
||||
n,
|
||||
ERR_error_string(n,
|
||||
(char *)context->service_buffer));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else
|
||||
wsi->ssl = NULL;
|
||||
|
||||
/* fallthru */
|
||||
|
||||
case LWS_CONNMODE_WS_CLIENT_WAITING_SSL:
|
||||
|
||||
if (wsi->use_ssl) {
|
||||
|
||||
if (wsi->mode == LWS_CONNMODE_WS_CLIENT_WAITING_SSL) {
|
||||
lws_latency_pre(context, wsi);
|
||||
n = SSL_connect(wsi->ssl);
|
||||
lws_latency(context, wsi,
|
||||
"SSL_connect LWS_CONNMODE_WS_CLIENT_WAITING_SSL",
|
||||
n, n > 0);
|
||||
|
||||
if (n < 0) {
|
||||
n = SSL_get_error(wsi->ssl, n);
|
||||
|
||||
if (n == SSL_ERROR_WANT_READ ||
|
||||
n == SSL_ERROR_WANT_WRITE) {
|
||||
/*
|
||||
* wants us to retry connect due to
|
||||
* state of the underlying ssl layer...
|
||||
* but since it may be stalled on
|
||||
* blocked write, no incoming data may
|
||||
* arrive to trigger the retry.
|
||||
* Force (possibly many times if the SSL
|
||||
* state persists in returning the
|
||||
* condition code, but other sockets
|
||||
* are getting serviced inbetweentimes)
|
||||
* us to get called back when writable.
|
||||
*/
|
||||
|
||||
lwsl_info(
|
||||
"SSL_connect WANT_... retrying\n");
|
||||
libwebsocket_callback_on_writable(
|
||||
context, wsi);
|
||||
|
||||
wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_SSL;
|
||||
|
||||
return 0; /* no error */
|
||||
}
|
||||
n = -1;
|
||||
}
|
||||
|
||||
if (n <= 0) {
|
||||
/*
|
||||
* retry if new data comes until we
|
||||
* run into the connection timeout or win
|
||||
*/
|
||||
n = ERR_get_error();
|
||||
if (n != SSL_ERROR_NONE) {
|
||||
lwsl_err("SSL connect error %lu: %s\n",
|
||||
n,
|
||||
ERR_error_string(n,
|
||||
(char *)context->service_buffer));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef USE_CYASSL
|
||||
/*
|
||||
* See comment above about CyaSSL certificate
|
||||
* verification
|
||||
*/
|
||||
lws_latency_pre(context, wsi);
|
||||
n = SSL_get_verify_result(wsi->ssl);
|
||||
lws_latency(context, wsi,
|
||||
"SSL_get_verify_result LWS_CONNMODE..HANDSHAKE",
|
||||
n, n > 0);
|
||||
if ((n != X509_V_OK) && (
|
||||
n != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ||
|
||||
wsi->use_ssl != 2)) {
|
||||
|
||||
lwsl_err(
|
||||
"server's cert didn't look good %d\n", n);
|
||||
libwebsocket_close_and_free_session(context,
|
||||
wsi, LWS_CLOSE_STATUS_NOSTATUS);
|
||||
return 0;
|
||||
}
|
||||
#endif /* USE_CYASSL */
|
||||
} else
|
||||
wsi->ssl = NULL;
|
||||
#endif
|
||||
|
||||
wsi->mode = LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE2;
|
||||
libwebsocket_set_timeout(wsi,
|
||||
PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND,
|
||||
AWAITING_TIMEOUT);
|
||||
|
||||
/* fallthru */
|
||||
|
||||
case LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE2:
|
||||
p = libwebsockets_generate_client_handshake(context, wsi, p);
|
||||
if (p == NULL) {
|
||||
lwsl_err("Failed to generate handshake for client\n");
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* send our request to the server */
|
||||
|
||||
lws_latency_pre(context, wsi);
|
||||
|
||||
n = lws_ssl_capable_write(wsi, context->service_buffer, p - (char *)context->service_buffer);
|
||||
lws_latency(context, wsi, "send lws_issue_raw", n, n == p - (char *)context->service_buffer);
|
||||
switch (n) {
|
||||
case LWS_SSL_CAPABLE_ERROR:
|
||||
lwsl_debug("ERROR writing to client socket\n");
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
return 0;
|
||||
case LWS_SSL_CAPABLE_MORE_SERVICE:
|
||||
libwebsocket_callback_on_writable(context, wsi);
|
||||
break;
|
||||
}
|
||||
|
||||
wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART;
|
||||
wsi->u.hdr.lextable_pos = 0;
|
||||
wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY;
|
||||
libwebsocket_set_timeout(wsi,
|
||||
PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE,
|
||||
AWAITING_TIMEOUT);
|
||||
break;
|
||||
|
||||
case LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY:
|
||||
|
||||
/* handle server hung up on us */
|
||||
|
||||
if (pollfd->revents & LWS_POLLHUP) {
|
||||
|
||||
lwsl_debug("Server connection %p (fd=%d) dead\n",
|
||||
(void *)wsi, pollfd->fd);
|
||||
|
||||
goto bail3;
|
||||
}
|
||||
|
||||
if (!(pollfd->revents & LWS_POLLIN))
|
||||
break;
|
||||
|
||||
/* 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->u.hdr.parser_state != WSI_PARSING_COMPLETE &&
|
||||
len > 0) {
|
||||
n = lws_ssl_capable_read(wsi, &c, 1);
|
||||
lws_latency(context, wsi, "send lws_issue_raw", n, n == 1);
|
||||
switch (n) {
|
||||
case LWS_SSL_CAPABLE_ERROR:
|
||||
goto bail3;
|
||||
case LWS_SSL_CAPABLE_MORE_SERVICE:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (libwebsocket_parse(context, wsi, c)) {
|
||||
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->u.hdr.parser_state != WSI_PARSING_COMPLETE)
|
||||
break;
|
||||
|
||||
/*
|
||||
* 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(context, wsi);
|
||||
|
||||
bail3:
|
||||
lwsl_info(
|
||||
"closing connection at LWS_CONNMODE...SERVER_REPLY\n");
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
return -1;
|
||||
|
||||
case LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT:
|
||||
lwsl_ext("LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT\n");
|
||||
break;
|
||||
|
||||
case LWS_CONNMODE_WS_CLIENT_PENDING_CANDIDATE_CHILD:
|
||||
lwsl_ext("LWS_CONNMODE_WS_CLIENT_PENDING_CANDIDATE_CHILD\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* In-place str to lower case
|
||||
*/
|
||||
|
||||
static void
|
||||
strtolower(char *s)
|
||||
{
|
||||
while (*s) {
|
||||
*s = tolower((int)*s);
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
lws_client_interpret_server_handshake(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi)
|
||||
{
|
||||
const char *pc;
|
||||
int okay = 0;
|
||||
char *p;
|
||||
int len;
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
char ext_name[128];
|
||||
struct libwebsocket_extension *ext;
|
||||
void *v;
|
||||
int more = 1;
|
||||
const char *c;
|
||||
#endif
|
||||
int n;
|
||||
int close_reason = LWS_CLOSE_STATUS_PROTOCOL_ERR;
|
||||
|
||||
/*
|
||||
* well, what the server sent looked reasonable for syntax.
|
||||
* Now let's confirm it sent all the necessary headers
|
||||
*/
|
||||
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_ACCEPT) == 0) {
|
||||
lwsl_info("no ACCEPT\n");
|
||||
goto bail3;
|
||||
}
|
||||
|
||||
p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP);
|
||||
if (!p) {
|
||||
lwsl_info("no URI\n");
|
||||
goto bail3;
|
||||
}
|
||||
if (p && strncmp(p, "101", 3)) {
|
||||
lwsl_warn(
|
||||
"lws_client_handshake: got bad HTTP response '%s'\n", p);
|
||||
goto bail3;
|
||||
}
|
||||
|
||||
p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_UPGRADE);
|
||||
if (!p) {
|
||||
lwsl_info("no UPGRADE\n");
|
||||
goto bail3;
|
||||
}
|
||||
strtolower(p);
|
||||
if (strcmp(p, "websocket")) {
|
||||
lwsl_warn(
|
||||
"lws_client_handshake: got bad Upgrade header '%s'\n", p);
|
||||
goto bail3;
|
||||
}
|
||||
|
||||
p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_CONNECTION);
|
||||
if (!p) {
|
||||
lwsl_info("no Connection hdr\n");
|
||||
goto bail3;
|
||||
}
|
||||
strtolower(p);
|
||||
if (strcmp(p, "upgrade")) {
|
||||
lwsl_warn("lws_client_int_s_hs: bad header %s\n", p);
|
||||
goto bail3;
|
||||
}
|
||||
|
||||
pc = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS);
|
||||
if (pc == NULL)
|
||||
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("lws_client_int_s_hs: WSI_TOKEN_PROTOCOL is null\n");
|
||||
/*
|
||||
* no protocol name to work from,
|
||||
* default to first protocol
|
||||
*/
|
||||
wsi->protocol = &context->protocols[0];
|
||||
goto check_extensions;
|
||||
}
|
||||
|
||||
p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL);
|
||||
len = strlen(p);
|
||||
|
||||
while (*pc && !okay) {
|
||||
if (!strncmp(pc, p, len) &&
|
||||
(pc[len] == ',' || pc[len] == '\0')) {
|
||||
okay = 1;
|
||||
continue;
|
||||
}
|
||||
while (*pc && *pc != ',')
|
||||
pc++;
|
||||
while (*pc && *pc != ' ')
|
||||
pc++;
|
||||
}
|
||||
|
||||
if (!okay) {
|
||||
lwsl_err("lws_client_int_s_hs: got bad protocol %s\n", p);
|
||||
goto bail2;
|
||||
}
|
||||
|
||||
/*
|
||||
* identify the selected protocol struct and set it
|
||||
*/
|
||||
n = 0;
|
||||
wsi->protocol = NULL;
|
||||
while (context->protocols[n].callback && !wsi->protocol) {
|
||||
if (strcmp(p, context->protocols[n].name) == 0) {
|
||||
wsi->protocol = &context->protocols[n];
|
||||
break;
|
||||
}
|
||||
n++;
|
||||
}
|
||||
|
||||
if (wsi->protocol == NULL) {
|
||||
lwsl_err("lws_client_int_s_hs: fail protocol %s\n", p);
|
||||
goto bail2;
|
||||
}
|
||||
|
||||
|
||||
check_extensions:
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
/* instantiate the accepted extensions */
|
||||
|
||||
if (!lws_hdr_total_length(wsi, WSI_TOKEN_EXTENSIONS)) {
|
||||
lwsl_ext("no client extenstions 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, (char *)context->service_buffer,
|
||||
sizeof(context->service_buffer), WSI_TOKEN_EXTENSIONS) < 0) {
|
||||
lwsl_warn("ext list from server failed to copy\n");
|
||||
goto bail2;
|
||||
}
|
||||
|
||||
c = (char *)context->service_buffer;
|
||||
n = 0;
|
||||
while (more) {
|
||||
|
||||
if (*c && (*c != ',' && *c != ' ' && *c != '\t')) {
|
||||
ext_name[n] = *c++;
|
||||
if (n < sizeof(ext_name) - 1)
|
||||
n++;
|
||||
continue;
|
||||
}
|
||||
ext_name[n] = '\0';
|
||||
if (!*c)
|
||||
more = 0;
|
||||
else {
|
||||
c++;
|
||||
if (!n)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* check we actually support it */
|
||||
|
||||
lwsl_ext("checking client ext %s\n", ext_name);
|
||||
|
||||
n = 0;
|
||||
ext = wsi->protocol->owning_server->extensions;
|
||||
while (ext && ext->callback) {
|
||||
|
||||
if (strcmp(ext_name, ext->name)) {
|
||||
ext++;
|
||||
continue;
|
||||
}
|
||||
|
||||
n = 1;
|
||||
|
||||
lwsl_ext("instantiating client ext %s\n", ext_name);
|
||||
|
||||
/* instantiate the extension on this conn */
|
||||
|
||||
wsi->active_extensions_user[
|
||||
wsi->count_active_extensions] =
|
||||
malloc(ext->per_session_data_size);
|
||||
if (wsi->active_extensions_user[
|
||||
wsi->count_active_extensions] == NULL) {
|
||||
lwsl_err("Out of mem\n");
|
||||
goto bail2;
|
||||
}
|
||||
memset(wsi->active_extensions_user[
|
||||
wsi->count_active_extensions], 0,
|
||||
ext->per_session_data_size);
|
||||
wsi->active_extensions[
|
||||
wsi->count_active_extensions] = ext;
|
||||
|
||||
/* allow him to construct his context */
|
||||
|
||||
ext->callback(wsi->protocol->owning_server,
|
||||
ext, wsi,
|
||||
LWS_EXT_CALLBACK_CLIENT_CONSTRUCT,
|
||||
wsi->active_extensions_user[
|
||||
wsi->count_active_extensions],
|
||||
NULL, 0);
|
||||
|
||||
wsi->count_active_extensions++;
|
||||
|
||||
ext++;
|
||||
}
|
||||
|
||||
if (n == 0) {
|
||||
lwsl_warn("Unknown ext '%s'!\n", ext_name);
|
||||
goto bail2;
|
||||
}
|
||||
|
||||
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->u.hdr.ah->initial_handshake_hash_base64)) {
|
||||
lwsl_warn("lws_client_int_s_hs: accept %s wrong vs %s\n", p,
|
||||
wsi->u.hdr.ah->initial_handshake_hash_base64);
|
||||
goto bail2;
|
||||
}
|
||||
|
||||
/* allocate the per-connection user memory (if any) */
|
||||
if (libwebsocket_ensure_user_space(wsi)) {
|
||||
lwsl_err("Problem allocating wsi user mem\n");
|
||||
goto bail2;
|
||||
}
|
||||
|
||||
/*
|
||||
* we seem to be good to go, give client last chance to check
|
||||
* headers and OK it
|
||||
*/
|
||||
|
||||
wsi->protocol->callback(context, wsi,
|
||||
LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH,
|
||||
wsi->user_space, NULL, 0);
|
||||
|
||||
/* clear his proxy connection timeout */
|
||||
|
||||
libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
|
||||
|
||||
/* free up his parsing allocations */
|
||||
if (wsi->u.hdr.ah)
|
||||
free(wsi->u.hdr.ah);
|
||||
|
||||
/* mark him as being alive */
|
||||
|
||||
wsi->state = WSI_STATE_ESTABLISHED;
|
||||
wsi->mode = LWS_CONNMODE_WS_CLIENT;
|
||||
|
||||
/* union transition */
|
||||
|
||||
memset(&wsi->u, 0, sizeof(wsi->u));
|
||||
|
||||
wsi->u.ws.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 = wsi->protocol->rx_buffer_size;
|
||||
if (!n)
|
||||
n = LWS_MAX_SOCKET_IO_BUF;
|
||||
n += LWS_SEND_BUFFER_PRE_PADDING + LWS_SEND_BUFFER_POST_PADDING;
|
||||
wsi->u.ws.rx_user_buffer = malloc(n);
|
||||
if (!wsi->u.ws.rx_user_buffer) {
|
||||
lwsl_err("Out of Mem allocating rx buffer %d\n", n);
|
||||
goto bail2;
|
||||
}
|
||||
lwsl_info("Allocating client RX buffer %d\n", n);
|
||||
|
||||
if (setsockopt(wsi->sock, SOL_SOCKET, SO_SNDBUF, (const char *)&n, sizeof n)) {
|
||||
lwsl_warn("Failed to set SNDBUF to %d", n);
|
||||
goto bail3;
|
||||
}
|
||||
|
||||
lwsl_debug("handshake OK for protocol %s\n", wsi->protocol->name);
|
||||
|
||||
/* call him back to inform him he is up */
|
||||
|
||||
wsi->protocol->callback(context, wsi,
|
||||
LWS_CALLBACK_CLIENT_ESTABLISHED,
|
||||
wsi->user_space, NULL, 0);
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
/*
|
||||
* inform all extensions, not just active ones since they
|
||||
* already know
|
||||
*/
|
||||
|
||||
ext = context->extensions;
|
||||
|
||||
while (ext && ext->callback) {
|
||||
v = NULL;
|
||||
for (n = 0; n < wsi->count_active_extensions; n++)
|
||||
if (wsi->active_extensions[n] == ext)
|
||||
v = wsi->active_extensions_user[n];
|
||||
|
||||
ext->callback(context, ext, wsi,
|
||||
LWS_EXT_CALLBACK_ANY_WSI_ESTABLISHED, v, NULL, 0);
|
||||
ext++;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
bail3:
|
||||
free(wsi->u.ws.rx_user_buffer);
|
||||
wsi->u.ws.rx_user_buffer = NULL;
|
||||
close_reason = LWS_CLOSE_STATUS_NOSTATUS;
|
||||
|
||||
bail2:
|
||||
if (wsi->protocol)
|
||||
wsi->protocol->callback(context, wsi,
|
||||
LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
|
||||
wsi->user_space, NULL, 0);
|
||||
|
||||
lwsl_info("closing connection due to bail2 connection error\n");
|
||||
|
||||
/* free up his parsing allocations */
|
||||
|
||||
if (wsi->u.hdr.ah)
|
||||
free(wsi->u.hdr.ah);
|
||||
|
||||
libwebsocket_close_and_free_session(context, wsi, close_reason);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
libwebsockets_generate_client_handshake(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, char *pkt)
|
||||
{
|
||||
char buf[128];
|
||||
char hash[20];
|
||||
char key_b64[40];
|
||||
char *p = pkt;
|
||||
int n;
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
struct libwebsocket_extension *ext;
|
||||
int ext_count = 0;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* create the random key
|
||||
*/
|
||||
|
||||
n = libwebsockets_get_random(context, hash, 16);
|
||||
if (n != 16) {
|
||||
lwsl_err("Unable to read from random dev %s\n",
|
||||
SYSTEM_RANDOM_FILEPATH);
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lws_b64_encode_string(hash, 16, key_b64, sizeof(key_b64));
|
||||
|
||||
/*
|
||||
* 00 example client handshake
|
||||
*
|
||||
* GET /socket.io/websocket HTTP/1.1
|
||||
* Upgrade: WebSocket
|
||||
* Connection: Upgrade
|
||||
* Host: 127.0.0.1:9999
|
||||
* Origin: http://127.0.0.1
|
||||
* Sec-WebSocket-Key1: 1 0 2#0W 9 89 7 92 ^
|
||||
* Sec-WebSocket-Key2: 7 7Y 4328 B2v[8(z1
|
||||
* Cookie: socketio=websocket
|
||||
*
|
||||
* (Á®Ä0¶†≥
|
||||
*
|
||||
* 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, "GET %s HTTP/1.1\x0d\x0a",
|
||||
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));
|
||||
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_ORIGIN))
|
||||
p += sprintf(p, "Origin: http://%s\x0d\x0a",
|
||||
lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN));
|
||||
|
||||
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 */
|
||||
|
||||
p += sprintf(p, "Sec-WebSocket-Extensions: ");
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
ext = context->extensions;
|
||||
while (ext && ext->callback) {
|
||||
|
||||
n = lws_ext_callback_for_each_extension_type(context, wsi,
|
||||
LWS_EXT_CALLBACK_CHECK_OK_TO_PROPOSE_EXTENSION,
|
||||
(char *)ext->name, 0);
|
||||
if (n) { /* an extension vetos us */
|
||||
lwsl_ext("ext %s vetoed\n", (char *)ext->name);
|
||||
ext++;
|
||||
continue;
|
||||
}
|
||||
|
||||
n = context->protocols[0].callback(context, 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++ = ',';
|
||||
p += sprintf(p, "%s", ext->name);
|
||||
ext_count++;
|
||||
|
||||
ext++;
|
||||
}
|
||||
#endif
|
||||
p += sprintf(p, "\x0d\x0a");
|
||||
|
||||
if (wsi->ietf_spec_revision)
|
||||
p += sprintf(p, "Sec-WebSocket-Version: %d\x0d\x0a",
|
||||
wsi->ietf_spec_revision);
|
||||
|
||||
/* give userland a chance to append, eg, cookies */
|
||||
|
||||
context->protocols[0].callback(context, wsi,
|
||||
LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER,
|
||||
NULL, &p, (pkt + sizeof(context->service_buffer)) - p - 12);
|
||||
|
||||
p += sprintf(p, "\x0d\x0a");
|
||||
|
||||
/* 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);
|
||||
|
||||
SHA1((unsigned char *)buf, n, (unsigned char *)hash);
|
||||
|
||||
lws_b64_encode_string(hash, 20,
|
||||
wsi->u.hdr.ah->initial_handshake_hash_base64,
|
||||
sizeof(wsi->u.hdr.ah->initial_handshake_hash_base64));
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
341
dependencies/libwebsockets/lib/context.c
vendored
Normal file
341
dependencies/libwebsockets/lib/context.c
vendored
Normal file
@ -0,0 +1,341 @@
|
||||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010-2014 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 "private-libwebsockets.h"
|
||||
|
||||
#ifndef LWS_BUILD_HASH
|
||||
#define LWS_BUILD_HASH "unknown-build-hash"
|
||||
#endif
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* libwebsocket_create_context() - Create the websocket handler
|
||||
* @info: pointer to struct with parameters
|
||||
*
|
||||
* This function creates the listening socket (if serving) and takes care
|
||||
* of all initialization in one step.
|
||||
*
|
||||
* After initialization, it returns a struct libwebsocket_context * that
|
||||
* represents this server. After calling, user code needs to take care
|
||||
* of calling libwebsocket_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 callack 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 struct libwebsocket_context *
|
||||
libwebsocket_create_context(struct lws_context_creation_info *info)
|
||||
{
|
||||
struct libwebsocket_context *context = NULL;
|
||||
char *p;
|
||||
|
||||
int pid_daemon = get_daemonize_pid();
|
||||
|
||||
lwsl_notice("Initial logging level %d\n", log_level);
|
||||
lwsl_notice("Library version: %s\n", library_version);
|
||||
#ifdef LWS_USE_IPV6
|
||||
if (!(info->options & LWS_SERVER_OPTION_DISABLE_IPV6))
|
||||
lwsl_notice("IPV6 compiled in and enabled\n");
|
||||
else
|
||||
lwsl_notice("IPV6 compiled in but disabled\n");
|
||||
#else
|
||||
lwsl_notice("IPV6 not compiled in\n");
|
||||
#endif
|
||||
lws_feature_status_libev(info);
|
||||
lwsl_info(" LWS_MAX_HEADER_LEN: %u\n", LWS_MAX_HEADER_LEN);
|
||||
lwsl_info(" LWS_MAX_PROTOCOLS: %u\n", LWS_MAX_PROTOCOLS);
|
||||
|
||||
lwsl_info(" SPEC_LATEST_SUPPORTED: %u\n", SPEC_LATEST_SUPPORTED);
|
||||
lwsl_info(" AWAITING_TIMEOUT: %u\n", AWAITING_TIMEOUT);
|
||||
lwsl_info(" SYSTEM_RANDOM_FILEPATH: '%s'\n", SYSTEM_RANDOM_FILEPATH);
|
||||
lwsl_info(" LWS_MAX_ZLIB_CONN_BUFFER: %u\n", LWS_MAX_ZLIB_CONN_BUFFER);
|
||||
|
||||
if (lws_plat_context_early_init())
|
||||
return NULL;
|
||||
|
||||
context = (struct libwebsocket_context *)
|
||||
malloc(sizeof(struct libwebsocket_context));
|
||||
if (!context) {
|
||||
lwsl_err("No memory for websocket context\n");
|
||||
return NULL;
|
||||
}
|
||||
memset(context, 0, sizeof(*context));
|
||||
|
||||
if (pid_daemon) {
|
||||
context->started_with_parent = pid_daemon;
|
||||
lwsl_notice(" Started with daemon pid %d\n", pid_daemon);
|
||||
}
|
||||
|
||||
context->listen_service_extraseen = 0;
|
||||
context->protocols = info->protocols;
|
||||
context->token_limits = info->token_limits;
|
||||
context->listen_port = info->port;
|
||||
context->http_proxy_port = 0;
|
||||
context->http_proxy_address[0] = '\0';
|
||||
context->options = info->options;
|
||||
context->iface = info->iface;
|
||||
/* to reduce this allocation, */
|
||||
context->max_fds = getdtablesize();
|
||||
lwsl_notice(" static allocation: %u + (%u x %u fds) = %u bytes\n",
|
||||
sizeof(struct libwebsocket_context),
|
||||
sizeof(struct libwebsocket_pollfd) +
|
||||
sizeof(struct libwebsocket *),
|
||||
context->max_fds,
|
||||
sizeof(struct libwebsocket_context) +
|
||||
((sizeof(struct libwebsocket_pollfd) +
|
||||
sizeof(struct libwebsocket *)) *
|
||||
context->max_fds));
|
||||
|
||||
context->fds = (struct libwebsocket_pollfd *)
|
||||
malloc(sizeof(struct libwebsocket_pollfd) *
|
||||
context->max_fds);
|
||||
if (context->fds == NULL) {
|
||||
lwsl_err("Unable to allocate fds array for %d connections\n",
|
||||
context->max_fds);
|
||||
free(context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
context->lws_lookup = (struct libwebsocket **)
|
||||
malloc(sizeof(struct libwebsocket *) * context->max_fds);
|
||||
if (context->lws_lookup == NULL) {
|
||||
lwsl_err(
|
||||
"Unable to allocate lws_lookup array for %d connections\n",
|
||||
context->max_fds);
|
||||
free(context->fds);
|
||||
free(context);
|
||||
return NULL;
|
||||
}
|
||||
memset(context->lws_lookup, 0, sizeof(struct libwebsocket *) *
|
||||
context->max_fds);
|
||||
|
||||
if (lws_plat_init_fd_tables(context)) {
|
||||
free(context->lws_lookup);
|
||||
free(context->fds);
|
||||
free(context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lws_context_init_extensions(info, context);
|
||||
|
||||
context->user_space = info->user;
|
||||
|
||||
strcpy(context->canonical_hostname, "unknown");
|
||||
|
||||
lws_server_get_canonical_hostname(context, info);
|
||||
|
||||
/* split the proxy ads:port if given */
|
||||
|
||||
if (info->http_proxy_address) {
|
||||
strncpy(context->http_proxy_address, info->http_proxy_address,
|
||||
sizeof(context->http_proxy_address) - 1);
|
||||
context->http_proxy_address[
|
||||
sizeof(context->http_proxy_address) - 1] = '\0';
|
||||
context->http_proxy_port = info->http_proxy_port;
|
||||
} else {
|
||||
#ifdef HAVE_GETENV
|
||||
p = getenv("http_proxy");
|
||||
if (p) {
|
||||
strncpy(context->http_proxy_address, p,
|
||||
sizeof(context->http_proxy_address) - 1);
|
||||
context->http_proxy_address[
|
||||
sizeof(context->http_proxy_address) - 1] = '\0';
|
||||
|
||||
p = strchr(context->http_proxy_address, ':');
|
||||
if (p == NULL) {
|
||||
lwsl_err("http_proxy needs to be ads:port\n");
|
||||
goto bail;
|
||||
}
|
||||
*p = '\0';
|
||||
context->http_proxy_port = atoi(p + 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (context->http_proxy_address[0])
|
||||
lwsl_notice(" Proxy %s:%u\n",
|
||||
context->http_proxy_address,
|
||||
context->http_proxy_port);
|
||||
|
||||
lwsl_notice(
|
||||
" per-conn mem: %u + %u headers + protocol rx buf\n",
|
||||
sizeof(struct libwebsocket),
|
||||
sizeof(struct allocated_headers));
|
||||
|
||||
if (lws_context_init_server_ssl(info, context))
|
||||
goto bail;
|
||||
|
||||
if (lws_context_init_client_ssl(info, context))
|
||||
goto bail;
|
||||
|
||||
if (lws_context_init_server(info, context))
|
||||
goto bail;
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
lws_plat_drop_app_privileges(info);
|
||||
|
||||
/* initialize supported protocols */
|
||||
|
||||
for (context->count_protocols = 0;
|
||||
info->protocols[context->count_protocols].callback;
|
||||
context->count_protocols++) {
|
||||
|
||||
lwsl_parser(" Protocol: %s\n",
|
||||
info->protocols[context->count_protocols].name);
|
||||
|
||||
info->protocols[context->count_protocols].owning_server =
|
||||
context;
|
||||
info->protocols[context->count_protocols].protocol_index =
|
||||
context->count_protocols;
|
||||
|
||||
/*
|
||||
* inform all the protocols that they are doing their one-time
|
||||
* initialization if they want to
|
||||
*/
|
||||
info->protocols[context->count_protocols].callback(context,
|
||||
NULL, LWS_CALLBACK_PROTOCOL_INIT, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* give all extensions a chance to create any per-context
|
||||
* allocations they need
|
||||
*/
|
||||
|
||||
if (info->port != CONTEXT_PORT_NO_LISTEN) {
|
||||
if (lws_ext_callback_for_each_extension_type(context, NULL,
|
||||
LWS_EXT_CALLBACK_SERVER_CONTEXT_CONSTRUCT,
|
||||
NULL, 0) < 0)
|
||||
goto bail;
|
||||
} else
|
||||
if (lws_ext_callback_for_each_extension_type(context, NULL,
|
||||
LWS_EXT_CALLBACK_CLIENT_CONTEXT_CONSTRUCT,
|
||||
NULL, 0) < 0)
|
||||
goto bail;
|
||||
|
||||
return context;
|
||||
|
||||
bail:
|
||||
libwebsocket_context_destroy(context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* libwebsocket_context_destroy() - Destroy the websocket context
|
||||
* @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 void
|
||||
libwebsocket_context_destroy(struct libwebsocket_context *context)
|
||||
{
|
||||
int n;
|
||||
struct libwebsocket_protocols *protocol = context->protocols;
|
||||
|
||||
lwsl_notice("%s\n", __func__);
|
||||
|
||||
#ifdef LWS_LATENCY
|
||||
if (context->worst_latency_info[0])
|
||||
lwsl_notice("Worst latency: %s\n", context->worst_latency_info);
|
||||
#endif
|
||||
|
||||
for (n = 0; n < context->fds_count; n++) {
|
||||
struct libwebsocket *wsi =
|
||||
context->lws_lookup[context->fds[n].fd];
|
||||
if (!wsi)
|
||||
continue;
|
||||
libwebsocket_close_and_free_session(context,
|
||||
wsi, LWS_CLOSE_STATUS_NOSTATUS /* no protocol close */);
|
||||
n--;
|
||||
}
|
||||
|
||||
/*
|
||||
* give all extensions a chance to clean up any per-context
|
||||
* allocations they might have made
|
||||
*/
|
||||
if (context->listen_port) {
|
||||
if (lws_ext_callback_for_each_extension_type(context, NULL,
|
||||
LWS_EXT_CALLBACK_SERVER_CONTEXT_DESTRUCT, NULL, 0) < 0)
|
||||
return;
|
||||
} else
|
||||
if (lws_ext_callback_for_each_extension_type(context, NULL,
|
||||
LWS_EXT_CALLBACK_CLIENT_CONTEXT_DESTRUCT, NULL, 0) < 0)
|
||||
return;
|
||||
|
||||
/*
|
||||
* inform all the protocols that they are done and will have no more
|
||||
* callbacks
|
||||
*/
|
||||
|
||||
while (protocol->callback) {
|
||||
protocol->callback(context, NULL, LWS_CALLBACK_PROTOCOL_DESTROY,
|
||||
NULL, NULL, 0);
|
||||
protocol++;
|
||||
}
|
||||
|
||||
lws_plat_context_early_destroy(context);
|
||||
|
||||
lws_ssl_context_destroy(context);
|
||||
|
||||
if (context->fds)
|
||||
free(context->fds);
|
||||
if (context->lws_lookup)
|
||||
free(context->lws_lookup);
|
||||
|
||||
lws_plat_context_late_destroy(context);
|
||||
|
||||
free(context);
|
||||
}
|
||||
222
dependencies/libwebsockets/lib/daemonize.c
vendored
Normal file
222
dependencies/libwebsockets/lib/daemonize.c
vendored
Normal file
@ -0,0 +1,222 @@
|
||||
/*
|
||||
* This code is mainly taken from Doug Potter's page
|
||||
*
|
||||
* http://www-theorie.physik.unizh.ch/~dpotter/howto/daemonize
|
||||
*
|
||||
* I contacted him 2007-04-16 about the license for the original code,
|
||||
* he replied it is Public Domain. Use the URL above to get the original
|
||||
* Public Domain version if you want it.
|
||||
*
|
||||
* This version is LGPL2 and is (c)2006 - 2013 Andy Green <andy@warmcat.com>
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "private-libwebsockets.h"
|
||||
|
||||
int pid_daemon;
|
||||
static char *lock_path;
|
||||
|
||||
int get_daemonize_pid()
|
||||
{
|
||||
return pid_daemon;
|
||||
}
|
||||
|
||||
static void
|
||||
child_handler(int signum)
|
||||
{
|
||||
int fd;
|
||||
int len;
|
||||
int sent;
|
||||
char sz[20];
|
||||
|
||||
switch (signum) {
|
||||
|
||||
case SIGALRM: /* timedout daemonizing */
|
||||
exit(1);
|
||||
break;
|
||||
|
||||
case SIGUSR1: /* positive confirmation we daemonized well */
|
||||
/* Create the lock file as the current user */
|
||||
|
||||
fd = open(lock_path, O_TRUNC | O_RDWR | O_CREAT, 0640);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr,
|
||||
"unable to create lock file %s, code=%d (%s)\n",
|
||||
lock_path, errno, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
len = sprintf(sz, "%u", pid_daemon);
|
||||
sent = write(fd, sz, len);
|
||||
if (sent != len)
|
||||
fprintf(stderr,
|
||||
"unable write pid to lock file %s, code=%d (%s)\n",
|
||||
lock_path, errno, strerror(errno));
|
||||
|
||||
close(fd);
|
||||
exit(!!(sent == len));
|
||||
|
||||
case SIGCHLD: /* daemonization failed */
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void lws_daemon_closing(int sigact)
|
||||
{
|
||||
if (getpid() == pid_daemon)
|
||||
if (lock_path) {
|
||||
unlink(lock_path);
|
||||
free(lock_path);
|
||||
lock_path = NULL;
|
||||
}
|
||||
|
||||
kill(getpid(), SIGKILL);
|
||||
}
|
||||
|
||||
/*
|
||||
* You just need to call this from your main(), when it
|
||||
* returns you are all set "in the background" decoupled
|
||||
* from the console you were started from.
|
||||
*
|
||||
* The process context you called from has been terminated then.
|
||||
*/
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_daemonize(const char *_lock_path)
|
||||
{
|
||||
pid_t sid, parent;
|
||||
int fd;
|
||||
char buf[10];
|
||||
int n, ret;
|
||||
struct sigaction act;
|
||||
|
||||
/* already a daemon */
|
||||
if (getppid() == 1)
|
||||
return 1;
|
||||
|
||||
fd = open(_lock_path, O_RDONLY);
|
||||
if (fd > 0) {
|
||||
n = read(fd, buf, sizeof(buf));
|
||||
close(fd);
|
||||
if (n) {
|
||||
n = atoi(buf);
|
||||
ret = kill(n, 0);
|
||||
if (ret >= 0) {
|
||||
fprintf(stderr,
|
||||
"Daemon already running from pid %d\n", n);
|
||||
exit(1);
|
||||
}
|
||||
fprintf(stderr,
|
||||
"Removing stale lock file %s from dead pid %d\n",
|
||||
_lock_path, n);
|
||||
unlink(lock_path);
|
||||
}
|
||||
}
|
||||
|
||||
n = strlen(_lock_path) + 1;
|
||||
lock_path = malloc(n);
|
||||
if (!lock_path) {
|
||||
fprintf(stderr, "Out of mem in lws_daemonize\n");
|
||||
return 1;
|
||||
}
|
||||
strcpy(lock_path, _lock_path);
|
||||
|
||||
/* Trap signals that we expect to recieve */
|
||||
signal(SIGCHLD, child_handler); /* died */
|
||||
signal(SIGUSR1, child_handler); /* was happy */
|
||||
signal(SIGALRM, child_handler); /* timeout daemonizing */
|
||||
|
||||
/* Fork off the parent process */
|
||||
pid_daemon = fork();
|
||||
if (pid_daemon < 0) {
|
||||
fprintf(stderr, "unable to fork daemon, code=%d (%s)",
|
||||
errno, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* If we got a good PID, then we can exit the parent process. */
|
||||
if (pid_daemon > 0) {
|
||||
|
||||
/*
|
||||
* Wait for confirmation signal from the child via
|
||||
* SIGCHILD / USR1, or for two seconds to elapse
|
||||
* (SIGALRM). pause() should not return.
|
||||
*/
|
||||
alarm(2);
|
||||
|
||||
pause();
|
||||
/* should not be reachable */
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* At this point we are executing as the child process */
|
||||
parent = getppid();
|
||||
pid_daemon = getpid();
|
||||
|
||||
/* Cancel certain signals */
|
||||
signal(SIGCHLD, SIG_DFL); /* A child process dies */
|
||||
signal(SIGTSTP, SIG_IGN); /* Various TTY signals */
|
||||
signal(SIGTTOU, SIG_IGN);
|
||||
signal(SIGTTIN, SIG_IGN);
|
||||
signal(SIGHUP, SIG_IGN); /* Ignore hangup signal */
|
||||
|
||||
/* Change the file mode mask */
|
||||
umask(0);
|
||||
|
||||
/* Create a new SID for the child process */
|
||||
sid = setsid();
|
||||
if (sid < 0) {
|
||||
fprintf(stderr,
|
||||
"unable to create a new session, code %d (%s)",
|
||||
errno, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Change the current working directory. This prevents the current
|
||||
* directory from being locked; hence not being able to remove it.
|
||||
*/
|
||||
if (chdir("/") < 0) {
|
||||
fprintf(stderr,
|
||||
"unable to change directory to %s, code %d (%s)",
|
||||
"/", errno, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Redirect standard files to /dev/null */
|
||||
if (!freopen("/dev/null", "r", stdin))
|
||||
fprintf(stderr, "unable to freopen() stdin, code %d (%s)",
|
||||
errno, strerror(errno));
|
||||
|
||||
if (!freopen("/dev/null", "w", stdout))
|
||||
fprintf(stderr, "unable to freopen() stdout, code %d (%s)",
|
||||
errno, strerror(errno));
|
||||
|
||||
if (!freopen("/dev/null", "w", stderr))
|
||||
fprintf(stderr, "unable to freopen() stderr, code %d (%s)",
|
||||
errno, strerror(errno));
|
||||
|
||||
/* Tell the parent process that we are A-okay */
|
||||
kill(parent, SIGUSR1);
|
||||
|
||||
act.sa_handler = lws_daemon_closing;
|
||||
sigemptyset(&act.sa_mask);
|
||||
act.sa_flags = 0;
|
||||
|
||||
sigaction(SIGTERM, &act, NULL);
|
||||
|
||||
/* return to continue what is now "the daemon" */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
294
dependencies/libwebsockets/lib/extension-deflate-frame.c
vendored
Normal file
294
dependencies/libwebsockets/lib/extension-deflate-frame.c
vendored
Normal file
@ -0,0 +1,294 @@
|
||||
#include "private-libwebsockets.h"
|
||||
#include "extension-deflate-frame.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define LWS_ZLIB_WINDOW_BITS 15
|
||||
#define LWS_ZLIB_MEMLEVEL 8
|
||||
|
||||
int lws_extension_callback_deflate_frame(
|
||||
struct libwebsocket_context *context,
|
||||
struct libwebsocket_extension *ext,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_extension_callback_reasons reason,
|
||||
void *user, void *in, size_t len)
|
||||
{
|
||||
struct lws_ext_deflate_frame_conn *conn =
|
||||
(struct lws_ext_deflate_frame_conn *)user;
|
||||
struct lws_tokens *eff_buf = (struct lws_tokens *)in;
|
||||
size_t current_payload, remaining_payload, total_payload;
|
||||
int n;
|
||||
size_t len_so_far;
|
||||
|
||||
switch (reason) {
|
||||
|
||||
/*
|
||||
* for deflate-frame, both client and server sides act the same
|
||||
*/
|
||||
|
||||
case LWS_EXT_CALLBACK_CLIENT_CONSTRUCT:
|
||||
case LWS_EXT_CALLBACK_CONSTRUCT:
|
||||
conn->zs_in.zalloc = conn->zs_out.zalloc = Z_NULL;
|
||||
conn->zs_in.zfree = conn->zs_out.zfree = Z_NULL;
|
||||
conn->zs_in.opaque = conn->zs_out.opaque = Z_NULL;
|
||||
n = inflateInit2(&conn->zs_in, -LWS_ZLIB_WINDOW_BITS);
|
||||
if (n != Z_OK) {
|
||||
lwsl_ext("deflateInit returned %d\n", n);
|
||||
return 1;
|
||||
}
|
||||
n = deflateInit2(&conn->zs_out,
|
||||
(context->listen_port ?
|
||||
DEFLATE_FRAME_COMPRESSION_LEVEL_SERVER :
|
||||
DEFLATE_FRAME_COMPRESSION_LEVEL_CLIENT),
|
||||
Z_DEFLATED,
|
||||
-LWS_ZLIB_WINDOW_BITS, LWS_ZLIB_MEMLEVEL,
|
||||
Z_DEFAULT_STRATEGY);
|
||||
if (n != Z_OK) {
|
||||
lwsl_ext("deflateInit2 returned %d\n", n);
|
||||
return 1;
|
||||
}
|
||||
conn->buf_pre_used = 0;
|
||||
conn->buf_pre_length = 0;
|
||||
conn->buf_in_length = sizeof(conn->buf_in);
|
||||
conn->buf_out_length = sizeof(conn->buf_out);
|
||||
conn->compressed_out = 0;
|
||||
conn->buf_pre = NULL;
|
||||
conn->buf_in = (unsigned char *)
|
||||
malloc(LWS_SEND_BUFFER_PRE_PADDING +
|
||||
conn->buf_in_length +
|
||||
LWS_SEND_BUFFER_POST_PADDING);
|
||||
if (!conn->buf_in)
|
||||
goto bail;
|
||||
conn->buf_out = (unsigned char *)
|
||||
malloc(LWS_SEND_BUFFER_PRE_PADDING +
|
||||
conn->buf_out_length +
|
||||
LWS_SEND_BUFFER_POST_PADDING);
|
||||
if (!conn->buf_out)
|
||||
goto bail;
|
||||
lwsl_ext("zlibs constructed\n");
|
||||
break;
|
||||
bail:
|
||||
lwsl_err("Out of mem\n");
|
||||
(void)inflateEnd(&conn->zs_in);
|
||||
(void)deflateEnd(&conn->zs_out);
|
||||
return -1;
|
||||
|
||||
case LWS_EXT_CALLBACK_DESTROY:
|
||||
if (conn->buf_pre)
|
||||
free(conn->buf_pre);
|
||||
free(conn->buf_in);
|
||||
free(conn->buf_out);
|
||||
conn->buf_pre_used = 0;
|
||||
conn->buf_pre_length = 0;
|
||||
conn->buf_in_length = 0;
|
||||
conn->buf_out_length = 0;
|
||||
conn->compressed_out = 0;
|
||||
(void)inflateEnd(&conn->zs_in);
|
||||
(void)deflateEnd(&conn->zs_out);
|
||||
lwsl_ext("zlibs destructed\n");
|
||||
break;
|
||||
|
||||
case LWS_EXT_CALLBACK_PAYLOAD_RX:
|
||||
if (!(wsi->u.ws.rsv & 0x40))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* inflate the incoming payload
|
||||
*/
|
||||
current_payload = eff_buf->token_len;
|
||||
|
||||
remaining_payload = wsi->u.ws.rx_packet_length;
|
||||
if (remaining_payload) {
|
||||
total_payload = conn->buf_pre_used +
|
||||
current_payload +
|
||||
remaining_payload;
|
||||
|
||||
if (conn->buf_pre_length < total_payload) {
|
||||
conn->buf_pre_length = total_payload;
|
||||
if (conn->buf_pre)
|
||||
free(conn->buf_pre);
|
||||
conn->buf_pre =
|
||||
(unsigned char *)malloc(total_payload + 4);
|
||||
if (!conn->buf_pre) {
|
||||
lwsl_err("Out of memory\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(conn->buf_pre + conn->buf_pre_used,
|
||||
eff_buf->token, current_payload);
|
||||
conn->buf_pre_used += current_payload;
|
||||
|
||||
eff_buf->token = NULL;
|
||||
eff_buf->token_len = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
if (conn->buf_pre_used) {
|
||||
total_payload = conn->buf_pre_used +
|
||||
current_payload;
|
||||
|
||||
memcpy(conn->buf_pre + conn->buf_pre_used,
|
||||
eff_buf->token, current_payload);
|
||||
conn->buf_pre_used = 0;
|
||||
|
||||
conn->zs_in.next_in = conn->buf_pre;
|
||||
} else {
|
||||
total_payload = current_payload;
|
||||
|
||||
conn->zs_in.next_in = (unsigned char *)eff_buf->token;
|
||||
}
|
||||
|
||||
conn->zs_in.next_in[total_payload + 0] = 0;
|
||||
conn->zs_in.next_in[total_payload + 1] = 0;
|
||||
conn->zs_in.next_in[total_payload + 2] = 0xff;
|
||||
conn->zs_in.next_in[total_payload + 3] = 0xff;
|
||||
|
||||
conn->zs_in.avail_in = total_payload + 4;
|
||||
|
||||
conn->zs_in.next_out =
|
||||
conn->buf_in + LWS_SEND_BUFFER_PRE_PADDING;
|
||||
conn->zs_in.avail_out = conn->buf_in_length;
|
||||
|
||||
while (1) {
|
||||
n = inflate(&conn->zs_in, Z_SYNC_FLUSH);
|
||||
switch (n) {
|
||||
case Z_NEED_DICT:
|
||||
case Z_STREAM_ERROR:
|
||||
case Z_DATA_ERROR:
|
||||
case Z_MEM_ERROR:
|
||||
/*
|
||||
* screwed.. close the connection...
|
||||
* we will get a destroy callback to take care
|
||||
* of closing nicely
|
||||
*/
|
||||
lwsl_info("zlib error inflate %d: %s\n",
|
||||
n, conn->zs_in.msg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (conn->zs_in.avail_out)
|
||||
break;
|
||||
|
||||
len_so_far = conn->zs_in.next_out -
|
||||
(conn->buf_in + LWS_SEND_BUFFER_PRE_PADDING);
|
||||
|
||||
conn->buf_in_length *= 2;
|
||||
if (conn->buf_in_length > LWS_MAX_ZLIB_CONN_BUFFER) {
|
||||
lwsl_ext("zlib in buffer hit limit %u\n",
|
||||
LWS_MAX_ZLIB_CONN_BUFFER);
|
||||
return -1;
|
||||
}
|
||||
conn->buf_in = (unsigned char *)realloc(conn->buf_in,
|
||||
LWS_SEND_BUFFER_PRE_PADDING +
|
||||
conn->buf_in_length +
|
||||
LWS_SEND_BUFFER_POST_PADDING);
|
||||
if (!conn->buf_in) {
|
||||
lwsl_err("Out of memory\n");
|
||||
return -1;
|
||||
}
|
||||
lwsl_debug(
|
||||
"deflate-frame ext RX did realloc to %ld\n",
|
||||
conn->buf_in_length);
|
||||
conn->zs_in.next_out = conn->buf_in +
|
||||
LWS_SEND_BUFFER_PRE_PADDING + len_so_far;
|
||||
conn->zs_in.avail_out =
|
||||
conn->buf_in_length - len_so_far;
|
||||
}
|
||||
|
||||
/* rewrite the buffer pointers and length */
|
||||
eff_buf->token =
|
||||
(char *)(conn->buf_in + LWS_SEND_BUFFER_PRE_PADDING);
|
||||
eff_buf->token_len = (int)(conn->zs_in.next_out -
|
||||
(conn->buf_in + LWS_SEND_BUFFER_PRE_PADDING));
|
||||
|
||||
return 0;
|
||||
|
||||
case LWS_EXT_CALLBACK_PAYLOAD_TX:
|
||||
/*
|
||||
* deflate the outgoing payload
|
||||
*/
|
||||
current_payload = eff_buf->token_len;
|
||||
|
||||
conn->zs_out.next_in = (unsigned char *)eff_buf->token;
|
||||
conn->zs_out.avail_in = current_payload;
|
||||
|
||||
conn->zs_out.next_out =
|
||||
conn->buf_out + LWS_SEND_BUFFER_PRE_PADDING;
|
||||
conn->zs_out.avail_out = conn->buf_out_length;
|
||||
|
||||
while (1) {
|
||||
n = deflate(&conn->zs_out, Z_SYNC_FLUSH);
|
||||
if (n == Z_STREAM_ERROR) {
|
||||
/*
|
||||
* screwed.. close the connection... we will
|
||||
* get a destroy callback to take care of
|
||||
* closing nicely
|
||||
*/
|
||||
lwsl_ext("zlib error deflate\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (conn->zs_out.avail_out)
|
||||
break;
|
||||
|
||||
len_so_far = (conn->zs_out.next_out -
|
||||
(conn->buf_out +
|
||||
LWS_SEND_BUFFER_PRE_PADDING));
|
||||
conn->buf_out_length *= 2;
|
||||
if (conn->buf_out_length > LWS_MAX_ZLIB_CONN_BUFFER) {
|
||||
lwsl_ext("zlib out hit limit %u\n",
|
||||
LWS_MAX_ZLIB_CONN_BUFFER);
|
||||
return -1;
|
||||
}
|
||||
conn->buf_out = (unsigned char *)realloc(
|
||||
conn->buf_out,
|
||||
LWS_SEND_BUFFER_PRE_PADDING +
|
||||
conn->buf_out_length +
|
||||
LWS_SEND_BUFFER_POST_PADDING);
|
||||
if (!conn->buf_out) {
|
||||
lwsl_err("Out of memory\n");
|
||||
return -1;
|
||||
}
|
||||
lwsl_debug(
|
||||
"deflate-frame ext TX did realloc to %ld\n",
|
||||
conn->buf_in_length);
|
||||
|
||||
conn->zs_out.next_out = (conn->buf_out +
|
||||
LWS_SEND_BUFFER_PRE_PADDING + len_so_far);
|
||||
conn->zs_out.avail_out =
|
||||
(conn->buf_out_length - len_so_far);
|
||||
}
|
||||
|
||||
conn->compressed_out = 1;
|
||||
|
||||
/* rewrite the buffer pointers and length */
|
||||
eff_buf->token = (char *)(conn->buf_out +
|
||||
LWS_SEND_BUFFER_PRE_PADDING);
|
||||
eff_buf->token_len = (int)(conn->zs_out.next_out -
|
||||
(conn->buf_out + LWS_SEND_BUFFER_PRE_PADDING)) - 4;
|
||||
|
||||
return 0;
|
||||
|
||||
case LWS_EXT_CALLBACK_PACKET_TX_PRESEND:
|
||||
if (conn->compressed_out) {
|
||||
conn->compressed_out = 0;
|
||||
*((unsigned char *)eff_buf->token) |= 0x40;
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_EXT_CALLBACK_CHECK_OK_TO_PROPOSE_EXTENSION:
|
||||
/* Avoid x-webkit-deflate-frame extension on client */
|
||||
if (!strcmp((char *)in, "x-webkit-deflate-frame"))
|
||||
return 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
25
dependencies/libwebsockets/lib/extension-deflate-frame.h
vendored
Normal file
25
dependencies/libwebsockets/lib/extension-deflate-frame.h
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#define DEFLATE_FRAME_COMPRESSION_LEVEL_SERVER 1
|
||||
#define DEFLATE_FRAME_COMPRESSION_LEVEL_CLIENT Z_DEFAULT_COMPRESSION
|
||||
|
||||
struct lws_ext_deflate_frame_conn {
|
||||
z_stream zs_in;
|
||||
z_stream zs_out;
|
||||
size_t buf_pre_used;
|
||||
size_t buf_pre_length;
|
||||
size_t buf_in_length;
|
||||
size_t buf_out_length;
|
||||
int compressed_out;
|
||||
unsigned char *buf_pre;
|
||||
unsigned char *buf_in;
|
||||
unsigned char *buf_out;
|
||||
};
|
||||
|
||||
extern int lws_extension_callback_deflate_frame(
|
||||
struct libwebsocket_context *context,
|
||||
struct libwebsocket_extension *ext,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_extension_callback_reasons reason,
|
||||
void *user, void *in, size_t len);
|
||||
166
dependencies/libwebsockets/lib/extension-deflate-stream.c
vendored
Normal file
166
dependencies/libwebsockets/lib/extension-deflate-stream.c
vendored
Normal file
@ -0,0 +1,166 @@
|
||||
#include "private-libwebsockets.h"
|
||||
#include "extension-deflate-stream.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define LWS_ZLIB_WINDOW_BITS 15
|
||||
#define LWS_ZLIB_MEMLEVEL 8
|
||||
|
||||
int lws_extension_callback_deflate_stream(
|
||||
struct libwebsocket_context *context,
|
||||
struct libwebsocket_extension *ext,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_extension_callback_reasons reason,
|
||||
void *user, void *in, size_t len)
|
||||
{
|
||||
struct lws_ext_deflate_stream_conn *conn =
|
||||
(struct lws_ext_deflate_stream_conn *)user;
|
||||
int n;
|
||||
struct lws_tokens *eff_buf = (struct lws_tokens *)in;
|
||||
|
||||
switch (reason) {
|
||||
|
||||
/*
|
||||
* for deflate-stream, both client and server sides act the same
|
||||
*/
|
||||
|
||||
case LWS_EXT_CALLBACK_CLIENT_CONSTRUCT:
|
||||
case LWS_EXT_CALLBACK_CONSTRUCT:
|
||||
conn->zs_in.zalloc = conn->zs_out.zalloc = Z_NULL;
|
||||
conn->zs_in.zfree = conn->zs_out.zfree = Z_NULL;
|
||||
conn->zs_in.opaque = conn->zs_out.opaque = Z_NULL;
|
||||
n = inflateInit2(&conn->zs_in, -LWS_ZLIB_WINDOW_BITS);
|
||||
if (n != Z_OK) {
|
||||
lwsl_err("deflateInit returned %d\n", n);
|
||||
return 1;
|
||||
}
|
||||
n = deflateInit2(&conn->zs_out,
|
||||
DEFLATE_STREAM_COMPRESSION_LEVEL, Z_DEFLATED,
|
||||
-LWS_ZLIB_WINDOW_BITS, LWS_ZLIB_MEMLEVEL,
|
||||
Z_DEFAULT_STRATEGY);
|
||||
if (n != Z_OK) {
|
||||
lwsl_err("deflateInit returned %d\n", n);
|
||||
return 1;
|
||||
}
|
||||
lwsl_ext("zlibs constructed\n");
|
||||
conn->remaining_in = 0;
|
||||
break;
|
||||
|
||||
case LWS_EXT_CALLBACK_DESTROY:
|
||||
(void)inflateEnd(&conn->zs_in);
|
||||
(void)deflateEnd(&conn->zs_out);
|
||||
lwsl_ext("zlibs destructed\n");
|
||||
break;
|
||||
|
||||
case LWS_EXT_CALLBACK_PACKET_RX_PREPARSE:
|
||||
|
||||
/*
|
||||
* inflate the incoming compressed data
|
||||
* Notice, length may be 0 and pointer NULL
|
||||
* in the case we are flushing with nothing new coming in
|
||||
*/
|
||||
if (conn->remaining_in) {
|
||||
conn->zs_in.next_in = conn->buf_in;
|
||||
conn->zs_in.avail_in = conn->remaining_in;
|
||||
conn->remaining_in = 0;
|
||||
} else {
|
||||
conn->zs_in.next_in = (unsigned char *)eff_buf->token;
|
||||
conn->zs_in.avail_in = eff_buf->token_len;
|
||||
}
|
||||
|
||||
conn->zs_in.next_out = conn->buf_out;
|
||||
conn->zs_in.avail_out = sizeof(conn->buf_out);
|
||||
|
||||
n = inflate(&conn->zs_in, Z_SYNC_FLUSH);
|
||||
switch (n) {
|
||||
case Z_NEED_DICT:
|
||||
case Z_DATA_ERROR:
|
||||
case Z_MEM_ERROR:
|
||||
/*
|
||||
* screwed.. close the connection... we will get a
|
||||
* destroy callback to take care of closing nicely
|
||||
*/
|
||||
lwsl_err("zlib error inflate %d\n", n);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* rewrite the buffer pointers and length */
|
||||
|
||||
eff_buf->token = (char *)conn->buf_out;
|
||||
eff_buf->token_len =
|
||||
sizeof(conn->buf_out) - conn->zs_in.avail_out;
|
||||
|
||||
/* copy avail data if not consumed */
|
||||
if (conn->zs_in.avail_in > 0) {
|
||||
conn->remaining_in = conn->zs_in.avail_in;
|
||||
memcpy(conn->buf_in, conn->zs_in.next_in,
|
||||
conn->zs_in.avail_in);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* if we filled the output buffer, signal that we likely have
|
||||
* more and need to be called again
|
||||
*/
|
||||
|
||||
if (eff_buf->token_len == sizeof(conn->buf_out))
|
||||
return 1;
|
||||
|
||||
/* we don't need calling again until new input data comes */
|
||||
|
||||
return 0;
|
||||
|
||||
case LWS_EXT_CALLBACK_FLUSH_PENDING_TX:
|
||||
case LWS_EXT_CALLBACK_PACKET_TX_PRESEND:
|
||||
|
||||
/*
|
||||
* deflate the outgoing compressed data
|
||||
*/
|
||||
|
||||
conn->zs_out.next_in = (unsigned char *)eff_buf->token;
|
||||
conn->zs_out.avail_in = eff_buf->token_len;
|
||||
|
||||
conn->zs_out.next_out = conn->buf_out;
|
||||
conn->zs_out.avail_out = sizeof(conn->buf_out);
|
||||
|
||||
n = Z_PARTIAL_FLUSH;
|
||||
if (reason == LWS_EXT_CALLBACK_FLUSH_PENDING_TX)
|
||||
n = Z_FULL_FLUSH;
|
||||
|
||||
n = deflate(&conn->zs_out, n);
|
||||
if (n == Z_STREAM_ERROR) {
|
||||
/*
|
||||
* screwed.. close the connection... we will get a
|
||||
* destroy callback to take care of closing nicely
|
||||
*/
|
||||
lwsl_ext("zlib error deflate\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* rewrite the buffer pointers and length */
|
||||
|
||||
eff_buf->token = (char *)conn->buf_out;
|
||||
eff_buf->token_len =
|
||||
sizeof(conn->buf_out) - conn->zs_out.avail_out;
|
||||
|
||||
/*
|
||||
* if we filled the output buffer, signal that we likely have
|
||||
* more and need to be called again... even in deflate case
|
||||
* we might sometimes need to spill more than came in
|
||||
*/
|
||||
|
||||
if (eff_buf->token_len == sizeof(conn->buf_out))
|
||||
return 1;
|
||||
|
||||
/* we don't need calling again until new input data comes */
|
||||
|
||||
return 0;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
20
dependencies/libwebsockets/lib/extension-deflate-stream.h
vendored
Normal file
20
dependencies/libwebsockets/lib/extension-deflate-stream.h
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#define DEFLATE_STREAM_CHUNK 128
|
||||
#define DEFLATE_STREAM_COMPRESSION_LEVEL 1
|
||||
|
||||
struct lws_ext_deflate_stream_conn {
|
||||
z_stream zs_in;
|
||||
z_stream zs_out;
|
||||
int remaining_in;
|
||||
unsigned char buf_in[LWS_MAX_SOCKET_IO_BUF];
|
||||
unsigned char buf_out[LWS_MAX_SOCKET_IO_BUF];
|
||||
};
|
||||
|
||||
extern int lws_extension_callback_deflate_stream(
|
||||
struct libwebsocket_context *context,
|
||||
struct libwebsocket_extension *ext,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_extension_callback_reasons reason,
|
||||
void *user, void *in, size_t len);
|
||||
211
dependencies/libwebsockets/lib/extension.c
vendored
Normal file
211
dependencies/libwebsockets/lib/extension.c
vendored
Normal file
@ -0,0 +1,211 @@
|
||||
#include "private-libwebsockets.h"
|
||||
|
||||
#include "extension-deflate-frame.h"
|
||||
#include "extension-deflate-stream.h"
|
||||
|
||||
struct libwebsocket_extension libwebsocket_internal_extensions[] = {
|
||||
#ifdef LWS_EXT_DEFLATE_STREAM
|
||||
{
|
||||
"deflate-stream",
|
||||
lws_extension_callback_deflate_stream,
|
||||
sizeof(struct lws_ext_deflate_stream_conn)
|
||||
},
|
||||
#else
|
||||
{
|
||||
"x-webkit-deflate-frame",
|
||||
lws_extension_callback_deflate_frame,
|
||||
sizeof(struct lws_ext_deflate_frame_conn)
|
||||
},
|
||||
{
|
||||
"deflate-frame",
|
||||
lws_extension_callback_deflate_frame,
|
||||
sizeof(struct lws_ext_deflate_frame_conn)
|
||||
},
|
||||
#endif
|
||||
{ /* terminator */
|
||||
NULL, NULL, 0
|
||||
}
|
||||
};
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_context_init_extensions(struct lws_context_creation_info *info,
|
||||
struct libwebsocket_context *context)
|
||||
{
|
||||
context->extensions = info->extensions;
|
||||
lwsl_info(" LWS_MAX_EXTENSIONS_ACTIVE: %u\n", LWS_MAX_EXTENSIONS_ACTIVE);
|
||||
}
|
||||
|
||||
LWS_VISIBLE struct libwebsocket_extension *libwebsocket_get_internal_extensions()
|
||||
{
|
||||
return libwebsocket_internal_extensions;
|
||||
}
|
||||
|
||||
|
||||
/* 0 = nobody had nonzero return, 1 = somebody had positive return, -1 = fail */
|
||||
|
||||
int lws_ext_callback_for_each_active(struct libwebsocket *wsi, int reason,
|
||||
void *arg, int len)
|
||||
{
|
||||
int n, m, handled = 0;
|
||||
|
||||
for (n = 0; n < wsi->count_active_extensions; n++) {
|
||||
m = wsi->active_extensions[n]->callback(
|
||||
wsi->protocol->owning_server,
|
||||
wsi->active_extensions[n], wsi,
|
||||
reason,
|
||||
wsi->active_extensions_user[n],
|
||||
arg, len);
|
||||
if (m < 0) {
|
||||
lwsl_ext(
|
||||
"Extension '%s' failed to handle callback %d!\n",
|
||||
wsi->active_extensions[n]->name, reason);
|
||||
return -1;
|
||||
}
|
||||
if (m > handled)
|
||||
handled = m;
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
int lws_ext_callback_for_each_extension_type(
|
||||
struct libwebsocket_context *context, struct libwebsocket *wsi,
|
||||
int reason, void *arg, int len)
|
||||
{
|
||||
int n = 0, m, handled = 0;
|
||||
struct libwebsocket_extension *ext = context->extensions;
|
||||
|
||||
while (ext && ext->callback && !handled) {
|
||||
m = ext->callback(context, ext, wsi, reason,
|
||||
(void *)(long)n, arg, len);
|
||||
if (m < 0) {
|
||||
lwsl_ext(
|
||||
"Extension '%s' failed to handle callback %d!\n",
|
||||
wsi->active_extensions[n]->name, reason);
|
||||
return -1;
|
||||
}
|
||||
if (m)
|
||||
handled = 1;
|
||||
|
||||
ext++;
|
||||
n++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
lws_issue_raw_ext_access(struct libwebsocket *wsi,
|
||||
unsigned char *buf, size_t len)
|
||||
{
|
||||
int ret;
|
||||
struct lws_tokens eff_buf;
|
||||
int m;
|
||||
int n = 0;
|
||||
|
||||
eff_buf.token = (char *)buf;
|
||||
eff_buf.token_len = len;
|
||||
|
||||
/*
|
||||
* while we have original buf to spill ourselves, or extensions report
|
||||
* more in their pipeline
|
||||
*/
|
||||
|
||||
ret = 1;
|
||||
while (ret == 1) {
|
||||
|
||||
/* default to nobody has more to spill */
|
||||
|
||||
ret = 0;
|
||||
|
||||
/* show every extension the new incoming data */
|
||||
m = lws_ext_callback_for_each_active(wsi,
|
||||
LWS_EXT_CALLBACK_PACKET_TX_PRESEND, &eff_buf, 0);
|
||||
if (m < 0)
|
||||
return -1;
|
||||
if (m) /* handled */
|
||||
ret = 1;
|
||||
|
||||
if ((char *)buf != eff_buf.token)
|
||||
/*
|
||||
* extension recreated it:
|
||||
* need to buffer this if not all sent
|
||||
*/
|
||||
wsi->u.ws.clean_buffer = 0;
|
||||
|
||||
/* assuming they left us something to send, send it */
|
||||
|
||||
if (eff_buf.token_len) {
|
||||
n = lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
|
||||
eff_buf.token_len);
|
||||
if (n < 0) {
|
||||
lwsl_info("closing from ext access\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* always either sent it all or privately buffered */
|
||||
if (wsi->u.ws.clean_buffer) {
|
||||
eff_buf.token_len = n;
|
||||
len = n;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
lwsl_parser("written %d bytes to client\n", n);
|
||||
|
||||
/* no extension has more to spill? Then we can go */
|
||||
|
||||
if (!ret)
|
||||
break;
|
||||
|
||||
/* we used up what we had */
|
||||
|
||||
eff_buf.token = NULL;
|
||||
eff_buf.token_len = 0;
|
||||
|
||||
/*
|
||||
* Did that leave the pipe choked?
|
||||
* Or we had to hold on to some of it?
|
||||
*/
|
||||
|
||||
if (!lws_send_pipe_choked(wsi) && !wsi->truncated_send_len)
|
||||
/* no we could add more, lets's do that */
|
||||
continue;
|
||||
|
||||
lwsl_debug("choked\n");
|
||||
|
||||
/*
|
||||
* Yes, he's choked. Don't spill the rest now get a callback
|
||||
* when he is ready to send and take care of it there
|
||||
*/
|
||||
libwebsocket_callback_on_writable(
|
||||
wsi->protocol->owning_server, wsi);
|
||||
wsi->extension_data_pending = 1;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int
|
||||
lws_any_extension_handled(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_extension_callback_reasons r,
|
||||
void *v, size_t len)
|
||||
{
|
||||
int n;
|
||||
int handled = 0;
|
||||
|
||||
/* maybe an extension will take care of it for us */
|
||||
|
||||
for (n = 0; n < wsi->count_active_extensions && !handled; n++) {
|
||||
if (!wsi->active_extensions[n]->callback)
|
||||
continue;
|
||||
|
||||
handled |= wsi->active_extensions[n]->callback(context,
|
||||
wsi->active_extensions[n], wsi,
|
||||
r, wsi->active_extensions_user[n], v, len);
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
276
dependencies/libwebsockets/lib/getifaddrs.c
vendored
Normal file
276
dependencies/libwebsockets/lib/getifaddrs.c
vendored
Normal file
@ -0,0 +1,276 @@
|
||||
/*
|
||||
* downloaded from
|
||||
* http://ftp.uninett.no/pub/OpenBSD/src/kerberosV/src/lib/roken/getifaddrs.c
|
||||
*/
|
||||
#if !HAVE_GETIFADDRS
|
||||
/*
|
||||
* Copyright (c) 2000 - 2001 Kungliga Tekniska H<EFBFBD>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.
|
||||
*/
|
||||
|
||||
#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>
|
||||
|
||||
#ifdef HAVE_SYS_SOCKIO_H
|
||||
#include <sys/sockio.h>
|
||||
#endif
|
||||
|
||||
#ifdef 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 = calloc(1, buf_size);
|
||||
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;
|
||||
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 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 = malloc(sizeof(**end));
|
||||
|
||||
(*end)->ifa_next = NULL;
|
||||
(*end)->ifa_name = strdup(ifr->ifr_name);
|
||||
(*end)->ifa_flags = ifreq.ifr_flags;
|
||||
(*end)->ifa_addr = malloc(salen);
|
||||
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 =
|
||||
malloc(sizeof(ifr->ifr_broadaddr));
|
||||
memcpy((*end)->ifa_broadaddr, &ifr->ifr_broadaddr,
|
||||
sizeof(ifr->ifr_broadaddr));
|
||||
} else if (ifreq.ifr_flags & IFF_POINTOPOINT) {
|
||||
(*end)->ifa_dstaddr = malloc(sizeof(ifr->ifr_dstaddr));
|
||||
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);
|
||||
free(buf);
|
||||
return 0;
|
||||
|
||||
error_out:
|
||||
close(fd);
|
||||
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(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; ) {
|
||||
free(p->ifa_name);
|
||||
if (p->ifa_addr)
|
||||
free(p->ifa_addr);
|
||||
if (p->ifa_dstaddr)
|
||||
free(p->ifa_dstaddr);
|
||||
if (p->ifa_netmask)
|
||||
free(p->ifa_netmask);
|
||||
if (p->ifa_data)
|
||||
free(p->ifa_data);
|
||||
q = p;
|
||||
p = p->ifa_next;
|
||||
free(q);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
void
|
||||
print_addr(const char *s, struct sockaddr *sa)
|
||||
{
|
||||
int i;
|
||||
printf(" %s=%d/", s, sa->sa_family);
|
||||
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
|
||||
for (i = 0;
|
||||
i < sa->sa_len - ((long)sa->sa_data - (long)&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
|
||||
#endif
|
||||
76
dependencies/libwebsockets/lib/getifaddrs.h
vendored
Normal file
76
dependencies/libwebsockets/lib/getifaddrs.h
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
#if HAVE_GETIFADDRS
|
||||
#include <sys/types.h>
|
||||
#include <ifaddrs.h>
|
||||
#else
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/*
|
||||
* Copyright (c) 2000 Kungliga Tekniska H<EFBFBD>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
|
||||
171
dependencies/libwebsockets/lib/handshake.c
vendored
Normal file
171
dependencies/libwebsockets/lib/handshake.c
vendored
Normal file
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010-2013 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 "private-libwebsockets.h"
|
||||
|
||||
/*
|
||||
* -04 of the protocol (actually the 80th version) has a radically different
|
||||
* handshake. The 04 spec gives the following idea
|
||||
*
|
||||
* The handshake from the client looks as follows:
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* The handshake from the server looks as follows:
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
LWS_VISIBLE int
|
||||
libwebsocket_read(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, unsigned char *buf, size_t len)
|
||||
{
|
||||
size_t n;
|
||||
|
||||
switch (wsi->state) {
|
||||
|
||||
case WSI_STATE_HTTP_BODY:
|
||||
http_postbody:
|
||||
while (len--) {
|
||||
|
||||
if (wsi->u.http.content_length_seen >= wsi->u.http.content_length)
|
||||
break;
|
||||
|
||||
wsi->u.http.post_buffer[wsi->u.http.body_index++] = *buf++;
|
||||
wsi->u.http.content_length_seen++;
|
||||
n = wsi->protocol->rx_buffer_size;
|
||||
if (!n)
|
||||
n = LWS_MAX_SOCKET_IO_BUF;
|
||||
|
||||
if (wsi->u.http.body_index != n &&
|
||||
wsi->u.http.content_length_seen != wsi->u.http.content_length)
|
||||
continue;
|
||||
|
||||
if (wsi->protocol->callback) {
|
||||
n = wsi->protocol->callback(
|
||||
wsi->protocol->owning_server, wsi,
|
||||
LWS_CALLBACK_HTTP_BODY,
|
||||
wsi->user_space, wsi->u.http.post_buffer,
|
||||
wsi->u.http.body_index);
|
||||
wsi->u.http.body_index = 0;
|
||||
if (n)
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (wsi->u.http.content_length_seen == wsi->u.http.content_length) {
|
||||
/* he sent the content in time */
|
||||
libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
|
||||
n = wsi->protocol->callback(
|
||||
wsi->protocol->owning_server, wsi,
|
||||
LWS_CALLBACK_HTTP_BODY_COMPLETION,
|
||||
wsi->user_space, NULL, 0);
|
||||
wsi->u.http.body_index = 0;
|
||||
if (n)
|
||||
goto bail;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* we need to spill here so everything is seen in the case
|
||||
* there is no content-length
|
||||
*/
|
||||
if (wsi->u.http.body_index && wsi->protocol->callback) {
|
||||
n = wsi->protocol->callback(
|
||||
wsi->protocol->owning_server, wsi,
|
||||
LWS_CALLBACK_HTTP_BODY,
|
||||
wsi->user_space, wsi->u.http.post_buffer,
|
||||
wsi->u.http.body_index);
|
||||
wsi->u.http.body_index = 0;
|
||||
if (n)
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
|
||||
case WSI_STATE_HTTP_ISSUING_FILE:
|
||||
case WSI_STATE_HTTP:
|
||||
wsi->state = WSI_STATE_HTTP_HEADERS;
|
||||
wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART;
|
||||
wsi->u.hdr.lextable_pos = 0;
|
||||
/* fallthru */
|
||||
case WSI_STATE_HTTP_HEADERS:
|
||||
|
||||
lwsl_parser("issuing %d bytes to parser\n", (int)len);
|
||||
|
||||
if (lws_handshake_client(wsi, &buf, len))
|
||||
goto bail;
|
||||
|
||||
switch (lws_handshake_server(context, wsi, &buf, len)) {
|
||||
case 1:
|
||||
goto bail;
|
||||
case 2:
|
||||
goto http_postbody;
|
||||
}
|
||||
break;
|
||||
|
||||
case WSI_STATE_AWAITING_CLOSE_ACK:
|
||||
case WSI_STATE_ESTABLISHED:
|
||||
if (lws_handshake_client(wsi, &buf, len))
|
||||
goto bail;
|
||||
switch (wsi->mode) {
|
||||
case LWS_CONNMODE_WS_SERVING:
|
||||
|
||||
if (libwebsocket_interpret_incoming_packet(wsi, buf, len) < 0) {
|
||||
lwsl_info("interpret_incoming_packet has bailed\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
lwsl_err("libwebsocket_read: Unhandled state\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
bail:
|
||||
lwsl_debug("closing connection at libwebsocket_read bail:\n");
|
||||
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
|
||||
return -1;
|
||||
}
|
||||
338
dependencies/libwebsockets/lib/lextable.h
vendored
Normal file
338
dependencies/libwebsockets/lib/lextable.h
vendored
Normal file
@ -0,0 +1,338 @@
|
||||
/* pos 0000: 0 */ 0x67 /* 'g' */, 0x25, 0x00 /* (to 0x0025 state 1) */,
|
||||
0x70 /* 'p' */, 0x27, 0x00 /* (to 0x002A state 5) */,
|
||||
0x6F /* 'o' */, 0x30, 0x00 /* (to 0x0036 state 10) */,
|
||||
0x68 /* 'h' */, 0x3C, 0x00 /* (to 0x0045 state 18) */,
|
||||
0x63 /* 'c' */, 0x45, 0x00 /* (to 0x0051 state 23) */,
|
||||
0x73 /* 's' */, 0x60, 0x00 /* (to 0x006F state 34) */,
|
||||
0x75 /* 'u' */, 0x9F, 0x00 /* (to 0x00B1 state 64) */,
|
||||
0x0D /* '.' */, 0xB3, 0x00 /* (to 0x00C8 state 84) */,
|
||||
0x61 /* 'a' */, 0xEA, 0x00 /* (to 0x0102 state 134) */,
|
||||
0x69 /* 'i' */, 0x1D, 0x01 /* (to 0x0138 state 168) */,
|
||||
0x64 /* 'd' */, 0x9C, 0x01 /* (to 0x01BA state 270) */,
|
||||
0x72 /* 'r' */, 0x9F, 0x01 /* (to 0x01C0 state 275) */,
|
||||
0x08, /* fail */
|
||||
/* pos 0025: 1 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 0026: 2 */ 0xF4 /* 't' -> */,
|
||||
/* pos 0027: 3 */ 0xA0 /* ' ' -> */,
|
||||
/* pos 0028: 4 */ 0x00, 0x00 /* - terminal marker 0 - */,
|
||||
/* pos 002a: 5 */ 0x6F /* 'o' */, 0x07, 0x00 /* (to 0x0031 state 6) */,
|
||||
0x72 /* 'r' */, 0x4B, 0x01 /* (to 0x0178 state 216) */,
|
||||
0x08, /* fail */
|
||||
/* pos 0031: 6 */ 0xF3 /* 's' -> */,
|
||||
/* pos 0032: 7 */ 0xF4 /* 't' -> */,
|
||||
/* pos 0033: 8 */ 0xA0 /* ' ' -> */,
|
||||
/* pos 0034: 9 */ 0x00, 0x01 /* - terminal marker 1 - */,
|
||||
/* pos 0036: 10 */ 0x70 /* 'p' */, 0x07, 0x00 /* (to 0x003D state 11) */,
|
||||
0x72 /* 'r' */, 0x81, 0x00 /* (to 0x00BA state 72) */,
|
||||
0x08, /* fail */
|
||||
/* pos 003d: 11 */ 0xF4 /* 't' -> */,
|
||||
/* pos 003e: 12 */ 0xE9 /* 'i' -> */,
|
||||
/* pos 003f: 13 */ 0xEF /* 'o' -> */,
|
||||
/* pos 0040: 14 */ 0xEE /* 'n' -> */,
|
||||
/* pos 0041: 15 */ 0xF3 /* 's' -> */,
|
||||
/* pos 0042: 16 */ 0xA0 /* ' ' -> */,
|
||||
/* pos 0043: 17 */ 0x00, 0x02 /* - terminal marker 2 - */,
|
||||
/* pos 0045: 18 */ 0x6F /* 'o' */, 0x07, 0x00 /* (to 0x004C state 19) */,
|
||||
0x74 /* 't' */, 0xB1, 0x00 /* (to 0x00F9 state 126) */,
|
||||
0x08, /* fail */
|
||||
/* pos 004c: 19 */ 0xF3 /* 's' -> */,
|
||||
/* pos 004d: 20 */ 0xF4 /* 't' -> */,
|
||||
/* pos 004e: 21 */ 0xBA /* ':' -> */,
|
||||
/* pos 004f: 22 */ 0x00, 0x03 /* - terminal marker 3 - */,
|
||||
/* pos 0051: 23 */ 0x6F /* 'o' */, 0x07, 0x00 /* (to 0x0058 state 24) */,
|
||||
0x61 /* 'a' */, 0x2B, 0x01 /* (to 0x017F state 222) */,
|
||||
0x08, /* fail */
|
||||
/* pos 0058: 24 */ 0x6E /* 'n' */, 0x07, 0x00 /* (to 0x005F state 25) */,
|
||||
0x6F /* 'o' */, 0x40, 0x01 /* (to 0x019B state 248) */,
|
||||
0x08, /* fail */
|
||||
/* pos 005f: 25 */ 0x6E /* 'n' */, 0x07, 0x00 /* (to 0x0066 state 26) */,
|
||||
0x74 /* 't' */, 0x3F, 0x01 /* (to 0x01A1 state 253) */,
|
||||
0x08, /* fail */
|
||||
/* pos 0066: 26 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 0067: 27 */ 0xE3 /* 'c' -> */,
|
||||
/* pos 0068: 28 */ 0xF4 /* 't' -> */,
|
||||
/* pos 0069: 29 */ 0xE9 /* 'i' -> */,
|
||||
/* pos 006a: 30 */ 0xEF /* 'o' -> */,
|
||||
/* pos 006b: 31 */ 0xEE /* 'n' -> */,
|
||||
/* pos 006c: 32 */ 0xBA /* ':' -> */,
|
||||
/* pos 006d: 33 */ 0x00, 0x04 /* - terminal marker 4 - */,
|
||||
/* pos 006f: 34 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 0070: 35 */ 0xE3 /* 'c' -> */,
|
||||
/* pos 0071: 36 */ 0xAD /* '-' -> */,
|
||||
/* pos 0072: 37 */ 0xF7 /* 'w' -> */,
|
||||
/* pos 0073: 38 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 0074: 39 */ 0xE2 /* 'b' -> */,
|
||||
/* pos 0075: 40 */ 0xF3 /* 's' -> */,
|
||||
/* pos 0076: 41 */ 0xEF /* 'o' -> */,
|
||||
/* pos 0077: 42 */ 0xE3 /* 'c' -> */,
|
||||
/* pos 0078: 43 */ 0xEB /* 'k' -> */,
|
||||
/* pos 0079: 44 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 007a: 45 */ 0xF4 /* 't' -> */,
|
||||
/* pos 007b: 46 */ 0xAD /* '-' -> */,
|
||||
/* pos 007c: 47 */ 0x6B /* 'k' */, 0x19, 0x00 /* (to 0x0095 state 48) */,
|
||||
0x70 /* 'p' */, 0x28, 0x00 /* (to 0x00A7 state 55) */,
|
||||
0x64 /* 'd' */, 0x3F, 0x00 /* (to 0x00C1 state 78) */,
|
||||
0x76 /* 'v' */, 0x48, 0x00 /* (to 0x00CD state 87) */,
|
||||
0x6F /* 'o' */, 0x4E, 0x00 /* (to 0x00D6 state 95) */,
|
||||
0x65 /* 'e' */, 0x53, 0x00 /* (to 0x00DE state 102) */,
|
||||
0x61 /* 'a' */, 0x5C, 0x00 /* (to 0x00EA state 113) */,
|
||||
0x6E /* 'n' */, 0x61, 0x00 /* (to 0x00F2 state 120) */,
|
||||
0x08, /* fail */
|
||||
/* pos 0095: 48 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 0096: 49 */ 0xF9 /* 'y' -> */,
|
||||
/* pos 0097: 50 */ 0x31 /* '1' */, 0x0A, 0x00 /* (to 0x00A1 state 51) */,
|
||||
0x32 /* '2' */, 0x0A, 0x00 /* (to 0x00A4 state 53) */,
|
||||
0x3A /* ':' */, 0x2E, 0x00 /* (to 0x00CB state 86) */,
|
||||
0x08, /* fail */
|
||||
/* pos 00a1: 51 */ 0xBA /* ':' -> */,
|
||||
/* pos 00a2: 52 */ 0x00, 0x05 /* - terminal marker 5 - */,
|
||||
/* pos 00a4: 53 */ 0xBA /* ':' -> */,
|
||||
/* pos 00a5: 54 */ 0x00, 0x06 /* - terminal marker 6 - */,
|
||||
/* pos 00a7: 55 */ 0xF2 /* 'r' -> */,
|
||||
/* pos 00a8: 56 */ 0xEF /* 'o' -> */,
|
||||
/* pos 00a9: 57 */ 0xF4 /* 't' -> */,
|
||||
/* pos 00aa: 58 */ 0xEF /* 'o' -> */,
|
||||
/* pos 00ab: 59 */ 0xE3 /* 'c' -> */,
|
||||
/* pos 00ac: 60 */ 0xEF /* 'o' -> */,
|
||||
/* pos 00ad: 61 */ 0xEC /* 'l' -> */,
|
||||
/* pos 00ae: 62 */ 0xBA /* ':' -> */,
|
||||
/* pos 00af: 63 */ 0x00, 0x07 /* - terminal marker 7 - */,
|
||||
/* pos 00b1: 64 */ 0xF0 /* 'p' -> */,
|
||||
/* pos 00b2: 65 */ 0xE7 /* 'g' -> */,
|
||||
/* pos 00b3: 66 */ 0xF2 /* 'r' -> */,
|
||||
/* pos 00b4: 67 */ 0xE1 /* 'a' -> */,
|
||||
/* pos 00b5: 68 */ 0xE4 /* 'd' -> */,
|
||||
/* pos 00b6: 69 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 00b7: 70 */ 0xBA /* ':' -> */,
|
||||
/* pos 00b8: 71 */ 0x00, 0x08 /* - terminal marker 8 - */,
|
||||
/* pos 00ba: 72 */ 0xE9 /* 'i' -> */,
|
||||
/* pos 00bb: 73 */ 0xE7 /* 'g' -> */,
|
||||
/* pos 00bc: 74 */ 0xE9 /* 'i' -> */,
|
||||
/* pos 00bd: 75 */ 0xEE /* 'n' -> */,
|
||||
/* pos 00be: 76 */ 0xBA /* ':' -> */,
|
||||
/* pos 00bf: 77 */ 0x00, 0x09 /* - terminal marker 9 - */,
|
||||
/* pos 00c1: 78 */ 0xF2 /* 'r' -> */,
|
||||
/* pos 00c2: 79 */ 0xE1 /* 'a' -> */,
|
||||
/* pos 00c3: 80 */ 0xE6 /* 'f' -> */,
|
||||
/* pos 00c4: 81 */ 0xF4 /* 't' -> */,
|
||||
/* pos 00c5: 82 */ 0xBA /* ':' -> */,
|
||||
/* pos 00c6: 83 */ 0x00, 0x0A /* - terminal marker 10 - */,
|
||||
/* pos 00c8: 84 */ 0x8A /* '.' -> */,
|
||||
/* pos 00c9: 85 */ 0x00, 0x0B /* - terminal marker 11 - */,
|
||||
/* pos 00cb: 86 */ 0x00, 0x0C /* - terminal marker 12 - */,
|
||||
/* pos 00cd: 87 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 00ce: 88 */ 0xF2 /* 'r' -> */,
|
||||
/* pos 00cf: 89 */ 0xF3 /* 's' -> */,
|
||||
/* pos 00d0: 90 */ 0xE9 /* 'i' -> */,
|
||||
/* pos 00d1: 91 */ 0xEF /* 'o' -> */,
|
||||
/* pos 00d2: 92 */ 0xEE /* 'n' -> */,
|
||||
/* pos 00d3: 93 */ 0xBA /* ':' -> */,
|
||||
/* pos 00d4: 94 */ 0x00, 0x0D /* - terminal marker 13 - */,
|
||||
/* pos 00d6: 95 */ 0xF2 /* 'r' -> */,
|
||||
/* pos 00d7: 96 */ 0xE9 /* 'i' -> */,
|
||||
/* pos 00d8: 97 */ 0xE7 /* 'g' -> */,
|
||||
/* pos 00d9: 98 */ 0xE9 /* 'i' -> */,
|
||||
/* pos 00da: 99 */ 0xEE /* 'n' -> */,
|
||||
/* pos 00db: 100 */ 0xBA /* ':' -> */,
|
||||
/* pos 00dc: 101 */ 0x00, 0x0E /* - terminal marker 14 - */,
|
||||
/* pos 00de: 102 */ 0xF8 /* 'x' -> */,
|
||||
/* pos 00df: 103 */ 0xF4 /* 't' -> */,
|
||||
/* pos 00e0: 104 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 00e1: 105 */ 0xEE /* 'n' -> */,
|
||||
/* pos 00e2: 106 */ 0xF3 /* 's' -> */,
|
||||
/* pos 00e3: 107 */ 0xE9 /* 'i' -> */,
|
||||
/* pos 00e4: 108 */ 0xEF /* 'o' -> */,
|
||||
/* pos 00e5: 109 */ 0xEE /* 'n' -> */,
|
||||
/* pos 00e6: 110 */ 0xF3 /* 's' -> */,
|
||||
/* pos 00e7: 111 */ 0xBA /* ':' -> */,
|
||||
/* pos 00e8: 112 */ 0x00, 0x0F /* - terminal marker 15 - */,
|
||||
/* pos 00ea: 113 */ 0xE3 /* 'c' -> */,
|
||||
/* pos 00eb: 114 */ 0xE3 /* 'c' -> */,
|
||||
/* pos 00ec: 115 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 00ed: 116 */ 0xF0 /* 'p' -> */,
|
||||
/* pos 00ee: 117 */ 0xF4 /* 't' -> */,
|
||||
/* pos 00ef: 118 */ 0xBA /* ':' -> */,
|
||||
/* pos 00f0: 119 */ 0x00, 0x10 /* - terminal marker 16 - */,
|
||||
/* pos 00f2: 120 */ 0xEF /* 'o' -> */,
|
||||
/* pos 00f3: 121 */ 0xEE /* 'n' -> */,
|
||||
/* pos 00f4: 122 */ 0xE3 /* 'c' -> */,
|
||||
/* pos 00f5: 123 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 00f6: 124 */ 0xBA /* ':' -> */,
|
||||
/* pos 00f7: 125 */ 0x00, 0x11 /* - terminal marker 17 - */,
|
||||
/* pos 00f9: 126 */ 0xF4 /* 't' -> */,
|
||||
/* pos 00fa: 127 */ 0xF0 /* 'p' -> */,
|
||||
/* pos 00fb: 128 */ 0xAF /* '/' -> */,
|
||||
/* pos 00fc: 129 */ 0xB1 /* '1' -> */,
|
||||
/* pos 00fd: 130 */ 0xAE /* '.' -> */,
|
||||
/* pos 00fe: 131 */ 0xB1 /* '1' -> */,
|
||||
/* pos 00ff: 132 */ 0xA0 /* ' ' -> */,
|
||||
/* pos 0100: 133 */ 0x00, 0x12 /* - terminal marker 18 - */,
|
||||
/* pos 0102: 134 */ 0x63 /* 'c' */, 0x07, 0x00 /* (to 0x0109 state 135) */,
|
||||
0x75 /* 'u' */, 0x88, 0x00 /* (to 0x018D state 235) */,
|
||||
0x08, /* fail */
|
||||
/* pos 0109: 135 */ 0xE3 /* 'c' -> */,
|
||||
/* pos 010a: 136 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 010b: 137 */ 0x70 /* 'p' */, 0x07, 0x00 /* (to 0x0112 state 138) */,
|
||||
0x73 /* 's' */, 0x0E, 0x00 /* (to 0x011C state 141) */,
|
||||
0x08, /* fail */
|
||||
/* pos 0112: 138 */ 0xF4 /* 't' -> */,
|
||||
/* pos 0113: 139 */ 0x3A /* ':' */, 0x07, 0x00 /* (to 0x011A state 140) */,
|
||||
0x2D /* '-' */, 0x47, 0x00 /* (to 0x015D state 197) */,
|
||||
0x08, /* fail */
|
||||
/* pos 011a: 140 */ 0x00, 0x13 /* - terminal marker 19 - */,
|
||||
/* pos 011c: 141 */ 0xF3 /* 's' -> */,
|
||||
/* pos 011d: 142 */ 0xAD /* '-' -> */,
|
||||
/* pos 011e: 143 */ 0xE3 /* 'c' -> */,
|
||||
/* pos 011f: 144 */ 0xEF /* 'o' -> */,
|
||||
/* pos 0120: 145 */ 0xEE /* 'n' -> */,
|
||||
/* pos 0121: 146 */ 0xF4 /* 't' -> */,
|
||||
/* pos 0122: 147 */ 0xF2 /* 'r' -> */,
|
||||
/* pos 0123: 148 */ 0xEF /* 'o' -> */,
|
||||
/* pos 0124: 149 */ 0xEC /* 'l' -> */,
|
||||
/* pos 0125: 150 */ 0xAD /* '-' -> */,
|
||||
/* pos 0126: 151 */ 0xF2 /* 'r' -> */,
|
||||
/* pos 0127: 152 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 0128: 153 */ 0xF1 /* 'q' -> */,
|
||||
/* pos 0129: 154 */ 0xF5 /* 'u' -> */,
|
||||
/* pos 012a: 155 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 012b: 156 */ 0xF3 /* 's' -> */,
|
||||
/* pos 012c: 157 */ 0xF4 /* 't' -> */,
|
||||
/* pos 012d: 158 */ 0xAD /* '-' -> */,
|
||||
/* pos 012e: 159 */ 0xE8 /* 'h' -> */,
|
||||
/* pos 012f: 160 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 0130: 161 */ 0xE1 /* 'a' -> */,
|
||||
/* pos 0131: 162 */ 0xE4 /* 'd' -> */,
|
||||
/* pos 0132: 163 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 0133: 164 */ 0xF2 /* 'r' -> */,
|
||||
/* pos 0134: 165 */ 0xF3 /* 's' -> */,
|
||||
/* pos 0135: 166 */ 0xBA /* ':' -> */,
|
||||
/* pos 0136: 167 */ 0x00, 0x14 /* - terminal marker 20 - */,
|
||||
/* pos 0138: 168 */ 0xE6 /* 'f' -> */,
|
||||
/* pos 0139: 169 */ 0xAD /* '-' -> */,
|
||||
/* pos 013a: 170 */ 0x6D /* 'm' */, 0x07, 0x00 /* (to 0x0141 state 171) */,
|
||||
0x6E /* 'n' */, 0x14, 0x00 /* (to 0x0151 state 186) */,
|
||||
0x08, /* fail */
|
||||
/* pos 0141: 171 */ 0xEF /* 'o' -> */,
|
||||
/* pos 0142: 172 */ 0xE4 /* 'd' -> */,
|
||||
/* pos 0143: 173 */ 0xE9 /* 'i' -> */,
|
||||
/* pos 0144: 174 */ 0xE6 /* 'f' -> */,
|
||||
/* pos 0145: 175 */ 0xE9 /* 'i' -> */,
|
||||
/* pos 0146: 176 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 0147: 177 */ 0xE4 /* 'd' -> */,
|
||||
/* pos 0148: 178 */ 0xAD /* '-' -> */,
|
||||
/* pos 0149: 179 */ 0xF3 /* 's' -> */,
|
||||
/* pos 014a: 180 */ 0xE9 /* 'i' -> */,
|
||||
/* pos 014b: 181 */ 0xEE /* 'n' -> */,
|
||||
/* pos 014c: 182 */ 0xE3 /* 'c' -> */,
|
||||
/* pos 014d: 183 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 014e: 184 */ 0xBA /* ':' -> */,
|
||||
/* pos 014f: 185 */ 0x00, 0x15 /* - terminal marker 21 - */,
|
||||
/* pos 0151: 186 */ 0xEF /* 'o' -> */,
|
||||
/* pos 0152: 187 */ 0xEE /* 'n' -> */,
|
||||
/* pos 0153: 188 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 0154: 189 */ 0xAD /* '-' -> */,
|
||||
/* pos 0155: 190 */ 0xED /* 'm' -> */,
|
||||
/* pos 0156: 191 */ 0xE1 /* 'a' -> */,
|
||||
/* pos 0157: 192 */ 0xF4 /* 't' -> */,
|
||||
/* pos 0158: 193 */ 0xE3 /* 'c' -> */,
|
||||
/* pos 0159: 194 */ 0xE8 /* 'h' -> */,
|
||||
/* pos 015a: 195 */ 0xBA /* ':' -> */,
|
||||
/* pos 015b: 196 */ 0x00, 0x16 /* - terminal marker 22 - */,
|
||||
/* pos 015d: 197 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0164 state 198) */,
|
||||
0x6C /* 'l' */, 0x0E, 0x00 /* (to 0x016E state 207) */,
|
||||
0x08, /* fail */
|
||||
/* pos 0164: 198 */ 0xEE /* 'n' -> */,
|
||||
/* pos 0165: 199 */ 0xE3 /* 'c' -> */,
|
||||
/* pos 0166: 200 */ 0xEF /* 'o' -> */,
|
||||
/* pos 0167: 201 */ 0xE4 /* 'd' -> */,
|
||||
/* pos 0168: 202 */ 0xE9 /* 'i' -> */,
|
||||
/* pos 0169: 203 */ 0xEE /* 'n' -> */,
|
||||
/* pos 016a: 204 */ 0xE7 /* 'g' -> */,
|
||||
/* pos 016b: 205 */ 0xBA /* ':' -> */,
|
||||
/* pos 016c: 206 */ 0x00, 0x17 /* - terminal marker 23 - */,
|
||||
/* pos 016e: 207 */ 0xE1 /* 'a' -> */,
|
||||
/* pos 016f: 208 */ 0xEE /* 'n' -> */,
|
||||
/* pos 0170: 209 */ 0xE7 /* 'g' -> */,
|
||||
/* pos 0171: 210 */ 0xF5 /* 'u' -> */,
|
||||
/* pos 0172: 211 */ 0xE1 /* 'a' -> */,
|
||||
/* pos 0173: 212 */ 0xE7 /* 'g' -> */,
|
||||
/* pos 0174: 213 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 0175: 214 */ 0xBA /* ':' -> */,
|
||||
/* pos 0176: 215 */ 0x00, 0x18 /* - terminal marker 24 - */,
|
||||
/* pos 0178: 216 */ 0xE1 /* 'a' -> */,
|
||||
/* pos 0179: 217 */ 0xE7 /* 'g' -> */,
|
||||
/* pos 017a: 218 */ 0xED /* 'm' -> */,
|
||||
/* pos 017b: 219 */ 0xE1 /* 'a' -> */,
|
||||
/* pos 017c: 220 */ 0xBA /* ':' -> */,
|
||||
/* pos 017d: 221 */ 0x00, 0x19 /* - terminal marker 25 - */,
|
||||
/* pos 017f: 222 */ 0xE3 /* 'c' -> */,
|
||||
/* pos 0180: 223 */ 0xE8 /* 'h' -> */,
|
||||
/* pos 0181: 224 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 0182: 225 */ 0xAD /* '-' -> */,
|
||||
/* pos 0183: 226 */ 0xE3 /* 'c' -> */,
|
||||
/* pos 0184: 227 */ 0xEF /* 'o' -> */,
|
||||
/* pos 0185: 228 */ 0xEE /* 'n' -> */,
|
||||
/* pos 0186: 229 */ 0xF4 /* 't' -> */,
|
||||
/* pos 0187: 230 */ 0xF2 /* 'r' -> */,
|
||||
/* pos 0188: 231 */ 0xEF /* 'o' -> */,
|
||||
/* pos 0189: 232 */ 0xEC /* 'l' -> */,
|
||||
/* pos 018a: 233 */ 0xBA /* ':' -> */,
|
||||
/* pos 018b: 234 */ 0x00, 0x1A /* - terminal marker 26 - */,
|
||||
/* pos 018d: 235 */ 0xF4 /* 't' -> */,
|
||||
/* pos 018e: 236 */ 0xE8 /* 'h' -> */,
|
||||
/* pos 018f: 237 */ 0xEF /* 'o' -> */,
|
||||
/* pos 0190: 238 */ 0xF2 /* 'r' -> */,
|
||||
/* pos 0191: 239 */ 0xE9 /* 'i' -> */,
|
||||
/* pos 0192: 240 */ 0xFA /* 'z' -> */,
|
||||
/* pos 0193: 241 */ 0xE1 /* 'a' -> */,
|
||||
/* pos 0194: 242 */ 0xF4 /* 't' -> */,
|
||||
/* pos 0195: 243 */ 0xE9 /* 'i' -> */,
|
||||
/* pos 0196: 244 */ 0xEF /* 'o' -> */,
|
||||
/* pos 0197: 245 */ 0xEE /* 'n' -> */,
|
||||
/* pos 0198: 246 */ 0xBA /* ':' -> */,
|
||||
/* pos 0199: 247 */ 0x00, 0x1B /* - terminal marker 27 - */,
|
||||
/* pos 019b: 248 */ 0xEB /* 'k' -> */,
|
||||
/* pos 019c: 249 */ 0xE9 /* 'i' -> */,
|
||||
/* pos 019d: 250 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 019e: 251 */ 0xBA /* ':' -> */,
|
||||
/* pos 019f: 252 */ 0x00, 0x1C /* - terminal marker 28 - */,
|
||||
/* pos 01a1: 253 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 01a2: 254 */ 0xEE /* 'n' -> */,
|
||||
/* pos 01a3: 255 */ 0xF4 /* 't' -> */,
|
||||
/* pos 01a4: 256 */ 0xAD /* '-' -> */,
|
||||
/* pos 01a5: 257 */ 0x6C /* 'l' */, 0x07, 0x00 /* (to 0x01AC state 258) */,
|
||||
0x74 /* 't' */, 0x0C, 0x00 /* (to 0x01B4 state 265) */,
|
||||
0x08, /* fail */
|
||||
/* pos 01ac: 258 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 01ad: 259 */ 0xEE /* 'n' -> */,
|
||||
/* pos 01ae: 260 */ 0xE7 /* 'g' -> */,
|
||||
/* pos 01af: 261 */ 0xF4 /* 't' -> */,
|
||||
/* pos 01b0: 262 */ 0xE8 /* 'h' -> */,
|
||||
/* pos 01b1: 263 */ 0xBA /* ':' -> */,
|
||||
/* pos 01b2: 264 */ 0x00, 0x1D /* - terminal marker 29 - */,
|
||||
/* pos 01b4: 265 */ 0xF9 /* 'y' -> */,
|
||||
/* pos 01b5: 266 */ 0xF0 /* 'p' -> */,
|
||||
/* pos 01b6: 267 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 01b7: 268 */ 0xBA /* ':' -> */,
|
||||
/* pos 01b8: 269 */ 0x00, 0x1E /* - terminal marker 30 - */,
|
||||
/* pos 01ba: 270 */ 0xE1 /* 'a' -> */,
|
||||
/* pos 01bb: 271 */ 0xF4 /* 't' -> */,
|
||||
/* pos 01bc: 272 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 01bd: 273 */ 0xBA /* ':' -> */,
|
||||
/* pos 01be: 274 */ 0x00, 0x1F /* - terminal marker 31 - */,
|
||||
/* pos 01c0: 275 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x01C7 state 276) */,
|
||||
0x65 /* 'e' */, 0x0A, 0x00 /* (to 0x01CD state 281) */,
|
||||
0x08, /* fail */
|
||||
/* pos 01c7: 276 */ 0xEE /* 'n' -> */,
|
||||
/* pos 01c8: 277 */ 0xE7 /* 'g' -> */,
|
||||
/* pos 01c9: 278 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 01ca: 279 */ 0xBA /* ':' -> */,
|
||||
/* pos 01cb: 280 */ 0x00, 0x20 /* - terminal marker 32 - */,
|
||||
/* pos 01cd: 281 */ 0xE6 /* 'f' -> */,
|
||||
/* pos 01ce: 282 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 01cf: 283 */ 0xF2 /* 'r' -> */,
|
||||
/* pos 01d0: 284 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 01d1: 285 */ 0xF2 /* 'r' -> */,
|
||||
/* pos 01d2: 286 */ 0xBA /* ':' -> */,
|
||||
/* pos 01d3: 287 */ 0x00, 0x21 /* - terminal marker 33 - */,
|
||||
/* total size 469 bytes */
|
||||
175
dependencies/libwebsockets/lib/libev.c
vendored
Normal file
175
dependencies/libwebsockets/lib/libev.c
vendored
Normal file
@ -0,0 +1,175 @@
|
||||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010-2014 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 "private-libwebsockets.h"
|
||||
|
||||
void lws_feature_status_libev(struct lws_context_creation_info *info)
|
||||
{
|
||||
if (info->options & LWS_SERVER_OPTION_LIBEV)
|
||||
lwsl_notice("libev support compiled in and enabled\n");
|
||||
else
|
||||
lwsl_notice("libev support compiled in but disabled\n");
|
||||
}
|
||||
|
||||
static void
|
||||
libwebsocket_accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
|
||||
{
|
||||
struct libwebsocket_pollfd eventfd;
|
||||
struct lws_io_watcher *lws_io = (struct lws_io_watcher *)watcher;
|
||||
struct libwebsocket_context *context = lws_io->context;
|
||||
|
||||
if (revents & EV_ERROR)
|
||||
return;
|
||||
|
||||
eventfd.fd = watcher->fd;
|
||||
eventfd.revents = EV_NONE;
|
||||
if (revents & EV_READ)
|
||||
eventfd.revents |= LWS_POLLIN;
|
||||
|
||||
if (revents & EV_WRITE)
|
||||
eventfd.revents |= LWS_POLLOUT;
|
||||
|
||||
libwebsocket_service_fd(context, &eventfd);
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
libwebsocket_sigint_cb(struct ev_loop *loop,
|
||||
struct ev_signal *watcher, int revents)
|
||||
{
|
||||
ev_break(loop, EVBREAK_ALL);
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
libwebsocket_initloop(
|
||||
struct libwebsocket_context *context,
|
||||
struct ev_loop *loop)
|
||||
{
|
||||
int status = 0;
|
||||
int backend;
|
||||
const char * backend_name;
|
||||
struct ev_io *w_accept = (ev_io *)&context->w_accept;
|
||||
struct ev_signal *w_sigint = (ev_signal *)&context->w_sigint;
|
||||
|
||||
if (!loop)
|
||||
loop = ev_default_loop(0);
|
||||
|
||||
context->io_loop = loop;
|
||||
|
||||
/*
|
||||
* Initialize the accept w_accept with the listening socket
|
||||
* and register a callback for read operations:
|
||||
*/
|
||||
ev_io_init(w_accept, libwebsocket_accept_cb,
|
||||
context->listen_service_fd, EV_READ);
|
||||
ev_io_start(context->io_loop,w_accept);
|
||||
ev_signal_init(w_sigint, libwebsocket_sigint_cb, SIGINT);
|
||||
ev_signal_start(context->io_loop,w_sigint);
|
||||
backend = ev_backend(loop);
|
||||
|
||||
switch (backend) {
|
||||
case EVBACKEND_SELECT:
|
||||
backend_name = "select";
|
||||
break;
|
||||
case EVBACKEND_POLL:
|
||||
backend_name = "poll";
|
||||
break;
|
||||
case EVBACKEND_EPOLL:
|
||||
backend_name = "epoll";
|
||||
break;
|
||||
case EVBACKEND_KQUEUE:
|
||||
backend_name = "kqueue";
|
||||
break;
|
||||
case EVBACKEND_DEVPOLL:
|
||||
backend_name = "/dev/poll";
|
||||
break;
|
||||
case EVBACKEND_PORT:
|
||||
backend_name = "Solaris 10 \"port\"";
|
||||
break;
|
||||
default:
|
||||
backend_name = "Unknown libev backend";
|
||||
break;
|
||||
};
|
||||
|
||||
lwsl_notice(" libev backend: %s\n", backend_name);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_libev_accept(struct libwebsocket_context *context,
|
||||
struct libwebsocket *new_wsi, int accept_fd)
|
||||
{
|
||||
struct ev_io *r = &new_wsi->w_read.watcher;
|
||||
struct ev_io *w = &new_wsi->w_write.watcher;
|
||||
|
||||
if (!LWS_LIBEV_ENABLED(context))
|
||||
return;
|
||||
|
||||
new_wsi->w_read.context = context;
|
||||
new_wsi->w_write.context = context;
|
||||
ev_io_init(r, libwebsocket_accept_cb, accept_fd, EV_READ);
|
||||
ev_io_init(w, libwebsocket_accept_cb, accept_fd, EV_WRITE);
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_libev_io(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, int flags)
|
||||
{
|
||||
if (!LWS_LIBEV_ENABLED(context))
|
||||
return;
|
||||
|
||||
if (!context->io_loop)
|
||||
return;
|
||||
|
||||
assert((flags & (LWS_EV_START | LWS_EV_STOP)) &&
|
||||
(flags & (LWS_EV_READ | LWS_EV_WRITE)));
|
||||
|
||||
if (flags & LWS_EV_START) {
|
||||
if (flags & LWS_EV_WRITE)
|
||||
ev_io_start(context->io_loop, &wsi->w_write.watcher);
|
||||
if (flags & LWS_EV_READ)
|
||||
ev_io_start(context->io_loop, &wsi->w_read.watcher);
|
||||
} else {
|
||||
if (flags & LWS_EV_WRITE)
|
||||
ev_io_stop(context->io_loop, &wsi->w_write.watcher);
|
||||
if (flags & LWS_EV_READ)
|
||||
ev_io_stop(context->io_loop, &wsi->w_read.watcher);
|
||||
}
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_libev_init_fd_table(struct libwebsocket_context *context)
|
||||
{
|
||||
if (!LWS_LIBEV_ENABLED(context))
|
||||
return 0;
|
||||
|
||||
context->w_accept.context = context;
|
||||
context->w_sigint.context = context;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_libev_run(struct libwebsocket_context *context)
|
||||
{
|
||||
if (context->io_loop && LWS_LIBEV_ENABLED(context))
|
||||
ev_run(context->io_loop, 0);
|
||||
}
|
||||
761
dependencies/libwebsockets/lib/libwebsockets.c
vendored
Normal file
761
dependencies/libwebsockets/lib/libwebsockets.c
vendored
Normal file
@ -0,0 +1,761 @@
|
||||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010-2014 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 "private-libwebsockets.h"
|
||||
|
||||
int log_level = LLL_ERR | LLL_WARN | LLL_NOTICE;
|
||||
static void (*lwsl_emit)(int level, const char *line) = lwsl_emit_stderr;
|
||||
|
||||
static const char * const log_level_names[] = {
|
||||
"ERR",
|
||||
"WARN",
|
||||
"NOTICE",
|
||||
"INFO",
|
||||
"DEBUG",
|
||||
"PARSER",
|
||||
"HEADER",
|
||||
"EXTENSION",
|
||||
"CLIENT",
|
||||
"LATENCY",
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
libwebsocket_close_and_free_session(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, enum lws_close_status reason)
|
||||
{
|
||||
int n, m, ret;
|
||||
int old_state;
|
||||
unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 2 +
|
||||
LWS_SEND_BUFFER_POST_PADDING];
|
||||
struct lws_tokens eff_buf;
|
||||
|
||||
if (!wsi)
|
||||
return;
|
||||
|
||||
old_state = wsi->state;
|
||||
|
||||
switch (old_state) {
|
||||
case WSI_STATE_DEAD_SOCKET:
|
||||
return;
|
||||
|
||||
/* we tried the polite way... */
|
||||
case WSI_STATE_AWAITING_CLOSE_ACK:
|
||||
goto just_kill_connection;
|
||||
|
||||
case WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE:
|
||||
if (wsi->truncated_send_len) {
|
||||
libwebsocket_callback_on_writable(context, wsi);
|
||||
return;
|
||||
}
|
||||
lwsl_info("wsi %p completed WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE\n", wsi);
|
||||
goto just_kill_connection;
|
||||
default:
|
||||
if (wsi->truncated_send_len) {
|
||||
lwsl_info("wsi %p entering WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE\n", wsi);
|
||||
wsi->state = WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
wsi->u.ws.close_reason = reason;
|
||||
|
||||
if (wsi->mode == LWS_CONNMODE_WS_CLIENT_WAITING_CONNECT ||
|
||||
wsi->mode == LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE) {
|
||||
|
||||
context->protocols[0].callback(context, wsi,
|
||||
LWS_CALLBACK_CLIENT_CONNECTION_ERROR, NULL, NULL, 0);
|
||||
|
||||
free(wsi->u.hdr.ah);
|
||||
goto just_kill_connection;
|
||||
}
|
||||
|
||||
if (wsi->mode == LWS_CONNMODE_HTTP_SERVING_ACCEPTED) {
|
||||
if (wsi->u.http.post_buffer) {
|
||||
free(wsi->u.http.post_buffer);
|
||||
wsi->u.http.post_buffer = NULL;
|
||||
}
|
||||
if (wsi->u.http.fd != LWS_INVALID_FILE) {
|
||||
lwsl_debug("closing http file\n");
|
||||
compatible_file_close(wsi->u.http.fd);
|
||||
wsi->u.http.fd = LWS_INVALID_FILE;
|
||||
context->protocols[0].callback(context, wsi,
|
||||
LWS_CALLBACK_CLOSED_HTTP, wsi->user_space, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* are his extensions okay with him closing? Eg he might be a mux
|
||||
* parent and just his ch1 aspect is closing?
|
||||
*/
|
||||
|
||||
if (lws_ext_callback_for_each_active(wsi,
|
||||
LWS_EXT_CALLBACK_CHECK_OK_TO_REALLY_CLOSE, NULL, 0) > 0) {
|
||||
lwsl_ext("extension vetoed close\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* flush any tx pending from extensions, since we may send close packet
|
||||
* if there are problems with send, just nuke the connection
|
||||
*/
|
||||
|
||||
do {
|
||||
ret = 0;
|
||||
eff_buf.token = NULL;
|
||||
eff_buf.token_len = 0;
|
||||
|
||||
/* show every extension the new incoming data */
|
||||
|
||||
m = lws_ext_callback_for_each_active(wsi,
|
||||
LWS_EXT_CALLBACK_FLUSH_PENDING_TX, &eff_buf, 0);
|
||||
if (m < 0) {
|
||||
lwsl_ext("Extension reports fatal error\n");
|
||||
goto just_kill_connection;
|
||||
}
|
||||
if (m)
|
||||
/*
|
||||
* at least one extension told us he has more
|
||||
* to spill, so we will go around again after
|
||||
*/
|
||||
ret = 1;
|
||||
|
||||
/* assuming they left us something to send, send it */
|
||||
|
||||
if (eff_buf.token_len)
|
||||
if (lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
|
||||
eff_buf.token_len) != eff_buf.token_len) {
|
||||
lwsl_debug("close: ext spill failed\n");
|
||||
goto just_kill_connection;
|
||||
}
|
||||
} while (ret);
|
||||
|
||||
/*
|
||||
* signal we are closing, libsocket_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
|
||||
* WSI_STATE_RETURNED_CLOSE_ALREADY 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
|
||||
* WSI_STATE_AWAITING_CLOSE_ACK and will skip doing this a second time.
|
||||
*/
|
||||
|
||||
if (old_state == WSI_STATE_ESTABLISHED &&
|
||||
reason != LWS_CLOSE_STATUS_NOSTATUS) {
|
||||
|
||||
lwsl_debug("sending close indication...\n");
|
||||
|
||||
/* make valgrind happy */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
n = libwebsocket_write(wsi,
|
||||
&buf[LWS_SEND_BUFFER_PRE_PADDING + 2],
|
||||
0, LWS_WRITE_CLOSE);
|
||||
if (n >= 0) {
|
||||
/*
|
||||
* we have sent a nice protocol level indication we
|
||||
* now wish to close, we should not send anything more
|
||||
*/
|
||||
|
||||
wsi->state = WSI_STATE_AWAITING_CLOSE_ACK;
|
||||
|
||||
/*
|
||||
* ...and we should wait for a reply for a bit
|
||||
* out of politeness
|
||||
*/
|
||||
|
||||
libwebsocket_set_timeout(wsi,
|
||||
PENDING_TIMEOUT_CLOSE_ACK, 1);
|
||||
|
||||
lwsl_debug("sent close indication, awaiting ack\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
lwsl_info("close: sending close packet failed, hanging up\n");
|
||||
|
||||
/* else, the send failed and we should just hang up */
|
||||
}
|
||||
|
||||
just_kill_connection:
|
||||
|
||||
lwsl_debug("close: just_kill_connection\n");
|
||||
|
||||
/*
|
||||
* we won't be servicing or receiving anything further from this guy
|
||||
* delete socket from the internal poll list if still present
|
||||
*/
|
||||
|
||||
remove_wsi_socket_from_fds(context, wsi);
|
||||
|
||||
wsi->state = WSI_STATE_DEAD_SOCKET;
|
||||
|
||||
if ((old_state == WSI_STATE_ESTABLISHED ||
|
||||
wsi->mode == LWS_CONNMODE_WS_SERVING ||
|
||||
wsi->mode == LWS_CONNMODE_WS_CLIENT)) {
|
||||
|
||||
if (wsi->u.ws.rx_user_buffer) {
|
||||
free(wsi->u.ws.rx_user_buffer);
|
||||
wsi->u.ws.rx_user_buffer = NULL;
|
||||
}
|
||||
if (wsi->u.ws.rxflow_buffer) {
|
||||
free(wsi->u.ws.rxflow_buffer);
|
||||
wsi->u.ws.rxflow_buffer = NULL;
|
||||
}
|
||||
if (wsi->truncated_send_malloc) {
|
||||
/* not going to be completed... nuke it */
|
||||
free(wsi->truncated_send_malloc);
|
||||
wsi->truncated_send_malloc = NULL;
|
||||
wsi->truncated_send_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* tell the user it's all over for this guy */
|
||||
|
||||
if (wsi->protocol && wsi->protocol->callback &&
|
||||
((old_state == WSI_STATE_ESTABLISHED) ||
|
||||
(old_state == WSI_STATE_RETURNED_CLOSE_ALREADY) ||
|
||||
(old_state == WSI_STATE_AWAITING_CLOSE_ACK))) {
|
||||
lwsl_debug("calling back CLOSED\n");
|
||||
wsi->protocol->callback(context, wsi, LWS_CALLBACK_CLOSED,
|
||||
wsi->user_space, NULL, 0);
|
||||
} else if (wsi->mode == LWS_CONNMODE_HTTP_SERVING_ACCEPTED) {
|
||||
lwsl_debug("calling back CLOSED_HTTP\n");
|
||||
context->protocols[0].callback(context, wsi,
|
||||
LWS_CALLBACK_CLOSED_HTTP, wsi->user_space, NULL, 0 );
|
||||
} else
|
||||
lwsl_debug("not calling back closed\n");
|
||||
|
||||
/* deallocate any active extension contexts */
|
||||
|
||||
if (lws_ext_callback_for_each_active(wsi, LWS_EXT_CALLBACK_DESTROY, NULL, 0) < 0)
|
||||
lwsl_warn("extension destruction failed\n");
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
for (n = 0; n < wsi->count_active_extensions; n++)
|
||||
free(wsi->active_extensions_user[n]);
|
||||
#endif
|
||||
/*
|
||||
* inform all extensions in case they tracked this guy out of band
|
||||
* even though not active on him specifically
|
||||
*/
|
||||
if (lws_ext_callback_for_each_extension_type(context, wsi,
|
||||
LWS_EXT_CALLBACK_DESTROY_ANY_WSI_CLOSING, NULL, 0) < 0)
|
||||
lwsl_warn("ext destroy wsi failed\n");
|
||||
|
||||
/* lwsl_info("closing fd=%d\n", wsi->sock); */
|
||||
|
||||
if (!lws_ssl_close(wsi) && wsi->sock >= 0) {
|
||||
n = shutdown(wsi->sock, SHUT_RDWR);
|
||||
if (n)
|
||||
lwsl_debug("closing: shutdown ret %d\n", LWS_ERRNO);
|
||||
|
||||
n = compatible_close(wsi->sock);
|
||||
if (n)
|
||||
lwsl_debug("closing: close ret %d\n", LWS_ERRNO);
|
||||
}
|
||||
|
||||
/* outermost destroy notification for wsi (user_space still intact) */
|
||||
context->protocols[0].callback(context, wsi,
|
||||
LWS_CALLBACK_WSI_DESTROY, wsi->user_space, NULL, 0);
|
||||
|
||||
if (wsi->protocol && wsi->protocol->per_session_data_size &&
|
||||
wsi->user_space && !wsi->user_space_externally_allocated)
|
||||
free(wsi->user_space);
|
||||
|
||||
free(wsi);
|
||||
}
|
||||
|
||||
/**
|
||||
* libwebsockets_get_peer_addresses() - Get client address information
|
||||
* @context: Libwebsockets context
|
||||
* @wsi: Local struct libwebsocket associated with
|
||||
* @fd: Connection socket descriptor
|
||||
* @name: Buffer to take client address name
|
||||
* @name_len: Length of client address name buffer
|
||||
* @rip: Buffer to take client address IP qotted quad
|
||||
* @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 void
|
||||
libwebsockets_get_peer_addresses(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, int fd, char *name, int name_len,
|
||||
char *rip, int rip_len)
|
||||
{
|
||||
socklen_t len;
|
||||
#ifdef LWS_USE_IPV6
|
||||
struct sockaddr_in6 sin6;
|
||||
#endif
|
||||
struct sockaddr_in sin4;
|
||||
struct hostent *host;
|
||||
struct hostent *host1;
|
||||
char ip[128];
|
||||
unsigned char *p;
|
||||
int n;
|
||||
#ifdef AF_LOCAL
|
||||
struct sockaddr_un *un;
|
||||
#endif
|
||||
int ret = -1;
|
||||
|
||||
rip[0] = '\0';
|
||||
name[0] = '\0';
|
||||
|
||||
lws_latency_pre(context, wsi);
|
||||
|
||||
#ifdef LWS_USE_IPV6
|
||||
if (LWS_IPV6_ENABLED(context)) {
|
||||
|
||||
len = sizeof(sin6);
|
||||
if (getpeername(fd, (struct sockaddr *) &sin6, &len) < 0) {
|
||||
lwsl_warn("getpeername: %s\n", strerror(LWS_ERRNO));
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (!lws_plat_inet_ntop(AF_INET6, &sin6.sin6_addr, rip, rip_len)) {
|
||||
lwsl_err("inet_ntop", strerror(LWS_ERRNO));
|
||||
goto bail;
|
||||
}
|
||||
|
||||
// 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 *)&sin6,
|
||||
sizeof(struct sockaddr_in6), name,
|
||||
name_len, NULL, 0, 0);
|
||||
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
len = sizeof(sin4);
|
||||
if (getpeername(fd, (struct sockaddr *) &sin4, &len) < 0) {
|
||||
lwsl_warn("getpeername: %s\n", strerror(LWS_ERRNO));
|
||||
goto bail;
|
||||
}
|
||||
host = gethostbyaddr((char *) &sin4.sin_addr,
|
||||
sizeof(sin4.sin_addr), AF_INET);
|
||||
if (host == NULL) {
|
||||
lwsl_warn("gethostbyaddr: %s\n", strerror(LWS_ERRNO));
|
||||
goto bail;
|
||||
}
|
||||
|
||||
strncpy(name, host->h_name, name_len);
|
||||
name[name_len - 1] = '\0';
|
||||
|
||||
host1 = gethostbyname(host->h_name);
|
||||
if (host1 == NULL)
|
||||
goto bail;
|
||||
p = (unsigned char *)host1;
|
||||
n = 0;
|
||||
while (p != NULL) {
|
||||
p = (unsigned char *)host1->h_addr_list[n++];
|
||||
if (p == NULL)
|
||||
continue;
|
||||
if ((host1->h_addrtype != AF_INET)
|
||||
#ifdef AF_LOCAL
|
||||
&& (host1->h_addrtype != AF_LOCAL)
|
||||
#endif
|
||||
)
|
||||
continue;
|
||||
|
||||
if (host1->h_addrtype == AF_INET)
|
||||
sprintf(ip, "%u.%u.%u.%u",
|
||||
p[0], p[1], p[2], p[3]);
|
||||
#ifdef AF_LOCAL
|
||||
else {
|
||||
un = (struct sockaddr_un *)p;
|
||||
strncpy(ip, un->sun_path, sizeof(ip) - 1);
|
||||
ip[sizeof(ip) - 1] = '\0';
|
||||
}
|
||||
#endif
|
||||
p = NULL;
|
||||
strncpy(rip, ip, rip_len);
|
||||
rip[rip_len - 1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
bail:
|
||||
lws_latency(context, wsi, "libwebsockets_get_peer_addresses", ret, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* libwebsocket_context_user() - get the user data associated with the context
|
||||
* @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_EXTERN void *
|
||||
libwebsocket_context_user(struct libwebsocket_context *context)
|
||||
{
|
||||
return context->user_space;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* libwebsocket_callback_all_protocol() - Callback all connections using
|
||||
* the given protocol with the given reason
|
||||
*
|
||||
* @protocol: Protocol whose connections will get callbacks
|
||||
* @reason: Callback reason index
|
||||
*/
|
||||
|
||||
LWS_VISIBLE int
|
||||
libwebsocket_callback_all_protocol(
|
||||
const struct libwebsocket_protocols *protocol, int reason)
|
||||
{
|
||||
struct libwebsocket_context *context = protocol->owning_server;
|
||||
int n;
|
||||
struct libwebsocket *wsi;
|
||||
|
||||
for (n = 0; n < context->fds_count; n++) {
|
||||
wsi = context->lws_lookup[context->fds[n].fd];
|
||||
if (!wsi)
|
||||
continue;
|
||||
if (wsi->protocol == protocol)
|
||||
protocol->callback(context, wsi,
|
||||
reason, wsi->user_space, NULL, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* libwebsocket_set_timeout() - marks the wsi as subject to a timeout
|
||||
*
|
||||
* You will not need this unless you are doing something special
|
||||
*
|
||||
* @wsi: Websocket connection instance
|
||||
* @reason: timeout reason
|
||||
* @secs: how many seconds
|
||||
*/
|
||||
|
||||
LWS_VISIBLE void
|
||||
libwebsocket_set_timeout(struct libwebsocket *wsi,
|
||||
enum pending_timeout reason, int secs)
|
||||
{
|
||||
time_t now;
|
||||
|
||||
time(&now);
|
||||
|
||||
wsi->pending_timeout_limit = now + secs;
|
||||
wsi->pending_timeout = reason;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* libwebsocket_get_socket_fd() - returns the socket file descriptor
|
||||
*
|
||||
* You will not need this unless you are doing something special
|
||||
*
|
||||
* @wsi: Websocket connection instance
|
||||
*/
|
||||
|
||||
LWS_VISIBLE int
|
||||
libwebsocket_get_socket_fd(struct libwebsocket *wsi)
|
||||
{
|
||||
return wsi->sock;
|
||||
}
|
||||
|
||||
#ifdef LWS_LATENCY
|
||||
void
|
||||
lws_latency(struct libwebsocket_context *context, struct libwebsocket *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
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* libwebsocket_rx_flow_control() - Enable and disable socket servicing for
|
||||
* receieved packets.
|
||||
*
|
||||
* If the output side of a server process becomes choked, this allows flow
|
||||
* control for the input side.
|
||||
*
|
||||
* @wsi: Websocket connection instance to get callback for
|
||||
* @enable: 0 = disable read servicing for this connection, 1 = enable
|
||||
*/
|
||||
|
||||
LWS_VISIBLE int
|
||||
libwebsocket_rx_flow_control(struct libwebsocket *wsi, int enable)
|
||||
{
|
||||
if (enable == (wsi->u.ws.rxflow_change_to & LWS_RXFLOW_ALLOW))
|
||||
return 0;
|
||||
|
||||
lwsl_info("libwebsocket_rx_flow_control(0x%p, %d)\n", wsi, enable);
|
||||
wsi->u.ws.rxflow_change_to = LWS_RXFLOW_PENDING_CHANGE | !!enable;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* libwebsocket_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.
|
||||
*
|
||||
* @protocol: all connections using this protocol will be allowed to receive
|
||||
*/
|
||||
|
||||
LWS_VISIBLE void
|
||||
libwebsocket_rx_flow_allow_all_protocol(
|
||||
const struct libwebsocket_protocols *protocol)
|
||||
{
|
||||
struct libwebsocket_context *context = protocol->owning_server;
|
||||
int n;
|
||||
struct libwebsocket *wsi;
|
||||
|
||||
for (n = 0; n < context->fds_count; n++) {
|
||||
wsi = context->lws_lookup[context->fds[n].fd];
|
||||
if (!wsi)
|
||||
continue;
|
||||
if (wsi->protocol == protocol)
|
||||
libwebsocket_rx_flow_control(wsi, LWS_RXFLOW_ALLOW);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* libwebsocket_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.
|
||||
*
|
||||
* @context: Websocket context
|
||||
*/
|
||||
LWS_VISIBLE extern const char *
|
||||
libwebsocket_canonical_hostname(struct libwebsocket_context *context)
|
||||
{
|
||||
return (const char *)context->canonical_hostname;
|
||||
}
|
||||
|
||||
int user_callback_handle_rxflow(callback_function callback_function,
|
||||
struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_callback_reasons reason, void *user,
|
||||
void *in, size_t len)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = callback_function(context, wsi, reason, user, in, len);
|
||||
if (!n)
|
||||
n = _libwebsocket_rx_flow_control(wsi);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* libwebsocket_set_proxy() - Setups proxy to libwebsocket_context.
|
||||
* @context: pointer to struct libwebsocket_context you want set proxy to
|
||||
* @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
|
||||
* enviroment variable (eg, OSX)
|
||||
*
|
||||
* IMPORTANT! You should call this function right after creation of the
|
||||
* libwebsocket_context and before call to connect. If you call this
|
||||
* function after connect behavior is undefined.
|
||||
* This function will override proxy settings made on libwebsocket_context
|
||||
* creation with genenv() call.
|
||||
*/
|
||||
|
||||
LWS_VISIBLE int
|
||||
libwebsocket_set_proxy(struct libwebsocket_context *context, const char *proxy)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (!proxy)
|
||||
return -1;
|
||||
|
||||
strncpy(context->http_proxy_address, proxy,
|
||||
sizeof(context->http_proxy_address) - 1);
|
||||
context->http_proxy_address[
|
||||
sizeof(context->http_proxy_address) - 1] = '\0';
|
||||
|
||||
p = strchr(context->http_proxy_address, ':');
|
||||
if (!p) {
|
||||
lwsl_err("http_proxy needs to be ads:port\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
*p = '\0';
|
||||
context->http_proxy_port = atoi(p + 1);
|
||||
|
||||
lwsl_notice(" Proxy %s:%u\n", context->http_proxy_address,
|
||||
context->http_proxy_port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* libwebsockets_get_protocol() - Returns a protocol pointer from a websocket
|
||||
* connection.
|
||||
* @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 const struct libwebsocket_protocols *
|
||||
libwebsockets_get_protocol(struct libwebsocket *wsi)
|
||||
{
|
||||
return wsi->protocol;
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
libwebsocket_is_final_fragment(struct libwebsocket *wsi)
|
||||
{
|
||||
return wsi->u.ws.final;
|
||||
}
|
||||
|
||||
LWS_VISIBLE unsigned char
|
||||
libwebsocket_get_reserved_bits(struct libwebsocket *wsi)
|
||||
{
|
||||
return wsi->u.ws.rsv;
|
||||
}
|
||||
|
||||
int
|
||||
libwebsocket_ensure_user_space(struct libwebsocket *wsi)
|
||||
{
|
||||
if (!wsi->protocol)
|
||||
return 1;
|
||||
|
||||
/* allocate the per-connection user memory (if any) */
|
||||
|
||||
if (wsi->protocol->per_session_data_size && !wsi->user_space) {
|
||||
wsi->user_space = malloc(
|
||||
wsi->protocol->per_session_data_size);
|
||||
if (wsi->user_space == NULL) {
|
||||
lwsl_err("Out of memory for conn user space\n");
|
||||
return 1;
|
||||
}
|
||||
memset(wsi->user_space, 0,
|
||||
wsi->protocol->per_session_data_size);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
LWS_VISIBLE void lwsl_emit_stderr(int level, const char *line)
|
||||
{
|
||||
char buf[300];
|
||||
unsigned long long now;
|
||||
int n;
|
||||
|
||||
buf[0] = '\0';
|
||||
for (n = 0; n < LLL_COUNT; n++)
|
||||
if (level == (1 << n)) {
|
||||
now = time_in_microseconds() / 100;
|
||||
sprintf(buf, "[%lu:%04d] %s: ", (unsigned long) now / 10000,
|
||||
(int)(now % 10000), log_level_names[n]);
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s%s", buf, line);
|
||||
}
|
||||
|
||||
|
||||
LWS_VISIBLE void _lws_log(int filter, const char *format, ...)
|
||||
{
|
||||
char buf[256];
|
||||
va_list ap;
|
||||
|
||||
if (!(log_level & filter))
|
||||
return;
|
||||
|
||||
va_start(ap, format);
|
||||
vsnprintf(buf, sizeof(buf), format, ap);
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
va_end(ap);
|
||||
|
||||
lwsl_emit(filter, buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* lws_set_log_level() - Set the logging bitfield
|
||||
* @level: OR together the LLL_ debug contexts you want output from
|
||||
* @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.
|
||||
*/
|
||||
|
||||
LWS_VISIBLE void lws_set_log_level(int level, void (*log_emit_function)(int level,
|
||||
const char *line))
|
||||
{
|
||||
log_level = level;
|
||||
if (log_emit_function)
|
||||
lwsl_emit = log_emit_function;
|
||||
}
|
||||
1207
dependencies/libwebsockets/lib/libwebsockets.h
vendored
Normal file
1207
dependencies/libwebsockets/lib/libwebsockets.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
404
dependencies/libwebsockets/lib/lws-plat-unix.c
vendored
Normal file
404
dependencies/libwebsockets/lib/lws-plat-unix.c
vendored
Normal file
@ -0,0 +1,404 @@
|
||||
#include "private-libwebsockets.h"
|
||||
|
||||
/*
|
||||
* included from libwebsockets.c for unix builds
|
||||
*/
|
||||
|
||||
unsigned long long time_in_microseconds(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return (tv.tv_sec * 1000000) + tv.tv_usec;
|
||||
}
|
||||
|
||||
LWS_VISIBLE int libwebsockets_get_random(struct libwebsocket_context *context,
|
||||
void *buf, int len)
|
||||
{
|
||||
return read(context->fd_random, (char *)buf, len);
|
||||
}
|
||||
|
||||
LWS_VISIBLE int lws_send_pipe_choked(struct libwebsocket *wsi)
|
||||
{
|
||||
struct libwebsocket_pollfd fds;
|
||||
|
||||
/* treat the fact we got a truncated send pending as if we're choked */
|
||||
if (wsi->truncated_send_len)
|
||||
return 1;
|
||||
|
||||
fds.fd = wsi->sock;
|
||||
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 libwebsocket_pollfd *fd)
|
||||
{
|
||||
return poll(fd, 1, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is just used to interrupt poll waiting
|
||||
* we don't have to do anything with it.
|
||||
*/
|
||||
static void lws_sigusr2(int sig)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* libwebsocket_cancel_service() - Cancel servicing of pending websocket activity
|
||||
* @context: Websocket context
|
||||
*
|
||||
* This function let a call to libwebsocket_service() waiting for a timeout
|
||||
* immediately return.
|
||||
*/
|
||||
LWS_VISIBLE void
|
||||
libwebsocket_cancel_service(struct libwebsocket_context *context)
|
||||
{
|
||||
char buf = 0;
|
||||
|
||||
if (write(context->dummy_pipe_fds[1], &buf, sizeof(buf)) != 1)
|
||||
lwsl_err("Cannot write to dummy pipe");
|
||||
}
|
||||
|
||||
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 int
|
||||
lws_plat_service(struct libwebsocket_context *context, int timeout_ms)
|
||||
{
|
||||
int n;
|
||||
int m;
|
||||
char buf;
|
||||
|
||||
/* stay dead once we are dead */
|
||||
|
||||
if (!context)
|
||||
return 1;
|
||||
|
||||
lws_libev_run(context);
|
||||
|
||||
context->service_tid = context->protocols[0].callback(context, NULL,
|
||||
LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0);
|
||||
|
||||
n = poll(context->fds, context->fds_count, timeout_ms);
|
||||
context->service_tid = 0;
|
||||
|
||||
if (n == 0) /* poll timeout */ {
|
||||
libwebsocket_service_fd(context, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (n < 0) {
|
||||
if (LWS_ERRNO != LWS_EINTR)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* any socket with events to service? */
|
||||
|
||||
for (n = 0; n < context->fds_count; n++) {
|
||||
if (!context->fds[n].revents)
|
||||
continue;
|
||||
|
||||
if (context->fds[n].fd == context->dummy_pipe_fds[0]) {
|
||||
if (read(context->fds[n].fd, &buf, 1) != 1)
|
||||
lwsl_err("Cannot read from dummy pipe.");
|
||||
continue;
|
||||
}
|
||||
|
||||
m = libwebsocket_service_fd(context, &context->fds[n]);
|
||||
if (m < 0)
|
||||
return -1;
|
||||
/* if something closed, retry this slot */
|
||||
if (m)
|
||||
n--;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_plat_set_socket_options(struct libwebsocket_context *context, int fd)
|
||||
{
|
||||
int optval = 1;
|
||||
socklen_t optlen = sizeof(optval);
|
||||
|
||||
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
|
||||
defined(__OpenBSD__)
|
||||
struct protoent *tcp_proto;
|
||||
#endif
|
||||
|
||||
if (context->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(__NetBSD__) || \
|
||||
defined(__CYGWIN__) || defined(__OpenBSD__)
|
||||
|
||||
/*
|
||||
* didn't find a way to set these per-socket, need to
|
||||
* tune kernel systemwide values
|
||||
*/
|
||||
#else
|
||||
/* set the keepalive conditions we want on it too */
|
||||
optval = context->ka_time;
|
||||
if (setsockopt(fd, IPPROTO_IP, TCP_KEEPIDLE,
|
||||
(const void *)&optval, optlen) < 0)
|
||||
return 1;
|
||||
|
||||
optval = context->ka_interval;
|
||||
if (setsockopt(fd, IPPROTO_IP, TCP_KEEPINTVL,
|
||||
(const void *)&optval, optlen) < 0)
|
||||
return 1;
|
||||
|
||||
optval = context->ka_probes;
|
||||
if (setsockopt(fd, IPPROTO_IP, TCP_KEEPCNT,
|
||||
(const void *)&optval, optlen) < 0)
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Disable Nagle */
|
||||
optval = 1;
|
||||
#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && \
|
||||
!defined(__OpenBSD__)
|
||||
setsockopt(fd, SOL_TCP, TCP_NODELAY, (const void *)&optval, optlen);
|
||||
#else
|
||||
tcp_proto = getprotobyname("TCP");
|
||||
setsockopt(fd, tcp_proto->p_proto, TCP_NODELAY, &optval, optlen);
|
||||
#endif
|
||||
|
||||
/* We are nonblocking... */
|
||||
fcntl(fd, F_SETFL, O_NONBLOCK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_plat_drop_app_privileges(struct lws_context_creation_info *info)
|
||||
{
|
||||
if (info->gid != -1)
|
||||
if (setgid(info->gid))
|
||||
lwsl_warn("setgid: %s\n", strerror(LWS_ERRNO));
|
||||
if (info->uid != -1)
|
||||
if (setuid(info->uid))
|
||||
lwsl_warn("setuid: %s\n", strerror(LWS_ERRNO));
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_plat_init_fd_tables(struct libwebsocket_context *context)
|
||||
{
|
||||
if (lws_libev_init_fd_table(context))
|
||||
/* libev handled it instead */
|
||||
return 0;
|
||||
|
||||
if (pipe(context->dummy_pipe_fds)) {
|
||||
lwsl_err("Unable to create pipe\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* use the read end of pipe as first item */
|
||||
context->fds[0].fd = context->dummy_pipe_fds[0];
|
||||
context->fds[0].events = LWS_POLLIN;
|
||||
context->fds[0].revents = 0;
|
||||
context->fds_count = 1;
|
||||
|
||||
context->fd_random = open(SYSTEM_RANDOM_FILEPATH, O_RDONLY);
|
||||
if (context->fd_random < 0) {
|
||||
lwsl_err("Unable to open random device %s %d\n",
|
||||
SYSTEM_RANDOM_FILEPATH, context->fd_random);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sigpipe_handler(int x)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_plat_context_early_init(void)
|
||||
{
|
||||
sigset_t mask;
|
||||
|
||||
signal(SIGUSR2, lws_sigusr2);
|
||||
sigemptyset(&mask);
|
||||
sigaddset(&mask, SIGUSR2);
|
||||
|
||||
sigprocmask(SIG_BLOCK, &mask, NULL);
|
||||
|
||||
signal(SIGPIPE, sigpipe_handler);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_plat_context_early_destroy(struct libwebsocket_context *context)
|
||||
{
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_plat_context_late_destroy(struct libwebsocket_context *context)
|
||||
{
|
||||
close(context->dummy_pipe_fds[0]);
|
||||
close(context->dummy_pipe_fds[1]);
|
||||
close(context->fd_random);
|
||||
}
|
||||
|
||||
/* cast a struct sockaddr_in6 * into addr for ipv6 */
|
||||
|
||||
LWS_VISIBLE int
|
||||
interface_to_sa(struct libwebsocket_context *context,
|
||||
const char *ifname, struct sockaddr_in *addr, size_t addrlen)
|
||||
{
|
||||
int rc = -1;
|
||||
|
||||
struct ifaddrs *ifr;
|
||||
struct ifaddrs *ifc;
|
||||
#ifdef LWS_USE_IPV6
|
||||
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
|
||||
#endif
|
||||
|
||||
getifaddrs(&ifr);
|
||||
for (ifc = ifr; ifc != NULL && rc; ifc = ifc->ifa_next) {
|
||||
if (!ifc->ifa_addr)
|
||||
continue;
|
||||
|
||||
lwsl_info(" interface %s vs %s\n", ifc->ifa_name, ifname);
|
||||
|
||||
if (strcmp(ifc->ifa_name, ifname))
|
||||
continue;
|
||||
|
||||
switch (ifc->ifa_addr->sa_family) {
|
||||
case AF_INET:
|
||||
#ifdef LWS_USE_IPV6
|
||||
if (LWS_IPV6_ENABLED(context)) {
|
||||
/* map IPv4 to IPv6 */
|
||||
bzero((char *)&addr6->sin6_addr,
|
||||
sizeof(struct in6_addr));
|
||||
addr6->sin6_addr.s6_addr[10] = 0xff;
|
||||
addr6->sin6_addr.s6_addr[11] = 0xff;
|
||||
memcpy(&addr6->sin6_addr.s6_addr[12],
|
||||
&((struct sockaddr_in *)ifc->ifa_addr)->sin_addr,
|
||||
sizeof(struct in_addr));
|
||||
} else
|
||||
#endif
|
||||
memcpy(addr,
|
||||
(struct sockaddr_in *)ifc->ifa_addr,
|
||||
sizeof(struct sockaddr_in));
|
||||
break;
|
||||
#ifdef LWS_USE_IPV6
|
||||
case AF_INET6:
|
||||
if (rc >= 0)
|
||||
break;
|
||||
memcpy(&addr6->sin6_addr,
|
||||
&((struct sockaddr_in6 *)ifc->ifa_addr)->sin6_addr,
|
||||
sizeof(struct in6_addr));
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
freeifaddrs(ifr);
|
||||
|
||||
if (rc == -1) {
|
||||
/* check if bind to IP adddress */
|
||||
#ifdef LWS_USE_IPV6
|
||||
if (inet_pton(AF_INET6, ifname, &addr6->sin6_addr) == 1)
|
||||
rc = 0;
|
||||
else
|
||||
#endif
|
||||
if (inet_pton(AF_INET, ifname, &addr->sin_addr) == 1)
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_plat_insert_socket_into_fds(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi)
|
||||
{
|
||||
lws_libev_io(context, wsi, LWS_EV_START | LWS_EV_READ);
|
||||
context->fds[context->fds_count++].revents = 0;
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_plat_delete_socket_from_fds(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, int m)
|
||||
{
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_plat_service_periodic(struct libwebsocket_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 libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, struct libwebsocket_pollfd *pfd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_plat_open_file(const char* filename, unsigned long* filelen)
|
||||
{
|
||||
struct stat stat_buf;
|
||||
int ret = open(filename, O_RDONLY);
|
||||
|
||||
if (ret < 0)
|
||||
return LWS_INVALID_FILE;
|
||||
|
||||
fstat(ret, &stat_buf);
|
||||
*filelen = stat_buf.st_size;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef LWS_USE_IPV6
|
||||
LWS_VISIBLE const char *
|
||||
lws_plat_inet_ntop(int af, const void *src, char *dst, int cnt)
|
||||
{
|
||||
return inet_ntop(af, src, dst, cnt);
|
||||
}
|
||||
#endif
|
||||
358
dependencies/libwebsockets/lib/lws-plat-win.c
vendored
Normal file
358
dependencies/libwebsockets/lib/lws-plat-win.c
vendored
Normal file
@ -0,0 +1,358 @@
|
||||
#include "private-libwebsockets.h"
|
||||
|
||||
unsigned long long
|
||||
time_in_microseconds()
|
||||
{
|
||||
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
|
||||
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 - DELTA_EPOCH_IN_MICROSECS) / 10;
|
||||
}
|
||||
|
||||
#ifdef _WIN32_WCE
|
||||
time_t time(time_t *t)
|
||||
{
|
||||
time_t ret = time_in_microseconds() / 1000000;
|
||||
*t = ret;
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
LWS_VISIBLE int libwebsockets_get_random(struct libwebsocket_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 libwebsocket *wsi)
|
||||
{
|
||||
return wsi->sock_send_blocking;
|
||||
}
|
||||
|
||||
LWS_VISIBLE int lws_poll_listen_fd(struct libwebsocket_pollfd *fd)
|
||||
{
|
||||
fd_set readfds;
|
||||
struct timeval tv = { 0, 0 };
|
||||
|
||||
assert(fd->events == LWS_POLLIN);
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(fd->fd, &readfds);
|
||||
|
||||
return select(fd->fd + 1, &readfds, NULL, NULL, &tv);
|
||||
}
|
||||
|
||||
/**
|
||||
* libwebsocket_cancel_service() - Cancel servicing of pending websocket activity
|
||||
* @context: Websocket context
|
||||
*
|
||||
* This function let a call to libwebsocket_service() waiting for a timeout
|
||||
* immediately return.
|
||||
*/
|
||||
LWS_VISIBLE void
|
||||
libwebsocket_cancel_service(struct libwebsocket_context *context)
|
||||
{
|
||||
WSASetEvent(context->events[0]);
|
||||
}
|
||||
|
||||
LWS_VISIBLE void lwsl_emit_syslog(int level, const char *line)
|
||||
{
|
||||
lwsl_emit_stderr(level, line);
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_plat_service(struct libwebsocket_context *context, int timeout_ms)
|
||||
{
|
||||
int n;
|
||||
int i;
|
||||
DWORD ev;
|
||||
WSANETWORKEVENTS networkevents;
|
||||
struct libwebsocket_pollfd *pfd;
|
||||
|
||||
/* stay dead once we are dead */
|
||||
|
||||
if (context == NULL)
|
||||
return 1;
|
||||
|
||||
context->service_tid = context->protocols[0].callback(context, NULL,
|
||||
LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0);
|
||||
|
||||
for (i = 0; i < context->fds_count; ++i) {
|
||||
pfd = &context->fds[i];
|
||||
if (pfd->fd == context->listen_service_fd)
|
||||
continue;
|
||||
|
||||
if (pfd->events & LWS_POLLOUT) {
|
||||
if (context->lws_lookup[pfd->fd]->sock_send_blocking)
|
||||
continue;
|
||||
pfd->revents = LWS_POLLOUT;
|
||||
n = libwebsocket_service_fd(context, pfd);
|
||||
if (n < 0)
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
ev = WSAWaitForMultipleEvents(context->fds_count + 1,
|
||||
context->events, FALSE, timeout_ms, FALSE);
|
||||
context->service_tid = 0;
|
||||
|
||||
if (ev == WSA_WAIT_TIMEOUT) {
|
||||
libwebsocket_service_fd(context, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ev == WSA_WAIT_EVENT_0) {
|
||||
WSAResetEvent(context->events[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ev < WSA_WAIT_EVENT_0 || ev > WSA_WAIT_EVENT_0 + context->fds_count)
|
||||
return -1;
|
||||
|
||||
pfd = &context->fds[ev - WSA_WAIT_EVENT_0 - 1];
|
||||
|
||||
if (WSAEnumNetworkEvents(pfd->fd,
|
||||
context->events[ev - WSA_WAIT_EVENT_0],
|
||||
&networkevents) == SOCKET_ERROR) {
|
||||
lwsl_err("WSAEnumNetworkEvents() failed with error %d\n",
|
||||
LWS_ERRNO);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pfd->revents = networkevents.lNetworkEvents;
|
||||
|
||||
if (pfd->revents & LWS_POLLOUT)
|
||||
context->lws_lookup[pfd->fd]->sock_send_blocking = FALSE;
|
||||
|
||||
return libwebsocket_service_fd(context, pfd);
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_plat_set_socket_options(struct libwebsocket_context *context, int fd)
|
||||
{
|
||||
int optval = 1;
|
||||
int optlen = sizeof(optval);
|
||||
u_long optl = 1;
|
||||
DWORD dwBytesRet;
|
||||
struct tcp_keepalive alive;
|
||||
struct protoent *tcp_proto;
|
||||
|
||||
if (context->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 = context->ka_time;
|
||||
alive.keepaliveinterval = context->ka_interval;
|
||||
|
||||
if (WSAIoctl(fd, SIO_KEEPALIVE_VALS, &alive, sizeof(alive),
|
||||
NULL, 0, &dwBytesRet, NULL, NULL))
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Disable Nagle */
|
||||
optval = 1;
|
||||
tcp_proto = getprotobyname("TCP");
|
||||
setsockopt(fd, tcp_proto->p_proto, TCP_NODELAY, (const char *)&optval, optlen);
|
||||
|
||||
/* We are nonblocking... */
|
||||
ioctlsocket(fd, FIONBIO, &optl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_plat_drop_app_privileges(struct lws_context_creation_info *info)
|
||||
{
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_plat_init_fd_tables(struct libwebsocket_context *context)
|
||||
{
|
||||
context->events = (WSAEVENT *)malloc(sizeof(WSAEVENT) *
|
||||
(context->max_fds + 1));
|
||||
if (context->events == NULL) {
|
||||
lwsl_err("Unable to allocate events array for %d connections\n",
|
||||
context->max_fds);
|
||||
return 1;
|
||||
}
|
||||
|
||||
context->fds_count = 0;
|
||||
context->events[0] = WSACreateEvent();
|
||||
|
||||
context->fd_random = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 libwebsocket_context *context)
|
||||
{
|
||||
if (context->events) {
|
||||
WSACloseEvent(context->events[0]);
|
||||
free(context->events);
|
||||
}
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_plat_context_late_destroy(struct libwebsocket_context *context)
|
||||
{
|
||||
WSACleanup();
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
interface_to_sa(struct libwebsocket_context *context,
|
||||
const char *ifname, struct sockaddr_in *addr, size_t addrlen)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_plat_insert_socket_into_fds(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi)
|
||||
{
|
||||
context->fds[context->fds_count++].revents = 0;
|
||||
context->events[context->fds_count] = WSACreateEvent();
|
||||
WSAEventSelect(wsi->sock, context->events[context->fds_count], LWS_POLLIN);
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_plat_delete_socket_from_fds(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, int m)
|
||||
{
|
||||
WSACloseEvent(context->events[m + 1]);
|
||||
context->events[m + 1] = context->events[context->fds_count + 1];
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_plat_service_periodic(struct libwebsocket_context *context)
|
||||
{
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_plat_change_pollfd(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, struct libwebsocket_pollfd *pfd)
|
||||
{
|
||||
long networkevents = LWS_POLLOUT | LWS_POLLHUP;
|
||||
|
||||
if ((pfd->events & LWS_POLLIN))
|
||||
networkevents |= LWS_POLLIN;
|
||||
|
||||
if (WSAEventSelect(wsi->sock,
|
||||
context->events[wsi->position_in_fds_table + 1],
|
||||
networkevents) != SOCKET_ERROR)
|
||||
return 0;
|
||||
|
||||
lwsl_err("WSAEventSelect() failed with error %d\n", LWS_ERRNO);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
LWS_VISIBLE HANDLE
|
||||
lws_plat_open_file(const char* filename, unsigned long* filelen)
|
||||
{
|
||||
HANDLE ret;
|
||||
WCHAR buffer[MAX_PATH];
|
||||
|
||||
MultiByteToWideChar(CP_UTF8, 0, filename, -1, buffer,
|
||||
sizeof(buffer) / sizeof(buffer[0]));
|
||||
ret = CreateFileW(buffer, GENERIC_READ, FILE_SHARE_READ,
|
||||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (ret != LWS_INVALID_FILE)
|
||||
*filelen = GetFileSize(ret, NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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 = malloc(bufferlen);
|
||||
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_USE_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;
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
return ok ? dst : NULL;
|
||||
}
|
||||
316
dependencies/libwebsockets/lib/minilex.c
vendored
Normal file
316
dependencies/libwebsockets/lib/minilex.c
vendored
Normal file
@ -0,0 +1,316 @@
|
||||
/*
|
||||
* minilex.c
|
||||
*
|
||||
* High efficiency lexical state parser
|
||||
*
|
||||
* Copyright (C)2011-2014 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Licensed under LGPL2
|
||||
*
|
||||
* Usage: gcc minilex.c -o minilex && ./minilex > lextable.h
|
||||
*
|
||||
* Run it twice to test parsing on the generated table on stderr
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* set of parsable strings -- ALL LOWER CASE */
|
||||
|
||||
const char *set[] = {
|
||||
"get ",
|
||||
"post ",
|
||||
"options ",
|
||||
"host:",
|
||||
"connection:",
|
||||
"sec-websocket-key1:",
|
||||
"sec-websocket-key2:",
|
||||
"sec-websocket-protocol:",
|
||||
"upgrade:",
|
||||
"origin:",
|
||||
"sec-websocket-draft:",
|
||||
"\x0d\x0a",
|
||||
|
||||
"sec-websocket-key:",
|
||||
"sec-websocket-version:",
|
||||
"sec-websocket-origin:",
|
||||
|
||||
"sec-websocket-extensions:",
|
||||
|
||||
"sec-websocket-accept:",
|
||||
"sec-websocket-nonce:",
|
||||
"http/1.1 ",
|
||||
|
||||
"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:",
|
||||
"", /* not matchable */
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* b7 = 0 = 1-byte seq
|
||||
* 0x08 = fail
|
||||
* 2-byte seq
|
||||
* 0x00 - 0x07, then terminal as given in 2nd byte
|
||||
3-byte seq
|
||||
* no match: go fwd 3 byte, match: jump fwd by amt in +1/+2 bytes
|
||||
* = 1 = 1-byte seq
|
||||
* no match: die, match go fwd 1 byte
|
||||
*/
|
||||
|
||||
unsigned char lextable[] = {
|
||||
#include "lextable.h"
|
||||
};
|
||||
|
||||
#define PARALLEL 30
|
||||
|
||||
struct state {
|
||||
char c[PARALLEL];
|
||||
int state[PARALLEL];
|
||||
int count;
|
||||
int bytepos;
|
||||
|
||||
int real_pos;
|
||||
};
|
||||
|
||||
struct state state[1000];
|
||||
int next = 1;
|
||||
|
||||
#define FAIL_CHAR 0x08
|
||||
|
||||
int lextable_decode(int pos, char c)
|
||||
{
|
||||
|
||||
while (1) {
|
||||
if (lextable[pos] & (1 << 7)) { /* 1-byte, fail on mismatch */
|
||||
if ((lextable[pos] & 0x7f) != c)
|
||||
return -1;
|
||||
/* fall thru */
|
||||
pos++;
|
||||
if (lextable[pos] == FAIL_CHAR)
|
||||
return -1;
|
||||
return pos;
|
||||
} else { /* b7 = 0, end or 3-byte */
|
||||
if (lextable[pos] < FAIL_CHAR) /* terminal marker */
|
||||
return pos;
|
||||
|
||||
if (lextable[pos] == c) /* goto */
|
||||
return pos + (lextable[pos + 1]) +
|
||||
(lextable[pos + 2] << 8);
|
||||
/* fall thru goto */
|
||||
pos += 3;
|
||||
/* continue */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int n = 0;
|
||||
int m = 0;
|
||||
int prev;
|
||||
char c;
|
||||
int walk;
|
||||
int saw;
|
||||
int y;
|
||||
int j;
|
||||
int pos = 0;
|
||||
|
||||
while (n < sizeof(set) / sizeof(set[0])) {
|
||||
|
||||
m = 0;
|
||||
walk = 0;
|
||||
prev = 0;
|
||||
|
||||
if (set[n][0] == '\0') {
|
||||
n++;
|
||||
continue;
|
||||
}
|
||||
|
||||
while (set[n][m]) {
|
||||
|
||||
saw = 0;
|
||||
for (y = 0; y < state[walk].count; y++)
|
||||
if (state[walk].c[y] == set[n][m]) {
|
||||
/* exists -- go forward */
|
||||
walk = state[walk].state[y];
|
||||
saw = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (saw)
|
||||
goto again;
|
||||
|
||||
/* something we didn't see before */
|
||||
|
||||
state[walk].c[state[walk].count] = set[n][m];
|
||||
|
||||
state[walk].state[state[walk].count] = next;
|
||||
state[walk].count++;
|
||||
walk = next++;
|
||||
again:
|
||||
m++;
|
||||
}
|
||||
|
||||
state[walk].c[0] = n++;
|
||||
state[walk].state[0] = 0; /* terminal marker */
|
||||
state[walk].count = 1;
|
||||
}
|
||||
|
||||
walk = 0;
|
||||
for (n = 0; n < next; n++) {
|
||||
state[n].bytepos = walk;
|
||||
walk += (2 * state[n].count);
|
||||
}
|
||||
|
||||
/* compute everyone's position first */
|
||||
|
||||
pos = 0;
|
||||
walk = 0;
|
||||
for (n = 0; n < next; n++) {
|
||||
|
||||
state[n].real_pos = pos;
|
||||
|
||||
for (m = 0; m < state[n].count; m++) {
|
||||
|
||||
if (state[n].state[m] == 0)
|
||||
pos += 2; /* terminal marker */
|
||||
else { /* c is a character */
|
||||
if ((state[state[n].state[m]].bytepos -
|
||||
walk) == 2)
|
||||
pos++;
|
||||
else {
|
||||
pos += 3;
|
||||
if (m == state[n].count - 1)
|
||||
pos++; /* fail */
|
||||
}
|
||||
}
|
||||
walk += 2;
|
||||
}
|
||||
}
|
||||
|
||||
walk = 0;
|
||||
pos = 0;
|
||||
for (n = 0; n < next; n++) {
|
||||
for (m = 0; m < state[n].count; m++) {
|
||||
|
||||
if (!m)
|
||||
fprintf(stdout, "/* pos %04x: %3d */ ",
|
||||
state[n].real_pos, n);
|
||||
else
|
||||
fprintf(stdout, " ");
|
||||
|
||||
y = state[n].c[m];
|
||||
saw = state[n].state[m];
|
||||
|
||||
if (saw == 0) { // c is a terminal then
|
||||
|
||||
if (y > 0x7ff) {
|
||||
fprintf(stderr, "terminal too big\n");
|
||||
return 2;
|
||||
}
|
||||
|
||||
fprintf(stdout, " 0x%02X, 0x%02X "
|
||||
" "
|
||||
"/* - terminal marker %2d - */,\n",
|
||||
y >> 8, y & 0xff, y & 0x7f);
|
||||
pos += 2;
|
||||
walk += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* c is a character */
|
||||
|
||||
prev = y &0x7f;
|
||||
if (prev < 32 || prev > 126)
|
||||
prev = '.';
|
||||
|
||||
|
||||
if ((state[saw].bytepos - walk) == 2) {
|
||||
fprintf(stdout, " 0x%02X /* '%c' -> */,\n",
|
||||
y | 0x80, prev);
|
||||
pos++;
|
||||
walk += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
j = state[saw].real_pos - pos;
|
||||
|
||||
if (j > 0xffff) {
|
||||
fprintf(stderr,
|
||||
"Jump > 64K bytes ahead (%d to %d)\n",
|
||||
state[n].real_pos, state[saw].real_pos);
|
||||
return 1;
|
||||
}
|
||||
fprintf(stdout, " 0x%02X /* '%c' */, 0x%02X, 0x%02X "
|
||||
"/* (to 0x%04X state %3d) */,\n",
|
||||
y, prev,
|
||||
j & 0xff, j >> 8,
|
||||
state[saw].real_pos, saw);
|
||||
pos += 3;
|
||||
|
||||
if (m == state[n].count - 1) {
|
||||
fprintf(stdout,
|
||||
" 0x%02X, /* fail */\n",
|
||||
FAIL_CHAR);
|
||||
pos++; /* fail */
|
||||
}
|
||||
|
||||
walk += 2;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stdout, "/* total size %d bytes */\n", pos);
|
||||
|
||||
/*
|
||||
* Try to parse every legal input string
|
||||
*/
|
||||
|
||||
for (n = 0; n < sizeof(set) / sizeof(set[0]); n++) {
|
||||
walk = 0;
|
||||
m = 0;
|
||||
y = -1;
|
||||
|
||||
if (set[n][0] == '\0')
|
||||
continue;
|
||||
|
||||
fprintf(stderr, " trying '%s'\n", set[n]);
|
||||
|
||||
while (set[n][m]) {
|
||||
walk = lextable_decode(walk, set[n][m]);
|
||||
if (walk < 0) {
|
||||
fprintf(stderr, "failed\n");
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (lextable[walk] < FAIL_CHAR) {
|
||||
y = (lextable[walk] << 8) + lextable[walk + 1];
|
||||
break;
|
||||
}
|
||||
m++;
|
||||
}
|
||||
|
||||
if (y != n) {
|
||||
fprintf(stderr, "decode failed %d\n", y);
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "All decode OK\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
571
dependencies/libwebsockets/lib/output.c
vendored
Normal file
571
dependencies/libwebsockets/lib/output.c
vendored
Normal file
@ -0,0 +1,571 @@
|
||||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010-2014 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 "private-libwebsockets.h"
|
||||
|
||||
static int
|
||||
libwebsocket_0405_frame_mask_generate(struct libwebsocket *wsi)
|
||||
{
|
||||
int n;
|
||||
|
||||
/* fetch the per-frame nonce */
|
||||
|
||||
n = libwebsockets_get_random(wsi->protocol->owning_server,
|
||||
wsi->u.ws.frame_masking_nonce_04, 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->u.ws.frame_mask_index = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
||||
LWS_VISIBLE void lwsl_hexdump(void *vbuf, size_t len)
|
||||
{
|
||||
int n;
|
||||
int m;
|
||||
int start;
|
||||
unsigned char *buf = (unsigned char *)vbuf;
|
||||
char line[80];
|
||||
char *p;
|
||||
|
||||
lwsl_parser("\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';
|
||||
lwsl_debug("%s", line);
|
||||
}
|
||||
lwsl_debug("\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* notice this returns number of bytes consumed, or -1
|
||||
*/
|
||||
|
||||
int lws_issue_raw(struct libwebsocket *wsi, unsigned char *buf, size_t len)
|
||||
{
|
||||
struct libwebsocket_context *context = wsi->protocol->owning_server;
|
||||
int n;
|
||||
size_t real_len = len;
|
||||
int m;
|
||||
|
||||
if (!len)
|
||||
return 0;
|
||||
/* just ignore sends after we cleared the truncation buffer */
|
||||
if (wsi->state == WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE &&
|
||||
!wsi->truncated_send_len)
|
||||
return len;
|
||||
|
||||
if (wsi->truncated_send_len && (buf < wsi->truncated_send_malloc ||
|
||||
buf > (wsi->truncated_send_malloc +
|
||||
wsi->truncated_send_len +
|
||||
wsi->truncated_send_offset))) {
|
||||
lwsl_err("****** %x Sending new, pending truncated ...\n", wsi);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
m = lws_ext_callback_for_each_active(wsi,
|
||||
LWS_EXT_CALLBACK_PACKET_TX_DO_SEND, &buf, len);
|
||||
if (m < 0)
|
||||
return -1;
|
||||
if (m) /* handled */ {
|
||||
n = m;
|
||||
goto handle_truncated_send;
|
||||
}
|
||||
if (wsi->sock < 0)
|
||||
lwsl_warn("** error invalid sock but expected to send\n");
|
||||
|
||||
/*
|
||||
* nope, send it on the socket directly
|
||||
*/
|
||||
lws_latency_pre(context, wsi);
|
||||
n = lws_ssl_capable_write(wsi, buf, len);
|
||||
lws_latency(context, wsi, "send lws_issue_raw", n, n == len);
|
||||
|
||||
switch (n) {
|
||||
case LWS_SSL_CAPABLE_ERROR:
|
||||
return -1;
|
||||
case LWS_SSL_CAPABLE_MORE_SERVICE:
|
||||
/* nothing got sent, not fatal, retry the whole thing later */
|
||||
n = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
handle_truncated_send:
|
||||
/*
|
||||
* we were already handling a truncated send?
|
||||
*/
|
||||
if (wsi->truncated_send_len) {
|
||||
lwsl_info("***** %x partial send moved on by %d (vs %d)\n",
|
||||
wsi, n, real_len);
|
||||
wsi->truncated_send_offset += n;
|
||||
wsi->truncated_send_len -= n;
|
||||
|
||||
if (!wsi->truncated_send_len) {
|
||||
lwsl_info("***** %x partial send completed\n", wsi);
|
||||
/* done with it, but don't free it */
|
||||
n = real_len;
|
||||
if (wsi->state == WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE) {
|
||||
lwsl_info("***** %x signalling to close now\n", wsi);
|
||||
return -1; /* retry closing now */
|
||||
}
|
||||
}
|
||||
/* always callback on writeable */
|
||||
libwebsocket_callback_on_writable(
|
||||
wsi->protocol->owning_server, wsi);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
if (n == real_len)
|
||||
/* what we just sent went out cleanly */
|
||||
return n;
|
||||
|
||||
if (n && wsi->u.ws.clean_buffer)
|
||||
/*
|
||||
* This buffer unaffected by extension rewriting.
|
||||
* It means the user code is expected to deal with
|
||||
* partial sends. (lws knows the header was already
|
||||
* sent, so on next send will just resume sending
|
||||
* payload)
|
||||
*/
|
||||
return n;
|
||||
|
||||
/*
|
||||
* Newly truncated send. Buffer the remainder (it will get
|
||||
* first priority next time the socket is writable)
|
||||
*/
|
||||
lwsl_info("***** %x new partial sent %d from %d total\n",
|
||||
wsi, n, real_len);
|
||||
|
||||
/*
|
||||
* - 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->truncated_send_malloc ||
|
||||
real_len - n > wsi->truncated_send_allocation) {
|
||||
if (wsi->truncated_send_malloc)
|
||||
free(wsi->truncated_send_malloc);
|
||||
|
||||
wsi->truncated_send_allocation = real_len - n;
|
||||
wsi->truncated_send_malloc = malloc(real_len - n);
|
||||
if (!wsi->truncated_send_malloc) {
|
||||
lwsl_err("truncated send: unable to malloc %d\n",
|
||||
real_len - n);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
wsi->truncated_send_offset = 0;
|
||||
wsi->truncated_send_len = real_len - n;
|
||||
memcpy(wsi->truncated_send_malloc, buf + n, real_len - n);
|
||||
|
||||
/* since something buffered, force it to get another chance to send */
|
||||
libwebsocket_callback_on_writable(wsi->protocol->owning_server, wsi);
|
||||
|
||||
return real_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* libwebsocket_write() - Apply protocol then write data to client
|
||||
* @wsi: Websocket instance (available from user callback)
|
||||
* @buf: The data to send. For data being sent on a websocket
|
||||
* connection (ie, not default http), this buffer MUST have
|
||||
* LWS_SEND_BUFFER_PRE_PADDING bytes valid BEFORE the pointer
|
||||
* and an additional LWS_SEND_BUFFER_POST_PADDING bytes valid
|
||||
* in the buffer after (buf + len). This is so the protocol
|
||||
* header and trailer data can be added in-situ.
|
||||
* @len: Count of the data bytes in the payload starting from buf
|
||||
* @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.
|
||||
*
|
||||
* 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 a
|
||||
* positive number reflecting the amount of bytes actually sent. This
|
||||
* can be less than the requested number of bytes due to OS memory
|
||||
* pressure at any given time.
|
||||
*/
|
||||
|
||||
LWS_VISIBLE int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf,
|
||||
size_t len, enum libwebsocket_write_protocol protocol)
|
||||
{
|
||||
int n;
|
||||
int pre = 0;
|
||||
int post = 0;
|
||||
int masked7 = wsi->mode == LWS_CONNMODE_WS_CLIENT;
|
||||
unsigned char *dropmask = NULL;
|
||||
unsigned char is_masked_bit = 0;
|
||||
size_t orig_len = len;
|
||||
struct lws_tokens eff_buf;
|
||||
|
||||
if (len == 0 && protocol != LWS_WRITE_CLOSE &&
|
||||
protocol != LWS_WRITE_PING && protocol != LWS_WRITE_PONG) {
|
||||
lwsl_warn("zero length libwebsocket_write attempt\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (protocol == LWS_WRITE_HTTP)
|
||||
goto send_raw;
|
||||
|
||||
/* websocket protocol, either binary or text */
|
||||
|
||||
if (wsi->state != WSI_STATE_ESTABLISHED)
|
||||
return -1;
|
||||
|
||||
/* if we are continuing a frame that already had its header done */
|
||||
|
||||
if (wsi->u.ws.inside_frame)
|
||||
goto do_more_inside_frame;
|
||||
|
||||
/* if he wants all partials buffered, never have a clean_buffer */
|
||||
wsi->u.ws.clean_buffer = !wsi->protocol->no_buffer_all_partial_tx;
|
||||
|
||||
/*
|
||||
* give a chance to the extensions to modify payload
|
||||
* pre-TX mangling is not allowed to truncate
|
||||
*/
|
||||
eff_buf.token = (char *)buf;
|
||||
eff_buf.token_len = len;
|
||||
|
||||
switch (protocol) {
|
||||
case LWS_WRITE_PING:
|
||||
case LWS_WRITE_PONG:
|
||||
case LWS_WRITE_CLOSE:
|
||||
break;
|
||||
default:
|
||||
if (lws_ext_callback_for_each_active(wsi,
|
||||
LWS_EXT_CALLBACK_PAYLOAD_TX, &eff_buf, 0) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 != eff_buf.token)
|
||||
/*
|
||||
* extension recreated it:
|
||||
* need to buffer this if not all sent
|
||||
*/
|
||||
wsi->u.ws.clean_buffer = 0;
|
||||
|
||||
buf = (unsigned char *)eff_buf.token;
|
||||
len = eff_buf.token_len;
|
||||
|
||||
switch (wsi->ietf_spec_revision) {
|
||||
case 13:
|
||||
|
||||
if (masked7) {
|
||||
pre += 4;
|
||||
dropmask = &buf[0 - pre];
|
||||
is_masked_bit = 0x80;
|
||||
}
|
||||
|
||||
switch (protocol & 0xf) {
|
||||
case LWS_WRITE_TEXT:
|
||||
n = LWS_WS_OPCODE_07__TEXT_FRAME;
|
||||
break;
|
||||
case LWS_WRITE_BINARY:
|
||||
n = LWS_WS_OPCODE_07__BINARY_FRAME;
|
||||
break;
|
||||
case LWS_WRITE_CONTINUATION:
|
||||
n = LWS_WS_OPCODE_07__CONTINUATION;
|
||||
break;
|
||||
|
||||
case LWS_WRITE_CLOSE:
|
||||
n = LWS_WS_OPCODE_07__CLOSE;
|
||||
|
||||
/*
|
||||
* 06+ has a 2-byte status code in network order
|
||||
* we can do this because we demand post-buf
|
||||
*/
|
||||
|
||||
if (wsi->u.ws.close_reason) {
|
||||
/* reason codes count as data bytes */
|
||||
buf -= 2;
|
||||
buf[0] = wsi->u.ws.close_reason >> 8;
|
||||
buf[1] = wsi->u.ws.close_reason;
|
||||
len += 2;
|
||||
}
|
||||
break;
|
||||
case LWS_WRITE_PING:
|
||||
n = LWS_WS_OPCODE_07__PING;
|
||||
break;
|
||||
case LWS_WRITE_PONG:
|
||||
n = LWS_WS_OPCODE_07__PONG;
|
||||
break;
|
||||
default:
|
||||
lwsl_warn("lws_write: unknown write opc / protocol\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(protocol & LWS_WRITE_NO_FIN))
|
||||
n |= 1 << 7;
|
||||
|
||||
if (len < 126) {
|
||||
pre += 2;
|
||||
buf[-pre] = n;
|
||||
buf[-pre + 1] = len | is_masked_bit;
|
||||
} else {
|
||||
if (len < 65536) {
|
||||
pre += 4;
|
||||
buf[-pre] = n;
|
||||
buf[-pre + 1] = 126 | is_masked_bit;
|
||||
buf[-pre + 2] = len >> 8;
|
||||
buf[-pre + 3] = 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] = len >> 24;
|
||||
buf[-pre + 7] = len >> 16;
|
||||
buf[-pre + 8] = len >> 8;
|
||||
buf[-pre + 9] = len;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
do_more_inside_frame:
|
||||
|
||||
/*
|
||||
* Deal with masking if we are in client -> server direction and
|
||||
* the protocol demands it
|
||||
*/
|
||||
|
||||
if (wsi->mode == LWS_CONNMODE_WS_CLIENT) {
|
||||
|
||||
if (!wsi->u.ws.inside_frame)
|
||||
if (libwebsocket_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->u.ws.frame_masking_nonce_04[
|
||||
(wsi->u.ws.frame_mask_index++) & 3];
|
||||
|
||||
/* copy the frame nonce into place */
|
||||
memcpy(dropmask, wsi->u.ws.frame_masking_nonce_04, 4);
|
||||
}
|
||||
}
|
||||
|
||||
send_raw:
|
||||
switch (protocol) {
|
||||
case LWS_WRITE_CLOSE:
|
||||
/* lwsl_hexdump(&buf[-pre], len + post); */
|
||||
case LWS_WRITE_HTTP:
|
||||
case LWS_WRITE_PONG:
|
||||
case LWS_WRITE_PING:
|
||||
return lws_issue_raw(wsi, (unsigned char *)buf - pre,
|
||||
len + pre + post);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
wsi->u.ws.inside_frame = 1;
|
||||
|
||||
/*
|
||||
* 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->u.ws.clean_buffer is 0 (meaning an extension meddled with
|
||||
* the buffer). If wsi->u.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 + post);
|
||||
if (n <= 0)
|
||||
return n;
|
||||
|
||||
if (n == len + pre + post) {
|
||||
/* everything in the buffer was handled (or rebuffered...) */
|
||||
wsi->u.ws.inside_frame = 0;
|
||||
return 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 libwebsocket_write() again with the rest
|
||||
* later.
|
||||
*/
|
||||
|
||||
return n - (pre + post);
|
||||
}
|
||||
|
||||
LWS_VISIBLE int libwebsockets_serve_http_file_fragment(
|
||||
struct libwebsocket_context *context, struct libwebsocket *wsi)
|
||||
{
|
||||
int n;
|
||||
int m;
|
||||
|
||||
while (!lws_send_pipe_choked(wsi)) {
|
||||
|
||||
if (wsi->truncated_send_len) {
|
||||
if (lws_issue_raw(wsi, wsi->truncated_send_malloc +
|
||||
wsi->truncated_send_offset,
|
||||
wsi->truncated_send_len) < 0) {
|
||||
lwsl_info("closing from libwebsockets_serve_http_file_fragment\n");
|
||||
return -1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (wsi->u.http.filepos == wsi->u.http.filelen)
|
||||
goto all_sent;
|
||||
|
||||
compatible_file_read(n, wsi->u.http.fd, context->service_buffer,
|
||||
sizeof(context->service_buffer));
|
||||
if (n < 0)
|
||||
return -1; /* caller will close */
|
||||
if (n) {
|
||||
m = libwebsocket_write(wsi, context->service_buffer, n,
|
||||
LWS_WRITE_HTTP);
|
||||
if (m < 0)
|
||||
return -1;
|
||||
|
||||
wsi->u.http.filepos += m;
|
||||
if (m != n)
|
||||
/* adjust for what was not sent */
|
||||
compatible_file_seek_cur(wsi->u.http.fd, m - n);
|
||||
}
|
||||
all_sent:
|
||||
if (!wsi->truncated_send_len &&
|
||||
wsi->u.http.filepos == wsi->u.http.filelen) {
|
||||
wsi->state = WSI_STATE_HTTP;
|
||||
|
||||
if (wsi->protocol->callback)
|
||||
/* ignore callback returned value */
|
||||
user_callback_handle_rxflow(
|
||||
wsi->protocol->callback, context, wsi,
|
||||
LWS_CALLBACK_HTTP_FILE_COMPLETION,
|
||||
wsi->user_space, NULL, 0);
|
||||
return 1; /* >0 indicates completed */
|
||||
}
|
||||
}
|
||||
|
||||
lwsl_info("choked before able to send whole file (post)\n");
|
||||
libwebsocket_callback_on_writable(context, wsi);
|
||||
|
||||
return 0; /* indicates further processing must be done */
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_ssl_capable_read_no_ssl(struct libwebsocket *wsi, unsigned char *buf, int len)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = recv(wsi->sock, buf, len, 0);
|
||||
if (n >= 0)
|
||||
return n;
|
||||
|
||||
lwsl_warn("error on reading from skt\n");
|
||||
return LWS_SSL_CAPABLE_ERROR;
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_ssl_capable_write_no_ssl(struct libwebsocket *wsi, unsigned char *buf, int len)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = send(wsi->sock, buf, len, 0);
|
||||
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 %d\n", len, n);
|
||||
return LWS_SSL_CAPABLE_ERROR;
|
||||
}
|
||||
1008
dependencies/libwebsockets/lib/parsers.c
vendored
Normal file
1008
dependencies/libwebsockets/lib/parsers.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
239
dependencies/libwebsockets/lib/pollfd.c
vendored
Normal file
239
dependencies/libwebsockets/lib/pollfd.c
vendored
Normal file
@ -0,0 +1,239 @@
|
||||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010-2014 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 "private-libwebsockets.h"
|
||||
|
||||
int
|
||||
insert_wsi_socket_into_fds(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi)
|
||||
{
|
||||
struct libwebsocket_pollargs pa = { wsi->sock, LWS_POLLIN, 0 };
|
||||
|
||||
if (context->fds_count >= context->max_fds) {
|
||||
lwsl_err("Too many fds (%d)\n", context->max_fds);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (wsi->sock >= context->max_fds) {
|
||||
lwsl_err("Socket fd %d is too high (%d)\n",
|
||||
wsi->sock, context->max_fds);
|
||||
return 1;
|
||||
}
|
||||
|
||||
assert(wsi);
|
||||
assert(wsi->sock >= 0);
|
||||
|
||||
lwsl_info("insert_wsi_socket_into_fds: wsi=%p, sock=%d, fds pos=%d\n",
|
||||
wsi, wsi->sock, context->fds_count);
|
||||
|
||||
context->protocols[0].callback(context, wsi,
|
||||
LWS_CALLBACK_LOCK_POLL,
|
||||
wsi->user_space, (void *) &pa, 0);
|
||||
|
||||
context->lws_lookup[wsi->sock] = wsi;
|
||||
wsi->position_in_fds_table = context->fds_count;
|
||||
context->fds[context->fds_count].fd = wsi->sock;
|
||||
context->fds[context->fds_count].events = LWS_POLLIN;
|
||||
|
||||
lws_plat_insert_socket_into_fds(context, wsi);
|
||||
|
||||
/* external POLL support via protocol 0 */
|
||||
context->protocols[0].callback(context, wsi,
|
||||
LWS_CALLBACK_ADD_POLL_FD,
|
||||
wsi->user_space, (void *) &pa, 0);
|
||||
|
||||
context->protocols[0].callback(context, wsi,
|
||||
LWS_CALLBACK_UNLOCK_POLL,
|
||||
wsi->user_space, (void *)&pa, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
remove_wsi_socket_from_fds(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi)
|
||||
{
|
||||
int m;
|
||||
struct libwebsocket_pollargs pa = { wsi->sock, 0, 0 };
|
||||
|
||||
lws_libev_io(context, wsi, LWS_EV_STOP | LWS_EV_READ | LWS_EV_WRITE);
|
||||
|
||||
if (!--context->fds_count) {
|
||||
context->protocols[0].callback(context, wsi,
|
||||
LWS_CALLBACK_LOCK_POLL,
|
||||
wsi->user_space, (void *) &pa, 0);
|
||||
goto do_ext;
|
||||
}
|
||||
|
||||
if (wsi->sock > context->max_fds) {
|
||||
lwsl_err("Socket fd %d too high (%d)\n",
|
||||
wsi->sock, context->max_fds);
|
||||
return 1;
|
||||
}
|
||||
|
||||
lwsl_info("%s: wsi=%p, sock=%d, fds pos=%d\n", __func__,
|
||||
wsi, wsi->sock, wsi->position_in_fds_table);
|
||||
|
||||
context->protocols[0].callback(context, wsi,
|
||||
LWS_CALLBACK_LOCK_POLL,
|
||||
wsi->user_space, (void *)&pa, 0);
|
||||
|
||||
m = wsi->position_in_fds_table; /* replace the contents for this */
|
||||
|
||||
/* have the last guy take up the vacant slot */
|
||||
context->fds[m] = context->fds[context->fds_count];
|
||||
|
||||
lws_plat_delete_socket_from_fds(context, wsi, m);
|
||||
|
||||
/*
|
||||
* end guy's fds_lookup entry remains unchanged
|
||||
* (still same fd pointing to same wsi)
|
||||
*/
|
||||
/* end guy's "position in fds table" changed */
|
||||
context->lws_lookup[context->fds[context->fds_count].fd]->
|
||||
position_in_fds_table = m;
|
||||
/* deletion guy's lws_lookup entry needs nuking */
|
||||
context->lws_lookup[wsi->sock] = NULL;
|
||||
/* removed wsi has no position any more */
|
||||
wsi->position_in_fds_table = -1;
|
||||
|
||||
do_ext:
|
||||
/* remove also from external POLL support via protocol 0 */
|
||||
if (wsi->sock) {
|
||||
context->protocols[0].callback(context, wsi,
|
||||
LWS_CALLBACK_DEL_POLL_FD, wsi->user_space,
|
||||
(void *) &pa, 0);
|
||||
}
|
||||
context->protocols[0].callback(context, wsi,
|
||||
LWS_CALLBACK_UNLOCK_POLL,
|
||||
wsi->user_space, (void *) &pa, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
lws_change_pollfd(struct libwebsocket *wsi, int _and, int _or)
|
||||
{
|
||||
struct libwebsocket_context *context = wsi->protocol->owning_server;
|
||||
int tid;
|
||||
int sampled_tid;
|
||||
struct libwebsocket_pollfd *pfd;
|
||||
struct libwebsocket_pollargs pa;
|
||||
|
||||
pfd = &context->fds[wsi->position_in_fds_table];
|
||||
pa.fd = wsi->sock;
|
||||
|
||||
context->protocols[0].callback(context, wsi,
|
||||
LWS_CALLBACK_LOCK_POLL, wsi->user_space, (void *) &pa, 0);
|
||||
|
||||
pa.prev_events = pfd->events;
|
||||
pa.events = pfd->events = (pfd->events & ~_and) | _or;
|
||||
|
||||
context->protocols[0].callback(context, wsi,
|
||||
LWS_CALLBACK_CHANGE_MODE_POLL_FD,
|
||||
wsi->user_space, (void *) &pa, 0);
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
if (pa.prev_events != pa.events) {
|
||||
|
||||
if (lws_plat_change_pollfd(context, wsi, pfd)) {
|
||||
lwsl_info("%s failed\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
sampled_tid = context->service_tid;
|
||||
if (sampled_tid) {
|
||||
tid = context->protocols[0].callback(context, NULL,
|
||||
LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0);
|
||||
if (tid != sampled_tid)
|
||||
libwebsocket_cancel_service(context);
|
||||
}
|
||||
}
|
||||
|
||||
context->protocols[0].callback(context, wsi,
|
||||
LWS_CALLBACK_UNLOCK_POLL, wsi->user_space, (void *) &pa, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* libwebsocket_callback_on_writable() - Request a callback when this socket
|
||||
* becomes able to be written to without
|
||||
* blocking
|
||||
*
|
||||
* @context: libwebsockets context
|
||||
* @wsi: Websocket connection instance to get callback for
|
||||
*/
|
||||
|
||||
LWS_VISIBLE int
|
||||
libwebsocket_callback_on_writable(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi)
|
||||
{
|
||||
if (lws_ext_callback_for_each_active(wsi,
|
||||
LWS_EXT_CALLBACK_REQUEST_ON_WRITEABLE, NULL, 0))
|
||||
return 1;
|
||||
|
||||
if (wsi->position_in_fds_table < 0) {
|
||||
lwsl_err("%s: failed to find socket %d\n", __func__, wsi->sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (lws_change_pollfd(wsi, 0, LWS_POLLOUT))
|
||||
return -1;
|
||||
|
||||
lws_libev_io(context, wsi, LWS_EV_START | LWS_EV_WRITE);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* libwebsocket_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.
|
||||
*
|
||||
* @protocol: Protocol whose connections will get callbacks
|
||||
*/
|
||||
|
||||
LWS_VISIBLE int
|
||||
libwebsocket_callback_on_writable_all_protocol(
|
||||
const struct libwebsocket_protocols *protocol)
|
||||
{
|
||||
struct libwebsocket_context *context = protocol->owning_server;
|
||||
int n;
|
||||
struct libwebsocket *wsi;
|
||||
|
||||
for (n = 0; n < context->fds_count; n++) {
|
||||
wsi = context->lws_lookup[context->fds[n].fd];
|
||||
if (!wsi)
|
||||
continue;
|
||||
if (wsi->protocol == protocol)
|
||||
libwebsocket_callback_on_writable(context, wsi);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
912
dependencies/libwebsockets/lib/private-libwebsockets.h
vendored
Normal file
912
dependencies/libwebsockets/lib/private-libwebsockets.h
vendored
Normal file
@ -0,0 +1,912 @@
|
||||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2013 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
|
||||
*/
|
||||
|
||||
/* System introspection configs */
|
||||
#ifdef CMAKE_BUILD
|
||||
#include "lws_config.h"
|
||||
#else
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
#define inline __inline
|
||||
#else /* not WIN32 */
|
||||
#include "config.h"
|
||||
|
||||
#endif /* not WIN32 */
|
||||
#endif /* not CMAKE */
|
||||
|
||||
#ifdef 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>
|
||||
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
#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 LWS_POLLHUP (FD_CLOSE)
|
||||
#define LWS_POLLIN (FD_READ | FD_ACCEPT)
|
||||
#define LWS_POLLOUT (FD_WRITE)
|
||||
#define MSG_NOSIGNAL 0
|
||||
#define SHUT_RDWR SD_BOTH
|
||||
#define SOL_TCP IPPROTO_TCP
|
||||
|
||||
#define compatible_close(fd) closesocket(fd)
|
||||
#define compatible_file_close(fd) CloseHandle(fd)
|
||||
#define compatible_file_seek_cur(fd, offset) SetFilePointer(fd, offset, NULL, FILE_CURRENT)
|
||||
#define compatible_file_read(amount, fd, buf, len) {\
|
||||
DWORD _amount; \
|
||||
if (!ReadFile(fd, buf, len, &_amount, NULL)) \
|
||||
amount = -1; \
|
||||
else \
|
||||
amount = _amount; \
|
||||
}
|
||||
#define lws_set_blocking_send(wsi) wsi->sock_send_blocking = TRUE
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#ifdef HAVE_IN6ADDR_H
|
||||
#include <in6addr.h>
|
||||
#endif
|
||||
#include <mstcpip.h>
|
||||
|
||||
#ifndef __func__
|
||||
#define __func__ __FUNCTION__
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32_WCE
|
||||
#define vsnprintf _vsnprintf
|
||||
#endif
|
||||
|
||||
#define LWS_INVALID_FILE INVALID_HANDLE_VALUE
|
||||
#else /* not windows --> */
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <signal.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#ifdef LWS_BUILTIN_GETIFADDRS
|
||||
#include <getifaddrs.h>
|
||||
#else
|
||||
#include <ifaddrs.h>
|
||||
#endif
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#ifndef LWS_NO_FORK
|
||||
#ifdef HAVE_SYS_PRCTL_H
|
||||
#include <sys/prctl.h>
|
||||
#endif
|
||||
#endif
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <poll.h>
|
||||
#ifdef LWS_USE_LIBEV
|
||||
#include <ev.h>
|
||||
#endif /* LWS_USE_LIBEV */
|
||||
|
||||
#include <sys/mman.h>
|
||||
#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_INVALID_FILE -1
|
||||
#define LWS_POLLHUP (POLLHUP|POLLERR)
|
||||
#define LWS_POLLIN (POLLIN)
|
||||
#define LWS_POLLOUT (POLLOUT)
|
||||
#define compatible_close(fd) close(fd)
|
||||
#define compatible_file_close(fd) close(fd)
|
||||
#define compatible_file_seek_cur(fd, offset) lseek(fd, offset, SEEK_CUR)
|
||||
#define compatible_file_read(amount, fd, buf, len) \
|
||||
amount = read(fd, buf, len);
|
||||
#define lws_set_blocking_send(wsi)
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_BZERO
|
||||
#define bzero(b, len) (memset((b), '\0', (len)), (void) 0)
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRERROR
|
||||
#define strerror(x) ""
|
||||
#endif
|
||||
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
#ifdef USE_CYASSL
|
||||
#include <cyassl/openssl/ssl.h>
|
||||
#include <cyassl/error.h>
|
||||
unsigned char *
|
||||
SHA1(const unsigned char *d, size_t n, unsigned char *md);
|
||||
#else
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/md5.h>
|
||||
#include <openssl/sha.h>
|
||||
#endif /* not USE_CYASSL */
|
||||
#endif
|
||||
|
||||
#include "libwebsockets.h"
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
|
||||
#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
|
||||
typedef unsigned __int64 u_int64_t;
|
||||
|
||||
#undef __P
|
||||
#ifndef __P
|
||||
#if __STDC__
|
||||
#define __P(protos) protos
|
||||
#else
|
||||
#define __P(protos) ()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/cdefs.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
|
||||
|
||||
#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
|
||||
|
||||
#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
|
||||
|
||||
#ifndef LWS_MAX_HEADER_LEN
|
||||
#define LWS_MAX_HEADER_LEN 1024
|
||||
#endif
|
||||
#ifndef LWS_MAX_PROTOCOLS
|
||||
#define LWS_MAX_PROTOCOLS 5
|
||||
#endif
|
||||
#ifndef LWS_MAX_EXTENSIONS_ACTIVE
|
||||
#define LWS_MAX_EXTENSIONS_ACTIVE 3
|
||||
#endif
|
||||
#ifndef SPEC_LATEST_SUPPORTED
|
||||
#define SPEC_LATEST_SUPPORTED 13
|
||||
#endif
|
||||
#ifndef AWAITING_TIMEOUT
|
||||
#define AWAITING_TIMEOUT 5
|
||||
#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
|
||||
#define LWS_MAX_SOCKET_IO_BUF 4096
|
||||
|
||||
#ifndef SYSTEM_RANDOM_FILEPATH
|
||||
#define SYSTEM_RANDOM_FILEPATH "/dev/urandom"
|
||||
#endif
|
||||
#ifndef LWS_MAX_ZLIB_CONN_BUFFER
|
||||
#define LWS_MAX_ZLIB_CONN_BUFFER (64 * 1024)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* if not in a connection storm, check for incoming
|
||||
* connections this many normal connection services
|
||||
*/
|
||||
#define LWS_LISTEN_SERVICE_MODULO 10
|
||||
|
||||
enum lws_websocket_opcodes_07 {
|
||||
LWS_WS_OPCODE_07__CONTINUATION = 0,
|
||||
LWS_WS_OPCODE_07__TEXT_FRAME = 1,
|
||||
LWS_WS_OPCODE_07__BINARY_FRAME = 2,
|
||||
|
||||
LWS_WS_OPCODE_07__NOSPEC__MUX = 7,
|
||||
|
||||
/* control extensions 8+ */
|
||||
|
||||
LWS_WS_OPCODE_07__CLOSE = 8,
|
||||
LWS_WS_OPCODE_07__PING = 9,
|
||||
LWS_WS_OPCODE_07__PONG = 0xa,
|
||||
};
|
||||
|
||||
|
||||
enum lws_connection_states {
|
||||
WSI_STATE_HTTP,
|
||||
WSI_STATE_HTTP_ISSUING_FILE,
|
||||
WSI_STATE_HTTP_HEADERS,
|
||||
WSI_STATE_HTTP_BODY,
|
||||
WSI_STATE_DEAD_SOCKET,
|
||||
WSI_STATE_ESTABLISHED,
|
||||
WSI_STATE_CLIENT_UNCONNECTED,
|
||||
WSI_STATE_RETURNED_CLOSE_ALREADY,
|
||||
WSI_STATE_AWAITING_CLOSE_ACK,
|
||||
WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE,
|
||||
};
|
||||
|
||||
enum lws_rx_parse_state {
|
||||
LWS_RXPS_NEW,
|
||||
|
||||
LWS_RXPS_04_MASK_NONCE_1,
|
||||
LWS_RXPS_04_MASK_NONCE_2,
|
||||
LWS_RXPS_04_MASK_NONCE_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_PAYLOAD_UNTIL_LENGTH_EXHAUSTED
|
||||
};
|
||||
|
||||
|
||||
enum connection_mode {
|
||||
LWS_CONNMODE_HTTP_SERVING,
|
||||
LWS_CONNMODE_HTTP_SERVING_ACCEPTED, /* actual HTTP service going on */
|
||||
LWS_CONNMODE_PRE_WS_SERVING_ACCEPT,
|
||||
|
||||
LWS_CONNMODE_WS_SERVING,
|
||||
LWS_CONNMODE_WS_CLIENT,
|
||||
|
||||
/* transient, ssl delay hiding */
|
||||
LWS_CONNMODE_SSL_ACK_PENDING,
|
||||
|
||||
/* transient modes */
|
||||
LWS_CONNMODE_WS_CLIENT_WAITING_CONNECT,
|
||||
LWS_CONNMODE_WS_CLIENT_WAITING_PROXY_REPLY,
|
||||
LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE,
|
||||
LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE2,
|
||||
LWS_CONNMODE_WS_CLIENT_WAITING_SSL,
|
||||
LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY,
|
||||
LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT,
|
||||
LWS_CONNMODE_WS_CLIENT_PENDING_CANDIDATE_CHILD,
|
||||
|
||||
/* special internal types */
|
||||
LWS_CONNMODE_SERVER_LISTENER,
|
||||
};
|
||||
|
||||
enum {
|
||||
LWS_RXFLOW_ALLOW = (1 << 0),
|
||||
LWS_RXFLOW_PENDING_CHANGE = (1 << 1),
|
||||
};
|
||||
|
||||
struct libwebsocket_protocols;
|
||||
struct libwebsocket;
|
||||
|
||||
#ifdef LWS_USE_LIBEV
|
||||
struct lws_io_watcher {
|
||||
struct ev_io watcher;
|
||||
struct libwebsocket_context* context;
|
||||
};
|
||||
|
||||
struct lws_signal_watcher {
|
||||
struct ev_signal watcher;
|
||||
struct libwebsocket_context* context;
|
||||
};
|
||||
#endif /* LWS_USE_LIBEV */
|
||||
|
||||
struct libwebsocket_context {
|
||||
#ifdef _WIN32
|
||||
WSAEVENT *events;
|
||||
#endif
|
||||
struct libwebsocket_pollfd *fds;
|
||||
struct libwebsocket **lws_lookup; /* fd to wsi */
|
||||
int fds_count;
|
||||
#ifdef LWS_USE_LIBEV
|
||||
struct ev_loop* io_loop;
|
||||
struct lws_io_watcher w_accept;
|
||||
struct lws_signal_watcher w_sigint;
|
||||
#endif /* LWS_USE_LIBEV */
|
||||
int max_fds;
|
||||
int listen_port;
|
||||
const char *iface;
|
||||
char http_proxy_address[128];
|
||||
char canonical_hostname[128];
|
||||
unsigned int http_proxy_port;
|
||||
unsigned int options;
|
||||
time_t last_timeout_check_s;
|
||||
|
||||
/*
|
||||
* 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 service_buffer[LWS_MAX_SOCKET_IO_BUF];
|
||||
|
||||
int started_with_parent;
|
||||
|
||||
int fd_random;
|
||||
int listen_service_modulo;
|
||||
int listen_service_count;
|
||||
int listen_service_fd;
|
||||
int listen_service_extraseen;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
#ifndef _WIN32
|
||||
int dummy_pipe_fds[2];
|
||||
#endif
|
||||
|
||||
int ka_time;
|
||||
int ka_probes;
|
||||
int ka_interval;
|
||||
|
||||
#ifdef LWS_LATENCY
|
||||
unsigned long worst_latency;
|
||||
char worst_latency_info[256];
|
||||
#endif
|
||||
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
int use_ssl;
|
||||
int allow_non_ssl_on_ssl_port;
|
||||
SSL_CTX *ssl_ctx;
|
||||
SSL_CTX *ssl_client_ctx;
|
||||
#endif
|
||||
struct libwebsocket_protocols *protocols;
|
||||
int count_protocols;
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
struct libwebsocket_extension *extensions;
|
||||
#endif
|
||||
struct lws_token_limits *token_limits;
|
||||
void *user_space;
|
||||
};
|
||||
|
||||
enum {
|
||||
LWS_EV_READ = (1 << 0),
|
||||
LWS_EV_WRITE = (1 << 1),
|
||||
LWS_EV_START = (1 << 2),
|
||||
LWS_EV_STOP = (1 << 3),
|
||||
};
|
||||
|
||||
#ifdef LWS_USE_LIBEV
|
||||
#define LWS_LIBEV_ENABLED(context) (context->options & LWS_SERVER_OPTION_LIBEV)
|
||||
LWS_EXTERN void lws_feature_status_libev(struct lws_context_creation_info *info);
|
||||
LWS_EXTERN void
|
||||
lws_libev_accept(struct libwebsocket_context *context,
|
||||
struct libwebsocket *new_wsi, int accept_fd);
|
||||
LWS_EXTERN void
|
||||
lws_libev_io(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, int flags);
|
||||
LWS_EXTERN int
|
||||
lws_libev_init_fd_table(struct libwebsocket_context *context);
|
||||
LWS_EXTERN void
|
||||
lws_libev_run(struct libwebsocket_context *context);
|
||||
#else
|
||||
#define LWS_LIBEV_ENABLED(context) (0)
|
||||
#define lws_feature_status_libev(_a) \
|
||||
lwsl_notice("libev support not compiled in\n")
|
||||
#define lws_libev_accept(_a, _b, _c) ((void) 0)
|
||||
#define lws_libev_io(_a, _b, _c) ((void) 0)
|
||||
#define lws_libev_init_fd_table(_a) (0)
|
||||
#define lws_libev_run(_a) ((void) 0)
|
||||
#endif
|
||||
|
||||
#ifdef LWS_USE_IPV6
|
||||
#define LWS_IPV6_ENABLED(context) (!(context->options & LWS_SERVER_OPTION_DISABLE_IPV6))
|
||||
#else
|
||||
#define LWS_IPV6_ENABLED(context) (0)
|
||||
#endif
|
||||
|
||||
enum uri_path_states {
|
||||
URIPS_IDLE,
|
||||
URIPS_SEEN_SLASH,
|
||||
URIPS_SEEN_SLASH_DOT,
|
||||
URIPS_SEEN_SLASH_DOT_DOT,
|
||||
URIPS_ARGUMENTS,
|
||||
};
|
||||
|
||||
enum uri_esc_states {
|
||||
URIES_IDLE,
|
||||
URIES_SEEN_PERCENT,
|
||||
URIES_SEEN_PERCENT_H1,
|
||||
};
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
struct lws_fragments {
|
||||
unsigned short offset;
|
||||
unsigned short len;
|
||||
unsigned char next_frag_index;
|
||||
};
|
||||
|
||||
struct allocated_headers {
|
||||
unsigned short next_frag_index;
|
||||
unsigned short pos;
|
||||
unsigned char frag_index[WSI_TOKEN_COUNT];
|
||||
struct lws_fragments frags[WSI_TOKEN_COUNT * 2];
|
||||
char data[LWS_MAX_HEADER_LEN];
|
||||
#ifndef LWS_NO_CLIENT
|
||||
char initial_handshake_hash_base64[30];
|
||||
unsigned short c_port;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct _lws_http_mode_related {
|
||||
struct allocated_headers *ah; /* mirroring _lws_header_related */
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
HANDLE fd;
|
||||
#else
|
||||
int fd;
|
||||
#endif
|
||||
unsigned long filepos;
|
||||
unsigned long filelen;
|
||||
|
||||
int content_length;
|
||||
int content_length_seen;
|
||||
int body_index;
|
||||
unsigned char *post_buffer;
|
||||
};
|
||||
|
||||
struct _lws_header_related {
|
||||
struct allocated_headers *ah;
|
||||
short lextable_pos;
|
||||
unsigned short current_token_limit;
|
||||
unsigned char parser_state; /* enum lws_token_indexes */
|
||||
enum uri_path_states ups;
|
||||
enum uri_esc_states ues;
|
||||
char esc_stash;
|
||||
};
|
||||
|
||||
struct _lws_websocket_related {
|
||||
char *rx_user_buffer;
|
||||
int rx_user_buffer_head;
|
||||
unsigned char frame_masking_nonce_04[4];
|
||||
unsigned char frame_mask_index;
|
||||
size_t rx_packet_length;
|
||||
unsigned char opcode;
|
||||
unsigned int final:1;
|
||||
unsigned char rsv;
|
||||
unsigned int frame_is_binary:1;
|
||||
unsigned int all_zero_nonce:1;
|
||||
short close_reason; /* enum lws_close_status */
|
||||
unsigned char *rxflow_buffer;
|
||||
int rxflow_len;
|
||||
int rxflow_pos;
|
||||
unsigned int rxflow_change_to:2;
|
||||
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 */
|
||||
};
|
||||
|
||||
struct libwebsocket {
|
||||
|
||||
/* lifetime members */
|
||||
|
||||
#ifdef LWS_USE_LIBEV
|
||||
struct lws_io_watcher w_read;
|
||||
struct lws_io_watcher w_write;
|
||||
#endif /* LWS_USE_LIBEV */
|
||||
const struct libwebsocket_protocols *protocol;
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
struct libwebsocket_extension *
|
||||
active_extensions[LWS_MAX_EXTENSIONS_ACTIVE];
|
||||
void *active_extensions_user[LWS_MAX_EXTENSIONS_ACTIVE];
|
||||
unsigned char count_active_extensions;
|
||||
unsigned int extension_data_pending:1;
|
||||
#endif
|
||||
unsigned char ietf_spec_revision;
|
||||
|
||||
char mode; /* enum connection_mode */
|
||||
char state; /* enum lws_connection_states */
|
||||
char lws_rx_parse_state; /* enum lws_rx_parse_state */
|
||||
char rx_frame_type; /* enum libwebsocket_write_protocol */
|
||||
|
||||
unsigned int hdr_parsing_completed:1;
|
||||
unsigned int user_space_externally_allocated:1;
|
||||
|
||||
char pending_timeout; /* enum pending_timeout */
|
||||
time_t pending_timeout_limit;
|
||||
|
||||
int sock;
|
||||
int position_in_fds_table;
|
||||
#ifdef LWS_LATENCY
|
||||
unsigned long action_start;
|
||||
unsigned long latency_start;
|
||||
#endif
|
||||
|
||||
/* truncated send handling */
|
||||
unsigned char *truncated_send_malloc; /* non-NULL means buffering in progress */
|
||||
unsigned int truncated_send_allocation; /* size of malloc */
|
||||
unsigned int truncated_send_offset; /* where we are in terms of spilling */
|
||||
unsigned int truncated_send_len; /* how much is buffered */
|
||||
|
||||
void *user_space;
|
||||
|
||||
/* members with mutually exclusive lifetimes are unionized */
|
||||
|
||||
union u {
|
||||
struct _lws_http_mode_related http;
|
||||
struct _lws_header_related hdr;
|
||||
struct _lws_websocket_related ws;
|
||||
} u;
|
||||
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
SSL *ssl;
|
||||
BIO *client_bio;
|
||||
unsigned int use_ssl:2;
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
BOOL sock_send_blocking;
|
||||
#endif
|
||||
};
|
||||
|
||||
LWS_EXTERN int log_level;
|
||||
|
||||
LWS_EXTERN void
|
||||
libwebsocket_close_and_free_session(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, enum lws_close_status);
|
||||
|
||||
LWS_EXTERN int
|
||||
remove_wsi_socket_from_fds(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi);
|
||||
|
||||
#ifndef LWS_LATENCY
|
||||
static inline void lws_latency(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, const char *action,
|
||||
int ret, int completion) { while (0); }
|
||||
static inline void lws_latency_pre(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi) { while (0); }
|
||||
#else
|
||||
#define lws_latency_pre(_context, _wsi) lws_latency(_context, _wsi, NULL, 0, 0)
|
||||
extern void
|
||||
lws_latency(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, const char *action,
|
||||
int ret, int completion);
|
||||
#endif
|
||||
|
||||
LWS_EXTERN int
|
||||
libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c);
|
||||
|
||||
LWS_EXTERN int
|
||||
libwebsocket_parse(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, unsigned char c);
|
||||
|
||||
LWS_EXTERN int
|
||||
lws_b64_selftest(void);
|
||||
|
||||
LWS_EXTERN struct libwebsocket *
|
||||
wsi_from_fd(struct libwebsocket_context *context, int fd);
|
||||
|
||||
LWS_EXTERN int
|
||||
insert_wsi_socket_into_fds(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi);
|
||||
|
||||
LWS_EXTERN int
|
||||
lws_issue_raw(struct libwebsocket *wsi, unsigned char *buf, size_t len);
|
||||
|
||||
|
||||
LWS_EXTERN int
|
||||
libwebsocket_service_timeout_check(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, unsigned int sec);
|
||||
|
||||
LWS_EXTERN struct libwebsocket *
|
||||
libwebsocket_client_connect_2(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi);
|
||||
|
||||
LWS_EXTERN struct libwebsocket *
|
||||
libwebsocket_create_new_server_wsi(struct libwebsocket_context *context);
|
||||
|
||||
LWS_EXTERN char *
|
||||
libwebsockets_generate_client_handshake(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, char *pkt);
|
||||
|
||||
LWS_EXTERN int
|
||||
lws_handle_POLLOUT_event(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, struct libwebsocket_pollfd *pollfd);
|
||||
/*
|
||||
* EXTENSIONS
|
||||
*/
|
||||
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
LWS_VISIBLE void
|
||||
lws_context_init_extensions(struct lws_context_creation_info *info,
|
||||
struct libwebsocket_context *context);
|
||||
LWS_EXTERN int
|
||||
lws_any_extension_handled(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_extension_callback_reasons r,
|
||||
void *v, size_t len);
|
||||
|
||||
LWS_EXTERN int
|
||||
lws_ext_callback_for_each_active(struct libwebsocket *wsi, int reason,
|
||||
void *buf, int len);
|
||||
LWS_EXTERN int
|
||||
lws_ext_callback_for_each_extension_type(
|
||||
struct libwebsocket_context *context, struct libwebsocket *wsi,
|
||||
int reason, void *arg, int len);
|
||||
#else
|
||||
#define lws_any_extension_handled(_a, _b, _c, _d, _e) (0)
|
||||
#define lws_ext_callback_for_each_active(_a, _b, _c, _d) (0)
|
||||
#define lws_ext_callback_for_each_extension_type(_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_client_interpret_server_handshake(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi);
|
||||
|
||||
LWS_EXTERN int
|
||||
libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c);
|
||||
|
||||
LWS_EXTERN int
|
||||
lws_issue_raw_ext_access(struct libwebsocket *wsi,
|
||||
unsigned char *buf, size_t len);
|
||||
|
||||
LWS_EXTERN int
|
||||
_libwebsocket_rx_flow_control(struct libwebsocket *wsi);
|
||||
|
||||
LWS_EXTERN int
|
||||
user_callback_handle_rxflow(callback_function,
|
||||
struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_callback_reasons reason, void *user,
|
||||
void *in, size_t len);
|
||||
|
||||
LWS_EXTERN int
|
||||
lws_plat_set_socket_options(struct libwebsocket_context *context, int fd);
|
||||
|
||||
LWS_EXTERN int
|
||||
lws_allocate_header_table(struct libwebsocket *wsi);
|
||||
|
||||
LWS_EXTERN char *
|
||||
lws_hdr_simple_ptr(struct libwebsocket *wsi, enum lws_token_indexes h);
|
||||
|
||||
LWS_EXTERN int
|
||||
lws_hdr_simple_create(struct libwebsocket *wsi,
|
||||
enum lws_token_indexes h, const char *s);
|
||||
|
||||
LWS_EXTERN int
|
||||
libwebsocket_ensure_user_space(struct libwebsocket *wsi);
|
||||
|
||||
LWS_EXTERN int
|
||||
lws_change_pollfd(struct libwebsocket *wsi, int _and, int _or);
|
||||
|
||||
#ifndef LWS_NO_SERVER
|
||||
int lws_context_init_server(struct lws_context_creation_info *info,
|
||||
struct libwebsocket_context *context);
|
||||
LWS_EXTERN int handshake_0405(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi);
|
||||
LWS_EXTERN int
|
||||
libwebsocket_interpret_incoming_packet(struct libwebsocket *wsi,
|
||||
unsigned char *buf, size_t len);
|
||||
LWS_EXTERN void
|
||||
lws_server_get_canonical_hostname(struct libwebsocket_context *context,
|
||||
struct lws_context_creation_info *info);
|
||||
#else
|
||||
#define lws_context_init_server(_a, _b) (0)
|
||||
#define libwebsocket_interpret_incoming_packet(_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 interface_to_sa(struct libwebsocket_context *context,
|
||||
const char *ifname, struct sockaddr_in *addr, size_t addrlen);
|
||||
|
||||
LWS_EXTERN void lwsl_emit_stderr(int level, const char *line);
|
||||
|
||||
#ifdef _WIN32
|
||||
LWS_EXTERN HANDLE lws_plat_open_file(const char* filename, unsigned long* filelen);
|
||||
#else
|
||||
LWS_EXTERN int lws_plat_open_file(const char* filename, unsigned long* filelen);
|
||||
#endif
|
||||
|
||||
enum lws_ssl_capable_status {
|
||||
LWS_SSL_CAPABLE_ERROR = -1,
|
||||
LWS_SSL_CAPABLE_MORE_SERVICE = -2,
|
||||
};
|
||||
|
||||
#ifndef LWS_OPENSSL_SUPPORT
|
||||
#define LWS_SSL_ENABLED(context) (0)
|
||||
unsigned char *
|
||||
SHA1(const unsigned char *d, size_t n, unsigned char *md);
|
||||
#define lws_context_init_server_ssl(_a, _b) (0)
|
||||
#define lws_ssl_destroy(_a)
|
||||
#define lws_context_init_http2_ssl(_a)
|
||||
#define lws_ssl_pending(_a) (0)
|
||||
#define lws_ssl_capable_read lws_ssl_capable_read_no_ssl
|
||||
#define lws_ssl_capable_write lws_ssl_capable_write_no_ssl
|
||||
#define lws_server_socket_service_ssl(_a, _b, _c, _d, _e) (0)
|
||||
#define lws_ssl_close(_a) (0)
|
||||
#define lws_ssl_context_destroy(_a)
|
||||
#else
|
||||
#define LWS_SSL_ENABLED(context) (context->use_ssl)
|
||||
LWS_EXTERN int lws_ssl_pending(struct libwebsocket *wsi);
|
||||
LWS_EXTERN int openssl_websocket_private_data_index;
|
||||
LWS_EXTERN int
|
||||
lws_ssl_capable_read(struct libwebsocket *wsi, unsigned char *buf, int len);
|
||||
|
||||
LWS_EXTERN int
|
||||
lws_ssl_capable_write(struct libwebsocket *wsi, unsigned char *buf, int len);
|
||||
LWS_EXTERN int
|
||||
lws_server_socket_service_ssl(struct libwebsocket_context *context,
|
||||
struct libwebsocket **wsi, struct libwebsocket *new_wsi,
|
||||
int accept_fd, struct libwebsocket_pollfd *pollfd);
|
||||
LWS_EXTERN int
|
||||
lws_ssl_close(struct libwebsocket *wsi);
|
||||
LWS_EXTERN void
|
||||
lws_ssl_context_destroy(struct libwebsocket_context *context);
|
||||
#ifndef LWS_NO_SERVER
|
||||
LWS_EXTERN int
|
||||
lws_context_init_server_ssl(struct lws_context_creation_info *info,
|
||||
struct libwebsocket_context *context);
|
||||
#else
|
||||
#define lws_context_init_server_ssl(_a, _b) (0)
|
||||
#endif
|
||||
LWS_EXTERN void
|
||||
lws_ssl_destroy(struct libwebsocket_context *context);
|
||||
|
||||
/* HTTP2-related */
|
||||
|
||||
#ifdef LWS_USE_HTTP2
|
||||
LWS_EXTERN void
|
||||
lws_context_init_http2_ssl(struct libwebsocket_context *context);
|
||||
#else
|
||||
#define lws_context_init_http2_ssl(_a)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
LWS_EXTERN int
|
||||
lws_ssl_capable_read_no_ssl(struct libwebsocket *wsi, unsigned char *buf, int len);
|
||||
|
||||
LWS_EXTERN int
|
||||
lws_ssl_capable_write_no_ssl(struct libwebsocket *wsi, unsigned char *buf, int len);
|
||||
|
||||
#ifndef LWS_NO_CLIENT
|
||||
LWS_EXTERN int lws_client_socket_service(
|
||||
struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, struct libwebsocket_pollfd *pollfd);
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
LWS_EXTERN int lws_context_init_client_ssl(struct lws_context_creation_info *info,
|
||||
struct libwebsocket_context *context);
|
||||
#else
|
||||
#define lws_context_init_client_ssl(_a, _b) (0)
|
||||
#endif
|
||||
LWS_EXTERN int lws_handshake_client(struct libwebsocket *wsi, unsigned char **buf, size_t len);
|
||||
LWS_EXTERN void
|
||||
libwebsockets_decode_ssl_error(void);
|
||||
#else
|
||||
#define lws_context_init_client_ssl(_a, _b) (0)
|
||||
#define lws_handshake_client(_a, _b, _c) (0)
|
||||
#endif
|
||||
#ifndef LWS_NO_SERVER
|
||||
LWS_EXTERN int lws_server_socket_service(
|
||||
struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, struct libwebsocket_pollfd *pollfd);
|
||||
LWS_EXTERN int _libwebsocket_rx_flow_control(struct libwebsocket *wsi);
|
||||
LWS_EXTERN int lws_handshake_server(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, unsigned char **buf, size_t len);
|
||||
#else
|
||||
#define lws_server_socket_service(_a, _b, _c) (0)
|
||||
#define _libwebsocket_rx_flow_control(_a) (0)
|
||||
#define lws_handshake_server(_a, _b, _c, _d) (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* lws_plat_
|
||||
*/
|
||||
LWS_EXTERN void
|
||||
lws_plat_delete_socket_from_fds(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, int m);
|
||||
LWS_EXTERN void
|
||||
lws_plat_insert_socket_into_fds(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi);
|
||||
LWS_EXTERN void
|
||||
lws_plat_service_periodic(struct libwebsocket_context *context);
|
||||
|
||||
LWS_EXTERN int
|
||||
lws_plat_change_pollfd(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, struct libwebsocket_pollfd *pfd);
|
||||
LWS_EXTERN int
|
||||
lws_plat_context_early_init(void);
|
||||
LWS_EXTERN void
|
||||
lws_plat_context_early_destroy(struct libwebsocket_context *context);
|
||||
LWS_EXTERN void
|
||||
lws_plat_context_late_destroy(struct libwebsocket_context *context);
|
||||
LWS_EXTERN int
|
||||
lws_poll_listen_fd(struct libwebsocket_pollfd *fd);
|
||||
LWS_EXTERN int
|
||||
lws_plat_service(struct libwebsocket_context *context, int timeout_ms);
|
||||
LWS_EXTERN int
|
||||
lws_plat_init_fd_tables(struct libwebsocket_context *context);
|
||||
LWS_EXTERN void
|
||||
lws_plat_drop_app_privileges(struct lws_context_creation_info *info);
|
||||
LWS_EXTERN unsigned long long
|
||||
time_in_microseconds(void);
|
||||
LWS_EXTERN const char *
|
||||
lws_plat_inet_ntop(int af, const void *src, char *dst, int cnt);
|
||||
280
dependencies/libwebsockets/lib/server-handshake.c
vendored
Normal file
280
dependencies/libwebsockets/lib/server-handshake.c
vendored
Normal file
@ -0,0 +1,280 @@
|
||||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010-2013 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 "private-libwebsockets.h"
|
||||
|
||||
#define LWS_CPYAPP(ptr, str) { strcpy(ptr, str); ptr += strlen(str); }
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
LWS_VISIBLE int
|
||||
lws_extension_server_handshake(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, char **p)
|
||||
{
|
||||
int n;
|
||||
char *c;
|
||||
char ext_name[128];
|
||||
struct libwebsocket_extension *ext;
|
||||
int ext_count = 0;
|
||||
int more = 1;
|
||||
|
||||
/*
|
||||
* 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 *)context->service_buffer,
|
||||
sizeof(context->service_buffer),
|
||||
WSI_TOKEN_EXTENSIONS) < 0)
|
||||
return 1;
|
||||
|
||||
c = (char *)context->service_buffer;
|
||||
lwsl_parser("WSI_TOKEN_EXTENSIONS = '%s'\n", c);
|
||||
wsi->count_active_extensions = 0;
|
||||
n = 0;
|
||||
while (more) {
|
||||
|
||||
if (*c && (*c != ',' && *c != ' ' && *c != '\t')) {
|
||||
ext_name[n] = *c++;
|
||||
if (n < sizeof(ext_name) - 1)
|
||||
n++;
|
||||
continue;
|
||||
}
|
||||
ext_name[n] = '\0';
|
||||
if (!*c)
|
||||
more = 0;
|
||||
else {
|
||||
c++;
|
||||
if (!n)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* check a client's extension against our support */
|
||||
|
||||
ext = wsi->protocol->owning_server->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 ask user
|
||||
* code if it's OK to apply it on this
|
||||
* particular connection + protocol
|
||||
*/
|
||||
|
||||
n = wsi->protocol->owning_server->
|
||||
protocols[0].callback(
|
||||
wsi->protocol->owning_server,
|
||||
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 (n) {
|
||||
ext++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* apply it */
|
||||
|
||||
if (ext_count)
|
||||
*(*p)++ = ',';
|
||||
else
|
||||
LWS_CPYAPP(*p,
|
||||
"\x0d\x0aSec-WebSocket-Extensions: ");
|
||||
*p += sprintf(*p, "%s", ext_name);
|
||||
ext_count++;
|
||||
|
||||
/* instantiate the extension on this conn */
|
||||
|
||||
wsi->active_extensions_user[
|
||||
wsi->count_active_extensions] =
|
||||
malloc(ext->per_session_data_size);
|
||||
if (wsi->active_extensions_user[
|
||||
wsi->count_active_extensions] == NULL) {
|
||||
lwsl_err("Out of mem\n");
|
||||
return 1;
|
||||
}
|
||||
memset(wsi->active_extensions_user[
|
||||
wsi->count_active_extensions], 0,
|
||||
ext->per_session_data_size);
|
||||
|
||||
wsi->active_extensions[
|
||||
wsi->count_active_extensions] = ext;
|
||||
|
||||
/* allow him to construct his context */
|
||||
|
||||
ext->callback(wsi->protocol->owning_server,
|
||||
ext, wsi,
|
||||
LWS_EXT_CALLBACK_CONSTRUCT,
|
||||
wsi->active_extensions_user[
|
||||
wsi->count_active_extensions], NULL, 0);
|
||||
|
||||
wsi->count_active_extensions++;
|
||||
lwsl_parser("count_active_extensions <- %d\n",
|
||||
wsi->count_active_extensions);
|
||||
|
||||
ext++;
|
||||
}
|
||||
|
||||
n = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
int
|
||||
handshake_0405(struct libwebsocket_context *context, struct libwebsocket *wsi)
|
||||
{
|
||||
unsigned char hash[20];
|
||||
int n;
|
||||
char *response;
|
||||
char *p;
|
||||
int accept_len;
|
||||
|
||||
if (!lws_hdr_total_length(wsi, WSI_TOKEN_HOST) ||
|
||||
!lws_hdr_total_length(wsi, WSI_TOKEN_KEY)) {
|
||||
lwsl_parser("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 *)context->service_buffer,
|
||||
"%s258EAFA5-E914-47DA-95CA-C5AB0DC85B11",
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_KEY));
|
||||
|
||||
SHA1(context->service_buffer, n, hash);
|
||||
|
||||
accept_len = lws_b64_encode_string((char *)hash, 20,
|
||||
(char *)context->service_buffer,
|
||||
sizeof(context->service_buffer));
|
||||
if (accept_len < 0) {
|
||||
lwsl_warn("Base64 encoded hash too long\n");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* allocate the per-connection user memory (if any) */
|
||||
if (libwebsocket_ensure_user_space(wsi))
|
||||
goto bail;
|
||||
|
||||
/* create the response packet */
|
||||
|
||||
/* make a buffer big enough for everything */
|
||||
|
||||
response = (char *)context->service_buffer + MAX_WEBSOCKET_04_KEY_LEN;
|
||||
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 *)context->service_buffer);
|
||||
p += accept_len;
|
||||
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL)) {
|
||||
LWS_CPYAPP(p, "\x0d\x0aSec-WebSocket-Protocol: ");
|
||||
n = lws_hdr_copy(wsi, p, 128, WSI_TOKEN_PROTOCOL);
|
||||
if (n < 0)
|
||||
goto bail;
|
||||
p += n;
|
||||
}
|
||||
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
/*
|
||||
* Figure out which extensions the client has that we want to
|
||||
* enable on this connection, and give him back the list
|
||||
*/
|
||||
if (lws_extension_server_handshake(context, wsi, &p))
|
||||
goto bail;
|
||||
#endif
|
||||
/* end of response packet */
|
||||
|
||||
LWS_CPYAPP(p, "\x0d\x0a\x0d\x0a");
|
||||
|
||||
if (!lws_any_extension_handled(context, wsi,
|
||||
LWS_EXT_CALLBACK_HANDSHAKE_REPLY_TX,
|
||||
response, p - response)) {
|
||||
|
||||
/* okay send the handshake response accepting the connection */
|
||||
|
||||
lwsl_parser("issuing resp pkt %d len\n", (int)(p - response));
|
||||
#ifdef DEBUG
|
||||
fwrite(response, 1, p - response, stderr);
|
||||
#endif
|
||||
n = libwebsocket_write(wsi, (unsigned char *)response,
|
||||
p - response, LWS_WRITE_HTTP);
|
||||
if (n != (p - response)) {
|
||||
lwsl_debug("handshake_0405: ERROR writing to socket\n");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* alright clean up and set ourselves into established state */
|
||||
|
||||
wsi->state = WSI_STATE_ESTABLISHED;
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_NEW;
|
||||
|
||||
/* notify user code that we're ready to roll */
|
||||
|
||||
if (wsi->protocol->callback)
|
||||
wsi->protocol->callback(wsi->protocol->owning_server,
|
||||
wsi, LWS_CALLBACK_ESTABLISHED,
|
||||
wsi->user_space, NULL, 0);
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
bail:
|
||||
/* free up his parsing allocations */
|
||||
|
||||
if (wsi->u.hdr.ah)
|
||||
free(wsi->u.hdr.ah);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
876
dependencies/libwebsockets/lib/server.c
vendored
Normal file
876
dependencies/libwebsockets/lib/server.c
vendored
Normal file
@ -0,0 +1,876 @@
|
||||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010-2013 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 "private-libwebsockets.h"
|
||||
|
||||
int lws_context_init_server(struct lws_context_creation_info *info,
|
||||
struct libwebsocket_context *context)
|
||||
{
|
||||
int n;
|
||||
int sockfd;
|
||||
struct sockaddr_in sin;
|
||||
socklen_t len = sizeof(sin);
|
||||
int opt = 1;
|
||||
struct libwebsocket *wsi;
|
||||
#ifdef LWS_USE_IPV6
|
||||
struct sockaddr_in6 serv_addr6;
|
||||
#endif
|
||||
struct sockaddr_in serv_addr4;
|
||||
struct sockaddr *v;
|
||||
|
||||
/* set up our external listening socket we serve on */
|
||||
|
||||
if (info->port == CONTEXT_PORT_NO_LISTEN)
|
||||
return 0;
|
||||
|
||||
#ifdef LWS_USE_IPV6
|
||||
if (LWS_IPV6_ENABLED(context))
|
||||
sockfd = socket(AF_INET6, SOCK_STREAM, 0);
|
||||
else
|
||||
#endif
|
||||
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
if (sockfd < 0) {
|
||||
lwsl_err("ERROR opening socket\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* allow us to restart even if old sockets in TIME_WAIT
|
||||
*/
|
||||
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
|
||||
(const void *)&opt, sizeof(opt));
|
||||
|
||||
lws_plat_set_socket_options(context, sockfd);
|
||||
|
||||
#ifdef LWS_USE_IPV6
|
||||
if (LWS_IPV6_ENABLED(context)) {
|
||||
v = (struct sockaddr *)&serv_addr6;
|
||||
n = sizeof(struct sockaddr_in6);
|
||||
bzero((char *) &serv_addr6, sizeof(serv_addr6));
|
||||
serv_addr6.sin6_addr = in6addr_any;
|
||||
serv_addr6.sin6_family = AF_INET6;
|
||||
serv_addr6.sin6_port = htons(info->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 (info->iface) {
|
||||
if (interface_to_sa(context, info->iface,
|
||||
(struct sockaddr_in *)v, n) < 0) {
|
||||
lwsl_err("Unable to find interface %s\n",
|
||||
info->iface);
|
||||
compatible_close(sockfd);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
serv_addr4.sin_port = htons(info->port);
|
||||
} /* ipv4 */
|
||||
|
||||
n = bind(sockfd, v, n);
|
||||
if (n < 0) {
|
||||
lwsl_err("ERROR on binding to port %d (%d %d)\n",
|
||||
info->port, n, LWS_ERRNO);
|
||||
compatible_close(sockfd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (getsockname(sockfd, (struct sockaddr *)&sin, &len) == -1)
|
||||
lwsl_warn("getsockname: %s\n", strerror(LWS_ERRNO));
|
||||
else
|
||||
info->port = ntohs(sin.sin_port);
|
||||
|
||||
context->listen_port = info->port;
|
||||
|
||||
wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
|
||||
if (wsi == NULL) {
|
||||
lwsl_err("Out of mem\n");
|
||||
compatible_close(sockfd);
|
||||
return 1;
|
||||
}
|
||||
memset(wsi, 0, sizeof(struct libwebsocket));
|
||||
wsi->sock = sockfd;
|
||||
wsi->mode = LWS_CONNMODE_SERVER_LISTENER;
|
||||
|
||||
insert_wsi_socket_into_fds(context, wsi);
|
||||
|
||||
context->listen_service_modulo = LWS_LISTEN_SERVICE_MODULO;
|
||||
context->listen_service_count = 0;
|
||||
context->listen_service_fd = sockfd;
|
||||
|
||||
listen(sockfd, LWS_SOMAXCONN);
|
||||
lwsl_notice(" Listening on port %d\n", info->port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
_libwebsocket_rx_flow_control(struct libwebsocket *wsi)
|
||||
{
|
||||
struct libwebsocket_context *context = wsi->protocol->owning_server;
|
||||
|
||||
/* there is no pending change */
|
||||
if (!(wsi->u.ws.rxflow_change_to & LWS_RXFLOW_PENDING_CHANGE))
|
||||
return 0;
|
||||
|
||||
/* stuff is still buffered, not ready to really accept new input */
|
||||
if (wsi->u.ws.rxflow_buffer) {
|
||||
/* get ourselves called back to deal with stashed buffer */
|
||||
libwebsocket_callback_on_writable(context, wsi);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* pending is cleared, we can change rxflow state */
|
||||
|
||||
wsi->u.ws.rxflow_change_to &= ~LWS_RXFLOW_PENDING_CHANGE;
|
||||
|
||||
lwsl_info("rxflow: wsi %p change_to %d\n", wsi,
|
||||
wsi->u.ws.rxflow_change_to & LWS_RXFLOW_ALLOW);
|
||||
|
||||
/* adjust the pollfd for this wsi */
|
||||
|
||||
if (wsi->u.ws.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;
|
||||
}
|
||||
|
||||
|
||||
int lws_handshake_server(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, unsigned char **buf, size_t len)
|
||||
{
|
||||
struct allocated_headers *ah;
|
||||
char *uri_ptr = NULL;
|
||||
int uri_len = 0;
|
||||
char content_length_str[32];
|
||||
int n;
|
||||
|
||||
/* LWS_CONNMODE_WS_SERVING */
|
||||
|
||||
while (len--) {
|
||||
if (libwebsocket_parse(context, wsi, *(*buf)++)) {
|
||||
lwsl_info("libwebsocket_parse failed\n");
|
||||
goto bail_nuke_ah;
|
||||
}
|
||||
|
||||
if (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE)
|
||||
continue;
|
||||
|
||||
lwsl_parser("libwebsocket_parse sees parsing complete\n");
|
||||
|
||||
wsi->mode = LWS_CONNMODE_PRE_WS_SERVING_ACCEPT;
|
||||
libwebsocket_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) ||
|
||||
!lws_hdr_total_length(wsi, WSI_TOKEN_CONNECTION)) {
|
||||
|
||||
/* it's not websocket.... shall we accept it as http? */
|
||||
|
||||
if (!lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI) &&
|
||||
!lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI) &&
|
||||
!lws_hdr_total_length(wsi, WSI_TOKEN_OPTIONS_URI)) {
|
||||
lwsl_warn("Missing URI in HTTP request\n");
|
||||
goto bail_nuke_ah;
|
||||
}
|
||||
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI) &&
|
||||
lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI)) {
|
||||
lwsl_warn("GET and POST methods?\n");
|
||||
goto bail_nuke_ah;
|
||||
}
|
||||
|
||||
if (libwebsocket_ensure_user_space(wsi))
|
||||
goto bail_nuke_ah;
|
||||
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI)) {
|
||||
uri_ptr = lws_hdr_simple_ptr(wsi, WSI_TOKEN_GET_URI);
|
||||
uri_len = lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI);
|
||||
lwsl_info("HTTP GET request for '%s'\n",
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_GET_URI));
|
||||
|
||||
}
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI)) {
|
||||
lwsl_info("HTTP POST request for '%s'\n",
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_POST_URI));
|
||||
uri_ptr = lws_hdr_simple_ptr(wsi, WSI_TOKEN_POST_URI);
|
||||
uri_len = lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI);
|
||||
}
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_OPTIONS_URI)) {
|
||||
lwsl_info("HTTP OPTIONS request for '%s'\n",
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_OPTIONS_URI));
|
||||
uri_ptr = lws_hdr_simple_ptr(wsi, WSI_TOKEN_OPTIONS_URI);
|
||||
uri_len = lws_hdr_total_length(wsi, WSI_TOKEN_OPTIONS_URI);
|
||||
}
|
||||
|
||||
/*
|
||||
* Hm we still need the headers so the
|
||||
* callback can look at leaders like the URI, but we
|
||||
* need to transition to http union state.... hold a
|
||||
* copy of u.hdr.ah and deallocate afterwards
|
||||
*/
|
||||
ah = wsi->u.hdr.ah;
|
||||
|
||||
/* union transition */
|
||||
memset(&wsi->u, 0, sizeof(wsi->u));
|
||||
wsi->mode = LWS_CONNMODE_HTTP_SERVING_ACCEPTED;
|
||||
wsi->state = WSI_STATE_HTTP;
|
||||
wsi->u.http.fd = LWS_INVALID_FILE;
|
||||
|
||||
/* expose it at the same offset as u.hdr */
|
||||
wsi->u.http.ah = ah;
|
||||
|
||||
/* HTTP header had a content length? */
|
||||
|
||||
wsi->u.http.content_length = 0;
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI))
|
||||
wsi->u.http.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->u.http.content_length = atoi(content_length_str);
|
||||
}
|
||||
|
||||
if (wsi->u.http.content_length > 0) {
|
||||
wsi->u.http.body_index = 0;
|
||||
n = wsi->protocol->rx_buffer_size;
|
||||
if (!n)
|
||||
n = LWS_MAX_SOCKET_IO_BUF;
|
||||
wsi->u.http.post_buffer = malloc(n);
|
||||
if (!wsi->u.http.post_buffer) {
|
||||
lwsl_err("Unable to allocate post buffer\n");
|
||||
n = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
n = 0;
|
||||
if (wsi->protocol->callback)
|
||||
n = wsi->protocol->callback(context, wsi,
|
||||
LWS_CALLBACK_FILTER_HTTP_CONNECTION,
|
||||
wsi->user_space, uri_ptr, uri_len);
|
||||
|
||||
if (!n) {
|
||||
/*
|
||||
* if there is content supposed to be coming,
|
||||
* put a timeout on it having arrived
|
||||
*/
|
||||
libwebsocket_set_timeout(wsi,
|
||||
PENDING_TIMEOUT_HTTP_CONTENT,
|
||||
AWAITING_TIMEOUT);
|
||||
|
||||
if (wsi->protocol->callback)
|
||||
n = wsi->protocol->callback(context, wsi,
|
||||
LWS_CALLBACK_HTTP,
|
||||
wsi->user_space, uri_ptr, uri_len);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
/* now drop the header info we kept a pointer to */
|
||||
if (ah)
|
||||
free(ah);
|
||||
/* not possible to continue to use past here */
|
||||
wsi->u.http.ah = NULL;
|
||||
|
||||
if (n) {
|
||||
lwsl_info("LWS_CALLBACK_HTTP closing\n");
|
||||
return 1; /* struct ah ptr already nuked */
|
||||
}
|
||||
|
||||
/*
|
||||
* (if callback didn't start sending a file)
|
||||
* deal with anything else as body, whether
|
||||
* there was a content-length or not
|
||||
*/
|
||||
|
||||
if (wsi->state != WSI_STATE_HTTP_ISSUING_FILE)
|
||||
wsi->state = WSI_STATE_HTTP_BODY;
|
||||
return 2; /* goto http_postbody; */
|
||||
}
|
||||
|
||||
if (!wsi->protocol)
|
||||
lwsl_err("NULL protocol at libwebsocket_read\n");
|
||||
|
||||
/*
|
||||
* It's websocket
|
||||
*
|
||||
* Make sure user side is happy about protocol
|
||||
*/
|
||||
|
||||
while (wsi->protocol->callback) {
|
||||
|
||||
if (!lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL)) {
|
||||
if (wsi->protocol->name == NULL)
|
||||
break;
|
||||
} else
|
||||
if (wsi->protocol->name && strcmp(
|
||||
lws_hdr_simple_ptr(wsi,
|
||||
WSI_TOKEN_PROTOCOL),
|
||||
wsi->protocol->name) == 0)
|
||||
break;
|
||||
|
||||
wsi->protocol++;
|
||||
}
|
||||
|
||||
/* we didn't find a protocol he wanted? */
|
||||
|
||||
if (wsi->protocol->callback == NULL) {
|
||||
if (lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL) ==
|
||||
NULL) {
|
||||
lwsl_info("no protocol -> prot 0 handler\n");
|
||||
wsi->protocol = &context->protocols[0];
|
||||
} else {
|
||||
lwsl_err("Req protocol %s not supported\n",
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL));
|
||||
goto bail_nuke_ah;
|
||||
}
|
||||
}
|
||||
|
||||
/* allocate wsi->user storage */
|
||||
if (libwebsocket_ensure_user_space(wsi))
|
||||
goto bail_nuke_ah;
|
||||
|
||||
/*
|
||||
* Give the user code a chance to study the request and
|
||||
* have the opportunity to deny it
|
||||
*/
|
||||
|
||||
if ((wsi->protocol->callback)(wsi->protocol->owning_server, 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");
|
||||
goto bail_nuke_ah;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Perform the handshake according to the protocol version the
|
||||
* client announced
|
||||
*/
|
||||
|
||||
switch (wsi->ietf_spec_revision) {
|
||||
case 13:
|
||||
lwsl_parser("lws_parse calling handshake_04\n");
|
||||
if (handshake_0405(context, wsi)) {
|
||||
lwsl_info("hs0405 has failed the connection\n");
|
||||
goto bail_nuke_ah;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
lwsl_warn("Unknown client spec version %d\n",
|
||||
wsi->ietf_spec_revision);
|
||||
goto bail_nuke_ah;
|
||||
}
|
||||
|
||||
/* drop the header info -- no bail_nuke_ah after this */
|
||||
|
||||
if (wsi->u.hdr.ah)
|
||||
free(wsi->u.hdr.ah);
|
||||
|
||||
wsi->mode = LWS_CONNMODE_WS_SERVING;
|
||||
|
||||
/* union transition */
|
||||
memset(&wsi->u, 0, sizeof(wsi->u));
|
||||
wsi->u.ws.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, use
|
||||
* a big default for compatibility
|
||||
*/
|
||||
|
||||
n = wsi->protocol->rx_buffer_size;
|
||||
if (!n)
|
||||
n = LWS_MAX_SOCKET_IO_BUF;
|
||||
n += LWS_SEND_BUFFER_PRE_PADDING + LWS_SEND_BUFFER_POST_PADDING;
|
||||
wsi->u.ws.rx_user_buffer = malloc(n);
|
||||
if (!wsi->u.ws.rx_user_buffer) {
|
||||
lwsl_err("Out of Mem allocating rx buffer %d\n", n);
|
||||
return 1;
|
||||
}
|
||||
lwsl_info("Allocating RX buffer %d\n", n);
|
||||
|
||||
if (setsockopt(wsi->sock, SOL_SOCKET, SO_SNDBUF, (const char *)&n, sizeof n)) {
|
||||
lwsl_warn("Failed to set SNDBUF to %d", n);
|
||||
return 1;
|
||||
}
|
||||
|
||||
lwsl_parser("accepted v%02d connection\n",
|
||||
wsi->ietf_spec_revision);
|
||||
} /* while all chars are handled */
|
||||
|
||||
return 0;
|
||||
|
||||
bail_nuke_ah:
|
||||
/* drop the header info */
|
||||
if (wsi->u.hdr.ah)
|
||||
free(wsi->u.hdr.ah);
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct libwebsocket *
|
||||
libwebsocket_create_new_server_wsi(struct libwebsocket_context *context)
|
||||
{
|
||||
struct libwebsocket *new_wsi;
|
||||
|
||||
new_wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
|
||||
if (new_wsi == NULL) {
|
||||
lwsl_err("Out of memory for new connection\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(new_wsi, 0, sizeof(struct libwebsocket));
|
||||
new_wsi->pending_timeout = NO_PENDING_TIMEOUT;
|
||||
|
||||
/* intialize the instance struct */
|
||||
|
||||
new_wsi->state = WSI_STATE_HTTP;
|
||||
new_wsi->mode = LWS_CONNMODE_HTTP_SERVING;
|
||||
new_wsi->hdr_parsing_completed = 0;
|
||||
|
||||
if (lws_allocate_header_table(new_wsi)) {
|
||||
free(new_wsi);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* these can only be set once the protocol is known
|
||||
* we set an unestablished connection's protocol pointer
|
||||
* to the start of the supported list, so it can look
|
||||
* for matching ones during the handshake
|
||||
*/
|
||||
new_wsi->protocol = context->protocols;
|
||||
new_wsi->user_space = NULL;
|
||||
new_wsi->ietf_spec_revision = 0;
|
||||
|
||||
/*
|
||||
* outermost create notification for wsi
|
||||
* no user_space because no protocol selection
|
||||
*/
|
||||
context->protocols[0].callback(context, new_wsi,
|
||||
LWS_CALLBACK_WSI_CREATE, NULL, NULL, 0);
|
||||
|
||||
return new_wsi;
|
||||
}
|
||||
|
||||
int lws_server_socket_service(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, struct libwebsocket_pollfd *pollfd)
|
||||
{
|
||||
struct libwebsocket *new_wsi = NULL;
|
||||
int accept_fd = 0;
|
||||
socklen_t clilen;
|
||||
struct sockaddr_in cli_addr;
|
||||
int n;
|
||||
int len;
|
||||
|
||||
switch (wsi->mode) {
|
||||
|
||||
case LWS_CONNMODE_HTTP_SERVING:
|
||||
case LWS_CONNMODE_HTTP_SERVING_ACCEPTED:
|
||||
|
||||
/* handle http headers coming in */
|
||||
|
||||
/* pending truncated sends have uber priority */
|
||||
|
||||
if (wsi->truncated_send_malloc) {
|
||||
if (pollfd->revents & LWS_POLLOUT)
|
||||
if (lws_issue_raw(wsi, wsi->truncated_send_malloc +
|
||||
wsi->truncated_send_offset,
|
||||
wsi->truncated_send_len) < 0) {
|
||||
lwsl_info("closing from socket service\n");
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* we can't afford to allow input processing send
|
||||
* something new, so spin around he event loop until
|
||||
* he doesn't have any partials
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
/* any incoming data ready? */
|
||||
|
||||
if (pollfd->revents & LWS_POLLIN) {
|
||||
len = lws_ssl_capable_read(wsi,
|
||||
context->service_buffer,
|
||||
sizeof(context->service_buffer));
|
||||
switch (len) {
|
||||
case 0:
|
||||
lwsl_info("lws_server_skt_srv: read 0 len\n");
|
||||
/* lwsl_info(" state=%d\n", wsi->state); */
|
||||
if (!wsi->hdr_parsing_completed)
|
||||
free(wsi->u.hdr.ah);
|
||||
/* fallthru */
|
||||
case LWS_SSL_CAPABLE_ERROR:
|
||||
libwebsocket_close_and_free_session(
|
||||
context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
return 0;
|
||||
case LWS_SSL_CAPABLE_MORE_SERVICE:
|
||||
break;
|
||||
}
|
||||
|
||||
/* just ignore incoming if waiting for close */
|
||||
if (wsi->state != WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE) {
|
||||
|
||||
/* hm this may want to send (via HTTP callback for example) */
|
||||
|
||||
n = libwebsocket_read(context, wsi,
|
||||
context->service_buffer, len);
|
||||
if (n < 0)
|
||||
/* we closed wsi */
|
||||
return 0;
|
||||
|
||||
/* hum he may have used up the writability above */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* this handles POLLOUT for http serving fragments */
|
||||
|
||||
if (!(pollfd->revents & LWS_POLLOUT))
|
||||
break;
|
||||
|
||||
/* one shot */
|
||||
if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
|
||||
goto fail;
|
||||
|
||||
lws_libev_io(context, wsi, LWS_EV_STOP | LWS_EV_WRITE);
|
||||
|
||||
if (wsi->state != WSI_STATE_HTTP_ISSUING_FILE) {
|
||||
n = user_callback_handle_rxflow(
|
||||
wsi->protocol->callback,
|
||||
wsi->protocol->owning_server,
|
||||
wsi, LWS_CALLBACK_HTTP_WRITEABLE,
|
||||
wsi->user_space,
|
||||
NULL,
|
||||
0);
|
||||
if (n < 0)
|
||||
libwebsocket_close_and_free_session(
|
||||
context, wsi, LWS_CLOSE_STATUS_NOSTATUS);
|
||||
break;
|
||||
}
|
||||
|
||||
/* nonzero for completion or error */
|
||||
if (libwebsockets_serve_http_file_fragment(context, wsi))
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
break;
|
||||
|
||||
case LWS_CONNMODE_SERVER_LISTENER:
|
||||
|
||||
/* pollin means a client has connected to us then */
|
||||
|
||||
if (!(pollfd->revents & LWS_POLLIN))
|
||||
break;
|
||||
|
||||
/* listen socket got an unencrypted connection... */
|
||||
|
||||
clilen = sizeof(cli_addr);
|
||||
lws_latency_pre(context, wsi);
|
||||
accept_fd = accept(pollfd->fd, (struct sockaddr *)&cli_addr,
|
||||
&clilen);
|
||||
lws_latency(context, wsi,
|
||||
"unencrypted accept LWS_CONNMODE_SERVER_LISTENER",
|
||||
accept_fd, accept_fd >= 0);
|
||||
if (accept_fd < 0) {
|
||||
if (LWS_ERRNO == LWS_EAGAIN || LWS_ERRNO == LWS_EWOULDBLOCK) {
|
||||
lwsl_debug("accept asks to try again\n");
|
||||
break;
|
||||
}
|
||||
lwsl_warn("ERROR on accept: %s\n", strerror(LWS_ERRNO));
|
||||
break;
|
||||
}
|
||||
|
||||
lws_plat_set_socket_options(context, accept_fd);
|
||||
|
||||
/*
|
||||
* 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 ((context->protocols[0].callback)(context, wsi,
|
||||
LWS_CALLBACK_FILTER_NETWORK_CONNECTION,
|
||||
NULL, (void *)(long)accept_fd, 0)) {
|
||||
lwsl_debug("Callback denied network connection\n");
|
||||
compatible_close(accept_fd);
|
||||
break;
|
||||
}
|
||||
|
||||
new_wsi = libwebsocket_create_new_server_wsi(context);
|
||||
if (new_wsi == NULL) {
|
||||
compatible_close(accept_fd);
|
||||
break;
|
||||
}
|
||||
|
||||
new_wsi->sock = accept_fd;
|
||||
|
||||
/* the transport is accepted... give him time to negotiate */
|
||||
libwebsocket_set_timeout(new_wsi,
|
||||
PENDING_TIMEOUT_ESTABLISH_WITH_SERVER,
|
||||
AWAITING_TIMEOUT);
|
||||
|
||||
/*
|
||||
* 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 protocols[0]
|
||||
*/
|
||||
|
||||
(context->protocols[0].callback)(context, new_wsi,
|
||||
LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED, NULL, NULL, 0);
|
||||
|
||||
lws_libev_accept(context, new_wsi, accept_fd);
|
||||
|
||||
if (!LWS_SSL_ENABLED(context)) {
|
||||
lwsl_debug("accepted new conn port %u on fd=%d\n",
|
||||
ntohs(cli_addr.sin_port), accept_fd);
|
||||
|
||||
insert_wsi_socket_into_fds(context, new_wsi);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (lws_server_socket_service_ssl(context, &wsi, new_wsi, accept_fd, pollfd))
|
||||
goto fail;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static const char *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"
|
||||
};
|
||||
|
||||
static const char *err500[] = {
|
||||
"Internal Server Error",
|
||||
"Not Implemented",
|
||||
"Bad Gateway",
|
||||
"Service Unavailable",
|
||||
"Gateway Timeout",
|
||||
"HTTP Version Not Supported"
|
||||
};
|
||||
|
||||
/**
|
||||
* libwebsockets_return_http_status() - Return simple http status
|
||||
* @context: libwebsockets context
|
||||
* @wsi: Websocket instance (available from user callback)
|
||||
* @code: Status index, eg, 404
|
||||
* @html_body: User-readable HTML description, or NULL
|
||||
*
|
||||
* Helper to report HTTP errors back to the client cleanly and
|
||||
* consistently
|
||||
*/
|
||||
LWS_VISIBLE int libwebsockets_return_http_status(
|
||||
struct libwebsocket_context *context, struct libwebsocket *wsi,
|
||||
unsigned int code, const char *html_body)
|
||||
{
|
||||
int n, m;
|
||||
const char *description = "";
|
||||
|
||||
if (!html_body)
|
||||
html_body = "";
|
||||
|
||||
if (code >= 400 && code < (400 + ARRAY_SIZE(err400)))
|
||||
description = err400[code - 400];
|
||||
if (code >= 500 && code < (500 + ARRAY_SIZE(err500)))
|
||||
description = err500[code - 500];
|
||||
|
||||
n = sprintf((char *)context->service_buffer,
|
||||
"HTTP/1.0 %u %s\x0d\x0a"
|
||||
"Server: libwebsockets\x0d\x0a"
|
||||
"Content-Type: text/html\x0d\x0a\x0d\x0a"
|
||||
"<h1>%u %s</h1>%s",
|
||||
code, description, code, description, html_body);
|
||||
|
||||
lwsl_info((const char *)context->service_buffer);
|
||||
|
||||
m = libwebsocket_write(wsi, context->service_buffer, n, LWS_WRITE_HTTP);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* libwebsockets_serve_http_file() - Send a file back to the client using http
|
||||
* @context: libwebsockets context
|
||||
* @wsi: Websocket instance (available from user callback)
|
||||
* @file: The file to issue over http
|
||||
* @content_type: The http content type, eg, text/html
|
||||
* @other_headers: NULL or pointer to \0-terminated other header string
|
||||
*
|
||||
* 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 the wsi should be closed.
|
||||
* ==0 indicates the file transfer is started and needs more service later,
|
||||
* the wsi should be left alone.
|
||||
*/
|
||||
|
||||
LWS_VISIBLE int libwebsockets_serve_http_file(
|
||||
struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, const char *file,
|
||||
const char *content_type, const char *other_headers)
|
||||
{
|
||||
unsigned char *p = context->service_buffer;
|
||||
int ret = 0;
|
||||
int n;
|
||||
|
||||
wsi->u.http.fd = lws_plat_open_file(file, &wsi->u.http.filelen);
|
||||
|
||||
if (wsi->u.http.fd == LWS_INVALID_FILE) {
|
||||
lwsl_err("Unable to open '%s'\n", file);
|
||||
libwebsockets_return_http_status(context, wsi,
|
||||
HTTP_STATUS_NOT_FOUND, NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
p += sprintf((char *)p,
|
||||
"HTTP/1.0 200 OK\x0d\x0aServer: libwebsockets\x0d\x0a""Content-Type: %s\x0d\x0a",
|
||||
content_type);
|
||||
if (other_headers) {
|
||||
n = strlen(other_headers);
|
||||
memcpy(p, other_headers, n);
|
||||
p += n;
|
||||
}
|
||||
p += sprintf((char *)p,
|
||||
"Content-Length: %lu\x0d\x0a\x0d\x0a", wsi->u.http.filelen);
|
||||
|
||||
ret = libwebsocket_write(wsi, context->service_buffer,
|
||||
p - context->service_buffer, LWS_WRITE_HTTP);
|
||||
if (ret != (p - context->service_buffer)) {
|
||||
lwsl_err("_write returned %d from %d\n", ret, (p - context->service_buffer));
|
||||
return -1;
|
||||
}
|
||||
|
||||
wsi->u.http.filepos = 0;
|
||||
wsi->state = WSI_STATE_HTTP_ISSUING_FILE;
|
||||
|
||||
return libwebsockets_serve_http_file_fragment(context, wsi);
|
||||
}
|
||||
|
||||
|
||||
int libwebsocket_interpret_incoming_packet(struct libwebsocket *wsi,
|
||||
unsigned char *buf, size_t len)
|
||||
{
|
||||
size_t n = 0;
|
||||
int m;
|
||||
|
||||
#if 0
|
||||
lwsl_parser("received %d byte packet\n", (int)len);
|
||||
lwsl_hexdump(buf, len);
|
||||
#endif
|
||||
|
||||
/* let the rx protocol state machine have as much as it needs */
|
||||
|
||||
while (n < len) {
|
||||
/*
|
||||
* we were accepting input but now we stopped doing so
|
||||
*/
|
||||
if (!(wsi->u.ws.rxflow_change_to & LWS_RXFLOW_ALLOW)) {
|
||||
/* his RX is flowcontrolled, don't send remaining now */
|
||||
if (!wsi->u.ws.rxflow_buffer) {
|
||||
/* a new rxflow, buffer it and warn caller */
|
||||
lwsl_info("new rxflow input buffer len %d\n",
|
||||
len - n);
|
||||
wsi->u.ws.rxflow_buffer =
|
||||
(unsigned char *)malloc(len - n);
|
||||
wsi->u.ws.rxflow_len = len - n;
|
||||
wsi->u.ws.rxflow_pos = 0;
|
||||
memcpy(wsi->u.ws.rxflow_buffer,
|
||||
buf + n, len - n);
|
||||
} else
|
||||
/* rxflow while we were spilling prev rxflow */
|
||||
lwsl_info("stalling in existing rxflow buf\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* account for what we're using in rxflow buffer */
|
||||
if (wsi->u.ws.rxflow_buffer)
|
||||
wsi->u.ws.rxflow_pos++;
|
||||
|
||||
/* process the byte */
|
||||
m = libwebsocket_rx_sm(wsi, buf[n++]);
|
||||
if (m < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_server_get_canonical_hostname(struct libwebsocket_context *context,
|
||||
struct lws_context_creation_info *info)
|
||||
{
|
||||
if (info->options & LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME)
|
||||
return;
|
||||
|
||||
/* find canonical hostname */
|
||||
gethostname((char *)context->canonical_hostname,
|
||||
sizeof(context->canonical_hostname) - 1);
|
||||
|
||||
lwsl_notice(" canonical_hostname = %s\n", context->canonical_hostname);
|
||||
}
|
||||
517
dependencies/libwebsockets/lib/service.c
vendored
Normal file
517
dependencies/libwebsockets/lib/service.c
vendored
Normal file
@ -0,0 +1,517 @@
|
||||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010-2014 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 "private-libwebsockets.h"
|
||||
|
||||
int
|
||||
lws_handle_POLLOUT_event(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, struct libwebsocket_pollfd *pollfd)
|
||||
{
|
||||
int n;
|
||||
struct lws_tokens eff_buf;
|
||||
int ret;
|
||||
int m;
|
||||
int handled = 0;
|
||||
|
||||
/* pending truncated sends have uber priority */
|
||||
|
||||
if (wsi->truncated_send_len) {
|
||||
if (lws_issue_raw(wsi, wsi->truncated_send_malloc +
|
||||
wsi->truncated_send_offset,
|
||||
wsi->truncated_send_len) < 0) {
|
||||
lwsl_info("lws_handle_POLLOUT_event signalling to close\n");
|
||||
return -1;
|
||||
}
|
||||
/* leave POLLOUT active either way */
|
||||
return 0;
|
||||
} else
|
||||
if (wsi->state == WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE) {
|
||||
lwsl_info("***** %x signalling to close in POLLOUT handler\n", wsi);
|
||||
return -1; /* retry closing now */
|
||||
}
|
||||
|
||||
|
||||
m = lws_ext_callback_for_each_active(wsi, LWS_EXT_CALLBACK_IS_WRITEABLE,
|
||||
NULL, 0);
|
||||
if (handled == 1)
|
||||
goto notify_action;
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
if (!wsi->extension_data_pending || handled == 2)
|
||||
goto user_service;
|
||||
#endif
|
||||
/*
|
||||
* 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 eff_buf means just spill pending
|
||||
*/
|
||||
|
||||
ret = 1;
|
||||
while (ret == 1) {
|
||||
|
||||
/* default to nobody has more to spill */
|
||||
|
||||
ret = 0;
|
||||
eff_buf.token = NULL;
|
||||
eff_buf.token_len = 0;
|
||||
|
||||
/* give every extension a chance to spill */
|
||||
|
||||
m = lws_ext_callback_for_each_active(wsi,
|
||||
LWS_EXT_CALLBACK_PACKET_TX_PRESEND,
|
||||
&eff_buf, 0);
|
||||
if (m < 0) {
|
||||
lwsl_err("ext reports fatal error\n");
|
||||
return -1;
|
||||
}
|
||||
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 (eff_buf.token_len) {
|
||||
n = lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
|
||||
eff_buf.token_len);
|
||||
if (n < 0) {
|
||||
lwsl_info("closing from POLLOUT spill\n");
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* Keep amount spilled small to minimize chance of this
|
||||
*/
|
||||
if (n != eff_buf.token_len) {
|
||||
lwsl_err("Unable to spill ext %d vs %s\n",
|
||||
eff_buf.token_len, n);
|
||||
return -1;
|
||||
}
|
||||
} 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 0;
|
||||
}
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
wsi->extension_data_pending = 0;
|
||||
|
||||
user_service:
|
||||
#endif
|
||||
/* one shot */
|
||||
|
||||
if (pollfd) {
|
||||
if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
|
||||
return 1;
|
||||
|
||||
lws_libev_io(context, wsi, LWS_EV_STOP | LWS_EV_WRITE);
|
||||
}
|
||||
|
||||
notify_action:
|
||||
if (wsi->mode == LWS_CONNMODE_WS_CLIENT)
|
||||
n = LWS_CALLBACK_CLIENT_WRITEABLE;
|
||||
else
|
||||
n = LWS_CALLBACK_SERVER_WRITEABLE;
|
||||
|
||||
return user_callback_handle_rxflow(wsi->protocol->callback, context,
|
||||
wsi, (enum libwebsocket_callback_reasons) n,
|
||||
wsi->user_space, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
libwebsocket_service_timeout_check(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, unsigned int sec)
|
||||
{
|
||||
/*
|
||||
* if extensions want in on it (eg, we are a mux parent)
|
||||
* give them a chance to service child timeouts
|
||||
*/
|
||||
if (lws_ext_callback_for_each_active(wsi, LWS_EXT_CALLBACK_1HZ, NULL, sec) < 0)
|
||||
return 0;
|
||||
|
||||
if (!wsi->pending_timeout)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* if we went beyond the allowed time, kill the
|
||||
* connection
|
||||
*/
|
||||
if (sec > wsi->pending_timeout_limit) {
|
||||
lwsl_info("TIMEDOUT WAITING on %d\n", wsi->pending_timeout);
|
||||
libwebsocket_close_and_free_session(context,
|
||||
wsi, LWS_CLOSE_STATUS_NOSTATUS);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* libwebsocket_service_fd() - Service polled socket with something waiting
|
||||
* @context: Websocket context
|
||||
* @pollfd: The pollfd entry describing the socket fd and which events
|
||||
* happened.
|
||||
*
|
||||
* This function takes a pollfd that has POLLIN or POLLOUT activity and
|
||||
* services it according to the state of the associated
|
||||
* struct libwebsocket.
|
||||
*
|
||||
* 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
|
||||
* libwebsocket_serice_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.
|
||||
*/
|
||||
|
||||
LWS_VISIBLE int
|
||||
libwebsocket_service_fd(struct libwebsocket_context *context,
|
||||
struct libwebsocket_pollfd *pollfd)
|
||||
{
|
||||
struct libwebsocket *wsi;
|
||||
int n;
|
||||
int m;
|
||||
int listen_socket_fds_index = 0;
|
||||
time_t now;
|
||||
int timed_out = 0;
|
||||
int our_fd = 0;
|
||||
char draining_flow = 0;
|
||||
int more;
|
||||
struct lws_tokens eff_buf;
|
||||
|
||||
if (context->listen_service_fd)
|
||||
listen_socket_fds_index = context->lws_lookup[
|
||||
context->listen_service_fd]->position_in_fds_table;
|
||||
|
||||
/*
|
||||
* you can call us 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.
|
||||
*/
|
||||
|
||||
time(&now);
|
||||
|
||||
/* TODO: if using libev, we should probably use timeout watchers... */
|
||||
if (context->last_timeout_check_s != now) {
|
||||
context->last_timeout_check_s = now;
|
||||
|
||||
lws_plat_service_periodic(context);
|
||||
|
||||
/* global timeout check once per second */
|
||||
|
||||
if (pollfd)
|
||||
our_fd = pollfd->fd;
|
||||
|
||||
for (n = 0; n < context->fds_count; n++) {
|
||||
m = context->fds[n].fd;
|
||||
wsi = context->lws_lookup[m];
|
||||
if (!wsi)
|
||||
continue;
|
||||
|
||||
if (libwebsocket_service_timeout_check(context, wsi, now))
|
||||
/* he did time out... */
|
||||
if (m == our_fd) {
|
||||
/* it was the guy we came to service! */
|
||||
timed_out = 1;
|
||||
/* mark as handled */
|
||||
pollfd->revents = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* the socket we came to service timed out, nothing to do */
|
||||
if (timed_out)
|
||||
return 0;
|
||||
|
||||
/* just here for timeout management? */
|
||||
if (pollfd == NULL)
|
||||
return 0;
|
||||
|
||||
/* no, here to service a socket descriptor */
|
||||
wsi = context->lws_lookup[pollfd->fd];
|
||||
if (wsi == NULL)
|
||||
/* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* deal with listen service piggybacking
|
||||
* every listen_service_modulo services of other fds, we
|
||||
* sneak one in to service the listen socket if there's anything waiting
|
||||
*
|
||||
* To handle connection storms, as found in ab, if we previously saw a
|
||||
* pending connection here, it causes us to check again next time.
|
||||
*/
|
||||
|
||||
if (context->listen_service_fd && pollfd !=
|
||||
&context->fds[listen_socket_fds_index]) {
|
||||
context->listen_service_count++;
|
||||
if (context->listen_service_extraseen ||
|
||||
context->listen_service_count ==
|
||||
context->listen_service_modulo) {
|
||||
context->listen_service_count = 0;
|
||||
m = 1;
|
||||
if (context->listen_service_extraseen > 5)
|
||||
m = 2;
|
||||
while (m--) {
|
||||
/*
|
||||
* even with extpoll, we prepared this
|
||||
* internal fds for listen
|
||||
*/
|
||||
n = lws_poll_listen_fd(&context->fds[listen_socket_fds_index]);
|
||||
if (n > 0) { /* there's a conn waiting for us */
|
||||
libwebsocket_service_fd(context,
|
||||
&context->
|
||||
fds[listen_socket_fds_index]);
|
||||
context->listen_service_extraseen++;
|
||||
} else {
|
||||
if (context->listen_service_extraseen)
|
||||
context->
|
||||
listen_service_extraseen--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* handle session socket closed */
|
||||
|
||||
if ((!(pollfd->revents & LWS_POLLIN)) &&
|
||||
(pollfd->revents & LWS_POLLHUP)) {
|
||||
|
||||
lwsl_debug("Session Socket %p (fd=%d) dead\n",
|
||||
(void *)wsi, pollfd->fd);
|
||||
|
||||
goto close_and_handled;
|
||||
}
|
||||
|
||||
/* okay, what we came here to do... */
|
||||
|
||||
switch (wsi->mode) {
|
||||
case LWS_CONNMODE_HTTP_SERVING:
|
||||
case LWS_CONNMODE_HTTP_SERVING_ACCEPTED:
|
||||
case LWS_CONNMODE_SERVER_LISTENER:
|
||||
case LWS_CONNMODE_SSL_ACK_PENDING:
|
||||
n = lws_server_socket_service(context, wsi, pollfd);
|
||||
if (n < 0)
|
||||
goto close_and_handled;
|
||||
goto handled;
|
||||
|
||||
case LWS_CONNMODE_WS_SERVING:
|
||||
case LWS_CONNMODE_WS_CLIENT:
|
||||
|
||||
/* the guy requested a callback when it was OK to write */
|
||||
|
||||
if ((pollfd->revents & LWS_POLLOUT) &&
|
||||
(wsi->state == WSI_STATE_ESTABLISHED ||
|
||||
wsi->state == WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE) &&
|
||||
lws_handle_POLLOUT_event(context, wsi, pollfd)) {
|
||||
lwsl_info("libwebsocket_service_fd: closing\n");
|
||||
goto close_and_handled;
|
||||
}
|
||||
|
||||
if (wsi->u.ws.rxflow_buffer &&
|
||||
(wsi->u.ws.rxflow_change_to & LWS_RXFLOW_ALLOW)) {
|
||||
lwsl_info("draining rxflow\n");
|
||||
/* well, drain it */
|
||||
eff_buf.token = (char *)wsi->u.ws.rxflow_buffer +
|
||||
wsi->u.ws.rxflow_pos;
|
||||
eff_buf.token_len = wsi->u.ws.rxflow_len -
|
||||
wsi->u.ws.rxflow_pos;
|
||||
draining_flow = 1;
|
||||
goto drain;
|
||||
}
|
||||
|
||||
/* any incoming data ready? */
|
||||
|
||||
if (!(pollfd->revents & LWS_POLLIN))
|
||||
break;
|
||||
|
||||
read_pending:
|
||||
eff_buf.token_len = lws_ssl_capable_read(wsi,
|
||||
context->service_buffer,
|
||||
sizeof(context->service_buffer));
|
||||
switch (eff_buf.token_len) {
|
||||
case 0:
|
||||
lwsl_info("service_fd: closing due to 0 length read\n");
|
||||
goto close_and_handled;
|
||||
case LWS_SSL_CAPABLE_MORE_SERVICE:
|
||||
lwsl_info("SSL Capable more service\n");
|
||||
n = 0;
|
||||
goto handled;
|
||||
case LWS_SSL_CAPABLE_ERROR:
|
||||
lwsl_info("Closing when error\n");
|
||||
goto close_and_handled;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
eff_buf.token = (char *)context->service_buffer;
|
||||
drain:
|
||||
|
||||
do {
|
||||
|
||||
more = 0;
|
||||
|
||||
m = lws_ext_callback_for_each_active(wsi,
|
||||
LWS_EXT_CALLBACK_PACKET_RX_PREPARSE, &eff_buf, 0);
|
||||
if (m < 0)
|
||||
goto close_and_handled;
|
||||
if (m)
|
||||
more = 1;
|
||||
|
||||
/* service incoming data */
|
||||
|
||||
if (eff_buf.token_len) {
|
||||
n = libwebsocket_read(context, wsi,
|
||||
(unsigned char *)eff_buf.token,
|
||||
eff_buf.token_len);
|
||||
if (n < 0) {
|
||||
/* we closed wsi */
|
||||
n = 0;
|
||||
goto handled;
|
||||
}
|
||||
}
|
||||
|
||||
eff_buf.token = NULL;
|
||||
eff_buf.token_len = 0;
|
||||
} while (more);
|
||||
|
||||
if (draining_flow && wsi->u.ws.rxflow_buffer &&
|
||||
wsi->u.ws.rxflow_pos == wsi->u.ws.rxflow_len) {
|
||||
lwsl_info("flow buffer: drained\n");
|
||||
free(wsi->u.ws.rxflow_buffer);
|
||||
wsi->u.ws.rxflow_buffer = NULL;
|
||||
/* having drained the rxflow buffer, can rearm POLLIN */
|
||||
n = _libwebsocket_rx_flow_control(wsi); /* n ignored, needed for NO_SERVER case */
|
||||
}
|
||||
|
||||
if (lws_ssl_pending(wsi))
|
||||
goto read_pending;
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef LWS_NO_CLIENT
|
||||
break;
|
||||
#else
|
||||
n = lws_client_socket_service(context, wsi, pollfd);
|
||||
goto handled;
|
||||
#endif
|
||||
}
|
||||
|
||||
n = 0;
|
||||
goto handled;
|
||||
|
||||
close_and_handled:
|
||||
lwsl_debug("Close and handled\n");
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
n = 1;
|
||||
|
||||
handled:
|
||||
pollfd->revents = 0;
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* libwebsocket_service() - Service any pending websocket activity
|
||||
* @context: Websocket context
|
||||
* @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 int
|
||||
libwebsocket_service(struct libwebsocket_context *context, int timeout_ms)
|
||||
{
|
||||
return lws_plat_service(context, timeout_ms);
|
||||
}
|
||||
|
||||
301
dependencies/libwebsockets/lib/sha-1.c
vendored
Normal file
301
dependencies/libwebsockets/lib/sha-1.c
vendored
Normal file
@ -0,0 +1,301 @@
|
||||
/*
|
||||
* 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 "private-libwebsockets.h"
|
||||
|
||||
#ifdef 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];
|
||||
u_int64_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 __P((struct sha1_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 += 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 += (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 += 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
|
||||
*/
|
||||
|
||||
unsigned char *
|
||||
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*/
|
||||
78
dependencies/libwebsockets/lib/ssl-http2.c
vendored
Normal file
78
dependencies/libwebsockets/lib/ssl-http2.c
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010-2014 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
|
||||
*
|
||||
* Some or all of this file is based on code from nghttp2, which has the
|
||||
* following license. Since it's more liberal than lws license, you're also
|
||||
* at liberty to get the original code from
|
||||
* https://github.com/tatsuhiro-t/nghttp2 under his liberal terms alone.
|
||||
*
|
||||
* nghttp2 - HTTP/2.0 C Library
|
||||
*
|
||||
* Copyright (c) 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 "private-libwebsockets.h"
|
||||
|
||||
#ifndef LWS_NO_SERVER
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
static int alpn_select_proto_cb(SSL* ssl,
|
||||
const unsigned char **out,
|
||||
unsigned char *outlen,
|
||||
const unsigned char *in, unsigned int inlen,
|
||||
void *arg)
|
||||
{
|
||||
lwsl_err((char *)in);
|
||||
return SSL_TLSEXT_ERR_OK; /* SSL_TLSEXT_ERR_NOACK */
|
||||
}
|
||||
#endif
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_context_init_http2_ssl(struct libwebsocket_context *context)
|
||||
{
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
// ALPN selection callback
|
||||
SSL_CTX_set_alpn_select_cb(context->ssl_ctx, alpn_select_proto_cb, NULL);
|
||||
lwsl_notice(" HTTP2 / ALPN enabled\n");
|
||||
#else
|
||||
lwsl_notice(" HTTP2 / ALPN configured but not supported by OpenSSL version\n");
|
||||
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
}
|
||||
|
||||
#endif
|
||||
571
dependencies/libwebsockets/lib/ssl.c
vendored
Normal file
571
dependencies/libwebsockets/lib/ssl.c
vendored
Normal file
@ -0,0 +1,571 @@
|
||||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010-2014 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 "private-libwebsockets.h"
|
||||
|
||||
int openssl_websocket_private_data_index;
|
||||
|
||||
static int
|
||||
OpenSSL_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
|
||||
{
|
||||
SSL *ssl;
|
||||
int n;
|
||||
struct libwebsocket_context *context;
|
||||
|
||||
ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
|
||||
SSL_get_ex_data_X509_STORE_CTX_idx());
|
||||
|
||||
/*
|
||||
* !!! nasty openssl requires the index to come as a library-scope
|
||||
* static
|
||||
*/
|
||||
context = SSL_get_ex_data(ssl, openssl_websocket_private_data_index);
|
||||
|
||||
n = context->protocols[0].callback(NULL, NULL,
|
||||
LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION,
|
||||
x509_ctx, ssl, preverify_ok);
|
||||
|
||||
/* convert return code from 0 = OK to 1 = OK */
|
||||
return !n;
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_context_init_server_ssl(struct lws_context_creation_info *info,
|
||||
struct libwebsocket_context *context)
|
||||
{
|
||||
SSL_METHOD *method;
|
||||
int error;
|
||||
int n;
|
||||
|
||||
#ifndef LWS_NO_SERVER
|
||||
if (info->port != CONTEXT_PORT_NO_LISTEN) {
|
||||
|
||||
context->use_ssl = info->ssl_cert_filepath != NULL &&
|
||||
info->ssl_private_key_filepath != NULL;
|
||||
#ifdef USE_CYASSL
|
||||
lwsl_notice(" Compiled with CYASSL support\n");
|
||||
#else
|
||||
lwsl_notice(" Compiled with OpenSSL support\n");
|
||||
#endif
|
||||
|
||||
if (info->ssl_cipher_list)
|
||||
lwsl_notice(" SSL ciphers: '%s'\n", info->ssl_cipher_list);
|
||||
|
||||
if (context->use_ssl)
|
||||
lwsl_notice(" Using SSL mode\n");
|
||||
else
|
||||
lwsl_notice(" Using non-SSL mode\n");
|
||||
}
|
||||
|
||||
#else
|
||||
if (info->ssl_cert_filepath != NULL &&
|
||||
info->ssl_private_key_filepath != NULL) {
|
||||
lwsl_notice(" Not compiled for OpenSSl support!\n");
|
||||
return 1;
|
||||
}
|
||||
lwsl_notice(" Compiled without SSL support\n");
|
||||
}
|
||||
#endif /* no server */
|
||||
|
||||
/* basic openssl init */
|
||||
|
||||
SSL_library_init();
|
||||
|
||||
OpenSSL_add_all_algorithms();
|
||||
SSL_load_error_strings();
|
||||
|
||||
openssl_websocket_private_data_index =
|
||||
SSL_get_ex_new_index(0, "libwebsockets", NULL, NULL, NULL);
|
||||
|
||||
/*
|
||||
* Firefox insists on SSLv23 not SSLv3
|
||||
* Konq disables SSLv2 by default now, SSLv23 works
|
||||
*/
|
||||
|
||||
method = (SSL_METHOD *)SSLv23_server_method();
|
||||
if (!method) {
|
||||
error = ERR_get_error();
|
||||
lwsl_err("problem creating ssl method %lu: %s\n",
|
||||
error, ERR_error_string(error,
|
||||
(char *)context->service_buffer));
|
||||
return 1;
|
||||
}
|
||||
context->ssl_ctx = SSL_CTX_new(method); /* create context */
|
||||
if (!context->ssl_ctx) {
|
||||
error = ERR_get_error();
|
||||
lwsl_err("problem creating ssl context %lu: %s\n",
|
||||
error, ERR_error_string(error,
|
||||
(char *)context->service_buffer));
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef SSL_OP_NO_COMPRESSION
|
||||
SSL_CTX_set_options(context->ssl_ctx, SSL_OP_NO_COMPRESSION);
|
||||
#endif
|
||||
SSL_CTX_set_options(context->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
|
||||
if (info->ssl_cipher_list)
|
||||
SSL_CTX_set_cipher_list(context->ssl_ctx,
|
||||
info->ssl_cipher_list);
|
||||
|
||||
/* as a server, are we requiring clients to identify themselves? */
|
||||
|
||||
if (info->options &
|
||||
LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT) {
|
||||
|
||||
/* absolutely require the client cert */
|
||||
|
||||
SSL_CTX_set_verify(context->ssl_ctx,
|
||||
SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
|
||||
OpenSSL_verify_callback);
|
||||
|
||||
/*
|
||||
* give user code a chance to load certs into the server
|
||||
* allowing it to verify incoming client certs
|
||||
*/
|
||||
|
||||
context->protocols[0].callback(context, NULL,
|
||||
LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS,
|
||||
context->ssl_ctx, NULL, 0);
|
||||
}
|
||||
|
||||
if (info->options & LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT) {
|
||||
/* Normally SSL listener rejects non-ssl, optionally allow */
|
||||
context->allow_non_ssl_on_ssl_port = 1;
|
||||
}
|
||||
|
||||
if (context->use_ssl) {
|
||||
|
||||
/* openssl init for server sockets */
|
||||
|
||||
/* set the local certificate from CertFile */
|
||||
n = SSL_CTX_use_certificate_chain_file(context->ssl_ctx,
|
||||
info->ssl_cert_filepath);
|
||||
if (n != 1) {
|
||||
error = ERR_get_error();
|
||||
lwsl_err("problem getting cert '%s' %lu: %s\n",
|
||||
info->ssl_cert_filepath,
|
||||
error,
|
||||
ERR_error_string(error,
|
||||
(char *)context->service_buffer));
|
||||
return 1;
|
||||
}
|
||||
/* set the private key from KeyFile */
|
||||
if (SSL_CTX_use_PrivateKey_file(context->ssl_ctx,
|
||||
info->ssl_private_key_filepath,
|
||||
SSL_FILETYPE_PEM) != 1) {
|
||||
error = ERR_get_error();
|
||||
lwsl_err("ssl problem getting key '%s' %lu: %s\n",
|
||||
info->ssl_private_key_filepath,
|
||||
error,
|
||||
ERR_error_string(error,
|
||||
(char *)context->service_buffer));
|
||||
return 1;
|
||||
}
|
||||
/* verify private key */
|
||||
if (!SSL_CTX_check_private_key(context->ssl_ctx)) {
|
||||
lwsl_err("Private SSL key doesn't match cert\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* SSL is happy and has a cert it's content with
|
||||
* If we're supporting HTTP2, initialize that
|
||||
*/
|
||||
|
||||
lws_context_init_http2_ssl(context);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_ssl_destroy(struct libwebsocket_context *context)
|
||||
{
|
||||
if (context->ssl_ctx)
|
||||
SSL_CTX_free(context->ssl_ctx);
|
||||
if (context->ssl_client_ctx)
|
||||
SSL_CTX_free(context->ssl_client_ctx);
|
||||
|
||||
ERR_remove_state(0);
|
||||
ERR_free_strings();
|
||||
EVP_cleanup();
|
||||
CRYPTO_cleanup_all_ex_data();
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
libwebsockets_decode_ssl_error(void)
|
||||
{
|
||||
char buf[256];
|
||||
u_long err;
|
||||
|
||||
while ((err = ERR_get_error()) != 0) {
|
||||
ERR_error_string_n(err, buf, sizeof(buf));
|
||||
lwsl_err("*** %lu %s\n", err, buf);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef LWS_NO_CLIENT
|
||||
int lws_context_init_client_ssl(struct lws_context_creation_info *info,
|
||||
struct libwebsocket_context *context)
|
||||
{
|
||||
int error;
|
||||
int n;
|
||||
SSL_METHOD *method;
|
||||
|
||||
if (info->port != CONTEXT_PORT_NO_LISTEN)
|
||||
return 0;
|
||||
|
||||
method = (SSL_METHOD *)SSLv23_client_method();
|
||||
if (!method) {
|
||||
error = ERR_get_error();
|
||||
lwsl_err("problem creating ssl method %lu: %s\n",
|
||||
error, ERR_error_string(error,
|
||||
(char *)context->service_buffer));
|
||||
return 1;
|
||||
}
|
||||
/* create context */
|
||||
context->ssl_client_ctx = SSL_CTX_new(method);
|
||||
if (!context->ssl_client_ctx) {
|
||||
error = ERR_get_error();
|
||||
lwsl_err("problem creating ssl context %lu: %s\n",
|
||||
error, ERR_error_string(error,
|
||||
(char *)context->service_buffer));
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef SSL_OP_NO_COMPRESSION
|
||||
SSL_CTX_set_options(context->ssl_client_ctx,
|
||||
SSL_OP_NO_COMPRESSION);
|
||||
#endif
|
||||
SSL_CTX_set_options(context->ssl_client_ctx,
|
||||
SSL_OP_CIPHER_SERVER_PREFERENCE);
|
||||
if (info->ssl_cipher_list)
|
||||
SSL_CTX_set_cipher_list(context->ssl_client_ctx,
|
||||
info->ssl_cipher_list);
|
||||
|
||||
#ifdef LWS_SSL_CLIENT_USE_OS_CA_CERTS
|
||||
if (!(info->options & LWS_SERVER_OPTION_DISABLE_OS_CA_CERTS))
|
||||
/* loads OS default CA certs */
|
||||
SSL_CTX_set_default_verify_paths(context->ssl_client_ctx);
|
||||
#endif
|
||||
|
||||
/* openssl init for cert verification (for client sockets) */
|
||||
if (!info->ssl_ca_filepath) {
|
||||
if (!SSL_CTX_load_verify_locations(
|
||||
context->ssl_client_ctx, NULL,
|
||||
LWS_OPENSSL_CLIENT_CERTS))
|
||||
lwsl_err(
|
||||
"Unable to load SSL Client certs from %s "
|
||||
"(set by --with-client-cert-dir= "
|
||||
"in configure) -- client ssl isn't "
|
||||
"going to work", LWS_OPENSSL_CLIENT_CERTS);
|
||||
} else
|
||||
if (!SSL_CTX_load_verify_locations(
|
||||
context->ssl_client_ctx, info->ssl_ca_filepath,
|
||||
NULL))
|
||||
lwsl_err(
|
||||
"Unable to load SSL Client certs "
|
||||
"file from %s -- client ssl isn't "
|
||||
"going to work", info->ssl_ca_filepath);
|
||||
|
||||
/*
|
||||
* callback allowing user code to load extra verification certs
|
||||
* helping the client to verify server identity
|
||||
*/
|
||||
|
||||
/* support for client-side certificate authentication */
|
||||
if (info->ssl_cert_filepath) {
|
||||
n = SSL_CTX_use_certificate_chain_file(
|
||||
context->ssl_client_ctx,
|
||||
info->ssl_cert_filepath);
|
||||
if (n != 1) {
|
||||
lwsl_err("problem getting cert '%s' %lu: %s\n",
|
||||
info->ssl_cert_filepath,
|
||||
ERR_get_error(),
|
||||
ERR_error_string(ERR_get_error(),
|
||||
(char *)context->service_buffer));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (info->ssl_private_key_filepath) {
|
||||
/* set the private key from KeyFile */
|
||||
if (SSL_CTX_use_PrivateKey_file(context->ssl_client_ctx,
|
||||
info->ssl_private_key_filepath,
|
||||
SSL_FILETYPE_PEM) != 1) {
|
||||
lwsl_err("use_PrivateKey_file '%s' %lu: %s\n",
|
||||
info->ssl_private_key_filepath,
|
||||
ERR_get_error(),
|
||||
ERR_error_string(ERR_get_error(),
|
||||
(char *)context->service_buffer));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* verify private key */
|
||||
if (!SSL_CTX_check_private_key(
|
||||
context->ssl_client_ctx)) {
|
||||
lwsl_err("Private SSL key doesn't match cert\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
context->protocols[0].callback(context, NULL,
|
||||
LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS,
|
||||
context->ssl_client_ctx, NULL, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_ssl_capable_read(struct libwebsocket *wsi, unsigned char *buf, int len)
|
||||
{
|
||||
int n;
|
||||
|
||||
if (!wsi->ssl)
|
||||
return lws_ssl_capable_read_no_ssl(wsi, buf, len);
|
||||
|
||||
n = SSL_read(wsi->ssl, buf, len);
|
||||
if (n >= 0)
|
||||
return n;
|
||||
|
||||
n = SSL_get_error(wsi->ssl, n);
|
||||
if (n == SSL_ERROR_WANT_READ || n == SSL_ERROR_WANT_WRITE)
|
||||
return LWS_SSL_CAPABLE_MORE_SERVICE;
|
||||
|
||||
return LWS_SSL_CAPABLE_ERROR;
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_ssl_capable_write(struct libwebsocket *wsi, unsigned char *buf, int len)
|
||||
{
|
||||
int n;
|
||||
|
||||
if (!wsi->ssl)
|
||||
return lws_ssl_capable_write_no_ssl(wsi, buf, len);
|
||||
|
||||
n = SSL_write(wsi->ssl, buf, len);
|
||||
if (n >= 0)
|
||||
return n;
|
||||
|
||||
n = SSL_get_error(wsi->ssl, n);
|
||||
if (n == SSL_ERROR_WANT_READ || n == SSL_ERROR_WANT_WRITE) {
|
||||
if (n == SSL_ERROR_WANT_WRITE)
|
||||
lws_set_blocking_send(wsi);
|
||||
return LWS_SSL_CAPABLE_MORE_SERVICE;
|
||||
}
|
||||
|
||||
return LWS_SSL_CAPABLE_ERROR;
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_ssl_pending(struct libwebsocket *wsi)
|
||||
{
|
||||
if (wsi->ssl)
|
||||
return SSL_pending(wsi->ssl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_ssl_close(struct libwebsocket *wsi)
|
||||
{
|
||||
int n;
|
||||
|
||||
if (!wsi->ssl)
|
||||
return 0; /* not handled */
|
||||
|
||||
n = SSL_get_fd(wsi->ssl);
|
||||
SSL_shutdown(wsi->ssl);
|
||||
compatible_close(n);
|
||||
SSL_free(wsi->ssl);
|
||||
|
||||
return 1; /* handled */
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_server_socket_service_ssl(struct libwebsocket_context *context,
|
||||
struct libwebsocket **pwsi, struct libwebsocket *new_wsi,
|
||||
int accept_fd, struct libwebsocket_pollfd *pollfd)
|
||||
{
|
||||
int n, m;
|
||||
struct libwebsocket *wsi = *pwsi;
|
||||
#ifndef USE_CYASSL
|
||||
BIO *bio;
|
||||
#endif
|
||||
|
||||
if (!LWS_SSL_ENABLED(context))
|
||||
return 0;
|
||||
|
||||
switch (wsi->mode) {
|
||||
case LWS_CONNMODE_SERVER_LISTENER:
|
||||
|
||||
new_wsi->ssl = SSL_new(context->ssl_ctx);
|
||||
if (new_wsi->ssl == NULL) {
|
||||
lwsl_err("SSL_new failed: %s\n",
|
||||
ERR_error_string(SSL_get_error(
|
||||
new_wsi->ssl, 0), NULL));
|
||||
libwebsockets_decode_ssl_error();
|
||||
free(new_wsi);
|
||||
compatible_close(accept_fd);
|
||||
break;
|
||||
}
|
||||
|
||||
SSL_set_ex_data(new_wsi->ssl,
|
||||
openssl_websocket_private_data_index, context);
|
||||
|
||||
SSL_set_fd(new_wsi->ssl, accept_fd);
|
||||
|
||||
#ifdef USE_CYASSL
|
||||
CyaSSL_set_using_nonblock(new_wsi->ssl, 1);
|
||||
#else
|
||||
SSL_set_mode(new_wsi->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
|
||||
bio = SSL_get_rbio(new_wsi->ssl);
|
||||
if (bio)
|
||||
BIO_set_nbio(bio, 1); /* nonblocking */
|
||||
else
|
||||
lwsl_notice("NULL rbio\n");
|
||||
bio = SSL_get_wbio(new_wsi->ssl);
|
||||
if (bio)
|
||||
BIO_set_nbio(bio, 1); /* nonblocking */
|
||||
else
|
||||
lwsl_notice("NULL rbio\n");
|
||||
#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
|
||||
*/
|
||||
|
||||
*pwsi = new_wsi;
|
||||
wsi = *pwsi;
|
||||
wsi->mode = LWS_CONNMODE_SSL_ACK_PENDING;
|
||||
insert_wsi_socket_into_fds(context, wsi);
|
||||
|
||||
libwebsocket_set_timeout(wsi, PENDING_TIMEOUT_SSL_ACCEPT,
|
||||
AWAITING_TIMEOUT);
|
||||
|
||||
lwsl_info("inserted SSL accept into fds, trying SSL_accept\n");
|
||||
|
||||
/* fallthru */
|
||||
|
||||
case LWS_CONNMODE_SSL_ACK_PENDING:
|
||||
|
||||
if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
|
||||
goto fail;
|
||||
|
||||
lws_libev_io(context, wsi, LWS_EV_STOP | LWS_EV_WRITE);
|
||||
|
||||
lws_latency_pre(context, wsi);
|
||||
|
||||
n = recv(wsi->sock, context->service_buffer,
|
||||
sizeof(context->service_buffer), 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 (context->allow_non_ssl_on_ssl_port && n >= 1 &&
|
||||
context->service_buffer[0] >= ' ') {
|
||||
/*
|
||||
* TLS content-type for Handshake is 0x16
|
||||
* TLS content-type for ChangeCipherSpec Record is 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->use_ssl = 0;
|
||||
SSL_shutdown(wsi->ssl);
|
||||
SSL_free(wsi->ssl);
|
||||
wsi->ssl = NULL;
|
||||
goto accepted;
|
||||
}
|
||||
|
||||
/* normal SSL connection processing path */
|
||||
|
||||
n = SSL_accept(wsi->ssl);
|
||||
lws_latency(context, wsi,
|
||||
"SSL_accept LWS_CONNMODE_SSL_ACK_PENDING\n", n, n == 1);
|
||||
|
||||
if (n == 1)
|
||||
goto accepted;
|
||||
|
||||
m = SSL_get_error(wsi->ssl, n);
|
||||
lwsl_debug("SSL_accept failed %d / %s\n",
|
||||
m, ERR_error_string(m, NULL));
|
||||
|
||||
if (m == SSL_ERROR_WANT_READ) {
|
||||
if (lws_change_pollfd(wsi, 0, LWS_POLLIN))
|
||||
goto fail;
|
||||
|
||||
lws_libev_io(context, wsi, LWS_EV_START | LWS_EV_READ);
|
||||
|
||||
lwsl_info("SSL_ERROR_WANT_READ\n");
|
||||
break;
|
||||
}
|
||||
if (m == SSL_ERROR_WANT_WRITE) {
|
||||
if (lws_change_pollfd(wsi, 0, LWS_POLLOUT))
|
||||
goto fail;
|
||||
|
||||
lws_libev_io(context, wsi, LWS_EV_START | LWS_EV_WRITE);
|
||||
break;
|
||||
}
|
||||
lwsl_debug("SSL_accept failed skt %u: %s\n",
|
||||
pollfd->fd, ERR_error_string(m, NULL));
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
break;
|
||||
|
||||
accepted:
|
||||
/* OK, we are accepted... give him some time to negotiate */
|
||||
libwebsocket_set_timeout(wsi,
|
||||
PENDING_TIMEOUT_ESTABLISH_WITH_SERVER,
|
||||
AWAITING_TIMEOUT);
|
||||
|
||||
wsi->mode = LWS_CONNMODE_HTTP_SERVING;
|
||||
|
||||
lwsl_debug("accepted new SSL conn\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
return 1;
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_ssl_context_destroy(struct libwebsocket_context *context)
|
||||
{
|
||||
if (context->ssl_ctx)
|
||||
SSL_CTX_free(context->ssl_ctx);
|
||||
if (context->ssl_client_ctx)
|
||||
SSL_CTX_free(context->ssl_client_ctx);
|
||||
|
||||
ERR_remove_state(0);
|
||||
ERR_free_strings();
|
||||
EVP_cleanup();
|
||||
CRYPTO_cleanup_all_ex_data();
|
||||
}
|
||||
1063
dependencies/libwebsockets/libwebsockets-api-doc.html
vendored
Normal file
1063
dependencies/libwebsockets/libwebsockets-api-doc.html
vendored
Normal file
File diff suppressed because it is too large
Load Diff
66
dependencies/libwebsockets/libwebsockets.spec
vendored
Normal file
66
dependencies/libwebsockets/libwebsockets.spec
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
Name: libwebsockets
|
||||
Version: 1.3
|
||||
Release: 47.gmaster_b89f21c%{?dist}
|
||||
Summary: Websocket Server Library
|
||||
|
||||
Group: System
|
||||
License: GPL
|
||||
URL: http://warmcat.com
|
||||
Source0: %{name}-%{version}.tar.gz
|
||||
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
|
||||
|
||||
BuildRequires: openssl-devel
|
||||
Requires: openssl-devel
|
||||
|
||||
%description
|
||||
Webserver server library
|
||||
|
||||
%package devel
|
||||
Summary: Development files for libwebsockets
|
||||
Group: Development/Libraries
|
||||
Requires: %{name} = %{version}-%{release}
|
||||
Requires: openssl-devel
|
||||
|
||||
%description devel
|
||||
Development files for libwebsockets
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
|
||||
%build
|
||||
mkdir -p build
|
||||
cd build
|
||||
%cmake ..
|
||||
make
|
||||
|
||||
%install
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
cd build
|
||||
make install DESTDIR=$RPM_BUILD_ROOT
|
||||
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files
|
||||
%defattr(-,root,root,-)
|
||||
%attr(755,root,root) /usr/bin/libwebsockets-test-server
|
||||
%attr(755,root,root) /usr/bin/libwebsockets-test-server-extpoll
|
||||
%attr(755,root,root) /usr/bin/libwebsockets-test-client
|
||||
%attr(755,root,root) /usr/bin/libwebsockets-test-ping
|
||||
%attr(755,root,root) /usr/bin/libwebsockets-test-echo
|
||||
%attr(755,root,root) /usr/bin/libwebsockets-test-fraggle
|
||||
%attr(755,root,root)
|
||||
/%{_libdir}/libwebsockets.so.4.0.0
|
||||
/%{_libdir}/libwebsockets.so
|
||||
%attr(755,root,root) /usr/share/libwebsockets-test-server
|
||||
%doc
|
||||
%files devel
|
||||
%defattr(-,root,root,-)
|
||||
/usr/include/*
|
||||
%attr(755,root,root)
|
||||
/%{_libdir}/libwebsockets.a
|
||||
/%{_libdir}/pkgconfig/libwebsockets.pc
|
||||
|
||||
%changelog
|
||||
|
||||
33
dependencies/libwebsockets/scripts/FindLibWebSockets.cmake
vendored
Normal file
33
dependencies/libwebsockets/scripts/FindLibWebSockets.cmake
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
# This module tries to find libWebsockets library and include files
|
||||
#
|
||||
# LIBWEBSOCKETS_INCLUDE_DIR, path where to find libwebsockets.h
|
||||
# LIBWEBSOCKETS_LIBRARY_DIR, path where to find libwebsockets.so
|
||||
# LIBWEBSOCKETS_LIBRARIES, the library to link against
|
||||
# LIBWEBSOCKETS_FOUND, If false, do not try to use libWebSockets
|
||||
#
|
||||
# This currently works probably only for Linux
|
||||
|
||||
FIND_PATH ( LIBWEBSOCKETS_INCLUDE_DIR libwebsockets.h
|
||||
/usr/local/include
|
||||
/usr/include
|
||||
)
|
||||
|
||||
FIND_LIBRARY ( LIBWEBSOCKETS_LIBRARIES websockets
|
||||
/usr/local/lib
|
||||
/usr/lib
|
||||
)
|
||||
|
||||
GET_FILENAME_COMPONENT( LIBWEBSOCKETS_LIBRARY_DIR ${LIBWEBSOCKETS_LIBRARIES} PATH )
|
||||
|
||||
SET ( LIBWEBSOCKETS_FOUND "NO" )
|
||||
IF ( LIBWEBSOCKETS_INCLUDE_DIR )
|
||||
IF ( LIBWEBSOCKETS_LIBRARIES )
|
||||
SET ( LIBWEBSOCKETS_FOUND "YES" )
|
||||
ENDIF ( LIBWEBSOCKETS_LIBRARIES )
|
||||
ENDIF ( LIBWEBSOCKETS_INCLUDE_DIR )
|
||||
|
||||
MARK_AS_ADVANCED(
|
||||
LIBWEBSOCKETS_LIBRARY_DIR
|
||||
LIBWEBSOCKETS_INCLUDE_DIR
|
||||
LIBWEBSOCKETS_LIBRARIES
|
||||
)
|
||||
2239
dependencies/libwebsockets/scripts/kernel-doc
vendored
Normal file
2239
dependencies/libwebsockets/scripts/kernel-doc
vendored
Normal file
File diff suppressed because it is too large
Load Diff
9
dependencies/libwebsockets/test-server/.gitignore
vendored
Normal file
9
dependencies/libwebsockets/test-server/.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
#Ignore build files
|
||||
libwebsockets-test-*
|
||||
Makefile
|
||||
*.o
|
||||
*.lo
|
||||
*.la
|
||||
.libs
|
||||
.deps
|
||||
|
||||
217
dependencies/libwebsockets/test-server/attack.sh
vendored
Normal file
217
dependencies/libwebsockets/test-server/attack.sh
vendored
Normal file
@ -0,0 +1,217 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# attack the test server and try to make it fall over
|
||||
#
|
||||
SERVER=127.0.0.1
|
||||
PORT=7681
|
||||
LOG=/tmp/lwslog
|
||||
|
||||
CPID=
|
||||
LEN=0
|
||||
|
||||
function check {
|
||||
kill -0 $CPID
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "(killed it) *******"
|
||||
exit 1
|
||||
fi
|
||||
dd if=$LOG bs=1 skip=$LEN 2>/dev/null
|
||||
|
||||
if [ "$1" = "default" ] ; then
|
||||
diff /tmp/lwscap /usr/share/libwebsockets-test-server/test.html > /dev/null
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "FAIL: got something other than test.html back"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$1" = "forbidden" ] ; then
|
||||
if [ -z "`grep '<h1>403 Forbidden</h1>' /tmp/lwscap`" ] ; then
|
||||
echo "FAIL: should have told forbidden (test server has no dirs)"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$1" == "args" ] ; then
|
||||
a="`dd if=$LOG bs=1 skip=$LEN 2>/dev/null |grep Uri.Args\: | tr -s ' ' | cut -d' ' -f4-`"
|
||||
if [ "$a" != "$2" ] ; then
|
||||
echo "Args '$a' not $2"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
LEN=`stat $LOG -c %s`
|
||||
}
|
||||
|
||||
|
||||
rm -rf $LOG
|
||||
killall libwebsockets-test-server 2>/dev/null
|
||||
libwebsockets-test-server -d31 2>> $LOG &
|
||||
CPID=$!
|
||||
|
||||
while [ -z "`grep Listening $LOG`" ] ; do
|
||||
sleep 0.5s
|
||||
done
|
||||
check
|
||||
|
||||
echo
|
||||
echo "---- ? processing (%2f%2e%2e%2f%2e./test.html?arg=1)"
|
||||
rm -f /tmp/lwscap
|
||||
echo -e "GET %2f%2e%2e%2f%2e./test.html?arg=1 HTTP/1.1\x0d\x0a\x0d\x0a" | nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
|
||||
check args "arg=1"
|
||||
|
||||
echo
|
||||
echo "---- ? processing (%2f%2e%2e%2f%2e./test.html?arg=/../.)"
|
||||
rm -f /tmp/lwscap
|
||||
echo -e "GET %2f%2e%2e%2f%2e./test.html?arg=/../. HTTP/1.1\x0d\x0a\x0d\x0a" | nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
|
||||
check args "arg=/../."
|
||||
|
||||
|
||||
echo
|
||||
echo "---- spam enough crap to not be GET"
|
||||
echo "not GET" | nc $SERVER $PORT
|
||||
check
|
||||
|
||||
echo
|
||||
echo "---- spam more than the name buffer of crap"
|
||||
dd if=/dev/urandom bs=1 count=80 2>/dev/null | nc -i1s $SERVER $PORT
|
||||
check
|
||||
|
||||
echo
|
||||
echo "---- spam 10MB of crap"
|
||||
dd if=/dev/urandom bs=1 count=655360 | nc -i1s $SERVER $PORT
|
||||
check
|
||||
|
||||
echo
|
||||
echo "---- malformed URI"
|
||||
echo "GET nonsense................................................................................................................" \
|
||||
| nc -i1s $SERVER $PORT
|
||||
check
|
||||
|
||||
echo
|
||||
echo "---- missing URI"
|
||||
echo -e "GET HTTP/1.1\x0d\x0a\x0d\x0a" | nc -i1s $SERVER $PORT >/tmp/lwscap
|
||||
check
|
||||
|
||||
echo
|
||||
echo "---- repeated method"
|
||||
echo -e "GET blah HTTP/1.1\x0d\x0aGET blah HTTP/1.1\x0d\x0a\x0d\x0a" | nc $SERVER $PORT >/tmp/lwscap
|
||||
check
|
||||
|
||||
echo
|
||||
echo "---- crazy header name part"
|
||||
echo -e "GET blah HTTP/1.1\x0d\x0a................................................................................................................" \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
| nc -i1s $SERVER $PORT
|
||||
check
|
||||
|
||||
echo
|
||||
echo "---- excessive uri content"
|
||||
echo -e "GET ................................................................................................................" \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
| nc -i1s $SERVER $PORT
|
||||
check
|
||||
|
||||
echo
|
||||
echo "---- good request but http payload coming too (should be ignored and test.html served)"
|
||||
echo -e "GET /test.html HTTP/1.1\x0d\x0a\x0d\x0aILLEGAL-PAYLOAD........................................" \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
"......................................................................................................................." \
|
||||
| nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
|
||||
check default
|
||||
|
||||
echo
|
||||
echo "---- directory attack 1 (/../../../../etc/passwd should be /etc/passswd)"
|
||||
rm -f /tmp/lwscap
|
||||
echo -e "GET /../../../../etc/passwd HTTP/1.1\x0d\x0a\x0d\x0a" | nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
|
||||
check forbidden
|
||||
|
||||
echo
|
||||
echo "---- directory attack 2 (/../ should be /)"
|
||||
rm -f /tmp/lwscap
|
||||
echo -e "GET /../ HTTP/1.1\x0d\x0a\x0d\x0a" | nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
|
||||
check default
|
||||
|
||||
echo
|
||||
echo "---- directory attack 3 (/./ should be /)"
|
||||
rm -f /tmp/lwscap
|
||||
echo -e "GET /./ HTTP/1.1\x0d\x0a\x0d\x0a" | nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
|
||||
check default
|
||||
|
||||
echo
|
||||
echo "---- directory attack 4 (/blah/.. should be /)"
|
||||
rm -f /tmp/lwscap
|
||||
echo -e "GET /blah/.. HTTP/1.1\x0d\x0a\x0d\x0a" | nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
|
||||
check default
|
||||
|
||||
echo
|
||||
echo "---- directory attack 5 (/blah/../ should be /)"
|
||||
rm -f /tmp/lwscap
|
||||
echo -e "GET /blah/../ HTTP/1.1\x0d\x0a\x0d\x0a" | nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
|
||||
check default
|
||||
|
||||
echo
|
||||
echo "---- directory attack 6 (/blah/../. should be /)"
|
||||
rm -f /tmp/lwscap
|
||||
echo -e "GET /blah/../. HTTP/1.1\x0d\x0a\x0d\x0a" | nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
|
||||
check default
|
||||
|
||||
echo
|
||||
echo "---- directory attack 7 (/%2e%2e%2f../../../etc/passwd should be /etc/passswd)"
|
||||
rm -f /tmp/lwscap
|
||||
echo -e "GET /%2e%2e%2f../../../etc/passwd HTTP/1.1\x0d\x0a\x0d\x0a" | nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
|
||||
check forbidden
|
||||
|
||||
echo
|
||||
echo "---- directory attack 7 (%2f%2e%2e%2f%2e./.%2e/.%2e%2fetc/passwd should be /etc/passswd)"
|
||||
rm -f /tmp/lwscap
|
||||
echo -e "GET %2f%2e%2e%2f%2e./.%2e/.%2e%2fetc/passwd HTTP/1.1\x0d\x0a\x0d\x0a" | nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
|
||||
check forbidden
|
||||
|
||||
|
||||
echo
|
||||
echo "--- survived OK ---"
|
||||
kill -2 $CPID
|
||||
|
||||
BIN
dependencies/libwebsockets/test-server/favicon.ico
vendored
Normal file
BIN
dependencies/libwebsockets/test-server/favicon.ico
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
BIN
dependencies/libwebsockets/test-server/leaf.jpg
vendored
Normal file
BIN
dependencies/libwebsockets/test-server/leaf.jpg
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.4 MiB |
BIN
dependencies/libwebsockets/test-server/libwebsockets.org-logo.png
vendored
Normal file
BIN
dependencies/libwebsockets/test-server/libwebsockets.org-logo.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.9 KiB |
392
dependencies/libwebsockets/test-server/test-client.c
vendored
Normal file
392
dependencies/libwebsockets/test-server/test-client.c
vendored
Normal file
@ -0,0 +1,392 @@
|
||||
/*
|
||||
* libwebsockets-test-client - libwebsockets test implementation
|
||||
*
|
||||
* Copyright (C) 2011 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define random rand
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef CMAKE_BUILD
|
||||
#include "lws_config.h"
|
||||
#endif
|
||||
|
||||
#include "../lib/libwebsockets.h"
|
||||
|
||||
static unsigned int opts;
|
||||
static int was_closed;
|
||||
static int deny_deflate;
|
||||
static int deny_mux;
|
||||
static struct libwebsocket *wsi_mirror;
|
||||
static int mirror_lifetime = 0;
|
||||
static volatile int force_exit = 0;
|
||||
static int longlived = 0;
|
||||
|
||||
/*
|
||||
* This demo shows how to connect multiple websockets simultaneously to a
|
||||
* websocket server (there is no restriction on their having to be the same
|
||||
* server just it simplifies the demo).
|
||||
*
|
||||
* dumb-increment-protocol: we connect to the server and print the number
|
||||
* we are given
|
||||
*
|
||||
* lws-mirror-protocol: draws random circles, which are mirrored on to every
|
||||
* client (see them being drawn in every browser
|
||||
* session also using the test server)
|
||||
*/
|
||||
|
||||
enum demo_protocols {
|
||||
|
||||
PROTOCOL_DUMB_INCREMENT,
|
||||
PROTOCOL_LWS_MIRROR,
|
||||
|
||||
/* always last */
|
||||
DEMO_PROTOCOL_COUNT
|
||||
};
|
||||
|
||||
|
||||
/* dumb_increment protocol */
|
||||
|
||||
static int
|
||||
callback_dumb_increment(struct libwebsocket_context *this,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_callback_reasons reason,
|
||||
void *user, void *in, size_t len)
|
||||
{
|
||||
switch (reason) {
|
||||
|
||||
case LWS_CALLBACK_CLIENT_ESTABLISHED:
|
||||
fprintf(stderr, "callback_dumb_increment: LWS_CALLBACK_CLIENT_ESTABLISHED\n");
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
|
||||
fprintf(stderr, "LWS_CALLBACK_CLIENT_CONNECTION_ERROR\n");
|
||||
was_closed = 1;
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_CLOSED:
|
||||
fprintf(stderr, "LWS_CALLBACK_CLOSED\n");
|
||||
was_closed = 1;
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_CLIENT_RECEIVE:
|
||||
((char *)in)[len] = '\0';
|
||||
fprintf(stderr, "rx %d '%s'\n", (int)len, (char *)in);
|
||||
break;
|
||||
|
||||
/* because we are protocols[0] ... */
|
||||
|
||||
case LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED:
|
||||
if ((strcmp(in, "deflate-stream") == 0) && deny_deflate) {
|
||||
fprintf(stderr, "denied deflate-stream extension\n");
|
||||
return 1;
|
||||
}
|
||||
if ((strcmp(in, "deflate-frame") == 0) && deny_deflate) {
|
||||
fprintf(stderr, "denied deflate-frame extension\n");
|
||||
return 1;
|
||||
}
|
||||
if ((strcmp(in, "x-google-mux") == 0) && deny_mux) {
|
||||
fprintf(stderr, "denied x-google-mux extension\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* lws-mirror_protocol */
|
||||
|
||||
|
||||
static int
|
||||
callback_lws_mirror(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_callback_reasons reason,
|
||||
void *user, void *in, size_t len)
|
||||
{
|
||||
unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 4096 +
|
||||
LWS_SEND_BUFFER_POST_PADDING];
|
||||
int l = 0;
|
||||
int n;
|
||||
|
||||
switch (reason) {
|
||||
|
||||
case LWS_CALLBACK_CLIENT_ESTABLISHED:
|
||||
|
||||
fprintf(stderr, "callback_lws_mirror: LWS_CALLBACK_CLIENT_ESTABLISHED\n");
|
||||
|
||||
mirror_lifetime = 10 + (random() & 1023);
|
||||
/* useful to test single connection stability */
|
||||
if (longlived)
|
||||
mirror_lifetime += 50000;
|
||||
|
||||
fprintf(stderr, "opened mirror connection with "
|
||||
"%d lifetime\n", mirror_lifetime);
|
||||
|
||||
/*
|
||||
* mirror_lifetime is decremented each send, when it reaches
|
||||
* zero the connection is closed in the send callback.
|
||||
* When the close callback comes, wsi_mirror is set to NULL
|
||||
* so a new connection will be opened
|
||||
*/
|
||||
|
||||
/*
|
||||
* start the ball rolling,
|
||||
* LWS_CALLBACK_CLIENT_WRITEABLE will come next service
|
||||
*/
|
||||
|
||||
libwebsocket_callback_on_writable(context, wsi);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_CLOSED:
|
||||
fprintf(stderr, "mirror: LWS_CALLBACK_CLOSED mirror_lifetime=%d\n", mirror_lifetime);
|
||||
wsi_mirror = NULL;
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_CLIENT_RECEIVE:
|
||||
/* fprintf(stderr, "rx %d '%s'\n", (int)len, (char *)in); */
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_CLIENT_WRITEABLE:
|
||||
|
||||
for (n = 0; n < 1; n++)
|
||||
l += sprintf((char *)&buf[LWS_SEND_BUFFER_PRE_PADDING + l],
|
||||
"c #%06X %d %d %d;",
|
||||
(int)random() & 0xffffff,
|
||||
(int)random() % 500,
|
||||
(int)random() % 250,
|
||||
(int)random() % 24);
|
||||
|
||||
n = libwebsocket_write(wsi,
|
||||
&buf[LWS_SEND_BUFFER_PRE_PADDING], l, opts | LWS_WRITE_TEXT);
|
||||
|
||||
if (n < 0)
|
||||
return -1;
|
||||
if (n < l) {
|
||||
lwsl_err("Partial write LWS_CALLBACK_CLIENT_WRITEABLE\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mirror_lifetime--;
|
||||
if (!mirror_lifetime) {
|
||||
fprintf(stderr, "closing mirror session\n");
|
||||
return -1;
|
||||
} else
|
||||
/* get notified as soon as we can write again */
|
||||
libwebsocket_callback_on_writable(context, wsi);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* list of supported protocols and callbacks */
|
||||
|
||||
static struct libwebsocket_protocols protocols[] = {
|
||||
{
|
||||
"dumb-increment-protocol",
|
||||
callback_dumb_increment,
|
||||
0,
|
||||
20,
|
||||
},
|
||||
{
|
||||
"lws-mirror-protocol",
|
||||
callback_lws_mirror,
|
||||
0,
|
||||
128,
|
||||
},
|
||||
{ NULL, NULL, 0, 0 } /* end */
|
||||
};
|
||||
|
||||
void sighandler(int sig)
|
||||
{
|
||||
force_exit = 1;
|
||||
}
|
||||
|
||||
static struct option options[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "debug", required_argument, NULL, 'd' },
|
||||
{ "port", required_argument, NULL, 'p' },
|
||||
{ "ssl", no_argument, NULL, 's' },
|
||||
{ "version", required_argument, NULL, 'v' },
|
||||
{ "undeflated", no_argument, NULL, 'u' },
|
||||
{ "nomux", no_argument, NULL, 'n' },
|
||||
{ "longlived", no_argument, NULL, 'l' },
|
||||
{ NULL, 0, 0, 0 }
|
||||
};
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int n = 0;
|
||||
int ret = 0;
|
||||
int port = 7681;
|
||||
int use_ssl = 0;
|
||||
struct libwebsocket_context *context;
|
||||
const char *address;
|
||||
struct libwebsocket *wsi_dumb;
|
||||
int ietf_version = -1; /* latest */
|
||||
struct lws_context_creation_info info;
|
||||
|
||||
memset(&info, 0, sizeof info);
|
||||
|
||||
fprintf(stderr, "libwebsockets test client\n"
|
||||
"(C) Copyright 2010-2013 Andy Green <andy@warmcat.com> "
|
||||
"licensed under LGPL2.1\n");
|
||||
|
||||
if (argc < 2)
|
||||
goto usage;
|
||||
|
||||
while (n >= 0) {
|
||||
n = getopt_long(argc, argv, "nuv:hsp:d:l", options, NULL);
|
||||
if (n < 0)
|
||||
continue;
|
||||
switch (n) {
|
||||
case 'd':
|
||||
lws_set_log_level(atoi(optarg), NULL);
|
||||
break;
|
||||
case 's':
|
||||
use_ssl = 2; /* 2 = allow selfsigned */
|
||||
break;
|
||||
case 'p':
|
||||
port = atoi(optarg);
|
||||
break;
|
||||
case 'l':
|
||||
longlived = 1;
|
||||
break;
|
||||
case 'v':
|
||||
ietf_version = atoi(optarg);
|
||||
break;
|
||||
case 'u':
|
||||
deny_deflate = 1;
|
||||
break;
|
||||
case 'n':
|
||||
deny_mux = 1;
|
||||
break;
|
||||
case 'h':
|
||||
goto usage;
|
||||
}
|
||||
}
|
||||
|
||||
if (optind >= argc)
|
||||
goto usage;
|
||||
|
||||
signal(SIGINT, sighandler);
|
||||
|
||||
address = argv[optind];
|
||||
|
||||
/*
|
||||
* create the websockets context. This tracks open connections and
|
||||
* knows how to route any traffic and which protocol version to use,
|
||||
* and if each connection is client or server side.
|
||||
*
|
||||
* For this client-only demo, we tell it to not listen on any port.
|
||||
*/
|
||||
|
||||
info.port = CONTEXT_PORT_NO_LISTEN;
|
||||
info.protocols = protocols;
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
info.extensions = libwebsocket_get_internal_extensions();
|
||||
#endif
|
||||
info.gid = -1;
|
||||
info.uid = -1;
|
||||
|
||||
context = libwebsocket_create_context(&info);
|
||||
if (context == NULL) {
|
||||
fprintf(stderr, "Creating libwebsocket context failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* create a client websocket using dumb increment protocol */
|
||||
|
||||
wsi_dumb = libwebsocket_client_connect(context, address, port, use_ssl,
|
||||
"/", argv[optind], argv[optind],
|
||||
protocols[PROTOCOL_DUMB_INCREMENT].name, ietf_version);
|
||||
|
||||
if (wsi_dumb == NULL) {
|
||||
fprintf(stderr, "libwebsocket connect failed\n");
|
||||
ret = 1;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Waiting for connect...\n");
|
||||
|
||||
/*
|
||||
* sit there servicing the websocket context to handle incoming
|
||||
* packets, and drawing random circles on the mirror protocol websocket
|
||||
* nothing happens until the client websocket connection is
|
||||
* asynchronously established
|
||||
*/
|
||||
|
||||
n = 0;
|
||||
while (n >= 0 && !was_closed && !force_exit) {
|
||||
n = libwebsocket_service(context, 10);
|
||||
|
||||
if (n < 0)
|
||||
continue;
|
||||
|
||||
if (wsi_mirror)
|
||||
continue;
|
||||
|
||||
/* create a client websocket using mirror protocol */
|
||||
|
||||
wsi_mirror = libwebsocket_client_connect(context,
|
||||
address, port, use_ssl, "/",
|
||||
argv[optind], argv[optind],
|
||||
protocols[PROTOCOL_LWS_MIRROR].name, ietf_version);
|
||||
|
||||
if (wsi_mirror == NULL) {
|
||||
fprintf(stderr, "libwebsocket "
|
||||
"mirror connect failed\n");
|
||||
ret = 1;
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
||||
bail:
|
||||
fprintf(stderr, "Exiting\n");
|
||||
|
||||
libwebsocket_context_destroy(context);
|
||||
|
||||
return ret;
|
||||
|
||||
usage:
|
||||
fprintf(stderr, "Usage: libwebsockets-test-client "
|
||||
"<server address> [--port=<p>] "
|
||||
"[--ssl] [-k] [-v <ver>] "
|
||||
"[-d <log bitfield>] [-l]\n");
|
||||
return 1;
|
||||
}
|
||||
361
dependencies/libwebsockets/test-server/test-echo.c
vendored
Normal file
361
dependencies/libwebsockets/test-server/test-echo.c
vendored
Normal file
@ -0,0 +1,361 @@
|
||||
/*
|
||||
* libwebsockets-test-echo - libwebsockets echo test implementation
|
||||
*
|
||||
* This implements both the client and server sides. It defaults to
|
||||
* serving, use --client <remote address> to connect as client.
|
||||
*
|
||||
* Copyright (C) 2010-2013 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <signal.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <syslog.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef CMAKE_BUILD
|
||||
#include "lws_config.h"
|
||||
#endif
|
||||
|
||||
#include "../lib/libwebsockets.h"
|
||||
|
||||
static volatile int force_exit = 0;
|
||||
|
||||
#define MAX_ECHO_PAYLOAD 1400
|
||||
#define LOCAL_RESOURCE_PATH INSTALL_DATADIR"/libwebsockets-test-server"
|
||||
|
||||
struct per_session_data__echo {
|
||||
unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + MAX_ECHO_PAYLOAD + LWS_SEND_BUFFER_POST_PADDING];
|
||||
unsigned int len;
|
||||
unsigned int index;
|
||||
};
|
||||
|
||||
static int
|
||||
callback_echo(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_callback_reasons reason, void *user,
|
||||
void *in, size_t len)
|
||||
{
|
||||
struct per_session_data__echo *pss = (struct per_session_data__echo *)user;
|
||||
int n;
|
||||
|
||||
switch (reason) {
|
||||
|
||||
#ifndef LWS_NO_SERVER
|
||||
/* when the callback is used for server operations --> */
|
||||
|
||||
case LWS_CALLBACK_SERVER_WRITEABLE:
|
||||
n = libwebsocket_write(wsi, &pss->buf[LWS_SEND_BUFFER_PRE_PADDING], pss->len, LWS_WRITE_TEXT);
|
||||
if (n < 0) {
|
||||
lwsl_err("ERROR %d writing to socket, hanging up\n", n);
|
||||
return 1;
|
||||
}
|
||||
if (n < (int)pss->len) {
|
||||
lwsl_err("Partial write\n");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_RECEIVE:
|
||||
if (len > MAX_ECHO_PAYLOAD) {
|
||||
lwsl_err("Server received packet bigger than %u, hanging up\n", MAX_ECHO_PAYLOAD);
|
||||
return 1;
|
||||
}
|
||||
memcpy(&pss->buf[LWS_SEND_BUFFER_PRE_PADDING], in, len);
|
||||
pss->len = (unsigned int)len;
|
||||
libwebsocket_callback_on_writable(context, wsi);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifndef LWS_NO_CLIENT
|
||||
/* when the callback is used for client operations --> */
|
||||
|
||||
case LWS_CALLBACK_CLIENT_ESTABLISHED:
|
||||
lwsl_notice("Client has connected\n");
|
||||
pss->index = 0;
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_CLIENT_RECEIVE:
|
||||
lwsl_notice("Client RX: %s", (char *)in);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_CLIENT_WRITEABLE:
|
||||
/* we will send our packet... */
|
||||
pss->len = sprintf((char *)&pss->buf[LWS_SEND_BUFFER_PRE_PADDING], "hello from libwebsockets-test-echo client pid %d index %d\n", getpid(), pss->index++);
|
||||
lwsl_notice("Client TX: %s", &pss->buf[LWS_SEND_BUFFER_PRE_PADDING]);
|
||||
n = libwebsocket_write(wsi, &pss->buf[LWS_SEND_BUFFER_PRE_PADDING], pss->len, LWS_WRITE_TEXT);
|
||||
if (n < 0) {
|
||||
lwsl_err("ERROR %d writing to socket, hanging up\n", n);
|
||||
return -1;
|
||||
}
|
||||
if (n < (int)pss->len) {
|
||||
lwsl_err("Partial write\n");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static struct libwebsocket_protocols protocols[] = {
|
||||
/* first protocol must always be HTTP handler */
|
||||
|
||||
{
|
||||
"default", /* name */
|
||||
callback_echo, /* callback */
|
||||
sizeof(struct per_session_data__echo) /* per_session_data_size */
|
||||
},
|
||||
{
|
||||
NULL, NULL, 0 /* End of list */
|
||||
}
|
||||
};
|
||||
|
||||
void sighandler(int sig)
|
||||
{
|
||||
force_exit = 1;
|
||||
}
|
||||
|
||||
static struct option options[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "debug", required_argument, NULL, 'd' },
|
||||
{ "port", required_argument, NULL, 'p' },
|
||||
#ifndef LWS_NO_CLIENT
|
||||
{ "client", required_argument, NULL, 'c' },
|
||||
{ "ratems", required_argument, NULL, 'r' },
|
||||
#endif
|
||||
{ "ssl", no_argument, NULL, 's' },
|
||||
{ "interface", required_argument, NULL, 'i' },
|
||||
#ifndef LWS_NO_DAEMONIZE
|
||||
{ "daemonize", no_argument, NULL, 'D' },
|
||||
#endif
|
||||
{ NULL, 0, 0, 0 }
|
||||
};
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int n = 0;
|
||||
int port = 7681;
|
||||
int use_ssl = 0;
|
||||
struct libwebsocket_context *context;
|
||||
int opts = 0;
|
||||
char interface_name[128] = "";
|
||||
const char *interface = NULL;
|
||||
#ifndef WIN32
|
||||
int syslog_options = LOG_PID | LOG_PERROR;
|
||||
#endif
|
||||
int client = 0;
|
||||
int listen_port;
|
||||
struct lws_context_creation_info info;
|
||||
#ifndef LWS_NO_CLIENT
|
||||
char address[256];
|
||||
int rate_us = 250000;
|
||||
unsigned int oldus = 0;
|
||||
struct libwebsocket *wsi;
|
||||
#endif
|
||||
|
||||
int debug_level = 7;
|
||||
#ifndef LWS_NO_DAEMONIZE
|
||||
int daemonize = 0;
|
||||
#endif
|
||||
|
||||
memset(&info, 0, sizeof info);
|
||||
|
||||
#ifndef LWS_NO_CLIENT
|
||||
lwsl_notice("Built to support client operations\n");
|
||||
#endif
|
||||
#ifndef LWS_NO_SERVER
|
||||
lwsl_notice("Built to support server operations\n");
|
||||
#endif
|
||||
|
||||
while (n >= 0) {
|
||||
n = getopt_long(argc, argv, "i:hsp:d:D"
|
||||
#ifndef LWS_NO_CLIENT
|
||||
"c:r:"
|
||||
#endif
|
||||
, options, NULL);
|
||||
if (n < 0)
|
||||
continue;
|
||||
switch (n) {
|
||||
#ifndef LWS_NO_DAEMONIZE
|
||||
case 'D':
|
||||
daemonize = 1;
|
||||
#ifndef WIN32
|
||||
syslog_options &= ~LOG_PERROR;
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
#ifndef LWS_NO_CLIENT
|
||||
case 'c':
|
||||
client = 1;
|
||||
strcpy(address, optarg);
|
||||
port = 80;
|
||||
break;
|
||||
case 'r':
|
||||
rate_us = atoi(optarg) * 1000;
|
||||
break;
|
||||
#endif
|
||||
case 'd':
|
||||
debug_level = atoi(optarg);
|
||||
break;
|
||||
case 's':
|
||||
use_ssl = 1; /* 1 = take care about cert verification, 2 = allow anything */
|
||||
break;
|
||||
case 'p':
|
||||
port = atoi(optarg);
|
||||
break;
|
||||
case 'i':
|
||||
strncpy(interface_name, optarg, sizeof interface_name);
|
||||
interface_name[(sizeof interface_name) - 1] = '\0';
|
||||
interface = interface_name;
|
||||
break;
|
||||
case '?':
|
||||
case 'h':
|
||||
fprintf(stderr, "Usage: libwebsockets-test-echo "
|
||||
"[--ssl] "
|
||||
#ifndef LWS_NO_CLIENT
|
||||
"[--client <remote ads>] "
|
||||
"[--ratems <ms>] "
|
||||
#endif
|
||||
"[--port=<p>] "
|
||||
"[-d <log bitfield>]\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef LWS_NO_DAEMONIZE
|
||||
/*
|
||||
* normally lock path would be /var/lock/lwsts or similar, to
|
||||
* simplify getting started without having to take care about
|
||||
* permissions or running as root, set to /tmp/.lwsts-lock
|
||||
*/
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
#else
|
||||
if (!client && daemonize && lws_daemonize("/tmp/.lwstecho-lock")) {
|
||||
fprintf(stderr, "Failed to daemonize\n");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#else
|
||||
/* we will only try to log things according to our debug_level */
|
||||
setlogmask(LOG_UPTO (LOG_DEBUG));
|
||||
openlog("lwsts", syslog_options, LOG_DAEMON);
|
||||
|
||||
/* tell the library what debug level to emit and to send it to syslog */
|
||||
lws_set_log_level(debug_level, lwsl_emit_syslog);
|
||||
#endif
|
||||
lwsl_notice("libwebsockets echo test - "
|
||||
"(C) Copyright 2010-2013 Andy Green <andy@warmcat.com> - "
|
||||
"licensed under LGPL2.1\n");
|
||||
#ifndef LWS_NO_CLIENT
|
||||
if (client) {
|
||||
lwsl_notice("Running in client mode\n");
|
||||
listen_port = CONTEXT_PORT_NO_LISTEN;
|
||||
if (use_ssl)
|
||||
use_ssl = 2;
|
||||
} else {
|
||||
#endif
|
||||
#ifndef LWS_NO_SERVER
|
||||
lwsl_notice("Running in server mode\n");
|
||||
listen_port = port;
|
||||
#endif
|
||||
#ifndef LWS_NO_CLIENT
|
||||
}
|
||||
#endif
|
||||
|
||||
info.port = listen_port;
|
||||
info.iface = interface;
|
||||
info.protocols = protocols;
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
info.extensions = libwebsocket_get_internal_extensions();
|
||||
#endif
|
||||
if (use_ssl && !client) {
|
||||
info.ssl_cert_filepath = LOCAL_RESOURCE_PATH"/libwebsockets-test-server.pem";
|
||||
info.ssl_private_key_filepath = LOCAL_RESOURCE_PATH"/libwebsockets-test-server.key.pem";
|
||||
}
|
||||
info.gid = -1;
|
||||
info.uid = -1;
|
||||
info.options = opts;
|
||||
|
||||
context = libwebsocket_create_context(&info);
|
||||
|
||||
if (context == NULL) {
|
||||
lwsl_err("libwebsocket init failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifndef LWS_NO_CLIENT
|
||||
if (client) {
|
||||
lwsl_notice("Client connecting to %s:%u....\n", address, port);
|
||||
/* we are in client mode */
|
||||
wsi = libwebsocket_client_connect(context, address,
|
||||
port, use_ssl, "/", address,
|
||||
"origin", NULL, -1);
|
||||
if (!wsi) {
|
||||
lwsl_err("Client failed to connect to %s:%u\n", address, port);
|
||||
goto bail;
|
||||
}
|
||||
lwsl_notice("Client connected to %s:%u\n", address, port);
|
||||
}
|
||||
#endif
|
||||
signal(SIGINT, sighandler);
|
||||
|
||||
n = 0;
|
||||
while (n >= 0 && !force_exit) {
|
||||
#ifndef LWS_NO_CLIENT
|
||||
struct timeval tv;
|
||||
|
||||
if (client) {
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
if (((unsigned int)tv.tv_usec - oldus) > (unsigned int)rate_us) {
|
||||
libwebsocket_callback_on_writable_all_protocol(&protocols[0]);
|
||||
oldus = tv.tv_usec;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
n = libwebsocket_service(context, 10);
|
||||
}
|
||||
#ifndef LWS_NO_CLIENT
|
||||
bail:
|
||||
#endif
|
||||
libwebsocket_context_destroy(context);
|
||||
|
||||
lwsl_notice("libwebsockets-test-echo exited cleanly\n");
|
||||
#ifdef WIN32
|
||||
#else
|
||||
closelog();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
358
dependencies/libwebsockets/test-server/test-fraggle.c
vendored
Normal file
358
dependencies/libwebsockets/test-server/test-fraggle.c
vendored
Normal file
@ -0,0 +1,358 @@
|
||||
/*
|
||||
* libwebsockets-test-fraggle - random fragmentation test
|
||||
*
|
||||
* Copyright (C) 2010-2011 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
#include <string.h>
|
||||
#include "../lib/libwebsockets.h"
|
||||
|
||||
#define LOCAL_RESOURCE_PATH INSTALL_DATADIR"/libwebsockets-test-server"
|
||||
|
||||
static int client;
|
||||
static int terminate;
|
||||
|
||||
enum demo_protocols {
|
||||
PROTOCOL_FRAGGLE,
|
||||
|
||||
/* always last */
|
||||
DEMO_PROTOCOL_COUNT
|
||||
};
|
||||
|
||||
/* fraggle protocol */
|
||||
|
||||
enum fraggle_states {
|
||||
FRAGSTATE_START_MESSAGE,
|
||||
FRAGSTATE_RANDOM_PAYLOAD,
|
||||
FRAGSTATE_POST_PAYLOAD_SUM,
|
||||
};
|
||||
|
||||
struct per_session_data__fraggle {
|
||||
int packets_left;
|
||||
int total_message;
|
||||
unsigned long sum;
|
||||
enum fraggle_states state;
|
||||
};
|
||||
|
||||
static int
|
||||
callback_fraggle(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_callback_reasons reason,
|
||||
void *user, void *in, size_t len)
|
||||
{
|
||||
int n;
|
||||
unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 8000 +
|
||||
LWS_SEND_BUFFER_POST_PADDING];
|
||||
struct per_session_data__fraggle *psf = user;
|
||||
int chunk;
|
||||
int write_mode = LWS_WRITE_CONTINUATION;
|
||||
unsigned long sum;
|
||||
unsigned char *p = (unsigned char *)in;
|
||||
unsigned char *bp = &buf[LWS_SEND_BUFFER_PRE_PADDING];
|
||||
|
||||
switch (reason) {
|
||||
|
||||
case LWS_CALLBACK_ESTABLISHED:
|
||||
|
||||
fprintf(stderr, "server sees client connect\n");
|
||||
psf->state = FRAGSTATE_START_MESSAGE;
|
||||
/* start the ball rolling */
|
||||
libwebsocket_callback_on_writable(context, wsi);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_CLIENT_ESTABLISHED:
|
||||
|
||||
fprintf(stderr, "client connects to server\n");
|
||||
psf->state = FRAGSTATE_START_MESSAGE;
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_CLIENT_RECEIVE:
|
||||
|
||||
switch (psf->state) {
|
||||
|
||||
case FRAGSTATE_START_MESSAGE:
|
||||
|
||||
psf->state = FRAGSTATE_RANDOM_PAYLOAD;
|
||||
psf->sum = 0;
|
||||
psf->total_message = 0;
|
||||
psf->packets_left = 0;
|
||||
|
||||
/* fallthru */
|
||||
|
||||
case FRAGSTATE_RANDOM_PAYLOAD:
|
||||
|
||||
for (n = 0; n < len; n++)
|
||||
psf->sum += p[n];
|
||||
|
||||
psf->total_message += len;
|
||||
psf->packets_left++;
|
||||
|
||||
if (libwebsocket_is_final_fragment(wsi))
|
||||
psf->state = FRAGSTATE_POST_PAYLOAD_SUM;
|
||||
break;
|
||||
|
||||
case FRAGSTATE_POST_PAYLOAD_SUM:
|
||||
|
||||
sum = p[0] << 24;
|
||||
sum |= p[1] << 16;
|
||||
sum |= p[2] << 8;
|
||||
sum |= p[3];
|
||||
if (sum == psf->sum)
|
||||
fprintf(stderr, "EOM received %d correctly "
|
||||
"from %d fragments\n",
|
||||
psf->total_message, psf->packets_left);
|
||||
else
|
||||
fprintf(stderr, "**** ERROR at EOM: "
|
||||
"length %d, rx sum = 0x%lX, "
|
||||
"server says it sent 0x%lX\n",
|
||||
psf->total_message, psf->sum, sum);
|
||||
|
||||
psf->state = FRAGSTATE_START_MESSAGE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_SERVER_WRITEABLE:
|
||||
|
||||
switch (psf->state) {
|
||||
|
||||
case FRAGSTATE_START_MESSAGE:
|
||||
|
||||
psf->packets_left = (random() % 1024) + 1;
|
||||
fprintf(stderr, "Spamming %d random fragments\n",
|
||||
psf->packets_left);
|
||||
psf->sum = 0;
|
||||
psf->total_message = 0;
|
||||
write_mode = LWS_WRITE_BINARY;
|
||||
psf->state = FRAGSTATE_RANDOM_PAYLOAD;
|
||||
|
||||
/* fallthru */
|
||||
|
||||
case FRAGSTATE_RANDOM_PAYLOAD:
|
||||
|
||||
/*
|
||||
* note how one chunk can be 8000, but we use the
|
||||
* default rx buffer size of 4096, so we exercise the
|
||||
* code for rx spill because the rx buffer is full
|
||||
*/
|
||||
|
||||
chunk = (random() % 8000) + 1;
|
||||
psf->total_message += chunk;
|
||||
|
||||
libwebsockets_get_random(context, bp, chunk);
|
||||
for (n = 0; n < chunk; n++)
|
||||
psf->sum += bp[n];
|
||||
|
||||
psf->packets_left--;
|
||||
if (psf->packets_left)
|
||||
write_mode |= LWS_WRITE_NO_FIN;
|
||||
else
|
||||
psf->state = FRAGSTATE_POST_PAYLOAD_SUM;
|
||||
|
||||
n = libwebsocket_write(wsi, bp, chunk, write_mode);
|
||||
if (n < 0)
|
||||
return -1;
|
||||
if (n < chunk) {
|
||||
lwsl_err("Partial write\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
libwebsocket_callback_on_writable(context, wsi);
|
||||
break;
|
||||
|
||||
case FRAGSTATE_POST_PAYLOAD_SUM:
|
||||
|
||||
fprintf(stderr, "Spamming session over, "
|
||||
"len = %d. sum = 0x%lX\n",
|
||||
psf->total_message, psf->sum);
|
||||
|
||||
bp[0] = psf->sum >> 24;
|
||||
bp[1] = psf->sum >> 16;
|
||||
bp[2] = psf->sum >> 8;
|
||||
bp[3] = psf->sum;
|
||||
|
||||
n = libwebsocket_write(wsi, (unsigned char *)bp,
|
||||
4, LWS_WRITE_BINARY);
|
||||
if (n < 0)
|
||||
return -1;
|
||||
if (n < 4) {
|
||||
lwsl_err("Partial write\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
psf->state = FRAGSTATE_START_MESSAGE;
|
||||
|
||||
libwebsocket_callback_on_writable(context, wsi);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_CLOSED:
|
||||
|
||||
terminate = 1;
|
||||
break;
|
||||
|
||||
/* because we are protocols[0] ... */
|
||||
|
||||
case LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED:
|
||||
if (strcmp(in, "deflate-stream") == 0) {
|
||||
fprintf(stderr, "denied deflate-stream extension\n");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* list of supported protocols and callbacks */
|
||||
|
||||
static struct libwebsocket_protocols protocols[] = {
|
||||
{
|
||||
"fraggle-protocol",
|
||||
callback_fraggle,
|
||||
sizeof(struct per_session_data__fraggle),
|
||||
},
|
||||
{
|
||||
NULL, NULL, 0 /* End of list */
|
||||
}
|
||||
};
|
||||
|
||||
static struct option options[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "debug", required_argument, NULL, 'd' },
|
||||
{ "port", required_argument, NULL, 'p' },
|
||||
{ "ssl", no_argument, NULL, 's' },
|
||||
{ "interface", required_argument, NULL, 'i' },
|
||||
{ "client", no_argument, NULL, 'c' },
|
||||
{ NULL, 0, 0, 0 }
|
||||
};
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int n = 0;
|
||||
int port = 7681;
|
||||
int use_ssl = 0;
|
||||
struct libwebsocket_context *context;
|
||||
int opts = 0;
|
||||
char interface_name[128] = "";
|
||||
const char *iface = NULL;
|
||||
struct libwebsocket *wsi;
|
||||
const char *address;
|
||||
int server_port = port;
|
||||
struct lws_context_creation_info info;
|
||||
|
||||
memset(&info, 0, sizeof info);
|
||||
|
||||
fprintf(stderr, "libwebsockets test fraggle\n"
|
||||
"(C) Copyright 2010-2013 Andy Green <andy@warmcat.com> "
|
||||
"licensed under LGPL2.1\n");
|
||||
|
||||
while (n >= 0) {
|
||||
n = getopt_long(argc, argv, "ci:hsp:d:", options, NULL);
|
||||
if (n < 0)
|
||||
continue;
|
||||
switch (n) {
|
||||
case 'd':
|
||||
lws_set_log_level(atoi(optarg), NULL);
|
||||
break;
|
||||
case 's':
|
||||
use_ssl = 1;
|
||||
break;
|
||||
case 'p':
|
||||
port = atoi(optarg);
|
||||
server_port = port;
|
||||
break;
|
||||
case 'i':
|
||||
strncpy(interface_name, optarg, sizeof interface_name);
|
||||
interface_name[(sizeof interface_name) - 1] = '\0';
|
||||
iface = interface_name;
|
||||
break;
|
||||
case 'c':
|
||||
client = 1;
|
||||
fprintf(stderr, " Client mode\n");
|
||||
break;
|
||||
case 'h':
|
||||
fprintf(stderr, "Usage: libwebsockets-test-fraggle "
|
||||
"[--port=<p>] [--ssl] "
|
||||
"[-d <log bitfield>] "
|
||||
"[--client]\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (client) {
|
||||
server_port = CONTEXT_PORT_NO_LISTEN;
|
||||
if (optind >= argc) {
|
||||
fprintf(stderr, "Must give address of server\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
info.port = server_port;
|
||||
info.iface = iface;
|
||||
info.protocols = protocols;
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
info.extensions = libwebsocket_get_internal_extensions();
|
||||
#endif
|
||||
if (use_ssl) {
|
||||
info.ssl_cert_filepath = LOCAL_RESOURCE_PATH"/libwebsockets-test-server.pem";
|
||||
info.ssl_private_key_filepath = LOCAL_RESOURCE_PATH"/libwebsockets-test-server.key.pem";
|
||||
}
|
||||
info.gid = -1;
|
||||
info.uid = -1;
|
||||
info.options = opts;
|
||||
|
||||
context = libwebsocket_create_context(&info);
|
||||
if (context == NULL) {
|
||||
fprintf(stderr, "libwebsocket init failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (client) {
|
||||
address = argv[optind];
|
||||
fprintf(stderr, "Connecting to %s:%u\n", address, port);
|
||||
wsi = libwebsocket_client_connect(context, address,
|
||||
port, use_ssl, "/", address,
|
||||
"origin", protocols[PROTOCOL_FRAGGLE].name,
|
||||
-1);
|
||||
if (wsi == NULL) {
|
||||
fprintf(stderr, "Client connect to server failed\n");
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
||||
n = 0;
|
||||
while (!n && !terminate)
|
||||
n = libwebsocket_service(context, 50);
|
||||
|
||||
fprintf(stderr, "Terminating...\n");
|
||||
|
||||
bail:
|
||||
libwebsocket_context_destroy(context);
|
||||
|
||||
return 0;
|
||||
}
|
||||
543
dependencies/libwebsockets/test-server/test-ping.c
vendored
Normal file
543
dependencies/libwebsockets/test-server/test-ping.c
vendored
Normal file
@ -0,0 +1,543 @@
|
||||
/*
|
||||
* libwebsockets-test-ping - libwebsockets floodping
|
||||
*
|
||||
* Copyright (C) 2011 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <poll.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef CMAKE_BUILD
|
||||
#include "lws_config.h"
|
||||
#endif
|
||||
|
||||
#include "../lib/libwebsockets.h"
|
||||
|
||||
/*
|
||||
* this is specified in the 04 standard, control frames can only have small
|
||||
* payload length styles
|
||||
*/
|
||||
#define MAX_PING_PAYLOAD 125
|
||||
#define MAX_MIRROR_PAYLOAD 4096
|
||||
#define MAX_PING_CLIENTS 256
|
||||
#define PING_RINGBUFFER_SIZE 256
|
||||
|
||||
static struct libwebsocket *ping_wsi[MAX_PING_CLIENTS];
|
||||
static unsigned int interval_us = 1000000;
|
||||
static unsigned int size = 64;
|
||||
static int flood;
|
||||
static const char *address;
|
||||
static unsigned char pingbuf[LWS_SEND_BUFFER_PRE_PADDING + MAX_MIRROR_PAYLOAD +
|
||||
LWS_SEND_BUFFER_POST_PADDING];
|
||||
static char peer_name[128];
|
||||
static unsigned long started;
|
||||
static int screen_width = 80;
|
||||
static int use_mirror;
|
||||
static unsigned int write_options;
|
||||
|
||||
static unsigned long rtt_min = 100000000;
|
||||
static unsigned long rtt_max;
|
||||
static unsigned long rtt_avg;
|
||||
static unsigned long global_rx_count;
|
||||
static unsigned long global_tx_count;
|
||||
static int clients = 1;
|
||||
static unsigned long interrupted_time;
|
||||
|
||||
struct ping {
|
||||
unsigned long issue_timestamp;
|
||||
unsigned long index;
|
||||
unsigned int seen;
|
||||
};
|
||||
|
||||
struct per_session_data__ping {
|
||||
unsigned long ping_index;
|
||||
|
||||
struct ping ringbuffer[PING_RINGBUFFER_SIZE];
|
||||
int ringbuffer_head;
|
||||
int ringbuffer_tail;
|
||||
|
||||
unsigned long rx_count;
|
||||
};
|
||||
|
||||
/*
|
||||
* uses the ping pong protocol features to provide an equivalent for the
|
||||
* ping utility for 04+ websockets
|
||||
*/
|
||||
|
||||
enum demo_protocols {
|
||||
|
||||
PROTOCOL_LWS_MIRROR,
|
||||
|
||||
/* always last */
|
||||
DEMO_PROTOCOL_COUNT
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
callback_lws_mirror(struct libwebsocket_context * this,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_callback_reasons reason,
|
||||
void *user, void *in, size_t len)
|
||||
{
|
||||
struct timeval tv;
|
||||
unsigned char *p;
|
||||
int shift;
|
||||
unsigned long l;
|
||||
unsigned long iv;
|
||||
int n;
|
||||
int match = 0;
|
||||
struct per_session_data__ping *psd = user;
|
||||
|
||||
switch (reason) {
|
||||
case LWS_CALLBACK_CLOSED:
|
||||
|
||||
fprintf(stderr, "LWS_CALLBACK_CLOSED on %p\n", (void *)wsi);
|
||||
|
||||
/* remove closed guy */
|
||||
|
||||
for (n = 0; n < clients; n++)
|
||||
if (ping_wsi[n] == wsi) {
|
||||
clients--;
|
||||
while (n < clients) {
|
||||
ping_wsi[n] = ping_wsi[n + 1];
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_CLIENT_ESTABLISHED:
|
||||
|
||||
psd->rx_count = 0;
|
||||
psd->ping_index = 1;
|
||||
psd->ringbuffer_head = 0;
|
||||
psd->ringbuffer_tail = 0;
|
||||
|
||||
/*
|
||||
* start the ball rolling,
|
||||
* LWS_CALLBACK_CLIENT_WRITEABLE will come next service
|
||||
*/
|
||||
|
||||
libwebsocket_callback_on_writable(this, wsi);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_CLIENT_RECEIVE:
|
||||
case LWS_CALLBACK_CLIENT_RECEIVE_PONG:
|
||||
gettimeofday(&tv, NULL);
|
||||
iv = (tv.tv_sec * 1000000) + tv.tv_usec;
|
||||
|
||||
psd->rx_count++;
|
||||
|
||||
shift = 56;
|
||||
p = in;
|
||||
l = 0;
|
||||
|
||||
while (shift >= 0) {
|
||||
l |= (*p++) << shift;
|
||||
shift -= 8;
|
||||
}
|
||||
|
||||
/* find it in the ringbuffer, look backwards from head */
|
||||
n = psd->ringbuffer_head;
|
||||
while (!match) {
|
||||
|
||||
if (psd->ringbuffer[n].index == l) {
|
||||
psd->ringbuffer[n].seen++;
|
||||
match = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (n == psd->ringbuffer_tail) {
|
||||
match = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (n == 0)
|
||||
n = PING_RINGBUFFER_SIZE - 1;
|
||||
else
|
||||
n--;
|
||||
}
|
||||
|
||||
if (match < 1) {
|
||||
|
||||
if (!flood)
|
||||
fprintf(stderr, "%d bytes from %s: req=%ld "
|
||||
"time=(unknown)\n", (int)len, address, l);
|
||||
else
|
||||
fprintf(stderr, "\b \b");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (psd->ringbuffer[n].seen > 1)
|
||||
fprintf(stderr, "DUP! ");
|
||||
|
||||
if ((iv - psd->ringbuffer[n].issue_timestamp) < rtt_min)
|
||||
rtt_min = iv - psd->ringbuffer[n].issue_timestamp;
|
||||
|
||||
if ((iv - psd->ringbuffer[n].issue_timestamp) > rtt_max)
|
||||
rtt_max = iv - psd->ringbuffer[n].issue_timestamp;
|
||||
|
||||
rtt_avg += iv - psd->ringbuffer[n].issue_timestamp;
|
||||
global_rx_count++;
|
||||
|
||||
if (!flood)
|
||||
fprintf(stderr, "%d bytes from %s: req=%ld "
|
||||
"time=%lu.%lums\n", (int)len, address, l,
|
||||
(iv - psd->ringbuffer[n].issue_timestamp) / 1000,
|
||||
((iv - psd->ringbuffer[n].issue_timestamp) / 100) % 10);
|
||||
else
|
||||
fprintf(stderr, "\b \b");
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_CLIENT_WRITEABLE:
|
||||
|
||||
shift = 56;
|
||||
p = &pingbuf[LWS_SEND_BUFFER_PRE_PADDING];
|
||||
|
||||
/* 64-bit ping index in network byte order */
|
||||
|
||||
while (shift >= 0) {
|
||||
*p++ = psd->ping_index >> shift;
|
||||
shift -= 8;
|
||||
}
|
||||
|
||||
while (p - &pingbuf[LWS_SEND_BUFFER_PRE_PADDING] < size)
|
||||
*p++ = 0;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
psd->ringbuffer[psd->ringbuffer_head].issue_timestamp =
|
||||
(tv.tv_sec * 1000000) + tv.tv_usec;
|
||||
psd->ringbuffer[psd->ringbuffer_head].index = psd->ping_index++;
|
||||
psd->ringbuffer[psd->ringbuffer_head].seen = 0;
|
||||
|
||||
if (psd->ringbuffer_head == PING_RINGBUFFER_SIZE - 1)
|
||||
psd->ringbuffer_head = 0;
|
||||
else
|
||||
psd->ringbuffer_head++;
|
||||
|
||||
/* snip any re-used tail so we keep to the ring length */
|
||||
|
||||
if (psd->ringbuffer_tail == psd->ringbuffer_head) {
|
||||
if (psd->ringbuffer_tail == PING_RINGBUFFER_SIZE - 1)
|
||||
psd->ringbuffer_tail = 0;
|
||||
else
|
||||
psd->ringbuffer_tail++;
|
||||
}
|
||||
|
||||
global_tx_count++;
|
||||
|
||||
if (use_mirror)
|
||||
n = libwebsocket_write(wsi,
|
||||
&pingbuf[LWS_SEND_BUFFER_PRE_PADDING],
|
||||
size, write_options | LWS_WRITE_BINARY);
|
||||
else
|
||||
n = libwebsocket_write(wsi,
|
||||
&pingbuf[LWS_SEND_BUFFER_PRE_PADDING],
|
||||
size, write_options | LWS_WRITE_PING);
|
||||
|
||||
if (n < 0)
|
||||
return -1;
|
||||
if (n < size) {
|
||||
lwsl_err("Partial write\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (flood &&
|
||||
(psd->ping_index - psd->rx_count) < (screen_width - 1))
|
||||
fprintf(stderr, ".");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* list of supported protocols and callbacks */
|
||||
|
||||
static struct libwebsocket_protocols protocols[] = {
|
||||
|
||||
{
|
||||
"lws-mirror-protocol",
|
||||
callback_lws_mirror,
|
||||
sizeof (struct per_session_data__ping),
|
||||
},
|
||||
{
|
||||
NULL, NULL, 0/* end of list */
|
||||
}
|
||||
};
|
||||
|
||||
static struct option options[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "debug", required_argument, NULL, 'd' },
|
||||
{ "port", required_argument, NULL, 'p' },
|
||||
{ "ssl", no_argument, NULL, 't' },
|
||||
{ "interval", required_argument, NULL, 'i' },
|
||||
{ "size", required_argument, NULL, 's' },
|
||||
{ "protocol", required_argument, NULL, 'n' },
|
||||
{ "flood", no_argument, NULL, 'f' },
|
||||
{ "mirror", no_argument, NULL, 'm' },
|
||||
{ "replicate", required_argument, NULL, 'r' },
|
||||
{ "killmask", no_argument, NULL, 'k' },
|
||||
{ "version", required_argument, NULL, 'v' },
|
||||
{ NULL, 0, 0, 0 }
|
||||
};
|
||||
|
||||
#ifndef WIN32
|
||||
static void
|
||||
signal_handler(int sig, siginfo_t *si, void *v)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
interrupted_time = (tv.tv_sec * 1000000) + tv.tv_usec;
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int n = 0;
|
||||
int port = 7681;
|
||||
int use_ssl = 0;
|
||||
struct libwebsocket_context *context;
|
||||
char protocol_name[256];
|
||||
char ip[30];
|
||||
#ifndef WIN32
|
||||
struct sigaction sa;
|
||||
struct winsize w;
|
||||
#endif
|
||||
struct timeval tv;
|
||||
unsigned long oldus = 0;
|
||||
unsigned long l;
|
||||
int ietf_version = -1;
|
||||
struct lws_context_creation_info info;
|
||||
|
||||
memset(&info, 0, sizeof info);
|
||||
|
||||
if (argc < 2)
|
||||
goto usage;
|
||||
|
||||
address = argv[1];
|
||||
optind++;
|
||||
|
||||
while (n >= 0) {
|
||||
n = getopt_long(argc, argv, "v:kr:hmfts:n:i:p:d:", options, NULL);
|
||||
if (n < 0)
|
||||
continue;
|
||||
switch (n) {
|
||||
case 'd':
|
||||
lws_set_log_level(atoi(optarg), NULL);
|
||||
break;
|
||||
case 'm':
|
||||
use_mirror = 1;
|
||||
break;
|
||||
case 't':
|
||||
use_ssl = 2; /* 2 = allow selfsigned */
|
||||
break;
|
||||
case 'p':
|
||||
port = atoi(optarg);
|
||||
break;
|
||||
case 'n':
|
||||
strncpy(protocol_name, optarg, sizeof protocol_name);
|
||||
protocol_name[(sizeof protocol_name) - 1] = '\0';
|
||||
protocols[PROTOCOL_LWS_MIRROR].name = protocol_name;
|
||||
break;
|
||||
case 'i':
|
||||
interval_us = 1000000.0 * atof(optarg);
|
||||
break;
|
||||
case 's':
|
||||
size = atoi(optarg);
|
||||
break;
|
||||
case 'f':
|
||||
flood = 1;
|
||||
break;
|
||||
case 'r':
|
||||
clients = atoi(optarg);
|
||||
if (clients > MAX_PING_CLIENTS || clients < 1) {
|
||||
fprintf(stderr, "Max clients supportd = %d\n",
|
||||
MAX_PING_CLIENTS);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'k':
|
||||
write_options = LWS_WRITE_CLIENT_IGNORE_XOR_MASK;
|
||||
break;
|
||||
case 'v':
|
||||
ietf_version = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
goto usage;
|
||||
}
|
||||
}
|
||||
|
||||
if (!use_mirror) {
|
||||
if (size > MAX_PING_PAYLOAD) {
|
||||
fprintf(stderr, "Max ping opcode payload size %d\n",
|
||||
MAX_PING_PAYLOAD);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
if (size > MAX_MIRROR_PAYLOAD) {
|
||||
fprintf(stderr, "Max mirror payload size %d\n",
|
||||
MAX_MIRROR_PAYLOAD);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
if (isatty(STDOUT_FILENO))
|
||||
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1)
|
||||
if (w.ws_col > 0)
|
||||
screen_width = w.ws_col;
|
||||
#endif
|
||||
|
||||
info.port = CONTEXT_PORT_NO_LISTEN;
|
||||
info.protocols = protocols;
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
info.extensions = libwebsocket_get_internal_extensions();
|
||||
#endif
|
||||
info.gid = -1;
|
||||
info.uid = -1;
|
||||
|
||||
context = libwebsocket_create_context(&info);
|
||||
if (context == NULL) {
|
||||
fprintf(stderr, "Creating libwebsocket context failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* create client websockets using dumb increment protocol */
|
||||
|
||||
for (n = 0; n < clients; n++) {
|
||||
ping_wsi[n] = libwebsocket_client_connect(context, address,
|
||||
port, use_ssl, "/", address,
|
||||
"origin", protocols[PROTOCOL_LWS_MIRROR].name,
|
||||
ietf_version);
|
||||
if (ping_wsi[n] == NULL) {
|
||||
fprintf(stderr, "client connection %d failed to "
|
||||
"connect\n", n);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
libwebsockets_get_peer_addresses(context, ping_wsi[0],
|
||||
libwebsocket_get_socket_fd(ping_wsi[0]),
|
||||
peer_name, sizeof peer_name, ip, sizeof ip);
|
||||
|
||||
fprintf(stderr, "Websocket PING %s (%s) %d bytes of data.\n",
|
||||
peer_name, ip, size);
|
||||
|
||||
#ifndef WIN32
|
||||
/* set the ^C handler */
|
||||
sa.sa_sigaction = signal_handler;
|
||||
sa.sa_flags = SA_SIGINFO;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sigaction(SIGINT, &sa, NULL);
|
||||
#endif
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
started = (tv.tv_sec * 1000000) + tv.tv_usec;
|
||||
|
||||
/* service loop */
|
||||
|
||||
n = 0;
|
||||
while (n >= 0) {
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
l = (tv.tv_sec * 1000000) + tv.tv_usec;
|
||||
|
||||
/* servers can hang up on us */
|
||||
|
||||
if (clients == 0) {
|
||||
n = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!interrupted_time) {
|
||||
if ((l - oldus) > interval_us) {
|
||||
for (n = 0; n < clients; n++)
|
||||
libwebsocket_callback_on_writable(
|
||||
context, ping_wsi[n]);
|
||||
oldus = l;
|
||||
}
|
||||
} else
|
||||
|
||||
/* allow time for in-flight pongs to come */
|
||||
|
||||
if ((l - interrupted_time) > 250000) {
|
||||
n = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!interval_us)
|
||||
n = libwebsocket_service(context, 0);
|
||||
else
|
||||
n = libwebsocket_service(context, 1);
|
||||
}
|
||||
|
||||
/* stats */
|
||||
|
||||
fprintf(stderr, "\n--- %s websocket ping statistics "
|
||||
"using %d connections ---\n"
|
||||
"%lu packets transmitted, %lu received, "
|
||||
"%lu%% packet loss, time %ldms\n"
|
||||
"rtt min/avg/max = %0.3f/%0.3f/%0.3f ms\n"
|
||||
"payload bandwidth average %0.3f KiBytes/sec\n",
|
||||
peer_name, clients, global_tx_count, global_rx_count,
|
||||
((global_tx_count - global_rx_count) * 100) / global_tx_count,
|
||||
(l - started) / 1000,
|
||||
((double)rtt_min) / 1000.0,
|
||||
((double)rtt_avg / global_rx_count) / 1000.0,
|
||||
((double)rtt_max) / 1000.0,
|
||||
((double)global_rx_count * (double)size) /
|
||||
((double)(l - started) / 1000000.0) / 1024.0);
|
||||
|
||||
libwebsocket_context_destroy(context);
|
||||
|
||||
return 0;
|
||||
|
||||
usage:
|
||||
fprintf(stderr, "Usage: libwebsockets-test-ping "
|
||||
"<server address> [--port=<p>] "
|
||||
"[--ssl] [--interval=<float sec>] "
|
||||
"[--size=<bytes>] "
|
||||
"[--protocol=<protocolname>] "
|
||||
"[--mirror] "
|
||||
"[--replicate=clients>] "
|
||||
"[--version <version>] "
|
||||
"[-d <log bitfield> ]"
|
||||
"\n");
|
||||
return 1;
|
||||
}
|
||||
968
dependencies/libwebsockets/test-server/test-server.c
vendored
Normal file
968
dependencies/libwebsockets/test-server/test-server.c
vendored
Normal file
@ -0,0 +1,968 @@
|
||||
/*
|
||||
* libwebsockets-test-server - libwebsockets test implementation
|
||||
*
|
||||
* Copyright (C) 2010-2011 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
|
||||
*/
|
||||
#ifdef CMAKE_BUILD
|
||||
#include "lws_config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#ifdef EXTERNAL_POLL
|
||||
#define poll WSAPoll
|
||||
#endif
|
||||
#else
|
||||
#include <syslog.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "../lib/libwebsockets.h"
|
||||
|
||||
static int close_testing;
|
||||
int max_poll_elements;
|
||||
|
||||
struct pollfd *pollfds;
|
||||
int *fd_lookup;
|
||||
int count_pollfds;
|
||||
static volatile int force_exit = 0;
|
||||
static struct libwebsocket_context *context;
|
||||
|
||||
/*
|
||||
* This demo server shows how to use libwebsockets for one or more
|
||||
* websocket protocols in the same server
|
||||
*
|
||||
* It defines the following websocket protocols:
|
||||
*
|
||||
* dumb-increment-protocol: once the socket is opened, an incrementing
|
||||
* ascii string is sent down it every 50ms.
|
||||
* If you send "reset\n" on the websocket, then
|
||||
* the incrementing number is reset to 0.
|
||||
*
|
||||
* lws-mirror-protocol: copies any received packet to every connection also
|
||||
* using this protocol, including the sender
|
||||
*/
|
||||
|
||||
enum demo_protocols {
|
||||
/* always first */
|
||||
PROTOCOL_HTTP = 0,
|
||||
|
||||
PROTOCOL_DUMB_INCREMENT,
|
||||
PROTOCOL_LWS_MIRROR,
|
||||
|
||||
/* always last */
|
||||
DEMO_PROTOCOL_COUNT
|
||||
};
|
||||
|
||||
|
||||
#define LOCAL_RESOURCE_PATH INSTALL_DATADIR"/libwebsockets-test-server"
|
||||
char *resource_path = LOCAL_RESOURCE_PATH;
|
||||
|
||||
/*
|
||||
* We take a strict whitelist approach to stop ../ attacks
|
||||
*/
|
||||
|
||||
struct serveable {
|
||||
const char *urlpath;
|
||||
const char *mimetype;
|
||||
};
|
||||
|
||||
struct per_session_data__http {
|
||||
int fd;
|
||||
};
|
||||
|
||||
/*
|
||||
* this is just an example of parsing handshake headers, you don't need this
|
||||
* in your code unless you will filter allowing connections by the header
|
||||
* content
|
||||
*/
|
||||
|
||||
static void
|
||||
dump_handshake_info(struct libwebsocket *wsi)
|
||||
{
|
||||
int n;
|
||||
static const char *token_names[] = {
|
||||
/*[WSI_TOKEN_GET_URI] =*/ "GET URI",
|
||||
/*[WSI_TOKEN_POST_URI] =*/ "POST URI",
|
||||
/*[WSI_TOKEN_HOST] =*/ "Host",
|
||||
/*[WSI_TOKEN_CONNECTION] =*/ "Connection",
|
||||
/*[WSI_TOKEN_KEY1] =*/ "key 1",
|
||||
/*[WSI_TOKEN_KEY2] =*/ "key 2",
|
||||
/*[WSI_TOKEN_PROTOCOL] =*/ "Protocol",
|
||||
/*[WSI_TOKEN_UPGRADE] =*/ "Upgrade",
|
||||
/*[WSI_TOKEN_ORIGIN] =*/ "Origin",
|
||||
/*[WSI_TOKEN_DRAFT] =*/ "Draft",
|
||||
/*[WSI_TOKEN_CHALLENGE] =*/ "Challenge",
|
||||
|
||||
/* new for 04 */
|
||||
/*[WSI_TOKEN_KEY] =*/ "Key",
|
||||
/*[WSI_TOKEN_VERSION] =*/ "Version",
|
||||
/*[WSI_TOKEN_SWORIGIN] =*/ "Sworigin",
|
||||
|
||||
/* new for 05 */
|
||||
/*[WSI_TOKEN_EXTENSIONS] =*/ "Extensions",
|
||||
|
||||
/* client receives these */
|
||||
/*[WSI_TOKEN_ACCEPT] =*/ "Accept",
|
||||
/*[WSI_TOKEN_NONCE] =*/ "Nonce",
|
||||
/*[WSI_TOKEN_HTTP] =*/ "Http",
|
||||
|
||||
"Accept:",
|
||||
"If-Modified-Since:",
|
||||
"Accept-Encoding:",
|
||||
"Accept-Language:",
|
||||
"Pragma:",
|
||||
"Cache-Control:",
|
||||
"Authorization:",
|
||||
"Cookie:",
|
||||
"Content-Length:",
|
||||
"Content-Type:",
|
||||
"Date:",
|
||||
"Range:",
|
||||
"Referer:",
|
||||
"Uri-Args:",
|
||||
|
||||
/*[WSI_TOKEN_MUXURL] =*/ "MuxURL",
|
||||
};
|
||||
char buf[256];
|
||||
|
||||
for (n = 0; n < sizeof(token_names) / sizeof(token_names[0]); n++) {
|
||||
if (!lws_hdr_total_length(wsi, n))
|
||||
continue;
|
||||
|
||||
lws_hdr_copy(wsi, buf, sizeof buf, n);
|
||||
|
||||
fprintf(stderr, " %s = %s\n", token_names[n], buf);
|
||||
}
|
||||
}
|
||||
|
||||
const char * get_mimetype(const char *file)
|
||||
{
|
||||
int n = strlen(file);
|
||||
|
||||
if (n < 5)
|
||||
return NULL;
|
||||
|
||||
if (!strcmp(&file[n - 4], ".ico"))
|
||||
return "image/x-icon";
|
||||
|
||||
if (!strcmp(&file[n - 4], ".png"))
|
||||
return "image/png";
|
||||
|
||||
if (!strcmp(&file[n - 5], ".html"))
|
||||
return "text/html";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* this protocol server (always the first one) just knows how to do HTTP */
|
||||
|
||||
static int callback_http(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_callback_reasons reason, void *user,
|
||||
void *in, size_t len)
|
||||
{
|
||||
#if 0
|
||||
char client_name[128];
|
||||
char client_ip[128];
|
||||
#endif
|
||||
char buf[256];
|
||||
char leaf_path[1024];
|
||||
char b64[64];
|
||||
struct timeval tv;
|
||||
int n, m;
|
||||
unsigned char *p;
|
||||
char *other_headers;
|
||||
static unsigned char buffer[4096];
|
||||
struct stat stat_buf;
|
||||
struct per_session_data__http *pss =
|
||||
(struct per_session_data__http *)user;
|
||||
const char *mimetype;
|
||||
#ifdef EXTERNAL_POLL
|
||||
struct libwebsocket_pollargs *pa = (struct libwebsocket_pollargs *)in;
|
||||
#endif
|
||||
|
||||
switch (reason) {
|
||||
case LWS_CALLBACK_HTTP:
|
||||
|
||||
dump_handshake_info(wsi);
|
||||
|
||||
if (len < 1) {
|
||||
libwebsockets_return_http_status(context, wsi,
|
||||
HTTP_STATUS_BAD_REQUEST, NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* this server has no concept of directories */
|
||||
if (strchr((const char *)in + 1, '/')) {
|
||||
libwebsockets_return_http_status(context, wsi,
|
||||
HTTP_STATUS_FORBIDDEN, NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* if a legal POST URL, let it continue and accept data */
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI))
|
||||
return 0;
|
||||
|
||||
/* check for the "send a big file by hand" example case */
|
||||
|
||||
if (!strcmp((const char *)in, "/leaf.jpg")) {
|
||||
if (strlen(resource_path) > sizeof(leaf_path) - 10)
|
||||
return -1;
|
||||
sprintf(leaf_path, "%s/leaf.jpg", resource_path);
|
||||
|
||||
/* well, let's demonstrate how to send the hard way */
|
||||
|
||||
p = buffer;
|
||||
|
||||
#ifdef WIN32
|
||||
pss->fd = open(leaf_path, O_RDONLY | _O_BINARY);
|
||||
#else
|
||||
pss->fd = open(leaf_path, O_RDONLY);
|
||||
#endif
|
||||
|
||||
if (pss->fd < 0)
|
||||
return -1;
|
||||
|
||||
fstat(pss->fd, &stat_buf);
|
||||
|
||||
/*
|
||||
* we will send a big jpeg file, but it could be
|
||||
* anything. Set the Content-Type: appropriately
|
||||
* so the browser knows what to do with it.
|
||||
*/
|
||||
|
||||
p += sprintf((char *)p,
|
||||
"HTTP/1.0 200 OK\x0d\x0a"
|
||||
"Server: libwebsockets\x0d\x0a"
|
||||
"Content-Type: image/jpeg\x0d\x0a"
|
||||
"Content-Length: %u\x0d\x0a\x0d\x0a",
|
||||
(unsigned int)stat_buf.st_size);
|
||||
|
||||
/*
|
||||
* send the http headers...
|
||||
* this won't block since it's the first payload sent
|
||||
* on the connection since it was established
|
||||
* (too small for partial)
|
||||
*/
|
||||
|
||||
n = libwebsocket_write(wsi, buffer,
|
||||
p - buffer, LWS_WRITE_HTTP);
|
||||
|
||||
if (n < 0) {
|
||||
close(pss->fd);
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* book us a LWS_CALLBACK_HTTP_WRITEABLE callback
|
||||
*/
|
||||
libwebsocket_callback_on_writable(context, wsi);
|
||||
break;
|
||||
}
|
||||
|
||||
/* if not, send a file the easy way */
|
||||
strcpy(buf, resource_path);
|
||||
if (strcmp(in, "/")) {
|
||||
if (*((const char *)in) != '/')
|
||||
strcat(buf, "/");
|
||||
strncat(buf, in, sizeof(buf) - strlen(resource_path));
|
||||
} else /* default file to serve */
|
||||
strcat(buf, "/test.html");
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
|
||||
/* refuse to serve files we don't understand */
|
||||
mimetype = get_mimetype(buf);
|
||||
if (!mimetype) {
|
||||
lwsl_err("Unknown mimetype for %s\n", buf);
|
||||
libwebsockets_return_http_status(context, wsi,
|
||||
HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE, NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* demostrates how to set a cookie on / */
|
||||
|
||||
other_headers = NULL;
|
||||
if (!strcmp((const char *)in, "/") &&
|
||||
!lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COOKIE)) {
|
||||
/* this isn't very unguessable but it'll do for us */
|
||||
gettimeofday(&tv, NULL);
|
||||
sprintf(b64, "LWS_%u_%u_COOKIE",
|
||||
(unsigned int)tv.tv_sec,
|
||||
(unsigned int)tv.tv_usec);
|
||||
|
||||
sprintf(leaf_path,
|
||||
"Set-Cookie: test=LWS_%u_%u_COOKIE;Max-Age=360000\x0d\x0a",
|
||||
(unsigned int)tv.tv_sec, (unsigned int)tv.tv_usec);
|
||||
other_headers = leaf_path;
|
||||
lwsl_err(other_headers);
|
||||
}
|
||||
|
||||
if (libwebsockets_serve_http_file(context, wsi, buf,
|
||||
mimetype, other_headers))
|
||||
return -1; /* through completion or error, close the socket */
|
||||
|
||||
/*
|
||||
* notice that the sending of the file completes asynchronously,
|
||||
* we'll get a LWS_CALLBACK_HTTP_FILE_COMPLETION callback when
|
||||
* it's done
|
||||
*/
|
||||
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_HTTP_BODY:
|
||||
strncpy(buf, in, 20);
|
||||
buf[20] = '\0';
|
||||
if (len < 20)
|
||||
buf[len] = '\0';
|
||||
|
||||
lwsl_notice("LWS_CALLBACK_HTTP_BODY: %s... len %d\n",
|
||||
(const char *)buf, (int)len);
|
||||
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_HTTP_BODY_COMPLETION:
|
||||
lwsl_notice("LWS_CALLBACK_HTTP_BODY_COMPLETION\n");
|
||||
/* the whole of the sent body arried, close the connection */
|
||||
libwebsockets_return_http_status(context, wsi,
|
||||
HTTP_STATUS_OK, NULL);
|
||||
|
||||
return -1;
|
||||
|
||||
case LWS_CALLBACK_HTTP_FILE_COMPLETION:
|
||||
// lwsl_info("LWS_CALLBACK_HTTP_FILE_COMPLETION seen\n");
|
||||
/* kill the connection after we sent one file */
|
||||
return -1;
|
||||
|
||||
case LWS_CALLBACK_HTTP_WRITEABLE:
|
||||
/*
|
||||
* we can send more of whatever it is we were sending
|
||||
*/
|
||||
|
||||
do {
|
||||
n = read(pss->fd, buffer, sizeof buffer);
|
||||
/* problem reading, close conn */
|
||||
if (n < 0)
|
||||
goto bail;
|
||||
/* sent it all, close conn */
|
||||
if (n == 0)
|
||||
goto flush_bail;
|
||||
/*
|
||||
* because it's HTTP and not websocket, don't need to take
|
||||
* care about pre and postamble
|
||||
*/
|
||||
m = libwebsocket_write(wsi, buffer, n, LWS_WRITE_HTTP);
|
||||
if (m < 0)
|
||||
/* write failed, close conn */
|
||||
goto bail;
|
||||
if (m != n)
|
||||
/* partial write, adjust */
|
||||
lseek(pss->fd, m - n, SEEK_CUR);
|
||||
|
||||
if (m) /* while still active, extend timeout */
|
||||
libwebsocket_set_timeout(wsi,
|
||||
PENDING_TIMEOUT_HTTP_CONTENT, 5);
|
||||
|
||||
} while (!lws_send_pipe_choked(wsi));
|
||||
libwebsocket_callback_on_writable(context, wsi);
|
||||
break;
|
||||
flush_bail:
|
||||
/* true if still partial pending */
|
||||
if (lws_send_pipe_choked(wsi)) {
|
||||
libwebsocket_callback_on_writable(context, wsi);
|
||||
break;
|
||||
}
|
||||
|
||||
bail:
|
||||
close(pss->fd);
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* callback for confirming to continue with client IP appear in
|
||||
* protocol 0 callback since no websocket protocol has been agreed
|
||||
* yet. You can just ignore this if you won't filter on client IP
|
||||
* since the default uhandled callback return is 0 meaning let the
|
||||
* connection continue.
|
||||
*/
|
||||
|
||||
case LWS_CALLBACK_FILTER_NETWORK_CONNECTION:
|
||||
#if 0
|
||||
libwebsockets_get_peer_addresses(context, wsi, (int)(long)in, client_name,
|
||||
sizeof(client_name), client_ip, sizeof(client_ip));
|
||||
|
||||
fprintf(stderr, "Received network connect from %s (%s)\n",
|
||||
client_name, client_ip);
|
||||
#endif
|
||||
/* if we returned non-zero from here, we kill the connection */
|
||||
break;
|
||||
|
||||
#ifdef EXTERNAL_POLL
|
||||
/*
|
||||
* callbacks for managing the external poll() array appear in
|
||||
* protocol 0 callback
|
||||
*/
|
||||
|
||||
case LWS_CALLBACK_LOCK_POLL:
|
||||
/*
|
||||
* lock mutex to protect pollfd state
|
||||
* called before any other POLL related callback
|
||||
*/
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_UNLOCK_POLL:
|
||||
/*
|
||||
* unlock mutex to protect pollfd state when
|
||||
* called after any other POLL related callback
|
||||
*/
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_ADD_POLL_FD:
|
||||
|
||||
if (count_pollfds >= max_poll_elements) {
|
||||
lwsl_err("LWS_CALLBACK_ADD_POLL_FD: too many sockets to track\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
fd_lookup[pa->fd] = count_pollfds;
|
||||
pollfds[count_pollfds].fd = pa->fd;
|
||||
pollfds[count_pollfds].events = pa->events;
|
||||
pollfds[count_pollfds++].revents = 0;
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_DEL_POLL_FD:
|
||||
if (!--count_pollfds)
|
||||
break;
|
||||
m = fd_lookup[pa->fd];
|
||||
/* have the last guy take up the vacant slot */
|
||||
pollfds[m] = pollfds[count_pollfds];
|
||||
fd_lookup[pollfds[count_pollfds].fd] = m;
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_CHANGE_MODE_POLL_FD:
|
||||
pollfds[fd_lookup[pa->fd]].events = pa->events;
|
||||
break;
|
||||
|
||||
#endif
|
||||
|
||||
case LWS_CALLBACK_GET_THREAD_ID:
|
||||
/*
|
||||
* if you will call "libwebsocket_callback_on_writable"
|
||||
* from a different thread, return the caller thread ID
|
||||
* here so lws can use this information to work out if it
|
||||
* should signal the poll() loop to exit and restart early
|
||||
*/
|
||||
|
||||
/* return pthread_getthreadid_np(); */
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* dumb_increment protocol */
|
||||
|
||||
/*
|
||||
* one of these is auto-created for each connection and a pointer to the
|
||||
* appropriate instance is passed to the callback in the user parameter
|
||||
*
|
||||
* for this example protocol we use it to individualize the count for each
|
||||
* connection.
|
||||
*/
|
||||
|
||||
struct per_session_data__dumb_increment {
|
||||
int number;
|
||||
};
|
||||
|
||||
static int
|
||||
callback_dumb_increment(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_callback_reasons reason,
|
||||
void *user, void *in, size_t len)
|
||||
{
|
||||
int n, m;
|
||||
unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 512 +
|
||||
LWS_SEND_BUFFER_POST_PADDING];
|
||||
unsigned char *p = &buf[LWS_SEND_BUFFER_PRE_PADDING];
|
||||
struct per_session_data__dumb_increment *pss = (struct per_session_data__dumb_increment *)user;
|
||||
|
||||
switch (reason) {
|
||||
|
||||
case LWS_CALLBACK_ESTABLISHED:
|
||||
lwsl_info("callback_dumb_increment: "
|
||||
"LWS_CALLBACK_ESTABLISHED\n");
|
||||
pss->number = 0;
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_SERVER_WRITEABLE:
|
||||
n = sprintf((char *)p, "%d", pss->number++);
|
||||
m = libwebsocket_write(wsi, p, n, LWS_WRITE_TEXT);
|
||||
if (m < n) {
|
||||
lwsl_err("ERROR %d writing to di socket\n", n);
|
||||
return -1;
|
||||
}
|
||||
if (close_testing && pss->number == 50) {
|
||||
lwsl_info("close tesing limit, closing\n");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_RECEIVE:
|
||||
// fprintf(stderr, "rx %d\n", (int)len);
|
||||
if (len < 6)
|
||||
break;
|
||||
if (strcmp((const char *)in, "reset\n") == 0)
|
||||
pss->number = 0;
|
||||
break;
|
||||
/*
|
||||
* this just demonstrates how to use the protocol filter. If you won't
|
||||
* study and reject connections based on header content, you don't need
|
||||
* to handle this callback
|
||||
*/
|
||||
|
||||
case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
|
||||
dump_handshake_info(wsi);
|
||||
/* you could return non-zero here and kill the connection */
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* lws-mirror_protocol */
|
||||
|
||||
#define MAX_MESSAGE_QUEUE 32
|
||||
|
||||
struct per_session_data__lws_mirror {
|
||||
struct libwebsocket *wsi;
|
||||
int ringbuffer_tail;
|
||||
};
|
||||
|
||||
struct a_message {
|
||||
void *payload;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
static struct a_message ringbuffer[MAX_MESSAGE_QUEUE];
|
||||
static int ringbuffer_head;
|
||||
|
||||
static int
|
||||
callback_lws_mirror(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_callback_reasons reason,
|
||||
void *user, void *in, size_t len)
|
||||
{
|
||||
int n;
|
||||
struct per_session_data__lws_mirror *pss = (struct per_session_data__lws_mirror *)user;
|
||||
|
||||
switch (reason) {
|
||||
|
||||
case LWS_CALLBACK_ESTABLISHED:
|
||||
lwsl_info("callback_lws_mirror: LWS_CALLBACK_ESTABLISHED\n");
|
||||
pss->ringbuffer_tail = ringbuffer_head;
|
||||
pss->wsi = wsi;
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_PROTOCOL_DESTROY:
|
||||
lwsl_notice("mirror protocol cleaning up\n");
|
||||
for (n = 0; n < sizeof ringbuffer / sizeof ringbuffer[0]; n++)
|
||||
if (ringbuffer[n].payload)
|
||||
free(ringbuffer[n].payload);
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_SERVER_WRITEABLE:
|
||||
if (close_testing)
|
||||
break;
|
||||
while (pss->ringbuffer_tail != ringbuffer_head) {
|
||||
|
||||
n = libwebsocket_write(wsi, (unsigned char *)
|
||||
ringbuffer[pss->ringbuffer_tail].payload +
|
||||
LWS_SEND_BUFFER_PRE_PADDING,
|
||||
ringbuffer[pss->ringbuffer_tail].len,
|
||||
LWS_WRITE_TEXT);
|
||||
if (n < 0) {
|
||||
lwsl_err("ERROR %d writing to mirror socket\n", n);
|
||||
return -1;
|
||||
}
|
||||
if (n < ringbuffer[pss->ringbuffer_tail].len)
|
||||
lwsl_err("mirror partial write %d vs %d\n",
|
||||
n, ringbuffer[pss->ringbuffer_tail].len);
|
||||
|
||||
if (pss->ringbuffer_tail == (MAX_MESSAGE_QUEUE - 1))
|
||||
pss->ringbuffer_tail = 0;
|
||||
else
|
||||
pss->ringbuffer_tail++;
|
||||
|
||||
if (((ringbuffer_head - pss->ringbuffer_tail) &
|
||||
(MAX_MESSAGE_QUEUE - 1)) == (MAX_MESSAGE_QUEUE - 15))
|
||||
libwebsocket_rx_flow_allow_all_protocol(
|
||||
libwebsockets_get_protocol(wsi));
|
||||
|
||||
// lwsl_debug("tx fifo %d\n", (ringbuffer_head - pss->ringbuffer_tail) & (MAX_MESSAGE_QUEUE - 1));
|
||||
|
||||
if (lws_send_pipe_choked(wsi)) {
|
||||
libwebsocket_callback_on_writable(context, wsi);
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* for tests with chrome on same machine as client and
|
||||
* server, this is needed to stop chrome choking
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
Sleep(1);
|
||||
#else
|
||||
usleep(1);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_RECEIVE:
|
||||
|
||||
if (((ringbuffer_head - pss->ringbuffer_tail) &
|
||||
(MAX_MESSAGE_QUEUE - 1)) == (MAX_MESSAGE_QUEUE - 1)) {
|
||||
lwsl_err("dropping!\n");
|
||||
goto choke;
|
||||
}
|
||||
|
||||
if (ringbuffer[ringbuffer_head].payload)
|
||||
free(ringbuffer[ringbuffer_head].payload);
|
||||
|
||||
ringbuffer[ringbuffer_head].payload =
|
||||
malloc(LWS_SEND_BUFFER_PRE_PADDING + len +
|
||||
LWS_SEND_BUFFER_POST_PADDING);
|
||||
ringbuffer[ringbuffer_head].len = len;
|
||||
memcpy((char *)ringbuffer[ringbuffer_head].payload +
|
||||
LWS_SEND_BUFFER_PRE_PADDING, in, len);
|
||||
if (ringbuffer_head == (MAX_MESSAGE_QUEUE - 1))
|
||||
ringbuffer_head = 0;
|
||||
else
|
||||
ringbuffer_head++;
|
||||
|
||||
if (((ringbuffer_head - pss->ringbuffer_tail) &
|
||||
(MAX_MESSAGE_QUEUE - 1)) != (MAX_MESSAGE_QUEUE - 2))
|
||||
goto done;
|
||||
|
||||
choke:
|
||||
lwsl_debug("LWS_CALLBACK_RECEIVE: throttling %p\n", wsi);
|
||||
libwebsocket_rx_flow_control(wsi, 0);
|
||||
|
||||
// lwsl_debug("rx fifo %d\n", (ringbuffer_head - pss->ringbuffer_tail) & (MAX_MESSAGE_QUEUE - 1));
|
||||
done:
|
||||
libwebsocket_callback_on_writable_all_protocol(
|
||||
libwebsockets_get_protocol(wsi));
|
||||
break;
|
||||
|
||||
/*
|
||||
* this just demonstrates how to use the protocol filter. If you won't
|
||||
* study and reject connections based on header content, you don't need
|
||||
* to handle this callback
|
||||
*/
|
||||
|
||||
case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
|
||||
dump_handshake_info(wsi);
|
||||
/* you could return non-zero here and kill the connection */
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* list of supported protocols and callbacks */
|
||||
|
||||
static struct libwebsocket_protocols protocols[] = {
|
||||
/* first protocol must always be HTTP handler */
|
||||
|
||||
{
|
||||
"http-only", /* name */
|
||||
callback_http, /* callback */
|
||||
sizeof (struct per_session_data__http), /* per_session_data_size */
|
||||
0, /* max frame size / rx buffer */
|
||||
},
|
||||
{
|
||||
"dumb-increment-protocol",
|
||||
callback_dumb_increment,
|
||||
sizeof(struct per_session_data__dumb_increment),
|
||||
10,
|
||||
},
|
||||
{
|
||||
"lws-mirror-protocol",
|
||||
callback_lws_mirror,
|
||||
sizeof(struct per_session_data__lws_mirror),
|
||||
128,
|
||||
},
|
||||
{ NULL, NULL, 0, 0 } /* terminator */
|
||||
};
|
||||
|
||||
void sighandler(int sig)
|
||||
{
|
||||
force_exit = 1;
|
||||
libwebsocket_cancel_service(context);
|
||||
}
|
||||
|
||||
static struct option options[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "debug", required_argument, NULL, 'd' },
|
||||
{ "port", required_argument, NULL, 'p' },
|
||||
{ "ssl", no_argument, NULL, 's' },
|
||||
{ "allow-non-ssl", no_argument, NULL, 'a' },
|
||||
{ "interface", required_argument, NULL, 'i' },
|
||||
{ "closetest", no_argument, NULL, 'c' },
|
||||
{ "libev", no_argument, NULL, 'e' },
|
||||
#ifndef LWS_NO_DAEMONIZE
|
||||
{ "daemonize", no_argument, NULL, 'D' },
|
||||
#endif
|
||||
{ "resource_path", required_argument, NULL, 'r' },
|
||||
{ NULL, 0, 0, 0 }
|
||||
};
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char cert_path[1024];
|
||||
char key_path[1024];
|
||||
int n = 0;
|
||||
int use_ssl = 0;
|
||||
int opts = 0;
|
||||
char interface_name[128] = "";
|
||||
const char *iface = NULL;
|
||||
#ifndef WIN32
|
||||
int syslog_options = LOG_PID | LOG_PERROR;
|
||||
#endif
|
||||
unsigned int ms, oldms = 0;
|
||||
struct lws_context_creation_info info;
|
||||
|
||||
int debug_level = 7;
|
||||
#ifndef LWS_NO_DAEMONIZE
|
||||
int daemonize = 0;
|
||||
#endif
|
||||
|
||||
memset(&info, 0, sizeof info);
|
||||
info.port = 7681;
|
||||
|
||||
while (n >= 0) {
|
||||
n = getopt_long(argc, argv, "eci:hsap:d:Dr:", options, NULL);
|
||||
if (n < 0)
|
||||
continue;
|
||||
switch (n) {
|
||||
case 'e':
|
||||
opts |= LWS_SERVER_OPTION_LIBEV;
|
||||
break;
|
||||
#ifndef LWS_NO_DAEMONIZE
|
||||
case 'D':
|
||||
daemonize = 1;
|
||||
#ifndef WIN32
|
||||
syslog_options &= ~LOG_PERROR;
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
case 'd':
|
||||
debug_level = atoi(optarg);
|
||||
break;
|
||||
case 's':
|
||||
use_ssl = 1;
|
||||
break;
|
||||
case 'a':
|
||||
opts |= LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT;
|
||||
break;
|
||||
case 'p':
|
||||
info.port = atoi(optarg);
|
||||
break;
|
||||
case 'i':
|
||||
strncpy(interface_name, optarg, sizeof interface_name);
|
||||
interface_name[(sizeof interface_name) - 1] = '\0';
|
||||
iface = interface_name;
|
||||
break;
|
||||
case 'c':
|
||||
close_testing = 1;
|
||||
fprintf(stderr, " Close testing mode -- closes on "
|
||||
"client after 50 dumb increments"
|
||||
"and suppresses lws_mirror spam\n");
|
||||
break;
|
||||
case 'r':
|
||||
resource_path = optarg;
|
||||
printf("Setting resource path to \"%s\"\n", resource_path);
|
||||
break;
|
||||
case 'h':
|
||||
fprintf(stderr, "Usage: test-server "
|
||||
"[--port=<p>] [--ssl] "
|
||||
"[-d <log bitfield>] "
|
||||
"[--resource_path <path>]\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(LWS_NO_DAEMONIZE) && !defined(WIN32)
|
||||
/*
|
||||
* normally lock path would be /var/lock/lwsts or similar, to
|
||||
* simplify getting started without having to take care about
|
||||
* permissions or running as root, set to /tmp/.lwsts-lock
|
||||
*/
|
||||
if (daemonize && lws_daemonize("/tmp/.lwsts-lock")) {
|
||||
fprintf(stderr, "Failed to daemonize\n");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
signal(SIGINT, sighandler);
|
||||
|
||||
#ifndef WIN32
|
||||
/* we will only try to log things according to our debug_level */
|
||||
setlogmask(LOG_UPTO (LOG_DEBUG));
|
||||
openlog("lwsts", syslog_options, LOG_DAEMON);
|
||||
#endif
|
||||
|
||||
/* tell the library what debug level to emit and to send it to syslog */
|
||||
lws_set_log_level(debug_level, lwsl_emit_syslog);
|
||||
|
||||
lwsl_notice("libwebsockets test server - "
|
||||
"(C) Copyright 2010-2013 Andy Green <andy@warmcat.com> - "
|
||||
"licensed under LGPL2.1\n");
|
||||
#ifdef EXTERNAL_POLL
|
||||
max_poll_elements = getdtablesize();
|
||||
pollfds = malloc(max_poll_elements * sizeof (struct pollfd));
|
||||
fd_lookup = malloc(max_poll_elements * sizeof (int));
|
||||
if (pollfds == NULL || fd_lookup == NULL) {
|
||||
lwsl_err("Out of memory pollfds=%d\n", max_poll_elements);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
info.iface = iface;
|
||||
info.protocols = protocols;
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
info.extensions = libwebsocket_get_internal_extensions();
|
||||
#endif
|
||||
if (!use_ssl) {
|
||||
info.ssl_cert_filepath = NULL;
|
||||
info.ssl_private_key_filepath = NULL;
|
||||
} else {
|
||||
if (strlen(resource_path) > sizeof(cert_path) - 32) {
|
||||
lwsl_err("resource path too long\n");
|
||||
return -1;
|
||||
}
|
||||
sprintf(cert_path, "%s/libwebsockets-test-server.pem",
|
||||
resource_path);
|
||||
if (strlen(resource_path) > sizeof(key_path) - 32) {
|
||||
lwsl_err("resource path too long\n");
|
||||
return -1;
|
||||
}
|
||||
sprintf(key_path, "%s/libwebsockets-test-server.key.pem",
|
||||
resource_path);
|
||||
|
||||
info.ssl_cert_filepath = cert_path;
|
||||
info.ssl_private_key_filepath = key_path;
|
||||
}
|
||||
info.gid = -1;
|
||||
info.uid = -1;
|
||||
info.options = opts;
|
||||
|
||||
context = libwebsocket_create_context(&info);
|
||||
if (context == NULL) {
|
||||
lwsl_err("libwebsocket init failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
n = 0;
|
||||
while (n >= 0 && !force_exit) {
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
/*
|
||||
* This provokes the LWS_CALLBACK_SERVER_WRITEABLE for every
|
||||
* live websocket connection using the DUMB_INCREMENT protocol,
|
||||
* as soon as it can take more packets (usually immediately)
|
||||
*/
|
||||
|
||||
ms = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
|
||||
if ((ms - oldms) > 50) {
|
||||
libwebsocket_callback_on_writable_all_protocol(&protocols[PROTOCOL_DUMB_INCREMENT]);
|
||||
oldms = ms;
|
||||
}
|
||||
|
||||
#ifdef EXTERNAL_POLL
|
||||
|
||||
/*
|
||||
* this represents an existing server's single poll action
|
||||
* which also includes libwebsocket sockets
|
||||
*/
|
||||
|
||||
n = poll(pollfds, count_pollfds, 50);
|
||||
if (n < 0)
|
||||
continue;
|
||||
|
||||
|
||||
if (n)
|
||||
for (n = 0; n < count_pollfds; n++)
|
||||
if (pollfds[n].revents)
|
||||
/*
|
||||
* returns immediately if the fd does not
|
||||
* match anything under libwebsockets
|
||||
* control
|
||||
*/
|
||||
if (libwebsocket_service_fd(context,
|
||||
&pollfds[n]) < 0)
|
||||
goto done;
|
||||
#else
|
||||
/*
|
||||
* If libwebsockets sockets are all we care about,
|
||||
* you can use this api which takes care of the poll()
|
||||
* and looping through finding who needed service.
|
||||
*
|
||||
* If no socket needs service, it'll return anyway after
|
||||
* the number of ms in the second argument.
|
||||
*/
|
||||
|
||||
n = libwebsocket_service(context, 50);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef EXTERNAL_POLL
|
||||
done:
|
||||
#endif
|
||||
|
||||
libwebsocket_context_destroy(context);
|
||||
|
||||
lwsl_notice("libwebsockets-test-server exited cleanly\n");
|
||||
|
||||
#ifndef WIN32
|
||||
closelog();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
398
dependencies/libwebsockets/test-server/test.html
vendored
Normal file
398
dependencies/libwebsockets/test-server/test.html
vendored
Normal file
@ -0,0 +1,398 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset=utf-8 http-equiv="Content-Language" content="en"/>
|
||||
<title>Minimal Websocket test app</title>
|
||||
<style type="text/css">
|
||||
div.title { font-size:18pt; font: Arial; font-weight:normal; text-align:center; color:#000000; }
|
||||
.browser { font-size:18pt; font: Arial; font-weight:normal; text-align:center; color:#ffff00; vertical-align:middle; text-align:center; background:#d0b070; padding:12px; -webkit-border-radius:10px; -moz-border-radius:10px; border-radius:10px;}
|
||||
.group2 { width:600px; vertical-align:middle; text-align:center; background:#f0f0e0; padding:12px; -webkit-border-radius:10px; -moz-border-radius:10px; border-radius:10px; }
|
||||
.explain { vertical-align:middle; text-align:center; background:#f0f0c0; padding:12px; -webkit-border-radius:10px; -moz-border-radius:10px; border-radius:10px; color:#404000; }
|
||||
.content { vertical-align:top; text-align:center; background:#fffff0; padding:12px; -webkit-border-radius:10px; -moz-border-radius:10px; border-radius:10px; }
|
||||
.canvas { vertical-align:top; text-align:center; background:#efefd0; padding:12px; -webkit-border-radius:10px; -moz-border-radius:10px; border-radius:10px; }
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header></header>
|
||||
<article>
|
||||
|
||||
<table><tr><td>
|
||||
|
||||
<table width="100%"><tr><td valign=middle align=center><a href="http://libwebsockets.org"><img src="/libwebsockets.org-logo.png"></a></td><td>
|
||||
<section class="browser">Detected Browser: <div id=brow>...</div></section></td></tr></table>
|
||||
|
||||
</td></tr><tr><td>
|
||||
|
||||
<section id="increment" class="group2">
|
||||
<div class="title">libwebsockets "dumb-increment-protocol"</div>
|
||||
<table><tr><td>
|
||||
<table class="content" width="200px">
|
||||
<tr><td align=center><input type=button id=offset value="Reset counter" onclick="reset();" ></td></tr>
|
||||
<tr><td width=200px align=center><div id=number> </div></td></tr>
|
||||
<tr><td id=wsdi_statustd align=center class="explain"><div id=wsdi_status>Not initialized</div></td></tr>
|
||||
</tr>
|
||||
</table>
|
||||
</td><td class="explain">
|
||||
The incrementing number is coming from the server and is individual for
|
||||
each connection to the server... try opening a second browser window.
|
||||
<br/><br/>
|
||||
The button zeros just this connection's number.
|
||||
<br/><br/>
|
||||
Click <a href="/leaf.jpg" target="_blank">Here</a> to have the test server send a big picture by http.
|
||||
</td></tr></table>
|
||||
</section>
|
||||
<br>
|
||||
<section id="mirror" class="group2">
|
||||
<div class="title">libwebsockets "lws-mirror-protocol"</div>
|
||||
<div class="explain">
|
||||
Use the mouse to draw on the canvas below -- all other browser windows open
|
||||
on this page see your drawing in realtime and you can see any of theirs as
|
||||
well.
|
||||
<br/><br/>
|
||||
The lws-mirror protocol doesn't interpret what is being sent to it, it just
|
||||
re-sends it to every other websocket it has a connection with using that
|
||||
protocol, including the guy who sent the packet.
|
||||
<br/><br/>
|
||||
<b>libwebsockets-test-client</b> joins in by spamming circles on to this shared canvas when
|
||||
run.
|
||||
</div>
|
||||
<table class="content">
|
||||
<tr>
|
||||
<td>Drawing color:
|
||||
<select id="color" onchange="update_color();">
|
||||
<option value=#000000>Black</option>
|
||||
<option value=#0000ff>Blue</option>
|
||||
<option value=#20ff20>Green</option>
|
||||
<option value=#802020>Dark Red</option>
|
||||
</select>
|
||||
</td>
|
||||
<td id=wslm_statustd align=center class="explain"><div id=wslm_status>Not initialized</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan=2 width=500 class="content">
|
||||
<div id="wslm_drawing">
|
||||
</div></td>
|
||||
</tr>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
</td></tr><tr><td>
|
||||
Looking for support? <a href="http://libwebsockets.org">http://libwebsockets.org</a><br/>
|
||||
Join the mailing list: <a href="http://ml.libwebsockets.org/mailman/listinfo/libwebsockets">http://ml.libwebsockets.org/mailman/listinfo/libwebsockets</a>
|
||||
|
||||
</td></tr></table>
|
||||
|
||||
</article>
|
||||
|
||||
<script>
|
||||
|
||||
/* BrowserDetect came from http://www.quirksmode.org/js/detect.html */
|
||||
|
||||
var BrowserDetect = {
|
||||
init: function () {
|
||||
this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
|
||||
this.version = this.searchVersion(navigator.userAgent)
|
||||
|| this.searchVersion(navigator.appVersion)
|
||||
|| "an unknown version";
|
||||
this.OS = this.searchString(this.dataOS) || "an unknown OS";
|
||||
},
|
||||
searchString: function (data) {
|
||||
for (var i=0;i<data.length;i++) {
|
||||
var dataString = data[i].string;
|
||||
var dataProp = data[i].prop;
|
||||
this.versionSearchString = data[i].versionSearch || data[i].identity;
|
||||
if (dataString) {
|
||||
if (dataString.indexOf(data[i].subString) != -1)
|
||||
return data[i].identity;
|
||||
}
|
||||
else if (dataProp)
|
||||
return data[i].identity;
|
||||
}
|
||||
},
|
||||
searchVersion: function (dataString) {
|
||||
var index = dataString.indexOf(this.versionSearchString);
|
||||
if (index == -1) return;
|
||||
return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
|
||||
},
|
||||
dataBrowser: [
|
||||
{
|
||||
string: navigator.userAgent,
|
||||
subString: "Chrome",
|
||||
identity: "Chrome"
|
||||
},
|
||||
{ string: navigator.userAgent,
|
||||
subString: "OmniWeb",
|
||||
versionSearch: "OmniWeb/",
|
||||
identity: "OmniWeb"
|
||||
},
|
||||
{
|
||||
string: navigator.vendor,
|
||||
subString: "Apple",
|
||||
identity: "Safari",
|
||||
versionSearch: "Version"
|
||||
},
|
||||
{
|
||||
prop: window.opera,
|
||||
identity: "Opera",
|
||||
versionSearch: "Version"
|
||||
},
|
||||
{
|
||||
string: navigator.vendor,
|
||||
subString: "iCab",
|
||||
identity: "iCab"
|
||||
},
|
||||
{
|
||||
string: navigator.vendor,
|
||||
subString: "KDE",
|
||||
identity: "Konqueror"
|
||||
},
|
||||
{
|
||||
string: navigator.userAgent,
|
||||
subString: "Firefox",
|
||||
identity: "Firefox"
|
||||
},
|
||||
{
|
||||
string: navigator.vendor,
|
||||
subString: "Camino",
|
||||
identity: "Camino"
|
||||
},
|
||||
{ // for newer Netscapes (6+)
|
||||
string: navigator.userAgent,
|
||||
subString: "Netscape",
|
||||
identity: "Netscape"
|
||||
},
|
||||
{
|
||||
string: navigator.userAgent,
|
||||
subString: "MSIE",
|
||||
identity: "Explorer",
|
||||
versionSearch: "MSIE"
|
||||
},
|
||||
{
|
||||
string: navigator.userAgent,
|
||||
subString: "Gecko",
|
||||
identity: "Mozilla",
|
||||
versionSearch: "rv"
|
||||
},
|
||||
{ // for older Netscapes (4-)
|
||||
string: navigator.userAgent,
|
||||
subString: "Mozilla",
|
||||
identity: "Netscape",
|
||||
versionSearch: "Mozilla"
|
||||
}
|
||||
],
|
||||
dataOS : [
|
||||
{
|
||||
string: navigator.platform,
|
||||
subString: "Win",
|
||||
identity: "Windows"
|
||||
},
|
||||
{
|
||||
string: navigator.platform,
|
||||
subString: "Mac",
|
||||
identity: "Mac"
|
||||
},
|
||||
{
|
||||
string: navigator.userAgent,
|
||||
subString: "iPhone",
|
||||
identity: "iPhone/iPod"
|
||||
},
|
||||
{
|
||||
string: navigator.platform,
|
||||
subString: "Linux",
|
||||
identity: "Linux"
|
||||
}
|
||||
]
|
||||
|
||||
};
|
||||
BrowserDetect.init();
|
||||
|
||||
document.getElementById("brow").textContent = " " + BrowserDetect.browser + " "
|
||||
+ BrowserDetect.version +" " + BrowserDetect.OS +" ";
|
||||
|
||||
var pos = 0;
|
||||
|
||||
function get_appropriate_ws_url()
|
||||
{
|
||||
var pcol;
|
||||
var u = document.URL;
|
||||
|
||||
/*
|
||||
* We open the websocket encrypted if this page came on an
|
||||
* https:// url itself, otherwise unencrypted
|
||||
*/
|
||||
|
||||
if (u.substring(0, 5) == "https") {
|
||||
pcol = "wss://";
|
||||
u = u.substr(8);
|
||||
} else {
|
||||
pcol = "ws://";
|
||||
if (u.substring(0, 4) == "http")
|
||||
u = u.substr(7);
|
||||
}
|
||||
|
||||
u = u.split('/');
|
||||
|
||||
/* + "/xxx" bit is for IE10 workaround */
|
||||
|
||||
return pcol + u[0] + "/xxx";
|
||||
}
|
||||
|
||||
|
||||
document.getElementById("number").textContent = get_appropriate_ws_url();
|
||||
|
||||
/* dumb increment protocol */
|
||||
|
||||
var socket_di;
|
||||
|
||||
if (typeof MozWebSocket != "undefined") {
|
||||
socket_di = new MozWebSocket(get_appropriate_ws_url(),
|
||||
"dumb-increment-protocol");
|
||||
} else {
|
||||
socket_di = new WebSocket(get_appropriate_ws_url(),
|
||||
"dumb-increment-protocol");
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
socket_di.onopen = function() {
|
||||
document.getElementById("wsdi_statustd").style.backgroundColor = "#40ff40";
|
||||
document.getElementById("wsdi_status").textContent = " websocket connection opened ";
|
||||
}
|
||||
|
||||
socket_di.onmessage =function got_packet(msg) {
|
||||
document.getElementById("number").textContent = msg.data + "\n";
|
||||
}
|
||||
|
||||
socket_di.onclose = function(){
|
||||
document.getElementById("wsdi_statustd").style.backgroundColor = "#ff4040";
|
||||
document.getElementById("wsdi_status").textContent = " websocket connection CLOSED ";
|
||||
}
|
||||
} catch(exception) {
|
||||
alert('<p>Error' + exception);
|
||||
}
|
||||
|
||||
function reset() {
|
||||
socket_di.send("reset\n");
|
||||
}
|
||||
|
||||
|
||||
/* lws-mirror protocol */
|
||||
|
||||
var down = 0;
|
||||
var no_last = 1;
|
||||
var last_x = 0, last_y = 0;
|
||||
var ctx;
|
||||
var socket_lm;
|
||||
var color = "#000000";
|
||||
|
||||
if (typeof MozWebSocket != "undefined") {
|
||||
socket_lm = new MozWebSocket(get_appropriate_ws_url(),
|
||||
"lws-mirror-protocol");
|
||||
} else {
|
||||
socket_lm = new WebSocket(get_appropriate_ws_url(),
|
||||
"lws-mirror-protocol");
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
socket_lm.onopen = function() {
|
||||
document.getElementById("wslm_statustd").style.backgroundColor = "#40ff40";
|
||||
document.getElementById("wslm_status").textContent = " websocket connection opened ";
|
||||
}
|
||||
|
||||
socket_lm.onmessage =function got_packet(msg) {
|
||||
j = msg.data.split(';');
|
||||
f = 0;
|
||||
while (f < j.length - 1) {
|
||||
i = j[f].split(' ');
|
||||
if (i[0] == 'd') {
|
||||
ctx.strokeStyle = i[1];
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(+(i[2]), +(i[3]));
|
||||
ctx.lineTo(+(i[4]), +(i[5]));
|
||||
ctx.stroke();
|
||||
}
|
||||
if (i[0] == 'c') {
|
||||
ctx.strokeStyle = i[1];
|
||||
ctx.beginPath();
|
||||
ctx.arc(+(i[2]), +(i[3]), +(i[4]), 0, Math.PI*2, true);
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
f++;
|
||||
}
|
||||
}
|
||||
|
||||
socket_lm.onclose = function(){
|
||||
document.getElementById("wslm_statustd").style.backgroundColor = "#ff4040";
|
||||
document.getElementById("wslm_status").textContent = " websocket connection CLOSED ";
|
||||
}
|
||||
} catch(exception) {
|
||||
alert('<p>Error' + exception);
|
||||
}
|
||||
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.height = 300;
|
||||
canvas.width = 480;
|
||||
ctx = canvas.getContext("2d");
|
||||
|
||||
document.getElementById('wslm_drawing').appendChild(canvas);
|
||||
|
||||
canvas.addEventListener('mousemove', ev_mousemove, false);
|
||||
canvas.addEventListener('mousedown', ev_mousedown, false);
|
||||
canvas.addEventListener('mouseup', ev_mouseup, false);
|
||||
|
||||
offsetX = offsetY = 0;
|
||||
element = canvas;
|
||||
if (element.offsetParent) {
|
||||
do {
|
||||
offsetX += element.offsetLeft;
|
||||
offsetY += element.offsetTop;
|
||||
} while ((element = element.offsetParent));
|
||||
}
|
||||
|
||||
function update_color() {
|
||||
color = document.getElementById("color").value;
|
||||
}
|
||||
|
||||
function ev_mousedown (ev) {
|
||||
down = 1;
|
||||
}
|
||||
|
||||
function ev_mouseup(ev) {
|
||||
down = 0;
|
||||
no_last = 1;
|
||||
}
|
||||
|
||||
function ev_mousemove (ev) {
|
||||
var x, y;
|
||||
|
||||
if (ev.offsetX) {
|
||||
x = ev.offsetX;
|
||||
y = ev.offsetY;
|
||||
} else {
|
||||
x = ev.layerX - offsetX;
|
||||
y = ev.layerY - offsetY;
|
||||
|
||||
}
|
||||
|
||||
if (!down)
|
||||
return;
|
||||
if (no_last) {
|
||||
no_last = 0;
|
||||
last_x = x;
|
||||
last_y = y;
|
||||
return;
|
||||
}
|
||||
socket_lm.send("d " + color + " " + last_x + " " + last_y + " " + x + ' ' + y + ';');
|
||||
|
||||
last_x = x;
|
||||
last_y = y;
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
153
dependencies/libwebsockets/win32port/win32helpers/getopt.c
vendored
Normal file
153
dependencies/libwebsockets/win32port/win32helpers/getopt.c
vendored
Normal file
@ -0,0 +1,153 @@
|
||||
/* $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 */
|
||||
}
|
||||
|
||||
33
dependencies/libwebsockets/win32port/win32helpers/getopt.h
vendored
Normal file
33
dependencies/libwebsockets/win32port/win32helpers/getopt.h
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
#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__ */
|
||||
237
dependencies/libwebsockets/win32port/win32helpers/getopt_long.c
vendored
Normal file
237
dependencies/libwebsockets/win32port/win32helpers/getopt_long.c
vendored
Normal file
@ -0,0 +1,237 @@
|
||||
|
||||
/*
|
||||
* 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"
|
||||
|
||||
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 = has_equal - current_argv;
|
||||
has_equal++;
|
||||
} else
|
||||
current_argv_len = 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);
|
||||
}
|
||||
52
dependencies/libwebsockets/win32port/win32helpers/gettimeofday.c
vendored
Normal file
52
dependencies/libwebsockets/win32port/win32helpers/gettimeofday.c
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
#include <time.h>
|
||||
#include <windows.h> //I've ommited context line
|
||||
|
||||
#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
|
||||
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
|
||||
#else
|
||||
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
|
||||
#endif
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#else
|
||||
#ifdef __MINGW64__
|
||||
#else
|
||||
struct timezone
|
||||
{
|
||||
int tz_minuteswest; /* minutes W of Greenwich */
|
||||
int tz_dsttime; /* type of dst correction */
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
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;
|
||||
}
|
||||
31
dependencies/libwebsockets/win32port/win32helpers/gettimeofday.h
vendored
Normal file
31
dependencies/libwebsockets/win32port/win32helpers/gettimeofday.h
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef _GET_TIME_OF_DAY_H
|
||||
#define _GET_TIME_OF_DAY_H
|
||||
|
||||
#ifdef __MINGW64__
|
||||
#else
|
||||
#ifdef __MINGW32__
|
||||
#else
|
||||
#include < time.h >
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <windows.h> //I've ommited context line.
|
||||
#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
|
||||
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
|
||||
#else
|
||||
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
|
||||
#endif
|
||||
|
||||
#ifndef _TIMEZONE_DEFINED
|
||||
struct timezone
|
||||
{
|
||||
int tz_minuteswest; /* minutes W of Greenwich */
|
||||
int tz_dsttime; /* type of dst correction */
|
||||
};
|
||||
|
||||
int gettimeofday(struct timeval *tv, struct timezone *tz);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
374
dependencies/libwebsockets/win32port/zlib/ZLib.vcxproj
vendored
Normal file
374
dependencies/libwebsockets/win32port/zlib/ZLib.vcxproj
vendored
Normal file
@ -0,0 +1,374 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug static|Win32">
|
||||
<Configuration>Debug static</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release DLL|Win32">
|
||||
<Configuration>Release DLL</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release DLL|x64">
|
||||
<Configuration>Release DLL</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release static|Win32">
|
||||
<Configuration>Release static</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{4156FC56-8443-2973-4FE2-A0BB2C621525}</ProjectGuid>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseOfMfc>false</UseOfMfc>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseOfMfc>false</UseOfMfc>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug static|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug static|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release static|Win32'">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug static|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug static|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>DebugV10\</OutDir>
|
||||
<IntDir>DebugV10\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug static|Win32'">
|
||||
<OutDir>$(SolutionDir)..\output\</OutDir>
|
||||
<IntDir>DebugV10\</IntDir>
|
||||
<TargetName>ZLib_vc100-mt-sgd</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutDir>DebugV10\</OutDir>
|
||||
<IntDir>DebugV10\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug static|x64'">
|
||||
<OutDir>DebugV10\</OutDir>
|
||||
<IntDir>DebugV10\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<IntDir>.\Release\</IntDir>
|
||||
<OutDir>.\Release\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<OutDir>.\Release\</OutDir>
|
||||
<IntDir>.\Release\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release static|Win32'">
|
||||
<OutDir>$(SolutionDir)..\output\</OutDir>
|
||||
<TargetName>ZLib_vc100-mt-s</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">
|
||||
<OutDir>$(SolutionDir)..\output\</OutDir>
|
||||
<TargetName>ZLib_vc100-mt-s</TargetName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<InlineFunctionExpansion>Default</InlineFunctionExpansion>
|
||||
<FunctionLevelLinking>false</FunctionLevelLinking>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AssemblerListingLocation>DebugV10\</AssemblerListingLocation>
|
||||
<PrecompiledHeaderOutputFile>DebugV10\ZLib.pch</PrecompiledHeaderOutputFile>
|
||||
<ObjectFileName>DebugV10\</ObjectFileName>
|
||||
<ProgramDataBaseFileName>DebugV10\</ProgramDataBaseFileName>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<ForceConformanceInForLoopScope>false</ForceConformanceInForLoopScope>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
</ClCompile>
|
||||
<ResourceCompile>
|
||||
<Culture>0x1c09</Culture>
|
||||
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
<Bscmake>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<OutputFile>DebugV10\ZLib.bsc</OutputFile>
|
||||
</Bscmake>
|
||||
<Lib>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<OutputFile>DebugV10\ZLib.lib</OutputFile>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug static|Win32'">
|
||||
<ClCompile>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<InlineFunctionExpansion>Default</InlineFunctionExpansion>
|
||||
<FunctionLevelLinking>false</FunctionLevelLinking>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AssemblerListingLocation>DebugV10\</AssemblerListingLocation>
|
||||
<PrecompiledHeaderOutputFile>DebugV10\ZLib.pch</PrecompiledHeaderOutputFile>
|
||||
<ObjectFileName>DebugV10\</ObjectFileName>
|
||||
<ProgramDataBaseFileName>DebugV10\</ProgramDataBaseFileName>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<ForceConformanceInForLoopScope>false</ForceConformanceInForLoopScope>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
</ClCompile>
|
||||
<ResourceCompile>
|
||||
<Culture>0x1c09</Culture>
|
||||
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
<Bscmake>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<OutputFile>DebugV10\ZLib.bsc</OutputFile>
|
||||
</Bscmake>
|
||||
<Lib>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<OutputFile>$(OutDir)ZLib_vc100-mt-sgd.lib</OutputFile>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<InlineFunctionExpansion>Default</InlineFunctionExpansion>
|
||||
<FunctionLevelLinking>false</FunctionLevelLinking>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AssemblerListingLocation>DebugV10\</AssemblerListingLocation>
|
||||
<PrecompiledHeaderOutputFile>DebugV10\ZLib.pch</PrecompiledHeaderOutputFile>
|
||||
<ObjectFileName>DebugV10\</ObjectFileName>
|
||||
<ProgramDataBaseFileName>DebugV10\</ProgramDataBaseFileName>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<ForceConformanceInForLoopScope>false</ForceConformanceInForLoopScope>
|
||||
</ClCompile>
|
||||
<ResourceCompile>
|
||||
<Culture>0x1c09</Culture>
|
||||
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
<Bscmake>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<OutputFile>DebugV10\ZLib.bsc</OutputFile>
|
||||
</Bscmake>
|
||||
<Lib>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<OutputFile>DebugV10\ZLib.lib</OutputFile>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug static|x64'">
|
||||
<ClCompile>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<InlineFunctionExpansion>Default</InlineFunctionExpansion>
|
||||
<FunctionLevelLinking>false</FunctionLevelLinking>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AssemblerListingLocation>DebugV10\</AssemblerListingLocation>
|
||||
<PrecompiledHeaderOutputFile>DebugV10\ZLib.pch</PrecompiledHeaderOutputFile>
|
||||
<ObjectFileName>DebugV10\</ObjectFileName>
|
||||
<ProgramDataBaseFileName>DebugV10\</ProgramDataBaseFileName>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<ForceConformanceInForLoopScope>false</ForceConformanceInForLoopScope>
|
||||
</ClCompile>
|
||||
<ResourceCompile>
|
||||
<Culture>0x1c09</Culture>
|
||||
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
<Bscmake>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<OutputFile>DebugV10\ZLib.bsc</OutputFile>
|
||||
</Bscmake>
|
||||
<Lib>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<OutputFile>DebugV10\ZLib.lib</OutputFile>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||
<StringPooling>true</StringPooling>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AssemblerListingLocation>.\Release\</AssemblerListingLocation>
|
||||
<PrecompiledHeaderOutputFile>.\Release\ZLib.pch</PrecompiledHeaderOutputFile>
|
||||
<ObjectFileName>.\Release\</ObjectFileName>
|
||||
<ProgramDataBaseFileName>.\Release\</ProgramDataBaseFileName>
|
||||
<ForceConformanceInForLoopScope>false</ForceConformanceInForLoopScope>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
</ClCompile>
|
||||
<ResourceCompile>
|
||||
<Culture>0x1c09</Culture>
|
||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
<Bscmake>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<OutputFile>.\Release\ZLib.bsc</OutputFile>
|
||||
</Bscmake>
|
||||
<Lib>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<OutputFile>.\Release\ZLib.lib</OutputFile>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||
<StringPooling>true</StringPooling>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AssemblerListingLocation>.\Release\</AssemblerListingLocation>
|
||||
<PrecompiledHeaderOutputFile>.\Release\ZLib.pch</PrecompiledHeaderOutputFile>
|
||||
<ObjectFileName>.\Release\</ObjectFileName>
|
||||
<ProgramDataBaseFileName>.\Release\</ProgramDataBaseFileName>
|
||||
<ForceConformanceInForLoopScope>false</ForceConformanceInForLoopScope>
|
||||
</ClCompile>
|
||||
<ResourceCompile>
|
||||
<Culture>0x1c09</Culture>
|
||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
<Bscmake>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<OutputFile>.\Release\ZLib.bsc</OutputFile>
|
||||
</Bscmake>
|
||||
<Lib>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<OutputFile>.\Release\ZLib.lib</OutputFile>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release static|Win32'">
|
||||
<Lib>
|
||||
<OutputFile>$(OutDir)ZLib_vc100-mt-s.lib</OutputFile>
|
||||
</Lib>
|
||||
<ClCompile>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release DLL|Win32'">
|
||||
<Lib>
|
||||
<OutputFile>$(OutDir)ZLib_vc100-mt-s.lib</OutputFile>
|
||||
<LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>
|
||||
</Lib>
|
||||
<ClCompile>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<PreprocessorDefinitions>WIN32</PreprocessorDefinitions>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="adler32.c" />
|
||||
<ClCompile Include="compress.c" />
|
||||
<ClCompile Include="crc32.c" />
|
||||
<ClCompile Include="deflate.c" />
|
||||
<ClCompile Include="gzclose.c" />
|
||||
<ClCompile Include="gzlib.c" />
|
||||
<ClCompile Include="gzread.c" />
|
||||
<ClCompile Include="gzwrite.c" />
|
||||
<ClCompile Include="infback.c" />
|
||||
<ClCompile Include="inffast.c" />
|
||||
<ClCompile Include="inflate.c" />
|
||||
<ClCompile Include="inftrees.c" />
|
||||
<ClCompile Include="trees.c" />
|
||||
<ClCompile Include="uncompr.c" />
|
||||
<ClCompile Include="zutil.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="crc32.h" />
|
||||
<ClInclude Include="deflate.h" />
|
||||
<ClInclude Include="gzguts.h" />
|
||||
<ClInclude Include="inffast.h" />
|
||||
<ClInclude Include="inffixed.h" />
|
||||
<ClInclude Include="inflate.h" />
|
||||
<ClInclude Include="inftrees.h" />
|
||||
<ClInclude Include="trees.h" />
|
||||
<ClInclude Include="zconf.h" />
|
||||
<ClInclude Include="zlib.h" />
|
||||
<ClInclude Include="zutil.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
95
dependencies/libwebsockets/win32port/zlib/ZLib.vcxproj.filters
vendored
Normal file
95
dependencies/libwebsockets/win32port/zlib/ZLib.vcxproj.filters
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{2e5deede-b2ef-40bd-950a-a7f7f0fc0413}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{85d35343-9068-43e8-875e-60b528a03c9b}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="adler32.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="compress.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="crc32.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="deflate.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="inffast.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="inflate.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="inftrees.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="trees.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="uncompr.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="zutil.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gzlib.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gzread.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gzwrite.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gzclose.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="infback.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="deflate.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="inffast.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="inffixed.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="inftrees.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="trees.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="zconf.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="zlib.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="zutil.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gzguts.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="inflate.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="crc32.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
169
dependencies/libwebsockets/win32port/zlib/adler32.c
vendored
Normal file
169
dependencies/libwebsockets/win32port/zlib/adler32.c
vendored
Normal file
@ -0,0 +1,169 @@
|
||||
/* adler32.c -- compute the Adler-32 checksum of a data stream
|
||||
* Copyright (C) 1995-2007 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#include "zutil.h"
|
||||
|
||||
#define local static
|
||||
|
||||
local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2);
|
||||
|
||||
#define BASE 65521UL /* largest prime smaller than 65536 */
|
||||
#define NMAX 5552
|
||||
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
|
||||
|
||||
#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
|
||||
#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
|
||||
#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
|
||||
#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
|
||||
#define DO16(buf) DO8(buf,0); DO8(buf,8);
|
||||
|
||||
/* use NO_DIVIDE if your processor does not do division in hardware */
|
||||
#ifdef NO_DIVIDE
|
||||
# define MOD(a) \
|
||||
do { \
|
||||
if (a >= (BASE << 16)) a -= (BASE << 16); \
|
||||
if (a >= (BASE << 15)) a -= (BASE << 15); \
|
||||
if (a >= (BASE << 14)) a -= (BASE << 14); \
|
||||
if (a >= (BASE << 13)) a -= (BASE << 13); \
|
||||
if (a >= (BASE << 12)) a -= (BASE << 12); \
|
||||
if (a >= (BASE << 11)) a -= (BASE << 11); \
|
||||
if (a >= (BASE << 10)) a -= (BASE << 10); \
|
||||
if (a >= (BASE << 9)) a -= (BASE << 9); \
|
||||
if (a >= (BASE << 8)) a -= (BASE << 8); \
|
||||
if (a >= (BASE << 7)) a -= (BASE << 7); \
|
||||
if (a >= (BASE << 6)) a -= (BASE << 6); \
|
||||
if (a >= (BASE << 5)) a -= (BASE << 5); \
|
||||
if (a >= (BASE << 4)) a -= (BASE << 4); \
|
||||
if (a >= (BASE << 3)) a -= (BASE << 3); \
|
||||
if (a >= (BASE << 2)) a -= (BASE << 2); \
|
||||
if (a >= (BASE << 1)) a -= (BASE << 1); \
|
||||
if (a >= BASE) a -= BASE; \
|
||||
} while (0)
|
||||
# define MOD4(a) \
|
||||
do { \
|
||||
if (a >= (BASE << 4)) a -= (BASE << 4); \
|
||||
if (a >= (BASE << 3)) a -= (BASE << 3); \
|
||||
if (a >= (BASE << 2)) a -= (BASE << 2); \
|
||||
if (a >= (BASE << 1)) a -= (BASE << 1); \
|
||||
if (a >= BASE) a -= BASE; \
|
||||
} while (0)
|
||||
#else
|
||||
# define MOD(a) a %= BASE
|
||||
# define MOD4(a) a %= BASE
|
||||
#endif
|
||||
|
||||
/* ========================================================================= */
|
||||
uLong ZEXPORT adler32(adler, buf, len)
|
||||
uLong adler;
|
||||
const Bytef *buf;
|
||||
uInt len;
|
||||
{
|
||||
unsigned long sum2;
|
||||
unsigned n;
|
||||
|
||||
/* split Adler-32 into component sums */
|
||||
sum2 = (adler >> 16) & 0xffff;
|
||||
adler &= 0xffff;
|
||||
|
||||
/* in case user likes doing a byte at a time, keep it fast */
|
||||
if (len == 1) {
|
||||
adler += buf[0];
|
||||
if (adler >= BASE)
|
||||
adler -= BASE;
|
||||
sum2 += adler;
|
||||
if (sum2 >= BASE)
|
||||
sum2 -= BASE;
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
/* initial Adler-32 value (deferred check for len == 1 speed) */
|
||||
if (buf == Z_NULL)
|
||||
return 1L;
|
||||
|
||||
/* in case short lengths are provided, keep it somewhat fast */
|
||||
if (len < 16) {
|
||||
while (len--) {
|
||||
adler += *buf++;
|
||||
sum2 += adler;
|
||||
}
|
||||
if (adler >= BASE)
|
||||
adler -= BASE;
|
||||
MOD4(sum2); /* only added so many BASE's */
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
/* do length NMAX blocks -- requires just one modulo operation */
|
||||
while (len >= NMAX) {
|
||||
len -= NMAX;
|
||||
n = NMAX / 16; /* NMAX is divisible by 16 */
|
||||
do {
|
||||
DO16(buf); /* 16 sums unrolled */
|
||||
buf += 16;
|
||||
} while (--n);
|
||||
MOD(adler);
|
||||
MOD(sum2);
|
||||
}
|
||||
|
||||
/* do remaining bytes (less than NMAX, still just one modulo) */
|
||||
if (len) { /* avoid modulos if none remaining */
|
||||
while (len >= 16) {
|
||||
len -= 16;
|
||||
DO16(buf);
|
||||
buf += 16;
|
||||
}
|
||||
while (len--) {
|
||||
adler += *buf++;
|
||||
sum2 += adler;
|
||||
}
|
||||
MOD(adler);
|
||||
MOD(sum2);
|
||||
}
|
||||
|
||||
/* return recombined sums */
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
local uLong adler32_combine_(adler1, adler2, len2)
|
||||
uLong adler1;
|
||||
uLong adler2;
|
||||
z_off64_t len2;
|
||||
{
|
||||
unsigned long sum1;
|
||||
unsigned long sum2;
|
||||
unsigned rem;
|
||||
|
||||
/* the derivation of this formula is left as an exercise for the reader */
|
||||
rem = (unsigned)(len2 % BASE);
|
||||
sum1 = adler1 & 0xffff;
|
||||
sum2 = rem * sum1;
|
||||
MOD(sum2);
|
||||
sum1 += (adler2 & 0xffff) + BASE - 1;
|
||||
sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
|
||||
if (sum1 >= BASE) sum1 -= BASE;
|
||||
if (sum1 >= BASE) sum1 -= BASE;
|
||||
if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1);
|
||||
if (sum2 >= BASE) sum2 -= BASE;
|
||||
return sum1 | (sum2 << 16);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
uLong ZEXPORT adler32_combine(adler1, adler2, len2)
|
||||
uLong adler1;
|
||||
uLong adler2;
|
||||
z_off_t len2;
|
||||
{
|
||||
return adler32_combine_(adler1, adler2, len2);
|
||||
}
|
||||
|
||||
uLong ZEXPORT adler32_combine64(adler1, adler2, len2)
|
||||
uLong adler1;
|
||||
uLong adler2;
|
||||
z_off64_t len2;
|
||||
{
|
||||
return adler32_combine_(adler1, adler2, len2);
|
||||
}
|
||||
80
dependencies/libwebsockets/win32port/zlib/compress.c
vendored
Normal file
80
dependencies/libwebsockets/win32port/zlib/compress.c
vendored
Normal file
@ -0,0 +1,80 @@
|
||||
/* compress.c -- compress a memory buffer
|
||||
* Copyright (C) 1995-2005 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#define ZLIB_INTERNAL
|
||||
#include "zlib.h"
|
||||
|
||||
/* ===========================================================================
|
||||
Compresses the source buffer into the destination buffer. The level
|
||||
parameter has the same meaning as in deflateInit. sourceLen is the byte
|
||||
length of the source buffer. Upon entry, destLen is the total size of the
|
||||
destination buffer, which must be at least 0.1% larger than sourceLen plus
|
||||
12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
|
||||
|
||||
compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
|
||||
memory, Z_BUF_ERROR if there was not enough room in the output buffer,
|
||||
Z_STREAM_ERROR if the level parameter is invalid.
|
||||
*/
|
||||
int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
|
||||
Bytef *dest;
|
||||
uLongf *destLen;
|
||||
const Bytef *source;
|
||||
uLong sourceLen;
|
||||
int level;
|
||||
{
|
||||
z_stream stream;
|
||||
int err;
|
||||
|
||||
stream.next_in = (Bytef*)source;
|
||||
stream.avail_in = (uInt)sourceLen;
|
||||
#ifdef MAXSEG_64K
|
||||
/* Check for source > 64K on 16-bit machine: */
|
||||
if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
|
||||
#endif
|
||||
stream.next_out = dest;
|
||||
stream.avail_out = (uInt)*destLen;
|
||||
if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
|
||||
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
stream.opaque = (voidpf)0;
|
||||
|
||||
err = deflateInit(&stream, level);
|
||||
if (err != Z_OK) return err;
|
||||
|
||||
err = deflate(&stream, Z_FINISH);
|
||||
if (err != Z_STREAM_END) {
|
||||
deflateEnd(&stream);
|
||||
return err == Z_OK ? Z_BUF_ERROR : err;
|
||||
}
|
||||
*destLen = stream.total_out;
|
||||
|
||||
err = deflateEnd(&stream);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
*/
|
||||
int ZEXPORT compress (dest, destLen, source, sourceLen)
|
||||
Bytef *dest;
|
||||
uLongf *destLen;
|
||||
const Bytef *source;
|
||||
uLong sourceLen;
|
||||
{
|
||||
return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
If the default memLevel or windowBits for deflateInit() is changed, then
|
||||
this function needs to be updated.
|
||||
*/
|
||||
uLong ZEXPORT compressBound (sourceLen)
|
||||
uLong sourceLen;
|
||||
{
|
||||
return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
|
||||
(sourceLen >> 25) + 13;
|
||||
}
|
||||
442
dependencies/libwebsockets/win32port/zlib/crc32.c
vendored
Normal file
442
dependencies/libwebsockets/win32port/zlib/crc32.c
vendored
Normal file
@ -0,0 +1,442 @@
|
||||
/* crc32.c -- compute the CRC-32 of a data stream
|
||||
* Copyright (C) 1995-2006, 2010 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*
|
||||
* Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
|
||||
* CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
|
||||
* tables for updating the shift register in one step with three exclusive-ors
|
||||
* instead of four steps with four exclusive-ors. This results in about a
|
||||
* factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
/*
|
||||
Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
|
||||
protection on the static variables used to control the first-use generation
|
||||
of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
|
||||
first call get_crc_table() to initialize the tables before allowing more than
|
||||
one thread to use crc32().
|
||||
*/
|
||||
|
||||
#ifdef MAKECRCH
|
||||
# include <stdio.h>
|
||||
# ifndef DYNAMIC_CRC_TABLE
|
||||
# define DYNAMIC_CRC_TABLE
|
||||
# endif /* !DYNAMIC_CRC_TABLE */
|
||||
#endif /* MAKECRCH */
|
||||
|
||||
#include "zutil.h" /* for STDC and FAR definitions */
|
||||
|
||||
#define local static
|
||||
|
||||
/* Find a four-byte integer type for crc32_little() and crc32_big(). */
|
||||
#ifndef NOBYFOUR
|
||||
# ifdef STDC /* need ANSI C limits.h to determine sizes */
|
||||
# include <limits.h>
|
||||
# define BYFOUR
|
||||
# if (UINT_MAX == 0xffffffffUL)
|
||||
typedef unsigned int u4;
|
||||
# else
|
||||
# if (ULONG_MAX == 0xffffffffUL)
|
||||
typedef unsigned long u4;
|
||||
# else
|
||||
# if (USHRT_MAX == 0xffffffffUL)
|
||||
typedef unsigned short u4;
|
||||
# else
|
||||
# undef BYFOUR /* can't find a four-byte integer type! */
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# endif /* STDC */
|
||||
#endif /* !NOBYFOUR */
|
||||
|
||||
/* Definitions for doing the crc four data bytes at a time. */
|
||||
#ifdef BYFOUR
|
||||
# define REV(w) ((((w)>>24)&0xff)+(((w)>>8)&0xff00)+ \
|
||||
(((w)&0xff00)<<8)+(((w)&0xff)<<24))
|
||||
local unsigned long crc32_little OF((unsigned long,
|
||||
const unsigned char FAR *, unsigned));
|
||||
local unsigned long crc32_big OF((unsigned long,
|
||||
const unsigned char FAR *, unsigned));
|
||||
# define TBLS 8
|
||||
#else
|
||||
# define TBLS 1
|
||||
#endif /* BYFOUR */
|
||||
|
||||
/* Local functions for crc concatenation */
|
||||
local unsigned long gf2_matrix_times OF((unsigned long *mat,
|
||||
unsigned long vec));
|
||||
local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
|
||||
local uLong crc32_combine_(uLong crc1, uLong crc2, z_off64_t len2);
|
||||
|
||||
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
|
||||
local volatile int crc_table_empty = 1;
|
||||
local unsigned long FAR crc_table[TBLS][256];
|
||||
local void make_crc_table OF((void));
|
||||
#ifdef MAKECRCH
|
||||
local void write_table OF((FILE *, const unsigned long FAR *));
|
||||
#endif /* MAKECRCH */
|
||||
/*
|
||||
Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
|
||||
x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
|
||||
|
||||
Polynomials over GF(2) are represented in binary, one bit per coefficient,
|
||||
with the lowest powers in the most significant bit. Then adding polynomials
|
||||
is just exclusive-or, and multiplying a polynomial by x is a right shift by
|
||||
one. If we call the above polynomial p, and represent a byte as the
|
||||
polynomial q, also with the lowest power in the most significant bit (so the
|
||||
byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
|
||||
where a mod b means the remainder after dividing a by b.
|
||||
|
||||
This calculation is done using the shift-register method of multiplying and
|
||||
taking the remainder. The register is initialized to zero, and for each
|
||||
incoming bit, x^32 is added mod p to the register if the bit is a one (where
|
||||
x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
|
||||
x (which is shifting right by one and adding x^32 mod p if the bit shifted
|
||||
out is a one). We start with the highest power (least significant bit) of
|
||||
q and repeat for all eight bits of q.
|
||||
|
||||
The first table is simply the CRC of all possible eight bit values. This is
|
||||
all the information needed to generate CRCs on data a byte at a time for all
|
||||
combinations of CRC register values and incoming bytes. The remaining tables
|
||||
allow for word-at-a-time CRC calculation for both big-endian and little-
|
||||
endian machines, where a word is four bytes.
|
||||
*/
|
||||
local void make_crc_table()
|
||||
{
|
||||
unsigned long c;
|
||||
int n, k;
|
||||
unsigned long poly; /* polynomial exclusive-or pattern */
|
||||
/* terms of polynomial defining this crc (except x^32): */
|
||||
static volatile int first = 1; /* flag to limit concurrent making */
|
||||
static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
|
||||
|
||||
/* See if another task is already doing this (not thread-safe, but better
|
||||
than nothing -- significantly reduces duration of vulnerability in
|
||||
case the advice about DYNAMIC_CRC_TABLE is ignored) */
|
||||
if (first) {
|
||||
first = 0;
|
||||
|
||||
/* make exclusive-or pattern from polynomial (0xedb88320UL) */
|
||||
poly = 0UL;
|
||||
for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++)
|
||||
poly |= 1UL << (31 - p[n]);
|
||||
|
||||
/* generate a crc for every 8-bit value */
|
||||
for (n = 0; n < 256; n++) {
|
||||
c = (unsigned long)n;
|
||||
for (k = 0; k < 8; k++)
|
||||
c = c & 1 ? poly ^ (c >> 1) : c >> 1;
|
||||
crc_table[0][n] = c;
|
||||
}
|
||||
|
||||
#ifdef BYFOUR
|
||||
/* generate crc for each value followed by one, two, and three zeros,
|
||||
and then the byte reversal of those as well as the first table */
|
||||
for (n = 0; n < 256; n++) {
|
||||
c = crc_table[0][n];
|
||||
crc_table[4][n] = REV(c);
|
||||
for (k = 1; k < 4; k++) {
|
||||
c = crc_table[0][c & 0xff] ^ (c >> 8);
|
||||
crc_table[k][n] = c;
|
||||
crc_table[k + 4][n] = REV(c);
|
||||
}
|
||||
}
|
||||
#endif /* BYFOUR */
|
||||
|
||||
crc_table_empty = 0;
|
||||
}
|
||||
else { /* not first */
|
||||
/* wait for the other guy to finish (not efficient, but rare) */
|
||||
while (crc_table_empty)
|
||||
;
|
||||
}
|
||||
|
||||
#ifdef MAKECRCH
|
||||
/* write out CRC tables to crc32.h */
|
||||
{
|
||||
FILE *out;
|
||||
|
||||
out = fopen("crc32.h", "w");
|
||||
if (out == NULL) return;
|
||||
fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
|
||||
fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
|
||||
fprintf(out, "local const unsigned long FAR ");
|
||||
fprintf(out, "crc_table[TBLS][256] =\n{\n {\n");
|
||||
write_table(out, crc_table[0]);
|
||||
# ifdef BYFOUR
|
||||
fprintf(out, "#ifdef BYFOUR\n");
|
||||
for (k = 1; k < 8; k++) {
|
||||
fprintf(out, " },\n {\n");
|
||||
write_table(out, crc_table[k]);
|
||||
}
|
||||
fprintf(out, "#endif\n");
|
||||
# endif /* BYFOUR */
|
||||
fprintf(out, " }\n};\n");
|
||||
fclose(out);
|
||||
}
|
||||
#endif /* MAKECRCH */
|
||||
}
|
||||
|
||||
#ifdef MAKECRCH
|
||||
local void write_table(out, table)
|
||||
FILE *out;
|
||||
const unsigned long FAR *table;
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; n < 256; n++)
|
||||
fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n],
|
||||
n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
|
||||
}
|
||||
#endif /* MAKECRCH */
|
||||
|
||||
#else /* !DYNAMIC_CRC_TABLE */
|
||||
/* ========================================================================
|
||||
* Tables of CRC-32s of all single-byte values, made by make_crc_table().
|
||||
*/
|
||||
#include "crc32.h"
|
||||
#endif /* DYNAMIC_CRC_TABLE */
|
||||
|
||||
/* =========================================================================
|
||||
* This function can be used by asm versions of crc32()
|
||||
*/
|
||||
const unsigned long FAR * ZEXPORT get_crc_table()
|
||||
{
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
if (crc_table_empty)
|
||||
make_crc_table();
|
||||
#endif /* DYNAMIC_CRC_TABLE */
|
||||
return (const unsigned long FAR *)crc_table;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
|
||||
#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
|
||||
|
||||
/* ========================================================================= */
|
||||
unsigned long ZEXPORT crc32(crc, buf, len)
|
||||
unsigned long crc;
|
||||
const unsigned char FAR *buf;
|
||||
uInt len;
|
||||
{
|
||||
if (buf == Z_NULL) return 0UL;
|
||||
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
if (crc_table_empty)
|
||||
make_crc_table();
|
||||
#endif /* DYNAMIC_CRC_TABLE */
|
||||
|
||||
#ifdef BYFOUR
|
||||
if (sizeof(void *) == sizeof(ptrdiff_t)) {
|
||||
u4 endian;
|
||||
|
||||
endian = 1;
|
||||
if (*((unsigned char *)(&endian)))
|
||||
return crc32_little(crc, buf, len);
|
||||
else
|
||||
return crc32_big(crc, buf, len);
|
||||
}
|
||||
#endif /* BYFOUR */
|
||||
crc = crc ^ 0xffffffffUL;
|
||||
while (len >= 8) {
|
||||
DO8;
|
||||
len -= 8;
|
||||
}
|
||||
if (len) do {
|
||||
DO1;
|
||||
} while (--len);
|
||||
return crc ^ 0xffffffffUL;
|
||||
}
|
||||
|
||||
#ifdef BYFOUR
|
||||
|
||||
/* ========================================================================= */
|
||||
#define DOLIT4 c ^= *buf4++; \
|
||||
c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
|
||||
crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
|
||||
#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
|
||||
|
||||
/* ========================================================================= */
|
||||
local unsigned long crc32_little(crc, buf, len)
|
||||
unsigned long crc;
|
||||
const unsigned char FAR *buf;
|
||||
unsigned len;
|
||||
{
|
||||
register u4 c;
|
||||
register const u4 FAR *buf4;
|
||||
|
||||
c = (u4)crc;
|
||||
c = ~c;
|
||||
while (len && ((ptrdiff_t)buf & 3)) {
|
||||
c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
|
||||
len--;
|
||||
}
|
||||
|
||||
buf4 = (const u4 FAR *)(const void FAR *)buf;
|
||||
while (len >= 32) {
|
||||
DOLIT32;
|
||||
len -= 32;
|
||||
}
|
||||
while (len >= 4) {
|
||||
DOLIT4;
|
||||
len -= 4;
|
||||
}
|
||||
buf = (const unsigned char FAR *)buf4;
|
||||
|
||||
if (len) do {
|
||||
c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
|
||||
} while (--len);
|
||||
c = ~c;
|
||||
return (unsigned long)c;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
#define DOBIG4 c ^= *++buf4; \
|
||||
c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
|
||||
crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
|
||||
#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
|
||||
|
||||
/* ========================================================================= */
|
||||
local unsigned long crc32_big(crc, buf, len)
|
||||
unsigned long crc;
|
||||
const unsigned char FAR *buf;
|
||||
unsigned len;
|
||||
{
|
||||
register u4 c;
|
||||
register const u4 FAR *buf4;
|
||||
|
||||
c = REV((u4)crc);
|
||||
c = ~c;
|
||||
while (len && ((ptrdiff_t)buf & 3)) {
|
||||
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
|
||||
len--;
|
||||
}
|
||||
|
||||
buf4 = (const u4 FAR *)(const void FAR *)buf;
|
||||
buf4--;
|
||||
while (len >= 32) {
|
||||
DOBIG32;
|
||||
len -= 32;
|
||||
}
|
||||
while (len >= 4) {
|
||||
DOBIG4;
|
||||
len -= 4;
|
||||
}
|
||||
buf4++;
|
||||
buf = (const unsigned char FAR *)buf4;
|
||||
|
||||
if (len) do {
|
||||
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
|
||||
} while (--len);
|
||||
c = ~c;
|
||||
return (unsigned long)(REV(c));
|
||||
}
|
||||
|
||||
#endif /* BYFOUR */
|
||||
|
||||
#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */
|
||||
|
||||
/* ========================================================================= */
|
||||
local unsigned long gf2_matrix_times(mat, vec)
|
||||
unsigned long *mat;
|
||||
unsigned long vec;
|
||||
{
|
||||
unsigned long sum;
|
||||
|
||||
sum = 0;
|
||||
while (vec) {
|
||||
if (vec & 1)
|
||||
sum ^= *mat;
|
||||
vec >>= 1;
|
||||
mat++;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
local void gf2_matrix_square(square, mat)
|
||||
unsigned long *square;
|
||||
unsigned long *mat;
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; n < GF2_DIM; n++)
|
||||
square[n] = gf2_matrix_times(mat, mat[n]);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
local uLong crc32_combine_(crc1, crc2, len2)
|
||||
uLong crc1;
|
||||
uLong crc2;
|
||||
z_off64_t len2;
|
||||
{
|
||||
int n;
|
||||
unsigned long row;
|
||||
unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */
|
||||
unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */
|
||||
|
||||
/* degenerate case (also disallow negative lengths) */
|
||||
if (len2 <= 0)
|
||||
return crc1;
|
||||
|
||||
/* put operator for one zero bit in odd */
|
||||
odd[0] = 0xedb88320UL; /* CRC-32 polynomial */
|
||||
row = 1;
|
||||
for (n = 1; n < GF2_DIM; n++) {
|
||||
odd[n] = row;
|
||||
row <<= 1;
|
||||
}
|
||||
|
||||
/* put operator for two zero bits in even */
|
||||
gf2_matrix_square(even, odd);
|
||||
|
||||
/* put operator for four zero bits in odd */
|
||||
gf2_matrix_square(odd, even);
|
||||
|
||||
/* apply len2 zeros to crc1 (first square will put the operator for one
|
||||
zero byte, eight zero bits, in even) */
|
||||
do {
|
||||
/* apply zeros operator for this bit of len2 */
|
||||
gf2_matrix_square(even, odd);
|
||||
if (len2 & 1)
|
||||
crc1 = gf2_matrix_times(even, crc1);
|
||||
len2 >>= 1;
|
||||
|
||||
/* if no more bits set, then done */
|
||||
if (len2 == 0)
|
||||
break;
|
||||
|
||||
/* another iteration of the loop with odd and even swapped */
|
||||
gf2_matrix_square(odd, even);
|
||||
if (len2 & 1)
|
||||
crc1 = gf2_matrix_times(odd, crc1);
|
||||
len2 >>= 1;
|
||||
|
||||
/* if no more bits set, then done */
|
||||
} while (len2 != 0);
|
||||
|
||||
/* return combined crc */
|
||||
crc1 ^= crc2;
|
||||
return crc1;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
uLong ZEXPORT crc32_combine(crc1, crc2, len2)
|
||||
uLong crc1;
|
||||
uLong crc2;
|
||||
z_off_t len2;
|
||||
{
|
||||
return crc32_combine_(crc1, crc2, len2);
|
||||
}
|
||||
|
||||
uLong ZEXPORT crc32_combine64(crc1, crc2, len2)
|
||||
uLong crc1;
|
||||
uLong crc2;
|
||||
z_off64_t len2;
|
||||
{
|
||||
return crc32_combine_(crc1, crc2, len2);
|
||||
}
|
||||
441
dependencies/libwebsockets/win32port/zlib/crc32.h
vendored
Normal file
441
dependencies/libwebsockets/win32port/zlib/crc32.h
vendored
Normal file
@ -0,0 +1,441 @@
|
||||
/* crc32.h -- tables for rapid CRC calculation
|
||||
* Generated automatically by crc32.c
|
||||
*/
|
||||
|
||||
local const unsigned long FAR crc_table[TBLS][256] =
|
||||
{
|
||||
{
|
||||
0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
|
||||
0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
|
||||
0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
|
||||
0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
|
||||
0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
|
||||
0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
|
||||
0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
|
||||
0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
|
||||
0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
|
||||
0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
|
||||
0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
|
||||
0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
|
||||
0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
|
||||
0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
|
||||
0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
|
||||
0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
|
||||
0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
|
||||
0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
|
||||
0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
|
||||
0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
|
||||
0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
|
||||
0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
|
||||
0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
|
||||
0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
|
||||
0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
|
||||
0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
|
||||
0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
|
||||
0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
|
||||
0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
|
||||
0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
|
||||
0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
|
||||
0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
|
||||
0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
|
||||
0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
|
||||
0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
|
||||
0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
|
||||
0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
|
||||
0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
|
||||
0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
|
||||
0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
|
||||
0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
|
||||
0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
|
||||
0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
|
||||
0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
|
||||
0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
|
||||
0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
|
||||
0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
|
||||
0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
|
||||
0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
|
||||
0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
|
||||
0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
|
||||
0x2d02ef8dUL
|
||||
#ifdef BYFOUR
|
||||
},
|
||||
{
|
||||
0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL,
|
||||
0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL,
|
||||
0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL,
|
||||
0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL,
|
||||
0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL,
|
||||
0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL,
|
||||
0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL,
|
||||
0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL,
|
||||
0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL,
|
||||
0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL,
|
||||
0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL,
|
||||
0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL,
|
||||
0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL,
|
||||
0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL,
|
||||
0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL,
|
||||
0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL,
|
||||
0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL,
|
||||
0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL,
|
||||
0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL,
|
||||
0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL,
|
||||
0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL,
|
||||
0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL,
|
||||
0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL,
|
||||
0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL,
|
||||
0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL,
|
||||
0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL,
|
||||
0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL,
|
||||
0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL,
|
||||
0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL,
|
||||
0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL,
|
||||
0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL,
|
||||
0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL,
|
||||
0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL,
|
||||
0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL,
|
||||
0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL,
|
||||
0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL,
|
||||
0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL,
|
||||
0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL,
|
||||
0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL,
|
||||
0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL,
|
||||
0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL,
|
||||
0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL,
|
||||
0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL,
|
||||
0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL,
|
||||
0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL,
|
||||
0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL,
|
||||
0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL,
|
||||
0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL,
|
||||
0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL,
|
||||
0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL,
|
||||
0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL,
|
||||
0x9324fd72UL
|
||||
},
|
||||
{
|
||||
0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL,
|
||||
0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL,
|
||||
0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL,
|
||||
0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL,
|
||||
0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL,
|
||||
0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL,
|
||||
0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL,
|
||||
0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL,
|
||||
0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL,
|
||||
0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL,
|
||||
0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL,
|
||||
0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL,
|
||||
0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL,
|
||||
0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL,
|
||||
0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL,
|
||||
0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL,
|
||||
0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL,
|
||||
0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL,
|
||||
0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL,
|
||||
0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL,
|
||||
0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL,
|
||||
0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL,
|
||||
0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL,
|
||||
0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL,
|
||||
0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL,
|
||||
0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL,
|
||||
0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL,
|
||||
0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL,
|
||||
0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL,
|
||||
0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL,
|
||||
0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL,
|
||||
0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL,
|
||||
0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL,
|
||||
0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL,
|
||||
0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL,
|
||||
0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL,
|
||||
0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL,
|
||||
0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL,
|
||||
0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL,
|
||||
0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL,
|
||||
0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL,
|
||||
0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL,
|
||||
0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL,
|
||||
0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL,
|
||||
0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL,
|
||||
0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL,
|
||||
0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL,
|
||||
0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL,
|
||||
0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL,
|
||||
0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL,
|
||||
0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL,
|
||||
0xbe9834edUL
|
||||
},
|
||||
{
|
||||
0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL,
|
||||
0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL,
|
||||
0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL,
|
||||
0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL,
|
||||
0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL,
|
||||
0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL,
|
||||
0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL,
|
||||
0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL,
|
||||
0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL,
|
||||
0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL,
|
||||
0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL,
|
||||
0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL,
|
||||
0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL,
|
||||
0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL,
|
||||
0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL,
|
||||
0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL,
|
||||
0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL,
|
||||
0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL,
|
||||
0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL,
|
||||
0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL,
|
||||
0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL,
|
||||
0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL,
|
||||
0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL,
|
||||
0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL,
|
||||
0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL,
|
||||
0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL,
|
||||
0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL,
|
||||
0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL,
|
||||
0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL,
|
||||
0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL,
|
||||
0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL,
|
||||
0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL,
|
||||
0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL,
|
||||
0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL,
|
||||
0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL,
|
||||
0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL,
|
||||
0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL,
|
||||
0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL,
|
||||
0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL,
|
||||
0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL,
|
||||
0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL,
|
||||
0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL,
|
||||
0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL,
|
||||
0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL,
|
||||
0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL,
|
||||
0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL,
|
||||
0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL,
|
||||
0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL,
|
||||
0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL,
|
||||
0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL,
|
||||
0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL,
|
||||
0xde0506f1UL
|
||||
},
|
||||
{
|
||||
0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL,
|
||||
0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL,
|
||||
0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL,
|
||||
0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL,
|
||||
0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL,
|
||||
0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL,
|
||||
0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL,
|
||||
0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL,
|
||||
0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL,
|
||||
0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL,
|
||||
0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL,
|
||||
0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL,
|
||||
0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL,
|
||||
0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL,
|
||||
0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL,
|
||||
0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL,
|
||||
0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL,
|
||||
0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL,
|
||||
0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL,
|
||||
0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL,
|
||||
0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL,
|
||||
0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL,
|
||||
0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL,
|
||||
0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL,
|
||||
0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL,
|
||||
0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL,
|
||||
0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL,
|
||||
0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL,
|
||||
0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL,
|
||||
0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL,
|
||||
0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL,
|
||||
0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL,
|
||||
0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL,
|
||||
0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL,
|
||||
0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL,
|
||||
0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL,
|
||||
0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL,
|
||||
0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL,
|
||||
0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL,
|
||||
0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL,
|
||||
0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL,
|
||||
0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL,
|
||||
0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL,
|
||||
0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL,
|
||||
0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL,
|
||||
0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL,
|
||||
0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL,
|
||||
0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL,
|
||||
0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL,
|
||||
0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL,
|
||||
0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL,
|
||||
0x8def022dUL
|
||||
},
|
||||
{
|
||||
0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL,
|
||||
0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL,
|
||||
0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL,
|
||||
0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL,
|
||||
0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL,
|
||||
0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL,
|
||||
0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL,
|
||||
0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL,
|
||||
0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL,
|
||||
0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL,
|
||||
0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL,
|
||||
0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL,
|
||||
0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL,
|
||||
0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL,
|
||||
0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL,
|
||||
0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL,
|
||||
0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL,
|
||||
0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL,
|
||||
0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL,
|
||||
0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL,
|
||||
0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL,
|
||||
0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL,
|
||||
0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL,
|
||||
0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL,
|
||||
0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL,
|
||||
0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL,
|
||||
0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL,
|
||||
0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL,
|
||||
0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL,
|
||||
0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL,
|
||||
0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL,
|
||||
0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL,
|
||||
0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL,
|
||||
0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL,
|
||||
0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL,
|
||||
0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL,
|
||||
0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL,
|
||||
0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL,
|
||||
0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL,
|
||||
0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL,
|
||||
0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL,
|
||||
0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL,
|
||||
0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL,
|
||||
0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL,
|
||||
0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL,
|
||||
0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL,
|
||||
0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL,
|
||||
0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL,
|
||||
0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL,
|
||||
0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL,
|
||||
0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL,
|
||||
0x72fd2493UL
|
||||
},
|
||||
{
|
||||
0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL,
|
||||
0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL,
|
||||
0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL,
|
||||
0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL,
|
||||
0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL,
|
||||
0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL,
|
||||
0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL,
|
||||
0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL,
|
||||
0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL,
|
||||
0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL,
|
||||
0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL,
|
||||
0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL,
|
||||
0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL,
|
||||
0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL,
|
||||
0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL,
|
||||
0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL,
|
||||
0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL,
|
||||
0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL,
|
||||
0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL,
|
||||
0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL,
|
||||
0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL,
|
||||
0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL,
|
||||
0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL,
|
||||
0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL,
|
||||
0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL,
|
||||
0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL,
|
||||
0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL,
|
||||
0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL,
|
||||
0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL,
|
||||
0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL,
|
||||
0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL,
|
||||
0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL,
|
||||
0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL,
|
||||
0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL,
|
||||
0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL,
|
||||
0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL,
|
||||
0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL,
|
||||
0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL,
|
||||
0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL,
|
||||
0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL,
|
||||
0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL,
|
||||
0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL,
|
||||
0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL,
|
||||
0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL,
|
||||
0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL,
|
||||
0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL,
|
||||
0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL,
|
||||
0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL,
|
||||
0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL,
|
||||
0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL,
|
||||
0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL,
|
||||
0xed3498beUL
|
||||
},
|
||||
{
|
||||
0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL,
|
||||
0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL,
|
||||
0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL,
|
||||
0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL,
|
||||
0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL,
|
||||
0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL,
|
||||
0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL,
|
||||
0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL,
|
||||
0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL,
|
||||
0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL,
|
||||
0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL,
|
||||
0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL,
|
||||
0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL,
|
||||
0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL,
|
||||
0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL,
|
||||
0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL,
|
||||
0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL,
|
||||
0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL,
|
||||
0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL,
|
||||
0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL,
|
||||
0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL,
|
||||
0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL,
|
||||
0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL,
|
||||
0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL,
|
||||
0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL,
|
||||
0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL,
|
||||
0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL,
|
||||
0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL,
|
||||
0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL,
|
||||
0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL,
|
||||
0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL,
|
||||
0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL,
|
||||
0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL,
|
||||
0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL,
|
||||
0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL,
|
||||
0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL,
|
||||
0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL,
|
||||
0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL,
|
||||
0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL,
|
||||
0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL,
|
||||
0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL,
|
||||
0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL,
|
||||
0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL,
|
||||
0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL,
|
||||
0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL,
|
||||
0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL,
|
||||
0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL,
|
||||
0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL,
|
||||
0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL,
|
||||
0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL,
|
||||
0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL,
|
||||
0xf10605deUL
|
||||
#endif
|
||||
}
|
||||
};
|
||||
1834
dependencies/libwebsockets/win32port/zlib/deflate.c
vendored
Normal file
1834
dependencies/libwebsockets/win32port/zlib/deflate.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
342
dependencies/libwebsockets/win32port/zlib/deflate.h
vendored
Normal file
342
dependencies/libwebsockets/win32port/zlib/deflate.h
vendored
Normal file
@ -0,0 +1,342 @@
|
||||
/* deflate.h -- internal compression state
|
||||
* Copyright (C) 1995-2010 Jean-loup Gailly
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* WARNING: this file should *not* be used by applications. It is
|
||||
part of the implementation of the compression library and is
|
||||
subject to change. Applications should only use zlib.h.
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#ifndef DEFLATE_H
|
||||
#define DEFLATE_H
|
||||
|
||||
#include "zutil.h"
|
||||
|
||||
/* define NO_GZIP when compiling if you want to disable gzip header and
|
||||
trailer creation by deflate(). NO_GZIP would be used to avoid linking in
|
||||
the crc code when it is not needed. For shared libraries, gzip encoding
|
||||
should be left enabled. */
|
||||
#ifndef NO_GZIP
|
||||
# define GZIP
|
||||
#endif
|
||||
|
||||
/* ===========================================================================
|
||||
* Internal compression state.
|
||||
*/
|
||||
|
||||
#define LENGTH_CODES 29
|
||||
/* number of length codes, not counting the special END_BLOCK code */
|
||||
|
||||
#define LITERALS 256
|
||||
/* number of literal bytes 0..255 */
|
||||
|
||||
#define L_CODES (LITERALS+1+LENGTH_CODES)
|
||||
/* number of Literal or Length codes, including the END_BLOCK code */
|
||||
|
||||
#define D_CODES 30
|
||||
/* number of distance codes */
|
||||
|
||||
#define BL_CODES 19
|
||||
/* number of codes used to transfer the bit lengths */
|
||||
|
||||
#define HEAP_SIZE (2*L_CODES+1)
|
||||
/* maximum heap size */
|
||||
|
||||
#define MAX_BITS 15
|
||||
/* All codes must not exceed MAX_BITS bits */
|
||||
|
||||
#define INIT_STATE 42
|
||||
#define EXTRA_STATE 69
|
||||
#define NAME_STATE 73
|
||||
#define COMMENT_STATE 91
|
||||
#define HCRC_STATE 103
|
||||
#define BUSY_STATE 113
|
||||
#define FINISH_STATE 666
|
||||
/* Stream status */
|
||||
|
||||
|
||||
/* Data structure describing a single value and its code string. */
|
||||
typedef struct ct_data_s {
|
||||
union {
|
||||
ush freq; /* frequency count */
|
||||
ush code; /* bit string */
|
||||
} fc;
|
||||
union {
|
||||
ush dad; /* father node in Huffman tree */
|
||||
ush len; /* length of bit string */
|
||||
} dl;
|
||||
} FAR ct_data;
|
||||
|
||||
#define Freq fc.freq
|
||||
#define Code fc.code
|
||||
#define Dad dl.dad
|
||||
#define Len dl.len
|
||||
|
||||
typedef struct static_tree_desc_s static_tree_desc;
|
||||
|
||||
typedef struct tree_desc_s {
|
||||
ct_data *dyn_tree; /* the dynamic tree */
|
||||
int max_code; /* largest code with non zero frequency */
|
||||
static_tree_desc *stat_desc; /* the corresponding static tree */
|
||||
} FAR tree_desc;
|
||||
|
||||
typedef ush Pos;
|
||||
typedef Pos FAR Posf;
|
||||
typedef unsigned IPos;
|
||||
|
||||
/* A Pos is an index in the character window. We use short instead of int to
|
||||
* save space in the various tables. IPos is used only for parameter passing.
|
||||
*/
|
||||
|
||||
typedef struct internal_state {
|
||||
z_streamp strm; /* pointer back to this zlib stream */
|
||||
int status; /* as the name implies */
|
||||
Bytef *pending_buf; /* output still pending */
|
||||
ulg pending_buf_size; /* size of pending_buf */
|
||||
Bytef *pending_out; /* next pending byte to output to the stream */
|
||||
uInt pending; /* nb of bytes in the pending buffer */
|
||||
int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
|
||||
gz_headerp gzhead; /* gzip header information to write */
|
||||
uInt gzindex; /* where in extra, name, or comment */
|
||||
Byte method; /* STORED (for zip only) or DEFLATED */
|
||||
int last_flush; /* value of flush param for previous deflate call */
|
||||
|
||||
/* used by deflate.c: */
|
||||
|
||||
uInt w_size; /* LZ77 window size (32K by default) */
|
||||
uInt w_bits; /* log2(w_size) (8..16) */
|
||||
uInt w_mask; /* w_size - 1 */
|
||||
|
||||
Bytef *window;
|
||||
/* Sliding window. Input bytes are read into the second half of the window,
|
||||
* and move to the first half later to keep a dictionary of at least wSize
|
||||
* bytes. With this organization, matches are limited to a distance of
|
||||
* wSize-MAX_MATCH bytes, but this ensures that IO is always
|
||||
* performed with a length multiple of the block size. Also, it limits
|
||||
* the window size to 64K, which is quite useful on MSDOS.
|
||||
* To do: use the user input buffer as sliding window.
|
||||
*/
|
||||
|
||||
ulg window_size;
|
||||
/* Actual size of window: 2*wSize, except when the user input buffer
|
||||
* is directly used as sliding window.
|
||||
*/
|
||||
|
||||
Posf *prev;
|
||||
/* Link to older string with same hash index. To limit the size of this
|
||||
* array to 64K, this link is maintained only for the last 32K strings.
|
||||
* An index in this array is thus a window index modulo 32K.
|
||||
*/
|
||||
|
||||
Posf *head; /* Heads of the hash chains or NIL. */
|
||||
|
||||
uInt ins_h; /* hash index of string to be inserted */
|
||||
uInt hash_size; /* number of elements in hash table */
|
||||
uInt hash_bits; /* log2(hash_size) */
|
||||
uInt hash_mask; /* hash_size-1 */
|
||||
|
||||
uInt hash_shift;
|
||||
/* Number of bits by which ins_h must be shifted at each input
|
||||
* step. It must be such that after MIN_MATCH steps, the oldest
|
||||
* byte no longer takes part in the hash key, that is:
|
||||
* hash_shift * MIN_MATCH >= hash_bits
|
||||
*/
|
||||
|
||||
long block_start;
|
||||
/* Window position at the beginning of the current output block. Gets
|
||||
* negative when the window is moved backwards.
|
||||
*/
|
||||
|
||||
uInt match_length; /* length of best match */
|
||||
IPos prev_match; /* previous match */
|
||||
int match_available; /* set if previous match exists */
|
||||
uInt strstart; /* start of string to insert */
|
||||
uInt match_start; /* start of matching string */
|
||||
uInt lookahead; /* number of valid bytes ahead in window */
|
||||
|
||||
uInt prev_length;
|
||||
/* Length of the best match at previous step. Matches not greater than this
|
||||
* are discarded. This is used in the lazy match evaluation.
|
||||
*/
|
||||
|
||||
uInt max_chain_length;
|
||||
/* To speed up deflation, hash chains are never searched beyond this
|
||||
* length. A higher limit improves compression ratio but degrades the
|
||||
* speed.
|
||||
*/
|
||||
|
||||
uInt max_lazy_match;
|
||||
/* Attempt to find a better match only when the current match is strictly
|
||||
* smaller than this value. This mechanism is used only for compression
|
||||
* levels >= 4.
|
||||
*/
|
||||
# define max_insert_length max_lazy_match
|
||||
/* Insert new strings in the hash table only if the match length is not
|
||||
* greater than this length. This saves time but degrades compression.
|
||||
* max_insert_length is used only for compression levels <= 3.
|
||||
*/
|
||||
|
||||
int level; /* compression level (1..9) */
|
||||
int strategy; /* favor or force Huffman coding*/
|
||||
|
||||
uInt good_match;
|
||||
/* Use a faster search when the previous match is longer than this */
|
||||
|
||||
int nice_match; /* Stop searching when current match exceeds this */
|
||||
|
||||
/* used by trees.c: */
|
||||
/* Didn't use ct_data typedef below to supress compiler warning */
|
||||
struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
|
||||
struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
|
||||
struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
|
||||
|
||||
struct tree_desc_s l_desc; /* desc. for literal tree */
|
||||
struct tree_desc_s d_desc; /* desc. for distance tree */
|
||||
struct tree_desc_s bl_desc; /* desc. for bit length tree */
|
||||
|
||||
ush bl_count[MAX_BITS+1];
|
||||
/* number of codes at each bit length for an optimal tree */
|
||||
|
||||
int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
|
||||
int heap_len; /* number of elements in the heap */
|
||||
int heap_max; /* element of largest frequency */
|
||||
/* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
|
||||
* The same heap array is used to build all trees.
|
||||
*/
|
||||
|
||||
uch depth[2*L_CODES+1];
|
||||
/* Depth of each subtree used as tie breaker for trees of equal frequency
|
||||
*/
|
||||
|
||||
uchf *l_buf; /* buffer for literals or lengths */
|
||||
|
||||
uInt lit_bufsize;
|
||||
/* Size of match buffer for literals/lengths. There are 4 reasons for
|
||||
* limiting lit_bufsize to 64K:
|
||||
* - frequencies can be kept in 16 bit counters
|
||||
* - if compression is not successful for the first block, all input
|
||||
* data is still in the window so we can still emit a stored block even
|
||||
* when input comes from standard input. (This can also be done for
|
||||
* all blocks if lit_bufsize is not greater than 32K.)
|
||||
* - if compression is not successful for a file smaller than 64K, we can
|
||||
* even emit a stored file instead of a stored block (saving 5 bytes).
|
||||
* This is applicable only for zip (not gzip or zlib).
|
||||
* - creating new Huffman trees less frequently may not provide fast
|
||||
* adaptation to changes in the input data statistics. (Take for
|
||||
* example a binary file with poorly compressible code followed by
|
||||
* a highly compressible string table.) Smaller buffer sizes give
|
||||
* fast adaptation but have of course the overhead of transmitting
|
||||
* trees more frequently.
|
||||
* - I can't count above 4
|
||||
*/
|
||||
|
||||
uInt last_lit; /* running index in l_buf */
|
||||
|
||||
ushf *d_buf;
|
||||
/* Buffer for distances. To simplify the code, d_buf and l_buf have
|
||||
* the same number of elements. To use different lengths, an extra flag
|
||||
* array would be necessary.
|
||||
*/
|
||||
|
||||
ulg opt_len; /* bit length of current block with optimal trees */
|
||||
ulg static_len; /* bit length of current block with static trees */
|
||||
uInt matches; /* number of string matches in current block */
|
||||
int last_eob_len; /* bit length of EOB code for last block */
|
||||
|
||||
#ifdef DEBUG
|
||||
ulg compressed_len; /* total bit length of compressed file mod 2^32 */
|
||||
ulg bits_sent; /* bit length of compressed data sent mod 2^32 */
|
||||
#endif
|
||||
|
||||
ush bi_buf;
|
||||
/* Output buffer. bits are inserted starting at the bottom (least
|
||||
* significant bits).
|
||||
*/
|
||||
int bi_valid;
|
||||
/* Number of valid bits in bi_buf. All bits above the last valid bit
|
||||
* are always zero.
|
||||
*/
|
||||
|
||||
ulg high_water;
|
||||
/* High water mark offset in window for initialized bytes -- bytes above
|
||||
* this are set to zero in order to avoid memory check warnings when
|
||||
* longest match routines access bytes past the input. This is then
|
||||
* updated to the new high water mark.
|
||||
*/
|
||||
|
||||
} FAR deflate_state;
|
||||
|
||||
/* Output a byte on the stream.
|
||||
* IN assertion: there is enough room in pending_buf.
|
||||
*/
|
||||
#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
|
||||
|
||||
|
||||
#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
|
||||
/* Minimum amount of lookahead, except at the end of the input file.
|
||||
* See deflate.c for comments about the MIN_MATCH+1.
|
||||
*/
|
||||
|
||||
#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD)
|
||||
/* In order to simplify the code, particularly on 16 bit machines, match
|
||||
* distances are limited to MAX_DIST instead of WSIZE.
|
||||
*/
|
||||
|
||||
#define WIN_INIT MAX_MATCH
|
||||
/* Number of bytes after end of data in window to initialize in order to avoid
|
||||
memory checker errors from longest match routines */
|
||||
|
||||
/* in trees.c */
|
||||
void ZLIB_INTERNAL _tr_init OF((deflate_state *s));
|
||||
int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
|
||||
void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf,
|
||||
ulg stored_len, int last));
|
||||
void ZLIB_INTERNAL _tr_align OF((deflate_state *s));
|
||||
void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf,
|
||||
ulg stored_len, int last));
|
||||
|
||||
#define d_code(dist) \
|
||||
((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
|
||||
/* Mapping from a distance to a distance code. dist is the distance - 1 and
|
||||
* must not have side effects. _dist_code[256] and _dist_code[257] are never
|
||||
* used.
|
||||
*/
|
||||
|
||||
#ifndef DEBUG
|
||||
/* Inline versions of _tr_tally for speed: */
|
||||
|
||||
#if defined(GEN_TREES_H) || !defined(STDC)
|
||||
extern uch ZLIB_INTERNAL _length_code[];
|
||||
extern uch ZLIB_INTERNAL _dist_code[];
|
||||
#else
|
||||
extern const uch ZLIB_INTERNAL _length_code[];
|
||||
extern const uch ZLIB_INTERNAL _dist_code[];
|
||||
#endif
|
||||
|
||||
# define _tr_tally_lit(s, c, flush) \
|
||||
{ uch cc = (c); \
|
||||
s->d_buf[s->last_lit] = 0; \
|
||||
s->l_buf[s->last_lit++] = cc; \
|
||||
s->dyn_ltree[cc].Freq++; \
|
||||
flush = (s->last_lit == s->lit_bufsize-1); \
|
||||
}
|
||||
# define _tr_tally_dist(s, distance, length, flush) \
|
||||
{ uch len = (length); \
|
||||
ush dist = (distance); \
|
||||
s->d_buf[s->last_lit] = dist; \
|
||||
s->l_buf[s->last_lit++] = len; \
|
||||
dist--; \
|
||||
s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
|
||||
s->dyn_dtree[d_code(dist)].Freq++; \
|
||||
flush = (s->last_lit == s->lit_bufsize-1); \
|
||||
}
|
||||
#else
|
||||
# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
|
||||
# define _tr_tally_dist(s, distance, length, flush) \
|
||||
flush = _tr_tally(s, distance, length)
|
||||
#endif
|
||||
|
||||
#endif /* DEFLATE_H */
|
||||
25
dependencies/libwebsockets/win32port/zlib/gzclose.c
vendored
Normal file
25
dependencies/libwebsockets/win32port/zlib/gzclose.c
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
/* gzclose.c -- zlib gzclose() function
|
||||
* Copyright (C) 2004, 2010 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "gzguts.h"
|
||||
|
||||
/* gzclose() is in a separate file so that it is linked in only if it is used.
|
||||
That way the other gzclose functions can be used instead to avoid linking in
|
||||
unneeded compression or decompression routines. */
|
||||
int ZEXPORT gzclose(file)
|
||||
gzFile file;
|
||||
{
|
||||
#ifndef NO_GZCOMPRESS
|
||||
gz_statep state;
|
||||
|
||||
if (file == NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
state = (gz_statep)file;
|
||||
|
||||
return state->mode == GZ_READ ? gzclose_r(file) : gzclose_w(file);
|
||||
#else
|
||||
return gzclose_r(file);
|
||||
#endif
|
||||
}
|
||||
132
dependencies/libwebsockets/win32port/zlib/gzguts.h
vendored
Normal file
132
dependencies/libwebsockets/win32port/zlib/gzguts.h
vendored
Normal file
@ -0,0 +1,132 @@
|
||||
/* gzguts.h -- zlib internal header definitions for gz* operations
|
||||
* Copyright (C) 2004, 2005, 2010 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#ifdef _LARGEFILE64_SOURCE
|
||||
# ifndef _LARGEFILE_SOURCE
|
||||
# define _LARGEFILE_SOURCE 1
|
||||
# endif
|
||||
# ifdef _FILE_OFFSET_BITS
|
||||
# undef _FILE_OFFSET_BITS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ)
|
||||
# define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
|
||||
#else
|
||||
# define ZLIB_INTERNAL
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "zlib.h"
|
||||
#ifdef STDC
|
||||
# include <string.h>
|
||||
# include <stdlib.h>
|
||||
# include <limits.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef NO_DEFLATE /* for compatibility with old definition */
|
||||
# define NO_GZCOMPRESS
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# include <io.h>
|
||||
# define vsnprintf _vsnprintf
|
||||
#endif
|
||||
|
||||
#ifndef local
|
||||
# define local static
|
||||
#endif
|
||||
/* compile with -Dlocal if your debugger can't find static symbols */
|
||||
|
||||
/* gz* functions always use library allocation functions */
|
||||
#ifndef STDC
|
||||
extern voidp malloc OF((uInt size));
|
||||
extern void free OF((voidpf ptr));
|
||||
#endif
|
||||
|
||||
/* get errno and strerror definition */
|
||||
#if defined UNDER_CE
|
||||
# include <windows.h>
|
||||
# define zstrerror() gz_strwinerror((DWORD)GetLastError())
|
||||
#else
|
||||
# ifdef STDC
|
||||
# include <errno.h>
|
||||
# define zstrerror() strerror(errno)
|
||||
# else
|
||||
# define zstrerror() "stdio error (consult errno)"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* provide prototypes for these when building zlib without LFS */
|
||||
#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0
|
||||
ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
|
||||
ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
|
||||
ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
|
||||
ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
|
||||
#endif
|
||||
|
||||
/* default i/o buffer size -- double this for output when reading */
|
||||
#define GZBUFSIZE 8192
|
||||
|
||||
/* gzip modes, also provide a little integrity check on the passed structure */
|
||||
#define GZ_NONE 0
|
||||
#define GZ_READ 7247
|
||||
#define GZ_WRITE 31153
|
||||
#define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */
|
||||
|
||||
/* values for gz_state how */
|
||||
#define LOOK 0 /* look for a gzip header */
|
||||
#define COPY 1 /* copy input directly */
|
||||
#define GZIP 2 /* decompress a gzip stream */
|
||||
|
||||
/* internal gzip file state data structure */
|
||||
typedef struct {
|
||||
/* used for both reading and writing */
|
||||
int mode; /* see gzip modes above */
|
||||
int fd; /* file descriptor */
|
||||
char *path; /* path or fd for error messages */
|
||||
z_off64_t pos; /* current position in uncompressed data */
|
||||
unsigned size; /* buffer size, zero if not allocated yet */
|
||||
unsigned want; /* requested buffer size, default is GZBUFSIZE */
|
||||
unsigned char *in; /* input buffer */
|
||||
unsigned char *out; /* output buffer (double-sized when reading) */
|
||||
unsigned char *next; /* next output data to deliver or write */
|
||||
/* just for reading */
|
||||
unsigned have; /* amount of output data unused at next */
|
||||
int eof; /* true if end of input file reached */
|
||||
z_off64_t start; /* where the gzip data started, for rewinding */
|
||||
z_off64_t raw; /* where the raw data started, for seeking */
|
||||
int how; /* 0: get header, 1: copy, 2: decompress */
|
||||
int direct; /* true if last read direct, false if gzip */
|
||||
/* just for writing */
|
||||
int level; /* compression level */
|
||||
int strategy; /* compression strategy */
|
||||
/* seek request */
|
||||
z_off64_t skip; /* amount to skip (already rewound if backwards) */
|
||||
int seek; /* true if seek request pending */
|
||||
/* error information */
|
||||
int err; /* error code */
|
||||
char *msg; /* error message */
|
||||
/* zlib inflate or deflate stream */
|
||||
z_stream strm; /* stream structure in-place (not a pointer) */
|
||||
} gz_state;
|
||||
typedef gz_state FAR *gz_statep;
|
||||
|
||||
/* shared functions */
|
||||
void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *));
|
||||
#if defined UNDER_CE
|
||||
char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error));
|
||||
#endif
|
||||
|
||||
/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t
|
||||
value -- needed when comparing unsigned to z_off64_t, which is signed
|
||||
(possible z_off64_t types off_t, off64_t, and long are all signed) */
|
||||
#ifdef INT_MAX
|
||||
# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX)
|
||||
#else
|
||||
unsigned ZLIB_INTERNAL gz_intmax OF((void));
|
||||
# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())
|
||||
#endif
|
||||
1006
dependencies/libwebsockets/win32port/zlib/gzio.c
vendored
Normal file
1006
dependencies/libwebsockets/win32port/zlib/gzio.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
537
dependencies/libwebsockets/win32port/zlib/gzlib.c
vendored
Normal file
537
dependencies/libwebsockets/win32port/zlib/gzlib.c
vendored
Normal file
@ -0,0 +1,537 @@
|
||||
/* gzlib.c -- zlib functions common to reading and writing gzip files
|
||||
* Copyright (C) 2004, 2010 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "gzguts.h"
|
||||
|
||||
#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
|
||||
# define LSEEK lseek64
|
||||
#else
|
||||
# define LSEEK lseek
|
||||
#endif
|
||||
|
||||
/* Local functions */
|
||||
local void gz_reset OF((gz_statep));
|
||||
local gzFile gz_open OF((const char *, int, const char *));
|
||||
|
||||
#if defined UNDER_CE
|
||||
|
||||
/* Map the Windows error number in ERROR to a locale-dependent error message
|
||||
string and return a pointer to it. Typically, the values for ERROR come
|
||||
from GetLastError.
|
||||
|
||||
The string pointed to shall not be modified by the application, but may be
|
||||
overwritten by a subsequent call to gz_strwinerror
|
||||
|
||||
The gz_strwinerror function does not change the current setting of
|
||||
GetLastError. */
|
||||
char ZLIB_INTERNAL *gz_strwinerror (error)
|
||||
DWORD error;
|
||||
{
|
||||
static char buf[1024];
|
||||
|
||||
wchar_t *msgbuf;
|
||||
DWORD lasterr = GetLastError();
|
||||
DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
|
||||
| FORMAT_MESSAGE_ALLOCATE_BUFFER,
|
||||
NULL,
|
||||
error,
|
||||
0, /* Default language */
|
||||
(LPVOID)&msgbuf,
|
||||
0,
|
||||
NULL);
|
||||
if (chars != 0) {
|
||||
/* If there is an \r\n appended, zap it. */
|
||||
if (chars >= 2
|
||||
&& msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
|
||||
chars -= 2;
|
||||
msgbuf[chars] = 0;
|
||||
}
|
||||
|
||||
if (chars > sizeof (buf) - 1) {
|
||||
chars = sizeof (buf) - 1;
|
||||
msgbuf[chars] = 0;
|
||||
}
|
||||
|
||||
wcstombs(buf, msgbuf, chars + 1);
|
||||
LocalFree(msgbuf);
|
||||
}
|
||||
else {
|
||||
sprintf(buf, "unknown win32 error (%ld)", error);
|
||||
}
|
||||
|
||||
SetLastError(lasterr);
|
||||
return buf;
|
||||
}
|
||||
|
||||
#endif /* UNDER_CE */
|
||||
|
||||
/* Reset gzip file state */
|
||||
local void gz_reset(state)
|
||||
gz_statep state;
|
||||
{
|
||||
if (state->mode == GZ_READ) { /* for reading ... */
|
||||
state->have = 0; /* no output data available */
|
||||
state->eof = 0; /* not at end of file */
|
||||
state->how = LOOK; /* look for gzip header */
|
||||
state->direct = 1; /* default for empty file */
|
||||
}
|
||||
state->seek = 0; /* no seek request pending */
|
||||
gz_error(state, Z_OK, NULL); /* clear error */
|
||||
state->pos = 0; /* no uncompressed data yet */
|
||||
state->strm.avail_in = 0; /* no input data yet */
|
||||
}
|
||||
|
||||
/* Open a gzip file either by name or file descriptor. */
|
||||
local gzFile gz_open(path, fd, mode)
|
||||
const char *path;
|
||||
int fd;
|
||||
const char *mode;
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* allocate gzFile structure to return */
|
||||
state = malloc(sizeof(gz_state));
|
||||
if (state == NULL)
|
||||
return NULL;
|
||||
state->size = 0; /* no buffers allocated yet */
|
||||
state->want = GZBUFSIZE; /* requested buffer size */
|
||||
state->msg = NULL; /* no error message yet */
|
||||
|
||||
/* interpret mode */
|
||||
state->mode = GZ_NONE;
|
||||
state->level = Z_DEFAULT_COMPRESSION;
|
||||
state->strategy = Z_DEFAULT_STRATEGY;
|
||||
while (*mode) {
|
||||
if (*mode >= '0' && *mode <= '9')
|
||||
state->level = *mode - '0';
|
||||
else
|
||||
switch (*mode) {
|
||||
case 'r':
|
||||
state->mode = GZ_READ;
|
||||
break;
|
||||
#ifndef NO_GZCOMPRESS
|
||||
case 'w':
|
||||
state->mode = GZ_WRITE;
|
||||
break;
|
||||
case 'a':
|
||||
state->mode = GZ_APPEND;
|
||||
break;
|
||||
#endif
|
||||
case '+': /* can't read and write at the same time */
|
||||
free(state);
|
||||
return NULL;
|
||||
case 'b': /* ignore -- will request binary anyway */
|
||||
break;
|
||||
case 'f':
|
||||
state->strategy = Z_FILTERED;
|
||||
break;
|
||||
case 'h':
|
||||
state->strategy = Z_HUFFMAN_ONLY;
|
||||
break;
|
||||
case 'R':
|
||||
state->strategy = Z_RLE;
|
||||
break;
|
||||
case 'F':
|
||||
state->strategy = Z_FIXED;
|
||||
default: /* could consider as an error, but just ignore */
|
||||
;
|
||||
}
|
||||
mode++;
|
||||
}
|
||||
|
||||
/* must provide an "r", "w", or "a" */
|
||||
if (state->mode == GZ_NONE) {
|
||||
free(state);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* save the path name for error messages */
|
||||
state->path = malloc(strlen(path) + 1);
|
||||
if (state->path == NULL) {
|
||||
free(state);
|
||||
return NULL;
|
||||
}
|
||||
strcpy(state->path, path);
|
||||
|
||||
/* open the file with the appropriate mode (or just use fd) */
|
||||
state->fd = fd != -1 ? fd :
|
||||
open(path,
|
||||
#ifdef O_LARGEFILE
|
||||
O_LARGEFILE |
|
||||
#endif
|
||||
#ifdef O_BINARY
|
||||
O_BINARY |
|
||||
#endif
|
||||
(state->mode == GZ_READ ?
|
||||
O_RDONLY :
|
||||
(O_WRONLY | O_CREAT | (
|
||||
state->mode == GZ_WRITE ?
|
||||
O_TRUNC :
|
||||
O_APPEND))),
|
||||
0666);
|
||||
if (state->fd == -1) {
|
||||
free(state->path);
|
||||
free(state);
|
||||
return NULL;
|
||||
}
|
||||
if (state->mode == GZ_APPEND)
|
||||
state->mode = GZ_WRITE; /* simplify later checks */
|
||||
|
||||
/* save the current position for rewinding (only if reading) */
|
||||
if (state->mode == GZ_READ) {
|
||||
state->start = LSEEK(state->fd, 0, SEEK_CUR);
|
||||
if (state->start == -1) state->start = 0;
|
||||
}
|
||||
|
||||
/* initialize stream */
|
||||
gz_reset(state);
|
||||
|
||||
/* return stream */
|
||||
return (gzFile)state;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
gzFile ZEXPORT gzopen(path, mode)
|
||||
const char *path;
|
||||
const char *mode;
|
||||
{
|
||||
return gz_open(path, -1, mode);
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
gzFile ZEXPORT gzopen64(path, mode)
|
||||
const char *path;
|
||||
const char *mode;
|
||||
{
|
||||
return gz_open(path, -1, mode);
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
gzFile ZEXPORT gzdopen(fd, mode)
|
||||
int fd;
|
||||
const char *mode;
|
||||
{
|
||||
char *path; /* identifier for error messages */
|
||||
gzFile gz;
|
||||
|
||||
if (fd == -1 || (path = malloc(7 + 3 * sizeof(int))) == NULL)
|
||||
return NULL;
|
||||
sprintf(path, "<fd:%d>", fd); /* for debugging */
|
||||
gz = gz_open(path, fd, mode);
|
||||
free(path);
|
||||
return gz;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzbuffer(file, size)
|
||||
gzFile file;
|
||||
unsigned size;
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
|
||||
return -1;
|
||||
|
||||
/* make sure we haven't already allocated memory */
|
||||
if (state->size != 0)
|
||||
return -1;
|
||||
|
||||
/* check and set requested size */
|
||||
if (size == 0)
|
||||
return -1;
|
||||
state->want = size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzrewind(file)
|
||||
gzFile file;
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
|
||||
/* check that we're reading and that there's no error */
|
||||
if (state->mode != GZ_READ || state->err != Z_OK)
|
||||
return -1;
|
||||
|
||||
/* back up and start over */
|
||||
if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
|
||||
return -1;
|
||||
gz_reset(state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
z_off64_t ZEXPORT gzseek64(file, offset, whence)
|
||||
gzFile file;
|
||||
z_off64_t offset;
|
||||
int whence;
|
||||
{
|
||||
unsigned n;
|
||||
z_off64_t ret;
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
|
||||
return -1;
|
||||
|
||||
/* check that there's no error */
|
||||
if (state->err != Z_OK)
|
||||
return -1;
|
||||
|
||||
/* can only seek from start or relative to current position */
|
||||
if (whence != SEEK_SET && whence != SEEK_CUR)
|
||||
return -1;
|
||||
|
||||
/* normalize offset to a SEEK_CUR specification */
|
||||
if (whence == SEEK_SET)
|
||||
offset -= state->pos;
|
||||
else if (state->seek)
|
||||
offset += state->skip;
|
||||
state->seek = 0;
|
||||
|
||||
/* if within raw area while reading, just go there */
|
||||
if (state->mode == GZ_READ && state->how == COPY &&
|
||||
state->pos + offset >= state->raw) {
|
||||
ret = LSEEK(state->fd, offset - state->have, SEEK_CUR);
|
||||
if (ret == -1)
|
||||
return -1;
|
||||
state->have = 0;
|
||||
state->eof = 0;
|
||||
state->seek = 0;
|
||||
gz_error(state, Z_OK, NULL);
|
||||
state->strm.avail_in = 0;
|
||||
state->pos += offset;
|
||||
return state->pos;
|
||||
}
|
||||
|
||||
/* calculate skip amount, rewinding if needed for back seek when reading */
|
||||
if (offset < 0) {
|
||||
if (state->mode != GZ_READ) /* writing -- can't go backwards */
|
||||
return -1;
|
||||
offset += state->pos;
|
||||
if (offset < 0) /* before start of file! */
|
||||
return -1;
|
||||
if (gzrewind(file) == -1) /* rewind, then skip to offset */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* if reading, skip what's in output buffer (one less gzgetc() check) */
|
||||
if (state->mode == GZ_READ) {
|
||||
n = GT_OFF(state->have) || (z_off64_t)state->have > offset ?
|
||||
(unsigned)offset : state->have;
|
||||
state->have -= n;
|
||||
state->next += n;
|
||||
state->pos += n;
|
||||
offset -= n;
|
||||
}
|
||||
|
||||
/* request skip (if not zero) */
|
||||
if (offset) {
|
||||
state->seek = 1;
|
||||
state->skip = offset;
|
||||
}
|
||||
return state->pos + offset;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
z_off_t ZEXPORT gzseek(file, offset, whence)
|
||||
gzFile file;
|
||||
z_off_t offset;
|
||||
int whence;
|
||||
{
|
||||
z_off64_t ret;
|
||||
|
||||
ret = gzseek64(file, (z_off64_t)offset, whence);
|
||||
return ret == (z_off_t)ret ? (z_off_t)ret : -1;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
z_off64_t ZEXPORT gztell64(file)
|
||||
gzFile file;
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
|
||||
return -1;
|
||||
|
||||
/* return position */
|
||||
return state->pos + (state->seek ? state->skip : 0);
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
z_off_t ZEXPORT gztell(file)
|
||||
gzFile file;
|
||||
{
|
||||
z_off64_t ret;
|
||||
|
||||
ret = gztell64(file);
|
||||
return ret == (z_off_t)ret ? (z_off_t)ret : -1;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
z_off64_t ZEXPORT gzoffset64(file)
|
||||
gzFile file;
|
||||
{
|
||||
z_off64_t offset;
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
|
||||
return -1;
|
||||
|
||||
/* compute and return effective offset in file */
|
||||
offset = LSEEK(state->fd, 0, SEEK_CUR);
|
||||
if (offset == -1)
|
||||
return -1;
|
||||
if (state->mode == GZ_READ) /* reading */
|
||||
offset -= state->strm.avail_in; /* don't count buffered input */
|
||||
return offset;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
z_off_t ZEXPORT gzoffset(file)
|
||||
gzFile file;
|
||||
{
|
||||
z_off64_t ret;
|
||||
|
||||
ret = gzoffset64(file);
|
||||
return ret == (z_off_t)ret ? (z_off_t)ret : -1;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzeof(file)
|
||||
gzFile file;
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return 0;
|
||||
state = (gz_statep)file;
|
||||
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
|
||||
return 0;
|
||||
|
||||
/* return end-of-file state */
|
||||
return state->mode == GZ_READ ?
|
||||
(state->eof && state->strm.avail_in == 0 && state->have == 0) : 0;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
const char * ZEXPORT gzerror(file, errnum)
|
||||
gzFile file;
|
||||
int *errnum;
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return NULL;
|
||||
state = (gz_statep)file;
|
||||
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
|
||||
return NULL;
|
||||
|
||||
/* return error information */
|
||||
if (errnum != NULL)
|
||||
*errnum = state->err;
|
||||
return state->msg == NULL ? "" : state->msg;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
void ZEXPORT gzclearerr(file)
|
||||
gzFile file;
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return;
|
||||
state = (gz_statep)file;
|
||||
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
|
||||
return;
|
||||
|
||||
/* clear error and end-of-file */
|
||||
if (state->mode == GZ_READ)
|
||||
state->eof = 0;
|
||||
gz_error(state, Z_OK, NULL);
|
||||
}
|
||||
|
||||
/* Create an error message in allocated memory and set state->err and
|
||||
state->msg accordingly. Free any previous error message already there. Do
|
||||
not try to free or allocate space if the error is Z_MEM_ERROR (out of
|
||||
memory). Simply save the error message as a static string. If there is an
|
||||
allocation failure constructing the error message, then convert the error to
|
||||
out of memory. */
|
||||
void ZLIB_INTERNAL gz_error(state, err, msg)
|
||||
gz_statep state;
|
||||
int err;
|
||||
const char *msg;
|
||||
{
|
||||
/* free previously allocated message and clear */
|
||||
if (state->msg != NULL) {
|
||||
if (state->err != Z_MEM_ERROR)
|
||||
free(state->msg);
|
||||
state->msg = NULL;
|
||||
}
|
||||
|
||||
/* set error code, and if no message, then done */
|
||||
state->err = err;
|
||||
if (msg == NULL)
|
||||
return;
|
||||
|
||||
/* for an out of memory error, save as static string */
|
||||
if (err == Z_MEM_ERROR) {
|
||||
state->msg = (char *)msg;
|
||||
return;
|
||||
}
|
||||
|
||||
/* construct error message with path */
|
||||
if ((state->msg = malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) {
|
||||
state->err = Z_MEM_ERROR;
|
||||
state->msg = (char *)"out of memory";
|
||||
return;
|
||||
}
|
||||
strcpy(state->msg, state->path);
|
||||
strcat(state->msg, ": ");
|
||||
strcat(state->msg, msg);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef INT_MAX
|
||||
/* portably return maximum value for an int (when limits.h presumed not
|
||||
available) -- we need to do this to cover cases where 2's complement not
|
||||
used, since C standard permits 1's complement and sign-bit representations,
|
||||
otherwise we could just use ((unsigned)-1) >> 1 */
|
||||
unsigned ZLIB_INTERNAL gz_intmax()
|
||||
{
|
||||
unsigned p, q;
|
||||
|
||||
p = 1;
|
||||
do {
|
||||
q = p;
|
||||
p <<= 1;
|
||||
p++;
|
||||
} while (p > q);
|
||||
return q >> 1;
|
||||
}
|
||||
#endif
|
||||
653
dependencies/libwebsockets/win32port/zlib/gzread.c
vendored
Normal file
653
dependencies/libwebsockets/win32port/zlib/gzread.c
vendored
Normal file
@ -0,0 +1,653 @@
|
||||
/* gzread.c -- zlib functions for reading gzip files
|
||||
* Copyright (C) 2004, 2005, 2010 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "gzguts.h"
|
||||
|
||||
/* Local functions */
|
||||
local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *));
|
||||
local int gz_avail OF((gz_statep));
|
||||
local int gz_next4 OF((gz_statep, unsigned long *));
|
||||
local int gz_head OF((gz_statep));
|
||||
local int gz_decomp OF((gz_statep));
|
||||
local int gz_make OF((gz_statep));
|
||||
local int gz_skip OF((gz_statep, z_off64_t));
|
||||
|
||||
/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from
|
||||
state->fd, and update state->eof, state->err, and state->msg as appropriate.
|
||||
This function needs to loop on read(), since read() is not guaranteed to
|
||||
read the number of bytes requested, depending on the type of descriptor. */
|
||||
local int gz_load(state, buf, len, have)
|
||||
gz_statep state;
|
||||
unsigned char *buf;
|
||||
unsigned len;
|
||||
unsigned *have;
|
||||
{
|
||||
int ret;
|
||||
|
||||
*have = 0;
|
||||
do {
|
||||
ret = read(state->fd, buf + *have, len - *have);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
*have += ret;
|
||||
} while (*have < len);
|
||||
if (ret < 0) {
|
||||
gz_error(state, Z_ERRNO, zstrerror());
|
||||
return -1;
|
||||
}
|
||||
if (ret == 0)
|
||||
state->eof = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Load up input buffer and set eof flag if last data loaded -- return -1 on
|
||||
error, 0 otherwise. Note that the eof flag is set when the end of the input
|
||||
file is reached, even though there may be unused data in the buffer. Once
|
||||
that data has been used, no more attempts will be made to read the file.
|
||||
gz_avail() assumes that strm->avail_in == 0. */
|
||||
local int gz_avail(state)
|
||||
gz_statep state;
|
||||
{
|
||||
z_streamp strm = &(state->strm);
|
||||
|
||||
if (state->err != Z_OK)
|
||||
return -1;
|
||||
if (state->eof == 0) {
|
||||
if (gz_load(state, state->in, state->size,
|
||||
(unsigned *)&(strm->avail_in)) == -1)
|
||||
return -1;
|
||||
strm->next_in = state->in;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get next byte from input, or -1 if end or error. */
|
||||
#define NEXT() ((strm->avail_in == 0 && gz_avail(state) == -1) ? -1 : \
|
||||
(strm->avail_in == 0 ? -1 : \
|
||||
(strm->avail_in--, *(strm->next_in)++)))
|
||||
|
||||
/* Get a four-byte little-endian integer and return 0 on success and the value
|
||||
in *ret. Otherwise -1 is returned and *ret is not modified. */
|
||||
local int gz_next4(state, ret)
|
||||
gz_statep state;
|
||||
unsigned long *ret;
|
||||
{
|
||||
int ch;
|
||||
unsigned long val;
|
||||
z_streamp strm = &(state->strm);
|
||||
|
||||
val = NEXT();
|
||||
val += (unsigned)NEXT() << 8;
|
||||
val += (unsigned long)NEXT() << 16;
|
||||
ch = NEXT();
|
||||
if (ch == -1)
|
||||
return -1;
|
||||
val += (unsigned long)ch << 24;
|
||||
*ret = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Look for gzip header, set up for inflate or copy. state->have must be zero.
|
||||
If this is the first time in, allocate required memory. state->how will be
|
||||
left unchanged if there is no more input data available, will be set to COPY
|
||||
if there is no gzip header and direct copying will be performed, or it will
|
||||
be set to GZIP for decompression, and the gzip header will be skipped so
|
||||
that the next available input data is the raw deflate stream. If direct
|
||||
copying, then leftover input data from the input buffer will be copied to
|
||||
the output buffer. In that case, all further file reads will be directly to
|
||||
either the output buffer or a user buffer. If decompressing, the inflate
|
||||
state and the check value will be initialized. gz_head() will return 0 on
|
||||
success or -1 on failure. Failures may include read errors or gzip header
|
||||
errors. */
|
||||
local int gz_head(state)
|
||||
gz_statep state;
|
||||
{
|
||||
z_streamp strm = &(state->strm);
|
||||
int flags;
|
||||
unsigned len;
|
||||
|
||||
/* allocate read buffers and inflate memory */
|
||||
if (state->size == 0) {
|
||||
/* allocate buffers */
|
||||
state->in = malloc(state->want);
|
||||
state->out = malloc(state->want << 1);
|
||||
if (state->in == NULL || state->out == NULL) {
|
||||
if (state->out != NULL)
|
||||
free(state->out);
|
||||
if (state->in != NULL)
|
||||
free(state->in);
|
||||
gz_error(state, Z_MEM_ERROR, "out of memory");
|
||||
return -1;
|
||||
}
|
||||
state->size = state->want;
|
||||
|
||||
/* allocate inflate memory */
|
||||
state->strm.zalloc = Z_NULL;
|
||||
state->strm.zfree = Z_NULL;
|
||||
state->strm.opaque = Z_NULL;
|
||||
state->strm.avail_in = 0;
|
||||
state->strm.next_in = Z_NULL;
|
||||
if (inflateInit2(&(state->strm), -15) != Z_OK) { /* raw inflate */
|
||||
free(state->out);
|
||||
free(state->in);
|
||||
state->size = 0;
|
||||
gz_error(state, Z_MEM_ERROR, "out of memory");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* get some data in the input buffer */
|
||||
if (strm->avail_in == 0) {
|
||||
if (gz_avail(state) == -1)
|
||||
return -1;
|
||||
if (strm->avail_in == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* look for the gzip magic header bytes 31 and 139 */
|
||||
if (strm->next_in[0] == 31) {
|
||||
strm->avail_in--;
|
||||
strm->next_in++;
|
||||
if (strm->avail_in == 0 && gz_avail(state) == -1)
|
||||
return -1;
|
||||
if (strm->avail_in && strm->next_in[0] == 139) {
|
||||
/* we have a gzip header, woo hoo! */
|
||||
strm->avail_in--;
|
||||
strm->next_in++;
|
||||
|
||||
/* skip rest of header */
|
||||
if (NEXT() != 8) { /* compression method */
|
||||
gz_error(state, Z_DATA_ERROR, "unknown compression method");
|
||||
return -1;
|
||||
}
|
||||
flags = NEXT();
|
||||
if (flags & 0xe0) { /* reserved flag bits */
|
||||
gz_error(state, Z_DATA_ERROR, "unknown header flags set");
|
||||
return -1;
|
||||
}
|
||||
NEXT(); /* modification time */
|
||||
NEXT();
|
||||
NEXT();
|
||||
NEXT();
|
||||
NEXT(); /* extra flags */
|
||||
NEXT(); /* operating system */
|
||||
if (flags & 4) { /* extra field */
|
||||
len = (unsigned)NEXT();
|
||||
len += (unsigned)NEXT() << 8;
|
||||
while (len--)
|
||||
if (NEXT() < 0)
|
||||
break;
|
||||
}
|
||||
if (flags & 8) /* file name */
|
||||
while (NEXT() > 0)
|
||||
;
|
||||
if (flags & 16) /* comment */
|
||||
while (NEXT() > 0)
|
||||
;
|
||||
if (flags & 2) { /* header crc */
|
||||
NEXT();
|
||||
NEXT();
|
||||
}
|
||||
/* an unexpected end of file is not checked for here -- it will be
|
||||
noticed on the first request for uncompressed data */
|
||||
|
||||
/* set up for decompression */
|
||||
inflateReset(strm);
|
||||
strm->adler = crc32(0L, Z_NULL, 0);
|
||||
state->how = GZIP;
|
||||
state->direct = 0;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
/* not a gzip file -- save first byte (31) and fall to raw i/o */
|
||||
state->out[0] = 31;
|
||||
state->have = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* doing raw i/o, save start of raw data for seeking, copy any leftover
|
||||
input to output -- this assumes that the output buffer is larger than
|
||||
the input buffer, which also assures space for gzungetc() */
|
||||
state->raw = state->pos;
|
||||
state->next = state->out;
|
||||
if (strm->avail_in) {
|
||||
memcpy(state->next + state->have, strm->next_in, strm->avail_in);
|
||||
state->have += strm->avail_in;
|
||||
strm->avail_in = 0;
|
||||
}
|
||||
state->how = COPY;
|
||||
state->direct = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Decompress from input to the provided next_out and avail_out in the state.
|
||||
If the end of the compressed data is reached, then verify the gzip trailer
|
||||
check value and length (modulo 2^32). state->have and state->next are set
|
||||
to point to the just decompressed data, and the crc is updated. If the
|
||||
trailer is verified, state->how is reset to LOOK to look for the next gzip
|
||||
stream or raw data, once state->have is depleted. Returns 0 on success, -1
|
||||
on failure. Failures may include invalid compressed data or a failed gzip
|
||||
trailer verification. */
|
||||
local int gz_decomp(state)
|
||||
gz_statep state;
|
||||
{
|
||||
int ret;
|
||||
unsigned had;
|
||||
unsigned long crc, len;
|
||||
z_streamp strm = &(state->strm);
|
||||
|
||||
/* fill output buffer up to end of deflate stream */
|
||||
had = strm->avail_out;
|
||||
do {
|
||||
/* get more input for inflate() */
|
||||
if (strm->avail_in == 0 && gz_avail(state) == -1)
|
||||
return -1;
|
||||
if (strm->avail_in == 0) {
|
||||
gz_error(state, Z_DATA_ERROR, "unexpected end of file");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* decompress and handle errors */
|
||||
ret = inflate(strm, Z_NO_FLUSH);
|
||||
if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {
|
||||
gz_error(state, Z_STREAM_ERROR,
|
||||
"internal error: inflate stream corrupt");
|
||||
return -1;
|
||||
}
|
||||
if (ret == Z_MEM_ERROR) {
|
||||
gz_error(state, Z_MEM_ERROR, "out of memory");
|
||||
return -1;
|
||||
}
|
||||
if (ret == Z_DATA_ERROR) { /* deflate stream invalid */
|
||||
gz_error(state, Z_DATA_ERROR,
|
||||
strm->msg == NULL ? "compressed data error" : strm->msg);
|
||||
return -1;
|
||||
}
|
||||
} while (strm->avail_out && ret != Z_STREAM_END);
|
||||
|
||||
/* update available output and crc check value */
|
||||
state->have = had - strm->avail_out;
|
||||
state->next = strm->next_out - state->have;
|
||||
strm->adler = crc32(strm->adler, state->next, state->have);
|
||||
|
||||
/* check gzip trailer if at end of deflate stream */
|
||||
if (ret == Z_STREAM_END) {
|
||||
if (gz_next4(state, &crc) == -1 || gz_next4(state, &len) == -1) {
|
||||
gz_error(state, Z_DATA_ERROR, "unexpected end of file");
|
||||
return -1;
|
||||
}
|
||||
if (crc != strm->adler) {
|
||||
gz_error(state, Z_DATA_ERROR, "incorrect data check");
|
||||
return -1;
|
||||
}
|
||||
if (len != (strm->total_out & 0xffffffffL)) {
|
||||
gz_error(state, Z_DATA_ERROR, "incorrect length check");
|
||||
return -1;
|
||||
}
|
||||
state->how = LOOK; /* ready for next stream, once have is 0 (leave
|
||||
state->direct unchanged to remember how) */
|
||||
}
|
||||
|
||||
/* good decompression */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Make data and put in the output buffer. Assumes that state->have == 0.
|
||||
Data is either copied from the input file or decompressed from the input
|
||||
file depending on state->how. If state->how is LOOK, then a gzip header is
|
||||
looked for (and skipped if found) to determine wither to copy or decompress.
|
||||
Returns -1 on error, otherwise 0. gz_make() will leave state->have as COPY
|
||||
or GZIP unless the end of the input file has been reached and all data has
|
||||
been processed. */
|
||||
local int gz_make(state)
|
||||
gz_statep state;
|
||||
{
|
||||
z_streamp strm = &(state->strm);
|
||||
|
||||
if (state->how == LOOK) { /* look for gzip header */
|
||||
if (gz_head(state) == -1)
|
||||
return -1;
|
||||
if (state->have) /* got some data from gz_head() */
|
||||
return 0;
|
||||
}
|
||||
if (state->how == COPY) { /* straight copy */
|
||||
if (gz_load(state, state->out, state->size << 1, &(state->have)) == -1)
|
||||
return -1;
|
||||
state->next = state->out;
|
||||
}
|
||||
else if (state->how == GZIP) { /* decompress */
|
||||
strm->avail_out = state->size << 1;
|
||||
strm->next_out = state->out;
|
||||
if (gz_decomp(state) == -1)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */
|
||||
local int gz_skip(state, len)
|
||||
gz_statep state;
|
||||
z_off64_t len;
|
||||
{
|
||||
unsigned n;
|
||||
|
||||
/* skip over len bytes or reach end-of-file, whichever comes first */
|
||||
while (len)
|
||||
/* skip over whatever is in output buffer */
|
||||
if (state->have) {
|
||||
n = GT_OFF(state->have) || (z_off64_t)state->have > len ?
|
||||
(unsigned)len : state->have;
|
||||
state->have -= n;
|
||||
state->next += n;
|
||||
state->pos += n;
|
||||
len -= n;
|
||||
}
|
||||
|
||||
/* output buffer empty -- return if we're at the end of the input */
|
||||
else if (state->eof && state->strm.avail_in == 0)
|
||||
break;
|
||||
|
||||
/* need more data to skip -- load up output buffer */
|
||||
else {
|
||||
/* get more output, looking for header if required */
|
||||
if (gz_make(state) == -1)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzread(file, buf, len)
|
||||
gzFile file;
|
||||
voidp buf;
|
||||
unsigned len;
|
||||
{
|
||||
unsigned got, n;
|
||||
gz_statep state;
|
||||
z_streamp strm;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
strm = &(state->strm);
|
||||
|
||||
/* check that we're reading and that there's no error */
|
||||
if (state->mode != GZ_READ || state->err != Z_OK)
|
||||
return -1;
|
||||
|
||||
/* since an int is returned, make sure len fits in one, otherwise return
|
||||
with an error (this avoids the flaw in the interface) */
|
||||
if ((int)len < 0) {
|
||||
gz_error(state, Z_BUF_ERROR, "requested length does not fit in int");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* if len is zero, avoid unnecessary operations */
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
/* process a skip request */
|
||||
if (state->seek) {
|
||||
state->seek = 0;
|
||||
if (gz_skip(state, state->skip) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* get len bytes to buf, or less than len if at the end */
|
||||
got = 0;
|
||||
do {
|
||||
/* first just try copying data from the output buffer */
|
||||
if (state->have) {
|
||||
n = state->have > len ? len : state->have;
|
||||
memcpy(buf, state->next, n);
|
||||
state->next += n;
|
||||
state->have -= n;
|
||||
}
|
||||
|
||||
/* output buffer empty -- return if we're at the end of the input */
|
||||
else if (state->eof && strm->avail_in == 0)
|
||||
break;
|
||||
|
||||
/* need output data -- for small len or new stream load up our output
|
||||
buffer */
|
||||
else if (state->how == LOOK || len < (state->size << 1)) {
|
||||
/* get more output, looking for header if required */
|
||||
if (gz_make(state) == -1)
|
||||
return -1;
|
||||
continue; /* no progress yet -- go back to memcpy() above */
|
||||
/* the copy above assures that we will leave with space in the
|
||||
output buffer, allowing at least one gzungetc() to succeed */
|
||||
}
|
||||
|
||||
/* large len -- read directly into user buffer */
|
||||
else if (state->how == COPY) { /* read directly */
|
||||
if (gz_load(state, buf, len, &n) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* large len -- decompress directly into user buffer */
|
||||
else { /* state->how == GZIP */
|
||||
strm->avail_out = len;
|
||||
strm->next_out = buf;
|
||||
if (gz_decomp(state) == -1)
|
||||
return -1;
|
||||
n = state->have;
|
||||
state->have = 0;
|
||||
}
|
||||
|
||||
/* update progress */
|
||||
len -= n;
|
||||
buf = (char *)buf + n;
|
||||
got += n;
|
||||
state->pos += n;
|
||||
} while (len);
|
||||
|
||||
/* return number of bytes read into user buffer (will fit in int) */
|
||||
return (int)got;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzgetc(file)
|
||||
gzFile file;
|
||||
{
|
||||
int ret;
|
||||
unsigned char buf[1];
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
|
||||
/* check that we're reading and that there's no error */
|
||||
if (state->mode != GZ_READ || state->err != Z_OK)
|
||||
return -1;
|
||||
|
||||
/* try output buffer (no need to check for skip request) */
|
||||
if (state->have) {
|
||||
state->have--;
|
||||
state->pos++;
|
||||
return *(state->next)++;
|
||||
}
|
||||
|
||||
/* nothing there -- try gzread() */
|
||||
ret = gzread(file, buf, 1);
|
||||
return ret < 1 ? -1 : buf[0];
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzungetc(c, file)
|
||||
int c;
|
||||
gzFile file;
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
|
||||
/* check that we're reading and that there's no error */
|
||||
if (state->mode != GZ_READ || state->err != Z_OK)
|
||||
return -1;
|
||||
|
||||
/* process a skip request */
|
||||
if (state->seek) {
|
||||
state->seek = 0;
|
||||
if (gz_skip(state, state->skip) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* can't push EOF */
|
||||
if (c < 0)
|
||||
return -1;
|
||||
|
||||
/* if output buffer empty, put byte at end (allows more pushing) */
|
||||
if (state->have == 0) {
|
||||
state->have = 1;
|
||||
state->next = state->out + (state->size << 1) - 1;
|
||||
state->next[0] = c;
|
||||
state->pos--;
|
||||
return c;
|
||||
}
|
||||
|
||||
/* if no room, give up (must have already done a gzungetc()) */
|
||||
if (state->have == (state->size << 1)) {
|
||||
gz_error(state, Z_BUF_ERROR, "out of room to push characters");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* slide output data if needed and insert byte before existing data */
|
||||
if (state->next == state->out) {
|
||||
unsigned char *src = state->out + state->have;
|
||||
unsigned char *dest = state->out + (state->size << 1);
|
||||
while (src > state->out)
|
||||
*--dest = *--src;
|
||||
state->next = dest;
|
||||
}
|
||||
state->have++;
|
||||
state->next--;
|
||||
state->next[0] = c;
|
||||
state->pos--;
|
||||
return c;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
char * ZEXPORT gzgets(file, buf, len)
|
||||
gzFile file;
|
||||
char *buf;
|
||||
int len;
|
||||
{
|
||||
unsigned left, n;
|
||||
char *str;
|
||||
unsigned char *eol;
|
||||
gz_statep state;
|
||||
|
||||
/* check parameters and get internal structure */
|
||||
if (file == NULL || buf == NULL || len < 1)
|
||||
return NULL;
|
||||
state = (gz_statep)file;
|
||||
|
||||
/* check that we're reading and that there's no error */
|
||||
if (state->mode != GZ_READ || state->err != Z_OK)
|
||||
return NULL;
|
||||
|
||||
/* process a skip request */
|
||||
if (state->seek) {
|
||||
state->seek = 0;
|
||||
if (gz_skip(state, state->skip) == -1)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* copy output bytes up to new line or len - 1, whichever comes first --
|
||||
append a terminating zero to the string (we don't check for a zero in
|
||||
the contents, let the user worry about that) */
|
||||
str = buf;
|
||||
left = (unsigned)len - 1;
|
||||
if (left) do {
|
||||
/* assure that something is in the output buffer */
|
||||
if (state->have == 0) {
|
||||
if (gz_make(state) == -1)
|
||||
return NULL; /* error */
|
||||
if (state->have == 0) { /* end of file */
|
||||
if (buf == str) /* got bupkus */
|
||||
return NULL;
|
||||
break; /* got something -- return it */
|
||||
}
|
||||
}
|
||||
|
||||
/* look for end-of-line in current output buffer */
|
||||
n = state->have > left ? left : state->have;
|
||||
eol = memchr(state->next, '\n', n);
|
||||
if (eol != NULL)
|
||||
n = (unsigned)(eol - state->next) + 1;
|
||||
|
||||
/* copy through end-of-line, or remainder if not found */
|
||||
memcpy(buf, state->next, n);
|
||||
state->have -= n;
|
||||
state->next += n;
|
||||
state->pos += n;
|
||||
left -= n;
|
||||
buf += n;
|
||||
} while (left && eol == NULL);
|
||||
|
||||
/* found end-of-line or out of space -- terminate string and return it */
|
||||
buf[0] = 0;
|
||||
return str;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzdirect(file)
|
||||
gzFile file;
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return 0;
|
||||
state = (gz_statep)file;
|
||||
|
||||
/* check that we're reading */
|
||||
if (state->mode != GZ_READ)
|
||||
return 0;
|
||||
|
||||
/* if the state is not known, but we can find out, then do so (this is
|
||||
mainly for right after a gzopen() or gzdopen()) */
|
||||
if (state->how == LOOK && state->have == 0)
|
||||
(void)gz_head(state);
|
||||
|
||||
/* return 1 if reading direct, 0 if decompressing a gzip stream */
|
||||
return state->direct;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzclose_r(file)
|
||||
gzFile file;
|
||||
{
|
||||
int ret;
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
state = (gz_statep)file;
|
||||
|
||||
/* check that we're reading */
|
||||
if (state->mode != GZ_READ)
|
||||
return Z_STREAM_ERROR;
|
||||
|
||||
/* free memory and close file */
|
||||
if (state->size) {
|
||||
inflateEnd(&(state->strm));
|
||||
free(state->out);
|
||||
free(state->in);
|
||||
}
|
||||
gz_error(state, Z_OK, NULL);
|
||||
free(state->path);
|
||||
ret = close(state->fd);
|
||||
free(state);
|
||||
return ret ? Z_ERRNO : Z_OK;
|
||||
}
|
||||
531
dependencies/libwebsockets/win32port/zlib/gzwrite.c
vendored
Normal file
531
dependencies/libwebsockets/win32port/zlib/gzwrite.c
vendored
Normal file
@ -0,0 +1,531 @@
|
||||
/* gzwrite.c -- zlib functions for writing gzip files
|
||||
* Copyright (C) 2004, 2005, 2010 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "gzguts.h"
|
||||
|
||||
/* Local functions */
|
||||
local int gz_init OF((gz_statep));
|
||||
local int gz_comp OF((gz_statep, int));
|
||||
local int gz_zero OF((gz_statep, z_off64_t));
|
||||
|
||||
/* Initialize state for writing a gzip file. Mark initialization by setting
|
||||
state->size to non-zero. Return -1 on failure or 0 on success. */
|
||||
local int gz_init(state)
|
||||
gz_statep state;
|
||||
{
|
||||
int ret;
|
||||
z_streamp strm = &(state->strm);
|
||||
|
||||
/* allocate input and output buffers */
|
||||
state->in = malloc(state->want);
|
||||
state->out = malloc(state->want);
|
||||
if (state->in == NULL || state->out == NULL) {
|
||||
if (state->out != NULL)
|
||||
free(state->out);
|
||||
if (state->in != NULL)
|
||||
free(state->in);
|
||||
gz_error(state, Z_MEM_ERROR, "out of memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* allocate deflate memory, set up for gzip compression */
|
||||
strm->zalloc = Z_NULL;
|
||||
strm->zfree = Z_NULL;
|
||||
strm->opaque = Z_NULL;
|
||||
ret = deflateInit2(strm, state->level, Z_DEFLATED,
|
||||
15 + 16, 8, state->strategy);
|
||||
if (ret != Z_OK) {
|
||||
free(state->in);
|
||||
gz_error(state, Z_MEM_ERROR, "out of memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* mark state as initialized */
|
||||
state->size = state->want;
|
||||
|
||||
/* initialize write buffer */
|
||||
strm->avail_out = state->size;
|
||||
strm->next_out = state->out;
|
||||
state->next = strm->next_out;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Compress whatever is at avail_in and next_in and write to the output file.
|
||||
Return -1 if there is an error writing to the output file, otherwise 0.
|
||||
flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH,
|
||||
then the deflate() state is reset to start a new gzip stream. */
|
||||
local int gz_comp(state, flush)
|
||||
gz_statep state;
|
||||
int flush;
|
||||
{
|
||||
int ret, got;
|
||||
unsigned have;
|
||||
z_streamp strm = &(state->strm);
|
||||
|
||||
/* allocate memory if this is the first time through */
|
||||
if (state->size == 0 && gz_init(state) == -1)
|
||||
return -1;
|
||||
|
||||
/* run deflate() on provided input until it produces no more output */
|
||||
ret = Z_OK;
|
||||
do {
|
||||
/* write out current buffer contents if full, or if flushing, but if
|
||||
doing Z_FINISH then don't write until we get to Z_STREAM_END */
|
||||
if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
|
||||
(flush != Z_FINISH || ret == Z_STREAM_END))) {
|
||||
have = (unsigned)(strm->next_out - state->next);
|
||||
if (have && ((got = write(state->fd, state->next, have)) < 0 ||
|
||||
(unsigned)got != have)) {
|
||||
gz_error(state, Z_ERRNO, zstrerror());
|
||||
return -1;
|
||||
}
|
||||
if (strm->avail_out == 0) {
|
||||
strm->avail_out = state->size;
|
||||
strm->next_out = state->out;
|
||||
}
|
||||
state->next = strm->next_out;
|
||||
}
|
||||
|
||||
/* compress */
|
||||
have = strm->avail_out;
|
||||
ret = deflate(strm, flush);
|
||||
if (ret == Z_STREAM_ERROR) {
|
||||
gz_error(state, Z_STREAM_ERROR,
|
||||
"internal error: deflate stream corrupt");
|
||||
return -1;
|
||||
}
|
||||
have -= strm->avail_out;
|
||||
} while (have);
|
||||
|
||||
/* if that completed a deflate stream, allow another to start */
|
||||
if (flush == Z_FINISH)
|
||||
deflateReset(strm);
|
||||
|
||||
/* all done, no errors */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Compress len zeros to output. Return -1 on error, 0 on success. */
|
||||
local int gz_zero(state, len)
|
||||
gz_statep state;
|
||||
z_off64_t len;
|
||||
{
|
||||
int first;
|
||||
unsigned n;
|
||||
z_streamp strm = &(state->strm);
|
||||
|
||||
/* consume whatever's left in the input buffer */
|
||||
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
|
||||
return -1;
|
||||
|
||||
/* compress len zeros (len guaranteed > 0) */
|
||||
first = 1;
|
||||
while (len) {
|
||||
n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
|
||||
(unsigned)len : state->size;
|
||||
if (first) {
|
||||
memset(state->in, 0, n);
|
||||
first = 0;
|
||||
}
|
||||
strm->avail_in = n;
|
||||
strm->next_in = state->in;
|
||||
state->pos += n;
|
||||
if (gz_comp(state, Z_NO_FLUSH) == -1)
|
||||
return -1;
|
||||
len -= n;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzwrite(file, buf, len)
|
||||
gzFile file;
|
||||
voidpc buf;
|
||||
unsigned len;
|
||||
{
|
||||
unsigned put = len;
|
||||
unsigned n;
|
||||
gz_statep state;
|
||||
z_streamp strm;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return 0;
|
||||
state = (gz_statep)file;
|
||||
strm = &(state->strm);
|
||||
|
||||
/* check that we're writing and that there's no error */
|
||||
if (state->mode != GZ_WRITE || state->err != Z_OK)
|
||||
return 0;
|
||||
|
||||
/* since an int is returned, make sure len fits in one, otherwise return
|
||||
with an error (this avoids the flaw in the interface) */
|
||||
if ((int)len < 0) {
|
||||
gz_error(state, Z_BUF_ERROR, "requested length does not fit in int");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if len is zero, avoid unnecessary operations */
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
/* allocate memory if this is the first time through */
|
||||
if (state->size == 0 && gz_init(state) == -1)
|
||||
return 0;
|
||||
|
||||
/* check for seek request */
|
||||
if (state->seek) {
|
||||
state->seek = 0;
|
||||
if (gz_zero(state, state->skip) == -1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* for small len, copy to input buffer, otherwise compress directly */
|
||||
if (len < state->size) {
|
||||
/* copy to input buffer, compress when full */
|
||||
do {
|
||||
if (strm->avail_in == 0)
|
||||
strm->next_in = state->in;
|
||||
n = state->size - strm->avail_in;
|
||||
if (n > len)
|
||||
n = len;
|
||||
memcpy(strm->next_in + strm->avail_in, buf, n);
|
||||
strm->avail_in += n;
|
||||
state->pos += n;
|
||||
buf = (char *)buf + n;
|
||||
len -= n;
|
||||
if (len && gz_comp(state, Z_NO_FLUSH) == -1)
|
||||
return 0;
|
||||
} while (len);
|
||||
}
|
||||
else {
|
||||
/* consume whatever's left in the input buffer */
|
||||
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
|
||||
return 0;
|
||||
|
||||
/* directly compress user buffer to file */
|
||||
strm->avail_in = len;
|
||||
strm->next_in = (voidp)buf;
|
||||
state->pos += len;
|
||||
if (gz_comp(state, Z_NO_FLUSH) == -1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* input was all buffered or compressed (put will fit in int) */
|
||||
return (int)put;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzputc(file, c)
|
||||
gzFile file;
|
||||
int c;
|
||||
{
|
||||
unsigned char buf[1];
|
||||
gz_statep state;
|
||||
z_streamp strm;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
strm = &(state->strm);
|
||||
|
||||
/* check that we're writing and that there's no error */
|
||||
if (state->mode != GZ_WRITE || state->err != Z_OK)
|
||||
return -1;
|
||||
|
||||
/* check for seek request */
|
||||
if (state->seek) {
|
||||
state->seek = 0;
|
||||
if (gz_zero(state, state->skip) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* try writing to input buffer for speed (state->size == 0 if buffer not
|
||||
initialized) */
|
||||
if (strm->avail_in < state->size) {
|
||||
if (strm->avail_in == 0)
|
||||
strm->next_in = state->in;
|
||||
strm->next_in[strm->avail_in++] = c;
|
||||
state->pos++;
|
||||
return c;
|
||||
}
|
||||
|
||||
/* no room in buffer or not initialized, use gz_write() */
|
||||
buf[0] = c;
|
||||
if (gzwrite(file, buf, 1) != 1)
|
||||
return -1;
|
||||
return c;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzputs(file, str)
|
||||
gzFile file;
|
||||
const char *str;
|
||||
{
|
||||
int ret;
|
||||
unsigned len;
|
||||
|
||||
/* write string */
|
||||
len = (unsigned)strlen(str);
|
||||
ret = gzwrite(file, str, len);
|
||||
return ret == 0 && len != 0 ? -1 : ret;
|
||||
}
|
||||
|
||||
#ifdef STDC
|
||||
#include <stdarg.h>
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORTVA gzprintf (gzFile file, const char *format, ...)
|
||||
{
|
||||
int size, len;
|
||||
gz_statep state;
|
||||
z_streamp strm;
|
||||
va_list va;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
strm = &(state->strm);
|
||||
|
||||
/* check that we're writing and that there's no error */
|
||||
if (state->mode != GZ_WRITE || state->err != Z_OK)
|
||||
return 0;
|
||||
|
||||
/* make sure we have some buffer space */
|
||||
if (state->size == 0 && gz_init(state) == -1)
|
||||
return 0;
|
||||
|
||||
/* check for seek request */
|
||||
if (state->seek) {
|
||||
state->seek = 0;
|
||||
if (gz_zero(state, state->skip) == -1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* consume whatever's left in the input buffer */
|
||||
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
|
||||
return 0;
|
||||
|
||||
/* do the printf() into the input buffer, put length in len */
|
||||
size = (int)(state->size);
|
||||
state->in[size - 1] = 0;
|
||||
va_start(va, format);
|
||||
#ifdef NO_vsnprintf
|
||||
# ifdef HAS_vsprintf_void
|
||||
(void)vsprintf(state->in, format, va);
|
||||
va_end(va);
|
||||
for (len = 0; len < size; len++)
|
||||
if (state->in[len] == 0) break;
|
||||
# else
|
||||
len = vsprintf(state->in, format, va);
|
||||
va_end(va);
|
||||
# endif
|
||||
#else
|
||||
# ifdef HAS_vsnprintf_void
|
||||
(void)vsnprintf(state->in, size, format, va);
|
||||
va_end(va);
|
||||
len = strlen(state->in);
|
||||
# else
|
||||
len = vsnprintf((char *)(state->in), size, format, va);
|
||||
va_end(va);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* check that printf() results fit in buffer */
|
||||
if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
|
||||
return 0;
|
||||
|
||||
/* update buffer and position, defer compression until needed */
|
||||
strm->avail_in = (unsigned)len;
|
||||
strm->next_in = state->in;
|
||||
state->pos += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
#else /* !STDC */
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
|
||||
a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
gzFile file;
|
||||
const char *format;
|
||||
int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
|
||||
a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
|
||||
{
|
||||
int size, len;
|
||||
gz_statep state;
|
||||
z_streamp strm;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
strm = &(state->strm);
|
||||
|
||||
/* check that we're writing and that there's no error */
|
||||
if (state->mode != GZ_WRITE || state->err != Z_OK)
|
||||
return 0;
|
||||
|
||||
/* make sure we have some buffer space */
|
||||
if (state->size == 0 && gz_init(state) == -1)
|
||||
return 0;
|
||||
|
||||
/* check for seek request */
|
||||
if (state->seek) {
|
||||
state->seek = 0;
|
||||
if (gz_zero(state, state->skip) == -1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* consume whatever's left in the input buffer */
|
||||
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
|
||||
return 0;
|
||||
|
||||
/* do the printf() into the input buffer, put length in len */
|
||||
size = (int)(state->size);
|
||||
state->in[size - 1] = 0;
|
||||
#ifdef NO_snprintf
|
||||
# ifdef HAS_sprintf_void
|
||||
sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8,
|
||||
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
|
||||
for (len = 0; len < size; len++)
|
||||
if (state->in[len] == 0) break;
|
||||
# else
|
||||
len = sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8,
|
||||
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
|
||||
# endif
|
||||
#else
|
||||
# ifdef HAS_snprintf_void
|
||||
snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8,
|
||||
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
|
||||
len = strlen(state->in);
|
||||
# else
|
||||
len = snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8,
|
||||
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* check that printf() results fit in buffer */
|
||||
if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
|
||||
return 0;
|
||||
|
||||
/* update buffer and position, defer compression until needed */
|
||||
strm->avail_in = (unsigned)len;
|
||||
strm->next_in = state->in;
|
||||
state->pos += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzflush(file, flush)
|
||||
gzFile file;
|
||||
int flush;
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
|
||||
/* check that we're writing and that there's no error */
|
||||
if (state->mode != GZ_WRITE || state->err != Z_OK)
|
||||
return Z_STREAM_ERROR;
|
||||
|
||||
/* check flush parameter */
|
||||
if (flush < 0 || flush > Z_FINISH)
|
||||
return Z_STREAM_ERROR;
|
||||
|
||||
/* check for seek request */
|
||||
if (state->seek) {
|
||||
state->seek = 0;
|
||||
if (gz_zero(state, state->skip) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* compress remaining data with requested flush */
|
||||
gz_comp(state, flush);
|
||||
return state->err;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzsetparams(file, level, strategy)
|
||||
gzFile file;
|
||||
int level;
|
||||
int strategy;
|
||||
{
|
||||
gz_statep state;
|
||||
z_streamp strm;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
state = (gz_statep)file;
|
||||
strm = &(state->strm);
|
||||
|
||||
/* check that we're writing and that there's no error */
|
||||
if (state->mode != GZ_WRITE || state->err != Z_OK)
|
||||
return Z_STREAM_ERROR;
|
||||
|
||||
/* if no change is requested, then do nothing */
|
||||
if (level == state->level && strategy == state->strategy)
|
||||
return Z_OK;
|
||||
|
||||
/* check for seek request */
|
||||
if (state->seek) {
|
||||
state->seek = 0;
|
||||
if (gz_zero(state, state->skip) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* change compression parameters for subsequent input */
|
||||
if (state->size) {
|
||||
/* flush previous input with previous parameters before changing */
|
||||
if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1)
|
||||
return state->err;
|
||||
deflateParams(strm, level, strategy);
|
||||
}
|
||||
state->level = level;
|
||||
state->strategy = strategy;
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzclose_w(file)
|
||||
gzFile file;
|
||||
{
|
||||
int ret = 0;
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
state = (gz_statep)file;
|
||||
|
||||
/* check that we're writing */
|
||||
if (state->mode != GZ_WRITE)
|
||||
return Z_STREAM_ERROR;
|
||||
|
||||
/* check for seek request */
|
||||
if (state->seek) {
|
||||
state->seek = 0;
|
||||
ret += gz_zero(state, state->skip);
|
||||
}
|
||||
|
||||
/* flush, free memory, and close file */
|
||||
ret += gz_comp(state, Z_FINISH);
|
||||
(void)deflateEnd(&(state->strm));
|
||||
free(state->out);
|
||||
free(state->in);
|
||||
gz_error(state, Z_OK, NULL);
|
||||
free(state->path);
|
||||
ret += close(state->fd);
|
||||
free(state);
|
||||
return ret ? Z_ERRNO : Z_OK;
|
||||
}
|
||||
632
dependencies/libwebsockets/win32port/zlib/infback.c
vendored
Normal file
632
dependencies/libwebsockets/win32port/zlib/infback.c
vendored
Normal file
@ -0,0 +1,632 @@
|
||||
/* infback.c -- inflate using a call-back interface
|
||||
* Copyright (C) 1995-2009 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/*
|
||||
This code is largely copied from inflate.c. Normally either infback.o or
|
||||
inflate.o would be linked into an application--not both. The interface
|
||||
with inffast.c is retained so that optimized assembler-coded versions of
|
||||
inflate_fast() can be used with either inflate.c or infback.c.
|
||||
*/
|
||||
|
||||
#include "zutil.h"
|
||||
#include "inftrees.h"
|
||||
#include "inflate.h"
|
||||
#include "inffast.h"
|
||||
|
||||
/* function prototypes */
|
||||
local void fixedtables OF((struct inflate_state FAR *state));
|
||||
|
||||
/*
|
||||
strm provides memory allocation functions in zalloc and zfree, or
|
||||
Z_NULL to use the library memory allocation functions.
|
||||
|
||||
windowBits is in the range 8..15, and window is a user-supplied
|
||||
window and output buffer that is 2**windowBits bytes.
|
||||
*/
|
||||
int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
|
||||
z_streamp strm;
|
||||
int windowBits;
|
||||
unsigned char FAR *window;
|
||||
const char *version;
|
||||
int stream_size;
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
|
||||
if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
|
||||
stream_size != (int)(sizeof(z_stream)))
|
||||
return Z_VERSION_ERROR;
|
||||
if (strm == Z_NULL || window == Z_NULL ||
|
||||
windowBits < 8 || windowBits > 15)
|
||||
return Z_STREAM_ERROR;
|
||||
strm->msg = Z_NULL; /* in case we return an error */
|
||||
if (strm->zalloc == (alloc_func)0) {
|
||||
strm->zalloc = zcalloc;
|
||||
strm->opaque = (voidpf)0;
|
||||
}
|
||||
if (strm->zfree == (free_func)0) strm->zfree = zcfree;
|
||||
state = (struct inflate_state FAR *)ZALLOC(strm, 1,
|
||||
sizeof(struct inflate_state));
|
||||
if (state == Z_NULL) return Z_MEM_ERROR;
|
||||
Tracev((stderr, "inflate: allocated\n"));
|
||||
strm->state = (struct internal_state FAR *)state;
|
||||
state->dmax = 32768U;
|
||||
state->wbits = windowBits;
|
||||
state->wsize = 1U << windowBits;
|
||||
state->window = window;
|
||||
state->wnext = 0;
|
||||
state->whave = 0;
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
Return state with length and distance decoding tables and index sizes set to
|
||||
fixed code decoding. Normally this returns fixed tables from inffixed.h.
|
||||
If BUILDFIXED is defined, then instead this routine builds the tables the
|
||||
first time it's called, and returns those tables the first time and
|
||||
thereafter. This reduces the size of the code by about 2K bytes, in
|
||||
exchange for a little execution time. However, BUILDFIXED should not be
|
||||
used for threaded applications, since the rewriting of the tables and virgin
|
||||
may not be thread-safe.
|
||||
*/
|
||||
local void fixedtables(state)
|
||||
struct inflate_state FAR *state;
|
||||
{
|
||||
#ifdef BUILDFIXED
|
||||
static int virgin = 1;
|
||||
static code *lenfix, *distfix;
|
||||
static code fixed[544];
|
||||
|
||||
/* build fixed huffman tables if first call (may not be thread safe) */
|
||||
if (virgin) {
|
||||
unsigned sym, bits;
|
||||
static code *next;
|
||||
|
||||
/* literal/length table */
|
||||
sym = 0;
|
||||
while (sym < 144) state->lens[sym++] = 8;
|
||||
while (sym < 256) state->lens[sym++] = 9;
|
||||
while (sym < 280) state->lens[sym++] = 7;
|
||||
while (sym < 288) state->lens[sym++] = 8;
|
||||
next = fixed;
|
||||
lenfix = next;
|
||||
bits = 9;
|
||||
inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
|
||||
|
||||
/* distance table */
|
||||
sym = 0;
|
||||
while (sym < 32) state->lens[sym++] = 5;
|
||||
distfix = next;
|
||||
bits = 5;
|
||||
inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
|
||||
|
||||
/* do this just once */
|
||||
virgin = 0;
|
||||
}
|
||||
#else /* !BUILDFIXED */
|
||||
# include "inffixed.h"
|
||||
#endif /* BUILDFIXED */
|
||||
state->lencode = lenfix;
|
||||
state->lenbits = 9;
|
||||
state->distcode = distfix;
|
||||
state->distbits = 5;
|
||||
}
|
||||
|
||||
/* Macros for inflateBack(): */
|
||||
|
||||
/* Load returned state from inflate_fast() */
|
||||
#define LOAD() \
|
||||
do { \
|
||||
put = strm->next_out; \
|
||||
left = strm->avail_out; \
|
||||
next = strm->next_in; \
|
||||
have = strm->avail_in; \
|
||||
hold = state->hold; \
|
||||
bits = state->bits; \
|
||||
} while (0)
|
||||
|
||||
/* Set state from registers for inflate_fast() */
|
||||
#define RESTORE() \
|
||||
do { \
|
||||
strm->next_out = put; \
|
||||
strm->avail_out = left; \
|
||||
strm->next_in = next; \
|
||||
strm->avail_in = have; \
|
||||
state->hold = hold; \
|
||||
state->bits = bits; \
|
||||
} while (0)
|
||||
|
||||
/* Clear the input bit accumulator */
|
||||
#define INITBITS() \
|
||||
do { \
|
||||
hold = 0; \
|
||||
bits = 0; \
|
||||
} while (0)
|
||||
|
||||
/* Assure that some input is available. If input is requested, but denied,
|
||||
then return a Z_BUF_ERROR from inflateBack(). */
|
||||
#define PULL() \
|
||||
do { \
|
||||
if (have == 0) { \
|
||||
have = in(in_desc, &next); \
|
||||
if (have == 0) { \
|
||||
next = Z_NULL; \
|
||||
ret = Z_BUF_ERROR; \
|
||||
goto inf_leave; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Get a byte of input into the bit accumulator, or return from inflateBack()
|
||||
with an error if there is no input available. */
|
||||
#define PULLBYTE() \
|
||||
do { \
|
||||
PULL(); \
|
||||
have--; \
|
||||
hold += (unsigned long)(*next++) << bits; \
|
||||
bits += 8; \
|
||||
} while (0)
|
||||
|
||||
/* Assure that there are at least n bits in the bit accumulator. If there is
|
||||
not enough available input to do that, then return from inflateBack() with
|
||||
an error. */
|
||||
#define NEEDBITS(n) \
|
||||
do { \
|
||||
while (bits < (unsigned)(n)) \
|
||||
PULLBYTE(); \
|
||||
} while (0)
|
||||
|
||||
/* Return the low n bits of the bit accumulator (n < 16) */
|
||||
#define BITS(n) \
|
||||
((unsigned)hold & ((1U << (n)) - 1))
|
||||
|
||||
/* Remove n bits from the bit accumulator */
|
||||
#define DROPBITS(n) \
|
||||
do { \
|
||||
hold >>= (n); \
|
||||
bits -= (unsigned)(n); \
|
||||
} while (0)
|
||||
|
||||
/* Remove zero to seven bits as needed to go to a byte boundary */
|
||||
#define BYTEBITS() \
|
||||
do { \
|
||||
hold >>= bits & 7; \
|
||||
bits -= bits & 7; \
|
||||
} while (0)
|
||||
|
||||
/* Assure that some output space is available, by writing out the window
|
||||
if it's full. If the write fails, return from inflateBack() with a
|
||||
Z_BUF_ERROR. */
|
||||
#define ROOM() \
|
||||
do { \
|
||||
if (left == 0) { \
|
||||
put = state->window; \
|
||||
left = state->wsize; \
|
||||
state->whave = left; \
|
||||
if (out(out_desc, put, left)) { \
|
||||
ret = Z_BUF_ERROR; \
|
||||
goto inf_leave; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
strm provides the memory allocation functions and window buffer on input,
|
||||
and provides information on the unused input on return. For Z_DATA_ERROR
|
||||
returns, strm will also provide an error message.
|
||||
|
||||
in() and out() are the call-back input and output functions. When
|
||||
inflateBack() needs more input, it calls in(). When inflateBack() has
|
||||
filled the window with output, or when it completes with data in the
|
||||
window, it calls out() to write out the data. The application must not
|
||||
change the provided input until in() is called again or inflateBack()
|
||||
returns. The application must not change the window/output buffer until
|
||||
inflateBack() returns.
|
||||
|
||||
in() and out() are called with a descriptor parameter provided in the
|
||||
inflateBack() call. This parameter can be a structure that provides the
|
||||
information required to do the read or write, as well as accumulated
|
||||
information on the input and output such as totals and check values.
|
||||
|
||||
in() should return zero on failure. out() should return non-zero on
|
||||
failure. If either in() or out() fails, than inflateBack() returns a
|
||||
Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it
|
||||
was in() or out() that caused in the error. Otherwise, inflateBack()
|
||||
returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
|
||||
error, or Z_MEM_ERROR if it could not allocate memory for the state.
|
||||
inflateBack() can also return Z_STREAM_ERROR if the input parameters
|
||||
are not correct, i.e. strm is Z_NULL or the state was not initialized.
|
||||
*/
|
||||
int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
|
||||
z_streamp strm;
|
||||
in_func in;
|
||||
void FAR *in_desc;
|
||||
out_func out;
|
||||
void FAR *out_desc;
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
unsigned char FAR *next; /* next input */
|
||||
unsigned char FAR *put; /* next output */
|
||||
unsigned have, left; /* available input and output */
|
||||
unsigned long hold; /* bit buffer */
|
||||
unsigned bits; /* bits in bit buffer */
|
||||
unsigned copy; /* number of stored or match bytes to copy */
|
||||
unsigned char FAR *from; /* where to copy match bytes from */
|
||||
code here; /* current decoding table entry */
|
||||
code last; /* parent table entry */
|
||||
unsigned len; /* length to copy for repeats, bits to drop */
|
||||
int ret; /* return code */
|
||||
static const unsigned short order[19] = /* permutation of code lengths */
|
||||
{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
|
||||
|
||||
/* Check that the strm exists and that the state was initialized */
|
||||
if (strm == Z_NULL || strm->state == Z_NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
state = (struct inflate_state FAR *)strm->state;
|
||||
|
||||
/* Reset the state */
|
||||
strm->msg = Z_NULL;
|
||||
state->mode = TYPE;
|
||||
state->last = 0;
|
||||
state->whave = 0;
|
||||
next = strm->next_in;
|
||||
have = next != Z_NULL ? strm->avail_in : 0;
|
||||
hold = 0;
|
||||
bits = 0;
|
||||
put = state->window;
|
||||
left = state->wsize;
|
||||
|
||||
/* Inflate until end of block marked as last */
|
||||
for (;;)
|
||||
switch (state->mode) {
|
||||
case TYPE:
|
||||
/* determine and dispatch block type */
|
||||
if (state->last) {
|
||||
BYTEBITS();
|
||||
state->mode = DONE;
|
||||
break;
|
||||
}
|
||||
NEEDBITS(3);
|
||||
state->last = BITS(1);
|
||||
DROPBITS(1);
|
||||
switch (BITS(2)) {
|
||||
case 0: /* stored block */
|
||||
Tracev((stderr, "inflate: stored block%s\n",
|
||||
state->last ? " (last)" : ""));
|
||||
state->mode = STORED;
|
||||
break;
|
||||
case 1: /* fixed block */
|
||||
fixedtables(state);
|
||||
Tracev((stderr, "inflate: fixed codes block%s\n",
|
||||
state->last ? " (last)" : ""));
|
||||
state->mode = LEN; /* decode codes */
|
||||
break;
|
||||
case 2: /* dynamic block */
|
||||
Tracev((stderr, "inflate: dynamic codes block%s\n",
|
||||
state->last ? " (last)" : ""));
|
||||
state->mode = TABLE;
|
||||
break;
|
||||
case 3:
|
||||
strm->msg = (char *)"invalid block type";
|
||||
state->mode = BAD;
|
||||
}
|
||||
DROPBITS(2);
|
||||
break;
|
||||
|
||||
case STORED:
|
||||
/* get and verify stored block length */
|
||||
BYTEBITS(); /* go to byte boundary */
|
||||
NEEDBITS(32);
|
||||
if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
|
||||
strm->msg = (char *)"invalid stored block lengths";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
state->length = (unsigned)hold & 0xffff;
|
||||
Tracev((stderr, "inflate: stored length %u\n",
|
||||
state->length));
|
||||
INITBITS();
|
||||
|
||||
/* copy stored block from input to output */
|
||||
while (state->length != 0) {
|
||||
copy = state->length;
|
||||
PULL();
|
||||
ROOM();
|
||||
if (copy > have) copy = have;
|
||||
if (copy > left) copy = left;
|
||||
zmemcpy(put, next, copy);
|
||||
have -= copy;
|
||||
next += copy;
|
||||
left -= copy;
|
||||
put += copy;
|
||||
state->length -= copy;
|
||||
}
|
||||
Tracev((stderr, "inflate: stored end\n"));
|
||||
state->mode = TYPE;
|
||||
break;
|
||||
|
||||
case TABLE:
|
||||
/* get dynamic table entries descriptor */
|
||||
NEEDBITS(14);
|
||||
state->nlen = BITS(5) + 257;
|
||||
DROPBITS(5);
|
||||
state->ndist = BITS(5) + 1;
|
||||
DROPBITS(5);
|
||||
state->ncode = BITS(4) + 4;
|
||||
DROPBITS(4);
|
||||
#ifndef PKZIP_BUG_WORKAROUND
|
||||
if (state->nlen > 286 || state->ndist > 30) {
|
||||
strm->msg = (char *)"too many length or distance symbols";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
Tracev((stderr, "inflate: table sizes ok\n"));
|
||||
|
||||
/* get code length code lengths (not a typo) */
|
||||
state->have = 0;
|
||||
while (state->have < state->ncode) {
|
||||
NEEDBITS(3);
|
||||
state->lens[order[state->have++]] = (unsigned short)BITS(3);
|
||||
DROPBITS(3);
|
||||
}
|
||||
while (state->have < 19)
|
||||
state->lens[order[state->have++]] = 0;
|
||||
state->next = state->codes;
|
||||
state->lencode = (code const FAR *)(state->next);
|
||||
state->lenbits = 7;
|
||||
ret = inflate_table(CODES, state->lens, 19, &(state->next),
|
||||
&(state->lenbits), state->work);
|
||||
if (ret) {
|
||||
strm->msg = (char *)"invalid code lengths set";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
Tracev((stderr, "inflate: code lengths ok\n"));
|
||||
|
||||
/* get length and distance code code lengths */
|
||||
state->have = 0;
|
||||
while (state->have < state->nlen + state->ndist) {
|
||||
for (;;) {
|
||||
here = state->lencode[BITS(state->lenbits)];
|
||||
if ((unsigned)(here.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
if (here.val < 16) {
|
||||
NEEDBITS(here.bits);
|
||||
DROPBITS(here.bits);
|
||||
state->lens[state->have++] = here.val;
|
||||
}
|
||||
else {
|
||||
if (here.val == 16) {
|
||||
NEEDBITS(here.bits + 2);
|
||||
DROPBITS(here.bits);
|
||||
if (state->have == 0) {
|
||||
strm->msg = (char *)"invalid bit length repeat";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
len = (unsigned)(state->lens[state->have - 1]);
|
||||
copy = 3 + BITS(2);
|
||||
DROPBITS(2);
|
||||
}
|
||||
else if (here.val == 17) {
|
||||
NEEDBITS(here.bits + 3);
|
||||
DROPBITS(here.bits);
|
||||
len = 0;
|
||||
copy = 3 + BITS(3);
|
||||
DROPBITS(3);
|
||||
}
|
||||
else {
|
||||
NEEDBITS(here.bits + 7);
|
||||
DROPBITS(here.bits);
|
||||
len = 0;
|
||||
copy = 11 + BITS(7);
|
||||
DROPBITS(7);
|
||||
}
|
||||
if (state->have + copy > state->nlen + state->ndist) {
|
||||
strm->msg = (char *)"invalid bit length repeat";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
while (copy--)
|
||||
state->lens[state->have++] = (unsigned short)len;
|
||||
}
|
||||
}
|
||||
|
||||
/* handle error breaks in while */
|
||||
if (state->mode == BAD) break;
|
||||
|
||||
/* check for end-of-block code (better have one) */
|
||||
if (state->lens[256] == 0) {
|
||||
strm->msg = (char *)"invalid code -- missing end-of-block";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
|
||||
/* build code tables -- note: do not change the lenbits or distbits
|
||||
values here (9 and 6) without reading the comments in inftrees.h
|
||||
concerning the ENOUGH constants, which depend on those values */
|
||||
state->next = state->codes;
|
||||
state->lencode = (code const FAR *)(state->next);
|
||||
state->lenbits = 9;
|
||||
ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
|
||||
&(state->lenbits), state->work);
|
||||
if (ret) {
|
||||
strm->msg = (char *)"invalid literal/lengths set";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
state->distcode = (code const FAR *)(state->next);
|
||||
state->distbits = 6;
|
||||
ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
|
||||
&(state->next), &(state->distbits), state->work);
|
||||
if (ret) {
|
||||
strm->msg = (char *)"invalid distances set";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
Tracev((stderr, "inflate: codes ok\n"));
|
||||
state->mode = LEN;
|
||||
|
||||
case LEN:
|
||||
/* use inflate_fast() if we have enough input and output */
|
||||
if (have >= 6 && left >= 258) {
|
||||
RESTORE();
|
||||
if (state->whave < state->wsize)
|
||||
state->whave = state->wsize - left;
|
||||
inflate_fast(strm, state->wsize);
|
||||
LOAD();
|
||||
break;
|
||||
}
|
||||
|
||||
/* get a literal, length, or end-of-block code */
|
||||
for (;;) {
|
||||
here = state->lencode[BITS(state->lenbits)];
|
||||
if ((unsigned)(here.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
if (here.op && (here.op & 0xf0) == 0) {
|
||||
last = here;
|
||||
for (;;) {
|
||||
here = state->lencode[last.val +
|
||||
(BITS(last.bits + last.op) >> last.bits)];
|
||||
if ((unsigned)(last.bits + here.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
DROPBITS(last.bits);
|
||||
}
|
||||
DROPBITS(here.bits);
|
||||
state->length = (unsigned)here.val;
|
||||
|
||||
/* process literal */
|
||||
if (here.op == 0) {
|
||||
Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
|
||||
"inflate: literal '%c'\n" :
|
||||
"inflate: literal 0x%02x\n", here.val));
|
||||
ROOM();
|
||||
*put++ = (unsigned char)(state->length);
|
||||
left--;
|
||||
state->mode = LEN;
|
||||
break;
|
||||
}
|
||||
|
||||
/* process end of block */
|
||||
if (here.op & 32) {
|
||||
Tracevv((stderr, "inflate: end of block\n"));
|
||||
state->mode = TYPE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* invalid code */
|
||||
if (here.op & 64) {
|
||||
strm->msg = (char *)"invalid literal/length code";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
|
||||
/* length code -- get extra bits, if any */
|
||||
state->extra = (unsigned)(here.op) & 15;
|
||||
if (state->extra != 0) {
|
||||
NEEDBITS(state->extra);
|
||||
state->length += BITS(state->extra);
|
||||
DROPBITS(state->extra);
|
||||
}
|
||||
Tracevv((stderr, "inflate: length %u\n", state->length));
|
||||
|
||||
/* get distance code */
|
||||
for (;;) {
|
||||
here = state->distcode[BITS(state->distbits)];
|
||||
if ((unsigned)(here.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
if ((here.op & 0xf0) == 0) {
|
||||
last = here;
|
||||
for (;;) {
|
||||
here = state->distcode[last.val +
|
||||
(BITS(last.bits + last.op) >> last.bits)];
|
||||
if ((unsigned)(last.bits + here.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
DROPBITS(last.bits);
|
||||
}
|
||||
DROPBITS(here.bits);
|
||||
if (here.op & 64) {
|
||||
strm->msg = (char *)"invalid distance code";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
state->offset = (unsigned)here.val;
|
||||
|
||||
/* get distance extra bits, if any */
|
||||
state->extra = (unsigned)(here.op) & 15;
|
||||
if (state->extra != 0) {
|
||||
NEEDBITS(state->extra);
|
||||
state->offset += BITS(state->extra);
|
||||
DROPBITS(state->extra);
|
||||
}
|
||||
if (state->offset > state->wsize - (state->whave < state->wsize ?
|
||||
left : 0)) {
|
||||
strm->msg = (char *)"invalid distance too far back";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
Tracevv((stderr, "inflate: distance %u\n", state->offset));
|
||||
|
||||
/* copy match from window to output */
|
||||
do {
|
||||
ROOM();
|
||||
copy = state->wsize - state->offset;
|
||||
if (copy < left) {
|
||||
from = put + copy;
|
||||
copy = left - copy;
|
||||
}
|
||||
else {
|
||||
from = put - state->offset;
|
||||
copy = left;
|
||||
}
|
||||
if (copy > state->length) copy = state->length;
|
||||
state->length -= copy;
|
||||
left -= copy;
|
||||
do {
|
||||
*put++ = *from++;
|
||||
} while (--copy);
|
||||
} while (state->length != 0);
|
||||
break;
|
||||
|
||||
case DONE:
|
||||
/* inflate stream terminated properly -- write leftover output */
|
||||
ret = Z_STREAM_END;
|
||||
if (left < state->wsize) {
|
||||
if (out(out_desc, state->window, state->wsize - left))
|
||||
ret = Z_BUF_ERROR;
|
||||
}
|
||||
goto inf_leave;
|
||||
|
||||
case BAD:
|
||||
ret = Z_DATA_ERROR;
|
||||
goto inf_leave;
|
||||
|
||||
default: /* can't happen, but makes compilers happy */
|
||||
ret = Z_STREAM_ERROR;
|
||||
goto inf_leave;
|
||||
}
|
||||
|
||||
/* Return unused input */
|
||||
inf_leave:
|
||||
strm->next_in = next;
|
||||
strm->avail_in = have;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ZEXPORT inflateBackEnd(strm)
|
||||
z_streamp strm;
|
||||
{
|
||||
if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
|
||||
return Z_STREAM_ERROR;
|
||||
ZFREE(strm, strm->state);
|
||||
strm->state = Z_NULL;
|
||||
Tracev((stderr, "inflate: end\n"));
|
||||
return Z_OK;
|
||||
}
|
||||
340
dependencies/libwebsockets/win32port/zlib/inffast.c
vendored
Normal file
340
dependencies/libwebsockets/win32port/zlib/inffast.c
vendored
Normal file
@ -0,0 +1,340 @@
|
||||
/* inffast.c -- fast decoding
|
||||
* Copyright (C) 1995-2008, 2010 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "zutil.h"
|
||||
#include "inftrees.h"
|
||||
#include "inflate.h"
|
||||
#include "inffast.h"
|
||||
|
||||
#ifndef ASMINF
|
||||
|
||||
/* Allow machine dependent optimization for post-increment or pre-increment.
|
||||
Based on testing to date,
|
||||
Pre-increment preferred for:
|
||||
- PowerPC G3 (Adler)
|
||||
- MIPS R5000 (Randers-Pehrson)
|
||||
Post-increment preferred for:
|
||||
- none
|
||||
No measurable difference:
|
||||
- Pentium III (Anderson)
|
||||
- M68060 (Nikl)
|
||||
*/
|
||||
#ifdef POSTINC
|
||||
# define OFF 0
|
||||
# define PUP(a) *(a)++
|
||||
#else
|
||||
# define OFF 1
|
||||
# define PUP(a) *++(a)
|
||||
#endif
|
||||
|
||||
/*
|
||||
Decode literal, length, and distance codes and write out the resulting
|
||||
literal and match bytes until either not enough input or output is
|
||||
available, an end-of-block is encountered, or a data error is encountered.
|
||||
When large enough input and output buffers are supplied to inflate(), for
|
||||
example, a 16K input buffer and a 64K output buffer, more than 95% of the
|
||||
inflate execution time is spent in this routine.
|
||||
|
||||
Entry assumptions:
|
||||
|
||||
state->mode == LEN
|
||||
strm->avail_in >= 6
|
||||
strm->avail_out >= 258
|
||||
start >= strm->avail_out
|
||||
state->bits < 8
|
||||
|
||||
On return, state->mode is one of:
|
||||
|
||||
LEN -- ran out of enough output space or enough available input
|
||||
TYPE -- reached end of block code, inflate() to interpret next block
|
||||
BAD -- error in block data
|
||||
|
||||
Notes:
|
||||
|
||||
- The maximum input bits used by a length/distance pair is 15 bits for the
|
||||
length code, 5 bits for the length extra, 15 bits for the distance code,
|
||||
and 13 bits for the distance extra. This totals 48 bits, or six bytes.
|
||||
Therefore if strm->avail_in >= 6, then there is enough input to avoid
|
||||
checking for available input while decoding.
|
||||
|
||||
- The maximum bytes that a single length/distance pair can output is 258
|
||||
bytes, which is the maximum length that can be coded. inflate_fast()
|
||||
requires strm->avail_out >= 258 for each loop to avoid checking for
|
||||
output space.
|
||||
*/
|
||||
void ZLIB_INTERNAL inflate_fast(strm, start)
|
||||
z_streamp strm;
|
||||
unsigned start; /* inflate()'s starting value for strm->avail_out */
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
unsigned char FAR *in; /* local strm->next_in */
|
||||
unsigned char FAR *last; /* while in < last, enough input available */
|
||||
unsigned char FAR *out; /* local strm->next_out */
|
||||
unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
|
||||
unsigned char FAR *end; /* while out < end, enough space available */
|
||||
#ifdef INFLATE_STRICT
|
||||
unsigned dmax; /* maximum distance from zlib header */
|
||||
#endif
|
||||
unsigned wsize; /* window size or zero if not using window */
|
||||
unsigned whave; /* valid bytes in the window */
|
||||
unsigned wnext; /* window write index */
|
||||
unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */
|
||||
unsigned long hold; /* local strm->hold */
|
||||
unsigned bits; /* local strm->bits */
|
||||
code const FAR *lcode; /* local strm->lencode */
|
||||
code const FAR *dcode; /* local strm->distcode */
|
||||
unsigned lmask; /* mask for first level of length codes */
|
||||
unsigned dmask; /* mask for first level of distance codes */
|
||||
code here; /* retrieved table entry */
|
||||
unsigned op; /* code bits, operation, extra bits, or */
|
||||
/* window position, window bytes to copy */
|
||||
unsigned len; /* match length, unused bytes */
|
||||
unsigned dist; /* match distance */
|
||||
unsigned char FAR *from; /* where to copy match from */
|
||||
|
||||
/* copy state to local variables */
|
||||
state = (struct inflate_state FAR *)strm->state;
|
||||
in = strm->next_in - OFF;
|
||||
last = in + (strm->avail_in - 5);
|
||||
out = strm->next_out - OFF;
|
||||
beg = out - (start - strm->avail_out);
|
||||
end = out + (strm->avail_out - 257);
|
||||
#ifdef INFLATE_STRICT
|
||||
dmax = state->dmax;
|
||||
#endif
|
||||
wsize = state->wsize;
|
||||
whave = state->whave;
|
||||
wnext = state->wnext;
|
||||
window = state->window;
|
||||
hold = state->hold;
|
||||
bits = state->bits;
|
||||
lcode = state->lencode;
|
||||
dcode = state->distcode;
|
||||
lmask = (1U << state->lenbits) - 1;
|
||||
dmask = (1U << state->distbits) - 1;
|
||||
|
||||
/* decode literals and length/distances until end-of-block or not enough
|
||||
input data or output space */
|
||||
do {
|
||||
if (bits < 15) {
|
||||
hold += (unsigned long)(PUP(in)) << bits;
|
||||
bits += 8;
|
||||
hold += (unsigned long)(PUP(in)) << bits;
|
||||
bits += 8;
|
||||
}
|
||||
here = lcode[hold & lmask];
|
||||
dolen:
|
||||
op = (unsigned)(here.bits);
|
||||
hold >>= op;
|
||||
bits -= op;
|
||||
op = (unsigned)(here.op);
|
||||
if (op == 0) { /* literal */
|
||||
Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
|
||||
"inflate: literal '%c'\n" :
|
||||
"inflate: literal 0x%02x\n", here.val));
|
||||
PUP(out) = (unsigned char)(here.val);
|
||||
}
|
||||
else if (op & 16) { /* length base */
|
||||
len = (unsigned)(here.val);
|
||||
op &= 15; /* number of extra bits */
|
||||
if (op) {
|
||||
if (bits < op) {
|
||||
hold += (unsigned long)(PUP(in)) << bits;
|
||||
bits += 8;
|
||||
}
|
||||
len += (unsigned)hold & ((1U << op) - 1);
|
||||
hold >>= op;
|
||||
bits -= op;
|
||||
}
|
||||
Tracevv((stderr, "inflate: length %u\n", len));
|
||||
if (bits < 15) {
|
||||
hold += (unsigned long)(PUP(in)) << bits;
|
||||
bits += 8;
|
||||
hold += (unsigned long)(PUP(in)) << bits;
|
||||
bits += 8;
|
||||
}
|
||||
here = dcode[hold & dmask];
|
||||
dodist:
|
||||
op = (unsigned)(here.bits);
|
||||
hold >>= op;
|
||||
bits -= op;
|
||||
op = (unsigned)(here.op);
|
||||
if (op & 16) { /* distance base */
|
||||
dist = (unsigned)(here.val);
|
||||
op &= 15; /* number of extra bits */
|
||||
if (bits < op) {
|
||||
hold += (unsigned long)(PUP(in)) << bits;
|
||||
bits += 8;
|
||||
if (bits < op) {
|
||||
hold += (unsigned long)(PUP(in)) << bits;
|
||||
bits += 8;
|
||||
}
|
||||
}
|
||||
dist += (unsigned)hold & ((1U << op) - 1);
|
||||
#ifdef INFLATE_STRICT
|
||||
if (dist > dmax) {
|
||||
strm->msg = (char *)"invalid distance too far back";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
hold >>= op;
|
||||
bits -= op;
|
||||
Tracevv((stderr, "inflate: distance %u\n", dist));
|
||||
op = (unsigned)(out - beg); /* max distance in output */
|
||||
if (dist > op) { /* see if copy from window */
|
||||
op = dist - op; /* distance back in window */
|
||||
if (op > whave) {
|
||||
if (state->sane) {
|
||||
strm->msg =
|
||||
(char *)"invalid distance too far back";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
|
||||
if (len <= op - whave) {
|
||||
do {
|
||||
PUP(out) = 0;
|
||||
} while (--len);
|
||||
continue;
|
||||
}
|
||||
len -= op - whave;
|
||||
do {
|
||||
PUP(out) = 0;
|
||||
} while (--op > whave);
|
||||
if (op == 0) {
|
||||
from = out - dist;
|
||||
do {
|
||||
PUP(out) = PUP(from);
|
||||
} while (--len);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
from = window - OFF;
|
||||
if (wnext == 0) { /* very common case */
|
||||
from += wsize - op;
|
||||
if (op < len) { /* some from window */
|
||||
len -= op;
|
||||
do {
|
||||
PUP(out) = PUP(from);
|
||||
} while (--op);
|
||||
from = out - dist; /* rest from output */
|
||||
}
|
||||
}
|
||||
else if (wnext < op) { /* wrap around window */
|
||||
from += wsize + wnext - op;
|
||||
op -= wnext;
|
||||
if (op < len) { /* some from end of window */
|
||||
len -= op;
|
||||
do {
|
||||
PUP(out) = PUP(from);
|
||||
} while (--op);
|
||||
from = window - OFF;
|
||||
if (wnext < len) { /* some from start of window */
|
||||
op = wnext;
|
||||
len -= op;
|
||||
do {
|
||||
PUP(out) = PUP(from);
|
||||
} while (--op);
|
||||
from = out - dist; /* rest from output */
|
||||
}
|
||||
}
|
||||
}
|
||||
else { /* contiguous in window */
|
||||
from += wnext - op;
|
||||
if (op < len) { /* some from window */
|
||||
len -= op;
|
||||
do {
|
||||
PUP(out) = PUP(from);
|
||||
} while (--op);
|
||||
from = out - dist; /* rest from output */
|
||||
}
|
||||
}
|
||||
while (len > 2) {
|
||||
PUP(out) = PUP(from);
|
||||
PUP(out) = PUP(from);
|
||||
PUP(out) = PUP(from);
|
||||
len -= 3;
|
||||
}
|
||||
if (len) {
|
||||
PUP(out) = PUP(from);
|
||||
if (len > 1)
|
||||
PUP(out) = PUP(from);
|
||||
}
|
||||
}
|
||||
else {
|
||||
from = out - dist; /* copy direct from output */
|
||||
do { /* minimum length is three */
|
||||
PUP(out) = PUP(from);
|
||||
PUP(out) = PUP(from);
|
||||
PUP(out) = PUP(from);
|
||||
len -= 3;
|
||||
} while (len > 2);
|
||||
if (len) {
|
||||
PUP(out) = PUP(from);
|
||||
if (len > 1)
|
||||
PUP(out) = PUP(from);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((op & 64) == 0) { /* 2nd level distance code */
|
||||
here = dcode[here.val + (hold & ((1U << op) - 1))];
|
||||
goto dodist;
|
||||
}
|
||||
else {
|
||||
strm->msg = (char *)"invalid distance code";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ((op & 64) == 0) { /* 2nd level length code */
|
||||
here = lcode[here.val + (hold & ((1U << op) - 1))];
|
||||
goto dolen;
|
||||
}
|
||||
else if (op & 32) { /* end-of-block */
|
||||
Tracevv((stderr, "inflate: end of block\n"));
|
||||
state->mode = TYPE;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
strm->msg = (char *)"invalid literal/length code";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
} while (in < last && out < end);
|
||||
|
||||
/* return unused bytes (on entry, bits < 8, so in won't go too far back) */
|
||||
len = bits >> 3;
|
||||
in -= len;
|
||||
bits -= len << 3;
|
||||
hold &= (1U << bits) - 1;
|
||||
|
||||
/* update state and return */
|
||||
strm->next_in = in + OFF;
|
||||
strm->next_out = out + OFF;
|
||||
strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
|
||||
strm->avail_out = (unsigned)(out < end ?
|
||||
257 + (end - out) : 257 - (out - end));
|
||||
state->hold = hold;
|
||||
state->bits = bits;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
|
||||
- Using bit fields for code structure
|
||||
- Different op definition to avoid & for extra bits (do & for table bits)
|
||||
- Three separate decoding do-loops for direct, window, and wnext == 0
|
||||
- Special case for distance > 1 copies to do overlapped load and store copy
|
||||
- Explicit branch predictions (based on measured branch probabilities)
|
||||
- Deferring match copy and interspersed it with decoding subsequent codes
|
||||
- Swapping literal/length else
|
||||
- Swapping window/direct else
|
||||
- Larger unrolled copy loops (three is about right)
|
||||
- Moving len -= 3 statement into middle of loop
|
||||
*/
|
||||
|
||||
#endif /* !ASMINF */
|
||||
11
dependencies/libwebsockets/win32port/zlib/inffast.h
vendored
Normal file
11
dependencies/libwebsockets/win32port/zlib/inffast.h
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
/* inffast.h -- header to use inffast.c
|
||||
* Copyright (C) 1995-2003, 2010 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* WARNING: this file should *not* be used by applications. It is
|
||||
part of the implementation of the compression library and is
|
||||
subject to change. Applications should only use zlib.h.
|
||||
*/
|
||||
|
||||
void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start));
|
||||
94
dependencies/libwebsockets/win32port/zlib/inffixed.h
vendored
Normal file
94
dependencies/libwebsockets/win32port/zlib/inffixed.h
vendored
Normal file
@ -0,0 +1,94 @@
|
||||
/* inffixed.h -- table for decoding fixed codes
|
||||
* Generated automatically by makefixed().
|
||||
*/
|
||||
|
||||
/* WARNING: this file should *not* be used by applications. It
|
||||
is part of the implementation of the compression library and
|
||||
is subject to change. Applications should only use zlib.h.
|
||||
*/
|
||||
|
||||
static const code lenfix[512] = {
|
||||
{96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
|
||||
{0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
|
||||
{0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
|
||||
{0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
|
||||
{0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
|
||||
{21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
|
||||
{0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
|
||||
{0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
|
||||
{18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
|
||||
{0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
|
||||
{0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
|
||||
{0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
|
||||
{20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
|
||||
{0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
|
||||
{0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
|
||||
{0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
|
||||
{16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
|
||||
{0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
|
||||
{0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
|
||||
{0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
|
||||
{0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
|
||||
{0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
|
||||
{0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
|
||||
{0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
|
||||
{17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
|
||||
{0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
|
||||
{0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
|
||||
{0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
|
||||
{19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
|
||||
{0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
|
||||
{0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
|
||||
{0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
|
||||
{16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
|
||||
{0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
|
||||
{0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
|
||||
{0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
|
||||
{0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
|
||||
{20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
|
||||
{0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
|
||||
{0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
|
||||
{17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
|
||||
{0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
|
||||
{0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
|
||||
{0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
|
||||
{20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
|
||||
{0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
|
||||
{0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
|
||||
{0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
|
||||
{16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
|
||||
{0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
|
||||
{0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
|
||||
{0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
|
||||
{0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
|
||||
{0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
|
||||
{0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
|
||||
{0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
|
||||
{16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
|
||||
{0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
|
||||
{0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
|
||||
{0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
|
||||
{19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
|
||||
{0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
|
||||
{0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
|
||||
{0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
|
||||
{16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
|
||||
{0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
|
||||
{0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
|
||||
{0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
|
||||
{0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
|
||||
{64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
|
||||
{0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
|
||||
{0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
|
||||
{18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
|
||||
{0,9,255}
|
||||
};
|
||||
|
||||
static const code distfix[32] = {
|
||||
{16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
|
||||
{21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
|
||||
{18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
|
||||
{19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
|
||||
{16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
|
||||
{22,5,193},{64,5,0}
|
||||
};
|
||||
1480
dependencies/libwebsockets/win32port/zlib/inflate.c
vendored
Normal file
1480
dependencies/libwebsockets/win32port/zlib/inflate.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
122
dependencies/libwebsockets/win32port/zlib/inflate.h
vendored
Normal file
122
dependencies/libwebsockets/win32port/zlib/inflate.h
vendored
Normal file
@ -0,0 +1,122 @@
|
||||
/* inflate.h -- internal inflate state definition
|
||||
* Copyright (C) 1995-2009 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* WARNING: this file should *not* be used by applications. It is
|
||||
part of the implementation of the compression library and is
|
||||
subject to change. Applications should only use zlib.h.
|
||||
*/
|
||||
|
||||
/* define NO_GZIP when compiling if you want to disable gzip header and
|
||||
trailer decoding by inflate(). NO_GZIP would be used to avoid linking in
|
||||
the crc code when it is not needed. For shared libraries, gzip decoding
|
||||
should be left enabled. */
|
||||
#ifndef NO_GZIP
|
||||
# define GUNZIP
|
||||
#endif
|
||||
|
||||
/* Possible inflate modes between inflate() calls */
|
||||
typedef enum {
|
||||
HEAD, /* i: waiting for magic header */
|
||||
FLAGS, /* i: waiting for method and flags (gzip) */
|
||||
TIME, /* i: waiting for modification time (gzip) */
|
||||
OS, /* i: waiting for extra flags and operating system (gzip) */
|
||||
EXLEN, /* i: waiting for extra length (gzip) */
|
||||
EXTRA, /* i: waiting for extra bytes (gzip) */
|
||||
NAME, /* i: waiting for end of file name (gzip) */
|
||||
COMMENT, /* i: waiting for end of comment (gzip) */
|
||||
HCRC, /* i: waiting for header crc (gzip) */
|
||||
DICTID, /* i: waiting for dictionary check value */
|
||||
DICT, /* waiting for inflateSetDictionary() call */
|
||||
TYPE, /* i: waiting for type bits, including last-flag bit */
|
||||
TYPEDO, /* i: same, but skip check to exit inflate on new block */
|
||||
STORED, /* i: waiting for stored size (length and complement) */
|
||||
COPY_, /* i/o: same as COPY below, but only first time in */
|
||||
COPY, /* i/o: waiting for input or output to copy stored block */
|
||||
TABLE, /* i: waiting for dynamic block table lengths */
|
||||
LENLENS, /* i: waiting for code length code lengths */
|
||||
CODELENS, /* i: waiting for length/lit and distance code lengths */
|
||||
LEN_, /* i: same as LEN below, but only first time in */
|
||||
LEN, /* i: waiting for length/lit/eob code */
|
||||
LENEXT, /* i: waiting for length extra bits */
|
||||
DIST, /* i: waiting for distance code */
|
||||
DISTEXT, /* i: waiting for distance extra bits */
|
||||
MATCH, /* o: waiting for output space to copy string */
|
||||
LIT, /* o: waiting for output space to write literal */
|
||||
CHECK, /* i: waiting for 32-bit check value */
|
||||
LENGTH, /* i: waiting for 32-bit length (gzip) */
|
||||
DONE, /* finished check, done -- remain here until reset */
|
||||
BAD, /* got a data error -- remain here until reset */
|
||||
MEM, /* got an inflate() memory error -- remain here until reset */
|
||||
SYNC /* looking for synchronization bytes to restart inflate() */
|
||||
} inflate_mode;
|
||||
|
||||
/*
|
||||
State transitions between above modes -
|
||||
|
||||
(most modes can go to BAD or MEM on error -- not shown for clarity)
|
||||
|
||||
Process header:
|
||||
HEAD -> (gzip) or (zlib) or (raw)
|
||||
(gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT ->
|
||||
HCRC -> TYPE
|
||||
(zlib) -> DICTID or TYPE
|
||||
DICTID -> DICT -> TYPE
|
||||
(raw) -> TYPEDO
|
||||
Read deflate blocks:
|
||||
TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK
|
||||
STORED -> COPY_ -> COPY -> TYPE
|
||||
TABLE -> LENLENS -> CODELENS -> LEN_
|
||||
LEN_ -> LEN
|
||||
Read deflate codes in fixed or dynamic block:
|
||||
LEN -> LENEXT or LIT or TYPE
|
||||
LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
|
||||
LIT -> LEN
|
||||
Process trailer:
|
||||
CHECK -> LENGTH -> DONE
|
||||
*/
|
||||
|
||||
/* state maintained between inflate() calls. Approximately 10K bytes. */
|
||||
struct inflate_state {
|
||||
inflate_mode mode; /* current inflate mode */
|
||||
int last; /* true if processing last block */
|
||||
int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
|
||||
int havedict; /* true if dictionary provided */
|
||||
int flags; /* gzip header method and flags (0 if zlib) */
|
||||
unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
|
||||
unsigned long check; /* protected copy of check value */
|
||||
unsigned long total; /* protected copy of output count */
|
||||
gz_headerp head; /* where to save gzip header information */
|
||||
/* sliding window */
|
||||
unsigned wbits; /* log base 2 of requested window size */
|
||||
unsigned wsize; /* window size or zero if not using window */
|
||||
unsigned whave; /* valid bytes in the window */
|
||||
unsigned wnext; /* window write index */
|
||||
unsigned char FAR *window; /* allocated sliding window, if needed */
|
||||
/* bit accumulator */
|
||||
unsigned long hold; /* input bit accumulator */
|
||||
unsigned bits; /* number of bits in "in" */
|
||||
/* for string and stored block copying */
|
||||
unsigned length; /* literal or length of data to copy */
|
||||
unsigned offset; /* distance back to copy string from */
|
||||
/* for table and code decoding */
|
||||
unsigned extra; /* extra bits needed */
|
||||
/* fixed and dynamic code tables */
|
||||
code const FAR *lencode; /* starting table for length/literal codes */
|
||||
code const FAR *distcode; /* starting table for distance codes */
|
||||
unsigned lenbits; /* index bits for lencode */
|
||||
unsigned distbits; /* index bits for distcode */
|
||||
/* dynamic table building */
|
||||
unsigned ncode; /* number of code length code lengths */
|
||||
unsigned nlen; /* number of length code lengths */
|
||||
unsigned ndist; /* number of distance code lengths */
|
||||
unsigned have; /* number of code lengths in lens[] */
|
||||
code FAR *next; /* next available space in codes[] */
|
||||
unsigned short lens[320]; /* temporary storage for code lengths */
|
||||
unsigned short work[288]; /* work area for code table building */
|
||||
code codes[ENOUGH]; /* space for code tables */
|
||||
int sane; /* if false, allow invalid distance too far */
|
||||
int back; /* bits back of last unprocessed length/lit */
|
||||
unsigned was; /* initial length of match */
|
||||
};
|
||||
330
dependencies/libwebsockets/win32port/zlib/inftrees.c
vendored
Normal file
330
dependencies/libwebsockets/win32port/zlib/inftrees.c
vendored
Normal file
@ -0,0 +1,330 @@
|
||||
/* inftrees.c -- generate Huffman trees for efficient decoding
|
||||
* Copyright (C) 1995-2010 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "zutil.h"
|
||||
#include "inftrees.h"
|
||||
|
||||
#define MAXBITS 15
|
||||
|
||||
const char inflate_copyright[] =
|
||||
" inflate 1.2.5 Copyright 1995-2010 Mark Adler ";
|
||||
/*
|
||||
If you use the zlib library in a product, an acknowledgment is welcome
|
||||
in the documentation of your product. If for some reason you cannot
|
||||
include such an acknowledgment, I would appreciate that you keep this
|
||||
copyright string in the executable of your product.
|
||||
*/
|
||||
|
||||
/*
|
||||
Build a set of tables to decode the provided canonical Huffman code.
|
||||
The code lengths are lens[0..codes-1]. The result starts at *table,
|
||||
whose indices are 0..2^bits-1. work is a writable array of at least
|
||||
lens shorts, which is used as a work area. type is the type of code
|
||||
to be generated, CODES, LENS, or DISTS. On return, zero is success,
|
||||
-1 is an invalid code, and +1 means that ENOUGH isn't enough. table
|
||||
on return points to the next available entry's address. bits is the
|
||||
requested root table index bits, and on return it is the actual root
|
||||
table index bits. It will differ if the request is greater than the
|
||||
longest code or if it is less than the shortest code.
|
||||
*/
|
||||
int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work)
|
||||
codetype type;
|
||||
unsigned short FAR *lens;
|
||||
unsigned codes;
|
||||
code FAR * FAR *table;
|
||||
unsigned FAR *bits;
|
||||
unsigned short FAR *work;
|
||||
{
|
||||
unsigned len; /* a code's length in bits */
|
||||
unsigned sym; /* index of code symbols */
|
||||
unsigned min, max; /* minimum and maximum code lengths */
|
||||
unsigned root; /* number of index bits for root table */
|
||||
unsigned curr; /* number of index bits for current table */
|
||||
unsigned drop; /* code bits to drop for sub-table */
|
||||
int left; /* number of prefix codes available */
|
||||
unsigned used; /* code entries in table used */
|
||||
unsigned huff; /* Huffman code */
|
||||
unsigned incr; /* for incrementing code, index */
|
||||
unsigned fill; /* index for replicating entries */
|
||||
unsigned low; /* low bits for current root entry */
|
||||
unsigned mask; /* mask for low root bits */
|
||||
code here; /* table entry for duplication */
|
||||
code FAR *next; /* next available space in table */
|
||||
const unsigned short FAR *base; /* base value table to use */
|
||||
const unsigned short FAR *extra; /* extra bits table to use */
|
||||
int end; /* use base and extra for symbol > end */
|
||||
unsigned short count[MAXBITS+1]; /* number of codes of each length */
|
||||
unsigned short offs[MAXBITS+1]; /* offsets in table for each length */
|
||||
static const unsigned short lbase[31] = { /* Length codes 257..285 base */
|
||||
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
|
||||
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
|
||||
static const unsigned short lext[31] = { /* Length codes 257..285 extra */
|
||||
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
|
||||
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 73, 195};
|
||||
static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
|
||||
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
|
||||
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
|
||||
8193, 12289, 16385, 24577, 0, 0};
|
||||
static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
|
||||
16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
|
||||
23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
|
||||
28, 28, 29, 29, 64, 64};
|
||||
|
||||
/*
|
||||
Process a set of code lengths to create a canonical Huffman code. The
|
||||
code lengths are lens[0..codes-1]. Each length corresponds to the
|
||||
symbols 0..codes-1. The Huffman code is generated by first sorting the
|
||||
symbols by length from short to long, and retaining the symbol order
|
||||
for codes with equal lengths. Then the code starts with all zero bits
|
||||
for the first code of the shortest length, and the codes are integer
|
||||
increments for the same length, and zeros are appended as the length
|
||||
increases. For the deflate format, these bits are stored backwards
|
||||
from their more natural integer increment ordering, and so when the
|
||||
decoding tables are built in the large loop below, the integer codes
|
||||
are incremented backwards.
|
||||
|
||||
This routine assumes, but does not check, that all of the entries in
|
||||
lens[] are in the range 0..MAXBITS. The caller must assure this.
|
||||
1..MAXBITS is interpreted as that code length. zero means that that
|
||||
symbol does not occur in this code.
|
||||
|
||||
The codes are sorted by computing a count of codes for each length,
|
||||
creating from that a table of starting indices for each length in the
|
||||
sorted table, and then entering the symbols in order in the sorted
|
||||
table. The sorted table is work[], with that space being provided by
|
||||
the caller.
|
||||
|
||||
The length counts are used for other purposes as well, i.e. finding
|
||||
the minimum and maximum length codes, determining if there are any
|
||||
codes at all, checking for a valid set of lengths, and looking ahead
|
||||
at length counts to determine sub-table sizes when building the
|
||||
decoding tables.
|
||||
*/
|
||||
|
||||
/* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
|
||||
for (len = 0; len <= MAXBITS; len++)
|
||||
count[len] = 0;
|
||||
for (sym = 0; sym < codes; sym++)
|
||||
count[lens[sym]]++;
|
||||
|
||||
/* bound code lengths, force root to be within code lengths */
|
||||
root = *bits;
|
||||
for (max = MAXBITS; max >= 1; max--)
|
||||
if (count[max] != 0) break;
|
||||
if (root > max) root = max;
|
||||
if (max == 0) { /* no symbols to code at all */
|
||||
here.op = (unsigned char)64; /* invalid code marker */
|
||||
here.bits = (unsigned char)1;
|
||||
here.val = (unsigned short)0;
|
||||
*(*table)++ = here; /* make a table to force an error */
|
||||
*(*table)++ = here;
|
||||
*bits = 1;
|
||||
return 0; /* no symbols, but wait for decoding to report error */
|
||||
}
|
||||
for (min = 1; min < max; min++)
|
||||
if (count[min] != 0) break;
|
||||
if (root < min) root = min;
|
||||
|
||||
/* check for an over-subscribed or incomplete set of lengths */
|
||||
left = 1;
|
||||
for (len = 1; len <= MAXBITS; len++) {
|
||||
left <<= 1;
|
||||
left -= count[len];
|
||||
if (left < 0) return -1; /* over-subscribed */
|
||||
}
|
||||
if (left > 0 && (type == CODES || max != 1))
|
||||
return -1; /* incomplete set */
|
||||
|
||||
/* generate offsets into symbol table for each length for sorting */
|
||||
offs[1] = 0;
|
||||
for (len = 1; len < MAXBITS; len++)
|
||||
offs[len + 1] = offs[len] + count[len];
|
||||
|
||||
/* sort symbols by length, by symbol order within each length */
|
||||
for (sym = 0; sym < codes; sym++)
|
||||
if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
|
||||
|
||||
/*
|
||||
Create and fill in decoding tables. In this loop, the table being
|
||||
filled is at next and has curr index bits. The code being used is huff
|
||||
with length len. That code is converted to an index by dropping drop
|
||||
bits off of the bottom. For codes where len is less than drop + curr,
|
||||
those top drop + curr - len bits are incremented through all values to
|
||||
fill the table with replicated entries.
|
||||
|
||||
root is the number of index bits for the root table. When len exceeds
|
||||
root, sub-tables are created pointed to by the root entry with an index
|
||||
of the low root bits of huff. This is saved in low to check for when a
|
||||
new sub-table should be started. drop is zero when the root table is
|
||||
being filled, and drop is root when sub-tables are being filled.
|
||||
|
||||
When a new sub-table is needed, it is necessary to look ahead in the
|
||||
code lengths to determine what size sub-table is needed. The length
|
||||
counts are used for this, and so count[] is decremented as codes are
|
||||
entered in the tables.
|
||||
|
||||
used keeps track of how many table entries have been allocated from the
|
||||
provided *table space. It is checked for LENS and DIST tables against
|
||||
the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
|
||||
the initial root table size constants. See the comments in inftrees.h
|
||||
for more information.
|
||||
|
||||
sym increments through all symbols, and the loop terminates when
|
||||
all codes of length max, i.e. all codes, have been processed. This
|
||||
routine permits incomplete codes, so another loop after this one fills
|
||||
in the rest of the decoding tables with invalid code markers.
|
||||
*/
|
||||
|
||||
/* set up for code type */
|
||||
switch (type) {
|
||||
case CODES:
|
||||
base = extra = work; /* dummy value--not used */
|
||||
end = 19;
|
||||
break;
|
||||
case LENS:
|
||||
base = lbase;
|
||||
base -= 257;
|
||||
extra = lext;
|
||||
extra -= 257;
|
||||
end = 256;
|
||||
break;
|
||||
default: /* DISTS */
|
||||
base = dbase;
|
||||
extra = dext;
|
||||
end = -1;
|
||||
}
|
||||
|
||||
/* initialize state for loop */
|
||||
huff = 0; /* starting code */
|
||||
sym = 0; /* starting code symbol */
|
||||
len = min; /* starting code length */
|
||||
next = *table; /* current table to fill in */
|
||||
curr = root; /* current table index bits */
|
||||
drop = 0; /* current bits to drop from code for index */
|
||||
low = (unsigned)(-1); /* trigger new sub-table when len > root */
|
||||
used = 1U << root; /* use root table entries */
|
||||
mask = used - 1; /* mask for comparing low */
|
||||
|
||||
/* check available table space */
|
||||
if ((type == LENS && used >= ENOUGH_LENS) ||
|
||||
(type == DISTS && used >= ENOUGH_DISTS))
|
||||
return 1;
|
||||
|
||||
/* process all codes and make table entries */
|
||||
for (;;) {
|
||||
/* create table entry */
|
||||
here.bits = (unsigned char)(len - drop);
|
||||
if ((int)(work[sym]) < end) {
|
||||
here.op = (unsigned char)0;
|
||||
here.val = work[sym];
|
||||
}
|
||||
else if ((int)(work[sym]) > end) {
|
||||
here.op = (unsigned char)(extra[work[sym]]);
|
||||
here.val = base[work[sym]];
|
||||
}
|
||||
else {
|
||||
here.op = (unsigned char)(32 + 64); /* end of block */
|
||||
here.val = 0;
|
||||
}
|
||||
|
||||
/* replicate for those indices with low len bits equal to huff */
|
||||
incr = 1U << (len - drop);
|
||||
fill = 1U << curr;
|
||||
min = fill; /* save offset to next table */
|
||||
do {
|
||||
fill -= incr;
|
||||
next[(huff >> drop) + fill] = here;
|
||||
} while (fill != 0);
|
||||
|
||||
/* backwards increment the len-bit code huff */
|
||||
incr = 1U << (len - 1);
|
||||
while (huff & incr)
|
||||
incr >>= 1;
|
||||
if (incr != 0) {
|
||||
huff &= incr - 1;
|
||||
huff += incr;
|
||||
}
|
||||
else
|
||||
huff = 0;
|
||||
|
||||
/* go to next symbol, update count, len */
|
||||
sym++;
|
||||
if (--(count[len]) == 0) {
|
||||
if (len == max) break;
|
||||
len = lens[work[sym]];
|
||||
}
|
||||
|
||||
/* create new sub-table if needed */
|
||||
if (len > root && (huff & mask) != low) {
|
||||
/* if first time, transition to sub-tables */
|
||||
if (drop == 0)
|
||||
drop = root;
|
||||
|
||||
/* increment past last table */
|
||||
next += min; /* here min is 1 << curr */
|
||||
|
||||
/* determine length of next table */
|
||||
curr = len - drop;
|
||||
left = (int)(1 << curr);
|
||||
while (curr + drop < max) {
|
||||
left -= count[curr + drop];
|
||||
if (left <= 0) break;
|
||||
curr++;
|
||||
left <<= 1;
|
||||
}
|
||||
|
||||
/* check for enough space */
|
||||
used += 1U << curr;
|
||||
if ((type == LENS && used >= ENOUGH_LENS) ||
|
||||
(type == DISTS && used >= ENOUGH_DISTS))
|
||||
return 1;
|
||||
|
||||
/* point entry in root table to sub-table */
|
||||
low = huff & mask;
|
||||
(*table)[low].op = (unsigned char)curr;
|
||||
(*table)[low].bits = (unsigned char)root;
|
||||
(*table)[low].val = (unsigned short)(next - *table);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Fill in rest of table for incomplete codes. This loop is similar to the
|
||||
loop above in incrementing huff for table indices. It is assumed that
|
||||
len is equal to curr + drop, so there is no loop needed to increment
|
||||
through high index bits. When the current sub-table is filled, the loop
|
||||
drops back to the root table to fill in any remaining entries there.
|
||||
*/
|
||||
here.op = (unsigned char)64; /* invalid code marker */
|
||||
here.bits = (unsigned char)(len - drop);
|
||||
here.val = (unsigned short)0;
|
||||
while (huff != 0) {
|
||||
/* when done with sub-table, drop back to root table */
|
||||
if (drop != 0 && (huff & mask) != low) {
|
||||
drop = 0;
|
||||
len = root;
|
||||
next = *table;
|
||||
here.bits = (unsigned char)len;
|
||||
}
|
||||
|
||||
/* put invalid code marker in table */
|
||||
next[huff >> drop] = here;
|
||||
|
||||
/* backwards increment the len-bit code huff */
|
||||
incr = 1U << (len - 1);
|
||||
while (huff & incr)
|
||||
incr >>= 1;
|
||||
if (incr != 0) {
|
||||
huff &= incr - 1;
|
||||
huff += incr;
|
||||
}
|
||||
else
|
||||
huff = 0;
|
||||
}
|
||||
|
||||
/* set return parameters */
|
||||
*table += used;
|
||||
*bits = root;
|
||||
return 0;
|
||||
}
|
||||
62
dependencies/libwebsockets/win32port/zlib/inftrees.h
vendored
Normal file
62
dependencies/libwebsockets/win32port/zlib/inftrees.h
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
/* inftrees.h -- header to use inftrees.c
|
||||
* Copyright (C) 1995-2005, 2010 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* WARNING: this file should *not* be used by applications. It is
|
||||
part of the implementation of the compression library and is
|
||||
subject to change. Applications should only use zlib.h.
|
||||
*/
|
||||
|
||||
/* Structure for decoding tables. Each entry provides either the
|
||||
information needed to do the operation requested by the code that
|
||||
indexed that table entry, or it provides a pointer to another
|
||||
table that indexes more bits of the code. op indicates whether
|
||||
the entry is a pointer to another table, a literal, a length or
|
||||
distance, an end-of-block, or an invalid code. For a table
|
||||
pointer, the low four bits of op is the number of index bits of
|
||||
that table. For a length or distance, the low four bits of op
|
||||
is the number of extra bits to get after the code. bits is
|
||||
the number of bits in this code or part of the code to drop off
|
||||
of the bit buffer. val is the actual byte to output in the case
|
||||
of a literal, the base length or distance, or the offset from
|
||||
the current table to the next table. Each entry is four bytes. */
|
||||
typedef struct {
|
||||
unsigned char op; /* operation, extra bits, table bits */
|
||||
unsigned char bits; /* bits in this part of the code */
|
||||
unsigned short val; /* offset in table or code value */
|
||||
} code;
|
||||
|
||||
/* op values as set by inflate_table():
|
||||
00000000 - literal
|
||||
0000tttt - table link, tttt != 0 is the number of table index bits
|
||||
0001eeee - length or distance, eeee is the number of extra bits
|
||||
01100000 - end of block
|
||||
01000000 - invalid code
|
||||
*/
|
||||
|
||||
/* Maximum size of the dynamic table. The maximum number of code structures is
|
||||
1444, which is the sum of 852 for literal/length codes and 592 for distance
|
||||
codes. These values were found by exhaustive searches using the program
|
||||
examples/enough.c found in the zlib distribtution. The arguments to that
|
||||
program are the number of symbols, the initial root table size, and the
|
||||
maximum bit length of a code. "enough 286 9 15" for literal/length codes
|
||||
returns returns 852, and "enough 30 6 15" for distance codes returns 592.
|
||||
The initial root table size (9 or 6) is found in the fifth argument of the
|
||||
inflate_table() calls in inflate.c and infback.c. If the root table size is
|
||||
changed, then these maximum sizes would be need to be recalculated and
|
||||
updated. */
|
||||
#define ENOUGH_LENS 852
|
||||
#define ENOUGH_DISTS 592
|
||||
#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS)
|
||||
|
||||
/* Type of code to build for inflate_table() */
|
||||
typedef enum {
|
||||
CODES,
|
||||
LENS,
|
||||
DISTS
|
||||
} codetype;
|
||||
|
||||
int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens,
|
||||
unsigned codes, code FAR * FAR *table,
|
||||
unsigned FAR *bits, unsigned short FAR *work));
|
||||
1244
dependencies/libwebsockets/win32port/zlib/trees.c
vendored
Normal file
1244
dependencies/libwebsockets/win32port/zlib/trees.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
128
dependencies/libwebsockets/win32port/zlib/trees.h
vendored
Normal file
128
dependencies/libwebsockets/win32port/zlib/trees.h
vendored
Normal file
@ -0,0 +1,128 @@
|
||||
/* header created automatically with -DGEN_TREES_H */
|
||||
|
||||
local const ct_data static_ltree[L_CODES+2] = {
|
||||
{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}},
|
||||
{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}},
|
||||
{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}},
|
||||
{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}},
|
||||
{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}},
|
||||
{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}},
|
||||
{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}},
|
||||
{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}},
|
||||
{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}},
|
||||
{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}},
|
||||
{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}},
|
||||
{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}},
|
||||
{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}},
|
||||
{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}},
|
||||
{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}},
|
||||
{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}},
|
||||
{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}},
|
||||
{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}},
|
||||
{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}},
|
||||
{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}},
|
||||
{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}},
|
||||
{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}},
|
||||
{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}},
|
||||
{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}},
|
||||
{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}},
|
||||
{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}},
|
||||
{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}},
|
||||
{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}},
|
||||
{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}},
|
||||
{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}},
|
||||
{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}},
|
||||
{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}},
|
||||
{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}},
|
||||
{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}},
|
||||
{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}},
|
||||
{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}},
|
||||
{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}},
|
||||
{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}},
|
||||
{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}},
|
||||
{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}},
|
||||
{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}},
|
||||
{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}},
|
||||
{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}},
|
||||
{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}},
|
||||
{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}},
|
||||
{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}},
|
||||
{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}},
|
||||
{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}},
|
||||
{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}},
|
||||
{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}},
|
||||
{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}},
|
||||
{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}},
|
||||
{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}},
|
||||
{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}},
|
||||
{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}},
|
||||
{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}},
|
||||
{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}},
|
||||
{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}}
|
||||
};
|
||||
|
||||
local const ct_data static_dtree[D_CODES] = {
|
||||
{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},
|
||||
{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},
|
||||
{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},
|
||||
{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},
|
||||
{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},
|
||||
{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
|
||||
};
|
||||
|
||||
const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {
|
||||
0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
|
||||
10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
|
||||
11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
|
||||
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
|
||||
18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
|
||||
23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
||||
24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
|
||||
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
|
||||
27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
||||
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
||||
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
||||
28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
||||
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
||||
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
||||
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
|
||||
};
|
||||
|
||||
const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
|
||||
13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
|
||||
17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
|
||||
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
|
||||
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||
23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
||||
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
||||
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
|
||||
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
|
||||
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
|
||||
};
|
||||
|
||||
local const int base_length[LENGTH_CODES] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
|
||||
64, 80, 96, 112, 128, 160, 192, 224, 0
|
||||
};
|
||||
|
||||
local const int base_dist[D_CODES] = {
|
||||
0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
|
||||
32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
|
||||
1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
|
||||
};
|
||||
|
||||
59
dependencies/libwebsockets/win32port/zlib/uncompr.c
vendored
Normal file
59
dependencies/libwebsockets/win32port/zlib/uncompr.c
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
/* uncompr.c -- decompress a memory buffer
|
||||
* Copyright (C) 1995-2003, 2010 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#define ZLIB_INTERNAL
|
||||
#include "zlib.h"
|
||||
|
||||
/* ===========================================================================
|
||||
Decompresses the source buffer into the destination buffer. sourceLen is
|
||||
the byte length of the source buffer. Upon entry, destLen is the total
|
||||
size of the destination buffer, which must be large enough to hold the
|
||||
entire uncompressed data. (The size of the uncompressed data must have
|
||||
been saved previously by the compressor and transmitted to the decompressor
|
||||
by some mechanism outside the scope of this compression library.)
|
||||
Upon exit, destLen is the actual size of the compressed buffer.
|
||||
|
||||
uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
|
||||
enough memory, Z_BUF_ERROR if there was not enough room in the output
|
||||
buffer, or Z_DATA_ERROR if the input data was corrupted.
|
||||
*/
|
||||
int ZEXPORT uncompress (dest, destLen, source, sourceLen)
|
||||
Bytef *dest;
|
||||
uLongf *destLen;
|
||||
const Bytef *source;
|
||||
uLong sourceLen;
|
||||
{
|
||||
z_stream stream;
|
||||
int err;
|
||||
|
||||
stream.next_in = (Bytef*)source;
|
||||
stream.avail_in = (uInt)sourceLen;
|
||||
/* Check for source > 64K on 16-bit machine: */
|
||||
if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
|
||||
|
||||
stream.next_out = dest;
|
||||
stream.avail_out = (uInt)*destLen;
|
||||
if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
|
||||
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
|
||||
err = inflateInit(&stream);
|
||||
if (err != Z_OK) return err;
|
||||
|
||||
err = inflate(&stream, Z_FINISH);
|
||||
if (err != Z_STREAM_END) {
|
||||
inflateEnd(&stream);
|
||||
if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
|
||||
return Z_DATA_ERROR;
|
||||
return err;
|
||||
}
|
||||
*destLen = stream.total_out;
|
||||
|
||||
err = inflateEnd(&stream);
|
||||
return err;
|
||||
}
|
||||
428
dependencies/libwebsockets/win32port/zlib/zconf.h
vendored
Normal file
428
dependencies/libwebsockets/win32port/zlib/zconf.h
vendored
Normal file
@ -0,0 +1,428 @@
|
||||
/* zconf.h -- configuration of the zlib compression library
|
||||
* Copyright (C) 1995-2010 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#ifndef ZCONF_H
|
||||
#define ZCONF_H
|
||||
|
||||
/*
|
||||
* If you *really* need a unique prefix for all types and library functions,
|
||||
* compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
|
||||
* Even better than compiling with -DZ_PREFIX would be to use configure to set
|
||||
* this permanently in zconf.h using "./configure --zprefix".
|
||||
*/
|
||||
#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */
|
||||
|
||||
/* all linked symbols */
|
||||
# define _dist_code z__dist_code
|
||||
# define _length_code z__length_code
|
||||
# define _tr_align z__tr_align
|
||||
# define _tr_flush_block z__tr_flush_block
|
||||
# define _tr_init z__tr_init
|
||||
# define _tr_stored_block z__tr_stored_block
|
||||
# define _tr_tally z__tr_tally
|
||||
# define adler32 z_adler32
|
||||
# define adler32_combine z_adler32_combine
|
||||
# define adler32_combine64 z_adler32_combine64
|
||||
# define compress z_compress
|
||||
# define compress2 z_compress2
|
||||
# define compressBound z_compressBound
|
||||
# define crc32 z_crc32
|
||||
# define crc32_combine z_crc32_combine
|
||||
# define crc32_combine64 z_crc32_combine64
|
||||
# define deflate z_deflate
|
||||
# define deflateBound z_deflateBound
|
||||
# define deflateCopy z_deflateCopy
|
||||
# define deflateEnd z_deflateEnd
|
||||
# define deflateInit2_ z_deflateInit2_
|
||||
# define deflateInit_ z_deflateInit_
|
||||
# define deflateParams z_deflateParams
|
||||
# define deflatePrime z_deflatePrime
|
||||
# define deflateReset z_deflateReset
|
||||
# define deflateSetDictionary z_deflateSetDictionary
|
||||
# define deflateSetHeader z_deflateSetHeader
|
||||
# define deflateTune z_deflateTune
|
||||
# define deflate_copyright z_deflate_copyright
|
||||
# define get_crc_table z_get_crc_table
|
||||
# define gz_error z_gz_error
|
||||
# define gz_intmax z_gz_intmax
|
||||
# define gz_strwinerror z_gz_strwinerror
|
||||
# define gzbuffer z_gzbuffer
|
||||
# define gzclearerr z_gzclearerr
|
||||
# define gzclose z_gzclose
|
||||
# define gzclose_r z_gzclose_r
|
||||
# define gzclose_w z_gzclose_w
|
||||
# define gzdirect z_gzdirect
|
||||
# define gzdopen z_gzdopen
|
||||
# define gzeof z_gzeof
|
||||
# define gzerror z_gzerror
|
||||
# define gzflush z_gzflush
|
||||
# define gzgetc z_gzgetc
|
||||
# define gzgets z_gzgets
|
||||
# define gzoffset z_gzoffset
|
||||
# define gzoffset64 z_gzoffset64
|
||||
# define gzopen z_gzopen
|
||||
# define gzopen64 z_gzopen64
|
||||
# define gzprintf z_gzprintf
|
||||
# define gzputc z_gzputc
|
||||
# define gzputs z_gzputs
|
||||
# define gzread z_gzread
|
||||
# define gzrewind z_gzrewind
|
||||
# define gzseek z_gzseek
|
||||
# define gzseek64 z_gzseek64
|
||||
# define gzsetparams z_gzsetparams
|
||||
# define gztell z_gztell
|
||||
# define gztell64 z_gztell64
|
||||
# define gzungetc z_gzungetc
|
||||
# define gzwrite z_gzwrite
|
||||
# define inflate z_inflate
|
||||
# define inflateBack z_inflateBack
|
||||
# define inflateBackEnd z_inflateBackEnd
|
||||
# define inflateBackInit_ z_inflateBackInit_
|
||||
# define inflateCopy z_inflateCopy
|
||||
# define inflateEnd z_inflateEnd
|
||||
# define inflateGetHeader z_inflateGetHeader
|
||||
# define inflateInit2_ z_inflateInit2_
|
||||
# define inflateInit_ z_inflateInit_
|
||||
# define inflateMark z_inflateMark
|
||||
# define inflatePrime z_inflatePrime
|
||||
# define inflateReset z_inflateReset
|
||||
# define inflateReset2 z_inflateReset2
|
||||
# define inflateSetDictionary z_inflateSetDictionary
|
||||
# define inflateSync z_inflateSync
|
||||
# define inflateSyncPoint z_inflateSyncPoint
|
||||
# define inflateUndermine z_inflateUndermine
|
||||
# define inflate_copyright z_inflate_copyright
|
||||
# define inflate_fast z_inflate_fast
|
||||
# define inflate_table z_inflate_table
|
||||
# define uncompress z_uncompress
|
||||
# define zError z_zError
|
||||
# define zcalloc z_zcalloc
|
||||
# define zcfree z_zcfree
|
||||
# define zlibCompileFlags z_zlibCompileFlags
|
||||
# define zlibVersion z_zlibVersion
|
||||
|
||||
/* all zlib typedefs in zlib.h and zconf.h */
|
||||
# define Byte z_Byte
|
||||
# define Bytef z_Bytef
|
||||
# define alloc_func z_alloc_func
|
||||
# define charf z_charf
|
||||
# define free_func z_free_func
|
||||
# define gzFile z_gzFile
|
||||
# define gz_header z_gz_header
|
||||
# define gz_headerp z_gz_headerp
|
||||
# define in_func z_in_func
|
||||
# define intf z_intf
|
||||
# define out_func z_out_func
|
||||
# define uInt z_uInt
|
||||
# define uIntf z_uIntf
|
||||
# define uLong z_uLong
|
||||
# define uLongf z_uLongf
|
||||
# define voidp z_voidp
|
||||
# define voidpc z_voidpc
|
||||
# define voidpf z_voidpf
|
||||
|
||||
/* all zlib structs in zlib.h and zconf.h */
|
||||
# define gz_header_s z_gz_header_s
|
||||
# define internal_state z_internal_state
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__MSDOS__) && !defined(MSDOS)
|
||||
# define MSDOS
|
||||
#endif
|
||||
#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
|
||||
# define OS2
|
||||
#endif
|
||||
#if defined(_WINDOWS) && !defined(WINDOWS)
|
||||
# define WINDOWS
|
||||
#endif
|
||||
#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
|
||||
# ifndef WIN32
|
||||
# define WIN32
|
||||
# endif
|
||||
#endif
|
||||
#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
|
||||
# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
|
||||
# ifndef SYS16BIT
|
||||
# define SYS16BIT
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Compile with -DMAXSEG_64K if the alloc function cannot allocate more
|
||||
* than 64k bytes at a time (needed on systems with 16-bit int).
|
||||
*/
|
||||
#ifdef SYS16BIT
|
||||
# define MAXSEG_64K
|
||||
#endif
|
||||
#ifdef MSDOS
|
||||
# define UNALIGNED_OK
|
||||
#endif
|
||||
|
||||
#ifdef __STDC_VERSION__
|
||||
# ifndef STDC
|
||||
# define STDC
|
||||
# endif
|
||||
# if __STDC_VERSION__ >= 199901L
|
||||
# ifndef STDC99
|
||||
# define STDC99
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
|
||||
# define STDC
|
||||
#endif
|
||||
#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
|
||||
# define STDC
|
||||
#endif
|
||||
#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
|
||||
# define STDC
|
||||
#endif
|
||||
#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
|
||||
# define STDC
|
||||
#endif
|
||||
|
||||
#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
|
||||
# define STDC
|
||||
#endif
|
||||
|
||||
#ifndef STDC
|
||||
# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
|
||||
# define const /* note: need a more gentle solution here */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Some Mac compilers merge all .h files incorrectly: */
|
||||
#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
|
||||
# define NO_DUMMY_DECL
|
||||
#endif
|
||||
|
||||
/* Maximum value for memLevel in deflateInit2 */
|
||||
#ifndef MAX_MEM_LEVEL
|
||||
# ifdef MAXSEG_64K
|
||||
# define MAX_MEM_LEVEL 8
|
||||
# else
|
||||
# define MAX_MEM_LEVEL 9
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Maximum value for windowBits in deflateInit2 and inflateInit2.
|
||||
* WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
|
||||
* created by gzip. (Files created by minigzip can still be extracted by
|
||||
* gzip.)
|
||||
*/
|
||||
#ifndef MAX_WBITS
|
||||
# define MAX_WBITS 15 /* 32K LZ77 window */
|
||||
#endif
|
||||
|
||||
/* The memory requirements for deflate are (in bytes):
|
||||
(1 << (windowBits+2)) + (1 << (memLevel+9))
|
||||
that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
|
||||
plus a few kilobytes for small objects. For example, if you want to reduce
|
||||
the default memory requirements from 256K to 128K, compile with
|
||||
make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
|
||||
Of course this will generally degrade compression (there's no free lunch).
|
||||
|
||||
The memory requirements for inflate are (in bytes) 1 << windowBits
|
||||
that is, 32K for windowBits=15 (default value) plus a few kilobytes
|
||||
for small objects.
|
||||
*/
|
||||
|
||||
/* Type declarations */
|
||||
|
||||
#ifndef OF /* function prototypes */
|
||||
# ifdef STDC
|
||||
# define OF(args) args
|
||||
# else
|
||||
# define OF(args) ()
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* The following definitions for FAR are needed only for MSDOS mixed
|
||||
* model programming (small or medium model with some far allocations).
|
||||
* This was tested only with MSC; for other MSDOS compilers you may have
|
||||
* to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
|
||||
* just define FAR to be empty.
|
||||
*/
|
||||
#ifdef SYS16BIT
|
||||
# if defined(M_I86SM) || defined(M_I86MM)
|
||||
/* MSC small or medium model */
|
||||
# define SMALL_MEDIUM
|
||||
# ifdef _MSC_VER
|
||||
# define FAR _far
|
||||
# else
|
||||
# define FAR far
|
||||
# endif
|
||||
# endif
|
||||
# if (defined(__SMALL__) || defined(__MEDIUM__))
|
||||
/* Turbo C small or medium model */
|
||||
# define SMALL_MEDIUM
|
||||
# ifdef __BORLANDC__
|
||||
# define FAR _far
|
||||
# else
|
||||
# define FAR far
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(WINDOWS) || defined(WIN32)
|
||||
/* If building or using zlib as a DLL, define ZLIB_DLL.
|
||||
* This is not mandatory, but it offers a little performance increase.
|
||||
*/
|
||||
# ifdef ZLIB_DLL
|
||||
# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
|
||||
# ifdef ZLIB_INTERNAL
|
||||
# define ZEXTERN extern __declspec(dllexport)
|
||||
# else
|
||||
# define ZEXTERN extern __declspec(dllimport)
|
||||
# endif
|
||||
# endif
|
||||
# endif /* ZLIB_DLL */
|
||||
/* If building or using zlib with the WINAPI/WINAPIV calling convention,
|
||||
* define ZLIB_WINAPI.
|
||||
* Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
|
||||
*/
|
||||
# ifdef ZLIB_WINAPI
|
||||
# ifdef FAR
|
||||
# undef FAR
|
||||
# endif
|
||||
# include <windows.h>
|
||||
/* No need for _export, use ZLIB.DEF instead. */
|
||||
/* For complete Windows compatibility, use WINAPI, not __stdcall. */
|
||||
# define ZEXPORT WINAPI
|
||||
# ifdef WIN32
|
||||
# define ZEXPORTVA WINAPIV
|
||||
# else
|
||||
# define ZEXPORTVA FAR CDECL
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined (__BEOS__)
|
||||
# ifdef ZLIB_DLL
|
||||
# ifdef ZLIB_INTERNAL
|
||||
# define ZEXPORT __declspec(dllexport)
|
||||
# define ZEXPORTVA __declspec(dllexport)
|
||||
# else
|
||||
# define ZEXPORT __declspec(dllimport)
|
||||
# define ZEXPORTVA __declspec(dllimport)
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef ZEXTERN
|
||||
# define ZEXTERN extern
|
||||
#endif
|
||||
#ifndef ZEXPORT
|
||||
# define ZEXPORT
|
||||
#endif
|
||||
#ifndef ZEXPORTVA
|
||||
# define ZEXPORTVA
|
||||
#endif
|
||||
|
||||
#ifndef FAR
|
||||
# define FAR
|
||||
#endif
|
||||
|
||||
#if !defined(__MACTYPES__)
|
||||
typedef unsigned char Byte; /* 8 bits */
|
||||
#endif
|
||||
typedef unsigned int uInt; /* 16 bits or more */
|
||||
typedef unsigned long uLong; /* 32 bits or more */
|
||||
|
||||
#ifdef SMALL_MEDIUM
|
||||
/* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
|
||||
# define Bytef Byte FAR
|
||||
#else
|
||||
typedef Byte FAR Bytef;
|
||||
#endif
|
||||
typedef char FAR charf;
|
||||
typedef int FAR intf;
|
||||
typedef uInt FAR uIntf;
|
||||
typedef uLong FAR uLongf;
|
||||
|
||||
#ifdef STDC
|
||||
typedef void const *voidpc;
|
||||
typedef void FAR *voidpf;
|
||||
typedef void *voidp;
|
||||
#else
|
||||
typedef Byte const *voidpc;
|
||||
typedef Byte FAR *voidpf;
|
||||
typedef Byte *voidp;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */
|
||||
# define Z_HAVE_UNISTD_H
|
||||
#endif
|
||||
|
||||
#ifdef STDC
|
||||
# include <sys/types.h> /* for off_t */
|
||||
#endif
|
||||
|
||||
/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
|
||||
* "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even
|
||||
* though the former does not conform to the LFS document), but considering
|
||||
* both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
|
||||
* equivalently requesting no 64-bit operations
|
||||
*/
|
||||
#if -_LARGEFILE64_SOURCE - -1 == 1
|
||||
# undef _LARGEFILE64_SOURCE
|
||||
#endif
|
||||
|
||||
#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
|
||||
# include <unistd.h> /* for SEEK_* and off_t */
|
||||
# ifdef VMS
|
||||
# include <unixio.h> /* for off_t */
|
||||
# endif
|
||||
# ifndef z_off_t
|
||||
# define z_off_t off_t
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef SEEK_SET
|
||||
# define SEEK_SET 0 /* Seek from beginning of file. */
|
||||
# define SEEK_CUR 1 /* Seek from current position. */
|
||||
# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
|
||||
#endif
|
||||
|
||||
#ifndef z_off_t
|
||||
# define z_off_t long
|
||||
#endif
|
||||
|
||||
#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
|
||||
# define z_off64_t off64_t
|
||||
#else
|
||||
# define z_off64_t z_off_t
|
||||
#endif
|
||||
|
||||
#if defined(__OS400__)
|
||||
# define NO_vsnprintf
|
||||
#endif
|
||||
|
||||
#if defined(__MVS__)
|
||||
# define NO_vsnprintf
|
||||
#endif
|
||||
|
||||
/* MVS linker does not support external names larger than 8 bytes */
|
||||
#if defined(__MVS__)
|
||||
#pragma map(deflateInit_,"DEIN")
|
||||
#pragma map(deflateInit2_,"DEIN2")
|
||||
#pragma map(deflateEnd,"DEEND")
|
||||
#pragma map(deflateBound,"DEBND")
|
||||
#pragma map(inflateInit_,"ININ")
|
||||
#pragma map(inflateInit2_,"ININ2")
|
||||
#pragma map(inflateEnd,"INEND")
|
||||
#pragma map(inflateSync,"INSY")
|
||||
#pragma map(inflateSetDictionary,"INSEDI")
|
||||
#pragma map(compressBound,"CMBND")
|
||||
#pragma map(inflate_table,"INTABL")
|
||||
#pragma map(inflate_fast,"INFA")
|
||||
#pragma map(inflate_copyright,"INCOPY")
|
||||
#endif
|
||||
|
||||
#endif /* ZCONF_H */
|
||||
1613
dependencies/libwebsockets/win32port/zlib/zlib.h
vendored
Normal file
1613
dependencies/libwebsockets/win32port/zlib/zlib.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user