Compare commits
84 Commits
v9.6.2
...
feature/st
Author | SHA1 | Date | |
---|---|---|---|
ca829a3a98 | |||
26a1e63626 | |||
c98959b895 | |||
baf18648e9 | |||
b21306376b | |||
fbd17685a1 | |||
3a673575dd | |||
d5e51840ab | |||
543c2086b2 | |||
95eab59c08 | |||
e9e768a288 | |||
e2180a1f31 | |||
7c1b57c8cd | |||
89e7a35a81 | |||
de6acfe54e | |||
789e620451 | |||
4789e190a0 | |||
d6366587a0 | |||
dddf00e3b1 | |||
cc47fb1c83 | |||
8e8cea1bcd | |||
68c97da518 | |||
f8b8799799 | |||
615f1778c3 | |||
c45b197c85 | |||
78713895dd | |||
aae2402ed2 | |||
b62de6e516 | |||
6e747849d7 | |||
a3a73ce1ac | |||
10c014bf98 | |||
9bb3643fc7 | |||
56db55caca | |||
565a08b229 | |||
bf0f11fd65 | |||
558daf8911 | |||
7ba7ff4b2a | |||
c9854be1c4 | |||
2fbb1a846f | |||
aa142df486 | |||
5e200a440f | |||
6ed8723d7d | |||
ac9710d5d6 | |||
35d76c20dc | |||
ca7344d9dc | |||
7603d1a71b | |||
d0cd4aed5a | |||
c5aadffa08 | |||
ecfca1f905 | |||
e49bf24d2d | |||
2a1cd6bb3e | |||
766e33774c | |||
9b90b1d302 | |||
ee8a3a52ec | |||
531bd624b5 | |||
abd6581242 | |||
7095367b93 | |||
3bb359a774 | |||
1c6ff733f9 | |||
2ecf5d8a5a | |||
0f88969b77 | |||
c317100b47 | |||
b029f176b6 | |||
bcfcfb628e | |||
268f528423 | |||
31be2e2527 | |||
502f021a0e | |||
b0b451d2c7 | |||
4872b59fac | |||
bb1be240ec | |||
b008c97c83 | |||
9886a30490 | |||
4ed5206d79 | |||
33916869f1 | |||
9ddf707804 | |||
3a020a66b7 | |||
bd39e69185 | |||
9d4ca3f34e | |||
de6f3ded09 | |||
e0aace33ea | |||
16eb269e1e | |||
2319dec278 | |||
f1be48aff1 | |||
93fd44813a |
86
.github/workflows/ccpp.yml
vendored
86
.github/workflows/ccpp.yml
vendored
@ -1,86 +0,0 @@
|
||||
name: unittest
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
|
||||
jobs:
|
||||
linux:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: make test_make
|
||||
run: make test_make
|
||||
|
||||
mac_tsan_sectransport:
|
||||
runs-on: macOS-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: make test_tsan
|
||||
run: make test_tsan
|
||||
|
||||
mac_tsan_openssl:
|
||||
runs-on: macOS-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: install openssl
|
||||
run: brew install openssl@1.1
|
||||
- name: make test
|
||||
run: make test_tsan_openssl
|
||||
|
||||
mac_tsan_mbedtls:
|
||||
runs-on: macOS-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: install mbedtls
|
||||
run: brew install mbedtls
|
||||
- name: make test
|
||||
run: make test_tsan_mbedtls
|
||||
|
||||
windows:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: seanmiddleditch/gha-setup-vsdevenv@master
|
||||
- run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_CXX_COMPILER=cl.exe -DUSE_WS=1 -DUSE_TEST=1 ..
|
||||
- run: cmake --build build
|
||||
|
||||
# Running the unittest does not work, the binary cannot be found
|
||||
#- run: ../build/test/ixwebsocket_unittest.exe
|
||||
# working-directory: test
|
||||
|
||||
uwp:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: seanmiddleditch/gha-setup-vsdevenv@master
|
||||
- run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION="10.0" -DCMAKE_CXX_COMPILER=cl.exe -DUSE_TEST=1 ..
|
||||
- run: cmake --build build
|
||||
|
||||
#
|
||||
# Windows with OpenSSL is working but disabled as it takes 13 minutes (10 for openssl) to build with vcpkg
|
||||
#
|
||||
# windows_openssl:
|
||||
# runs-on: windows-latest
|
||||
# steps:
|
||||
# - uses: actions/checkout@v1
|
||||
# - uses: seanmiddleditch/gha-setup-vsdevenv@master
|
||||
# - run: |
|
||||
# vcpkg install zlib:x64-windows
|
||||
# vcpkg install openssl:x64-windows
|
||||
# - run: |
|
||||
# mkdir build
|
||||
# cd build
|
||||
# cmake -DCMAKE_TOOLCHAIN_FILE=c:/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_CXX_COMPILER=cl.exe -DUSE_OPEN_SSL=1 -DUSE_TLS=1 -DUSE_WS=1 -DUSE_TEST=1 ..
|
||||
# - run: cmake --build build
|
||||
#
|
||||
# # Running the unittest does not work, the binary cannot be found
|
||||
# #- run: ../build/test/ixwebsocket_unittest.exe
|
||||
# # working-directory: test
|
||||
|
13
.github/workflows/unittest_linux.yml
vendored
Normal file
13
.github/workflows/unittest_linux.yml
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
name: linux
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
|
||||
jobs:
|
||||
linux:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: make test_make
|
||||
run: make test_make
|
15
.github/workflows/unittest_mac_tsan_mbedtls.yml
vendored
Normal file
15
.github/workflows/unittest_mac_tsan_mbedtls.yml
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
name: mac_tsan_mbedtls
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
|
||||
jobs:
|
||||
mac_tsan_mbedtls:
|
||||
runs-on: macOS-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: install mbedtls
|
||||
run: brew install mbedtls
|
||||
- name: make test
|
||||
run: make test_tsan_mbedtls
|
15
.github/workflows/unittest_mac_tsan_openssl.yml
vendored
Normal file
15
.github/workflows/unittest_mac_tsan_openssl.yml
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
name: mac_tsan_openssl
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
|
||||
jobs:
|
||||
mac_tsan_openssl:
|
||||
runs-on: macOS-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: install openssl
|
||||
run: brew install openssl@1.1
|
||||
- name: make test
|
||||
run: make test_tsan_openssl
|
13
.github/workflows/unittest_mac_tsan_sectransport.yml
vendored
Normal file
13
.github/workflows/unittest_mac_tsan_sectransport.yml
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
name: mac_tsan_sectransport
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
|
||||
jobs:
|
||||
mac_tsan_sectransport:
|
||||
runs-on: macOS-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: make test_tsan
|
||||
run: make test_tsan
|
40
.github/workflows/unittest_uwp.yml
vendored
Normal file
40
.github/workflows/unittest_uwp.yml
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
name: uwp
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
|
||||
jobs:
|
||||
uwp:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: seanmiddleditch/gha-setup-vsdevenv@master
|
||||
- run: |
|
||||
vcpkg install zlib:x64-uwp
|
||||
- run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE=c:/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION="10.0" -DCMAKE_CXX_COMPILER=cl.exe -DUSE_TEST=1 ..
|
||||
- run: cmake --build build
|
||||
|
||||
#
|
||||
# Windows with OpenSSL is working but disabled as it takes 13 minutes (10 for openssl) to build with vcpkg
|
||||
#
|
||||
# windows_openssl:
|
||||
# runs-on: windows-latest
|
||||
# steps:
|
||||
# - uses: actions/checkout@v1
|
||||
# - uses: seanmiddleditch/gha-setup-vsdevenv@master
|
||||
# - run: |
|
||||
# vcpkg install zlib:x64-windows
|
||||
# vcpkg install openssl:x64-windows
|
||||
# - run: |
|
||||
# mkdir build
|
||||
# cd build
|
||||
# cmake -DCMAKE_TOOLCHAIN_FILE=c:/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_CXX_COMPILER=cl.exe -DUSE_OPEN_SSL=1 -DUSE_TLS=1 -DUSE_WS=1 -DUSE_TEST=1 ..
|
||||
# - run: cmake --build build
|
||||
#
|
||||
# # Running the unittest does not work, the binary cannot be found
|
||||
# #- run: ../build/test/ixwebsocket_unittest.exe
|
||||
# # working-directory: test
|
19
.github/workflows/unittest_windows.yml
vendored
Normal file
19
.github/workflows/unittest_windows.yml
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
name: windows
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
|
||||
jobs:
|
||||
windows:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: seanmiddleditch/gha-setup-vsdevenv@master
|
||||
- run: |
|
||||
vcpkg install zlib:x64-windows
|
||||
- run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE=c:/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_CXX_COMPILER=cl.exe -DUSE_WS=1 -DUSE_TEST=1 ..
|
||||
- run: cmake --build build
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,3 +5,4 @@ ixsnake/ixsnake/.certs/
|
||||
site/
|
||||
ws/.certs/
|
||||
ws/.srl
|
||||
ixhttpd
|
||||
|
@ -7,7 +7,7 @@ find_library(MBEDCRYPTO_LIBRARY mbedcrypto)
|
||||
set(MBEDTLS_LIBRARIES "${MBEDTLS_LIBRARY}" "${MBEDX509_LIBRARY}" "${MBEDCRYPTO_LIBRARY}")
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(MBEDTLS DEFAULT_MSG
|
||||
find_package_handle_standard_args(MbedTLS DEFAULT_MSG
|
||||
MBEDTLS_INCLUDE_DIRS MBEDTLS_LIBRARY MBEDX509_LIBRARY MBEDCRYPTO_LIBRARY)
|
||||
|
||||
mark_as_advanced(MBEDTLS_INCLUDE_DIRS MBEDTLS_LIBRARY MBEDX509_LIBRARY MBEDCRYPTO_LIBRARY)
|
||||
|
@ -3,7 +3,7 @@
|
||||
# Copyright (c) 2018 Machine Zone, Inc. All rights reserved.
|
||||
#
|
||||
|
||||
cmake_minimum_required(VERSION 3.4.1)
|
||||
cmake_minimum_required(VERSION 3.4.1...3.17.2)
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}")
|
||||
|
||||
project(ixwebsocket C CXX)
|
||||
@ -58,6 +58,7 @@ set( IXWEBSOCKET_SOURCES
|
||||
set( IXWEBSOCKET_HEADERS
|
||||
ixwebsocket/IXBench.h
|
||||
ixwebsocket/IXCancellationRequest.h
|
||||
ixwebsocket/IXConnectionInfo.h
|
||||
ixwebsocket/IXConnectionState.h
|
||||
ixwebsocket/IXDNSLookup.h
|
||||
ixwebsocket/IXExponentialBackoff.h
|
||||
@ -153,8 +154,6 @@ add_library( ixwebsocket STATIC
|
||||
${IXWEBSOCKET_HEADERS}
|
||||
)
|
||||
|
||||
add_library ( ixwebsocket::ixwebsocket ALIAS ixwebsocket )
|
||||
|
||||
if (USE_TLS)
|
||||
target_compile_definitions(ixwebsocket PUBLIC IXWEBSOCKET_USE_TLS)
|
||||
if (USE_MBED_TLS)
|
||||
@ -182,50 +181,42 @@ if (USE_TLS)
|
||||
# set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} /opt/local/include/openssl-1.0)
|
||||
endif()
|
||||
|
||||
# This OPENSSL_FOUND check is to help find a cmake manually configured OpenSSL
|
||||
if (NOT OPENSSL_FOUND)
|
||||
include(FindOpenSSL)
|
||||
endif()
|
||||
# Use OPENSSL_ROOT_DIR CMake variable if you need to use your own openssl
|
||||
find_package(OpenSSL REQUIRED)
|
||||
message(STATUS "OpenSSL: " ${OPENSSL_VERSION})
|
||||
|
||||
target_link_libraries(ixwebsocket PUBLIC OpenSSL::SSL OpenSSL::Crypto)
|
||||
add_definitions(${OPENSSL_DEFINITIONS})
|
||||
target_include_directories(ixwebsocket PUBLIC ${OPENSSL_INCLUDE_DIR})
|
||||
target_link_libraries(ixwebsocket ${OPENSSL_LIBRARIES})
|
||||
elseif (USE_MBED_TLS)
|
||||
message(STATUS "TLS configured to use mbedtls")
|
||||
|
||||
find_package(MbedTLS REQUIRED)
|
||||
target_include_directories(ixwebsocket PUBLIC ${MBEDTLS_INCLUDE_DIRS})
|
||||
target_link_libraries(ixwebsocket PUBLIC ${MBEDTLS_LIBRARIES})
|
||||
target_link_libraries(ixwebsocket ${MBEDTLS_LIBRARIES})
|
||||
elseif (USE_SECURE_TRANSPORT)
|
||||
message(STATUS "TLS configured to use secure transport")
|
||||
target_link_libraries(ixwebsocket PUBLIC "-framework foundation" "-framework security")
|
||||
target_link_libraries(ixwebsocket "-framework foundation" "-framework security")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# This ZLIB_FOUND check is to help find a cmake manually configured zlib
|
||||
if (NOT ZLIB_FOUND)
|
||||
find_package(ZLIB)
|
||||
endif()
|
||||
if (ZLIB_FOUND)
|
||||
include_directories(${ZLIB_INCLUDE_DIRS})
|
||||
target_link_libraries(ixwebsocket PUBLIC ${ZLIB_LIBRARIES})
|
||||
else()
|
||||
include_directories(third_party/zlib ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib)
|
||||
add_subdirectory(third_party/zlib EXCLUDE_FROM_ALL)
|
||||
target_link_libraries(ixwebsocket PRIVATE $<LINK_ONLY:zlibstatic>)
|
||||
endif()
|
||||
# Use ZLIB_ROOT CMake variable if you need to use your own zlib
|
||||
find_package(ZLIB REQUIRED)
|
||||
include_directories(${ZLIB_INCLUDE_DIRS})
|
||||
target_link_libraries(ixwebsocket ${ZLIB_LIBRARIES})
|
||||
|
||||
if (WIN32)
|
||||
target_link_libraries(ixwebsocket PUBLIC wsock32 ws2_32 shlwapi)
|
||||
target_link_libraries(ixwebsocket wsock32 ws2_32 shlwapi)
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
|
||||
if (USE_TLS)
|
||||
target_link_libraries(ixwebsocket PUBLIC Crypt32)
|
||||
target_link_libraries(ixwebsocket Crypt32)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (UNIX)
|
||||
find_package(Threads)
|
||||
target_link_libraries(ixwebsocket PUBLIC ${CMAKE_THREAD_LIBS_INIT})
|
||||
target_link_libraries(ixwebsocket ${CMAKE_THREAD_LIBS_INIT})
|
||||
endif()
|
||||
|
||||
|
||||
@ -238,27 +229,29 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
||||
target_compile_options(ixwebsocket PRIVATE /MP)
|
||||
endif()
|
||||
|
||||
target_include_directories(ixwebsocket PUBLIC $<BUILD_INTERFACE:${IXWEBSOCKET_INCLUDE_DIRS}> $<INSTALL_INTERFACE:include/ixwebsocket>)
|
||||
target_include_directories(ixwebsocket PUBLIC
|
||||
$<BUILD_INTERFACE:${IXWEBSOCKET_INCLUDE_DIRS}/>
|
||||
$<INSTALL_INTERFACE:include/ixwebsocket>
|
||||
)
|
||||
|
||||
set_target_properties(ixwebsocket PROPERTIES PUBLIC_HEADER "${IXWEBSOCKET_HEADERS}")
|
||||
|
||||
install(TARGETS ixwebsocket EXPORT ixwebsocket
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib
|
||||
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_PREFIX}/include/ixwebsocket/
|
||||
install(TARGETS ixwebsocket
|
||||
EXPORT ixwebsocket
|
||||
ARCHIVE DESTINATION lib
|
||||
PUBLIC_HEADER DESTINATION include/ixwebsocket/
|
||||
)
|
||||
|
||||
# This gets in the way of vcpkg in ways I do not know how to fix
|
||||
# https://github.com/microsoft/vcpkg/pull/11030
|
||||
# Maybe using vcpkg_fixup_cmake_targets could fix it
|
||||
if (INSTALL_CMAKE_FILE)
|
||||
install(EXPORT ixwebsocket NAMESPACE ixwebsocket:: DESTINATION lib/cmake/ixwebsocket)
|
||||
export(EXPORT ixwebsocket NAMESPACE ixwebsocket:: FILE ixwebsocketConfig.cmake)
|
||||
endif()
|
||||
install(EXPORT ixwebsocket
|
||||
FILE ixwebsocket-config.cmake
|
||||
NAMESPACE ixwebsocket::
|
||||
DESTINATION lib/cmake/ixwebsocket)
|
||||
|
||||
if (USE_WS OR USE_TEST)
|
||||
add_subdirectory(ixcore)
|
||||
add_subdirectory(ixcrypto)
|
||||
add_subdirectory(ixcobra)
|
||||
add_subdirectory(ixredis)
|
||||
add_subdirectory(ixsnake)
|
||||
add_subdirectory(ixsentry)
|
||||
add_subdirectory(ixbots)
|
||||
|
97
README.md
97
README.md
@ -1,37 +1,72 @@
|
||||
## Hello world
|
||||
|
||||

|
||||
|
||||
IXWebSocket is a C++ library for WebSocket client and server development. It has minimal dependencies (no boost), is very simple to use and support everything you'll likely need for websocket dev (SSL, deflate compression, compiles on most platforms, etc...). HTTP client and server code is also available, but it hasn't received as much testing.
|
||||
|
||||
It is been used on big mobile video game titles sending and receiving tons of messages since 2017 (iOS and Android). It was tested on macOS, iOS, Linux, Android, Windows and FreeBSD. Two important design goals are simplicity and correctness.
|
||||
|
||||
```cpp
|
||||
// Required on Windows
|
||||
ix::initNetSystem();
|
||||
/*
|
||||
* main.cpp
|
||||
* Author: Benjamin Sergeant
|
||||
* Copyright (c) 2020 Machine Zone, Inc. All rights reserved.
|
||||
*
|
||||
* Super simple standalone example. See ws folder, unittest and doc/usage.md for more.
|
||||
*
|
||||
* On macOS
|
||||
* $ mkdir -p build ; cd build ; cmake -DUSE_TLS=1 .. ; make -j ; make install
|
||||
* $ clang++ --std=c++14 --stdlib=libc++ main.cpp -lixwebsocket -lz -framework Security -framework Foundation
|
||||
* $ ./a.out
|
||||
*/
|
||||
|
||||
// Our websocket object
|
||||
ix::WebSocket webSocket;
|
||||
#include <ixwebsocket/IXNetSystem.h>
|
||||
#include <ixwebsocket/IXWebSocket.h>
|
||||
#include <iostream>
|
||||
|
||||
std::string url("ws://localhost:8080/");
|
||||
webSocket.setUrl(url);
|
||||
int main()
|
||||
{
|
||||
// Required on Windows
|
||||
ix::initNetSystem();
|
||||
|
||||
// Setup a callback to be fired (in a background thread, watch out for race conditions !)
|
||||
// when a message or an event (open, close, error) is received
|
||||
webSocket.setOnMessageCallback([](const ix::WebSocketMessagePtr& msg)
|
||||
{
|
||||
if (msg->type == ix::WebSocketMessageType::Message)
|
||||
// Our websocket object
|
||||
ix::WebSocket webSocket;
|
||||
|
||||
std::string url("wss://echo.websocket.org");
|
||||
webSocket.setUrl(url);
|
||||
|
||||
std::cout << "Connecting to " << url << "..." << std::endl;
|
||||
|
||||
// Setup a callback to be fired (in a background thread, watch out for race conditions !)
|
||||
// when a message or an event (open, close, error) is received
|
||||
webSocket.setOnMessageCallback([](const ix::WebSocketMessagePtr& msg)
|
||||
{
|
||||
std::cout << msg->str << std::endl;
|
||||
if (msg->type == ix::WebSocketMessageType::Message)
|
||||
{
|
||||
std::cout << "received message: " << msg->str << std::endl;
|
||||
}
|
||||
else if (msg->type == ix::WebSocketMessageType::Open)
|
||||
{
|
||||
std::cout << "Connection established" << std::endl;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Now that our callback is setup, we can start our background thread and receive messages
|
||||
webSocket.start();
|
||||
|
||||
// Send a message to the server (default to TEXT mode)
|
||||
webSocket.send("hello world");
|
||||
|
||||
while (true)
|
||||
{
|
||||
std::string text;
|
||||
std::cout << "> " << std::flush;
|
||||
std::getline(std::cin, text);
|
||||
|
||||
webSocket.send(text);
|
||||
}
|
||||
);
|
||||
|
||||
// Now that our callback is setup, we can start our background thread and receive messages
|
||||
webSocket.start();
|
||||
|
||||
// Send a message to the server (default to TEXT mode)
|
||||
webSocket.send("hello world");
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Interested? Go read the [docs](https://machinezone.github.io/IXWebSocket/)! If things don't work as expected, please create an issue on GitHub, or even better a pull request if you know how to fix your problem.
|
||||
@ -46,6 +81,26 @@ If your company or project is using this library, feel free to open an issue or
|
||||
|
||||
- [Machine Zone](https://www.mz.com)
|
||||
- [Tokio](https://gitlab.com/HCInk/tokio), a discord library focused on audio playback with node bindings.
|
||||
- [libDiscordBot](https://github.com/tostc/libDiscordBot/tree/master), a work in progress discord library
|
||||
- [libDiscordBot](https://github.com/tostc/libDiscordBot/tree/master), an easy to use Discord-bot framework.
|
||||
- [gwebsocket](https://github.com/norrbotten/gwebsocket), a websocket (lua) module for Garry's Mod
|
||||
- [DisCPP](https://github.com/DisCPP/DisCPP), a simple but feature rich Discord API wrapper
|
||||
|
||||
## Continuous Integration
|
||||
|
||||
| OS | TLS | Sanitizer | Status |
|
||||
|-------------------|-------------------|-------------------|-------------------|
|
||||
| Linux | OpenSSL | None | [![Build2][1]][7] |
|
||||
| macOS | Secure Transport | Thread Sanitizer | [![Build2][2]][7] |
|
||||
| macOS | OpenSSL | Thread Sanitizer | [![Build2][3]][7] |
|
||||
| macOS | MbedTLS | Thread Sanitizer | [![Build2][4]][7] |
|
||||
| Windows | Disabled | None | [![Build2][5]][7] |
|
||||
| UWP | Disabled | None | [![Build2][6]][7] |
|
||||
|
||||
[1]: https://github.com/machinezone/IXWebSocket/workflows/linux/badge.svg
|
||||
[2]: https://github.com/machinezone/IXWebSocket/workflows/mac_tsan_sectransport/badge.svg
|
||||
[3]: https://github.com/machinezone/IXWebSocket/workflows/mac_tsan_openssl/badge.svg
|
||||
[4]: https://github.com/machinezone/IXWebSocket/workflows/mac_tsan_mbedtls/badge.svg
|
||||
[5]: https://github.com/machinezone/IXWebSocket/workflows/windows/badge.svg
|
||||
[6]: https://github.com/machinezone/IXWebSocket/workflows/uwp/badge.svg
|
||||
[7]: https://github.com/machinezone/IXWebSocket
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
FROM alpine:3.11 as build
|
||||
FROM alpine:3.12 as build
|
||||
|
||||
RUN apk add --no-cache \
|
||||
gcc g++ musl-dev linux-headers \
|
||||
cmake mbedtls-dev make zlib-dev ninja
|
||||
cmake mbedtls-dev make zlib-dev python3-dev ninja
|
||||
|
||||
RUN addgroup -S app && \
|
||||
adduser -S -G app app && \
|
||||
@ -18,9 +18,9 @@ USER app
|
||||
RUN make ws_mbedtls_install && \
|
||||
sh tools/trim_repo_for_docker.sh
|
||||
|
||||
FROM alpine:3.11 as runtime
|
||||
FROM alpine:3.12 as runtime
|
||||
|
||||
RUN apk add --no-cache libstdc++ mbedtls ca-certificates && \
|
||||
RUN apk add --no-cache libstdc++ mbedtls ca-certificates python3 && \
|
||||
addgroup -S app && \
|
||||
adduser -S -G app app
|
||||
|
||||
|
@ -1,6 +1,98 @@
|
||||
# Changelog
|
||||
All changes to this project will be documented in this file.
|
||||
|
||||
## [9.9.0] - 2020-07-08
|
||||
|
||||
(socket+websocket+http+redis+snake servers) expose the remote ip and remote port when a new connection is made
|
||||
|
||||
## [9.8.6] - 2020-07-06
|
||||
|
||||
(cmake) change the way zlib and openssl are searched
|
||||
|
||||
## [9.8.5] - 2020-07-06
|
||||
|
||||
(cobra python bots) remove the test which stop the bot when events do not follow cobra metrics system schema with an id and a device entry
|
||||
|
||||
## [9.8.4] - 2020-06-26
|
||||
|
||||
(cobra bots) remove bots which is not required now that we can use Python extensions
|
||||
|
||||
## [9.8.3] - 2020-06-25
|
||||
|
||||
(cmake) new python code is optional and enabled at cmake time with -DUSE_PYTHON=1
|
||||
|
||||
## [9.8.2] - 2020-06-24
|
||||
|
||||
(cobra bots) new cobra metrics bot to send data to statsd using Python for processing the message
|
||||
|
||||
## [9.8.1] - 2020-06-19
|
||||
|
||||
(cobra metrics to statsd bot) fps slow frame info : do not include os name
|
||||
|
||||
## [9.8.0] - 2020-06-19
|
||||
|
||||
(cobra metrics to statsd bot) send info about memory warnings
|
||||
|
||||
## [9.7.9] - 2020-06-18
|
||||
|
||||
(http client) fix deadlock when following redirects
|
||||
|
||||
## [9.7.8] - 2020-06-18
|
||||
|
||||
(cobra metrics to statsd bot) send info about net requests
|
||||
|
||||
## [9.7.7] - 2020-06-17
|
||||
|
||||
(cobra client and bots) add batch_size subscription option for retrieving multiple messages at once
|
||||
|
||||
## [9.7.6] - 2020-06-15
|
||||
|
||||
(websocket) WebSocketServer is not a final class, so that users can extend it (fix #215)
|
||||
|
||||
## [9.7.5] - 2020-06-15
|
||||
|
||||
(cobra bots) minor aesthetic change, in how we display http headers with a : then space as key value separator instead of :: with no space
|
||||
|
||||
## [9.7.4] - 2020-06-11
|
||||
|
||||
(cobra metrics to statsd bot) change from a statsd type of gauge to a timing one
|
||||
|
||||
## [9.7.3] - 2020-06-11
|
||||
|
||||
(redis cobra bots) capture most used devices in a zset
|
||||
|
||||
## [9.7.2] - 2020-06-11
|
||||
|
||||
(ws) add bare bone redis-cli like sub-command, with command line editing powered by libnoise
|
||||
|
||||
## [9.7.1] - 2020-06-11
|
||||
|
||||
(redis cobra bots) ws cobra metrics to redis / hostname invalid parsing
|
||||
|
||||
## [9.7.0] - 2020-06-11
|
||||
|
||||
(redis cobra bots) xadd with maxlen + fix bug in xadd client implementation and ws cobra metrics to redis command argument parsing
|
||||
|
||||
## [9.6.9] - 2020-06-10
|
||||
|
||||
(redis cobra bots) update the cobra to redis bot to use the bot framework, and change it to report fps metrics into redis streams.
|
||||
|
||||
## [9.6.6] - 2020-06-04
|
||||
|
||||
(statsd cobra bots) statsd improvement: prefix does not need a dot as a suffix, message size can be larger than 256 bytes, error handling was invalid, use core logger for logging instead of std::cerr
|
||||
|
||||
## [9.6.5] - 2020-05-29
|
||||
|
||||
(http server) support gzip compression
|
||||
|
||||
## [9.6.4] - 2020-05-20
|
||||
|
||||
(compiler fix) support clang 5 and earlier (contributed by @LunarWatcher)
|
||||
|
||||
## [9.6.3] - 2020-05-18
|
||||
|
||||
(cmake) revert CMake changes to fix #203 and be able to use an external OpenSSL
|
||||
|
||||
## [9.6.2] - 2020-05-17
|
||||
|
||||
(cmake) make install cmake files optional to not conflict with vcpkg
|
||||
|
@ -22,8 +22,9 @@ Options for building:
|
||||
* `-DUSE_MBED_TLS=1` will use [mbedlts](https://tls.mbed.org/) for the TLS support
|
||||
* `-DUSE_WS=1` will build the ws interactive command line tool
|
||||
* `-DUSE_TEST=1` will build the unittest
|
||||
* `-DUSE_PYTHON=1` will use Python3 for cobra bots, require Python3 to be installed.
|
||||
|
||||
If you are on Windows, look at the [appveyor](https://github.com/machinezone/IXWebSocket/blob/master/appveyor.yml) file (not maintained much though) or rather the [github actions](https://github.com/machinezone/IXWebSocket/blob/master/.github/workflows/ccpp.yml#L40) which have instructions for building dependencies.
|
||||
If you are on Windows, look at the [appveyor](https://github.com/machinezone/IXWebSocket/blob/master/appveyor.yml) file (not maintained much though) or rather the [github actions](https://github.com/machinezone/IXWebSocket/blob/master/.github/workflows/unittest_windows.yml) which have instructions for building dependencies.
|
||||
|
||||
It is also possible to externally include the project, so that everything is fetched over the wire when you build like so:
|
||||
|
||||
@ -42,6 +43,19 @@ It is possible to get IXWebSocket through Microsoft [vcpkg](https://github.com/m
|
||||
```
|
||||
vcpkg install ixwebsocket
|
||||
```
|
||||
To use the installed package within a cmake project, use the following:
|
||||
```cmake
|
||||
set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" CACHE STRING "") # this is super important in order for cmake to include the vcpkg search/lib paths!
|
||||
|
||||
# find library and its headers
|
||||
find_path(IXWEBSOCKET_INCLUDE_DIR ixwebsocket/IXWebSocket.h)
|
||||
find_library(IXWEBSOCKET_LIBRARY ixwebsocket)
|
||||
# include headers
|
||||
include_directories(${IXWEBSOCKET_INCLUDE_DIR})
|
||||
# ...
|
||||
target_link_libraries(${PROJECT_NAME} ... ${IXWEBSOCKET_LIBRARY}) # Cmake will automatically fail the generation if the lib was not found, i.e is set to NOTFOUNS
|
||||
|
||||
```
|
||||
|
||||
### Conan
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||

|
||||
|
||||
## Introduction
|
||||
|
||||
[*WebSocket*](https://en.wikipedia.org/wiki/WebSocket) is a computer communications protocol, providing full-duplex and bi-directionnal communication channels over a single TCP connection. *IXWebSocket* is a C++ library for client and server Websocket communication, and for client and server HTTP communication. *TLS* aka *SSL* is supported. The code is derived from [easywsclient](https://github.com/dhbaird/easywsclient) and from the [Satori C SDK](https://github.com/satori-com/satori-rtm-sdk-c). It has been tested on the following platforms.
|
||||
|
@ -257,28 +257,31 @@ ix::WebSocketServer server(port);
|
||||
|
||||
server.setOnConnectionCallback(
|
||||
[&server](std::shared_ptr<WebSocket> webSocket,
|
||||
std::shared_ptr<ConnectionState> connectionState)
|
||||
std::shared_ptr<ConnectionState> connectionState,
|
||||
std::unique_ptr<ConnectionInfo> connectionInfo)
|
||||
{
|
||||
std::cout << "Remote ip: " << connectionInfo->remoteIp << std::endl;
|
||||
|
||||
webSocket->setOnMessageCallback(
|
||||
[webSocket, connectionState, &server](const ix::WebSocketMessagePtr msg)
|
||||
{
|
||||
if (msg->type == ix::WebSocketMessageType::Open)
|
||||
{
|
||||
std::cerr << "New connection" << std::endl;
|
||||
std::cout << "New connection" << std::endl;
|
||||
|
||||
// A connection state object is available, and has a default id
|
||||
// You can subclass ConnectionState and pass an alternate factory
|
||||
// to override it. It is useful if you want to store custom
|
||||
// attributes per connection (authenticated bool flag, attributes, etc...)
|
||||
std::cerr << "id: " << connectionState->getId() << std::endl;
|
||||
std::cout << "id: " << connectionState->getId() << std::endl;
|
||||
|
||||
// The uri the client did connect to.
|
||||
std::cerr << "Uri: " << msg->openInfo.uri << std::endl;
|
||||
std::cout << "Uri: " << msg->openInfo.uri << std::endl;
|
||||
|
||||
std::cerr << "Headers:" << std::endl;
|
||||
std::cout << "Headers:" << std::endl;
|
||||
for (auto it : msg->openInfo.headers)
|
||||
{
|
||||
std::cerr << it.first << ": " << it.second << std::endl;
|
||||
std::cout << it.first << ": " << it.second << std::endl;
|
||||
}
|
||||
}
|
||||
else if (msg->type == ix::WebSocketMessageType::Message)
|
||||
@ -392,6 +395,8 @@ bool ok = httpClient.performRequest(args, [](const HttpResponsePtr& response)
|
||||
// ok will be false if your httpClient is not async
|
||||
```
|
||||
|
||||
See this [issue](https://github.com/machinezone/IXWebSocket/issues/209) for links about uploading files with HTTP multipart.
|
||||
|
||||
## HTTP server API
|
||||
|
||||
```cpp
|
||||
@ -415,11 +420,14 @@ If you want to handle how requests are processed, implement the setOnConnectionC
|
||||
```cpp
|
||||
setOnConnectionCallback(
|
||||
[this](HttpRequestPtr request,
|
||||
std::shared_ptr<ConnectionState> /*connectionState*/) -> HttpResponsePtr
|
||||
std::shared_ptr<ConnectionState> /*connectionState*/,
|
||||
std::unique_ptr<ConnectionInfo> connectionInfo) -> HttpResponsePtr
|
||||
{
|
||||
// Build a string for the response
|
||||
std::stringstream ss;
|
||||
ss << request->method
|
||||
ss << connectionInfo->remoteIp
|
||||
<< " "
|
||||
<< request->method
|
||||
<< " "
|
||||
<< request->uri;
|
||||
|
||||
|
46
httpd.cpp
Normal file
46
httpd.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* httpd.cpp
|
||||
* Author: Benjamin Sergeant
|
||||
* Copyright (c) 2020 Machine Zone, Inc. All rights reserved.
|
||||
*
|
||||
* Buid with make httpd
|
||||
*/
|
||||
|
||||
#include <ixwebsocket/IXHttpServer.h>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if (argc != 3)
|
||||
{
|
||||
std::cerr << "Usage: " << argv[0]
|
||||
<< " <port> <host>" << std::endl;
|
||||
std::cerr << " " << argv[0] << " 9090 127.0.0.1" << std::endl;
|
||||
std::cerr << " " << argv[0] << " 9090 0.0.0.0" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int port;
|
||||
std::stringstream ss;
|
||||
ss << argv[1];
|
||||
ss >> port;
|
||||
std::string hostname(argv[2]);
|
||||
|
||||
std::cout << "Listening on " << hostname
|
||||
<< ":" << port << std::endl;
|
||||
|
||||
ix::HttpServer server(port, hostname);
|
||||
|
||||
auto res = server.listen();
|
||||
if (!res.first)
|
||||
{
|
||||
std::cout << res.second << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
server.start();
|
||||
server.wait();
|
||||
|
||||
return 0;
|
||||
}
|
@ -8,6 +8,8 @@ set (IXBOTS_SOURCES
|
||||
ixbots/IXCobraToSentryBot.cpp
|
||||
ixbots/IXCobraToStatsdBot.cpp
|
||||
ixbots/IXCobraToStdoutBot.cpp
|
||||
ixbots/IXCobraMetricsToRedisBot.cpp
|
||||
ixbots/IXCobraToPythonBot.cpp
|
||||
ixbots/IXStatsdClient.cpp
|
||||
)
|
||||
|
||||
@ -17,6 +19,8 @@ set (IXBOTS_HEADERS
|
||||
ixbots/IXCobraToSentryBot.h
|
||||
ixbots/IXCobraToStatsdBot.h
|
||||
ixbots/IXCobraToStdoutBot.h
|
||||
ixbots/IXCobraMetricsToRedisBot.h
|
||||
ixbots/IXCobraToPythonBot.h
|
||||
ixbots/IXStatsdClient.h
|
||||
)
|
||||
|
||||
@ -30,14 +34,24 @@ if (NOT JSONCPP_FOUND)
|
||||
set(JSONCPP_INCLUDE_DIRS ../third_party/jsoncpp)
|
||||
endif()
|
||||
|
||||
if (USE_PYTHON)
|
||||
target_compile_definitions(ixbots PUBLIC IXBOTS_USE_PYTHON)
|
||||
find_package(Python COMPONENTS Development)
|
||||
endif()
|
||||
|
||||
set(IXBOTS_INCLUDE_DIRS
|
||||
.
|
||||
..
|
||||
../ixcore
|
||||
../ixwebsocket
|
||||
../ixcobra
|
||||
../ixredis
|
||||
../ixsentry
|
||||
${JSONCPP_INCLUDE_DIRS}
|
||||
${SPDLOG_INCLUDE_DIRS})
|
||||
|
||||
if (USE_PYTHON)
|
||||
set(IXBOTS_INCLUDE_DIRS ${IXBOTS_INCLUDE_DIRS} ${Python_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
target_include_directories( ixbots PUBLIC ${IXBOTS_INCLUDE_DIRS} )
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include <ixcobra/IXCobraConnection.h>
|
||||
#include <ixcore/utils/IXCoreLogger.h>
|
||||
#include <ixwebsocket/IXSetThreadName.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
@ -28,6 +29,7 @@ namespace ix
|
||||
auto runtime = botConfig.runtime;
|
||||
auto maxEventsPerMinute = botConfig.maxEventsPerMinute;
|
||||
auto limitReceivedEvents = botConfig.limitReceivedEvents;
|
||||
auto batchSize = botConfig.batchSize;
|
||||
|
||||
ix::CobraConnection conn;
|
||||
conn.configure(config);
|
||||
@ -43,6 +45,7 @@ namespace ix
|
||||
std::atomic<bool> stop(false);
|
||||
std::atomic<bool> throttled(false);
|
||||
std::atomic<bool> fatalCobraError(false);
|
||||
std::atomic<bool> stalledConnection(false);
|
||||
int minuteCounter = 0;
|
||||
|
||||
auto timer = [&sentCount,
|
||||
@ -53,7 +56,9 @@ namespace ix
|
||||
&receivedCountPerSecs,
|
||||
&receivedCountPerMinutes,
|
||||
&minuteCounter,
|
||||
&conn,
|
||||
&stop] {
|
||||
setThreadName("Bot progress");
|
||||
while (!stop)
|
||||
{
|
||||
//
|
||||
@ -70,7 +75,11 @@ namespace ix
|
||||
<< sentCountPerSecs
|
||||
<< " "
|
||||
<< sentCountTotal;
|
||||
CoreLogger::info(ss.str());
|
||||
|
||||
if (conn.isAuthenticated())
|
||||
{
|
||||
CoreLogger::info(ss.str());
|
||||
}
|
||||
|
||||
receivedCountPerSecs = receivedCount - receivedCountTotal;
|
||||
sentCountPerSecs = sentCount - sentCountTotal;
|
||||
@ -93,7 +102,14 @@ namespace ix
|
||||
|
||||
std::thread t1(timer);
|
||||
|
||||
auto heartbeat = [&sentCount, &receivedCount, &stop, &enableHeartbeat, &heartBeatTimeout, &fatalCobraError] {
|
||||
auto heartbeat = [&sentCount,
|
||||
&receivedCount,
|
||||
&stop,
|
||||
&enableHeartbeat,
|
||||
&heartBeatTimeout,
|
||||
&stalledConnection]
|
||||
{
|
||||
setThreadName("Bot heartbeat");
|
||||
std::string state("na");
|
||||
|
||||
if (!enableHeartbeat) return;
|
||||
@ -108,9 +124,12 @@ namespace ix
|
||||
|
||||
if (currentState == state)
|
||||
{
|
||||
CoreLogger::error("no messages received or sent for 1 minute, exiting");
|
||||
fatalCobraError = true;
|
||||
break;
|
||||
ss.str("");
|
||||
ss << "no messages received or sent for "
|
||||
<< heartBeatTimeout << " seconds, reconnecting";
|
||||
|
||||
CoreLogger::error(ss.str());
|
||||
stalledConnection = true;
|
||||
}
|
||||
state = currentState;
|
||||
|
||||
@ -135,6 +154,7 @@ namespace ix
|
||||
&receivedCountPerMinutes,
|
||||
maxEventsPerMinute,
|
||||
limitReceivedEvents,
|
||||
batchSize,
|
||||
&fatalCobraError,
|
||||
&sentCount](const CobraEventPtr& event) {
|
||||
if (event->type == ix::CobraEventType::Open)
|
||||
@ -143,7 +163,7 @@ namespace ix
|
||||
|
||||
for (auto&& it : event->headers)
|
||||
{
|
||||
CoreLogger::info(it.first + "::" + it.second);
|
||||
CoreLogger::info(it.first + ": " + it.second);
|
||||
}
|
||||
}
|
||||
else if (event->type == ix::CobraEventType::Closed)
|
||||
@ -156,7 +176,7 @@ namespace ix
|
||||
CoreLogger::info("Subscribing to " + channel);
|
||||
CoreLogger::info("Subscribing at position " + subscriptionPosition);
|
||||
CoreLogger::info("Subscribing with filter " + filter);
|
||||
conn.subscribe(channel, filter, subscriptionPosition,
|
||||
conn.subscribe(channel, filter, subscriptionPosition, batchSize,
|
||||
[&sentCount, &receivedCountPerMinutes,
|
||||
maxEventsPerMinute, limitReceivedEvents,
|
||||
&throttled, &receivedCount,
|
||||
@ -231,6 +251,13 @@ namespace ix
|
||||
std::this_thread::sleep_for(duration);
|
||||
|
||||
if (fatalCobraError) break;
|
||||
|
||||
if (stalledConnection)
|
||||
{
|
||||
conn.disconnect();
|
||||
conn.connect();
|
||||
stalledConnection = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Run for a duration, used by unittesting now
|
||||
@ -242,6 +269,13 @@ namespace ix
|
||||
std::this_thread::sleep_for(duration);
|
||||
|
||||
if (fatalCobraError) break;
|
||||
|
||||
if (stalledConnection)
|
||||
{
|
||||
conn.disconnect();
|
||||
conn.connect();
|
||||
stalledConnection = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -265,4 +299,22 @@ namespace ix
|
||||
{
|
||||
_onBotMessageCallback = callback;
|
||||
}
|
||||
|
||||
std::string CobraBot::getDeviceIdentifier(const Json::Value& msg)
|
||||
{
|
||||
std::string deviceId("na");
|
||||
|
||||
auto osName = msg["device"]["os_name"];
|
||||
if (osName == "Android")
|
||||
{
|
||||
deviceId = msg["device"]["model"].asString();
|
||||
}
|
||||
else if (osName == "iOS")
|
||||
{
|
||||
deviceId = msg["device"]["hardware_model"].asString();
|
||||
}
|
||||
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
} // namespace ix
|
||||
|
@ -28,6 +28,8 @@ namespace ix
|
||||
int64_t run(const CobraBotConfig& botConfig);
|
||||
void setOnBotMessageCallback(const OnBotMessageCallback& callback);
|
||||
|
||||
std::string getDeviceIdentifier(const Json::Value& msg);
|
||||
|
||||
private:
|
||||
OnBotMessageCallback _onBotMessageCallback;
|
||||
};
|
||||
|
@ -27,5 +27,6 @@ namespace ix
|
||||
int runtime = -1;
|
||||
int maxEventsPerMinute = std::numeric_limits<int>::max();
|
||||
bool limitReceivedEvents = false;
|
||||
int batchSize = 1;
|
||||
};
|
||||
} // namespace ix
|
||||
|
149
ixbots/ixbots/IXCobraMetricsToRedisBot.cpp
Normal file
149
ixbots/ixbots/IXCobraMetricsToRedisBot.cpp
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* IXCobraMetricsToRedisBot.cpp
|
||||
* Author: Benjamin Sergeant
|
||||
* Copyright (c) 2020 Machine Zone, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "IXCobraMetricsToRedisBot.h"
|
||||
|
||||
#include "IXCobraBot.h"
|
||||
#include "IXStatsdClient.h"
|
||||
#include <chrono>
|
||||
#include <ixcobra/IXCobraConnection.h>
|
||||
#include <ixcore/utils/IXCoreLogger.h>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <cctype>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
std::string removeSpaces(const std::string& str)
|
||||
{
|
||||
std::string out(str);
|
||||
out.erase(
|
||||
std::remove_if(out.begin(), out.end(), [](unsigned char x) { return std::isspace(x); }),
|
||||
out.end());
|
||||
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
namespace ix
|
||||
{
|
||||
bool processPerfMetricsEventSlowFrames(const Json::Value& msg,
|
||||
RedisClient& redisClient,
|
||||
const std::string& deviceId)
|
||||
{
|
||||
auto frameRateHistogramCounts = msg["data"]["FrameRateHistogramCounts"];
|
||||
|
||||
int slowFrames = 0;
|
||||
slowFrames += frameRateHistogramCounts[4].asInt();
|
||||
slowFrames += frameRateHistogramCounts[5].asInt();
|
||||
slowFrames += frameRateHistogramCounts[6].asInt();
|
||||
slowFrames += frameRateHistogramCounts[7].asInt();
|
||||
|
||||
//
|
||||
// XADD without a device id
|
||||
//
|
||||
std::stringstream ss;
|
||||
ss << msg["id"].asString() << "_slow_frames" << "."
|
||||
<< msg["device"]["game"].asString() << "."
|
||||
<< msg["device"]["os_name"].asString() << "."
|
||||
<< removeSpaces(msg["data"]["Tag"].asString());
|
||||
|
||||
int maxLen;
|
||||
maxLen = 100000;
|
||||
std::string id = ss.str();
|
||||
std::string errMsg;
|
||||
if (redisClient.xadd(id, std::to_string(slowFrames), maxLen, errMsg).empty())
|
||||
{
|
||||
CoreLogger::info(std::string("redis XADD error: ") + errMsg);
|
||||
}
|
||||
|
||||
//
|
||||
// XADD with a device id
|
||||
//
|
||||
ss.str(""); // reset the stringstream
|
||||
ss << msg["id"].asString() << "_slow_frames_by_device" << "."
|
||||
<< deviceId << "."
|
||||
<< msg["device"]["game"].asString() << "."
|
||||
<< msg["device"]["os_name"].asString() << "."
|
||||
<< removeSpaces(msg["data"]["Tag"].asString());
|
||||
|
||||
id = ss.str();
|
||||
maxLen = 1000;
|
||||
if (redisClient.xadd(id, std::to_string(slowFrames), maxLen, errMsg).empty())
|
||||
{
|
||||
CoreLogger::info(std::string("redis XADD error: ") + errMsg);
|
||||
}
|
||||
|
||||
//
|
||||
// Add device to the device zset, and increment the score
|
||||
// so that we know which devices are used more than others
|
||||
// ZINCRBY myzset 1 one
|
||||
//
|
||||
ss.str(""); // reset the stringstream
|
||||
ss << msg["id"].asString() << "_slow_frames_devices" << "."
|
||||
<< msg["device"]["game"].asString();
|
||||
|
||||
id = ss.str();
|
||||
std::vector<std::string> args = {
|
||||
"ZINCRBY", id, "1", deviceId
|
||||
};
|
||||
auto response = redisClient.send(args, errMsg);
|
||||
if (response.first == RespType::Error)
|
||||
{
|
||||
CoreLogger::info(std::string("redis ZINCRBY error: ") + errMsg);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int64_t cobra_metrics_to_redis_bot(const ix::CobraBotConfig& config,
|
||||
RedisClient& redisClient,
|
||||
bool verbose)
|
||||
{
|
||||
CobraBot bot;
|
||||
|
||||
bot.setOnBotMessageCallback(
|
||||
[&redisClient, &verbose, &bot]
|
||||
(const Json::Value& msg,
|
||||
const std::string& /*position*/,
|
||||
std::atomic<bool>& /*throttled*/,
|
||||
std::atomic<bool>& /*fatalCobraError*/,
|
||||
std::atomic<uint64_t>& sentCount) -> void {
|
||||
if (msg["device"].isNull())
|
||||
{
|
||||
CoreLogger::info("no device entry, skipping event");
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg["id"].isNull())
|
||||
{
|
||||
CoreLogger::info("no id entry, skipping event");
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Display full message with
|
||||
if (verbose)
|
||||
{
|
||||
CoreLogger::info(msg.toStyledString());
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
if (msg["id"].asString() == "engine_performance_metrics_id")
|
||||
{
|
||||
auto deviceId = bot.getDeviceIdentifier(msg);
|
||||
success = processPerfMetricsEventSlowFrames(msg, redisClient, deviceId);
|
||||
}
|
||||
|
||||
if (success) sentCount++;
|
||||
});
|
||||
|
||||
return bot.run(config);
|
||||
}
|
||||
} // namespace ix
|
20
ixbots/ixbots/IXCobraMetricsToRedisBot.h
Normal file
20
ixbots/ixbots/IXCobraMetricsToRedisBot.h
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* IXCobraMetricsToRedisBot.h
|
||||
* Author: Benjamin Sergeant
|
||||
* Copyright (c) 2020 Machine Zone, Inc. All rights reserved.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <ixredis/IXRedisClient.h>
|
||||
#include "IXCobraBotConfig.h"
|
||||
#include <stddef.h>
|
||||
#include <string>
|
||||
|
||||
namespace ix
|
||||
{
|
||||
int64_t cobra_metrics_to_redis_bot(const ix::CobraBotConfig& config,
|
||||
RedisClient& redisClient,
|
||||
bool verbose);
|
||||
} // namespace ix
|
||||
|
332
ixbots/ixbots/IXCobraToPythonBot.cpp
Normal file
332
ixbots/ixbots/IXCobraToPythonBot.cpp
Normal file
@ -0,0 +1,332 @@
|
||||
/*
|
||||
* IXCobraToPythonBot.cpp
|
||||
* Author: Benjamin Sergeant
|
||||
* Copyright (c) 2020 Machine Zone, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "IXCobraToPythonBot.h"
|
||||
|
||||
#include "IXCobraBot.h"
|
||||
#include "IXStatsdClient.h"
|
||||
#include <chrono>
|
||||
#include <ixcobra/IXCobraConnection.h>
|
||||
#include <ixcore/utils/IXCoreLogger.h>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <cctype>
|
||||
|
||||
//
|
||||
// I cannot get Windows to easily build on CI (github action) so support
|
||||
// is disabled for now. It should be a simple fix
|
||||
// (linking error about missing debug build)
|
||||
//
|
||||
|
||||
#ifdef IXBOTS_USE_PYTHON
|
||||
#define PY_SSIZE_T_CLEAN
|
||||
#include <Python.h>
|
||||
#endif
|
||||
|
||||
#ifdef IXBOTS_USE_PYTHON
|
||||
namespace
|
||||
{
|
||||
//
|
||||
// This function is unused at this point. It produce a correct output,
|
||||
// but triggers memory leaks when called repeateadly, as I cannot figure out how to
|
||||
// make the reference counting Python functions to work properly (Py_DECREF and friends)
|
||||
//
|
||||
PyObject* jsonToPythonObject(const Json::Value& val)
|
||||
{
|
||||
switch(val.type())
|
||||
{
|
||||
case Json::nullValue:
|
||||
{
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
case Json::intValue:
|
||||
{
|
||||
return PyLong_FromLong(val.asInt64());
|
||||
}
|
||||
|
||||
case Json::uintValue:
|
||||
{
|
||||
return PyLong_FromLong(val.asUInt64());
|
||||
}
|
||||
|
||||
case Json::realValue:
|
||||
{
|
||||
return PyFloat_FromDouble(val.asDouble());
|
||||
}
|
||||
|
||||
case Json::stringValue:
|
||||
{
|
||||
return PyUnicode_FromString(val.asCString());
|
||||
}
|
||||
|
||||
case Json::booleanValue:
|
||||
{
|
||||
return val.asBool() ? Py_True : Py_False;
|
||||
}
|
||||
|
||||
case Json::arrayValue:
|
||||
{
|
||||
PyObject* list = PyList_New(val.size());
|
||||
Py_ssize_t i = 0;
|
||||
for (auto&& it = val.begin(); it != val.end(); ++it)
|
||||
{
|
||||
PyList_SetItem(list, i++, jsonToPythonObject(*it));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
case Json::objectValue:
|
||||
{
|
||||
PyObject* dict = PyDict_New();
|
||||
for (auto&& it = val.begin(); it != val.end(); ++it)
|
||||
{
|
||||
PyObject* key = jsonToPythonObject(it.key());
|
||||
PyObject* value = jsonToPythonObject(*it);
|
||||
|
||||
PyDict_SetItem(dict, key, value);
|
||||
}
|
||||
return dict;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace ix
|
||||
{
|
||||
int64_t cobra_to_python_bot(const ix::CobraBotConfig& config,
|
||||
StatsdClient& statsdClient,
|
||||
const std::string& scriptPath)
|
||||
{
|
||||
#ifndef IXBOTS_USE_PYTHON
|
||||
CoreLogger::error("Command is disabled. "
|
||||
"Needs to be configured with USE_PYTHON=1");
|
||||
return -1;
|
||||
#else
|
||||
CobraBot bot;
|
||||
Py_InitializeEx(0); // 0 arg so that we do not install signal handlers
|
||||
// which prevent us from using Ctrl-C
|
||||
|
||||
size_t lastIndex = scriptPath.find_last_of(".");
|
||||
std::string modulePath = scriptPath.substr(0, lastIndex);
|
||||
|
||||
PyObject* pyModuleName = PyUnicode_DecodeFSDefault(modulePath.c_str());
|
||||
|
||||
if (pyModuleName == nullptr)
|
||||
{
|
||||
CoreLogger::error("Python error: Cannot decode file system path");
|
||||
PyErr_Print();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Import module
|
||||
PyObject* pyModule = PyImport_Import(pyModuleName);
|
||||
Py_DECREF(pyModuleName);
|
||||
if (pyModule == nullptr)
|
||||
{
|
||||
CoreLogger::error("Python error: Cannot import module.");
|
||||
CoreLogger::error("Module name cannot countain dash characters.");
|
||||
CoreLogger::error("Is PYTHONPATH set correctly ?");
|
||||
PyErr_Print();
|
||||
return false;
|
||||
}
|
||||
|
||||
// module main funtion name is named 'run'
|
||||
const std::string entryPoint("run");
|
||||
PyObject* pyFunc = PyObject_GetAttrString(pyModule, entryPoint.c_str());
|
||||
|
||||
if (!pyFunc)
|
||||
{
|
||||
CoreLogger::error("run symbol is missing from module.");
|
||||
PyErr_Print();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!PyCallable_Check(pyFunc))
|
||||
{
|
||||
CoreLogger::error("run symbol is not a function.");
|
||||
PyErr_Print();
|
||||
return false;
|
||||
}
|
||||
|
||||
bot.setOnBotMessageCallback(
|
||||
[&statsdClient, pyFunc]
|
||||
(const Json::Value& msg,
|
||||
const std::string& /*position*/,
|
||||
std::atomic<bool>& /*throttled*/,
|
||||
std::atomic<bool>& fatalCobraError,
|
||||
std::atomic<uint64_t>& sentCount) -> void {
|
||||
//
|
||||
// Invoke python script here. First build function parameters, a tuple
|
||||
//
|
||||
const int kVersion = 1; // We can bump this and let the interface evolve
|
||||
|
||||
PyObject *pyArgs = PyTuple_New(2);
|
||||
PyTuple_SetItem(pyArgs, 0, PyLong_FromLong(kVersion)); // First argument
|
||||
|
||||
//
|
||||
// It would be better to create a Python object (a dictionary)
|
||||
// from the json msg, but it is simpler to serialize it to a string
|
||||
// and decode it on the Python side of the fence
|
||||
//
|
||||
PyObject* pySerializedJson = PyUnicode_FromString(msg.toStyledString().c_str());
|
||||
PyTuple_SetItem(pyArgs, 1, pySerializedJson); // Second argument
|
||||
|
||||
// Invoke the python routine
|
||||
PyObject* pyList = PyObject_CallObject(pyFunc, pyArgs);
|
||||
|
||||
// Error calling the function
|
||||
if (pyList == nullptr)
|
||||
{
|
||||
fatalCobraError = true;
|
||||
CoreLogger::error("run() function call failed. Input msg: ");
|
||||
auto serializedMsg = msg.toStyledString();
|
||||
CoreLogger::error(serializedMsg);
|
||||
PyErr_Print();
|
||||
CoreLogger::error("================");
|
||||
return;
|
||||
}
|
||||
|
||||
// Invalid return type
|
||||
if (!PyList_Check(pyList))
|
||||
{
|
||||
fatalCobraError = true;
|
||||
CoreLogger::error("run() return type should be a list");
|
||||
return;
|
||||
}
|
||||
|
||||
// The result is a list of dict containing sufficient info
|
||||
// to send messages to statsd
|
||||
auto listSize = PyList_Size(pyList);
|
||||
|
||||
for (Py_ssize_t i = 0 ; i < listSize; ++i)
|
||||
{
|
||||
PyObject* dict = PyList_GetItem(pyList, i);
|
||||
|
||||
// Make sure this is a dict
|
||||
if (!PyDict_Check(dict))
|
||||
{
|
||||
fatalCobraError = true;
|
||||
CoreLogger::error("list element is not a dict");
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Retrieve object kind
|
||||
//
|
||||
PyObject* pyKind = PyDict_GetItemString(dict, "kind");
|
||||
if (!PyUnicode_Check(pyKind))
|
||||
{
|
||||
fatalCobraError = true;
|
||||
CoreLogger::error("kind entry is not a string");
|
||||
continue;
|
||||
}
|
||||
std::string kind(PyUnicode_AsUTF8(pyKind));
|
||||
|
||||
bool counter = false;
|
||||
bool gauge = false;
|
||||
bool timing = false;
|
||||
|
||||
if (kind == "counter")
|
||||
{
|
||||
counter = true;
|
||||
}
|
||||
else if (kind == "gauge")
|
||||
{
|
||||
gauge = true;
|
||||
}
|
||||
else if (kind == "timing")
|
||||
{
|
||||
timing = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
fatalCobraError = true;
|
||||
CoreLogger::error(std::string("invalid kind entry: ") + kind +
|
||||
". Supported ones are counter, gauge, timing");
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Retrieve object key
|
||||
//
|
||||
PyObject* pyKey = PyDict_GetItemString(dict, "key");
|
||||
if (!PyUnicode_Check(pyKey))
|
||||
{
|
||||
fatalCobraError = true;
|
||||
CoreLogger::error("key entry is not a string");
|
||||
continue;
|
||||
}
|
||||
std::string key(PyUnicode_AsUTF8(pyKey));
|
||||
|
||||
//
|
||||
// Retrieve object value and send data to statsd
|
||||
//
|
||||
PyObject* pyValue = PyDict_GetItemString(dict, "value");
|
||||
|
||||
// Send data to statsd
|
||||
if (PyFloat_Check(pyValue))
|
||||
{
|
||||
double value = PyFloat_AsDouble(pyValue);
|
||||
|
||||
if (counter)
|
||||
{
|
||||
statsdClient.count(key, value);
|
||||
}
|
||||
else if (gauge)
|
||||
{
|
||||
statsdClient.gauge(key, value);
|
||||
}
|
||||
else if (timing)
|
||||
{
|
||||
statsdClient.timing(key, value);
|
||||
}
|
||||
}
|
||||
else if (PyLong_Check(pyValue))
|
||||
{
|
||||
long value = PyLong_AsLong(pyValue);
|
||||
|
||||
if (counter)
|
||||
{
|
||||
statsdClient.count(key, value);
|
||||
}
|
||||
else if (gauge)
|
||||
{
|
||||
statsdClient.gauge(key, value);
|
||||
}
|
||||
else if (timing)
|
||||
{
|
||||
statsdClient.timing(key, value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fatalCobraError = true;
|
||||
CoreLogger::error("value entry is neither an int or a float");
|
||||
continue;
|
||||
}
|
||||
|
||||
sentCount++; // should we update this for each statsd object sent ?
|
||||
}
|
||||
|
||||
Py_DECREF(pyArgs);
|
||||
Py_DECREF(pyList);
|
||||
});
|
||||
|
||||
bool status = bot.run(config);
|
||||
|
||||
// Cleanup - we should do something similar in all exit case ...
|
||||
Py_DECREF(pyFunc);
|
||||
Py_DECREF(pyModule);
|
||||
Py_FinalizeEx();
|
||||
|
||||
return status;
|
||||
#endif
|
||||
}
|
||||
}
|
19
ixbots/ixbots/IXCobraToPythonBot.h
Normal file
19
ixbots/ixbots/IXCobraToPythonBot.h
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* IXCobraMetricsToStatsdBot.h
|
||||
* Author: Benjamin Sergeant
|
||||
* Copyright (c) 2020 Machine Zone, Inc. All rights reserved.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <ixbots/IXStatsdClient.h>
|
||||
#include "IXCobraBotConfig.h"
|
||||
#include <stddef.h>
|
||||
#include <string>
|
||||
|
||||
namespace ix
|
||||
{
|
||||
int64_t cobra_to_python_bot(const ix::CobraBotConfig& config,
|
||||
StatsdClient& statsdClient,
|
||||
const std::string& scriptPath);
|
||||
} // namespace ix
|
@ -70,11 +70,17 @@ namespace ix
|
||||
std::atomic<bool>& fatalCobraError,
|
||||
std::atomic<uint64_t>& sentCount) -> void {
|
||||
std::string id;
|
||||
size_t idx = 0;
|
||||
for (auto&& attr : tokens)
|
||||
{
|
||||
id += ".";
|
||||
auto val = extractAttr(attr, msg);
|
||||
id += val.asString();
|
||||
|
||||
// We add a dot separator unless we are processing the last token
|
||||
if (idx++ != tokens.size() - 1)
|
||||
{
|
||||
id += ".";
|
||||
}
|
||||
}
|
||||
|
||||
if (gauge.empty() && timer.empty())
|
||||
|
@ -39,21 +39,28 @@
|
||||
|
||||
#include "IXStatsdClient.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <ixwebsocket/IXNetSystem.h>
|
||||
#include <stdio.h>
|
||||
#include <ixwebsocket/IXSetThreadName.h>
|
||||
#include <ixcore/utils/IXCoreLogger.h>
|
||||
#include <sstream>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace ix
|
||||
{
|
||||
StatsdClient::StatsdClient(const std::string& host, int port, const std::string& prefix)
|
||||
StatsdClient::StatsdClient(const std::string& host,
|
||||
int port,
|
||||
const std::string& prefix,
|
||||
bool verbose)
|
||||
: _host(host)
|
||||
, _port(port)
|
||||
, _prefix(prefix)
|
||||
, _stop(false)
|
||||
, _verbose(verbose)
|
||||
{
|
||||
_thread = std::thread([this] {
|
||||
setThreadName("Statsd");
|
||||
|
||||
while (!_stop)
|
||||
{
|
||||
flushQueue();
|
||||
@ -115,11 +122,15 @@ namespace ix
|
||||
{
|
||||
cleanup(key);
|
||||
|
||||
char buf[256];
|
||||
snprintf(
|
||||
buf, sizeof(buf), "%s%s:%zd|%s\n", _prefix.c_str(), key.c_str(), value, type.c_str());
|
||||
std::stringstream ss;
|
||||
ss << _prefix << "." << key << ":" << value << "|" << type;
|
||||
|
||||
enqueue(buf);
|
||||
if (_verbose)
|
||||
{
|
||||
CoreLogger::info(ss.str());
|
||||
}
|
||||
|
||||
enqueue(ss.str() + "\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -137,10 +148,13 @@ namespace ix
|
||||
{
|
||||
auto message = _queue.front();
|
||||
auto ret = _socket.sendto(message);
|
||||
if (ret != 0)
|
||||
if (ret == -1)
|
||||
{
|
||||
std::cerr << "error: " << strerror(UdpSocket::getErrno()) << std::endl;
|
||||
CoreLogger::error(std::string("statsd error: ") + strerror(UdpSocket::getErrno()));
|
||||
}
|
||||
|
||||
// we always dequeue regardless of the ability to send the message
|
||||
// so that we keep our queue size under control
|
||||
_queue.pop_front();
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,8 @@ namespace ix
|
||||
public:
|
||||
StatsdClient(const std::string& host = "127.0.0.1",
|
||||
int port = 8125,
|
||||
const std::string& prefix = "");
|
||||
const std::string& prefix = "",
|
||||
bool verbose = false);
|
||||
~StatsdClient();
|
||||
|
||||
bool init(std::string& errMsg);
|
||||
@ -52,6 +53,7 @@ namespace ix
|
||||
std::mutex _mutex; // for the queue
|
||||
|
||||
std::deque<std::string> _queue;
|
||||
bool _verbose;
|
||||
};
|
||||
|
||||
} // end namespace ix
|
||||
|
@ -562,11 +562,13 @@ namespace ix
|
||||
void CobraConnection::subscribe(const std::string& channel,
|
||||
const std::string& filter,
|
||||
const std::string& position,
|
||||
int batchSize,
|
||||
SubscriptionCallback cb)
|
||||
{
|
||||
// Create and send a subscribe pdu
|
||||
Json::Value body;
|
||||
body["channel"] = channel;
|
||||
body["batch_size"] = batchSize;
|
||||
|
||||
if (!filter.empty())
|
||||
{
|
||||
|
@ -88,6 +88,7 @@ namespace ix
|
||||
void subscribe(const std::string& channel,
|
||||
const std::string& filter = std::string(),
|
||||
const std::string& position = std::string(),
|
||||
int batchSize = 1,
|
||||
SubscriptionCallback cb = nullptr);
|
||||
|
||||
/// Unsubscribe from a channel
|
||||
|
@ -37,9 +37,7 @@ if (USE_MBED_TLS)
|
||||
target_include_directories(ixcrypto PUBLIC ${MBEDTLS_INCLUDE_DIRS})
|
||||
target_link_libraries(ixcrypto ${MBEDTLS_LIBRARIES})
|
||||
target_compile_definitions(ixcrypto PUBLIC IXCRYPTO_USE_MBED_TLS)
|
||||
elseif (APPLE)
|
||||
elseif (WIN32)
|
||||
else()
|
||||
elseif (USE_OPEN_SSL)
|
||||
find_package(OpenSSL REQUIRED)
|
||||
add_definitions(${OPENSSL_DEFINITIONS})
|
||||
message(STATUS "OpenSSL: " ${OPENSSL_VERSION})
|
||||
|
27
ixredis/CMakeLists.txt
Normal file
27
ixredis/CMakeLists.txt
Normal file
@ -0,0 +1,27 @@
|
||||
#
|
||||
# Author: Benjamin Sergeant
|
||||
# Copyright (c) 2020 Machine Zone, Inc. All rights reserved.
|
||||
#
|
||||
|
||||
set (IXREDIS_SOURCES
|
||||
ixredis/IXRedisClient.cpp
|
||||
ixredis/IXRedisServer.cpp
|
||||
)
|
||||
|
||||
set (IXREDIS_HEADERS
|
||||
ixredis/IXRedisClient.h
|
||||
ixredis/IXRedisServer.h
|
||||
)
|
||||
|
||||
add_library(ixredis STATIC
|
||||
${IXREDIS_SOURCES}
|
||||
${IXREDIS_HEADERS}
|
||||
)
|
||||
|
||||
set(IXREDIS_INCLUDE_DIRS
|
||||
.
|
||||
..
|
||||
../ixcore
|
||||
../ixwebsocket)
|
||||
|
||||
target_include_directories( ixredis PUBLIC ${IXREDIS_INCLUDE_DIRS} )
|
@ -9,6 +9,7 @@
|
||||
#include <cstring>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <ixwebsocket/IXSocket.h>
|
||||
#include <ixwebsocket/IXSocketFactory.h>
|
||||
#include <ixwebsocket/IXSocketTLSOptions.h>
|
||||
#include <sstream>
|
||||
@ -250,12 +251,16 @@ namespace ix
|
||||
}
|
||||
|
||||
std::string RedisClient::prepareXaddCommand(const std::string& stream,
|
||||
const std::string& message)
|
||||
const std::string& message,
|
||||
int maxLen)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "*5\r\n";
|
||||
ss << "*8\r\n";
|
||||
ss << writeString("XADD");
|
||||
ss << writeString(stream);
|
||||
ss << writeString("MAXLEN");
|
||||
ss << writeString("~");
|
||||
ss << writeString(std::to_string(maxLen));
|
||||
ss << writeString("*");
|
||||
ss << writeString("field");
|
||||
ss << writeString(message);
|
||||
@ -265,6 +270,7 @@ namespace ix
|
||||
|
||||
std::string RedisClient::xadd(const std::string& stream,
|
||||
const std::string& message,
|
||||
int maxLen,
|
||||
std::string& errMsg)
|
||||
{
|
||||
errMsg.clear();
|
||||
@ -275,7 +281,7 @@ namespace ix
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::string command = prepareXaddCommand(stream, message);
|
||||
std::string command = prepareXaddCommand(stream, message, maxLen);
|
||||
|
||||
bool sent = _socket->writeBytes(command, nullptr);
|
||||
if (!sent)
|
||||
@ -348,4 +354,104 @@ namespace ix
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
std::pair<RespType, std::string> RedisClient::send(
|
||||
const std::vector<std::string>& args,
|
||||
std::string& errMsg)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "*";
|
||||
ss << std::to_string(args.size());
|
||||
ss << "\r\n";
|
||||
|
||||
for (auto&& arg : args)
|
||||
{
|
||||
ss << writeString(arg);
|
||||
}
|
||||
|
||||
bool sent = _socket->writeBytes(ss.str(), nullptr);
|
||||
if (!sent)
|
||||
{
|
||||
errMsg = "Cannot write bytes to socket";
|
||||
return std::make_pair(RespType::Error, "");
|
||||
}
|
||||
|
||||
return readResponse(errMsg);
|
||||
}
|
||||
|
||||
std::pair<RespType, std::string> RedisClient::readResponse(std::string& errMsg)
|
||||
{
|
||||
// Read result
|
||||
auto pollResult = _socket->isReadyToRead(-1);
|
||||
if (pollResult == PollResultType::Error)
|
||||
{
|
||||
errMsg = "Error while polling for result";
|
||||
return std::make_pair(RespType::Error, "");
|
||||
}
|
||||
|
||||
// First line is the string length
|
||||
auto lineResult = _socket->readLine(nullptr);
|
||||
auto lineValid = lineResult.first;
|
||||
auto line = lineResult.second;
|
||||
|
||||
if (!lineValid)
|
||||
{
|
||||
errMsg = "Error while polling for result";
|
||||
return std::make_pair(RespType::Error, "");
|
||||
}
|
||||
|
||||
std::string response;
|
||||
|
||||
if (line[0] == '+') // Simple string
|
||||
{
|
||||
std::stringstream ss;
|
||||
response = line.substr(1, line.size() - 3);
|
||||
return std::make_pair(RespType::String, response);
|
||||
}
|
||||
else if (line[0] == '-') // Errors
|
||||
{
|
||||
std::stringstream ss;
|
||||
response = line.substr(1, line.size() - 3);
|
||||
return std::make_pair(RespType::Error, response);
|
||||
}
|
||||
else if (line[0] == ':') // Integers
|
||||
{
|
||||
std::stringstream ss;
|
||||
response = line.substr(1, line.size() - 3);
|
||||
return std::make_pair(RespType::Integer, response);
|
||||
}
|
||||
else if (line[0] == '$') // Bulk strings
|
||||
{
|
||||
int stringSize;
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << line.substr(1, line.size() - 1);
|
||||
ss >> stringSize;
|
||||
}
|
||||
|
||||
// Read the result, which is the stream id computed by the redis server
|
||||
lineResult = _socket->readLine(nullptr);
|
||||
lineValid = lineResult.first;
|
||||
line = lineResult.second;
|
||||
|
||||
std::string str = line.substr(0, stringSize);
|
||||
return std::make_pair(RespType::String, str);
|
||||
}
|
||||
else
|
||||
{
|
||||
errMsg = "Unhandled response type";
|
||||
return std::make_pair(RespType::Unknown, std::string());
|
||||
}
|
||||
}
|
||||
|
||||
std::string RedisClient::getRespTypeDescription(RespType respType)
|
||||
{
|
||||
switch (respType)
|
||||
{
|
||||
case RespType::Integer: return "integer";
|
||||
case RespType::Error: return "error";
|
||||
case RespType::String: return "string";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
} // namespace ix
|
@ -8,12 +8,20 @@
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <ixwebsocket/IXSocket.h>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <ixwebsocket/IXSocket.h>
|
||||
|
||||
namespace ix
|
||||
{
|
||||
enum class RespType : int
|
||||
{
|
||||
String = 0,
|
||||
Error = 1,
|
||||
Integer = 2,
|
||||
Unknown = 3
|
||||
};
|
||||
|
||||
class RedisClient
|
||||
{
|
||||
public:
|
||||
@ -40,13 +48,22 @@ namespace ix
|
||||
// XADD
|
||||
std::string xadd(const std::string& channel,
|
||||
const std::string& message,
|
||||
int maxLen,
|
||||
std::string& errMsg);
|
||||
|
||||
std::string prepareXaddCommand(const std::string& stream, const std::string& message);
|
||||
|
||||
std::string prepareXaddCommand(const std::string& stream,
|
||||
const std::string& message,
|
||||
int maxLen);
|
||||
std::string readXaddReply(std::string& errMsg);
|
||||
bool sendCommand(
|
||||
const std::string& commands, int commandsCount, std::string& errMsg);
|
||||
|
||||
bool sendCommand(const std::string& commands, int commandsCount, std::string& errMsg);
|
||||
// Arbitrary commands
|
||||
std::pair<RespType, std::string> send(
|
||||
const std::vector<std::string>& args,
|
||||
std::string& errMsg);
|
||||
std::pair<RespType, std::string> readResponse(std::string& errMsg);
|
||||
|
||||
std::string getRespTypeDescription(RespType respType);
|
||||
|
||||
void stop();
|
||||
|
@ -45,8 +45,11 @@ namespace ix
|
||||
}
|
||||
|
||||
void RedisServer::handleConnection(std::unique_ptr<Socket> socket,
|
||||
std::shared_ptr<ConnectionState> connectionState)
|
||||
std::shared_ptr<ConnectionState> connectionState,
|
||||
std::unique_ptr<ConnectionInfo> connectionInfo)
|
||||
{
|
||||
logInfo("New connection from remote ip " + connectionInfo->remoteIp);
|
||||
|
||||
_connectedClientsCount++;
|
||||
|
||||
while (!_stopHandlingConnections)
|
||||
@ -112,7 +115,7 @@ namespace ix
|
||||
it.second.erase(socket.get());
|
||||
}
|
||||
|
||||
for (auto it : _subscribers)
|
||||
for (auto&& it : _subscribers)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Subscription id: " << it.first << " #subscribers: " << it.second.size();
|
@ -6,8 +6,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IXSocket.h"
|
||||
#include "IXSocketServer.h"
|
||||
#include <ixwebsocket/IXSocket.h>
|
||||
#include <ixwebsocket/IXSocketServer.h>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
@ -44,7 +44,8 @@ namespace ix
|
||||
|
||||
// Methods
|
||||
virtual void handleConnection(std::unique_ptr<Socket>,
|
||||
std::shared_ptr<ConnectionState> connectionState) final;
|
||||
std::shared_ptr<ConnectionState> connectionState,
|
||||
std::unique_ptr<ConnectionInfo> connectionInfo) final;
|
||||
virtual size_t getConnectedClientsCount() final;
|
||||
|
||||
bool startsWith(const std::string& str, const std::string& start);
|
@ -7,16 +7,14 @@ set (IXSNAKE_SOURCES
|
||||
ixsnake/IXSnakeServer.cpp
|
||||
ixsnake/IXSnakeProtocol.cpp
|
||||
ixsnake/IXAppConfig.cpp
|
||||
ixsnake/IXRedisClient.cpp
|
||||
ixsnake/IXRedisServer.cpp
|
||||
ixsnake/IXStreamSql.cpp
|
||||
)
|
||||
|
||||
set (IXSNAKE_HEADERS
|
||||
ixsnake/IXSnakeServer.h
|
||||
ixsnake/IXSnakeProtocol.h
|
||||
ixsnake/IXAppConfig.h
|
||||
ixsnake/IXRedisClient.h
|
||||
ixsnake/IXRedisServer.h
|
||||
ixsnake/IXStreamSql.h
|
||||
)
|
||||
|
||||
add_library(ixsnake STATIC
|
||||
@ -30,6 +28,7 @@ set(IXSNAKE_INCLUDE_DIRS
|
||||
../ixcore
|
||||
../ixcrypto
|
||||
../ixwebsocket
|
||||
../ixredis
|
||||
../third_party)
|
||||
|
||||
target_include_directories( ixsnake PUBLIC ${IXSNAKE_INCLUDE_DIRS} )
|
||||
|
@ -33,6 +33,9 @@ namespace snake
|
||||
// Misc
|
||||
bool verbose;
|
||||
bool disablePong;
|
||||
|
||||
// If non empty, every published message gets republished to a given channel
|
||||
std::string republishChannel;
|
||||
};
|
||||
|
||||
bool isAppKeyValid(const AppConfig& appConfig, std::string appkey);
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IXRedisClient.h"
|
||||
#include <ixredis/IXRedisClient.h>
|
||||
#include <future>
|
||||
#include <ixwebsocket/IXConnectionState.h>
|
||||
#include <string>
|
||||
@ -30,6 +30,7 @@ namespace snake
|
||||
{
|
||||
return _appkey;
|
||||
}
|
||||
|
||||
void setAppkey(const std::string& appkey)
|
||||
{
|
||||
_appkey = appkey;
|
||||
@ -39,6 +40,7 @@ namespace snake
|
||||
{
|
||||
return _role;
|
||||
}
|
||||
|
||||
void setRole(const std::string& role)
|
||||
{
|
||||
_role = role;
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "IXAppConfig.h"
|
||||
#include "IXSnakeConnectionState.h"
|
||||
#include "IXStreamSql.h"
|
||||
#include "nlohmann/json.hpp"
|
||||
#include <iostream>
|
||||
#include <ixcore/utils/IXCoreLogger.h>
|
||||
@ -91,6 +92,7 @@ namespace snake
|
||||
|
||||
void handlePublish(std::shared_ptr<SnakeConnectionState> state,
|
||||
std::shared_ptr<ix::WebSocket> ws,
|
||||
const AppConfig& appConfig,
|
||||
const nlohmann::json& pdu)
|
||||
{
|
||||
std::vector<std::string> channels;
|
||||
@ -115,6 +117,12 @@ namespace snake
|
||||
return;
|
||||
}
|
||||
|
||||
// add an extra channel if the config has one specified
|
||||
if (!appConfig.republishChannel.empty())
|
||||
{
|
||||
channels.push_back(appConfig.republishChannel);
|
||||
}
|
||||
|
||||
for (auto&& channel : channels)
|
||||
{
|
||||
std::stringstream ss;
|
||||
@ -180,12 +188,25 @@ namespace snake
|
||||
}
|
||||
}
|
||||
|
||||
std::string filterStr;
|
||||
if (pdu["body"].find("filter") != pdu["body"].end())
|
||||
{
|
||||
std::string filterStr = pdu["body"]["filter"];
|
||||
}
|
||||
|
||||
std::unique_ptr<StreamSql> streamSql = std::make_unique<StreamSql>(filterStr);
|
||||
|
||||
int id = 0;
|
||||
auto callback = [ws, &id, &subscriptionId](const std::string& messageStr) {
|
||||
auto callback = [ws, &id, &subscriptionId, &streamSql](const std::string& messageStr) {
|
||||
auto msg = nlohmann::json::parse(messageStr);
|
||||
|
||||
msg = msg["body"]["message"];
|
||||
|
||||
if (streamSql->valid() && !streamSql->match(msg))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
nlohmann::json response = {
|
||||
{"action", "rtm/subscription/data"},
|
||||
{"id", id++},
|
||||
@ -279,7 +300,7 @@ namespace snake
|
||||
}
|
||||
else if (action == "rtm/publish")
|
||||
{
|
||||
handlePublish(state, ws, pdu);
|
||||
handlePublish(state, ws, appConfig, pdu);
|
||||
}
|
||||
else if (action == "rtm/subscribe")
|
||||
{
|
||||
|
@ -61,16 +61,19 @@ namespace snake
|
||||
|
||||
_server.setOnConnectionCallback(
|
||||
[this](std::shared_ptr<ix::WebSocket> webSocket,
|
||||
std::shared_ptr<ix::ConnectionState> connectionState) {
|
||||
std::shared_ptr<ix::ConnectionState> connectionState,
|
||||
std::unique_ptr<ix::ConnectionInfo> connectionInfo) {
|
||||
auto state = std::dynamic_pointer_cast<SnakeConnectionState>(connectionState);
|
||||
|
||||
auto remoteIp = connectionInfo->remoteIp;
|
||||
|
||||
webSocket->setOnMessageCallback(
|
||||
[this, webSocket, state](const ix::WebSocketMessagePtr& msg) {
|
||||
[this, webSocket, state, remoteIp](const ix::WebSocketMessagePtr& msg) {
|
||||
std::stringstream ss;
|
||||
ix::LogLevel logLevel = ix::LogLevel::Debug;
|
||||
if (msg->type == ix::WebSocketMessageType::Open)
|
||||
{
|
||||
ss << "New connection" << std::endl;
|
||||
ss << "remote ip: " << remoteIp << std::endl;
|
||||
ss << "id: " << state->getId() << std::endl;
|
||||
ss << "Uri: " << msg->openInfo.uri << std::endl;
|
||||
ss << "Headers:" << std::endl;
|
||||
|
63
ixsnake/ixsnake/IXStreamSql.cpp
Normal file
63
ixsnake/ixsnake/IXStreamSql.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* IXStreamSql.cpp
|
||||
* Author: Benjamin Sergeant
|
||||
* Copyright (c) 2020 Machine Zone, Inc. All rights reserved.
|
||||
*
|
||||
* Super simple hacked up version of a stream sql expression,
|
||||
* that only supports non nested field evaluation
|
||||
*/
|
||||
|
||||
#include "IXStreamSql.h"
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
namespace snake
|
||||
{
|
||||
StreamSql::StreamSql(const std::string& sqlFilter)
|
||||
: _valid(false)
|
||||
{
|
||||
std::string token;
|
||||
std::stringstream tokenStream(sqlFilter);
|
||||
std::vector<std::string> tokens;
|
||||
|
||||
// Split by ' '
|
||||
while (std::getline(tokenStream, token, ' '))
|
||||
{
|
||||
tokens.push_back(token);
|
||||
}
|
||||
|
||||
_valid = tokens.size() == 8;
|
||||
if (!_valid) return;
|
||||
|
||||
_field = tokens[5];
|
||||
_operator = tokens[6];
|
||||
_value = tokens[7];
|
||||
|
||||
// remove single quotes
|
||||
_value = _value.substr(1, _value.size() - 2);
|
||||
|
||||
if (_operator == "LIKE")
|
||||
{
|
||||
_value = _value.substr(1, _value.size() - 2);
|
||||
}
|
||||
}
|
||||
|
||||
bool StreamSql::valid() const
|
||||
{
|
||||
return _valid;
|
||||
}
|
||||
|
||||
bool StreamSql::match(const nlohmann::json& msg)
|
||||
{
|
||||
if (!_valid) return false;
|
||||
|
||||
if (msg.find(_field) == msg.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string value = msg[_field];
|
||||
return value == _value;
|
||||
}
|
||||
|
||||
} // namespace snake
|
29
ixsnake/ixsnake/IXStreamSql.h
Normal file
29
ixsnake/ixsnake/IXStreamSql.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* IXStreamSql.h
|
||||
* Author: Benjamin Sergeant
|
||||
* Copyright (c) 2020 Machine Zone, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "nlohmann/json.hpp"
|
||||
|
||||
namespace snake
|
||||
{
|
||||
class StreamSql
|
||||
{
|
||||
public:
|
||||
StreamSql(const std::string& sqlFilter = std::string());
|
||||
~StreamSql() = default;
|
||||
|
||||
bool match(const nlohmann::json& msg);
|
||||
bool valid() const;
|
||||
|
||||
private:
|
||||
std::string _field;
|
||||
std::string _operator;
|
||||
std::string _value;
|
||||
bool _valid;
|
||||
};
|
||||
}
|
25
ixwebsocket/IXConnectionInfo.h
Normal file
25
ixwebsocket/IXConnectionInfo.h
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* IXConnectionInfo.h
|
||||
* Author: Benjamin Sergeant
|
||||
* Copyright (c) 2020 Machine Zone, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace ix
|
||||
{
|
||||
struct ConnectionInfo
|
||||
{
|
||||
std::string remoteIp;
|
||||
int remotePort;
|
||||
|
||||
ConnectionInfo(const std::string& r = std::string(), int p = 0)
|
||||
: remoteIp(r)
|
||||
, remotePort(p)
|
||||
{
|
||||
;
|
||||
}
|
||||
};
|
||||
} // namespace ix
|
@ -127,7 +127,7 @@ namespace ix
|
||||
{
|
||||
// We only have one socket connection, so we cannot
|
||||
// make multiple requests concurrently.
|
||||
std::lock_guard<std::mutex> lock(_mutex);
|
||||
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||||
|
||||
uint64_t uploadSize = 0;
|
||||
uint64_t downloadSize = 0;
|
||||
|
@ -103,7 +103,9 @@ namespace ix
|
||||
std::thread _thread;
|
||||
|
||||
std::unique_ptr<Socket> _socket;
|
||||
std::mutex _mutex; // to protect accessing the _socket (only one socket per client)
|
||||
std::recursive_mutex _mutex; // to protect accessing the _socket (only one socket per
|
||||
// client) the mutex needs to be recursive as this function
|
||||
// might be called recursively to follow HTTP redirections
|
||||
|
||||
SocketTLSOptions _tlsOptions;
|
||||
|
||||
|
@ -9,9 +9,11 @@
|
||||
#include "IXNetSystem.h"
|
||||
#include "IXSocketConnect.h"
|
||||
#include "IXUserAgent.h"
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <zlib.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -38,6 +40,49 @@ namespace
|
||||
auto vec = res.second;
|
||||
return std::make_pair(res.first, std::string(vec.begin(), vec.end()));
|
||||
}
|
||||
|
||||
std::string gzipCompress(const std::string& str)
|
||||
{
|
||||
z_stream zs; // z_stream is zlib's control structure
|
||||
memset(&zs, 0, sizeof(zs));
|
||||
|
||||
// deflateInit2 configure the file format: request gzip instead of deflate
|
||||
const int windowBits = 15;
|
||||
const int GZIP_ENCODING = 16;
|
||||
|
||||
deflateInit2(&zs,
|
||||
Z_DEFAULT_COMPRESSION,
|
||||
Z_DEFLATED,
|
||||
windowBits | GZIP_ENCODING,
|
||||
8,
|
||||
Z_DEFAULT_STRATEGY);
|
||||
|
||||
zs.next_in = (Bytef*) str.data();
|
||||
zs.avail_in = (uInt) str.size(); // set the z_stream's input
|
||||
|
||||
int ret;
|
||||
char outbuffer[32768];
|
||||
std::string outstring;
|
||||
|
||||
// retrieve the compressed bytes blockwise
|
||||
do
|
||||
{
|
||||
zs.next_out = reinterpret_cast<Bytef*>(outbuffer);
|
||||
zs.avail_out = sizeof(outbuffer);
|
||||
|
||||
ret = deflate(&zs, Z_FINISH);
|
||||
|
||||
if (outstring.size() < zs.total_out)
|
||||
{
|
||||
// append the block to the output string
|
||||
outstring.append(outbuffer, zs.total_out - outstring.size());
|
||||
}
|
||||
} while (ret == Z_OK);
|
||||
|
||||
deflateEnd(&zs);
|
||||
|
||||
return outstring;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace ix
|
||||
@ -70,7 +115,8 @@ namespace ix
|
||||
}
|
||||
|
||||
void HttpServer::handleConnection(std::unique_ptr<Socket> socket,
|
||||
std::shared_ptr<ConnectionState> connectionState)
|
||||
std::shared_ptr<ConnectionState> connectionState,
|
||||
std::unique_ptr<ConnectionInfo> connectionInfo)
|
||||
{
|
||||
_connectedClientsCount++;
|
||||
|
||||
@ -79,7 +125,9 @@ namespace ix
|
||||
|
||||
if (std::get<0>(ret))
|
||||
{
|
||||
auto response = _onConnectionCallback(std::get<2>(ret), connectionState);
|
||||
auto response = _onConnectionCallback(std::get<2>(ret),
|
||||
connectionState,
|
||||
std::move(connectionInfo));
|
||||
if (!Http::sendResponse(response, socket))
|
||||
{
|
||||
logError("Cannot send response");
|
||||
@ -99,7 +147,8 @@ namespace ix
|
||||
{
|
||||
setOnConnectionCallback(
|
||||
[this](HttpRequestPtr request,
|
||||
std::shared_ptr<ConnectionState> /*connectionState*/) -> HttpResponsePtr {
|
||||
std::shared_ptr<ConnectionState> /*connectionState*/,
|
||||
std::unique_ptr<ConnectionInfo> connectionInfo) -> HttpResponsePtr {
|
||||
std::string uri(request->uri);
|
||||
if (uri.empty() || uri == "/")
|
||||
{
|
||||
@ -120,9 +169,17 @@ namespace ix
|
||||
|
||||
std::string content = res.second;
|
||||
|
||||
std::string acceptEncoding = request->headers["Accept-encoding"];
|
||||
if (acceptEncoding == "*" || acceptEncoding.find("gzip") != std::string::npos)
|
||||
{
|
||||
content = gzipCompress(content);
|
||||
headers["Content-Encoding"] = "gzip";
|
||||
}
|
||||
|
||||
// Log request
|
||||
std::stringstream ss;
|
||||
ss << request->method << " " << request->headers["User-Agent"] << " "
|
||||
ss << connectionInfo->remoteIp << ":" << connectionInfo->remotePort << " "
|
||||
<< request->method << " " << request->headers["User-Agent"] << " "
|
||||
<< request->uri << " " << content.size();
|
||||
logInfo(ss.str());
|
||||
|
||||
@ -148,13 +205,15 @@ namespace ix
|
||||
setOnConnectionCallback(
|
||||
[this,
|
||||
redirectUrl](HttpRequestPtr request,
|
||||
std::shared_ptr<ConnectionState> /*connectionState*/) -> HttpResponsePtr {
|
||||
std::shared_ptr<ConnectionState> /*connectionState*/,
|
||||
std::unique_ptr<ConnectionInfo> connectionInfo) -> HttpResponsePtr {
|
||||
WebSocketHttpHeaders headers;
|
||||
headers["Server"] = userAgent();
|
||||
|
||||
// Log request
|
||||
std::stringstream ss;
|
||||
ss << request->method << " " << request->headers["User-Agent"] << " "
|
||||
ss << connectionInfo->remoteIp << ":" << connectionInfo->remotePort << " "
|
||||
<< request->method << " " << request->headers["User-Agent"] << " "
|
||||
<< request->uri;
|
||||
logInfo(ss.str());
|
||||
|
||||
|
@ -23,7 +23,9 @@ namespace ix
|
||||
{
|
||||
public:
|
||||
using OnConnectionCallback =
|
||||
std::function<HttpResponsePtr(HttpRequestPtr, std::shared_ptr<ConnectionState>)>;
|
||||
std::function<HttpResponsePtr(HttpRequestPtr,
|
||||
std::shared_ptr<ConnectionState>,
|
||||
std::unique_ptr<ConnectionInfo> connectionInfo)>;
|
||||
|
||||
HttpServer(int port = SocketServer::kDefaultPort,
|
||||
const std::string& host = SocketServer::kDefaultHost,
|
||||
@ -44,7 +46,8 @@ namespace ix
|
||||
|
||||
// Methods
|
||||
virtual void handleConnection(std::unique_ptr<Socket>,
|
||||
std::shared_ptr<ConnectionState> connectionState) final;
|
||||
std::shared_ptr<ConnectionState> connectionState,
|
||||
std::unique_ptr<ConnectionInfo> connectionInfo) final;
|
||||
virtual size_t getConnectedClientsCount() final;
|
||||
|
||||
void setDefaultConnectionCallback();
|
||||
|
@ -276,6 +276,7 @@ namespace ix
|
||||
}
|
||||
|
||||
// Accept a connection.
|
||||
// FIXME: Is this working for ipv6 ?
|
||||
struct sockaddr_in client; // client address information
|
||||
int clientFd; // socket connected to client
|
||||
socklen_t addressLen = sizeof(client);
|
||||
@ -307,6 +308,45 @@ namespace ix
|
||||
continue;
|
||||
}
|
||||
|
||||
std::unique_ptr<ConnectionInfo> connectionInfo;
|
||||
|
||||
if (_addressFamily == AF_INET)
|
||||
{
|
||||
char remoteIp[INET_ADDRSTRLEN];
|
||||
if (inet_ntop(AF_INET, &client.sin_addr, remoteIp, INET_ADDRSTRLEN) == nullptr)
|
||||
{
|
||||
int err = Socket::getErrno();
|
||||
std::stringstream ss;
|
||||
ss << "SocketServer::run() error calling inet_ntop (ipv4): " << err << ", "
|
||||
<< strerror(err);
|
||||
logError(ss.str());
|
||||
|
||||
Socket::closeSocket(clientFd);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
connectionInfo = std::make_unique<ConnectionInfo>(remoteIp, client.sin_port);
|
||||
}
|
||||
else // AF_INET6
|
||||
{
|
||||
char remoteIp[INET6_ADDRSTRLEN];
|
||||
if (inet_ntop(AF_INET6, &client.sin_addr, remoteIp, INET6_ADDRSTRLEN) == nullptr)
|
||||
{
|
||||
int err = Socket::getErrno();
|
||||
std::stringstream ss;
|
||||
ss << "SocketServer::run() error calling inet_ntop (ipv6): " << err << ", "
|
||||
<< strerror(err);
|
||||
logError(ss.str());
|
||||
|
||||
Socket::closeSocket(clientFd);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
connectionInfo = std::make_unique<ConnectionInfo>(remoteIp, client.sin_port);
|
||||
}
|
||||
|
||||
std::shared_ptr<ConnectionState> connectionState;
|
||||
if (_connectionStateFactory)
|
||||
{
|
||||
@ -342,7 +382,7 @@ namespace ix
|
||||
_connectionsThreads.push_back(std::make_pair(
|
||||
connectionState,
|
||||
std::thread(
|
||||
&SocketServer::handleConnection, this, std::move(socket), connectionState)));
|
||||
&SocketServer::handleConnection, this, std::move(socket), connectionState, std::move(connectionInfo))));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IXConnectionInfo.h"
|
||||
#include "IXConnectionState.h"
|
||||
#include "IXSocketTLSOptions.h"
|
||||
#include <atomic>
|
||||
@ -102,7 +103,8 @@ namespace ix
|
||||
ConnectionStateFactory _connectionStateFactory;
|
||||
|
||||
virtual void handleConnection(std::unique_ptr<Socket>,
|
||||
std::shared_ptr<ConnectionState> connectionState) = 0;
|
||||
std::shared_ptr<ConnectionState> connectionState,
|
||||
std::unique_ptr<ConnectionInfo> connectionInfo) = 0;
|
||||
virtual size_t getConnectedClientsCount() = 0;
|
||||
|
||||
// Returns true if all connection threads are joined
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "IXUrlParser.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
namespace
|
||||
|
@ -59,14 +59,42 @@ namespace ix
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebSocketPerMessageDeflateCompressor::endsWith(const std::string& value,
|
||||
const std::string& ending)
|
||||
template<typename T>
|
||||
bool WebSocketPerMessageDeflateCompressor::endsWithEmptyUnCompressedBlock(const T& value)
|
||||
{
|
||||
if (ending.size() > value.size()) return false;
|
||||
return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
|
||||
if (kEmptyUncompressedBlock.size() > value.size()) return false;
|
||||
auto N = value.size();
|
||||
return value[N - 1] == kEmptyUncompressedBlock[3] &&
|
||||
value[N - 2] == kEmptyUncompressedBlock[2] &&
|
||||
value[N - 3] == kEmptyUncompressedBlock[1] &&
|
||||
value[N - 4] == kEmptyUncompressedBlock[0];
|
||||
}
|
||||
|
||||
bool WebSocketPerMessageDeflateCompressor::compress(const std::string& in, std::string& out)
|
||||
{
|
||||
return compressData(in, out);
|
||||
}
|
||||
|
||||
bool WebSocketPerMessageDeflateCompressor::compress(const std::string& in,
|
||||
std::vector<uint8_t>& out)
|
||||
{
|
||||
return compressData(in, out);
|
||||
}
|
||||
|
||||
bool WebSocketPerMessageDeflateCompressor::compress(const std::vector<uint8_t>& in,
|
||||
std::string& out)
|
||||
{
|
||||
return compressData(in, out);
|
||||
}
|
||||
|
||||
bool WebSocketPerMessageDeflateCompressor::compress(const std::vector<uint8_t>& in,
|
||||
std::vector<uint8_t>& out)
|
||||
{
|
||||
return compressData(in, out);
|
||||
}
|
||||
|
||||
template<typename T, typename S>
|
||||
bool WebSocketPerMessageDeflateCompressor::compressData(const T& in, S& out)
|
||||
{
|
||||
//
|
||||
// 7.2.1. Compression
|
||||
@ -96,7 +124,8 @@ namespace ix
|
||||
// The normal buffer size should be 6 but
|
||||
// we remove the 4 octets from the tail (#4)
|
||||
uint8_t buf[2] = {0x02, 0x00};
|
||||
out.append((char*) (buf), 2);
|
||||
out.push_back(buf[0]);
|
||||
out.push_back(buf[1]);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -114,10 +143,10 @@ namespace ix
|
||||
|
||||
output = _compressBufferSize - _deflateState.avail_out;
|
||||
|
||||
out.append((char*) (_compressBuffer.get()), output);
|
||||
out.insert(out.end(), _compressBuffer.get(), _compressBuffer.get() + output);
|
||||
} while (_deflateState.avail_out == 0);
|
||||
|
||||
if (endsWith(out, kEmptyUncompressedBlock))
|
||||
if (endsWithEmptyUnCompressedBlock(out))
|
||||
{
|
||||
out.resize(out.size() - 4);
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "zlib.h"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace ix
|
||||
{
|
||||
@ -20,9 +21,15 @@ namespace ix
|
||||
|
||||
bool init(uint8_t deflateBits, bool clientNoContextTakeOver);
|
||||
bool compress(const std::string& in, std::string& out);
|
||||
bool compress(const std::string& in, std::vector<uint8_t>& out);
|
||||
bool compress(const std::vector<uint8_t>& in, std::string& out);
|
||||
bool compress(const std::vector<uint8_t>& in, std::vector<uint8_t>& out);
|
||||
|
||||
private:
|
||||
static bool endsWith(const std::string& value, const std::string& ending);
|
||||
template<typename T, typename S>
|
||||
bool compressData(const T& in, S& out);
|
||||
template<typename T>
|
||||
bool endsWithEmptyUnCompressedBlock(const T& value);
|
||||
|
||||
int _flush;
|
||||
size_t _compressBufferSize;
|
||||
|
@ -72,12 +72,13 @@ namespace ix
|
||||
}
|
||||
|
||||
void WebSocketServer::handleConnection(std::unique_ptr<Socket> socket,
|
||||
std::shared_ptr<ConnectionState> connectionState)
|
||||
std::shared_ptr<ConnectionState> connectionState,
|
||||
std::unique_ptr<ConnectionInfo> connectionInfo)
|
||||
{
|
||||
setThreadName("WebSocketServer::" + connectionState->getId());
|
||||
|
||||
auto webSocket = std::make_shared<WebSocket>();
|
||||
_onConnectionCallback(webSocket, connectionState);
|
||||
_onConnectionCallback(webSocket, connectionState, std::move(connectionInfo));
|
||||
|
||||
webSocket->disableAutomaticReconnection();
|
||||
|
||||
|
@ -19,11 +19,12 @@
|
||||
|
||||
namespace ix
|
||||
{
|
||||
class WebSocketServer final : public SocketServer
|
||||
class WebSocketServer : public SocketServer
|
||||
{
|
||||
public:
|
||||
using OnConnectionCallback =
|
||||
std::function<void(std::shared_ptr<WebSocket>, std::shared_ptr<ConnectionState>)>;
|
||||
std::function<void(std::shared_ptr<WebSocket>, std::shared_ptr<ConnectionState>,
|
||||
std::unique_ptr<ConnectionInfo> connectionInfo)>;
|
||||
|
||||
WebSocketServer(int port = SocketServer::kDefaultPort,
|
||||
const std::string& host = SocketServer::kDefaultHost,
|
||||
@ -60,7 +61,8 @@ namespace ix
|
||||
|
||||
// Methods
|
||||
virtual void handleConnection(std::unique_ptr<Socket> socket,
|
||||
std::shared_ptr<ConnectionState> connectionState) final;
|
||||
std::shared_ptr<ConnectionState> connectionState,
|
||||
std::unique_ptr<ConnectionInfo> connectionInfo);
|
||||
virtual size_t getConnectedClientsCount() final;
|
||||
};
|
||||
} // namespace ix
|
||||
|
@ -326,9 +326,10 @@ namespace ix
|
||||
return _txbuf.empty();
|
||||
}
|
||||
|
||||
template<class Iterator>
|
||||
void WebSocketTransport::appendToSendBuffer(const std::vector<uint8_t>& header,
|
||||
std::string::const_iterator begin,
|
||||
std::string::const_iterator end,
|
||||
Iterator begin,
|
||||
Iterator end,
|
||||
uint64_t message_size,
|
||||
uint8_t masking_key[4])
|
||||
{
|
||||
@ -750,8 +751,9 @@ namespace ix
|
||||
return static_cast<unsigned>(seconds);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
WebSocketSendInfo WebSocketTransport::sendData(wsheader_type::opcode_type type,
|
||||
const std::string& message,
|
||||
const T& message,
|
||||
bool compress,
|
||||
const OnProgressCallback& onProgressCallback)
|
||||
{
|
||||
@ -764,8 +766,8 @@ namespace ix
|
||||
size_t wireSize = message.size();
|
||||
bool compressionError = false;
|
||||
|
||||
std::string::const_iterator message_begin = message.begin();
|
||||
std::string::const_iterator message_end = message.end();
|
||||
auto message_begin = message.cbegin();
|
||||
auto message_end = message.cend();
|
||||
|
||||
if (compress)
|
||||
{
|
||||
@ -780,8 +782,8 @@ namespace ix
|
||||
compressionError = false;
|
||||
wireSize = _compressedMessage.size();
|
||||
|
||||
message_begin = _compressedMessage.begin();
|
||||
message_end = _compressedMessage.end();
|
||||
message_begin = _compressedMessage.cbegin();
|
||||
message_end = _compressedMessage.cend();
|
||||
}
|
||||
|
||||
{
|
||||
@ -859,10 +861,11 @@ namespace ix
|
||||
return WebSocketSendInfo(success, compressionError, payloadSize, wireSize);
|
||||
}
|
||||
|
||||
template<class Iterator>
|
||||
bool WebSocketTransport::sendFragment(wsheader_type::opcode_type type,
|
||||
bool fin,
|
||||
std::string::const_iterator message_begin,
|
||||
std::string::const_iterator message_end,
|
||||
Iterator message_begin,
|
||||
Iterator message_end,
|
||||
bool compress)
|
||||
{
|
||||
uint64_t message_size = static_cast<uint64_t>(message_end - message_begin);
|
||||
@ -1055,7 +1058,7 @@ namespace ix
|
||||
else
|
||||
{
|
||||
// no close code/reason set
|
||||
sendData(wsheader_type::CLOSE, "", compress);
|
||||
sendData(wsheader_type::CLOSE, std::string(""), compress);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -239,16 +239,15 @@ namespace ix
|
||||
bool sendOnSocket();
|
||||
bool receiveFromSocket();
|
||||
|
||||
template<class T>
|
||||
WebSocketSendInfo sendData(wsheader_type::opcode_type type,
|
||||
const std::string& message,
|
||||
const T& message,
|
||||
bool compress,
|
||||
const OnProgressCallback& onProgressCallback = nullptr);
|
||||
|
||||
bool sendFragment(wsheader_type::opcode_type type,
|
||||
bool fin,
|
||||
std::string::const_iterator begin,
|
||||
std::string::const_iterator end,
|
||||
bool compress);
|
||||
template<class Iterator>
|
||||
bool sendFragment(
|
||||
wsheader_type::opcode_type type, bool fin, Iterator begin, Iterator end, bool compress);
|
||||
|
||||
void emitMessage(MessageKind messageKind,
|
||||
const std::string& message,
|
||||
@ -256,9 +255,11 @@ namespace ix
|
||||
const OnMessageCallback& onMessageCallback);
|
||||
|
||||
bool isSendBufferEmpty() const;
|
||||
|
||||
template<class Iterator>
|
||||
void appendToSendBuffer(const std::vector<uint8_t>& header,
|
||||
std::string::const_iterator begin,
|
||||
std::string::const_iterator end,
|
||||
Iterator begin,
|
||||
Iterator end,
|
||||
uint64_t message_size,
|
||||
uint8_t masking_key[4]);
|
||||
|
||||
|
@ -6,4 +6,4 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define IX_WEBSOCKET_VERSION "9.6.2"
|
||||
#define IX_WEBSOCKET_VERSION "9.9.0"
|
||||
|
62
main.cpp
Normal file
62
main.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* main.cpp
|
||||
* Author: Benjamin Sergeant
|
||||
* Copyright (c) 2020 Machine Zone, Inc. All rights reserved.
|
||||
*
|
||||
* Super simple standalone example. See ws folder, unittest and doc/usage.md for more.
|
||||
*
|
||||
* On macOS
|
||||
* $ mkdir -p build ; cd build ; cmake -DUSE_TLS=1 .. ; make -j ; make install
|
||||
* $ clang++ --std=c++14 --stdlib=libc++ main.cpp -lixwebsocket -lz -framework Security -framework Foundation
|
||||
* $ ./a.out
|
||||
*/
|
||||
|
||||
#include <ixwebsocket/IXNetSystem.h>
|
||||
#include <ixwebsocket/IXWebSocket.h>
|
||||
#include <iostream>
|
||||
|
||||
int main()
|
||||
{
|
||||
// Required on Windows
|
||||
ix::initNetSystem();
|
||||
|
||||
// Our websocket object
|
||||
ix::WebSocket webSocket;
|
||||
|
||||
std::string url("wss://echo.websocket.org");
|
||||
webSocket.setUrl(url);
|
||||
|
||||
std::cout << "Connecting to " << url << "..." << std::endl;
|
||||
|
||||
// Setup a callback to be fired (in a background thread, watch out for race conditions !)
|
||||
// when a message or an event (open, close, error) is received
|
||||
webSocket.setOnMessageCallback([](const ix::WebSocketMessagePtr& msg)
|
||||
{
|
||||
if (msg->type == ix::WebSocketMessageType::Message)
|
||||
{
|
||||
std::cout << "received message: " << msg->str << std::endl;
|
||||
}
|
||||
else if (msg->type == ix::WebSocketMessageType::Open)
|
||||
{
|
||||
std::cout << "Connection established" << std::endl;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Now that our callback is setup, we can start our background thread and receive messages
|
||||
webSocket.start();
|
||||
|
||||
// Send a message to the server (default to TEXT mode)
|
||||
webSocket.send("hello world");
|
||||
|
||||
while (true)
|
||||
{
|
||||
std::string text;
|
||||
std::cout << "> " << std::flush;
|
||||
std::getline(std::cin, text);
|
||||
|
||||
webSocket.send(text);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
91
makefile
91
makefile
@ -19,26 +19,28 @@ install: brew
|
||||
#
|
||||
# Release, Debug, MinSizeRel, RelWithDebInfo are the build types
|
||||
#
|
||||
# Default rule does not use python as that requires first time users to have Python3 installed
|
||||
#
|
||||
brew:
|
||||
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 -DUSE_TEST=1 .. ; ninja install)
|
||||
|
||||
# Docker default target. We've add problem with OpenSSL and TLS 1.3 (on the
|
||||
# Docker default target. We've had problems with OpenSSL and TLS 1.3 (on the
|
||||
# server side ?) and I can't work-around it easily, so we're using mbedtls on
|
||||
# Linux for the SSL backend, which works great.
|
||||
ws_mbedtls_install:
|
||||
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_BUILD_TYPE=MinSizeRel -DUSE_TLS=1 -DUSE_WS=1 -DUSE_MBED_TLS=1 .. ; ninja install)
|
||||
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_BUILD_TYPE=MinSizeRel -DUSE_PYTHON=1 -DUSE_TLS=1 -DUSE_WS=1 -DUSE_MBED_TLS=1 .. ; ninja install)
|
||||
|
||||
ws:
|
||||
mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 .. ; make -j 4)
|
||||
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DUSE_PYTHON=1 -DUSE_TLS=1 -DUSE_WS=1 .. && ninja install)
|
||||
|
||||
ws_install:
|
||||
mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=MinSizeRel -DUSE_TLS=1 -DUSE_WS=1 .. ; make -j 4 install)
|
||||
mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=MinSizeRel -DUSE_PYTHON=1 -DUSE_TLS=1 -DUSE_WS=1 .. && make -j 4 install)
|
||||
|
||||
ws_openssl:
|
||||
mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 -DUSE_OPEN_SSL=1 .. ; make -j 4)
|
||||
mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=Debug -DUSE_PYTHON=1 -DUSE_TLS=1 -DUSE_WS=1 -DUSE_OPEN_SSL=1 .. ; make -j 4)
|
||||
|
||||
ws_mbedtls:
|
||||
mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 -DUSE_MBED_TLS=1 .. ; make -j 4)
|
||||
mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=Debug -DUSE_PYTHON=1 -DUSE_TLS=1 -DUSE_WS=1 -DUSE_MBED_TLS=1 .. ; make -j 4)
|
||||
|
||||
ws_no_ssl:
|
||||
mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=Debug -DUSE_WS=1 .. ; make -j 4)
|
||||
@ -102,21 +104,23 @@ test_server:
|
||||
# env TEST=Websocket_server make test
|
||||
# env TEST=Websocket_chat make test
|
||||
# env TEST=heartbeat make test
|
||||
test:
|
||||
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 -DUSE_TEST=1 .. ; ninja install)
|
||||
build_test:
|
||||
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_TEST=1 .. ; ninja install)
|
||||
|
||||
test: build_test
|
||||
(cd test ; python2.7 run.py -r)
|
||||
|
||||
test_make:
|
||||
mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_WS=1 -DUSE_TEST=1 .. ; make -j 4)
|
||||
mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=Debug -DUSE_PYTHON=1 -DUSE_TLS=1 -DUSE_WS=1 -DUSE_TEST=1 .. ; make -j 4)
|
||||
(cd test ; python2.7 run.py -r)
|
||||
|
||||
test_tsan:
|
||||
mkdir -p build && (cd build && cmake -GXcode -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_TEST=1 .. && xcodebuild -project ixwebsocket.xcodeproj -target ixwebsocket_unittest -enableThreadSanitizer YES)
|
||||
mkdir -p build && (cd build && cmake -GXcode -DCMAKE_BUILD_TYPE=Debug -DUSE_PYTHON=1 -DUSE_TLS=1 -DUSE_TEST=1 .. && xcodebuild -project ixwebsocket.xcodeproj -target ixwebsocket_unittest -enableThreadSanitizer YES)
|
||||
(cd build/test ; ln -sf Debug/ixwebsocket_unittest)
|
||||
(cd test ; python2.7 run.py -r)
|
||||
|
||||
test_ubsan:
|
||||
mkdir -p build && (cd build && cmake -GXcode -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_TEST=1 .. && xcodebuild -project ixwebsocket.xcodeproj -target ixwebsocket_unittest -enableUndefinedBehaviorSanitizer YES)
|
||||
mkdir -p build && (cd build && cmake -GXcode -DCMAKE_BUILD_TYPE=Debug -DUSE_PYTHON=1 -DUSE_TLS=1 -DUSE_TEST=1 .. && xcodebuild -project ixwebsocket.xcodeproj -target ixwebsocket_unittest -enableUndefinedBehaviorSanitizer YES)
|
||||
(cd build/test ; ln -sf Debug/ixwebsocket_unittest)
|
||||
(cd test ; python2.7 run.py -r)
|
||||
|
||||
@ -124,37 +128,37 @@ test_asan: build_test_asan
|
||||
(cd test ; python2.7 run.py -r)
|
||||
|
||||
build_test_asan:
|
||||
mkdir -p build && (cd build && cmake -GXcode -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_TEST=1 .. && xcodebuild -project ixwebsocket.xcodeproj -target ixwebsocket_unittest -enableAddressSanitizer YES)
|
||||
mkdir -p build && (cd build && cmake -GXcode -DCMAKE_BUILD_TYPE=Debug -DUSE_PYTHON=1 -DUSE_TLS=1 -DUSE_TEST=1 .. && xcodebuild -project ixwebsocket.xcodeproj -target ixwebsocket_unittest -enableAddressSanitizer YES)
|
||||
(cd build/test ; ln -sf Debug/ixwebsocket_unittest)
|
||||
|
||||
test_tsan_openssl:
|
||||
mkdir -p build && (cd build && cmake -GXcode -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_TEST=1 -DUSE_OPEN_SSL=1 .. && xcodebuild -project ixwebsocket.xcodeproj -target ixwebsocket_unittest -enableThreadSanitizer YES)
|
||||
mkdir -p build && (cd build && cmake -GXcode -DCMAKE_BUILD_TYPE=Debug -DUSE_PYTHON=1 -DUSE_TLS=1 -DUSE_TEST=1 -DUSE_OPEN_SSL=1 .. && xcodebuild -project ixwebsocket.xcodeproj -target ixwebsocket_unittest -enableThreadSanitizer YES)
|
||||
(cd build/test ; ln -sf Debug/ixwebsocket_unittest)
|
||||
(cd test ; python2.7 run.py -r)
|
||||
|
||||
test_ubsan_openssl:
|
||||
mkdir -p build && (cd build && cmake -GXcode -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_TEST=1 -DUSE_OPEN_SSL=1 .. && xcodebuild -project ixwebsocket.xcodeproj -target ixwebsocket_unittest -enableUndefinedBehaviorSanitizer YES)
|
||||
mkdir -p build && (cd build && cmake -GXcode -DCMAKE_BUILD_TYPE=Debug -DUSE_PYTHON=1 -DUSE_TLS=1 -DUSE_TEST=1 -DUSE_OPEN_SSL=1 .. && xcodebuild -project ixwebsocket.xcodeproj -target ixwebsocket_unittest -enableUndefinedBehaviorSanitizer YES)
|
||||
(cd build/test ; ln -sf Debug/ixwebsocket_unittest)
|
||||
(cd test ; python2.7 run.py -r)
|
||||
|
||||
test_tsan_openssl_release:
|
||||
mkdir -p build && (cd build && cmake -GXcode -DCMAKE_BUILD_TYPE=Release -DUSE_TLS=1 -DUSE_TEST=1 -DUSE_OPEN_SSL=1 .. && xcodebuild -project ixwebsocket.xcodeproj -configuration Release -target ixwebsocket_unittest -enableThreadSanitizer YES)
|
||||
mkdir -p build && (cd build && cmake -GXcode -DCMAKE_BUILD_TYPE=Release -DUSE_PYTHON=1 -DUSE_TLS=1 -DUSE_TEST=1 -DUSE_OPEN_SSL=1 .. && xcodebuild -project ixwebsocket.xcodeproj -configuration Release -target ixwebsocket_unittest -enableThreadSanitizer YES)
|
||||
(cd build/test ; ln -sf Release/ixwebsocket_unittest)
|
||||
(cd test ; python2.7 run.py -r)
|
||||
|
||||
test_tsan_mbedtls:
|
||||
mkdir -p build && (cd build && cmake -GXcode -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_TEST=1 -DUSE_MBED_TLS=1 .. && xcodebuild -project ixwebsocket.xcodeproj -target ixwebsocket_unittest -enableThreadSanitizer YES)
|
||||
mkdir -p build && (cd build && cmake -GXcode -DCMAKE_BUILD_TYPE=Debug -DUSE_PYTHON=1 -DUSE_TLS=1 -DUSE_TEST=1 -DUSE_MBED_TLS=1 .. && xcodebuild -project ixwebsocket.xcodeproj -target ixwebsocket_unittest -enableThreadSanitizer YES)
|
||||
(cd build/test ; ln -sf Debug/ixwebsocket_unittest)
|
||||
(cd test ; python2.7 run.py -r)
|
||||
|
||||
build_test_openssl:
|
||||
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_OPEN_SSL=1 -DUSE_TEST=1 .. ; ninja install)
|
||||
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DUSE_PYTHON=1 -DUSE_TLS=1 -DUSE_OPEN_SSL=1 -DUSE_TEST=1 .. ; ninja install)
|
||||
|
||||
test_openssl: build_test_openssl
|
||||
(cd test ; python2.7 run.py -r)
|
||||
|
||||
build_test_mbedtls:
|
||||
mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_MBED_TLS=1 -DUSE_TEST=1 .. ; make -j 4)
|
||||
mkdir -p build && (cd build ; cmake -DCMAKE_BUILD_TYPE=Debug -DUSE_PYTHON=1 -DUSE_TLS=1 -DUSE_MBED_TLS=1 -DUSE_TEST=1 .. ; make -j 4)
|
||||
|
||||
test_mbedtls: build_test_mbedtls
|
||||
(cd test ; python2.7 run.py -r)
|
||||
@ -169,6 +173,53 @@ ws_test: ws
|
||||
autobahn_report:
|
||||
cp -rvf ~/sandbox/reports/clients/* ../bsergean.github.io/IXWebSocket/autobahn/
|
||||
|
||||
httpd:
|
||||
clang++ --std=c++14 --stdlib=libc++ httpd.cpp \
|
||||
ixwebsocket/IXSelectInterruptFactory.cpp \
|
||||
ixwebsocket/IXCancellationRequest.cpp \
|
||||
ixwebsocket/IXSocketTLSOptions.cpp \
|
||||
ixwebsocket/IXUserAgent.cpp \
|
||||
ixwebsocket/IXDNSLookup.cpp \
|
||||
ixwebsocket/IXBench.cpp \
|
||||
ixwebsocket/IXWebSocketHttpHeaders.cpp \
|
||||
ixwebsocket/IXSelectInterruptPipe.cpp \
|
||||
ixwebsocket/IXHttp.cpp \
|
||||
ixwebsocket/IXSocketConnect.cpp \
|
||||
ixwebsocket/IXSocket.cpp \
|
||||
ixwebsocket/IXSocketServer.cpp \
|
||||
ixwebsocket/IXNetSystem.cpp \
|
||||
ixwebsocket/IXHttpServer.cpp \
|
||||
ixwebsocket/IXSocketFactory.cpp \
|
||||
ixwebsocket/IXConnectionState.cpp \
|
||||
ixwebsocket/IXUrlParser.cpp \
|
||||
ixwebsocket/IXSelectInterrupt.cpp \
|
||||
ixwebsocket/apple/IXSetThreadName_apple.cpp \
|
||||
-lz
|
||||
|
||||
httpd_linux:
|
||||
g++ --std=c++11 -o ixhttpd httpd.cpp -Iixwebsocket \
|
||||
ixwebsocket/IXSelectInterruptFactory.cpp \
|
||||
ixwebsocket/IXCancellationRequest.cpp \
|
||||
ixwebsocket/IXSocketTLSOptions.cpp \
|
||||
ixwebsocket/IXUserAgent.cpp \
|
||||
ixwebsocket/IXDNSLookup.cpp \
|
||||
ixwebsocket/IXBench.cpp \
|
||||
ixwebsocket/IXWebSocketHttpHeaders.cpp \
|
||||
ixwebsocket/IXSelectInterruptPipe.cpp \
|
||||
ixwebsocket/IXHttp.cpp \
|
||||
ixwebsocket/IXSocketConnect.cpp \
|
||||
ixwebsocket/IXSocket.cpp \
|
||||
ixwebsocket/IXSocketServer.cpp \
|
||||
ixwebsocket/IXNetSystem.cpp \
|
||||
ixwebsocket/IXHttpServer.cpp \
|
||||
ixwebsocket/IXSocketFactory.cpp \
|
||||
ixwebsocket/IXConnectionState.cpp \
|
||||
ixwebsocket/IXUrlParser.cpp \
|
||||
ixwebsocket/IXSelectInterrupt.cpp \
|
||||
ixwebsocket/linux/IXSetThreadName_linux.cpp \
|
||||
-lz -lpthread
|
||||
cp -f ixhttpd /usr/local/bin
|
||||
|
||||
# For the fork that is configured with appveyor
|
||||
rebase_upstream:
|
||||
git fetch upstream
|
||||
@ -176,6 +227,7 @@ rebase_upstream:
|
||||
git reset --hard upstream/master
|
||||
git push origin master --force
|
||||
|
||||
# Legacy target
|
||||
install_cmake_for_linux:
|
||||
mkdir -p /tmp/cmake
|
||||
(cd /tmp/cmake ; curl -L -O https://github.com/Kitware/CMake/releases/download/v3.14.0/cmake-3.14.0-Linux-x86_64.tar.gz ; tar zxf cmake-3.14.0-Linux-x86_64.tar.gz)
|
||||
@ -186,6 +238,9 @@ install_cmake_for_linux:
|
||||
doc:
|
||||
mkdocs gh-deploy
|
||||
|
||||
change:
|
||||
vim ixwebsocket/IXWebSocketVersion.h docs/CHANGELOG.md
|
||||
|
||||
.PHONY: test
|
||||
.PHONY: build
|
||||
.PHONY: ws
|
||||
|
@ -42,6 +42,7 @@ set (SOURCES
|
||||
|
||||
IXSocketTest.cpp
|
||||
IXSocketConnectTest.cpp
|
||||
# IXWebSocketLeakTest.cpp # commented until we have a fix for #224
|
||||
IXWebSocketServerTest.cpp
|
||||
IXWebSocketTestConnectionDisconnection.cpp
|
||||
IXUrlParserTest.cpp
|
||||
@ -55,6 +56,8 @@ set (SOURCES
|
||||
IXSentryClientTest.cpp
|
||||
IXWebSocketChatTest.cpp
|
||||
IXWebSocketBroadcastTest.cpp
|
||||
IXWebSocketPerMessageDeflateCompressorTest.cpp
|
||||
IXStreamSqlTest.cpp
|
||||
)
|
||||
|
||||
# Some unittest don't work on windows yet
|
||||
@ -91,15 +94,30 @@ if (JSONCPP_FOUND)
|
||||
target_link_libraries(ixwebsocket_unittest ${JSONCPP_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if (USE_PYTHON)
|
||||
find_package(Python COMPONENTS Development)
|
||||
if (NOT Python_FOUND)
|
||||
message(FATAL_ERROR "Python3 not found")
|
||||
endif()
|
||||
message("Python_FOUND:${Python_FOUND}")
|
||||
message("Python_VERSION:${Python_VERSION}")
|
||||
message("Python_Development_FOUND:${Python_Development_FOUND}")
|
||||
message("Python_LIBRARIES:${Python_LIBRARIES}")
|
||||
endif()
|
||||
|
||||
# library with the most dependencies come first
|
||||
target_link_libraries(ixwebsocket_unittest ixbots)
|
||||
target_link_libraries(ixwebsocket_unittest ixsnake)
|
||||
target_link_libraries(ixwebsocket_unittest ixcobra)
|
||||
target_link_libraries(ixwebsocket_unittest ixsentry)
|
||||
target_link_libraries(ixwebsocket_unittest ixredis)
|
||||
target_link_libraries(ixwebsocket_unittest ixwebsocket)
|
||||
target_link_libraries(ixwebsocket_unittest ixcrypto)
|
||||
target_link_libraries(ixwebsocket_unittest ixcore)
|
||||
|
||||
target_link_libraries(ixwebsocket_unittest spdlog)
|
||||
if (USE_PYTHON)
|
||||
target_link_libraries(ixwebsocket_unittest ${Python_LIBRARIES})
|
||||
endif()
|
||||
|
||||
install(TARGETS ixwebsocket_unittest DESTINATION bin)
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include <iostream>
|
||||
#include <ixcobra/IXCobraConnection.h>
|
||||
#include <ixcrypto/IXUuid.h>
|
||||
#include <ixsnake/IXRedisServer.h>
|
||||
#include <ixredis/IXRedisServer.h>
|
||||
#include <ixsnake/IXSnakeServer.h>
|
||||
|
||||
using namespace ix;
|
||||
@ -125,10 +125,12 @@ namespace
|
||||
{
|
||||
std::string filter;
|
||||
std::string position("$");
|
||||
int batchSize = 1;
|
||||
|
||||
_conn.subscribe(channel,
|
||||
filter,
|
||||
position,
|
||||
batchSize,
|
||||
[this](const Json::Value& msg, const std::string& /*position*/) {
|
||||
spdlog::info("receive {}", msg.toStyledString());
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include <iostream>
|
||||
#include <ixcobra/IXCobraMetricsPublisher.h>
|
||||
#include <ixcrypto/IXUuid.h>
|
||||
#include <ixsnake/IXRedisServer.h>
|
||||
#include <ixredis/IXRedisServer.h>
|
||||
#include <ixsnake/IXSnakeServer.h>
|
||||
#include <set>
|
||||
|
||||
@ -76,10 +76,12 @@ namespace
|
||||
log("Subscriber authenticated");
|
||||
std::string filter;
|
||||
std::string position("$");
|
||||
int batchSize = 1;
|
||||
|
||||
conn.subscribe(channel,
|
||||
filter,
|
||||
position,
|
||||
batchSize,
|
||||
[](const Json::Value& msg, const std::string& /*position*/) {
|
||||
log(msg.toStyledString());
|
||||
|
||||
|
@ -12,8 +12,8 @@
|
||||
#include <ixcobra/IXCobraConnection.h>
|
||||
#include <ixcobra/IXCobraMetricsPublisher.h>
|
||||
#include <ixcrypto/IXUuid.h>
|
||||
#include <ixredis/IXRedisServer.h>
|
||||
#include <ixsentry/IXSentryClient.h>
|
||||
#include <ixsnake/IXRedisServer.h>
|
||||
#include <ixsnake/IXSnakeServer.h>
|
||||
#include <ixwebsocket/IXHttpServer.h>
|
||||
#include <ixwebsocket/IXUserAgent.h>
|
||||
@ -95,13 +95,15 @@ TEST_CASE("Cobra_to_sentry_bot", "[cobra_bots]")
|
||||
|
||||
sentryServer.setOnConnectionCallback(
|
||||
[](HttpRequestPtr request,
|
||||
std::shared_ptr<ConnectionState> /*connectionState*/) -> HttpResponsePtr {
|
||||
std::shared_ptr<ConnectionState> /*connectionState*/,
|
||||
std::unique_ptr<ConnectionInfo> connectionInfo) -> HttpResponsePtr {
|
||||
WebSocketHttpHeaders headers;
|
||||
headers["Server"] = userAgent();
|
||||
|
||||
// Log request
|
||||
std::stringstream ss;
|
||||
ss << request->method << " " << request->headers["User-Agent"] << " "
|
||||
ss << connectionInfo->remoteIp << ":" << connectionInfo->remotePort << " "
|
||||
<< request->method << " " << request->headers["User-Agent"] << " "
|
||||
<< request->uri;
|
||||
|
||||
if (request->method == "POST")
|
||||
|
@ -12,8 +12,8 @@
|
||||
#include <ixcobra/IXCobraConnection.h>
|
||||
#include <ixcobra/IXCobraMetricsPublisher.h>
|
||||
#include <ixcrypto/IXUuid.h>
|
||||
#include <ixredis/IXRedisServer.h>
|
||||
#include <ixsentry/IXSentryClient.h>
|
||||
#include <ixsnake/IXRedisServer.h>
|
||||
#include <ixsnake/IXSnakeServer.h>
|
||||
#include <ixwebsocket/IXHttpServer.h>
|
||||
#include <ixwebsocket/IXUserAgent.h>
|
||||
|
@ -12,8 +12,8 @@
|
||||
#include <ixcobra/IXCobraConnection.h>
|
||||
#include <ixcobra/IXCobraMetricsPublisher.h>
|
||||
#include <ixcrypto/IXUuid.h>
|
||||
#include <ixredis/IXRedisServer.h>
|
||||
#include <ixsentry/IXSentryClient.h>
|
||||
#include <ixsnake/IXRedisServer.h>
|
||||
#include <ixsnake/IXSnakeServer.h>
|
||||
#include <ixwebsocket/IXHttpServer.h>
|
||||
#include <ixwebsocket/IXUserAgent.h>
|
||||
@ -92,6 +92,9 @@ TEST_CASE("Cobra_to_stdout_bot", "[cobra_bots]")
|
||||
cobraBotConfig.enableHeartbeat = false;
|
||||
bool quiet = false;
|
||||
|
||||
cobraBotConfig.filter =
|
||||
std::string("select * from `") + channel + "` where id = 'sms_metric_A_id'";
|
||||
|
||||
// We could try to capture the output ... not sure how.
|
||||
bool fluentd = true;
|
||||
|
||||
|
@ -67,7 +67,8 @@ TEST_CASE("http server", "[httpd]")
|
||||
|
||||
TEST_CASE("http server redirection", "[httpd_redirect]")
|
||||
{
|
||||
SECTION("Connect to a local HTTP server, with redirection enabled")
|
||||
SECTION(
|
||||
"Connect to a local HTTP server, with redirection enabled, but we do not follow redirects")
|
||||
{
|
||||
int port = getFreePort();
|
||||
ix::HttpServer server(port, "127.0.0.1");
|
||||
@ -117,4 +118,54 @@ TEST_CASE("http server redirection", "[httpd_redirect]")
|
||||
|
||||
server.stop();
|
||||
}
|
||||
|
||||
SECTION("Connect to a local HTTP server, with redirection enabled, but we do follow redirects")
|
||||
{
|
||||
int port = getFreePort();
|
||||
ix::HttpServer server(port, "127.0.0.1");
|
||||
server.makeRedirectServer("http://www.google.com");
|
||||
|
||||
auto res = server.listen();
|
||||
REQUIRE(res.first);
|
||||
server.start();
|
||||
|
||||
HttpClient httpClient;
|
||||
WebSocketHttpHeaders headers;
|
||||
|
||||
std::string url("http://127.0.0.1:");
|
||||
url += std::to_string(port);
|
||||
url += "/data/foo.txt";
|
||||
auto args = httpClient.createRequest(url);
|
||||
|
||||
args->extraHeaders = headers;
|
||||
args->connectTimeout = 60;
|
||||
args->transferTimeout = 60;
|
||||
args->followRedirects = true;
|
||||
args->maxRedirects = 10;
|
||||
args->verbose = true;
|
||||
args->compress = true;
|
||||
args->logger = [](const std::string& msg) { std::cout << msg; };
|
||||
args->onProgressCallback = [](int current, int total) -> bool {
|
||||
std::cerr << "\r"
|
||||
<< "Downloaded " << current << " bytes out of " << total;
|
||||
return true;
|
||||
};
|
||||
|
||||
auto response = httpClient.get(url, args);
|
||||
|
||||
for (auto it : response->headers)
|
||||
{
|
||||
std::cerr << it.first << ": " << it.second << std::endl;
|
||||
}
|
||||
|
||||
std::cerr << "Upload size: " << response->uploadSize << std::endl;
|
||||
std::cerr << "Download size: " << response->downloadSize << std::endl;
|
||||
std::cerr << "Status: " << response->statusCode << std::endl;
|
||||
std::cerr << "Error message: " << response->errorMsg << std::endl;
|
||||
|
||||
REQUIRE(response->errorCode == HttpErrorCode::Ok);
|
||||
REQUIRE(response->statusCode == 200);
|
||||
|
||||
server.stop();
|
||||
}
|
||||
}
|
||||
|
42
test/IXStreamSqlTest.cpp
Normal file
42
test/IXStreamSqlTest.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* IXStreamSqlTest.cpp
|
||||
* Author: Benjamin Sergeant
|
||||
* Copyright (c) 2020 Machine Zone. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "IXTest.h"
|
||||
#include "catch.hpp"
|
||||
#include <iostream>
|
||||
#include <ixsnake/IXStreamSql.h>
|
||||
#include <string.h>
|
||||
|
||||
using namespace ix;
|
||||
|
||||
namespace ix
|
||||
{
|
||||
TEST_CASE("stream_sql", "[streamsql]")
|
||||
{
|
||||
SECTION("expression A")
|
||||
{
|
||||
snake::StreamSql streamSql(
|
||||
"select * from subscriber_republished_v1_neo where session LIKE '%123456%'");
|
||||
|
||||
nlohmann::json msg = {{"session", "123456"}, {"id", "foo_id"}, {"timestamp", 12}};
|
||||
|
||||
CHECK(streamSql.match(msg));
|
||||
}
|
||||
|
||||
SECTION("expression A")
|
||||
{
|
||||
snake::StreamSql streamSql("select * from `subscriber_republished_v1_neo` where "
|
||||
"session = '30091320ed8d4e50b758f8409b83bed7'");
|
||||
|
||||
nlohmann::json msg = {{"session", "30091320ed8d4e50b758f8409b83bed7"},
|
||||
{"id", "foo_id"},
|
||||
{"timestamp", 12}};
|
||||
|
||||
CHECK(streamSql.match(msg));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ix
|
@ -85,12 +85,15 @@ namespace ix
|
||||
bool startWebSocketEchoServer(ix::WebSocketServer& server)
|
||||
{
|
||||
server.setOnConnectionCallback([&server](std::shared_ptr<ix::WebSocket> webSocket,
|
||||
std::shared_ptr<ConnectionState> connectionState) {
|
||||
std::shared_ptr<ConnectionState> connectionState,
|
||||
std::unique_ptr<ConnectionInfo> connectionInfo) {
|
||||
auto remoteIp = connectionInfo->remoteIp;
|
||||
webSocket->setOnMessageCallback(
|
||||
[webSocket, connectionState, &server](const ix::WebSocketMessagePtr& msg) {
|
||||
[webSocket, connectionState, remoteIp, &server](const ix::WebSocketMessagePtr& msg) {
|
||||
if (msg->type == ix::WebSocketMessageType::Open)
|
||||
{
|
||||
TLogger() << "New connection";
|
||||
TLogger() << "Remote ip: " << remoteIp;
|
||||
TLogger() << "Uri: " << msg->openInfo.uri;
|
||||
TLogger() << "Headers:";
|
||||
for (auto it : msg->openInfo.headers)
|
||||
|
@ -191,13 +191,16 @@ namespace
|
||||
|
||||
server.setOnConnectionCallback([&server, &connectionId](
|
||||
std::shared_ptr<ix::WebSocket> webSocket,
|
||||
std::shared_ptr<ConnectionState> connectionState) {
|
||||
webSocket->setOnMessageCallback([webSocket, connectionState, &connectionId, &server](
|
||||
std::shared_ptr<ConnectionState> connectionState,
|
||||
std::unique_ptr<ConnectionInfo> connectionInfo) {
|
||||
auto remoteIp = connectionInfo->remoteIp;
|
||||
webSocket->setOnMessageCallback([webSocket, connectionState, remoteIp, &connectionId, &server](
|
||||
const ix::WebSocketMessagePtr& msg) {
|
||||
if (msg->type == ix::WebSocketMessageType::Open)
|
||||
{
|
||||
TLogger() << "New connection";
|
||||
connectionState->computeId();
|
||||
TLogger() << "remote ip: " << remoteIp;
|
||||
TLogger() << "id: " << connectionState->getId();
|
||||
TLogger() << "Uri: " << msg->openInfo.uri;
|
||||
TLogger() << "Headers:";
|
||||
|
@ -194,12 +194,16 @@ namespace
|
||||
bool startServer(ix::WebSocketServer& server)
|
||||
{
|
||||
server.setOnConnectionCallback([&server](std::shared_ptr<ix::WebSocket> webSocket,
|
||||
std::shared_ptr<ConnectionState> connectionState) {
|
||||
std::shared_ptr<ConnectionState> connectionState,
|
||||
|
||||
std::unique_ptr<ConnectionInfo> connectionInfo) {
|
||||
auto remoteIp = connectionInfo->remoteIp;
|
||||
webSocket->setOnMessageCallback(
|
||||
[webSocket, connectionState, &server](const ix::WebSocketMessagePtr& msg) {
|
||||
[webSocket, connectionState, remoteIp, &server](const ix::WebSocketMessagePtr& msg) {
|
||||
if (msg->type == ix::WebSocketMessageType::Open)
|
||||
{
|
||||
TLogger() << "New connection";
|
||||
TLogger() << "remote ip: " << remoteIp;
|
||||
TLogger() << "id: " << connectionState->getId();
|
||||
TLogger() << "Uri: " << msg->openInfo.uri;
|
||||
TLogger() << "Headers:";
|
||||
|
@ -171,9 +171,12 @@ namespace
|
||||
server.setOnConnectionCallback(
|
||||
[&receivedCloseCode, &receivedCloseReason, &receivedCloseRemote, &mutexWrite](
|
||||
std::shared_ptr<ix::WebSocket> webSocket,
|
||||
std::shared_ptr<ConnectionState> connectionState) {
|
||||
std::shared_ptr<ConnectionState> connectionState,
|
||||
std::unique_ptr<ConnectionInfo> connectionInfo) {
|
||||
auto remoteIp = connectionInfo->remoteIp;
|
||||
webSocket->setOnMessageCallback([webSocket,
|
||||
connectionState,
|
||||
remoteIp,
|
||||
&receivedCloseCode,
|
||||
&receivedCloseReason,
|
||||
&receivedCloseRemote,
|
||||
@ -181,6 +184,7 @@ namespace
|
||||
if (msg->type == ix::WebSocketMessageType::Open)
|
||||
{
|
||||
TLogger() << "New server connection";
|
||||
TLogger() << "remote ip: " << remoteIp;
|
||||
TLogger() << "id: " << connectionState->getId();
|
||||
TLogger() << "Uri: " << msg->openInfo.uri;
|
||||
TLogger() << "Headers:";
|
||||
|
182
test/IXWebSocketLeakTest.cpp
Normal file
182
test/IXWebSocketLeakTest.cpp
Normal file
@ -0,0 +1,182 @@
|
||||
/*
|
||||
* IXWebSocketServer.cpp
|
||||
* Author: Benjamin Sergeant, @marcelkauf
|
||||
* Copyright (c) 2020 Machine Zone, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "IXTest.h"
|
||||
|
||||
#include "catch.hpp"
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
#include <ixwebsocket/IXWebSocket.h>
|
||||
#include <ixwebsocket/IXWebSocketServer.h>
|
||||
|
||||
using namespace ix;
|
||||
|
||||
namespace
|
||||
{
|
||||
class WebSocketClient
|
||||
{
|
||||
public:
|
||||
WebSocketClient(int port);
|
||||
void start();
|
||||
void stop();
|
||||
bool isReady() const;
|
||||
bool hasConnectionError() const;
|
||||
|
||||
private:
|
||||
ix::WebSocket _webSocket;
|
||||
int _port;
|
||||
std::atomic<bool> _connectionError;
|
||||
};
|
||||
|
||||
WebSocketClient::WebSocketClient(int port)
|
||||
: _port(port)
|
||||
, _connectionError(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool WebSocketClient::hasConnectionError() const
|
||||
{
|
||||
return _connectionError;
|
||||
}
|
||||
|
||||
bool WebSocketClient::isReady() const
|
||||
{
|
||||
return _webSocket.getReadyState() == ix::ReadyState::Open;
|
||||
}
|
||||
|
||||
void WebSocketClient::stop()
|
||||
{
|
||||
_webSocket.stop();
|
||||
}
|
||||
|
||||
void WebSocketClient::start()
|
||||
{
|
||||
std::string url;
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "ws://localhost:" << _port << "/";
|
||||
|
||||
url = ss.str();
|
||||
}
|
||||
|
||||
_webSocket.setUrl(url);
|
||||
_webSocket.disableAutomaticReconnection();
|
||||
|
||||
std::stringstream ss;
|
||||
log(std::string("Connecting to url: ") + url);
|
||||
|
||||
_webSocket.setOnMessageCallback([this](const ix::WebSocketMessagePtr& msg)
|
||||
{
|
||||
std::stringstream ss;
|
||||
if (msg->type == ix::WebSocketMessageType::Open)
|
||||
{
|
||||
log("client connected");
|
||||
}
|
||||
else if (msg->type == ix::WebSocketMessageType::Close)
|
||||
{
|
||||
log("client disconnected");
|
||||
}
|
||||
else if (msg->type == ix::WebSocketMessageType::Error)
|
||||
{
|
||||
_connectionError = true;
|
||||
log("error");
|
||||
}
|
||||
else if (msg->type == ix::WebSocketMessageType::Pong)
|
||||
{
|
||||
log("pong");
|
||||
}
|
||||
else if (msg->type == ix::WebSocketMessageType::Ping)
|
||||
{
|
||||
log("ping");
|
||||
}
|
||||
else if (msg->type == ix::WebSocketMessageType::Message)
|
||||
{
|
||||
log("message");
|
||||
}
|
||||
else
|
||||
{
|
||||
log("invalid type");
|
||||
}
|
||||
});
|
||||
|
||||
_webSocket.start();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TEST_CASE("Websocket leak test")
|
||||
{
|
||||
SECTION("Websocket destructor is called when closing the connection.")
|
||||
{
|
||||
// stores the server websocket in order to check the use_count
|
||||
std::shared_ptr<WebSocket> webSocketPtr;
|
||||
|
||||
{
|
||||
int port = getFreePort();
|
||||
WebSocketServer server(port);
|
||||
|
||||
server.setOnConnectionCallback([&webSocketPtr](std::shared_ptr<ix::WebSocket> webSocket,
|
||||
std::shared_ptr<ConnectionState> connectionState,
|
||||
std::unique_ptr<ConnectionInfo> connectionInfo)
|
||||
{
|
||||
// original ptr in WebSocketServer::handleConnection and the callback argument
|
||||
REQUIRE(webSocket.use_count() == 2);
|
||||
webSocket->setOnMessageCallback([&webSocketPtr, webSocket, connectionState](const ix::WebSocketMessagePtr& msg)
|
||||
{
|
||||
if (msg->type == ix::WebSocketMessageType::Open)
|
||||
{
|
||||
log(std::string("New connection id: ") + connectionState->getId());
|
||||
// original ptr in WebSocketServer::handleConnection, captured ptr of this callback, and ptr in WebSocketServer::_clients
|
||||
REQUIRE(webSocket.use_count() == 3);
|
||||
webSocketPtr = std::shared_ptr<WebSocket>(webSocket);
|
||||
REQUIRE(webSocket.use_count() == 4);
|
||||
}
|
||||
else if (msg->type == ix::WebSocketMessageType::Close)
|
||||
{
|
||||
log(std::string("Client closed connection id: ") + connectionState->getId());
|
||||
}
|
||||
else
|
||||
{
|
||||
log(std::string(msg->str));
|
||||
}
|
||||
});
|
||||
// original ptr in WebSocketServer::handleConnection, argument of this callback, and captured ptr in websocket callback
|
||||
REQUIRE(webSocket.use_count() == 3);
|
||||
});
|
||||
|
||||
server.listen();
|
||||
server.start();
|
||||
|
||||
WebSocketClient webSocketClient(port);
|
||||
webSocketClient.start();
|
||||
|
||||
while (true)
|
||||
{
|
||||
REQUIRE(!webSocketClient.hasConnectionError());
|
||||
if (webSocketClient.isReady()) break;
|
||||
ix::msleep(10);
|
||||
}
|
||||
|
||||
REQUIRE(server.getClients().size() == 1);
|
||||
// same value as in Open-handler above
|
||||
REQUIRE(webSocketPtr.use_count() == 4);
|
||||
|
||||
ix::msleep(500);
|
||||
webSocketClient.stop();
|
||||
ix::msleep(500);
|
||||
REQUIRE(server.getClients().size() == 0);
|
||||
|
||||
// websocket should only be referenced by webSocketPtr but is still used by the websocket callback
|
||||
REQUIRE(webSocketPtr.use_count() == 1);
|
||||
webSocketPtr->setOnMessageCallback(nullptr);
|
||||
// websocket should only be referenced by webSocketPtr
|
||||
REQUIRE(webSocketPtr.use_count() == 1);
|
||||
server.stop();
|
||||
}
|
||||
// websocket should only be referenced by webSocketPtr
|
||||
REQUIRE(webSocketPtr.use_count() == 1);
|
||||
}
|
||||
}
|
76
test/IXWebSocketPerMessageDeflateCompressorTest.cpp
Normal file
76
test/IXWebSocketPerMessageDeflateCompressorTest.cpp
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* IXWebSocketPerMessageDeflateCodecTest.cpp
|
||||
* Author: Benjamin Sergeant
|
||||
* Copyright (c) 2020 Machine Zone. All rights reserved.
|
||||
*
|
||||
* make build_test && build/test/ixwebsocket_unittest per-message-deflate-codec
|
||||
*/
|
||||
|
||||
#include "IXTest.h"
|
||||
#include "catch.hpp"
|
||||
#include <iostream>
|
||||
#include <ixwebsocket/IXWebSocketPerMessageDeflateCodec.h>
|
||||
#include <string.h>
|
||||
|
||||
using namespace ix;
|
||||
|
||||
namespace ix
|
||||
{
|
||||
std::string compressAndDecompress(const std::string& a)
|
||||
{
|
||||
std::string b, c;
|
||||
|
||||
WebSocketPerMessageDeflateCompressor compressor;
|
||||
compressor.init(11, true);
|
||||
compressor.compress(a, b);
|
||||
|
||||
WebSocketPerMessageDeflateDecompressor decompressor;
|
||||
decompressor.init(11, true);
|
||||
decompressor.decompress(b, c);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
std::string compressAndDecompressVector(const std::string& a)
|
||||
{
|
||||
std::string b, c;
|
||||
|
||||
std::vector<uint8_t> vec(a.begin(), a.end());
|
||||
|
||||
WebSocketPerMessageDeflateCompressor compressor;
|
||||
compressor.init(11, true);
|
||||
compressor.compress(vec, b);
|
||||
|
||||
WebSocketPerMessageDeflateDecompressor decompressor;
|
||||
decompressor.init(11, true);
|
||||
decompressor.decompress(b, c);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
TEST_CASE("per-message-deflate-codec", "[zlib]")
|
||||
{
|
||||
SECTION("string api")
|
||||
{
|
||||
REQUIRE(compressAndDecompress("") == "");
|
||||
REQUIRE(compressAndDecompress("foo") == "foo");
|
||||
REQUIRE(compressAndDecompress("bar") == "bar");
|
||||
REQUIRE(compressAndDecompress("asdcaseqw`21897dehqwed") == "asdcaseqw`21897dehqwed");
|
||||
REQUIRE(compressAndDecompress("/usr/local/include/ixwebsocket/IXSocketAppleSSL.h") ==
|
||||
"/usr/local/include/ixwebsocket/IXSocketAppleSSL.h");
|
||||
}
|
||||
|
||||
SECTION("vector api")
|
||||
{
|
||||
REQUIRE(compressAndDecompressVector("") == "");
|
||||
REQUIRE(compressAndDecompressVector("foo") == "foo");
|
||||
REQUIRE(compressAndDecompressVector("bar") == "bar");
|
||||
REQUIRE(compressAndDecompressVector("asdcaseqw`21897dehqwed") ==
|
||||
"asdcaseqw`21897dehqwed");
|
||||
REQUIRE(
|
||||
compressAndDecompressVector("/usr/local/include/ixwebsocket/IXSocketAppleSSL.h") ==
|
||||
"/usr/local/include/ixwebsocket/IXSocketAppleSSL.h");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ix
|
@ -19,7 +19,7 @@ namespace
|
||||
class WebSocketClient
|
||||
{
|
||||
public:
|
||||
WebSocketClient(int port, bool useHeartBeatMethod);
|
||||
WebSocketClient(int port);
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
@ -29,12 +29,10 @@ namespace
|
||||
private:
|
||||
ix::WebSocket _webSocket;
|
||||
int _port;
|
||||
bool _useHeartBeatMethod;
|
||||
};
|
||||
|
||||
WebSocketClient::WebSocketClient(int port, bool useHeartBeatMethod)
|
||||
WebSocketClient::WebSocketClient(int port)
|
||||
: _port(port)
|
||||
, _useHeartBeatMethod(useHeartBeatMethod)
|
||||
{
|
||||
;
|
||||
}
|
||||
@ -63,49 +61,37 @@ namespace
|
||||
|
||||
// The important bit for this test.
|
||||
// Set a 1 second heartbeat with the setter method to test
|
||||
if (_useHeartBeatMethod)
|
||||
{
|
||||
_webSocket.setPingInterval(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
_webSocket.setPingInterval(1);
|
||||
}
|
||||
_webSocket.setPingInterval(1);
|
||||
|
||||
std::stringstream ss;
|
||||
log(std::string("Connecting to url: ") + url);
|
||||
|
||||
_webSocket.setOnMessageCallback([](ix::WebSocketMessageType messageType,
|
||||
const std::string& str,
|
||||
size_t wireSize,
|
||||
const ix::WebSocketErrorInfo& error,
|
||||
const ix::WebSocketOpenInfo& openInfo,
|
||||
const ix::WebSocketCloseInfo& closeInfo) {
|
||||
_webSocket.setOnMessageCallback([](const ix::WebSocketMessagePtr& msg) {
|
||||
std::stringstream ss;
|
||||
if (messageType == ix::WebSocketMessageType::Open)
|
||||
if (msg->type == ix::WebSocketMessageType::Open)
|
||||
{
|
||||
log("client connected");
|
||||
}
|
||||
else if (messageType == ix::WebSocketMessageType::Close)
|
||||
else if (msg->type == ix::WebSocketMessageType::Close)
|
||||
{
|
||||
log("client disconnected");
|
||||
}
|
||||
else if (messageType == ix::WebSocketMessageType::Error)
|
||||
else if (msg->type == ix::WebSocketMessageType::Error)
|
||||
{
|
||||
ss << "Error ! " << error.reason;
|
||||
ss << "Error ! " << msg->errorInfo.reason;
|
||||
log(ss.str());
|
||||
}
|
||||
else if (messageType == ix::WebSocketMessageType::Pong)
|
||||
else if (msg->type == ix::WebSocketMessageType::Pong)
|
||||
{
|
||||
ss << "Received pong message " << str;
|
||||
ss << "Received pong message " << msg->str;
|
||||
log(ss.str());
|
||||
}
|
||||
else if (messageType == ix::WebSocketMessageType::Ping)
|
||||
else if (msg->type == ix::WebSocketMessageType::Ping)
|
||||
{
|
||||
ss << "Received ping message " << str;
|
||||
ss << "Received ping message " << msg->str;
|
||||
log(ss.str());
|
||||
}
|
||||
else if (messageType == ix::WebSocketMessageType::Message)
|
||||
else if (msg->type == ix::WebSocketMessageType::Message)
|
||||
{
|
||||
// too many messages to log
|
||||
}
|
||||
@ -132,33 +118,28 @@ namespace
|
||||
std::shared_ptr<ConnectionState> connectionState) {
|
||||
webSocket->setOnMessageCallback(
|
||||
[webSocket, connectionState, &server, &receivedPingMessages](
|
||||
ix::WebSocketMessageType messageType,
|
||||
const std::string& str,
|
||||
size_t wireSize,
|
||||
const ix::WebSocketErrorInfo& error,
|
||||
const ix::WebSocketOpenInfo& openInfo,
|
||||
const ix::WebSocketCloseInfo& closeInfo) {
|
||||
if (messageType == ix::WebSocketMessageType::Open)
|
||||
const ix::WebSocketMessagePtr& msg) {
|
||||
if (msg->type == ix::WebSocketMessageType::Open)
|
||||
{
|
||||
TLogger() << "New server connection";
|
||||
TLogger() << "id: " << connectionState->getId();
|
||||
TLogger() << "Uri: " << openInfo.uri;
|
||||
TLogger() << "Uri: " << msg->openInfo.uri;
|
||||
TLogger() << "Headers:";
|
||||
for (auto it : openInfo.headers)
|
||||
for (auto it : msg->openInfo.headers)
|
||||
{
|
||||
TLogger() << it.first << ": " << it.second;
|
||||
}
|
||||
}
|
||||
else if (messageType == ix::WebSocketMessageType::Close)
|
||||
else if (msg->type == ix::WebSocketMessageType::Close)
|
||||
{
|
||||
log("Server closed connection");
|
||||
}
|
||||
else if (messageType == ix::WebSocketMessageType::Ping)
|
||||
else if (msg->type == ix::WebSocketMessageType::Ping)
|
||||
{
|
||||
log("Server received a ping");
|
||||
receivedPingMessages++;
|
||||
}
|
||||
else if (messageType == ix::WebSocketMessageType::Message)
|
||||
else if (msg->type == ix::WebSocketMessageType::Message)
|
||||
{
|
||||
// to many messages to log
|
||||
for (auto client : server.getClients())
|
||||
@ -193,8 +174,7 @@ TEST_CASE("Websocket_ping_no_data_sent_setPingInterval", "[setPingInterval]")
|
||||
REQUIRE(startServer(server, serverReceivedPingMessages));
|
||||
|
||||
std::string session = ix::generateSessionId();
|
||||
bool useSetHeartBeatPeriodMethod = false; // so use setPingInterval
|
||||
WebSocketClient webSocketClient(port, useSetHeartBeatPeriodMethod);
|
||||
WebSocketClient webSocketClient(port);
|
||||
|
||||
webSocketClient.start();
|
||||
|
||||
@ -236,8 +216,7 @@ TEST_CASE("Websocket_ping_data_sent_setPingInterval", "[setPingInterval]")
|
||||
REQUIRE(startServer(server, serverReceivedPingMessages));
|
||||
|
||||
std::string session = ix::generateSessionId();
|
||||
bool useSetHeartBeatPeriodMethod = false; // so use setPingInterval
|
||||
WebSocketClient webSocketClient(port, useSetHeartBeatPeriodMethod);
|
||||
WebSocketClient webSocketClient(port);
|
||||
|
||||
webSocketClient.start();
|
||||
|
||||
@ -261,7 +240,7 @@ TEST_CASE("Websocket_ping_data_sent_setPingInterval", "[setPingInterval]")
|
||||
// Here we test ping interval
|
||||
// client has sent data, but ping should have been sent no matter what
|
||||
// -> expected ping messages == 3 as 900+900+1300 = 3100 seconds, 1 ping sent every second
|
||||
REQUIRE(serverReceivedPingMessages == 3);
|
||||
REQUIRE(serverReceivedPingMessages >= 2);
|
||||
|
||||
// Give us 1000ms for the server to notice that clients went away
|
||||
ix::msleep(1000);
|
||||
@ -284,8 +263,7 @@ TEST_CASE("Websocket_ping_data_sent_setPingInterval_half_full", "[setPingInterva
|
||||
REQUIRE(startServer(server, serverReceivedPingMessages));
|
||||
|
||||
std::string session = ix::generateSessionId();
|
||||
bool useSetHeartBeatPeriodMethod = false; // so use setPingInterval
|
||||
WebSocketClient webSocketClient(port, useSetHeartBeatPeriodMethod);
|
||||
WebSocketClient webSocketClient(port);
|
||||
|
||||
webSocketClient.start();
|
||||
|
||||
@ -338,8 +316,7 @@ TEST_CASE("Websocket_ping_data_sent_setPingInterval_full", "[setPingInterval]")
|
||||
REQUIRE(startServer(server, serverReceivedPingMessages));
|
||||
|
||||
std::string session = ix::generateSessionId();
|
||||
bool useSetHeartBeatPeriodMethod = false; // so use setPingInterval
|
||||
WebSocketClient webSocketClient(port, useSetHeartBeatPeriodMethod);
|
||||
WebSocketClient webSocketClient(port);
|
||||
|
||||
webSocketClient.start();
|
||||
|
||||
@ -363,8 +340,9 @@ TEST_CASE("Websocket_ping_data_sent_setPingInterval_full", "[setPingInterval]")
|
||||
|
||||
// Here we test ping interval
|
||||
// client has sent data, but ping should have been sent no matter what
|
||||
// -> expected ping messages == 1, 1 ping sent every second
|
||||
REQUIRE(serverReceivedPingMessages == 1);
|
||||
// -> expected ping messages == 2, 1 ping sent every second
|
||||
// The first ping is sent right away on connect
|
||||
REQUIRE(serverReceivedPingMessages == 2);
|
||||
|
||||
ix::msleep(100);
|
||||
|
||||
@ -392,8 +370,7 @@ TEST_CASE("Websocket_ping_no_data_sent_setHeartBeatPeriod", "[setPingInterval]")
|
||||
REQUIRE(startServer(server, serverReceivedPingMessages));
|
||||
|
||||
std::string session = ix::generateSessionId();
|
||||
bool useSetHeartBeatPeriodMethod = true;
|
||||
WebSocketClient webSocketClient(port, useSetHeartBeatPeriodMethod);
|
||||
WebSocketClient webSocketClient(port);
|
||||
|
||||
webSocketClient.start();
|
||||
|
||||
@ -406,14 +383,13 @@ TEST_CASE("Websocket_ping_no_data_sent_setHeartBeatPeriod", "[setPingInterval]")
|
||||
|
||||
REQUIRE(server.getClients().size() == 1);
|
||||
|
||||
ix::msleep(1900);
|
||||
ix::msleep(2100);
|
||||
|
||||
webSocketClient.stop();
|
||||
|
||||
|
||||
// Here we test ping interval
|
||||
// -> expected ping messages == 1 as 1900 seconds, 1 ping sent every second
|
||||
REQUIRE(serverReceivedPingMessages == 1);
|
||||
// -> expected ping messages == 2 as 2100 seconds, 1 ping sent every second
|
||||
REQUIRE(serverReceivedPingMessages == 2);
|
||||
|
||||
// Give us 1000ms for the server to notice that clients went away
|
||||
ix::msleep(1000);
|
||||
@ -436,8 +412,7 @@ TEST_CASE("Websocket_ping_data_sent_setHeartBeatPeriod", "[setPingInterval]")
|
||||
REQUIRE(startServer(server, serverReceivedPingMessages));
|
||||
|
||||
std::string session = ix::generateSessionId();
|
||||
bool useSetHeartBeatPeriodMethod = true;
|
||||
WebSocketClient webSocketClient(port, useSetHeartBeatPeriodMethod);
|
||||
WebSocketClient webSocketClient(port);
|
||||
|
||||
webSocketClient.start();
|
||||
|
||||
@ -464,7 +439,7 @@ TEST_CASE("Websocket_ping_data_sent_setHeartBeatPeriod", "[setPingInterval]")
|
||||
// Here we test ping interval
|
||||
// client has sent data, but ping should have been sent no matter what
|
||||
// -> expected ping messages == 2 as 900+900+1100 = 2900 seconds, 1 ping sent every second
|
||||
REQUIRE(serverReceivedPingMessages == 2);
|
||||
REQUIRE(serverReceivedPingMessages >= 2);
|
||||
|
||||
// Give us 1000ms for the server to notice that clients went away
|
||||
ix::msleep(1000);
|
||||
|
@ -35,13 +35,16 @@ namespace ix
|
||||
|
||||
server.setOnConnectionCallback([&server, &connectionId](
|
||||
std::shared_ptr<ix::WebSocket> webSocket,
|
||||
std::shared_ptr<ConnectionState> connectionState) {
|
||||
webSocket->setOnMessageCallback([webSocket, connectionState, &connectionId, &server](
|
||||
std::shared_ptr<ConnectionState> connectionState,
|
||||
std::unique_ptr<ConnectionInfo> connectionInfo) {
|
||||
auto remoteIp = connectionInfo->remoteIp;
|
||||
webSocket->setOnMessageCallback([webSocket, connectionState, remoteIp, &connectionId, &server](
|
||||
const ix::WebSocketMessagePtr& msg) {
|
||||
if (msg->type == ix::WebSocketMessageType::Open)
|
||||
{
|
||||
TLogger() << "New connection";
|
||||
connectionState->computeId();
|
||||
TLogger() << "remote ip: " << remoteIp;
|
||||
TLogger() << "id: " << connectionState->getId();
|
||||
TLogger() << "Uri: " << msg->openInfo.uri;
|
||||
TLogger() << "Headers:";
|
||||
|
@ -18,12 +18,15 @@ bool startServer(ix::WebSocketServer& server, std::string& subProtocols)
|
||||
{
|
||||
server.setOnConnectionCallback(
|
||||
[&server, &subProtocols](std::shared_ptr<ix::WebSocket> webSocket,
|
||||
std::shared_ptr<ConnectionState> connectionState) {
|
||||
webSocket->setOnMessageCallback([webSocket, connectionState, &server, &subProtocols](
|
||||
std::shared_ptr<ConnectionState> connectionState,
|
||||
std::unique_ptr<ConnectionInfo> connectionInfo) {
|
||||
auto remoteIp = connectionInfo->remoteIp;
|
||||
webSocket->setOnMessageCallback([webSocket, connectionState, remoteIp, &server, &subProtocols](
|
||||
const ix::WebSocketMessagePtr& msg) {
|
||||
if (msg->type == ix::WebSocketMessageType::Open)
|
||||
{
|
||||
TLogger() << "New connection";
|
||||
TLogger() << "remote ip: " << remoteIp;
|
||||
TLogger() << "id: " << connectionState->getId();
|
||||
TLogger() << "Uri: " << msg->openInfo.uri;
|
||||
TLogger() << "Headers:";
|
||||
|
2428
third_party/cpp-linenoise/linenoise.cpp
vendored
Normal file
2428
third_party/cpp-linenoise/linenoise.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2298
third_party/cpp-linenoise/linenoise.hpp
vendored
2298
third_party/cpp-linenoise/linenoise.hpp
vendored
File diff suppressed because it is too large
Load Diff
26
third_party/zlib/.gitignore
vendored
26
third_party/zlib/.gitignore
vendored
@ -1,26 +0,0 @@
|
||||
*.diff
|
||||
*.patch
|
||||
*.orig
|
||||
*.rej
|
||||
|
||||
*~
|
||||
*.a
|
||||
*.lo
|
||||
*.o
|
||||
*.dylib
|
||||
|
||||
*.gcda
|
||||
*.gcno
|
||||
*.gcov
|
||||
|
||||
/example
|
||||
/example64
|
||||
/examplesh
|
||||
/libz.so*
|
||||
/minigzip
|
||||
/minigzip64
|
||||
/minigzipsh
|
||||
/zlib.pc
|
||||
/configure.log
|
||||
|
||||
.DS_Store
|
227
third_party/zlib/CMakeLists.txt
vendored
227
third_party/zlib/CMakeLists.txt
vendored
@ -1,227 +0,0 @@
|
||||
cmake_minimum_required(VERSION 2.4.4)
|
||||
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)
|
||||
|
||||
project(zlib C)
|
||||
|
||||
set(VERSION "1.2.11")
|
||||
|
||||
option(ASM686 "Enable building i686 assembly implementation")
|
||||
option(AMD64 "Enable building amd64 assembly implementation")
|
||||
|
||||
set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables")
|
||||
set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries")
|
||||
set(INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers")
|
||||
set(INSTALL_MAN_DIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Installation directory for manual pages")
|
||||
set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_PREFIX}/share/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files")
|
||||
|
||||
include(CheckTypeSize)
|
||||
include(CheckFunctionExists)
|
||||
include(CheckIncludeFile)
|
||||
include(CheckCSourceCompiles)
|
||||
enable_testing()
|
||||
|
||||
check_include_file(sys/types.h HAVE_SYS_TYPES_H)
|
||||
check_include_file(stdint.h HAVE_STDINT_H)
|
||||
check_include_file(stddef.h HAVE_STDDEF_H)
|
||||
|
||||
#
|
||||
# Check to see if we have large file support
|
||||
#
|
||||
set(CMAKE_REQUIRED_DEFINITIONS -D_LARGEFILE64_SOURCE=1)
|
||||
# We add these other definitions here because CheckTypeSize.cmake
|
||||
# in CMake 2.4.x does not automatically do so and we want
|
||||
# compatibility with CMake 2.4.x.
|
||||
if(HAVE_SYS_TYPES_H)
|
||||
list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_SYS_TYPES_H)
|
||||
endif()
|
||||
if(HAVE_STDINT_H)
|
||||
list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDINT_H)
|
||||
endif()
|
||||
if(HAVE_STDDEF_H)
|
||||
list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDDEF_H)
|
||||
endif()
|
||||
check_type_size(off64_t OFF64_T)
|
||||
if(HAVE_OFF64_T)
|
||||
add_definitions(-D_LARGEFILE64_SOURCE=1)
|
||||
endif()
|
||||
set(CMAKE_REQUIRED_DEFINITIONS) # clear variable
|
||||
|
||||
#
|
||||
# Check for fseeko
|
||||
#
|
||||
check_function_exists(fseeko HAVE_FSEEKO)
|
||||
if(NOT HAVE_FSEEKO)
|
||||
add_definitions(-DNO_FSEEKO)
|
||||
endif()
|
||||
|
||||
#
|
||||
# Check for unistd.h
|
||||
#
|
||||
check_include_file(unistd.h Z_HAVE_UNISTD_H)
|
||||
|
||||
if(MSVC)
|
||||
set(CMAKE_DEBUG_POSTFIX "d")
|
||||
add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
|
||||
add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
|
||||
# If we're doing an out of source build and the user has a zconf.h
|
||||
# in their source tree...
|
||||
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h)
|
||||
message(STATUS "Renaming")
|
||||
message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h")
|
||||
message(STATUS "to 'zconf.h.included' because this file is included with zlib")
|
||||
message(STATUS "but CMake generates it automatically in the build directory.")
|
||||
file(RENAME ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.included)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(ZLIB_PC ${CMAKE_CURRENT_BINARY_DIR}/zlib.pc)
|
||||
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zlib.pc.cmakein
|
||||
${ZLIB_PC} @ONLY)
|
||||
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.cmakein
|
||||
${CMAKE_CURRENT_BINARY_DIR}/zconf.h @ONLY)
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR})
|
||||
|
||||
|
||||
#============================================================================
|
||||
# zlib
|
||||
#============================================================================
|
||||
|
||||
set(ZLIB_PUBLIC_HDRS
|
||||
${CMAKE_CURRENT_BINARY_DIR}/zconf.h
|
||||
zlib.h
|
||||
)
|
||||
set(ZLIB_PRIVATE_HDRS
|
||||
crc32.h
|
||||
deflate.h
|
||||
gzguts.h
|
||||
inffast.h
|
||||
inffixed.h
|
||||
inflate.h
|
||||
inftrees.h
|
||||
trees.h
|
||||
zutil.h
|
||||
)
|
||||
set(ZLIB_SRCS
|
||||
adler32.c
|
||||
compress.c
|
||||
crc32.c
|
||||
deflate.c
|
||||
gzclose.c
|
||||
gzlib.c
|
||||
gzread.c
|
||||
gzwrite.c
|
||||
inflate.c
|
||||
infback.c
|
||||
inftrees.c
|
||||
inffast.c
|
||||
trees.c
|
||||
uncompr.c
|
||||
zutil.c
|
||||
)
|
||||
|
||||
if(NOT MINGW)
|
||||
set(ZLIB_DLL_SRCS
|
||||
win32/zlib1.rc # If present will override custom build rule below.
|
||||
)
|
||||
endif()
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCC)
|
||||
if(ASM686)
|
||||
set(ZLIB_ASMS contrib/asm686/match.S)
|
||||
elseif (AMD64)
|
||||
set(ZLIB_ASMS contrib/amd64/amd64-match.S)
|
||||
endif ()
|
||||
|
||||
if(ZLIB_ASMS)
|
||||
add_definitions(-DASMV)
|
||||
set_source_files_properties(${ZLIB_ASMS} PROPERTIES LANGUAGE C COMPILE_FLAGS -DNO_UNDERLINE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
if(ASM686)
|
||||
ENABLE_LANGUAGE(ASM_MASM)
|
||||
set(ZLIB_ASMS
|
||||
contrib/masmx86/inffas32.asm
|
||||
contrib/masmx86/match686.asm
|
||||
)
|
||||
elseif (AMD64)
|
||||
ENABLE_LANGUAGE(ASM_MASM)
|
||||
set(ZLIB_ASMS
|
||||
contrib/masmx64/gvmat64.asm
|
||||
contrib/masmx64/inffasx64.asm
|
||||
)
|
||||
endif()
|
||||
|
||||
if(ZLIB_ASMS)
|
||||
add_definitions(-DASMV -DASMINF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# parse the full version number from zlib.h and include in ZLIB_FULL_VERSION
|
||||
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib.h _zlib_h_contents)
|
||||
string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([-0-9A-Za-z.]+)\".*"
|
||||
"\\1" ZLIB_FULL_VERSION ${_zlib_h_contents})
|
||||
|
||||
if(MINGW)
|
||||
# This gets us DLL resource information when compiling on MinGW.
|
||||
if(NOT CMAKE_RC_COMPILER)
|
||||
set(CMAKE_RC_COMPILER windres.exe)
|
||||
endif()
|
||||
|
||||
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj
|
||||
COMMAND ${CMAKE_RC_COMPILER}
|
||||
-D GCC_WINDRES
|
||||
-I ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
-I ${CMAKE_CURRENT_BINARY_DIR}
|
||||
-o ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj
|
||||
-i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib1.rc)
|
||||
set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj)
|
||||
endif(MINGW)
|
||||
|
||||
add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
|
||||
add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
|
||||
set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL)
|
||||
set_target_properties(zlib PROPERTIES SOVERSION 1)
|
||||
|
||||
if(NOT CYGWIN)
|
||||
# This property causes shared libraries on Linux to have the full version
|
||||
# encoded into their final filename. We disable this on Cygwin because
|
||||
# it causes cygz-${ZLIB_FULL_VERSION}.dll to be created when cygz.dll
|
||||
# seems to be the default.
|
||||
#
|
||||
# This has no effect with MSVC, on that platform the version info for
|
||||
# the DLL comes from the resource file win32/zlib1.rc
|
||||
set_target_properties(zlib PROPERTIES VERSION ${ZLIB_FULL_VERSION})
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
# On unix-like platforms the library is almost always called libz
|
||||
set_target_properties(zlib zlibstatic PROPERTIES OUTPUT_NAME z)
|
||||
if(NOT APPLE)
|
||||
set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib.map\"")
|
||||
endif()
|
||||
elseif(BUILD_SHARED_LIBS AND WIN32)
|
||||
# Creates zlib1.dll when building shared library version
|
||||
set_target_properties(zlib PROPERTIES SUFFIX "1.dll")
|
||||
endif()
|
||||
|
||||
if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL )
|
||||
install(TARGETS zlib zlibstatic
|
||||
RUNTIME DESTINATION "${INSTALL_BIN_DIR}"
|
||||
ARCHIVE DESTINATION "${INSTALL_LIB_DIR}"
|
||||
LIBRARY DESTINATION "${INSTALL_LIB_DIR}" )
|
||||
endif()
|
||||
if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL )
|
||||
install(FILES ${ZLIB_PUBLIC_HDRS} DESTINATION "${INSTALL_INC_DIR}")
|
||||
endif()
|
||||
if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL )
|
||||
install(FILES zlib.3 DESTINATION "${INSTALL_MAN_DIR}/man3")
|
||||
endif()
|
||||
if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL )
|
||||
install(FILES ${ZLIB_PC} DESTINATION "${INSTALL_PKGCONFIG_DIR}")
|
||||
endif()
|
1515
third_party/zlib/ChangeLog
vendored
1515
third_party/zlib/ChangeLog
vendored
File diff suppressed because it is too large
Load Diff
368
third_party/zlib/FAQ
vendored
368
third_party/zlib/FAQ
vendored
@ -1,368 +0,0 @@
|
||||
|
||||
Frequently Asked Questions about zlib
|
||||
|
||||
|
||||
If your question is not there, please check the zlib home page
|
||||
http://zlib.net/ which may have more recent information.
|
||||
The lastest zlib FAQ is at http://zlib.net/zlib_faq.html
|
||||
|
||||
|
||||
1. Is zlib Y2K-compliant?
|
||||
|
||||
Yes. zlib doesn't handle dates.
|
||||
|
||||
2. Where can I get a Windows DLL version?
|
||||
|
||||
The zlib sources can be compiled without change to produce a DLL. See the
|
||||
file win32/DLL_FAQ.txt in the zlib distribution. Pointers to the
|
||||
precompiled DLL are found in the zlib web site at http://zlib.net/ .
|
||||
|
||||
3. Where can I get a Visual Basic interface to zlib?
|
||||
|
||||
See
|
||||
* http://marknelson.us/1997/01/01/zlib-engine/
|
||||
* win32/DLL_FAQ.txt in the zlib distribution
|
||||
|
||||
4. compress() returns Z_BUF_ERROR.
|
||||
|
||||
Make sure that before the call of compress(), the length of the compressed
|
||||
buffer is equal to the available size of the compressed buffer and not
|
||||
zero. For Visual Basic, check that this parameter is passed by reference
|
||||
("as any"), not by value ("as long").
|
||||
|
||||
5. deflate() or inflate() returns Z_BUF_ERROR.
|
||||
|
||||
Before making the call, make sure that avail_in and avail_out are not zero.
|
||||
When setting the parameter flush equal to Z_FINISH, also make sure that
|
||||
avail_out is big enough to allow processing all pending input. Note that a
|
||||
Z_BUF_ERROR is not fatal--another call to deflate() or inflate() can be
|
||||
made with more input or output space. A Z_BUF_ERROR may in fact be
|
||||
unavoidable depending on how the functions are used, since it is not
|
||||
possible to tell whether or not there is more output pending when
|
||||
strm.avail_out returns with zero. See http://zlib.net/zlib_how.html for a
|
||||
heavily annotated example.
|
||||
|
||||
6. Where's the zlib documentation (man pages, etc.)?
|
||||
|
||||
It's in zlib.h . Examples of zlib usage are in the files test/example.c
|
||||
and test/minigzip.c, with more in examples/ .
|
||||
|
||||
7. Why don't you use GNU autoconf or libtool or ...?
|
||||
|
||||
Because we would like to keep zlib as a very small and simple package.
|
||||
zlib is rather portable and doesn't need much configuration.
|
||||
|
||||
8. I found a bug in zlib.
|
||||
|
||||
Most of the time, such problems are due to an incorrect usage of zlib.
|
||||
Please try to reproduce the problem with a small program and send the
|
||||
corresponding source to us at zlib@gzip.org . Do not send multi-megabyte
|
||||
data files without prior agreement.
|
||||
|
||||
9. Why do I get "undefined reference to gzputc"?
|
||||
|
||||
If "make test" produces something like
|
||||
|
||||
example.o(.text+0x154): undefined reference to `gzputc'
|
||||
|
||||
check that you don't have old files libz.* in /usr/lib, /usr/local/lib or
|
||||
/usr/X11R6/lib. Remove any old versions, then do "make install".
|
||||
|
||||
10. I need a Delphi interface to zlib.
|
||||
|
||||
See the contrib/delphi directory in the zlib distribution.
|
||||
|
||||
11. Can zlib handle .zip archives?
|
||||
|
||||
Not by itself, no. See the directory contrib/minizip in the zlib
|
||||
distribution.
|
||||
|
||||
12. Can zlib handle .Z files?
|
||||
|
||||
No, sorry. You have to spawn an uncompress or gunzip subprocess, or adapt
|
||||
the code of uncompress on your own.
|
||||
|
||||
13. How can I make a Unix shared library?
|
||||
|
||||
By default a shared (and a static) library is built for Unix. So:
|
||||
|
||||
make distclean
|
||||
./configure
|
||||
make
|
||||
|
||||
14. How do I install a shared zlib library on Unix?
|
||||
|
||||
After the above, then:
|
||||
|
||||
make install
|
||||
|
||||
However, many flavors of Unix come with a shared zlib already installed.
|
||||
Before going to the trouble of compiling a shared version of zlib and
|
||||
trying to install it, you may want to check if it's already there! If you
|
||||
can #include <zlib.h>, it's there. The -lz option will probably link to
|
||||
it. You can check the version at the top of zlib.h or with the
|
||||
ZLIB_VERSION symbol defined in zlib.h .
|
||||
|
||||
15. I have a question about OttoPDF.
|
||||
|
||||
We are not the authors of OttoPDF. The real author is on the OttoPDF web
|
||||
site: Joel Hainley, jhainley@myndkryme.com.
|
||||
|
||||
16. Can zlib decode Flate data in an Adobe PDF file?
|
||||
|
||||
Yes. See http://www.pdflib.com/ . To modify PDF forms, see
|
||||
http://sourceforge.net/projects/acroformtool/ .
|
||||
|
||||
17. Why am I getting this "register_frame_info not found" error on Solaris?
|
||||
|
||||
After installing zlib 1.1.4 on Solaris 2.6, running applications using zlib
|
||||
generates an error such as:
|
||||
|
||||
ld.so.1: rpm: fatal: relocation error: file /usr/local/lib/libz.so:
|
||||
symbol __register_frame_info: referenced symbol not found
|
||||
|
||||
The symbol __register_frame_info is not part of zlib, it is generated by
|
||||
the C compiler (cc or gcc). You must recompile applications using zlib
|
||||
which have this problem. This problem is specific to Solaris. See
|
||||
http://www.sunfreeware.com for Solaris versions of zlib and applications
|
||||
using zlib.
|
||||
|
||||
18. Why does gzip give an error on a file I make with compress/deflate?
|
||||
|
||||
The compress and deflate functions produce data in the zlib format, which
|
||||
is different and incompatible with the gzip format. The gz* functions in
|
||||
zlib on the other hand use the gzip format. Both the zlib and gzip formats
|
||||
use the same compressed data format internally, but have different headers
|
||||
and trailers around the compressed data.
|
||||
|
||||
19. Ok, so why are there two different formats?
|
||||
|
||||
The gzip format was designed to retain the directory information about a
|
||||
single file, such as the name and last modification date. The zlib format
|
||||
on the other hand was designed for in-memory and communication channel
|
||||
applications, and has a much more compact header and trailer and uses a
|
||||
faster integrity check than gzip.
|
||||
|
||||
20. Well that's nice, but how do I make a gzip file in memory?
|
||||
|
||||
You can request that deflate write the gzip format instead of the zlib
|
||||
format using deflateInit2(). You can also request that inflate decode the
|
||||
gzip format using inflateInit2(). Read zlib.h for more details.
|
||||
|
||||
21. Is zlib thread-safe?
|
||||
|
||||
Yes. However any library routines that zlib uses and any application-
|
||||
provided memory allocation routines must also be thread-safe. zlib's gz*
|
||||
functions use stdio library routines, and most of zlib's functions use the
|
||||
library memory allocation routines by default. zlib's *Init* functions
|
||||
allow for the application to provide custom memory allocation routines.
|
||||
|
||||
Of course, you should only operate on any given zlib or gzip stream from a
|
||||
single thread at a time.
|
||||
|
||||
22. Can I use zlib in my commercial application?
|
||||
|
||||
Yes. Please read the license in zlib.h.
|
||||
|
||||
23. Is zlib under the GNU license?
|
||||
|
||||
No. Please read the license in zlib.h.
|
||||
|
||||
24. The license says that altered source versions must be "plainly marked". So
|
||||
what exactly do I need to do to meet that requirement?
|
||||
|
||||
You need to change the ZLIB_VERSION and ZLIB_VERNUM #defines in zlib.h. In
|
||||
particular, the final version number needs to be changed to "f", and an
|
||||
identification string should be appended to ZLIB_VERSION. Version numbers
|
||||
x.x.x.f are reserved for modifications to zlib by others than the zlib
|
||||
maintainers. For example, if the version of the base zlib you are altering
|
||||
is "1.2.3.4", then in zlib.h you should change ZLIB_VERNUM to 0x123f, and
|
||||
ZLIB_VERSION to something like "1.2.3.f-zachary-mods-v3". You can also
|
||||
update the version strings in deflate.c and inftrees.c.
|
||||
|
||||
For altered source distributions, you should also note the origin and
|
||||
nature of the changes in zlib.h, as well as in ChangeLog and README, along
|
||||
with the dates of the alterations. The origin should include at least your
|
||||
name (or your company's name), and an email address to contact for help or
|
||||
issues with the library.
|
||||
|
||||
Note that distributing a compiled zlib library along with zlib.h and
|
||||
zconf.h is also a source distribution, and so you should change
|
||||
ZLIB_VERSION and ZLIB_VERNUM and note the origin and nature of the changes
|
||||
in zlib.h as you would for a full source distribution.
|
||||
|
||||
25. Will zlib work on a big-endian or little-endian architecture, and can I
|
||||
exchange compressed data between them?
|
||||
|
||||
Yes and yes.
|
||||
|
||||
26. Will zlib work on a 64-bit machine?
|
||||
|
||||
Yes. It has been tested on 64-bit machines, and has no dependence on any
|
||||
data types being limited to 32-bits in length. If you have any
|
||||
difficulties, please provide a complete problem report to zlib@gzip.org
|
||||
|
||||
27. Will zlib decompress data from the PKWare Data Compression Library?
|
||||
|
||||
No. The PKWare DCL uses a completely different compressed data format than
|
||||
does PKZIP and zlib. However, you can look in zlib's contrib/blast
|
||||
directory for a possible solution to your problem.
|
||||
|
||||
28. Can I access data randomly in a compressed stream?
|
||||
|
||||
No, not without some preparation. If when compressing you periodically use
|
||||
Z_FULL_FLUSH, carefully write all the pending data at those points, and
|
||||
keep an index of those locations, then you can start decompression at those
|
||||
points. You have to be careful to not use Z_FULL_FLUSH too often, since it
|
||||
can significantly degrade compression. Alternatively, you can scan a
|
||||
deflate stream once to generate an index, and then use that index for
|
||||
random access. See examples/zran.c .
|
||||
|
||||
29. Does zlib work on MVS, OS/390, CICS, etc.?
|
||||
|
||||
It has in the past, but we have not heard of any recent evidence. There
|
||||
were working ports of zlib 1.1.4 to MVS, but those links no longer work.
|
||||
If you know of recent, successful applications of zlib on these operating
|
||||
systems, please let us know. Thanks.
|
||||
|
||||
30. Is there some simpler, easier to read version of inflate I can look at to
|
||||
understand the deflate format?
|
||||
|
||||
First off, you should read RFC 1951. Second, yes. Look in zlib's
|
||||
contrib/puff directory.
|
||||
|
||||
31. Does zlib infringe on any patents?
|
||||
|
||||
As far as we know, no. In fact, that was originally the whole point behind
|
||||
zlib. Look here for some more information:
|
||||
|
||||
http://www.gzip.org/#faq11
|
||||
|
||||
32. Can zlib work with greater than 4 GB of data?
|
||||
|
||||
Yes. inflate() and deflate() will process any amount of data correctly.
|
||||
Each call of inflate() or deflate() is limited to input and output chunks
|
||||
of the maximum value that can be stored in the compiler's "unsigned int"
|
||||
type, but there is no limit to the number of chunks. Note however that the
|
||||
strm.total_in and strm_total_out counters may be limited to 4 GB. These
|
||||
counters are provided as a convenience and are not used internally by
|
||||
inflate() or deflate(). The application can easily set up its own counters
|
||||
updated after each call of inflate() or deflate() to count beyond 4 GB.
|
||||
compress() and uncompress() may be limited to 4 GB, since they operate in a
|
||||
single call. gzseek() and gztell() may be limited to 4 GB depending on how
|
||||
zlib is compiled. See the zlibCompileFlags() function in zlib.h.
|
||||
|
||||
The word "may" appears several times above since there is a 4 GB limit only
|
||||
if the compiler's "long" type is 32 bits. If the compiler's "long" type is
|
||||
64 bits, then the limit is 16 exabytes.
|
||||
|
||||
33. Does zlib have any security vulnerabilities?
|
||||
|
||||
The only one that we are aware of is potentially in gzprintf(). If zlib is
|
||||
compiled to use sprintf() or vsprintf(), then there is no protection
|
||||
against a buffer overflow of an 8K string space (or other value as set by
|
||||
gzbuffer()), other than the caller of gzprintf() assuring that the output
|
||||
will not exceed 8K. On the other hand, if zlib is compiled to use
|
||||
snprintf() or vsnprintf(), which should normally be the case, then there is
|
||||
no vulnerability. The ./configure script will display warnings if an
|
||||
insecure variation of sprintf() will be used by gzprintf(). Also the
|
||||
zlibCompileFlags() function will return information on what variant of
|
||||
sprintf() is used by gzprintf().
|
||||
|
||||
If you don't have snprintf() or vsnprintf() and would like one, you can
|
||||
find a portable implementation here:
|
||||
|
||||
http://www.ijs.si/software/snprintf/
|
||||
|
||||
Note that you should be using the most recent version of zlib. Versions
|
||||
1.1.3 and before were subject to a double-free vulnerability, and versions
|
||||
1.2.1 and 1.2.2 were subject to an access exception when decompressing
|
||||
invalid compressed data.
|
||||
|
||||
34. Is there a Java version of zlib?
|
||||
|
||||
Probably what you want is to use zlib in Java. zlib is already included
|
||||
as part of the Java SDK in the java.util.zip package. If you really want
|
||||
a version of zlib written in the Java language, look on the zlib home
|
||||
page for links: http://zlib.net/ .
|
||||
|
||||
35. I get this or that compiler or source-code scanner warning when I crank it
|
||||
up to maximally-pedantic. Can't you guys write proper code?
|
||||
|
||||
Many years ago, we gave up attempting to avoid warnings on every compiler
|
||||
in the universe. It just got to be a waste of time, and some compilers
|
||||
were downright silly as well as contradicted each other. So now, we simply
|
||||
make sure that the code always works.
|
||||
|
||||
36. Valgrind (or some similar memory access checker) says that deflate is
|
||||
performing a conditional jump that depends on an uninitialized value.
|
||||
Isn't that a bug?
|
||||
|
||||
No. That is intentional for performance reasons, and the output of deflate
|
||||
is not affected. This only started showing up recently since zlib 1.2.x
|
||||
uses malloc() by default for allocations, whereas earlier versions used
|
||||
calloc(), which zeros out the allocated memory. Even though the code was
|
||||
correct, versions 1.2.4 and later was changed to not stimulate these
|
||||
checkers.
|
||||
|
||||
37. Will zlib read the (insert any ancient or arcane format here) compressed
|
||||
data format?
|
||||
|
||||
Probably not. Look in the comp.compression FAQ for pointers to various
|
||||
formats and associated software.
|
||||
|
||||
38. How can I encrypt/decrypt zip files with zlib?
|
||||
|
||||
zlib doesn't support encryption. The original PKZIP encryption is very
|
||||
weak and can be broken with freely available programs. To get strong
|
||||
encryption, use GnuPG, http://www.gnupg.org/ , which already includes zlib
|
||||
compression. For PKZIP compatible "encryption", look at
|
||||
http://www.info-zip.org/
|
||||
|
||||
39. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings?
|
||||
|
||||
"gzip" is the gzip format, and "deflate" is the zlib format. They should
|
||||
probably have called the second one "zlib" instead to avoid confusion with
|
||||
the raw deflate compressed data format. While the HTTP 1.1 RFC 2616
|
||||
correctly points to the zlib specification in RFC 1950 for the "deflate"
|
||||
transfer encoding, there have been reports of servers and browsers that
|
||||
incorrectly produce or expect raw deflate data per the deflate
|
||||
specification in RFC 1951, most notably Microsoft. So even though the
|
||||
"deflate" transfer encoding using the zlib format would be the more
|
||||
efficient approach (and in fact exactly what the zlib format was designed
|
||||
for), using the "gzip" transfer encoding is probably more reliable due to
|
||||
an unfortunate choice of name on the part of the HTTP 1.1 authors.
|
||||
|
||||
Bottom line: use the gzip format for HTTP 1.1 encoding.
|
||||
|
||||
40. Does zlib support the new "Deflate64" format introduced by PKWare?
|
||||
|
||||
No. PKWare has apparently decided to keep that format proprietary, since
|
||||
they have not documented it as they have previous compression formats. In
|
||||
any case, the compression improvements are so modest compared to other more
|
||||
modern approaches, that it's not worth the effort to implement.
|
||||
|
||||
41. I'm having a problem with the zip functions in zlib, can you help?
|
||||
|
||||
There are no zip functions in zlib. You are probably using minizip by
|
||||
Giles Vollant, which is found in the contrib directory of zlib. It is not
|
||||
part of zlib. In fact none of the stuff in contrib is part of zlib. The
|
||||
files in there are not supported by the zlib authors. You need to contact
|
||||
the authors of the respective contribution for help.
|
||||
|
||||
42. The match.asm code in contrib is under the GNU General Public License.
|
||||
Since it's part of zlib, doesn't that mean that all of zlib falls under the
|
||||
GNU GPL?
|
||||
|
||||
No. The files in contrib are not part of zlib. They were contributed by
|
||||
other authors and are provided as a convenience to the user within the zlib
|
||||
distribution. Each item in contrib has its own license.
|
||||
|
||||
43. Is zlib subject to export controls? What is its ECCN?
|
||||
|
||||
zlib is not subject to export controls, and so is classified as EAR99.
|
||||
|
||||
44. Can you please sign these lengthy legal documents and fax them back to us
|
||||
so that we can use your software in our product?
|
||||
|
||||
No. Go away. Shoo.
|
68
third_party/zlib/INDEX
vendored
68
third_party/zlib/INDEX
vendored
@ -1,68 +0,0 @@
|
||||
CMakeLists.txt cmake build file
|
||||
ChangeLog history of changes
|
||||
FAQ Frequently Asked Questions about zlib
|
||||
INDEX this file
|
||||
Makefile dummy Makefile that tells you to ./configure
|
||||
Makefile.in template for Unix Makefile
|
||||
README guess what
|
||||
configure configure script for Unix
|
||||
make_vms.com makefile for VMS
|
||||
test/example.c zlib usages examples for build testing
|
||||
test/minigzip.c minimal gzip-like functionality for build testing
|
||||
test/infcover.c inf*.c code coverage for build coverage testing
|
||||
treebuild.xml XML description of source file dependencies
|
||||
zconf.h.cmakein zconf.h template for cmake
|
||||
zconf.h.in zconf.h template for configure
|
||||
zlib.3 Man page for zlib
|
||||
zlib.3.pdf Man page in PDF format
|
||||
zlib.map Linux symbol information
|
||||
zlib.pc.in Template for pkg-config descriptor
|
||||
zlib.pc.cmakein zlib.pc template for cmake
|
||||
zlib2ansi perl script to convert source files for C++ compilation
|
||||
|
||||
amiga/ makefiles for Amiga SAS C
|
||||
as400/ makefiles for AS/400
|
||||
doc/ documentation for formats and algorithms
|
||||
msdos/ makefiles for MSDOS
|
||||
nintendods/ makefile for Nintendo DS
|
||||
old/ makefiles for various architectures and zlib documentation
|
||||
files that have not yet been updated for zlib 1.2.x
|
||||
qnx/ makefiles for QNX
|
||||
watcom/ makefiles for OpenWatcom
|
||||
win32/ makefiles for Windows
|
||||
|
||||
zlib public header files (required for library use):
|
||||
zconf.h
|
||||
zlib.h
|
||||
|
||||
private source files used to build the zlib library:
|
||||
adler32.c
|
||||
compress.c
|
||||
crc32.c
|
||||
crc32.h
|
||||
deflate.c
|
||||
deflate.h
|
||||
gzclose.c
|
||||
gzguts.h
|
||||
gzlib.c
|
||||
gzread.c
|
||||
gzwrite.c
|
||||
infback.c
|
||||
inffast.c
|
||||
inffast.h
|
||||
inffixed.h
|
||||
inflate.c
|
||||
inflate.h
|
||||
inftrees.c
|
||||
inftrees.h
|
||||
trees.c
|
||||
trees.h
|
||||
uncompr.c
|
||||
zutil.c
|
||||
zutil.h
|
||||
|
||||
source files for sample programs
|
||||
See examples/README.examples
|
||||
|
||||
unsupported contributions by third parties
|
||||
See contrib/README.contrib
|
5
third_party/zlib/Makefile
vendored
5
third_party/zlib/Makefile
vendored
@ -1,5 +0,0 @@
|
||||
all:
|
||||
-@echo "Please use ./configure first. Thank you."
|
||||
|
||||
distclean:
|
||||
make -f Makefile.in distclean
|
410
third_party/zlib/Makefile.in
vendored
410
third_party/zlib/Makefile.in
vendored
@ -1,410 +0,0 @@
|
||||
# Makefile for zlib
|
||||
# Copyright (C) 1995-2017 Jean-loup Gailly, Mark Adler
|
||||
# For conditions of distribution and use, see copyright notice in zlib.h
|
||||
|
||||
# To compile and test, type:
|
||||
# ./configure; make test
|
||||
# Normally configure builds both a static and a shared library.
|
||||
# If you want to build just a static library, use: ./configure --static
|
||||
|
||||
# To use the asm code, type:
|
||||
# cp contrib/asm?86/match.S ./match.S
|
||||
# make LOC=-DASMV OBJA=match.o
|
||||
|
||||
# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type:
|
||||
# make install
|
||||
# To install in $HOME instead of /usr/local, use:
|
||||
# make install prefix=$HOME
|
||||
|
||||
CC=cc
|
||||
|
||||
CFLAGS=-O
|
||||
#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
|
||||
#CFLAGS=-g -DZLIB_DEBUG
|
||||
#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
|
||||
# -Wstrict-prototypes -Wmissing-prototypes
|
||||
|
||||
SFLAGS=-O
|
||||
LDFLAGS=
|
||||
TEST_LDFLAGS=-L. libz.a
|
||||
LDSHARED=$(CC)
|
||||
CPP=$(CC) -E
|
||||
|
||||
STATICLIB=libz.a
|
||||
SHAREDLIB=libz.so
|
||||
SHAREDLIBV=libz.so.1.2.11
|
||||
SHAREDLIBM=libz.so.1
|
||||
LIBS=$(STATICLIB) $(SHAREDLIBV)
|
||||
|
||||
AR=ar
|
||||
ARFLAGS=rc
|
||||
RANLIB=ranlib
|
||||
LDCONFIG=ldconfig
|
||||
LDSHAREDLIBC=-lc
|
||||
TAR=tar
|
||||
SHELL=/bin/sh
|
||||
EXE=
|
||||
|
||||
prefix = /usr/local
|
||||
exec_prefix = ${prefix}
|
||||
libdir = ${exec_prefix}/lib
|
||||
sharedlibdir = ${libdir}
|
||||
includedir = ${prefix}/include
|
||||
mandir = ${prefix}/share/man
|
||||
man3dir = ${mandir}/man3
|
||||
pkgconfigdir = ${libdir}/pkgconfig
|
||||
SRCDIR=
|
||||
ZINC=
|
||||
ZINCOUT=-I.
|
||||
|
||||
OBJZ = adler32.o crc32.o deflate.o infback.o inffast.o inflate.o inftrees.o trees.o zutil.o
|
||||
OBJG = compress.o uncompr.o gzclose.o gzlib.o gzread.o gzwrite.o
|
||||
OBJC = $(OBJZ) $(OBJG)
|
||||
|
||||
PIC_OBJZ = adler32.lo crc32.lo deflate.lo infback.lo inffast.lo inflate.lo inftrees.lo trees.lo zutil.lo
|
||||
PIC_OBJG = compress.lo uncompr.lo gzclose.lo gzlib.lo gzread.lo gzwrite.lo
|
||||
PIC_OBJC = $(PIC_OBJZ) $(PIC_OBJG)
|
||||
|
||||
# to use the asm code: make OBJA=match.o, PIC_OBJA=match.lo
|
||||
OBJA =
|
||||
PIC_OBJA =
|
||||
|
||||
OBJS = $(OBJC) $(OBJA)
|
||||
|
||||
PIC_OBJS = $(PIC_OBJC) $(PIC_OBJA)
|
||||
|
||||
all: static shared
|
||||
|
||||
static: example$(EXE) minigzip$(EXE)
|
||||
|
||||
shared: examplesh$(EXE) minigzipsh$(EXE)
|
||||
|
||||
all64: example64$(EXE) minigzip64$(EXE)
|
||||
|
||||
check: test
|
||||
|
||||
test: all teststatic testshared
|
||||
|
||||
teststatic: static
|
||||
@TMPST=tmpst_$$; \
|
||||
if echo hello world | ./minigzip | ./minigzip -d && ./example $$TMPST ; then \
|
||||
echo ' *** zlib test OK ***'; \
|
||||
else \
|
||||
echo ' *** zlib test FAILED ***'; false; \
|
||||
fi; \
|
||||
rm -f $$TMPST
|
||||
|
||||
testshared: shared
|
||||
@LD_LIBRARY_PATH=`pwd`:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \
|
||||
LD_LIBRARYN32_PATH=`pwd`:$(LD_LIBRARYN32_PATH) ; export LD_LIBRARYN32_PATH; \
|
||||
DYLD_LIBRARY_PATH=`pwd`:$(DYLD_LIBRARY_PATH) ; export DYLD_LIBRARY_PATH; \
|
||||
SHLIB_PATH=`pwd`:$(SHLIB_PATH) ; export SHLIB_PATH; \
|
||||
TMPSH=tmpsh_$$; \
|
||||
if echo hello world | ./minigzipsh | ./minigzipsh -d && ./examplesh $$TMPSH; then \
|
||||
echo ' *** zlib shared test OK ***'; \
|
||||
else \
|
||||
echo ' *** zlib shared test FAILED ***'; false; \
|
||||
fi; \
|
||||
rm -f $$TMPSH
|
||||
|
||||
test64: all64
|
||||
@TMP64=tmp64_$$; \
|
||||
if echo hello world | ./minigzip64 | ./minigzip64 -d && ./example64 $$TMP64; then \
|
||||
echo ' *** zlib 64-bit test OK ***'; \
|
||||
else \
|
||||
echo ' *** zlib 64-bit test FAILED ***'; false; \
|
||||
fi; \
|
||||
rm -f $$TMP64
|
||||
|
||||
infcover.o: $(SRCDIR)test/infcover.c $(SRCDIR)zlib.h zconf.h
|
||||
$(CC) $(CFLAGS) $(ZINCOUT) -c -o $@ $(SRCDIR)test/infcover.c
|
||||
|
||||
infcover: infcover.o libz.a
|
||||
$(CC) $(CFLAGS) -o $@ infcover.o libz.a
|
||||
|
||||
cover: infcover
|
||||
rm -f *.gcda
|
||||
./infcover
|
||||
gcov inf*.c
|
||||
|
||||
libz.a: $(OBJS)
|
||||
$(AR) $(ARFLAGS) $@ $(OBJS)
|
||||
-@ ($(RANLIB) $@ || true) >/dev/null 2>&1
|
||||
|
||||
match.o: match.S
|
||||
$(CPP) match.S > _match.s
|
||||
$(CC) -c _match.s
|
||||
mv _match.o match.o
|
||||
rm -f _match.s
|
||||
|
||||
match.lo: match.S
|
||||
$(CPP) match.S > _match.s
|
||||
$(CC) -c -fPIC _match.s
|
||||
mv _match.o match.lo
|
||||
rm -f _match.s
|
||||
|
||||
example.o: $(SRCDIR)test/example.c $(SRCDIR)zlib.h zconf.h
|
||||
$(CC) $(CFLAGS) $(ZINCOUT) -c -o $@ $(SRCDIR)test/example.c
|
||||
|
||||
minigzip.o: $(SRCDIR)test/minigzip.c $(SRCDIR)zlib.h zconf.h
|
||||
$(CC) $(CFLAGS) $(ZINCOUT) -c -o $@ $(SRCDIR)test/minigzip.c
|
||||
|
||||
example64.o: $(SRCDIR)test/example.c $(SRCDIR)zlib.h zconf.h
|
||||
$(CC) $(CFLAGS) $(ZINCOUT) -D_FILE_OFFSET_BITS=64 -c -o $@ $(SRCDIR)test/example.c
|
||||
|
||||
minigzip64.o: $(SRCDIR)test/minigzip.c $(SRCDIR)zlib.h zconf.h
|
||||
$(CC) $(CFLAGS) $(ZINCOUT) -D_FILE_OFFSET_BITS=64 -c -o $@ $(SRCDIR)test/minigzip.c
|
||||
|
||||
|
||||
adler32.o: $(SRCDIR)adler32.c
|
||||
$(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)adler32.c
|
||||
|
||||
crc32.o: $(SRCDIR)crc32.c
|
||||
$(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)crc32.c
|
||||
|
||||
deflate.o: $(SRCDIR)deflate.c
|
||||
$(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)deflate.c
|
||||
|
||||
infback.o: $(SRCDIR)infback.c
|
||||
$(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)infback.c
|
||||
|
||||
inffast.o: $(SRCDIR)inffast.c
|
||||
$(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)inffast.c
|
||||
|
||||
inflate.o: $(SRCDIR)inflate.c
|
||||
$(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)inflate.c
|
||||
|
||||
inftrees.o: $(SRCDIR)inftrees.c
|
||||
$(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)inftrees.c
|
||||
|
||||
trees.o: $(SRCDIR)trees.c
|
||||
$(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)trees.c
|
||||
|
||||
zutil.o: $(SRCDIR)zutil.c
|
||||
$(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)zutil.c
|
||||
|
||||
compress.o: $(SRCDIR)compress.c
|
||||
$(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)compress.c
|
||||
|
||||
uncompr.o: $(SRCDIR)uncompr.c
|
||||
$(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)uncompr.c
|
||||
|
||||
gzclose.o: $(SRCDIR)gzclose.c
|
||||
$(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)gzclose.c
|
||||
|
||||
gzlib.o: $(SRCDIR)gzlib.c
|
||||
$(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)gzlib.c
|
||||
|
||||
gzread.o: $(SRCDIR)gzread.c
|
||||
$(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)gzread.c
|
||||
|
||||
gzwrite.o: $(SRCDIR)gzwrite.c
|
||||
$(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)gzwrite.c
|
||||
|
||||
|
||||
adler32.lo: $(SRCDIR)adler32.c
|
||||
-@mkdir objs 2>/dev/null || test -d objs
|
||||
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/adler32.o $(SRCDIR)adler32.c
|
||||
-@mv objs/adler32.o $@
|
||||
|
||||
crc32.lo: $(SRCDIR)crc32.c
|
||||
-@mkdir objs 2>/dev/null || test -d objs
|
||||
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/crc32.o $(SRCDIR)crc32.c
|
||||
-@mv objs/crc32.o $@
|
||||
|
||||
deflate.lo: $(SRCDIR)deflate.c
|
||||
-@mkdir objs 2>/dev/null || test -d objs
|
||||
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/deflate.o $(SRCDIR)deflate.c
|
||||
-@mv objs/deflate.o $@
|
||||
|
||||
infback.lo: $(SRCDIR)infback.c
|
||||
-@mkdir objs 2>/dev/null || test -d objs
|
||||
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/infback.o $(SRCDIR)infback.c
|
||||
-@mv objs/infback.o $@
|
||||
|
||||
inffast.lo: $(SRCDIR)inffast.c
|
||||
-@mkdir objs 2>/dev/null || test -d objs
|
||||
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/inffast.o $(SRCDIR)inffast.c
|
||||
-@mv objs/inffast.o $@
|
||||
|
||||
inflate.lo: $(SRCDIR)inflate.c
|
||||
-@mkdir objs 2>/dev/null || test -d objs
|
||||
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/inflate.o $(SRCDIR)inflate.c
|
||||
-@mv objs/inflate.o $@
|
||||
|
||||
inftrees.lo: $(SRCDIR)inftrees.c
|
||||
-@mkdir objs 2>/dev/null || test -d objs
|
||||
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/inftrees.o $(SRCDIR)inftrees.c
|
||||
-@mv objs/inftrees.o $@
|
||||
|
||||
trees.lo: $(SRCDIR)trees.c
|
||||
-@mkdir objs 2>/dev/null || test -d objs
|
||||
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/trees.o $(SRCDIR)trees.c
|
||||
-@mv objs/trees.o $@
|
||||
|
||||
zutil.lo: $(SRCDIR)zutil.c
|
||||
-@mkdir objs 2>/dev/null || test -d objs
|
||||
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/zutil.o $(SRCDIR)zutil.c
|
||||
-@mv objs/zutil.o $@
|
||||
|
||||
compress.lo: $(SRCDIR)compress.c
|
||||
-@mkdir objs 2>/dev/null || test -d objs
|
||||
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/compress.o $(SRCDIR)compress.c
|
||||
-@mv objs/compress.o $@
|
||||
|
||||
uncompr.lo: $(SRCDIR)uncompr.c
|
||||
-@mkdir objs 2>/dev/null || test -d objs
|
||||
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/uncompr.o $(SRCDIR)uncompr.c
|
||||
-@mv objs/uncompr.o $@
|
||||
|
||||
gzclose.lo: $(SRCDIR)gzclose.c
|
||||
-@mkdir objs 2>/dev/null || test -d objs
|
||||
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/gzclose.o $(SRCDIR)gzclose.c
|
||||
-@mv objs/gzclose.o $@
|
||||
|
||||
gzlib.lo: $(SRCDIR)gzlib.c
|
||||
-@mkdir objs 2>/dev/null || test -d objs
|
||||
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/gzlib.o $(SRCDIR)gzlib.c
|
||||
-@mv objs/gzlib.o $@
|
||||
|
||||
gzread.lo: $(SRCDIR)gzread.c
|
||||
-@mkdir objs 2>/dev/null || test -d objs
|
||||
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/gzread.o $(SRCDIR)gzread.c
|
||||
-@mv objs/gzread.o $@
|
||||
|
||||
gzwrite.lo: $(SRCDIR)gzwrite.c
|
||||
-@mkdir objs 2>/dev/null || test -d objs
|
||||
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/gzwrite.o $(SRCDIR)gzwrite.c
|
||||
-@mv objs/gzwrite.o $@
|
||||
|
||||
|
||||
placebo $(SHAREDLIBV): $(PIC_OBJS) libz.a
|
||||
$(LDSHARED) $(SFLAGS) -o $@ $(PIC_OBJS) $(LDSHAREDLIBC) $(LDFLAGS)
|
||||
rm -f $(SHAREDLIB) $(SHAREDLIBM)
|
||||
ln -s $@ $(SHAREDLIB)
|
||||
ln -s $@ $(SHAREDLIBM)
|
||||
-@rmdir objs
|
||||
|
||||
example$(EXE): example.o $(STATICLIB)
|
||||
$(CC) $(CFLAGS) -o $@ example.o $(TEST_LDFLAGS)
|
||||
|
||||
minigzip$(EXE): minigzip.o $(STATICLIB)
|
||||
$(CC) $(CFLAGS) -o $@ minigzip.o $(TEST_LDFLAGS)
|
||||
|
||||
examplesh$(EXE): example.o $(SHAREDLIBV)
|
||||
$(CC) $(CFLAGS) -o $@ example.o -L. $(SHAREDLIBV)
|
||||
|
||||
minigzipsh$(EXE): minigzip.o $(SHAREDLIBV)
|
||||
$(CC) $(CFLAGS) -o $@ minigzip.o -L. $(SHAREDLIBV)
|
||||
|
||||
example64$(EXE): example64.o $(STATICLIB)
|
||||
$(CC) $(CFLAGS) -o $@ example64.o $(TEST_LDFLAGS)
|
||||
|
||||
minigzip64$(EXE): minigzip64.o $(STATICLIB)
|
||||
$(CC) $(CFLAGS) -o $@ minigzip64.o $(TEST_LDFLAGS)
|
||||
|
||||
install-libs: $(LIBS)
|
||||
-@if [ ! -d $(DESTDIR)$(exec_prefix) ]; then mkdir -p $(DESTDIR)$(exec_prefix); fi
|
||||
-@if [ ! -d $(DESTDIR)$(libdir) ]; then mkdir -p $(DESTDIR)$(libdir); fi
|
||||
-@if [ ! -d $(DESTDIR)$(sharedlibdir) ]; then mkdir -p $(DESTDIR)$(sharedlibdir); fi
|
||||
-@if [ ! -d $(DESTDIR)$(man3dir) ]; then mkdir -p $(DESTDIR)$(man3dir); fi
|
||||
-@if [ ! -d $(DESTDIR)$(pkgconfigdir) ]; then mkdir -p $(DESTDIR)$(pkgconfigdir); fi
|
||||
rm -f $(DESTDIR)$(libdir)/$(STATICLIB)
|
||||
cp $(STATICLIB) $(DESTDIR)$(libdir)
|
||||
chmod 644 $(DESTDIR)$(libdir)/$(STATICLIB)
|
||||
-@($(RANLIB) $(DESTDIR)$(libdir)/libz.a || true) >/dev/null 2>&1
|
||||
-@if test -n "$(SHAREDLIBV)"; then \
|
||||
rm -f $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBV); \
|
||||
cp $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir); \
|
||||
echo "cp $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)"; \
|
||||
chmod 755 $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBV); \
|
||||
echo "chmod 755 $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBV)"; \
|
||||
rm -f $(DESTDIR)$(sharedlibdir)/$(SHAREDLIB) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBM); \
|
||||
ln -s $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIB); \
|
||||
ln -s $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBM); \
|
||||
($(LDCONFIG) || true) >/dev/null 2>&1; \
|
||||
fi
|
||||
rm -f $(DESTDIR)$(man3dir)/zlib.3
|
||||
cp $(SRCDIR)zlib.3 $(DESTDIR)$(man3dir)
|
||||
chmod 644 $(DESTDIR)$(man3dir)/zlib.3
|
||||
rm -f $(DESTDIR)$(pkgconfigdir)/zlib.pc
|
||||
cp zlib.pc $(DESTDIR)$(pkgconfigdir)
|
||||
chmod 644 $(DESTDIR)$(pkgconfigdir)/zlib.pc
|
||||
# The ranlib in install is needed on NeXTSTEP which checks file times
|
||||
# ldconfig is for Linux
|
||||
|
||||
install: install-libs
|
||||
-@if [ ! -d $(DESTDIR)$(includedir) ]; then mkdir -p $(DESTDIR)$(includedir); fi
|
||||
rm -f $(DESTDIR)$(includedir)/zlib.h $(DESTDIR)$(includedir)/zconf.h
|
||||
cp $(SRCDIR)zlib.h zconf.h $(DESTDIR)$(includedir)
|
||||
chmod 644 $(DESTDIR)$(includedir)/zlib.h $(DESTDIR)$(includedir)/zconf.h
|
||||
|
||||
uninstall:
|
||||
cd $(DESTDIR)$(includedir) && rm -f zlib.h zconf.h
|
||||
cd $(DESTDIR)$(libdir) && rm -f libz.a; \
|
||||
if test -n "$(SHAREDLIBV)" -a -f $(SHAREDLIBV); then \
|
||||
rm -f $(SHAREDLIBV) $(SHAREDLIB) $(SHAREDLIBM); \
|
||||
fi
|
||||
cd $(DESTDIR)$(man3dir) && rm -f zlib.3
|
||||
cd $(DESTDIR)$(pkgconfigdir) && rm -f zlib.pc
|
||||
|
||||
docs: zlib.3.pdf
|
||||
|
||||
zlib.3.pdf: $(SRCDIR)zlib.3
|
||||
groff -mandoc -f H -T ps $(SRCDIR)zlib.3 | ps2pdf - $@
|
||||
|
||||
zconf.h.cmakein: $(SRCDIR)zconf.h.in
|
||||
-@ TEMPFILE=zconfh_$$; \
|
||||
echo "/#define ZCONF_H/ a\\\\\n#cmakedefine Z_PREFIX\\\\\n#cmakedefine Z_HAVE_UNISTD_H\n" >> $$TEMPFILE &&\
|
||||
sed -f $$TEMPFILE $(SRCDIR)zconf.h.in > $@ &&\
|
||||
touch -r $(SRCDIR)zconf.h.in $@ &&\
|
||||
rm $$TEMPFILE
|
||||
|
||||
zconf: $(SRCDIR)zconf.h.in
|
||||
cp -p $(SRCDIR)zconf.h.in zconf.h
|
||||
|
||||
mostlyclean: clean
|
||||
clean:
|
||||
rm -f *.o *.lo *~ \
|
||||
example$(EXE) minigzip$(EXE) examplesh$(EXE) minigzipsh$(EXE) \
|
||||
example64$(EXE) minigzip64$(EXE) \
|
||||
infcover \
|
||||
libz.* foo.gz so_locations \
|
||||
_match.s maketree contrib/infback9/*.o
|
||||
rm -rf objs
|
||||
rm -f *.gcda *.gcno *.gcov
|
||||
rm -f contrib/infback9/*.gcda contrib/infback9/*.gcno contrib/infback9/*.gcov
|
||||
|
||||
maintainer-clean: distclean
|
||||
distclean: clean zconf zconf.h.cmakein docs
|
||||
rm -f Makefile zlib.pc configure.log
|
||||
-@rm -f .DS_Store
|
||||
@if [ -f Makefile.in ]; then \
|
||||
printf 'all:\n\t-@echo "Please use ./configure first. Thank you."\n' > Makefile ; \
|
||||
printf '\ndistclean:\n\tmake -f Makefile.in distclean\n' >> Makefile ; \
|
||||
touch -r $(SRCDIR)Makefile.in Makefile ; fi
|
||||
@if [ ! -f zconf.h.in ]; then rm -f zconf.h zconf.h.cmakein ; fi
|
||||
@if [ ! -f zlib.3 ]; then rm -f zlib.3.pdf ; fi
|
||||
|
||||
tags:
|
||||
etags $(SRCDIR)*.[ch]
|
||||
|
||||
adler32.o zutil.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h
|
||||
gzclose.o gzlib.o gzread.o gzwrite.o: $(SRCDIR)zlib.h zconf.h $(SRCDIR)gzguts.h
|
||||
compress.o example.o minigzip.o uncompr.o: $(SRCDIR)zlib.h zconf.h
|
||||
crc32.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)crc32.h
|
||||
deflate.o: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h
|
||||
infback.o inflate.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h $(SRCDIR)inffixed.h
|
||||
inffast.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h
|
||||
inftrees.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h
|
||||
trees.o: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)trees.h
|
||||
|
||||
adler32.lo zutil.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h
|
||||
gzclose.lo gzlib.lo gzread.lo gzwrite.lo: $(SRCDIR)zlib.h zconf.h $(SRCDIR)gzguts.h
|
||||
compress.lo example.lo minigzip.lo uncompr.lo: $(SRCDIR)zlib.h zconf.h
|
||||
crc32.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)crc32.h
|
||||
deflate.lo: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h
|
||||
infback.lo inflate.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h $(SRCDIR)inffixed.h
|
||||
inffast.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h
|
||||
inftrees.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h
|
||||
trees.lo: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)trees.h
|
115
third_party/zlib/README
vendored
115
third_party/zlib/README
vendored
@ -1,115 +0,0 @@
|
||||
ZLIB DATA COMPRESSION LIBRARY
|
||||
|
||||
zlib 1.2.11 is a general purpose data compression library. All the code is
|
||||
thread safe. The data format used by the zlib library is described by RFCs
|
||||
(Request for Comments) 1950 to 1952 in the files
|
||||
http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and
|
||||
rfc1952 (gzip format).
|
||||
|
||||
All functions of the compression library are documented in the file zlib.h
|
||||
(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example
|
||||
of the library is given in the file test/example.c which also tests that
|
||||
the library is working correctly. Another example is given in the file
|
||||
test/minigzip.c. The compression library itself is composed of all source
|
||||
files in the root directory.
|
||||
|
||||
To compile all files and run the test program, follow the instructions given at
|
||||
the top of Makefile.in. In short "./configure; make test", and if that goes
|
||||
well, "make install" should work for most flavors of Unix. For Windows, use
|
||||
one of the special makefiles in win32/ or contrib/vstudio/ . For VMS, use
|
||||
make_vms.com.
|
||||
|
||||
Questions about zlib should be sent to <zlib@gzip.org>, or to Gilles Vollant
|
||||
<info@winimage.com> for the Windows DLL version. The zlib home page is
|
||||
http://zlib.net/ . Before reporting a problem, please check this site to
|
||||
verify that you have the latest version of zlib; otherwise get the latest
|
||||
version and check whether the problem still exists or not.
|
||||
|
||||
PLEASE read the zlib FAQ http://zlib.net/zlib_faq.html before asking for help.
|
||||
|
||||
Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan. 1997
|
||||
issue of Dr. Dobb's Journal; a copy of the article is available at
|
||||
http://marknelson.us/1997/01/01/zlib-engine/ .
|
||||
|
||||
The changes made in version 1.2.11 are documented in the file ChangeLog.
|
||||
|
||||
Unsupported third party contributions are provided in directory contrib/ .
|
||||
|
||||
zlib is available in Java using the java.util.zip package, documented at
|
||||
http://java.sun.com/developer/technicalArticles/Programming/compression/ .
|
||||
|
||||
A Perl interface to zlib written by Paul Marquess <pmqs@cpan.org> is available
|
||||
at CPAN (Comprehensive Perl Archive Network) sites, including
|
||||
http://search.cpan.org/~pmqs/IO-Compress-Zlib/ .
|
||||
|
||||
A Python interface to zlib written by A.M. Kuchling <amk@amk.ca> is
|
||||
available in Python 1.5 and later versions, see
|
||||
http://docs.python.org/library/zlib.html .
|
||||
|
||||
zlib is built into tcl: http://wiki.tcl.tk/4610 .
|
||||
|
||||
An experimental package to read and write files in .zip format, written on top
|
||||
of zlib by Gilles Vollant <info@winimage.com>, is available in the
|
||||
contrib/minizip directory of zlib.
|
||||
|
||||
|
||||
Notes for some targets:
|
||||
|
||||
- For Windows DLL versions, please see win32/DLL_FAQ.txt
|
||||
|
||||
- For 64-bit Irix, deflate.c must be compiled without any optimization. With
|
||||
-O, one libpng test fails. The test works in 32 bit mode (with the -n32
|
||||
compiler flag). The compiler bug has been reported to SGI.
|
||||
|
||||
- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works
|
||||
when compiled with cc.
|
||||
|
||||
- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is
|
||||
necessary to get gzprintf working correctly. This is done by configure.
|
||||
|
||||
- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with
|
||||
other compilers. Use "make test" to check your compiler.
|
||||
|
||||
- gzdopen is not supported on RISCOS or BEOS.
|
||||
|
||||
- For PalmOs, see http://palmzlib.sourceforge.net/
|
||||
|
||||
|
||||
Acknowledgments:
|
||||
|
||||
The deflate format used by zlib was defined by Phil Katz. The deflate and
|
||||
zlib specifications were written by L. Peter Deutsch. Thanks to all the
|
||||
people who reported problems and suggested various improvements in zlib; they
|
||||
are too numerous to cite here.
|
||||
|
||||
Copyright notice:
|
||||
|
||||
(C) 1995-2017 Jean-loup Gailly and Mark Adler
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Jean-loup Gailly Mark Adler
|
||||
jloup@gzip.org madler@alumni.caltech.edu
|
||||
|
||||
If you use the zlib library in a product, we would appreciate *not* receiving
|
||||
lengthy legal documents to sign. The sources are provided for free but without
|
||||
warranty of any kind. The library has been entirely written by Jean-loup
|
||||
Gailly and Mark Adler; it does not include third-party code.
|
||||
|
||||
If you redistribute modified sources, we would appreciate that you include in
|
||||
the file ChangeLog history information documenting your changes. Please read
|
||||
the FAQ for more information on the distribution of modified source versions.
|
186
third_party/zlib/adler32.c
vendored
186
third_party/zlib/adler32.c
vendored
@ -1,186 +0,0 @@
|
||||
/* adler32.c -- compute the Adler-32 checksum of a data stream
|
||||
* Copyright (C) 1995-2011, 2016 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#include "zutil.h"
|
||||
|
||||
local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2));
|
||||
|
||||
#define BASE 65521U /* 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 --
|
||||
try it both ways to see which is faster */
|
||||
#ifdef NO_DIVIDE
|
||||
/* note that this assumes BASE is 65521, where 65536 % 65521 == 15
|
||||
(thank you to John Reiser for pointing this out) */
|
||||
# define CHOP(a) \
|
||||
do { \
|
||||
unsigned long tmp = a >> 16; \
|
||||
a &= 0xffffUL; \
|
||||
a += (tmp << 4) - tmp; \
|
||||
} while (0)
|
||||
# define MOD28(a) \
|
||||
do { \
|
||||
CHOP(a); \
|
||||
if (a >= BASE) a -= BASE; \
|
||||
} while (0)
|
||||
# define MOD(a) \
|
||||
do { \
|
||||
CHOP(a); \
|
||||
MOD28(a); \
|
||||
} while (0)
|
||||
# define MOD63(a) \
|
||||
do { /* this assumes a is not negative */ \
|
||||
z_off64_t tmp = a >> 32; \
|
||||
a &= 0xffffffffL; \
|
||||
a += (tmp << 8) - (tmp << 5) + tmp; \
|
||||
tmp = a >> 16; \
|
||||
a &= 0xffffL; \
|
||||
a += (tmp << 4) - tmp; \
|
||||
tmp = a >> 16; \
|
||||
a &= 0xffffL; \
|
||||
a += (tmp << 4) - tmp; \
|
||||
if (a >= BASE) a -= BASE; \
|
||||
} while (0)
|
||||
#else
|
||||
# define MOD(a) a %= BASE
|
||||
# define MOD28(a) a %= BASE
|
||||
# define MOD63(a) a %= BASE
|
||||
#endif
|
||||
|
||||
/* ========================================================================= */
|
||||
uLong ZEXPORT adler32_z(adler, buf, len)
|
||||
uLong adler;
|
||||
const Bytef *buf;
|
||||
z_size_t 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;
|
||||
MOD28(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);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
uLong ZEXPORT adler32(adler, buf, len)
|
||||
uLong adler;
|
||||
const Bytef *buf;
|
||||
uInt len;
|
||||
{
|
||||
return adler32_z(adler, buf, len);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
local uLong adler32_combine_(adler1, adler2, len2)
|
||||
uLong adler1;
|
||||
uLong adler2;
|
||||
z_off64_t len2;
|
||||
{
|
||||
unsigned long sum1;
|
||||
unsigned long sum2;
|
||||
unsigned rem;
|
||||
|
||||
/* for negative len, return invalid adler32 as a clue for debugging */
|
||||
if (len2 < 0)
|
||||
return 0xffffffffUL;
|
||||
|
||||
/* the derivation of this formula is left as an exercise for the reader */
|
||||
MOD63(len2); /* assumes len2 >= 0 */
|
||||
rem = (unsigned)len2;
|
||||
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 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)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);
|
||||
}
|
69
third_party/zlib/amiga/Makefile.pup
vendored
69
third_party/zlib/amiga/Makefile.pup
vendored
@ -1,69 +0,0 @@
|
||||
# Amiga powerUP (TM) Makefile
|
||||
# makefile for libpng and SAS C V6.58/7.00 PPC compiler
|
||||
# Copyright (C) 1998 by Andreas R. Kleinert
|
||||
|
||||
LIBNAME = libzip.a
|
||||
|
||||
CC = scppc
|
||||
CFLAGS = NOSTKCHK NOSINT OPTIMIZE OPTGO OPTPEEP OPTINLOCAL OPTINL \
|
||||
OPTLOOP OPTRDEP=8 OPTDEP=8 OPTCOMP=8 NOVER
|
||||
AR = ppc-amigaos-ar cr
|
||||
RANLIB = ppc-amigaos-ranlib
|
||||
LD = ppc-amigaos-ld -r
|
||||
LDFLAGS = -o
|
||||
LDLIBS = LIB:scppc.a LIB:end.o
|
||||
RM = delete quiet
|
||||
|
||||
OBJS = adler32.o compress.o crc32.o gzclose.o gzlib.o gzread.o gzwrite.o \
|
||||
uncompr.o deflate.o trees.o zutil.o inflate.o infback.o inftrees.o inffast.o
|
||||
|
||||
TEST_OBJS = example.o minigzip.o
|
||||
|
||||
all: example minigzip
|
||||
|
||||
check: test
|
||||
test: all
|
||||
example
|
||||
echo hello world | minigzip | minigzip -d
|
||||
|
||||
$(LIBNAME): $(OBJS)
|
||||
$(AR) $@ $(OBJS)
|
||||
-$(RANLIB) $@
|
||||
|
||||
example: example.o $(LIBNAME)
|
||||
$(LD) $(LDFLAGS) $@ LIB:c_ppc.o $@.o $(LIBNAME) $(LDLIBS)
|
||||
|
||||
minigzip: minigzip.o $(LIBNAME)
|
||||
$(LD) $(LDFLAGS) $@ LIB:c_ppc.o $@.o $(LIBNAME) $(LDLIBS)
|
||||
|
||||
mostlyclean: clean
|
||||
clean:
|
||||
$(RM) *.o example minigzip $(LIBNAME) foo.gz
|
||||
|
||||
zip:
|
||||
zip -ul9 zlib README ChangeLog Makefile Make????.??? Makefile.?? \
|
||||
descrip.mms *.[ch]
|
||||
|
||||
tgz:
|
||||
cd ..; tar cfz zlib/zlib.tgz zlib/README zlib/ChangeLog zlib/Makefile \
|
||||
zlib/Make????.??? zlib/Makefile.?? zlib/descrip.mms zlib/*.[ch]
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
|
||||
adler32.o: zlib.h zconf.h
|
||||
compress.o: zlib.h zconf.h
|
||||
crc32.o: crc32.h zlib.h zconf.h
|
||||
deflate.o: deflate.h zutil.h zlib.h zconf.h
|
||||
example.o: zlib.h zconf.h
|
||||
gzclose.o: zlib.h zconf.h gzguts.h
|
||||
gzlib.o: zlib.h zconf.h gzguts.h
|
||||
gzread.o: zlib.h zconf.h gzguts.h
|
||||
gzwrite.o: zlib.h zconf.h gzguts.h
|
||||
inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
inftrees.o: zutil.h zlib.h zconf.h inftrees.h
|
||||
minigzip.o: zlib.h zconf.h
|
||||
trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
|
||||
uncompr.o: zlib.h zconf.h
|
||||
zutil.o: zutil.h zlib.h zconf.h
|
68
third_party/zlib/amiga/Makefile.sas
vendored
68
third_party/zlib/amiga/Makefile.sas
vendored
@ -1,68 +0,0 @@
|
||||
# SMakefile for zlib
|
||||
# Modified from the standard UNIX Makefile Copyright Jean-loup Gailly
|
||||
# Osma Ahvenlampi <Osma.Ahvenlampi@hut.fi>
|
||||
# Amiga, SAS/C 6.56 & Smake
|
||||
|
||||
CC=sc
|
||||
CFLAGS=OPT
|
||||
#CFLAGS=OPT CPU=68030
|
||||
#CFLAGS=DEBUG=LINE
|
||||
LDFLAGS=LIB z.lib
|
||||
|
||||
SCOPTIONS=OPTSCHED OPTINLINE OPTALIAS OPTTIME OPTINLOCAL STRMERGE \
|
||||
NOICONS PARMS=BOTH NOSTACKCHECK UTILLIB NOVERSION ERRORREXX \
|
||||
DEF=POSTINC
|
||||
|
||||
OBJS = adler32.o compress.o crc32.o gzclose.o gzlib.o gzread.o gzwrite.o \
|
||||
uncompr.o deflate.o trees.o zutil.o inflate.o infback.o inftrees.o inffast.o
|
||||
|
||||
TEST_OBJS = example.o minigzip.o
|
||||
|
||||
all: SCOPTIONS example minigzip
|
||||
|
||||
check: test
|
||||
test: all
|
||||
example
|
||||
echo hello world | minigzip | minigzip -d
|
||||
|
||||
install: z.lib
|
||||
copy clone zlib.h zconf.h INCLUDE:
|
||||
copy clone z.lib LIB:
|
||||
|
||||
z.lib: $(OBJS)
|
||||
oml z.lib r $(OBJS)
|
||||
|
||||
example: example.o z.lib
|
||||
$(CC) $(CFLAGS) LINK TO $@ example.o $(LDFLAGS)
|
||||
|
||||
minigzip: minigzip.o z.lib
|
||||
$(CC) $(CFLAGS) LINK TO $@ minigzip.o $(LDFLAGS)
|
||||
|
||||
mostlyclean: clean
|
||||
clean:
|
||||
-delete force quiet example minigzip *.o z.lib foo.gz *.lnk SCOPTIONS
|
||||
|
||||
SCOPTIONS: Makefile.sas
|
||||
copy to $@ <from <
|
||||
$(SCOPTIONS)
|
||||
<
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
|
||||
adler32.o: zlib.h zconf.h
|
||||
compress.o: zlib.h zconf.h
|
||||
crc32.o: crc32.h zlib.h zconf.h
|
||||
deflate.o: deflate.h zutil.h zlib.h zconf.h
|
||||
example.o: zlib.h zconf.h
|
||||
gzclose.o: zlib.h zconf.h gzguts.h
|
||||
gzlib.o: zlib.h zconf.h gzguts.h
|
||||
gzread.o: zlib.h zconf.h gzguts.h
|
||||
gzwrite.o: zlib.h zconf.h gzguts.h
|
||||
inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
inftrees.o: zutil.h zlib.h zconf.h inftrees.h
|
||||
minigzip.o: zlib.h zconf.h
|
||||
trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
|
||||
uncompr.o: zlib.h zconf.h
|
||||
zutil.o: zutil.h zlib.h zconf.h
|
86
third_party/zlib/compress.c
vendored
86
third_party/zlib/compress.c
vendored
@ -1,86 +0,0 @@
|
||||
/* compress.c -- compress a memory buffer
|
||||
* Copyright (C) 1995-2005, 2014, 2016 Jean-loup Gailly, Mark Adler
|
||||
* 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;
|
||||
const uInt max = (uInt)-1;
|
||||
uLong left;
|
||||
|
||||
left = *destLen;
|
||||
*destLen = 0;
|
||||
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
stream.opaque = (voidpf)0;
|
||||
|
||||
err = deflateInit(&stream, level);
|
||||
if (err != Z_OK) return err;
|
||||
|
||||
stream.next_out = dest;
|
||||
stream.avail_out = 0;
|
||||
stream.next_in = (z_const Bytef *)source;
|
||||
stream.avail_in = 0;
|
||||
|
||||
do {
|
||||
if (stream.avail_out == 0) {
|
||||
stream.avail_out = left > (uLong)max ? max : (uInt)left;
|
||||
left -= stream.avail_out;
|
||||
}
|
||||
if (stream.avail_in == 0) {
|
||||
stream.avail_in = sourceLen > (uLong)max ? max : (uInt)sourceLen;
|
||||
sourceLen -= stream.avail_in;
|
||||
}
|
||||
err = deflate(&stream, sourceLen ? Z_NO_FLUSH : Z_FINISH);
|
||||
} while (err == Z_OK);
|
||||
|
||||
*destLen = stream.total_out;
|
||||
deflateEnd(&stream);
|
||||
return err == Z_STREAM_END ? Z_OK : 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;
|
||||
}
|
921
third_party/zlib/configure
vendored
921
third_party/zlib/configure
vendored
@ -1,921 +0,0 @@
|
||||
#!/bin/sh
|
||||
# configure script for zlib.
|
||||
#
|
||||
# Normally configure builds both a static and a shared library.
|
||||
# If you want to build just a static library, use: ./configure --static
|
||||
#
|
||||
# To impose specific compiler or flags or install directory, use for example:
|
||||
# prefix=$HOME CC=cc CFLAGS="-O4" ./configure
|
||||
# or for csh/tcsh users:
|
||||
# (setenv prefix $HOME; setenv CC cc; setenv CFLAGS "-O4"; ./configure)
|
||||
|
||||
# Incorrect settings of CC or CFLAGS may prevent creating a shared library.
|
||||
# If you have problems, try without defining CC and CFLAGS before reporting
|
||||
# an error.
|
||||
|
||||
# start off configure.log
|
||||
echo -------------------- >> configure.log
|
||||
echo $0 $* >> configure.log
|
||||
date >> configure.log
|
||||
|
||||
# get source directory
|
||||
SRCDIR=`dirname $0`
|
||||
if test $SRCDIR = "."; then
|
||||
ZINC=""
|
||||
ZINCOUT="-I."
|
||||
SRCDIR=""
|
||||
else
|
||||
ZINC='-include zconf.h'
|
||||
ZINCOUT='-I. -I$(SRCDIR)'
|
||||
SRCDIR="$SRCDIR/"
|
||||
fi
|
||||
|
||||
# set command prefix for cross-compilation
|
||||
if [ -n "${CHOST}" ]; then
|
||||
uname="`echo "${CHOST}" | sed -e 's/^[^-]*-\([^-]*\)$/\1/' -e 's/^[^-]*-[^-]*-\([^-]*\)$/\1/' -e 's/^[^-]*-[^-]*-\([^-]*\)-.*$/\1/'`"
|
||||
CROSS_PREFIX="${CHOST}-"
|
||||
fi
|
||||
|
||||
# destination name for static library
|
||||
STATICLIB=libz.a
|
||||
|
||||
# extract zlib version numbers from zlib.h
|
||||
VER=`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < ${SRCDIR}zlib.h`
|
||||
VER3=`sed -n -e '/VERSION "/s/.*"\([0-9]*\\.[0-9]*\\.[0-9]*\).*/\1/p' < ${SRCDIR}zlib.h`
|
||||
VER2=`sed -n -e '/VERSION "/s/.*"\([0-9]*\\.[0-9]*\)\\..*/\1/p' < ${SRCDIR}zlib.h`
|
||||
VER1=`sed -n -e '/VERSION "/s/.*"\([0-9]*\)\\..*/\1/p' < ${SRCDIR}zlib.h`
|
||||
|
||||
# establish commands for library building
|
||||
if "${CROSS_PREFIX}ar" --version >/dev/null 2>/dev/null || test $? -lt 126; then
|
||||
AR=${AR-"${CROSS_PREFIX}ar"}
|
||||
test -n "${CROSS_PREFIX}" && echo Using ${AR} | tee -a configure.log
|
||||
else
|
||||
AR=${AR-"ar"}
|
||||
test -n "${CROSS_PREFIX}" && echo Using ${AR} | tee -a configure.log
|
||||
fi
|
||||
ARFLAGS=${ARFLAGS-"rc"}
|
||||
if "${CROSS_PREFIX}ranlib" --version >/dev/null 2>/dev/null || test $? -lt 126; then
|
||||
RANLIB=${RANLIB-"${CROSS_PREFIX}ranlib"}
|
||||
test -n "${CROSS_PREFIX}" && echo Using ${RANLIB} | tee -a configure.log
|
||||
else
|
||||
RANLIB=${RANLIB-"ranlib"}
|
||||
fi
|
||||
if "${CROSS_PREFIX}nm" --version >/dev/null 2>/dev/null || test $? -lt 126; then
|
||||
NM=${NM-"${CROSS_PREFIX}nm"}
|
||||
test -n "${CROSS_PREFIX}" && echo Using ${NM} | tee -a configure.log
|
||||
else
|
||||
NM=${NM-"nm"}
|
||||
fi
|
||||
|
||||
# set defaults before processing command line options
|
||||
LDCONFIG=${LDCONFIG-"ldconfig"}
|
||||
LDSHAREDLIBC="${LDSHAREDLIBC--lc}"
|
||||
ARCHS=
|
||||
prefix=${prefix-/usr/local}
|
||||
exec_prefix=${exec_prefix-'${prefix}'}
|
||||
libdir=${libdir-'${exec_prefix}/lib'}
|
||||
sharedlibdir=${sharedlibdir-'${libdir}'}
|
||||
includedir=${includedir-'${prefix}/include'}
|
||||
mandir=${mandir-'${prefix}/share/man'}
|
||||
shared_ext='.so'
|
||||
shared=1
|
||||
solo=0
|
||||
cover=0
|
||||
zprefix=0
|
||||
zconst=0
|
||||
build64=0
|
||||
gcc=0
|
||||
warn=0
|
||||
debug=0
|
||||
old_cc="$CC"
|
||||
old_cflags="$CFLAGS"
|
||||
OBJC='$(OBJZ) $(OBJG)'
|
||||
PIC_OBJC='$(PIC_OBJZ) $(PIC_OBJG)'
|
||||
|
||||
# leave this script, optionally in a bad way
|
||||
leave()
|
||||
{
|
||||
if test "$*" != "0"; then
|
||||
echo "** $0 aborting." | tee -a configure.log
|
||||
fi
|
||||
rm -f $test.[co] $test $test$shared_ext $test.gcno ./--version
|
||||
echo -------------------- >> configure.log
|
||||
echo >> configure.log
|
||||
echo >> configure.log
|
||||
exit $1
|
||||
}
|
||||
|
||||
# process command line options
|
||||
while test $# -ge 1
|
||||
do
|
||||
case "$1" in
|
||||
-h* | --help)
|
||||
echo 'usage:' | tee -a configure.log
|
||||
echo ' configure [--const] [--zprefix] [--prefix=PREFIX] [--eprefix=EXPREFIX]' | tee -a configure.log
|
||||
echo ' [--static] [--64] [--libdir=LIBDIR] [--sharedlibdir=LIBDIR]' | tee -a configure.log
|
||||
echo ' [--includedir=INCLUDEDIR] [--archs="-arch i386 -arch x86_64"]' | tee -a configure.log
|
||||
exit 0 ;;
|
||||
-p*=* | --prefix=*) prefix=`echo $1 | sed 's/.*=//'`; shift ;;
|
||||
-e*=* | --eprefix=*) exec_prefix=`echo $1 | sed 's/.*=//'`; shift ;;
|
||||
-l*=* | --libdir=*) libdir=`echo $1 | sed 's/.*=//'`; shift ;;
|
||||
--sharedlibdir=*) sharedlibdir=`echo $1 | sed 's/.*=//'`; shift ;;
|
||||
-i*=* | --includedir=*) includedir=`echo $1 | sed 's/.*=//'`;shift ;;
|
||||
-u*=* | --uname=*) uname=`echo $1 | sed 's/.*=//'`;shift ;;
|
||||
-p* | --prefix) prefix="$2"; shift; shift ;;
|
||||
-e* | --eprefix) exec_prefix="$2"; shift; shift ;;
|
||||
-l* | --libdir) libdir="$2"; shift; shift ;;
|
||||
-i* | --includedir) includedir="$2"; shift; shift ;;
|
||||
-s* | --shared | --enable-shared) shared=1; shift ;;
|
||||
-t | --static) shared=0; shift ;;
|
||||
--solo) solo=1; shift ;;
|
||||
--cover) cover=1; shift ;;
|
||||
-z* | --zprefix) zprefix=1; shift ;;
|
||||
-6* | --64) build64=1; shift ;;
|
||||
-a*=* | --archs=*) ARCHS=`echo $1 | sed 's/.*=//'`; shift ;;
|
||||
--sysconfdir=*) echo "ignored option: --sysconfdir" | tee -a configure.log; shift ;;
|
||||
--localstatedir=*) echo "ignored option: --localstatedir" | tee -a configure.log; shift ;;
|
||||
-c* | --const) zconst=1; shift ;;
|
||||
-w* | --warn) warn=1; shift ;;
|
||||
-d* | --debug) debug=1; shift ;;
|
||||
*)
|
||||
echo "unknown option: $1" | tee -a configure.log
|
||||
echo "$0 --help for help" | tee -a configure.log
|
||||
leave 1;;
|
||||
esac
|
||||
done
|
||||
|
||||
# temporary file name
|
||||
test=ztest$$
|
||||
|
||||
# put arguments in log, also put test file in log if used in arguments
|
||||
show()
|
||||
{
|
||||
case "$*" in
|
||||
*$test.c*)
|
||||
echo === $test.c === >> configure.log
|
||||
cat $test.c >> configure.log
|
||||
echo === >> configure.log;;
|
||||
esac
|
||||
echo $* >> configure.log
|
||||
}
|
||||
|
||||
# check for gcc vs. cc and set compile and link flags based on the system identified by uname
|
||||
cat > $test.c <<EOF
|
||||
extern int getchar();
|
||||
int hello() {return getchar();}
|
||||
EOF
|
||||
|
||||
test -z "$CC" && echo Checking for ${CROSS_PREFIX}gcc... | tee -a configure.log
|
||||
cc=${CC-${CROSS_PREFIX}gcc}
|
||||
cflags=${CFLAGS-"-O3"}
|
||||
# to force the asm version use: CFLAGS="-O3 -DASMV" ./configure
|
||||
case "$cc" in
|
||||
*gcc*) gcc=1 ;;
|
||||
*clang*) gcc=1 ;;
|
||||
esac
|
||||
case `$cc -v 2>&1` in
|
||||
*gcc*) gcc=1 ;;
|
||||
*clang*) gcc=1 ;;
|
||||
esac
|
||||
|
||||
show $cc -c $test.c
|
||||
if test "$gcc" -eq 1 && ($cc -c $test.c) >> configure.log 2>&1; then
|
||||
echo ... using gcc >> configure.log
|
||||
CC="$cc"
|
||||
CFLAGS="${CFLAGS--O3}"
|
||||
SFLAGS="${CFLAGS--O3} -fPIC"
|
||||
if test "$ARCHS"; then
|
||||
CFLAGS="${CFLAGS} ${ARCHS}"
|
||||
LDFLAGS="${LDFLAGS} ${ARCHS}"
|
||||
fi
|
||||
if test $build64 -eq 1; then
|
||||
CFLAGS="${CFLAGS} -m64"
|
||||
SFLAGS="${SFLAGS} -m64"
|
||||
fi
|
||||
if test "$warn" -eq 1; then
|
||||
if test "$zconst" -eq 1; then
|
||||
CFLAGS="${CFLAGS} -Wall -Wextra -Wcast-qual -pedantic -DZLIB_CONST"
|
||||
else
|
||||
CFLAGS="${CFLAGS} -Wall -Wextra -pedantic"
|
||||
fi
|
||||
fi
|
||||
if test $debug -eq 1; then
|
||||
CFLAGS="${CFLAGS} -DZLIB_DEBUG"
|
||||
SFLAGS="${SFLAGS} -DZLIB_DEBUG"
|
||||
fi
|
||||
if test -z "$uname"; then
|
||||
uname=`(uname -s || echo unknown) 2>/dev/null`
|
||||
fi
|
||||
case "$uname" in
|
||||
Linux* | linux* | GNU | GNU/* | solaris*)
|
||||
LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1,--version-script,${SRCDIR}zlib.map"} ;;
|
||||
*BSD | *bsd* | DragonFly)
|
||||
LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1,--version-script,${SRCDIR}zlib.map"}
|
||||
LDCONFIG="ldconfig -m" ;;
|
||||
CYGWIN* | Cygwin* | cygwin* | OS/2*)
|
||||
EXE='.exe' ;;
|
||||
MINGW* | mingw*)
|
||||
# temporary bypass
|
||||
rm -f $test.[co] $test $test$shared_ext
|
||||
echo "Please use win32/Makefile.gcc instead." | tee -a configure.log
|
||||
leave 1
|
||||
LDSHARED=${LDSHARED-"$cc -shared"}
|
||||
LDSHAREDLIBC=""
|
||||
EXE='.exe' ;;
|
||||
QNX*) # This is for QNX6. I suppose that the QNX rule below is for QNX2,QNX4
|
||||
# (alain.bonnefoy@icbt.com)
|
||||
LDSHARED=${LDSHARED-"$cc -shared -Wl,-hlibz.so.1"} ;;
|
||||
HP-UX*)
|
||||
LDSHARED=${LDSHARED-"$cc -shared $SFLAGS"}
|
||||
case `(uname -m || echo unknown) 2>/dev/null` in
|
||||
ia64)
|
||||
shared_ext='.so'
|
||||
SHAREDLIB='libz.so' ;;
|
||||
*)
|
||||
shared_ext='.sl'
|
||||
SHAREDLIB='libz.sl' ;;
|
||||
esac ;;
|
||||
Darwin* | darwin*)
|
||||
shared_ext='.dylib'
|
||||
SHAREDLIB=libz$shared_ext
|
||||
SHAREDLIBV=libz.$VER$shared_ext
|
||||
SHAREDLIBM=libz.$VER1$shared_ext
|
||||
LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER3"}
|
||||
if libtool -V 2>&1 | grep Apple > /dev/null; then
|
||||
AR="libtool"
|
||||
else
|
||||
AR="/usr/bin/libtool"
|
||||
fi
|
||||
ARFLAGS="-o" ;;
|
||||
*) LDSHARED=${LDSHARED-"$cc -shared"} ;;
|
||||
esac
|
||||
else
|
||||
# find system name and corresponding cc options
|
||||
CC=${CC-cc}
|
||||
gcc=0
|
||||
echo ... using $CC >> configure.log
|
||||
if test -z "$uname"; then
|
||||
uname=`(uname -sr || echo unknown) 2>/dev/null`
|
||||
fi
|
||||
case "$uname" in
|
||||
HP-UX*) SFLAGS=${CFLAGS-"-O +z"}
|
||||
CFLAGS=${CFLAGS-"-O"}
|
||||
# LDSHARED=${LDSHARED-"ld -b +vnocompatwarnings"}
|
||||
LDSHARED=${LDSHARED-"ld -b"}
|
||||
case `(uname -m || echo unknown) 2>/dev/null` in
|
||||
ia64)
|
||||
shared_ext='.so'
|
||||
SHAREDLIB='libz.so' ;;
|
||||
*)
|
||||
shared_ext='.sl'
|
||||
SHAREDLIB='libz.sl' ;;
|
||||
esac ;;
|
||||
IRIX*) SFLAGS=${CFLAGS-"-ansi -O2 -rpath ."}
|
||||
CFLAGS=${CFLAGS-"-ansi -O2"}
|
||||
LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so.1"} ;;
|
||||
OSF1\ V4*) SFLAGS=${CFLAGS-"-O -std1"}
|
||||
CFLAGS=${CFLAGS-"-O -std1"}
|
||||
LDFLAGS="${LDFLAGS} -Wl,-rpath,."
|
||||
LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so -Wl,-msym -Wl,-rpath,$(libdir) -Wl,-set_version,${VER}:1.0"} ;;
|
||||
OSF1*) SFLAGS=${CFLAGS-"-O -std1"}
|
||||
CFLAGS=${CFLAGS-"-O -std1"}
|
||||
LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so.1"} ;;
|
||||
QNX*) SFLAGS=${CFLAGS-"-4 -O"}
|
||||
CFLAGS=${CFLAGS-"-4 -O"}
|
||||
LDSHARED=${LDSHARED-"cc"}
|
||||
RANLIB=${RANLIB-"true"}
|
||||
AR="cc"
|
||||
ARFLAGS="-A" ;;
|
||||
SCO_SV\ 3.2*) SFLAGS=${CFLAGS-"-O3 -dy -KPIC "}
|
||||
CFLAGS=${CFLAGS-"-O3"}
|
||||
LDSHARED=${LDSHARED-"cc -dy -KPIC -G"} ;;
|
||||
SunOS\ 5* | solaris*)
|
||||
LDSHARED=${LDSHARED-"cc -G -h libz$shared_ext.$VER1"}
|
||||
SFLAGS=${CFLAGS-"-fast -KPIC"}
|
||||
CFLAGS=${CFLAGS-"-fast"}
|
||||
if test $build64 -eq 1; then
|
||||
# old versions of SunPRO/Workshop/Studio don't support -m64,
|
||||
# but newer ones do. Check for it.
|
||||
flag64=`$CC -flags | egrep -- '^-m64'`
|
||||
if test x"$flag64" != x"" ; then
|
||||
CFLAGS="${CFLAGS} -m64"
|
||||
SFLAGS="${SFLAGS} -m64"
|
||||
else
|
||||
case `(uname -m || echo unknown) 2>/dev/null` in
|
||||
i86*)
|
||||
SFLAGS="$SFLAGS -xarch=amd64"
|
||||
CFLAGS="$CFLAGS -xarch=amd64" ;;
|
||||
*)
|
||||
SFLAGS="$SFLAGS -xarch=v9"
|
||||
CFLAGS="$CFLAGS -xarch=v9" ;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
if test -n "$ZINC"; then
|
||||
ZINC='-I- -I. -I$(SRCDIR)'
|
||||
fi
|
||||
;;
|
||||
SunOS\ 4*) SFLAGS=${CFLAGS-"-O2 -PIC"}
|
||||
CFLAGS=${CFLAGS-"-O2"}
|
||||
LDSHARED=${LDSHARED-"ld"} ;;
|
||||
SunStudio\ 9*) SFLAGS=${CFLAGS-"-fast -xcode=pic32 -xtarget=ultra3 -xarch=v9b"}
|
||||
CFLAGS=${CFLAGS-"-fast -xtarget=ultra3 -xarch=v9b"}
|
||||
LDSHARED=${LDSHARED-"cc -xarch=v9b"} ;;
|
||||
UNIX_System_V\ 4.2.0)
|
||||
SFLAGS=${CFLAGS-"-KPIC -O"}
|
||||
CFLAGS=${CFLAGS-"-O"}
|
||||
LDSHARED=${LDSHARED-"cc -G"} ;;
|
||||
UNIX_SV\ 4.2MP)
|
||||
SFLAGS=${CFLAGS-"-Kconform_pic -O"}
|
||||
CFLAGS=${CFLAGS-"-O"}
|
||||
LDSHARED=${LDSHARED-"cc -G"} ;;
|
||||
OpenUNIX\ 5)
|
||||
SFLAGS=${CFLAGS-"-KPIC -O"}
|
||||
CFLAGS=${CFLAGS-"-O"}
|
||||
LDSHARED=${LDSHARED-"cc -G"} ;;
|
||||
AIX*) # Courtesy of dbakker@arrayasolutions.com
|
||||
SFLAGS=${CFLAGS-"-O -qmaxmem=8192"}
|
||||
CFLAGS=${CFLAGS-"-O -qmaxmem=8192"}
|
||||
LDSHARED=${LDSHARED-"xlc -G"} ;;
|
||||
# send working options for other systems to zlib@gzip.org
|
||||
*) SFLAGS=${CFLAGS-"-O"}
|
||||
CFLAGS=${CFLAGS-"-O"}
|
||||
LDSHARED=${LDSHARED-"cc -shared"} ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# destination names for shared library if not defined above
|
||||
SHAREDLIB=${SHAREDLIB-"libz$shared_ext"}
|
||||
SHAREDLIBV=${SHAREDLIBV-"libz$shared_ext.$VER"}
|
||||
SHAREDLIBM=${SHAREDLIBM-"libz$shared_ext.$VER1"}
|
||||
|
||||
echo >> configure.log
|
||||
|
||||
# define functions for testing compiler and library characteristics and logging the results
|
||||
|
||||
cat > $test.c <<EOF
|
||||
#error error
|
||||
EOF
|
||||
if ($CC -c $CFLAGS $test.c) 2>/dev/null; then
|
||||
try()
|
||||
{
|
||||
show $*
|
||||
test "`( $* ) 2>&1 | tee -a configure.log`" = ""
|
||||
}
|
||||
echo - using any output from compiler to indicate an error >> configure.log
|
||||
else
|
||||
try()
|
||||
{
|
||||
show $*
|
||||
( $* ) >> configure.log 2>&1
|
||||
ret=$?
|
||||
if test $ret -ne 0; then
|
||||
echo "(exit code "$ret")" >> configure.log
|
||||
fi
|
||||
return $ret
|
||||
}
|
||||
fi
|
||||
|
||||
tryboth()
|
||||
{
|
||||
show $*
|
||||
got=`( $* ) 2>&1`
|
||||
ret=$?
|
||||
printf %s "$got" >> configure.log
|
||||
if test $ret -ne 0; then
|
||||
return $ret
|
||||
fi
|
||||
test "$got" = ""
|
||||
}
|
||||
|
||||
cat > $test.c << EOF
|
||||
int foo() { return 0; }
|
||||
EOF
|
||||
echo "Checking for obsessive-compulsive compiler options..." >> configure.log
|
||||
if try $CC -c $CFLAGS $test.c; then
|
||||
:
|
||||
else
|
||||
echo "Compiler error reporting is too harsh for $0 (perhaps remove -Werror)." | tee -a configure.log
|
||||
leave 1
|
||||
fi
|
||||
|
||||
echo >> configure.log
|
||||
|
||||
# see if shared library build supported
|
||||
cat > $test.c <<EOF
|
||||
extern int getchar();
|
||||
int hello() {return getchar();}
|
||||
EOF
|
||||
if test $shared -eq 1; then
|
||||
echo Checking for shared library support... | tee -a configure.log
|
||||
# we must test in two steps (cc then ld), required at least on SunOS 4.x
|
||||
if try $CC -w -c $SFLAGS $test.c &&
|
||||
try $LDSHARED $SFLAGS -o $test$shared_ext $test.o; then
|
||||
echo Building shared library $SHAREDLIBV with $CC. | tee -a configure.log
|
||||
elif test -z "$old_cc" -a -z "$old_cflags"; then
|
||||
echo No shared library support. | tee -a configure.log
|
||||
shared=0;
|
||||
else
|
||||
echo 'No shared library support; try without defining CC and CFLAGS' | tee -a configure.log
|
||||
shared=0;
|
||||
fi
|
||||
fi
|
||||
if test $shared -eq 0; then
|
||||
LDSHARED="$CC"
|
||||
ALL="static"
|
||||
TEST="all teststatic"
|
||||
SHAREDLIB=""
|
||||
SHAREDLIBV=""
|
||||
SHAREDLIBM=""
|
||||
echo Building static library $STATICLIB version $VER with $CC. | tee -a configure.log
|
||||
else
|
||||
ALL="static shared"
|
||||
TEST="all teststatic testshared"
|
||||
fi
|
||||
|
||||
# check for underscores in external names for use by assembler code
|
||||
CPP=${CPP-"$CC -E"}
|
||||
case $CFLAGS in
|
||||
*ASMV*)
|
||||
echo >> configure.log
|
||||
show "$NM $test.o | grep _hello"
|
||||
if test "`$NM $test.o | grep _hello | tee -a configure.log`" = ""; then
|
||||
CPP="$CPP -DNO_UNDERLINE"
|
||||
echo Checking for underline in external names... No. | tee -a configure.log
|
||||
else
|
||||
echo Checking for underline in external names... Yes. | tee -a configure.log
|
||||
fi ;;
|
||||
esac
|
||||
|
||||
echo >> configure.log
|
||||
|
||||
# check for size_t
|
||||
cat > $test.c <<EOF
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
size_t dummy = 0;
|
||||
EOF
|
||||
if try $CC -c $CFLAGS $test.c; then
|
||||
echo "Checking for size_t... Yes." | tee -a configure.log
|
||||
need_sizet=0
|
||||
else
|
||||
echo "Checking for size_t... No." | tee -a configure.log
|
||||
need_sizet=1
|
||||
fi
|
||||
|
||||
echo >> configure.log
|
||||
|
||||
# find the size_t integer type, if needed
|
||||
if test $need_sizet -eq 1; then
|
||||
cat > $test.c <<EOF
|
||||
long long dummy = 0;
|
||||
EOF
|
||||
if try $CC -c $CFLAGS $test.c; then
|
||||
echo "Checking for long long... Yes." | tee -a configure.log
|
||||
cat > $test.c <<EOF
|
||||
#include <stdio.h>
|
||||
int main(void) {
|
||||
if (sizeof(void *) <= sizeof(int)) puts("int");
|
||||
else if (sizeof(void *) <= sizeof(long)) puts("long");
|
||||
else puts("z_longlong");
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
else
|
||||
echo "Checking for long long... No." | tee -a configure.log
|
||||
cat > $test.c <<EOF
|
||||
#include <stdio.h>
|
||||
int main(void) {
|
||||
if (sizeof(void *) <= sizeof(int)) puts("int");
|
||||
else puts("long");
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
if try $CC $CFLAGS -o $test $test.c; then
|
||||
sizet=`./$test`
|
||||
echo "Checking for a pointer-size integer type..." $sizet"." | tee -a configure.log
|
||||
else
|
||||
echo "Failed to find a pointer-size integer type." | tee -a configure.log
|
||||
leave 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if test $need_sizet -eq 1; then
|
||||
CFLAGS="${CFLAGS} -DNO_SIZE_T=${sizet}"
|
||||
SFLAGS="${SFLAGS} -DNO_SIZE_T=${sizet}"
|
||||
fi
|
||||
|
||||
echo >> configure.log
|
||||
|
||||
# check for large file support, and if none, check for fseeko()
|
||||
cat > $test.c <<EOF
|
||||
#include <sys/types.h>
|
||||
off64_t dummy = 0;
|
||||
EOF
|
||||
if try $CC -c $CFLAGS -D_LARGEFILE64_SOURCE=1 $test.c; then
|
||||
CFLAGS="${CFLAGS} -D_LARGEFILE64_SOURCE=1"
|
||||
SFLAGS="${SFLAGS} -D_LARGEFILE64_SOURCE=1"
|
||||
ALL="${ALL} all64"
|
||||
TEST="${TEST} test64"
|
||||
echo "Checking for off64_t... Yes." | tee -a configure.log
|
||||
echo "Checking for fseeko... Yes." | tee -a configure.log
|
||||
else
|
||||
echo "Checking for off64_t... No." | tee -a configure.log
|
||||
echo >> configure.log
|
||||
cat > $test.c <<EOF
|
||||
#include <stdio.h>
|
||||
int main(void) {
|
||||
fseeko(NULL, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
if try $CC $CFLAGS -o $test $test.c; then
|
||||
echo "Checking for fseeko... Yes." | tee -a configure.log
|
||||
else
|
||||
CFLAGS="${CFLAGS} -DNO_FSEEKO"
|
||||
SFLAGS="${SFLAGS} -DNO_FSEEKO"
|
||||
echo "Checking for fseeko... No." | tee -a configure.log
|
||||
fi
|
||||
fi
|
||||
|
||||
echo >> configure.log
|
||||
|
||||
# check for strerror() for use by gz* functions
|
||||
cat > $test.c <<EOF
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
int main() { return strlen(strerror(errno)); }
|
||||
EOF
|
||||
if try $CC $CFLAGS -o $test $test.c; then
|
||||
echo "Checking for strerror... Yes." | tee -a configure.log
|
||||
else
|
||||
CFLAGS="${CFLAGS} -DNO_STRERROR"
|
||||
SFLAGS="${SFLAGS} -DNO_STRERROR"
|
||||
echo "Checking for strerror... No." | tee -a configure.log
|
||||
fi
|
||||
|
||||
# copy clean zconf.h for subsequent edits
|
||||
cp -p ${SRCDIR}zconf.h.in zconf.h
|
||||
|
||||
echo >> configure.log
|
||||
|
||||
# check for unistd.h and save result in zconf.h
|
||||
cat > $test.c <<EOF
|
||||
#include <unistd.h>
|
||||
int main() { return 0; }
|
||||
EOF
|
||||
if try $CC -c $CFLAGS $test.c; then
|
||||
sed < zconf.h "/^#ifdef HAVE_UNISTD_H.* may be/s/def HAVE_UNISTD_H\(.*\) may be/ 1\1 was/" > zconf.temp.h
|
||||
mv zconf.temp.h zconf.h
|
||||
echo "Checking for unistd.h... Yes." | tee -a configure.log
|
||||
else
|
||||
echo "Checking for unistd.h... No." | tee -a configure.log
|
||||
fi
|
||||
|
||||
echo >> configure.log
|
||||
|
||||
# check for stdarg.h and save result in zconf.h
|
||||
cat > $test.c <<EOF
|
||||
#include <stdarg.h>
|
||||
int main() { return 0; }
|
||||
EOF
|
||||
if try $CC -c $CFLAGS $test.c; then
|
||||
sed < zconf.h "/^#ifdef HAVE_STDARG_H.* may be/s/def HAVE_STDARG_H\(.*\) may be/ 1\1 was/" > zconf.temp.h
|
||||
mv zconf.temp.h zconf.h
|
||||
echo "Checking for stdarg.h... Yes." | tee -a configure.log
|
||||
else
|
||||
echo "Checking for stdarg.h... No." | tee -a configure.log
|
||||
fi
|
||||
|
||||
# if the z_ prefix was requested, save that in zconf.h
|
||||
if test $zprefix -eq 1; then
|
||||
sed < zconf.h "/#ifdef Z_PREFIX.* may be/s/def Z_PREFIX\(.*\) may be/ 1\1 was/" > zconf.temp.h
|
||||
mv zconf.temp.h zconf.h
|
||||
echo >> configure.log
|
||||
echo "Using z_ prefix on all symbols." | tee -a configure.log
|
||||
fi
|
||||
|
||||
# if --solo compilation was requested, save that in zconf.h and remove gz stuff from object lists
|
||||
if test $solo -eq 1; then
|
||||
sed '/#define ZCONF_H/a\
|
||||
#define Z_SOLO
|
||||
|
||||
' < zconf.h > zconf.temp.h
|
||||
mv zconf.temp.h zconf.h
|
||||
OBJC='$(OBJZ)'
|
||||
PIC_OBJC='$(PIC_OBJZ)'
|
||||
fi
|
||||
|
||||
# if code coverage testing was requested, use older gcc if defined, e.g. "gcc-4.2" on Mac OS X
|
||||
if test $cover -eq 1; then
|
||||
CFLAGS="${CFLAGS} -fprofile-arcs -ftest-coverage"
|
||||
if test -n "$GCC_CLASSIC"; then
|
||||
CC=$GCC_CLASSIC
|
||||
fi
|
||||
fi
|
||||
|
||||
echo >> configure.log
|
||||
|
||||
# conduct a series of tests to resolve eight possible cases of using "vs" or "s" printf functions
|
||||
# (using stdarg or not), with or without "n" (proving size of buffer), and with or without a
|
||||
# return value. The most secure result is vsnprintf() with a return value. snprintf() with a
|
||||
# return value is secure as well, but then gzprintf() will be limited to 20 arguments.
|
||||
cat > $test.c <<EOF
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include "zconf.h"
|
||||
int main()
|
||||
{
|
||||
#ifndef STDC
|
||||
choke me
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
if try $CC -c $CFLAGS $test.c; then
|
||||
echo "Checking whether to use vs[n]printf() or s[n]printf()... using vs[n]printf()." | tee -a configure.log
|
||||
|
||||
echo >> configure.log
|
||||
cat > $test.c <<EOF
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
int mytest(const char *fmt, ...)
|
||||
{
|
||||
char buf[20];
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
return 0;
|
||||
}
|
||||
int main()
|
||||
{
|
||||
return (mytest("Hello%d\n", 1));
|
||||
}
|
||||
EOF
|
||||
if try $CC $CFLAGS -o $test $test.c; then
|
||||
echo "Checking for vsnprintf() in stdio.h... Yes." | tee -a configure.log
|
||||
|
||||
echo >> configure.log
|
||||
cat >$test.c <<EOF
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
int mytest(const char *fmt, ...)
|
||||
{
|
||||
int n;
|
||||
char buf[20];
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
n = vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
return n;
|
||||
}
|
||||
int main()
|
||||
{
|
||||
return (mytest("Hello%d\n", 1));
|
||||
}
|
||||
EOF
|
||||
|
||||
if try $CC -c $CFLAGS $test.c; then
|
||||
echo "Checking for return value of vsnprintf()... Yes." | tee -a configure.log
|
||||
else
|
||||
CFLAGS="$CFLAGS -DHAS_vsnprintf_void"
|
||||
SFLAGS="$SFLAGS -DHAS_vsnprintf_void"
|
||||
echo "Checking for return value of vsnprintf()... No." | tee -a configure.log
|
||||
echo " WARNING: apparently vsnprintf() does not return a value. zlib" | tee -a configure.log
|
||||
echo " can build but will be open to possible string-format security" | tee -a configure.log
|
||||
echo " vulnerabilities." | tee -a configure.log
|
||||
fi
|
||||
else
|
||||
CFLAGS="$CFLAGS -DNO_vsnprintf"
|
||||
SFLAGS="$SFLAGS -DNO_vsnprintf"
|
||||
echo "Checking for vsnprintf() in stdio.h... No." | tee -a configure.log
|
||||
echo " WARNING: vsnprintf() not found, falling back to vsprintf(). zlib" | tee -a configure.log
|
||||
echo " can build but will be open to possible buffer-overflow security" | tee -a configure.log
|
||||
echo " vulnerabilities." | tee -a configure.log
|
||||
|
||||
echo >> configure.log
|
||||
cat >$test.c <<EOF
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
int mytest(const char *fmt, ...)
|
||||
{
|
||||
int n;
|
||||
char buf[20];
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
n = vsprintf(buf, fmt, ap);
|
||||
va_end(ap);
|
||||
return n;
|
||||
}
|
||||
int main()
|
||||
{
|
||||
return (mytest("Hello%d\n", 1));
|
||||
}
|
||||
EOF
|
||||
|
||||
if try $CC -c $CFLAGS $test.c; then
|
||||
echo "Checking for return value of vsprintf()... Yes." | tee -a configure.log
|
||||
else
|
||||
CFLAGS="$CFLAGS -DHAS_vsprintf_void"
|
||||
SFLAGS="$SFLAGS -DHAS_vsprintf_void"
|
||||
echo "Checking for return value of vsprintf()... No." | tee -a configure.log
|
||||
echo " WARNING: apparently vsprintf() does not return a value. zlib" | tee -a configure.log
|
||||
echo " can build but will be open to possible string-format security" | tee -a configure.log
|
||||
echo " vulnerabilities." | tee -a configure.log
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "Checking whether to use vs[n]printf() or s[n]printf()... using s[n]printf()." | tee -a configure.log
|
||||
|
||||
echo >> configure.log
|
||||
cat >$test.c <<EOF
|
||||
#include <stdio.h>
|
||||
int mytest()
|
||||
{
|
||||
char buf[20];
|
||||
snprintf(buf, sizeof(buf), "%s", "foo");
|
||||
return 0;
|
||||
}
|
||||
int main()
|
||||
{
|
||||
return (mytest());
|
||||
}
|
||||
EOF
|
||||
|
||||
if try $CC $CFLAGS -o $test $test.c; then
|
||||
echo "Checking for snprintf() in stdio.h... Yes." | tee -a configure.log
|
||||
|
||||
echo >> configure.log
|
||||
cat >$test.c <<EOF
|
||||
#include <stdio.h>
|
||||
int mytest()
|
||||
{
|
||||
char buf[20];
|
||||
return snprintf(buf, sizeof(buf), "%s", "foo");
|
||||
}
|
||||
int main()
|
||||
{
|
||||
return (mytest());
|
||||
}
|
||||
EOF
|
||||
|
||||
if try $CC -c $CFLAGS $test.c; then
|
||||
echo "Checking for return value of snprintf()... Yes." | tee -a configure.log
|
||||
else
|
||||
CFLAGS="$CFLAGS -DHAS_snprintf_void"
|
||||
SFLAGS="$SFLAGS -DHAS_snprintf_void"
|
||||
echo "Checking for return value of snprintf()... No." | tee -a configure.log
|
||||
echo " WARNING: apparently snprintf() does not return a value. zlib" | tee -a configure.log
|
||||
echo " can build but will be open to possible string-format security" | tee -a configure.log
|
||||
echo " vulnerabilities." | tee -a configure.log
|
||||
fi
|
||||
else
|
||||
CFLAGS="$CFLAGS -DNO_snprintf"
|
||||
SFLAGS="$SFLAGS -DNO_snprintf"
|
||||
echo "Checking for snprintf() in stdio.h... No." | tee -a configure.log
|
||||
echo " WARNING: snprintf() not found, falling back to sprintf(). zlib" | tee -a configure.log
|
||||
echo " can build but will be open to possible buffer-overflow security" | tee -a configure.log
|
||||
echo " vulnerabilities." | tee -a configure.log
|
||||
|
||||
echo >> configure.log
|
||||
cat >$test.c <<EOF
|
||||
#include <stdio.h>
|
||||
int mytest()
|
||||
{
|
||||
char buf[20];
|
||||
return sprintf(buf, "%s", "foo");
|
||||
}
|
||||
int main()
|
||||
{
|
||||
return (mytest());
|
||||
}
|
||||
EOF
|
||||
|
||||
if try $CC -c $CFLAGS $test.c; then
|
||||
echo "Checking for return value of sprintf()... Yes." | tee -a configure.log
|
||||
else
|
||||
CFLAGS="$CFLAGS -DHAS_sprintf_void"
|
||||
SFLAGS="$SFLAGS -DHAS_sprintf_void"
|
||||
echo "Checking for return value of sprintf()... No." | tee -a configure.log
|
||||
echo " WARNING: apparently sprintf() does not return a value. zlib" | tee -a configure.log
|
||||
echo " can build but will be open to possible string-format security" | tee -a configure.log
|
||||
echo " vulnerabilities." | tee -a configure.log
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# see if we can hide zlib internal symbols that are linked between separate source files
|
||||
if test "$gcc" -eq 1; then
|
||||
echo >> configure.log
|
||||
cat > $test.c <<EOF
|
||||
#define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
|
||||
int ZLIB_INTERNAL foo;
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
if tryboth $CC -c $CFLAGS $test.c; then
|
||||
CFLAGS="$CFLAGS -DHAVE_HIDDEN"
|
||||
SFLAGS="$SFLAGS -DHAVE_HIDDEN"
|
||||
echo "Checking for attribute(visibility) support... Yes." | tee -a configure.log
|
||||
else
|
||||
echo "Checking for attribute(visibility) support... No." | tee -a configure.log
|
||||
fi
|
||||
fi
|
||||
|
||||
# show the results in the log
|
||||
echo >> configure.log
|
||||
echo ALL = $ALL >> configure.log
|
||||
echo AR = $AR >> configure.log
|
||||
echo ARFLAGS = $ARFLAGS >> configure.log
|
||||
echo CC = $CC >> configure.log
|
||||
echo CFLAGS = $CFLAGS >> configure.log
|
||||
echo CPP = $CPP >> configure.log
|
||||
echo EXE = $EXE >> configure.log
|
||||
echo LDCONFIG = $LDCONFIG >> configure.log
|
||||
echo LDFLAGS = $LDFLAGS >> configure.log
|
||||
echo LDSHARED = $LDSHARED >> configure.log
|
||||
echo LDSHAREDLIBC = $LDSHAREDLIBC >> configure.log
|
||||
echo OBJC = $OBJC >> configure.log
|
||||
echo PIC_OBJC = $PIC_OBJC >> configure.log
|
||||
echo RANLIB = $RANLIB >> configure.log
|
||||
echo SFLAGS = $SFLAGS >> configure.log
|
||||
echo SHAREDLIB = $SHAREDLIB >> configure.log
|
||||
echo SHAREDLIBM = $SHAREDLIBM >> configure.log
|
||||
echo SHAREDLIBV = $SHAREDLIBV >> configure.log
|
||||
echo STATICLIB = $STATICLIB >> configure.log
|
||||
echo TEST = $TEST >> configure.log
|
||||
echo VER = $VER >> configure.log
|
||||
echo Z_U4 = $Z_U4 >> configure.log
|
||||
echo SRCDIR = $SRCDIR >> configure.log
|
||||
echo exec_prefix = $exec_prefix >> configure.log
|
||||
echo includedir = $includedir >> configure.log
|
||||
echo libdir = $libdir >> configure.log
|
||||
echo mandir = $mandir >> configure.log
|
||||
echo prefix = $prefix >> configure.log
|
||||
echo sharedlibdir = $sharedlibdir >> configure.log
|
||||
echo uname = $uname >> configure.log
|
||||
|
||||
# udpate Makefile with the configure results
|
||||
sed < ${SRCDIR}Makefile.in "
|
||||
/^CC *=/s#=.*#=$CC#
|
||||
/^CFLAGS *=/s#=.*#=$CFLAGS#
|
||||
/^SFLAGS *=/s#=.*#=$SFLAGS#
|
||||
/^LDFLAGS *=/s#=.*#=$LDFLAGS#
|
||||
/^LDSHARED *=/s#=.*#=$LDSHARED#
|
||||
/^CPP *=/s#=.*#=$CPP#
|
||||
/^STATICLIB *=/s#=.*#=$STATICLIB#
|
||||
/^SHAREDLIB *=/s#=.*#=$SHAREDLIB#
|
||||
/^SHAREDLIBV *=/s#=.*#=$SHAREDLIBV#
|
||||
/^SHAREDLIBM *=/s#=.*#=$SHAREDLIBM#
|
||||
/^AR *=/s#=.*#=$AR#
|
||||
/^ARFLAGS *=/s#=.*#=$ARFLAGS#
|
||||
/^RANLIB *=/s#=.*#=$RANLIB#
|
||||
/^LDCONFIG *=/s#=.*#=$LDCONFIG#
|
||||
/^LDSHAREDLIBC *=/s#=.*#=$LDSHAREDLIBC#
|
||||
/^EXE *=/s#=.*#=$EXE#
|
||||
/^SRCDIR *=/s#=.*#=$SRCDIR#
|
||||
/^ZINC *=/s#=.*#=$ZINC#
|
||||
/^ZINCOUT *=/s#=.*#=$ZINCOUT#
|
||||
/^prefix *=/s#=.*#=$prefix#
|
||||
/^exec_prefix *=/s#=.*#=$exec_prefix#
|
||||
/^libdir *=/s#=.*#=$libdir#
|
||||
/^sharedlibdir *=/s#=.*#=$sharedlibdir#
|
||||
/^includedir *=/s#=.*#=$includedir#
|
||||
/^mandir *=/s#=.*#=$mandir#
|
||||
/^OBJC *=/s#=.*#= $OBJC#
|
||||
/^PIC_OBJC *=/s#=.*#= $PIC_OBJC#
|
||||
/^all: */s#:.*#: $ALL#
|
||||
/^test: */s#:.*#: $TEST#
|
||||
" > Makefile
|
||||
|
||||
# create zlib.pc with the configure results
|
||||
sed < ${SRCDIR}zlib.pc.in "
|
||||
/^CC *=/s#=.*#=$CC#
|
||||
/^CFLAGS *=/s#=.*#=$CFLAGS#
|
||||
/^CPP *=/s#=.*#=$CPP#
|
||||
/^LDSHARED *=/s#=.*#=$LDSHARED#
|
||||
/^STATICLIB *=/s#=.*#=$STATICLIB#
|
||||
/^SHAREDLIB *=/s#=.*#=$SHAREDLIB#
|
||||
/^SHAREDLIBV *=/s#=.*#=$SHAREDLIBV#
|
||||
/^SHAREDLIBM *=/s#=.*#=$SHAREDLIBM#
|
||||
/^AR *=/s#=.*#=$AR#
|
||||
/^ARFLAGS *=/s#=.*#=$ARFLAGS#
|
||||
/^RANLIB *=/s#=.*#=$RANLIB#
|
||||
/^EXE *=/s#=.*#=$EXE#
|
||||
/^prefix *=/s#=.*#=$prefix#
|
||||
/^exec_prefix *=/s#=.*#=$exec_prefix#
|
||||
/^libdir *=/s#=.*#=$libdir#
|
||||
/^sharedlibdir *=/s#=.*#=$sharedlibdir#
|
||||
/^includedir *=/s#=.*#=$includedir#
|
||||
/^mandir *=/s#=.*#=$mandir#
|
||||
/^LDFLAGS *=/s#=.*#=$LDFLAGS#
|
||||
" | sed -e "
|
||||
s/\@VERSION\@/$VER/g;
|
||||
" > zlib.pc
|
||||
|
||||
# done
|
||||
leave 0
|
78
third_party/zlib/contrib/README.contrib
vendored
78
third_party/zlib/contrib/README.contrib
vendored
@ -1,78 +0,0 @@
|
||||
All files under this contrib directory are UNSUPPORTED. There were
|
||||
provided by users of zlib and were not tested by the authors of zlib.
|
||||
Use at your own risk. Please contact the authors of the contributions
|
||||
for help about these, not the zlib authors. Thanks.
|
||||
|
||||
|
||||
ada/ by Dmitriy Anisimkov <anisimkov@yahoo.com>
|
||||
Support for Ada
|
||||
See http://zlib-ada.sourceforge.net/
|
||||
|
||||
amd64/ by Mikhail Teterin <mi@ALDAN.algebra.com>
|
||||
asm code for AMD64
|
||||
See patch at http://www.freebsd.org/cgi/query-pr.cgi?pr=bin/96393
|
||||
|
||||
asm686/ by Brian Raiter <breadbox@muppetlabs.com>
|
||||
asm code for Pentium and PPro/PII, using the AT&T (GNU as) syntax
|
||||
See http://www.muppetlabs.com/~breadbox/software/assembly.html
|
||||
|
||||
blast/ by Mark Adler <madler@alumni.caltech.edu>
|
||||
Decompressor for output of PKWare Data Compression Library (DCL)
|
||||
|
||||
delphi/ by Cosmin Truta <cosmint@cs.ubbcluj.ro>
|
||||
Support for Delphi and C++ Builder
|
||||
|
||||
dotzlib/ by Henrik Ravn <henrik@ravn.com>
|
||||
Support for Microsoft .Net and Visual C++ .Net
|
||||
|
||||
gcc_gvmat64/by Gilles Vollant <info@winimage.com>
|
||||
GCC Version of x86 64-bit (AMD64 and Intel EM64t) code for x64
|
||||
assembler to replace longest_match() and inflate_fast()
|
||||
|
||||
infback9/ by Mark Adler <madler@alumni.caltech.edu>
|
||||
Unsupported diffs to infback to decode the deflate64 format
|
||||
|
||||
inflate86/ by Chris Anderson <christop@charm.net>
|
||||
Tuned x86 gcc asm code to replace inflate_fast()
|
||||
|
||||
iostream/ by Kevin Ruland <kevin@rodin.wustl.edu>
|
||||
A C++ I/O streams interface to the zlib gz* functions
|
||||
|
||||
iostream2/ by Tyge Løvset <Tyge.Lovset@cmr.no>
|
||||
Another C++ I/O streams interface
|
||||
|
||||
iostream3/ by Ludwig Schwardt <schwardt@sun.ac.za>
|
||||
and Kevin Ruland <kevin@rodin.wustl.edu>
|
||||
Yet another C++ I/O streams interface
|
||||
|
||||
masmx64/ by Gilles Vollant <info@winimage.com>
|
||||
x86 64-bit (AMD64 and Intel EM64t) code for x64 assembler to
|
||||
replace longest_match() and inflate_fast(), also masm x86
|
||||
64-bits translation of Chris Anderson inflate_fast()
|
||||
|
||||
masmx86/ by Gilles Vollant <info@winimage.com>
|
||||
x86 asm code to replace longest_match() and inflate_fast(),
|
||||
for Visual C++ and MASM (32 bits).
|
||||
Based on Brian Raiter (asm686) and Chris Anderson (inflate86)
|
||||
|
||||
minizip/ by Gilles Vollant <info@winimage.com>
|
||||
Mini zip and unzip based on zlib
|
||||
Includes Zip64 support by Mathias Svensson <mathias@result42.com>
|
||||
See http://www.winimage.com/zLibDll/minizip.html
|
||||
|
||||
pascal/ by Bob Dellaca <bobdl@xtra.co.nz> et al.
|
||||
Support for Pascal
|
||||
|
||||
puff/ by Mark Adler <madler@alumni.caltech.edu>
|
||||
Small, low memory usage inflate. Also serves to provide an
|
||||
unambiguous description of the deflate format.
|
||||
|
||||
testzlib/ by Gilles Vollant <info@winimage.com>
|
||||
Example of the use of zlib
|
||||
|
||||
untgz/ by Pedro A. Aranda Gutierrez <paag@tid.es>
|
||||
A very simple tar.gz file extractor using zlib
|
||||
|
||||
vstudio/ by Gilles Vollant <info@winimage.com>
|
||||
Building a minizip-enhanced zlib with Microsoft Visual Studio
|
||||
Includes vc11 from kreuzerkrieg and vc12 from davispuh
|
106
third_party/zlib/contrib/ada/buffer_demo.adb
vendored
106
third_party/zlib/contrib/ada/buffer_demo.adb
vendored
@ -1,106 +0,0 @@
|
||||
----------------------------------------------------------------
|
||||
-- ZLib for Ada thick binding. --
|
||||
-- --
|
||||
-- Copyright (C) 2002-2004 Dmitriy Anisimkov --
|
||||
-- --
|
||||
-- Open source license information is in the zlib.ads file. --
|
||||
----------------------------------------------------------------
|
||||
--
|
||||
-- $Id: buffer_demo.adb,v 1.3 2004/09/06 06:55:35 vagul Exp $
|
||||
|
||||
-- This demo program provided by Dr Steve Sangwine <sjs@essex.ac.uk>
|
||||
--
|
||||
-- Demonstration of a problem with Zlib-Ada (already fixed) when a buffer
|
||||
-- of exactly the correct size is used for decompressed data, and the last
|
||||
-- few bytes passed in to Zlib are checksum bytes.
|
||||
|
||||
-- This program compresses a string of text, and then decompresses the
|
||||
-- compressed text into a buffer of the same size as the original text.
|
||||
|
||||
with Ada.Streams; use Ada.Streams;
|
||||
with Ada.Text_IO;
|
||||
|
||||
with ZLib; use ZLib;
|
||||
|
||||
procedure Buffer_Demo is
|
||||
EOL : Character renames ASCII.LF;
|
||||
Text : constant String
|
||||
:= "Four score and seven years ago our fathers brought forth," & EOL &
|
||||
"upon this continent, a new nation, conceived in liberty," & EOL &
|
||||
"and dedicated to the proposition that `all men are created equal'.";
|
||||
|
||||
Source : Stream_Element_Array (1 .. Text'Length);
|
||||
for Source'Address use Text'Address;
|
||||
|
||||
begin
|
||||
Ada.Text_IO.Put (Text);
|
||||
Ada.Text_IO.New_Line;
|
||||
Ada.Text_IO.Put_Line
|
||||
("Uncompressed size : " & Positive'Image (Text'Length) & " bytes");
|
||||
|
||||
declare
|
||||
Compressed_Data : Stream_Element_Array (1 .. Text'Length);
|
||||
L : Stream_Element_Offset;
|
||||
begin
|
||||
Compress : declare
|
||||
Compressor : Filter_Type;
|
||||
I : Stream_Element_Offset;
|
||||
begin
|
||||
Deflate_Init (Compressor);
|
||||
|
||||
-- Compress the whole of T at once.
|
||||
|
||||
Translate (Compressor, Source, I, Compressed_Data, L, Finish);
|
||||
pragma Assert (I = Source'Last);
|
||||
|
||||
Close (Compressor);
|
||||
|
||||
Ada.Text_IO.Put_Line
|
||||
("Compressed size : "
|
||||
& Stream_Element_Offset'Image (L) & " bytes");
|
||||
end Compress;
|
||||
|
||||
-- Now we decompress the data, passing short blocks of data to Zlib
|
||||
-- (because this demonstrates the problem - the last block passed will
|
||||
-- contain checksum information and there will be no output, only a
|
||||
-- check inside Zlib that the checksum is correct).
|
||||
|
||||
Decompress : declare
|
||||
Decompressor : Filter_Type;
|
||||
|
||||
Uncompressed_Data : Stream_Element_Array (1 .. Text'Length);
|
||||
|
||||
Block_Size : constant := 4;
|
||||
-- This makes sure that the last block contains
|
||||
-- only Adler checksum data.
|
||||
|
||||
P : Stream_Element_Offset := Compressed_Data'First - 1;
|
||||
O : Stream_Element_Offset;
|
||||
begin
|
||||
Inflate_Init (Decompressor);
|
||||
|
||||
loop
|
||||
Translate
|
||||
(Decompressor,
|
||||
Compressed_Data
|
||||
(P + 1 .. Stream_Element_Offset'Min (P + Block_Size, L)),
|
||||
P,
|
||||
Uncompressed_Data
|
||||
(Total_Out (Decompressor) + 1 .. Uncompressed_Data'Last),
|
||||
O,
|
||||
No_Flush);
|
||||
|
||||
Ada.Text_IO.Put_Line
|
||||
("Total in : " & Count'Image (Total_In (Decompressor)) &
|
||||
", out : " & Count'Image (Total_Out (Decompressor)));
|
||||
|
||||
exit when P = L;
|
||||
end loop;
|
||||
|
||||
Ada.Text_IO.New_Line;
|
||||
Ada.Text_IO.Put_Line
|
||||
("Decompressed text matches original text : "
|
||||
& Boolean'Image (Uncompressed_Data = Source));
|
||||
end Decompress;
|
||||
end;
|
||||
end Buffer_Demo;
|
156
third_party/zlib/contrib/ada/mtest.adb
vendored
156
third_party/zlib/contrib/ada/mtest.adb
vendored
@ -1,156 +0,0 @@
|
||||
----------------------------------------------------------------
|
||||
-- ZLib for Ada thick binding. --
|
||||
-- --
|
||||
-- Copyright (C) 2002-2003 Dmitriy Anisimkov --
|
||||
-- --
|
||||
-- Open source license information is in the zlib.ads file. --
|
||||
----------------------------------------------------------------
|
||||
-- Continuous test for ZLib multithreading. If the test would fail
|
||||
-- we should provide thread safe allocation routines for the Z_Stream.
|
||||
--
|
||||
-- $Id: mtest.adb,v 1.4 2004/07/23 07:49:54 vagul Exp $
|
||||
|
||||
with ZLib;
|
||||
with Ada.Streams;
|
||||
with Ada.Numerics.Discrete_Random;
|
||||
with Ada.Text_IO;
|
||||
with Ada.Exceptions;
|
||||
with Ada.Task_Identification;
|
||||
|
||||
procedure MTest is
|
||||
use Ada.Streams;
|
||||
use ZLib;
|
||||
|
||||
Stop : Boolean := False;
|
||||
|
||||
pragma Atomic (Stop);
|
||||
|
||||
subtype Visible_Symbols is Stream_Element range 16#20# .. 16#7E#;
|
||||
|
||||
package Random_Elements is
|
||||
new Ada.Numerics.Discrete_Random (Visible_Symbols);
|
||||
|
||||
task type Test_Task;
|
||||
|
||||
task body Test_Task is
|
||||
Buffer : Stream_Element_Array (1 .. 100_000);
|
||||
Gen : Random_Elements.Generator;
|
||||
|
||||
Buffer_First : Stream_Element_Offset;
|
||||
Compare_First : Stream_Element_Offset;
|
||||
|
||||
Deflate : Filter_Type;
|
||||
Inflate : Filter_Type;
|
||||
|
||||
procedure Further (Item : in Stream_Element_Array);
|
||||
|
||||
procedure Read_Buffer
|
||||
(Item : out Ada.Streams.Stream_Element_Array;
|
||||
Last : out Ada.Streams.Stream_Element_Offset);
|
||||
|
||||
-------------
|
||||
-- Further --
|
||||
-------------
|
||||
|
||||
procedure Further (Item : in Stream_Element_Array) is
|
||||
|
||||
procedure Compare (Item : in Stream_Element_Array);
|
||||
|
||||
-------------
|
||||
-- Compare --
|
||||
-------------
|
||||
|
||||
procedure Compare (Item : in Stream_Element_Array) is
|
||||
Next_First : Stream_Element_Offset := Compare_First + Item'Length;
|
||||
begin
|
||||
if Buffer (Compare_First .. Next_First - 1) /= Item then
|
||||
raise Program_Error;
|
||||
end if;
|
||||
|
||||
Compare_First := Next_First;
|
||||
end Compare;
|
||||
|
||||
procedure Compare_Write is new ZLib.Write (Write => Compare);
|
||||
begin
|
||||
Compare_Write (Inflate, Item, No_Flush);
|
||||
end Further;
|
||||
|
||||
-----------------
|
||||
-- Read_Buffer --
|
||||
-----------------
|
||||
|
||||
procedure Read_Buffer
|
||||
(Item : out Ada.Streams.Stream_Element_Array;
|
||||
Last : out Ada.Streams.Stream_Element_Offset)
|
||||
is
|
||||
Buff_Diff : Stream_Element_Offset := Buffer'Last - Buffer_First;
|
||||
Next_First : Stream_Element_Offset;
|
||||
begin
|
||||
if Item'Length <= Buff_Diff then
|
||||
Last := Item'Last;
|
||||
|
||||
Next_First := Buffer_First + Item'Length;
|
||||
|
||||
Item := Buffer (Buffer_First .. Next_First - 1);
|
||||
|
||||
Buffer_First := Next_First;
|
||||
else
|
||||
Last := Item'First + Buff_Diff;
|
||||
Item (Item'First .. Last) := Buffer (Buffer_First .. Buffer'Last);
|
||||
Buffer_First := Buffer'Last + 1;
|
||||
end if;
|
||||
end Read_Buffer;
|
||||
|
||||
procedure Translate is new Generic_Translate
|
||||
(Data_In => Read_Buffer,
|
||||
Data_Out => Further);
|
||||
|
||||
begin
|
||||
Random_Elements.Reset (Gen);
|
||||
|
||||
Buffer := (others => 20);
|
||||
|
||||
Main : loop
|
||||
for J in Buffer'Range loop
|
||||
Buffer (J) := Random_Elements.Random (Gen);
|
||||
|
||||
Deflate_Init (Deflate);
|
||||
Inflate_Init (Inflate);
|
||||
|
||||
Buffer_First := Buffer'First;
|
||||
Compare_First := Buffer'First;
|
||||
|
||||
Translate (Deflate);
|
||||
|
||||
if Compare_First /= Buffer'Last + 1 then
|
||||
raise Program_Error;
|
||||
end if;
|
||||
|
||||
Ada.Text_IO.Put_Line
|
||||
(Ada.Task_Identification.Image
|
||||
(Ada.Task_Identification.Current_Task)
|
||||
& Stream_Element_Offset'Image (J)
|
||||
& ZLib.Count'Image (Total_Out (Deflate)));
|
||||
|
||||
Close (Deflate);
|
||||
Close (Inflate);
|
||||
|
||||
exit Main when Stop;
|
||||
end loop;
|
||||
end loop Main;
|
||||
exception
|
||||
when E : others =>
|
||||
Ada.Text_IO.Put_Line (Ada.Exceptions.Exception_Information (E));
|
||||
Stop := True;
|
||||
end Test_Task;
|
||||
|
||||
Test : array (1 .. 4) of Test_Task;
|
||||
|
||||
pragma Unreferenced (Test);
|
||||
|
||||
Dummy : Character;
|
||||
|
||||
begin
|
||||
Ada.Text_IO.Get_Immediate (Dummy);
|
||||
Stop := True;
|
||||
end MTest;
|
156
third_party/zlib/contrib/ada/read.adb
vendored
156
third_party/zlib/contrib/ada/read.adb
vendored
@ -1,156 +0,0 @@
|
||||
----------------------------------------------------------------
|
||||
-- ZLib for Ada thick binding. --
|
||||
-- --
|
||||
-- Copyright (C) 2002-2003 Dmitriy Anisimkov --
|
||||
-- --
|
||||
-- Open source license information is in the zlib.ads file. --
|
||||
----------------------------------------------------------------
|
||||
|
||||
-- $Id: read.adb,v 1.8 2004/05/31 10:53:40 vagul Exp $
|
||||
|
||||
-- Test/demo program for the generic read interface.
|
||||
|
||||
with Ada.Numerics.Discrete_Random;
|
||||
with Ada.Streams;
|
||||
with Ada.Text_IO;
|
||||
|
||||
with ZLib;
|
||||
|
||||
procedure Read is
|
||||
|
||||
use Ada.Streams;
|
||||
|
||||
------------------------------------
|
||||
-- Test configuration parameters --
|
||||
------------------------------------
|
||||
|
||||
File_Size : Stream_Element_Offset := 100_000;
|
||||
|
||||
Continuous : constant Boolean := False;
|
||||
-- If this constant is True, the test would be repeated again and again,
|
||||
-- with increment File_Size for every iteration.
|
||||
|
||||
Header : constant ZLib.Header_Type := ZLib.Default;
|
||||
-- Do not use Header other than Default in ZLib versions 1.1.4 and older.
|
||||
|
||||
Init_Random : constant := 8;
|
||||
-- We are using the same random sequence, in case of we catch bug,
|
||||
-- so we would be able to reproduce it.
|
||||
|
||||
-- End --
|
||||
|
||||
Pack_Size : Stream_Element_Offset;
|
||||
Offset : Stream_Element_Offset;
|
||||
|
||||
Filter : ZLib.Filter_Type;
|
||||
|
||||
subtype Visible_Symbols
|
||||
is Stream_Element range 16#20# .. 16#7E#;
|
||||
|
||||
package Random_Elements is new
|
||||
Ada.Numerics.Discrete_Random (Visible_Symbols);
|
||||
|
||||
Gen : Random_Elements.Generator;
|
||||
Period : constant Stream_Element_Offset := 200;
|
||||
-- Period constant variable for random generator not to be very random.
|
||||
-- Bigger period, harder random.
|
||||
|
||||
Read_Buffer : Stream_Element_Array (1 .. 2048);
|
||||
Read_First : Stream_Element_Offset;
|
||||
Read_Last : Stream_Element_Offset;
|
||||
|
||||
procedure Reset;
|
||||
|
||||
procedure Read
|
||||
(Item : out Stream_Element_Array;
|
||||
Last : out Stream_Element_Offset);
|
||||
-- this procedure is for generic instantiation of
|
||||
-- ZLib.Read
|
||||
-- reading data from the File_In.
|
||||
|
||||
procedure Read is new ZLib.Read
|
||||
(Read,
|
||||
Read_Buffer,
|
||||
Rest_First => Read_First,
|
||||
Rest_Last => Read_Last);
|
||||
|
||||
----------
|
||||
-- Read --
|
||||
----------
|
||||
|
||||
procedure Read
|
||||
(Item : out Stream_Element_Array;
|
||||
Last : out Stream_Element_Offset) is
|
||||
begin
|
||||
Last := Stream_Element_Offset'Min
|
||||
(Item'Last,
|
||||
Item'First + File_Size - Offset);
|
||||
|
||||
for J in Item'First .. Last loop
|
||||
if J < Item'First + Period then
|
||||
Item (J) := Random_Elements.Random (Gen);
|
||||
else
|
||||
Item (J) := Item (J - Period);
|
||||
end if;
|
||||
|
||||
Offset := Offset + 1;
|
||||
end loop;
|
||||
end Read;
|
||||
|
||||
-----------
|
||||
-- Reset --
|
||||
-----------
|
||||
|
||||
procedure Reset is
|
||||
begin
|
||||
Random_Elements.Reset (Gen, Init_Random);
|
||||
Pack_Size := 0;
|
||||
Offset := 1;
|
||||
Read_First := Read_Buffer'Last + 1;
|
||||
Read_Last := Read_Buffer'Last;
|
||||
end Reset;
|
||||
|
||||
begin
|
||||
Ada.Text_IO.Put_Line ("ZLib " & ZLib.Version);
|
||||
|
||||
loop
|
||||
for Level in ZLib.Compression_Level'Range loop
|
||||
|
||||
Ada.Text_IO.Put ("Level ="
|
||||
& ZLib.Compression_Level'Image (Level));
|
||||
|
||||
-- Deflate using generic instantiation.
|
||||
|
||||
ZLib.Deflate_Init
|
||||
(Filter,
|
||||
Level,
|
||||
Header => Header);
|
||||
|
||||
Reset;
|
||||
|
||||
Ada.Text_IO.Put
|
||||
(Stream_Element_Offset'Image (File_Size) & " ->");
|
||||
|
||||
loop
|
||||
declare
|
||||
Buffer : Stream_Element_Array (1 .. 1024);
|
||||
Last : Stream_Element_Offset;
|
||||
begin
|
||||
Read (Filter, Buffer, Last);
|
||||
|
||||
Pack_Size := Pack_Size + Last - Buffer'First + 1;
|
||||
|
||||
exit when Last < Buffer'Last;
|
||||
end;
|
||||
end loop;
|
||||
|
||||
Ada.Text_IO.Put_Line (Stream_Element_Offset'Image (Pack_Size));
|
||||
|
||||
ZLib.Close (Filter);
|
||||
end loop;
|
||||
|
||||
exit when not Continuous;
|
||||
|
||||
File_Size := File_Size + 1;
|
||||
end loop;
|
||||
end Read;
|
65
third_party/zlib/contrib/ada/readme.txt
vendored
65
third_party/zlib/contrib/ada/readme.txt
vendored
@ -1,65 +0,0 @@
|
||||
ZLib for Ada thick binding (ZLib.Ada)
|
||||
Release 1.3
|
||||
|
||||
ZLib.Ada is a thick binding interface to the popular ZLib data
|
||||
compression library, available at http://www.gzip.org/zlib/.
|
||||
It provides Ada-style access to the ZLib C library.
|
||||
|
||||
|
||||
Here are the main changes since ZLib.Ada 1.2:
|
||||
|
||||
- Attension: ZLib.Read generic routine have a initialization requirement
|
||||
for Read_Last parameter now. It is a bit incompartible with previous version,
|
||||
but extends functionality, we could use new parameters Allow_Read_Some and
|
||||
Flush now.
|
||||
|
||||
- Added Is_Open routines to ZLib and ZLib.Streams packages.
|
||||
|
||||
- Add pragma Assert to check Stream_Element is 8 bit.
|
||||
|
||||
- Fix extraction to buffer with exact known decompressed size. Error reported by
|
||||
Steve Sangwine.
|
||||
|
||||
- Fix definition of ULong (changed to unsigned_long), fix regression on 64 bits
|
||||
computers. Patch provided by Pascal Obry.
|
||||
|
||||
- Add Status_Error exception definition.
|
||||
|
||||
- Add pragma Assertion that Ada.Streams.Stream_Element size is 8 bit.
|
||||
|
||||
|
||||
How to build ZLib.Ada under GNAT
|
||||
|
||||
You should have the ZLib library already build on your computer, before
|
||||
building ZLib.Ada. Make the directory of ZLib.Ada sources current and
|
||||
issue the command:
|
||||
|
||||
gnatmake test -largs -L<directory where libz.a is> -lz
|
||||
|
||||
Or use the GNAT project file build for GNAT 3.15 or later:
|
||||
|
||||
gnatmake -Pzlib.gpr -L<directory where libz.a is>
|
||||
|
||||
|
||||
How to build ZLib.Ada under Aonix ObjectAda for Win32 7.2.2
|
||||
|
||||
1. Make a project with all *.ads and *.adb files from the distribution.
|
||||
2. Build the libz.a library from the ZLib C sources.
|
||||
3. Rename libz.a to z.lib.
|
||||
4. Add the library z.lib to the project.
|
||||
5. Add the libc.lib library from the ObjectAda distribution to the project.
|
||||
6. Build the executable using test.adb as a main procedure.
|
||||
|
||||
|
||||
How to use ZLib.Ada
|
||||
|
||||
The source files test.adb and read.adb are small demo programs that show
|
||||
the main functionality of ZLib.Ada.
|
||||
|
||||
The routines from the package specifications are commented.
|
||||
|
||||
|
||||
Homepage: http://zlib-ada.sourceforge.net/
|
||||
Author: Dmitriy Anisimkov <anisimkov@yahoo.com>
|
||||
|
||||
Contributors: Pascal Obry <pascal@obry.org>, Steve Sangwine <sjs@essex.ac.uk>
|
463
third_party/zlib/contrib/ada/test.adb
vendored
463
third_party/zlib/contrib/ada/test.adb
vendored
@ -1,463 +0,0 @@
|
||||
----------------------------------------------------------------
|
||||
-- ZLib for Ada thick binding. --
|
||||
-- --
|
||||
-- Copyright (C) 2002-2003 Dmitriy Anisimkov --
|
||||
-- --
|
||||
-- Open source license information is in the zlib.ads file. --
|
||||
----------------------------------------------------------------
|
||||
|
||||
-- $Id: test.adb,v 1.17 2003/08/12 12:13:30 vagul Exp $
|
||||
|
||||
-- The program has a few aims.
|
||||
-- 1. Test ZLib.Ada95 thick binding functionality.
|
||||
-- 2. Show the example of use main functionality of the ZLib.Ada95 binding.
|
||||
-- 3. Build this program automatically compile all ZLib.Ada95 packages under
|
||||
-- GNAT Ada95 compiler.
|
||||
|
||||
with ZLib.Streams;
|
||||
with Ada.Streams.Stream_IO;
|
||||
with Ada.Numerics.Discrete_Random;
|
||||
|
||||
with Ada.Text_IO;
|
||||
|
||||
with Ada.Calendar;
|
||||
|
||||
procedure Test is
|
||||
|
||||
use Ada.Streams;
|
||||
use Stream_IO;
|
||||
|
||||
------------------------------------
|
||||
-- Test configuration parameters --
|
||||
------------------------------------
|
||||
|
||||
File_Size : Count := 100_000;
|
||||
Continuous : constant Boolean := False;
|
||||
|
||||
Header : constant ZLib.Header_Type := ZLib.Default;
|
||||
-- ZLib.None;
|
||||
-- ZLib.Auto;
|
||||
-- ZLib.GZip;
|
||||
-- Do not use Header other then Default in ZLib versions 1.1.4
|
||||
-- and older.
|
||||
|
||||
Strategy : constant ZLib.Strategy_Type := ZLib.Default_Strategy;
|
||||
Init_Random : constant := 10;
|
||||
|
||||
-- End --
|
||||
|
||||
In_File_Name : constant String := "testzlib.in";
|
||||
-- Name of the input file
|
||||
|
||||
Z_File_Name : constant String := "testzlib.zlb";
|
||||
-- Name of the compressed file.
|
||||
|
||||
Out_File_Name : constant String := "testzlib.out";
|
||||
-- Name of the decompressed file.
|
||||
|
||||
File_In : File_Type;
|
||||
File_Out : File_Type;
|
||||
File_Back : File_Type;
|
||||
File_Z : ZLib.Streams.Stream_Type;
|
||||
|
||||
Filter : ZLib.Filter_Type;
|
||||
|
||||
Time_Stamp : Ada.Calendar.Time;
|
||||
|
||||
procedure Generate_File;
|
||||
-- Generate file of spetsified size with some random data.
|
||||
-- The random data is repeatable, for the good compression.
|
||||
|
||||
procedure Compare_Streams
|
||||
(Left, Right : in out Root_Stream_Type'Class);
|
||||
-- The procedure compearing data in 2 streams.
|
||||
-- It is for compare data before and after compression/decompression.
|
||||
|
||||
procedure Compare_Files (Left, Right : String);
|
||||
-- Compare files. Based on the Compare_Streams.
|
||||
|
||||
procedure Copy_Streams
|
||||
(Source, Target : in out Root_Stream_Type'Class;
|
||||
Buffer_Size : in Stream_Element_Offset := 1024);
|
||||
-- Copying data from one stream to another. It is for test stream
|
||||
-- interface of the library.
|
||||
|
||||
procedure Data_In
|
||||
(Item : out Stream_Element_Array;
|
||||
Last : out Stream_Element_Offset);
|
||||
-- this procedure is for generic instantiation of
|
||||
-- ZLib.Generic_Translate.
|
||||
-- reading data from the File_In.
|
||||
|
||||
procedure Data_Out (Item : in Stream_Element_Array);
|
||||
-- this procedure is for generic instantiation of
|
||||
-- ZLib.Generic_Translate.
|
||||
-- writing data to the File_Out.
|
||||
|
||||
procedure Stamp;
|
||||
-- Store the timestamp to the local variable.
|
||||
|
||||
procedure Print_Statistic (Msg : String; Data_Size : ZLib.Count);
|
||||
-- Print the time statistic with the message.
|
||||
|
||||
procedure Translate is new ZLib.Generic_Translate
|
||||
(Data_In => Data_In,
|
||||
Data_Out => Data_Out);
|
||||
-- This procedure is moving data from File_In to File_Out
|
||||
-- with compression or decompression, depend on initialization of
|
||||
-- Filter parameter.
|
||||
|
||||
-------------------
|
||||
-- Compare_Files --
|
||||
-------------------
|
||||
|
||||
procedure Compare_Files (Left, Right : String) is
|
||||
Left_File, Right_File : File_Type;
|
||||
begin
|
||||
Open (Left_File, In_File, Left);
|
||||
Open (Right_File, In_File, Right);
|
||||
Compare_Streams (Stream (Left_File).all, Stream (Right_File).all);
|
||||
Close (Left_File);
|
||||
Close (Right_File);
|
||||
end Compare_Files;
|
||||
|
||||
---------------------
|
||||
-- Compare_Streams --
|
||||
---------------------
|
||||
|
||||
procedure Compare_Streams
|
||||
(Left, Right : in out Ada.Streams.Root_Stream_Type'Class)
|
||||
is
|
||||
Left_Buffer, Right_Buffer : Stream_Element_Array (0 .. 16#FFF#);
|
||||
Left_Last, Right_Last : Stream_Element_Offset;
|
||||
begin
|
||||
loop
|
||||
Read (Left, Left_Buffer, Left_Last);
|
||||
Read (Right, Right_Buffer, Right_Last);
|
||||
|
||||
if Left_Last /= Right_Last then
|
||||
Ada.Text_IO.Put_Line ("Compare error :"
|
||||
& Stream_Element_Offset'Image (Left_Last)
|
||||
& " /= "
|
||||
& Stream_Element_Offset'Image (Right_Last));
|
||||
|
||||
raise Constraint_Error;
|
||||
|
||||
elsif Left_Buffer (0 .. Left_Last)
|
||||
/= Right_Buffer (0 .. Right_Last)
|
||||
then
|
||||
Ada.Text_IO.Put_Line ("ERROR: IN and OUT files is not equal.");
|
||||
raise Constraint_Error;
|
||||
|
||||
end if;
|
||||
|
||||
exit when Left_Last < Left_Buffer'Last;
|
||||
end loop;
|
||||
end Compare_Streams;
|
||||
|
||||
------------------
|
||||
-- Copy_Streams --
|
||||
------------------
|
||||
|
||||
procedure Copy_Streams
|
||||
(Source, Target : in out Ada.Streams.Root_Stream_Type'Class;
|
||||
Buffer_Size : in Stream_Element_Offset := 1024)
|
||||
is
|
||||
Buffer : Stream_Element_Array (1 .. Buffer_Size);
|
||||
Last : Stream_Element_Offset;
|
||||
begin
|
||||
loop
|
||||
Read (Source, Buffer, Last);
|
||||
Write (Target, Buffer (1 .. Last));
|
||||
|
||||
exit when Last < Buffer'Last;
|
||||
end loop;
|
||||
end Copy_Streams;
|
||||
|
||||
-------------
|
||||
-- Data_In --
|
||||
-------------
|
||||
|
||||
procedure Data_In
|
||||
(Item : out Stream_Element_Array;
|
||||
Last : out Stream_Element_Offset) is
|
||||
begin
|
||||
Read (File_In, Item, Last);
|
||||
end Data_In;
|
||||
|
||||
--------------
|
||||
-- Data_Out --
|
||||
--------------
|
||||
|
||||
procedure Data_Out (Item : in Stream_Element_Array) is
|
||||
begin
|
||||
Write (File_Out, Item);
|
||||
end Data_Out;
|
||||
|
||||
-------------------
|
||||
-- Generate_File --
|
||||
-------------------
|
||||
|
||||
procedure Generate_File is
|
||||
subtype Visible_Symbols is Stream_Element range 16#20# .. 16#7E#;
|
||||
|
||||
package Random_Elements is
|
||||
new Ada.Numerics.Discrete_Random (Visible_Symbols);
|
||||
|
||||
Gen : Random_Elements.Generator;
|
||||
Buffer : Stream_Element_Array := (1 .. 77 => 16#20#) & 10;
|
||||
|
||||
Buffer_Count : constant Count := File_Size / Buffer'Length;
|
||||
-- Number of same buffers in the packet.
|
||||
|
||||
Density : constant Count := 30; -- from 0 to Buffer'Length - 2;
|
||||
|
||||
procedure Fill_Buffer (J, D : in Count);
|
||||
-- Change the part of the buffer.
|
||||
|
||||
-----------------
|
||||
-- Fill_Buffer --
|
||||
-----------------
|
||||
|
||||
procedure Fill_Buffer (J, D : in Count) is
|
||||
begin
|
||||
for K in 0 .. D loop
|
||||
Buffer
|
||||
(Stream_Element_Offset ((J + K) mod (Buffer'Length - 1) + 1))
|
||||
:= Random_Elements.Random (Gen);
|
||||
|
||||
end loop;
|
||||
end Fill_Buffer;
|
||||
|
||||
begin
|
||||
Random_Elements.Reset (Gen, Init_Random);
|
||||
|
||||
Create (File_In, Out_File, In_File_Name);
|
||||
|
||||
Fill_Buffer (1, Buffer'Length - 2);
|
||||
|
||||
for J in 1 .. Buffer_Count loop
|
||||
Write (File_In, Buffer);
|
||||
|
||||
Fill_Buffer (J, Density);
|
||||
end loop;
|
||||
|
||||
-- fill remain size.
|
||||
|
||||
Write
|
||||
(File_In,
|
||||
Buffer
|
||||
(1 .. Stream_Element_Offset
|
||||
(File_Size - Buffer'Length * Buffer_Count)));
|
||||
|
||||
Flush (File_In);
|
||||
Close (File_In);
|
||||
end Generate_File;
|
||||
|
||||
---------------------
|
||||
-- Print_Statistic --
|
||||
---------------------
|
||||
|
||||
procedure Print_Statistic (Msg : String; Data_Size : ZLib.Count) is
|
||||
use Ada.Calendar;
|
||||
use Ada.Text_IO;
|
||||
|
||||
package Count_IO is new Integer_IO (ZLib.Count);
|
||||
|
||||
Curr_Dur : Duration := Clock - Time_Stamp;
|
||||
begin
|
||||
Put (Msg);
|
||||
|
||||
Set_Col (20);
|
||||
Ada.Text_IO.Put ("size =");
|
||||
|
||||
Count_IO.Put
|
||||
(Data_Size,
|
||||
Width => Stream_IO.Count'Image (File_Size)'Length);
|
||||
|
||||
Put_Line (" duration =" & Duration'Image (Curr_Dur));
|
||||
end Print_Statistic;
|
||||
|
||||
-----------
|
||||
-- Stamp --
|
||||
-----------
|
||||
|
||||
procedure Stamp is
|
||||
begin
|
||||
Time_Stamp := Ada.Calendar.Clock;
|
||||
end Stamp;
|
||||
|
||||
begin
|
||||
Ada.Text_IO.Put_Line ("ZLib " & ZLib.Version);
|
||||
|
||||
loop
|
||||
Generate_File;
|
||||
|
||||
for Level in ZLib.Compression_Level'Range loop
|
||||
|
||||
Ada.Text_IO.Put_Line ("Level ="
|
||||
& ZLib.Compression_Level'Image (Level));
|
||||
|
||||
-- Test generic interface.
|
||||
Open (File_In, In_File, In_File_Name);
|
||||
Create (File_Out, Out_File, Z_File_Name);
|
||||
|
||||
Stamp;
|
||||
|
||||
-- Deflate using generic instantiation.
|
||||
|
||||
ZLib.Deflate_Init
|
||||
(Filter => Filter,
|
||||
Level => Level,
|
||||
Strategy => Strategy,
|
||||
Header => Header);
|
||||
|
||||
Translate (Filter);
|
||||
Print_Statistic ("Generic compress", ZLib.Total_Out (Filter));
|
||||
ZLib.Close (Filter);
|
||||
|
||||
Close (File_In);
|
||||
Close (File_Out);
|
||||
|
||||
Open (File_In, In_File, Z_File_Name);
|
||||
Create (File_Out, Out_File, Out_File_Name);
|
||||
|
||||
Stamp;
|
||||
|
||||
-- Inflate using generic instantiation.
|
||||
|
||||
ZLib.Inflate_Init (Filter, Header => Header);
|
||||
|
||||
Translate (Filter);
|
||||
Print_Statistic ("Generic decompress", ZLib.Total_Out (Filter));
|
||||
|
||||
ZLib.Close (Filter);
|
||||
|
||||
Close (File_In);
|
||||
Close (File_Out);
|
||||
|
||||
Compare_Files (In_File_Name, Out_File_Name);
|
||||
|
||||
-- Test stream interface.
|
||||
|
||||
-- Compress to the back stream.
|
||||
|
||||
Open (File_In, In_File, In_File_Name);
|
||||
Create (File_Back, Out_File, Z_File_Name);
|
||||
|
||||
Stamp;
|
||||
|
||||
ZLib.Streams.Create
|
||||
(Stream => File_Z,
|
||||
Mode => ZLib.Streams.Out_Stream,
|
||||
Back => ZLib.Streams.Stream_Access
|
||||
(Stream (File_Back)),
|
||||
Back_Compressed => True,
|
||||
Level => Level,
|
||||
Strategy => Strategy,
|
||||
Header => Header);
|
||||
|
||||
Copy_Streams
|
||||
(Source => Stream (File_In).all,
|
||||
Target => File_Z);
|
||||
|
||||
-- Flushing internal buffers to the back stream.
|
||||
|
||||
ZLib.Streams.Flush (File_Z, ZLib.Finish);
|
||||
|
||||
Print_Statistic ("Write compress",
|
||||
ZLib.Streams.Write_Total_Out (File_Z));
|
||||
|
||||
ZLib.Streams.Close (File_Z);
|
||||
|
||||
Close (File_In);
|
||||
Close (File_Back);
|
||||
|
||||
-- Compare reading from original file and from
|
||||
-- decompression stream.
|
||||
|
||||
Open (File_In, In_File, In_File_Name);
|
||||
Open (File_Back, In_File, Z_File_Name);
|
||||
|
||||
ZLib.Streams.Create
|
||||
(Stream => File_Z,
|
||||
Mode => ZLib.Streams.In_Stream,
|
||||
Back => ZLib.Streams.Stream_Access
|
||||
(Stream (File_Back)),
|
||||
Back_Compressed => True,
|
||||
Header => Header);
|
||||
|
||||
Stamp;
|
||||
Compare_Streams (Stream (File_In).all, File_Z);
|
||||
|
||||
Print_Statistic ("Read decompress",
|
||||
ZLib.Streams.Read_Total_Out (File_Z));
|
||||
|
||||
ZLib.Streams.Close (File_Z);
|
||||
Close (File_In);
|
||||
Close (File_Back);
|
||||
|
||||
-- Compress by reading from compression stream.
|
||||
|
||||
Open (File_Back, In_File, In_File_Name);
|
||||
Create (File_Out, Out_File, Z_File_Name);
|
||||
|
||||
ZLib.Streams.Create
|
||||
(Stream => File_Z,
|
||||
Mode => ZLib.Streams.In_Stream,
|
||||
Back => ZLib.Streams.Stream_Access
|
||||
(Stream (File_Back)),
|
||||
Back_Compressed => False,
|
||||
Level => Level,
|
||||
Strategy => Strategy,
|
||||
Header => Header);
|
||||
|
||||
Stamp;
|
||||
Copy_Streams
|
||||
(Source => File_Z,
|
||||
Target => Stream (File_Out).all);
|
||||
|
||||
Print_Statistic ("Read compress",
|
||||
ZLib.Streams.Read_Total_Out (File_Z));
|
||||
|
||||
ZLib.Streams.Close (File_Z);
|
||||
|
||||
Close (File_Out);
|
||||
Close (File_Back);
|
||||
|
||||
-- Decompress to decompression stream.
|
||||
|
||||
Open (File_In, In_File, Z_File_Name);
|
||||
Create (File_Back, Out_File, Out_File_Name);
|
||||
|
||||
ZLib.Streams.Create
|
||||
(Stream => File_Z,
|
||||
Mode => ZLib.Streams.Out_Stream,
|
||||
Back => ZLib.Streams.Stream_Access
|
||||
(Stream (File_Back)),
|
||||
Back_Compressed => False,
|
||||
Header => Header);
|
||||
|
||||
Stamp;
|
||||
|
||||
Copy_Streams
|
||||
(Source => Stream (File_In).all,
|
||||
Target => File_Z);
|
||||
|
||||
Print_Statistic ("Write decompress",
|
||||
ZLib.Streams.Write_Total_Out (File_Z));
|
||||
|
||||
ZLib.Streams.Close (File_Z);
|
||||
Close (File_In);
|
||||
Close (File_Back);
|
||||
|
||||
Compare_Files (In_File_Name, Out_File_Name);
|
||||
end loop;
|
||||
|
||||
Ada.Text_IO.Put_Line (Count'Image (File_Size) & " Ok.");
|
||||
|
||||
exit when not Continuous;
|
||||
|
||||
File_Size := File_Size + 1;
|
||||
end loop;
|
||||
end Test;
|
225
third_party/zlib/contrib/ada/zlib-streams.adb
vendored
225
third_party/zlib/contrib/ada/zlib-streams.adb
vendored
@ -1,225 +0,0 @@
|
||||
----------------------------------------------------------------
|
||||
-- ZLib for Ada thick binding. --
|
||||
-- --
|
||||
-- Copyright (C) 2002-2003 Dmitriy Anisimkov --
|
||||
-- --
|
||||
-- Open source license information is in the zlib.ads file. --
|
||||
----------------------------------------------------------------
|
||||
|
||||
-- $Id: zlib-streams.adb,v 1.10 2004/05/31 10:53:40 vagul Exp $
|
||||
|
||||
with Ada.Unchecked_Deallocation;
|
||||
|
||||
package body ZLib.Streams is
|
||||
|
||||
-----------
|
||||
-- Close --
|
||||
-----------
|
||||
|
||||
procedure Close (Stream : in out Stream_Type) is
|
||||
procedure Free is new Ada.Unchecked_Deallocation
|
||||
(Stream_Element_Array, Buffer_Access);
|
||||
begin
|
||||
if Stream.Mode = Out_Stream or Stream.Mode = Duplex then
|
||||
-- We should flush the data written by the writer.
|
||||
|
||||
Flush (Stream, Finish);
|
||||
|
||||
Close (Stream.Writer);
|
||||
end if;
|
||||
|
||||
if Stream.Mode = In_Stream or Stream.Mode = Duplex then
|
||||
Close (Stream.Reader);
|
||||
Free (Stream.Buffer);
|
||||
end if;
|
||||
end Close;
|
||||
|
||||
------------
|
||||
-- Create --
|
||||
------------
|
||||
|
||||
procedure Create
|
||||
(Stream : out Stream_Type;
|
||||
Mode : in Stream_Mode;
|
||||
Back : in Stream_Access;
|
||||
Back_Compressed : in Boolean;
|
||||
Level : in Compression_Level := Default_Compression;
|
||||
Strategy : in Strategy_Type := Default_Strategy;
|
||||
Header : in Header_Type := Default;
|
||||
Read_Buffer_Size : in Ada.Streams.Stream_Element_Offset
|
||||
:= Default_Buffer_Size;
|
||||
Write_Buffer_Size : in Ada.Streams.Stream_Element_Offset
|
||||
:= Default_Buffer_Size)
|
||||
is
|
||||
|
||||
subtype Buffer_Subtype is Stream_Element_Array (1 .. Read_Buffer_Size);
|
||||
|
||||
procedure Init_Filter
|
||||
(Filter : in out Filter_Type;
|
||||
Compress : in Boolean);
|
||||
|
||||
-----------------
|
||||
-- Init_Filter --
|
||||
-----------------
|
||||
|
||||
procedure Init_Filter
|
||||
(Filter : in out Filter_Type;
|
||||
Compress : in Boolean) is
|
||||
begin
|
||||
if Compress then
|
||||
Deflate_Init
|
||||
(Filter, Level, Strategy, Header => Header);
|
||||
else
|
||||
Inflate_Init (Filter, Header => Header);
|
||||
end if;
|
||||
end Init_Filter;
|
||||
|
||||
begin
|
||||
Stream.Back := Back;
|
||||
Stream.Mode := Mode;
|
||||
|
||||
if Mode = Out_Stream or Mode = Duplex then
|
||||
Init_Filter (Stream.Writer, Back_Compressed);
|
||||
Stream.Buffer_Size := Write_Buffer_Size;
|
||||
else
|
||||
Stream.Buffer_Size := 0;
|
||||
end if;
|
||||
|
||||
if Mode = In_Stream or Mode = Duplex then
|
||||
Init_Filter (Stream.Reader, not Back_Compressed);
|
||||
|
||||
Stream.Buffer := new Buffer_Subtype;
|
||||
Stream.Rest_First := Stream.Buffer'Last + 1;
|
||||
Stream.Rest_Last := Stream.Buffer'Last;
|
||||
end if;
|
||||
end Create;
|
||||
|
||||
-----------
|
||||
-- Flush --
|
||||
-----------
|
||||
|
||||
procedure Flush
|
||||
(Stream : in out Stream_Type;
|
||||
Mode : in Flush_Mode := Sync_Flush)
|
||||
is
|
||||
Buffer : Stream_Element_Array (1 .. Stream.Buffer_Size);
|
||||
Last : Stream_Element_Offset;
|
||||
begin
|
||||
loop
|
||||
Flush (Stream.Writer, Buffer, Last, Mode);
|
||||
|
||||
Ada.Streams.Write (Stream.Back.all, Buffer (1 .. Last));
|
||||
|
||||
exit when Last < Buffer'Last;
|
||||
end loop;
|
||||
end Flush;
|
||||
|
||||
-------------
|
||||
-- Is_Open --
|
||||
-------------
|
||||
|
||||
function Is_Open (Stream : Stream_Type) return Boolean is
|
||||
begin
|
||||
return Is_Open (Stream.Reader) or else Is_Open (Stream.Writer);
|
||||
end Is_Open;
|
||||
|
||||
----------
|
||||
-- Read --
|
||||
----------
|
||||
|
||||
procedure Read
|
||||
(Stream : in out Stream_Type;
|
||||
Item : out Stream_Element_Array;
|
||||
Last : out Stream_Element_Offset)
|
||||
is
|
||||
|
||||
procedure Read
|
||||
(Item : out Stream_Element_Array;
|
||||
Last : out Stream_Element_Offset);
|
||||
|
||||
----------
|
||||
-- Read --
|
||||
----------
|
||||
|
||||
procedure Read
|
||||
(Item : out Stream_Element_Array;
|
||||
Last : out Stream_Element_Offset) is
|
||||
begin
|
||||
Ada.Streams.Read (Stream.Back.all, Item, Last);
|
||||
end Read;
|
||||
|
||||
procedure Read is new ZLib.Read
|
||||
(Read => Read,
|
||||
Buffer => Stream.Buffer.all,
|
||||
Rest_First => Stream.Rest_First,
|
||||
Rest_Last => Stream.Rest_Last);
|
||||
|
||||
begin
|
||||
Read (Stream.Reader, Item, Last);
|
||||
end Read;
|
||||
|
||||
-------------------
|
||||
-- Read_Total_In --
|
||||
-------------------
|
||||
|
||||
function Read_Total_In (Stream : in Stream_Type) return Count is
|
||||
begin
|
||||
return Total_In (Stream.Reader);
|
||||
end Read_Total_In;
|
||||
|
||||
--------------------
|
||||
-- Read_Total_Out --
|
||||
--------------------
|
||||
|
||||
function Read_Total_Out (Stream : in Stream_Type) return Count is
|
||||
begin
|
||||
return Total_Out (Stream.Reader);
|
||||
end Read_Total_Out;
|
||||
|
||||
-----------
|
||||
-- Write --
|
||||
-----------
|
||||
|
||||
procedure Write
|
||||
(Stream : in out Stream_Type;
|
||||
Item : in Stream_Element_Array)
|
||||
is
|
||||
|
||||
procedure Write (Item : in Stream_Element_Array);
|
||||
|
||||
-----------
|
||||
-- Write --
|
||||
-----------
|
||||
|
||||
procedure Write (Item : in Stream_Element_Array) is
|
||||
begin
|
||||
Ada.Streams.Write (Stream.Back.all, Item);
|
||||
end Write;
|
||||
|
||||
procedure Write is new ZLib.Write
|
||||
(Write => Write,
|
||||
Buffer_Size => Stream.Buffer_Size);
|
||||
|
||||
begin
|
||||
Write (Stream.Writer, Item, No_Flush);
|
||||
end Write;
|
||||
|
||||
--------------------
|
||||
-- Write_Total_In --
|
||||
--------------------
|
||||
|
||||
function Write_Total_In (Stream : in Stream_Type) return Count is
|
||||
begin
|
||||
return Total_In (Stream.Writer);
|
||||
end Write_Total_In;
|
||||
|
||||
---------------------
|
||||
-- Write_Total_Out --
|
||||
---------------------
|
||||
|
||||
function Write_Total_Out (Stream : in Stream_Type) return Count is
|
||||
begin
|
||||
return Total_Out (Stream.Writer);
|
||||
end Write_Total_Out;
|
||||
|
||||
end ZLib.Streams;
|
114
third_party/zlib/contrib/ada/zlib-streams.ads
vendored
114
third_party/zlib/contrib/ada/zlib-streams.ads
vendored
@ -1,114 +0,0 @@
|
||||
----------------------------------------------------------------
|
||||
-- ZLib for Ada thick binding. --
|
||||
-- --
|
||||
-- Copyright (C) 2002-2003 Dmitriy Anisimkov --
|
||||
-- --
|
||||
-- Open source license information is in the zlib.ads file. --
|
||||
----------------------------------------------------------------
|
||||
|
||||
-- $Id: zlib-streams.ads,v 1.12 2004/05/31 10:53:40 vagul Exp $
|
||||
|
||||
package ZLib.Streams is
|
||||
|
||||
type Stream_Mode is (In_Stream, Out_Stream, Duplex);
|
||||
|
||||
type Stream_Access is access all Ada.Streams.Root_Stream_Type'Class;
|
||||
|
||||
type Stream_Type is
|
||||
new Ada.Streams.Root_Stream_Type with private;
|
||||
|
||||
procedure Read
|
||||
(Stream : in out Stream_Type;
|
||||
Item : out Ada.Streams.Stream_Element_Array;
|
||||
Last : out Ada.Streams.Stream_Element_Offset);
|
||||
|
||||
procedure Write
|
||||
(Stream : in out Stream_Type;
|
||||
Item : in Ada.Streams.Stream_Element_Array);
|
||||
|
||||
procedure Flush
|
||||
(Stream : in out Stream_Type;
|
||||
Mode : in Flush_Mode := Sync_Flush);
|
||||
-- Flush the written data to the back stream,
|
||||
-- all data placed to the compressor is flushing to the Back stream.
|
||||
-- Should not be used until necessary, because it is decreasing
|
||||
-- compression.
|
||||
|
||||
function Read_Total_In (Stream : in Stream_Type) return Count;
|
||||
pragma Inline (Read_Total_In);
|
||||
-- Return total number of bytes read from back stream so far.
|
||||
|
||||
function Read_Total_Out (Stream : in Stream_Type) return Count;
|
||||
pragma Inline (Read_Total_Out);
|
||||
-- Return total number of bytes read so far.
|
||||
|
||||
function Write_Total_In (Stream : in Stream_Type) return Count;
|
||||
pragma Inline (Write_Total_In);
|
||||
-- Return total number of bytes written so far.
|
||||
|
||||
function Write_Total_Out (Stream : in Stream_Type) return Count;
|
||||
pragma Inline (Write_Total_Out);
|
||||
-- Return total number of bytes written to the back stream.
|
||||
|
||||
procedure Create
|
||||
(Stream : out Stream_Type;
|
||||
Mode : in Stream_Mode;
|
||||
Back : in Stream_Access;
|
||||
Back_Compressed : in Boolean;
|
||||
Level : in Compression_Level := Default_Compression;
|
||||
Strategy : in Strategy_Type := Default_Strategy;
|
||||
Header : in Header_Type := Default;
|
||||
Read_Buffer_Size : in Ada.Streams.Stream_Element_Offset
|
||||
:= Default_Buffer_Size;
|
||||
Write_Buffer_Size : in Ada.Streams.Stream_Element_Offset
|
||||
:= Default_Buffer_Size);
|
||||
-- Create the Comression/Decompression stream.
|
||||
-- If mode is In_Stream then Write operation is disabled.
|
||||
-- If mode is Out_Stream then Read operation is disabled.
|
||||
|
||||
-- If Back_Compressed is true then
|
||||
-- Data written to the Stream is compressing to the Back stream
|
||||
-- and data read from the Stream is decompressed data from the Back stream.
|
||||
|
||||
-- If Back_Compressed is false then
|
||||
-- Data written to the Stream is decompressing to the Back stream
|
||||
-- and data read from the Stream is compressed data from the Back stream.
|
||||
|
||||
-- !!! When the Need_Header is False ZLib-Ada is using undocumented
|
||||
-- ZLib 1.1.4 functionality to do not create/wait for ZLib headers.
|
||||
|
||||
function Is_Open (Stream : Stream_Type) return Boolean;
|
||||
|
||||
procedure Close (Stream : in out Stream_Type);
|
||||
|
||||
private
|
||||
|
||||
use Ada.Streams;
|
||||
|
||||
type Buffer_Access is access all Stream_Element_Array;
|
||||
|
||||
type Stream_Type
|
||||
is new Root_Stream_Type with
|
||||
record
|
||||
Mode : Stream_Mode;
|
||||
|
||||
Buffer : Buffer_Access;
|
||||
Rest_First : Stream_Element_Offset;
|
||||
Rest_Last : Stream_Element_Offset;
|
||||
-- Buffer for Read operation.
|
||||
-- We need to have this buffer in the record
|
||||
-- because not all read data from back stream
|
||||
-- could be processed during the read operation.
|
||||
|
||||
Buffer_Size : Stream_Element_Offset;
|
||||
-- Buffer size for write operation.
|
||||
-- We do not need to have this buffer
|
||||
-- in the record because all data could be
|
||||
-- processed in the write operation.
|
||||
|
||||
Back : Stream_Access;
|
||||
Reader : Filter_Type;
|
||||
Writer : Filter_Type;
|
||||
end record;
|
||||
|
||||
end ZLib.Streams;
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user