(build) make using zlib optional, with the caveat that some http and websocket features are not available when zlib is absent

This commit is contained in:
Benjamin Sergeant 2020-07-31 22:54:57 -07:00
parent 2e3d625c1e
commit 6f0307fb35
13 changed files with 85 additions and 11 deletions

View File

@ -10,12 +10,10 @@ jobs:
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- uses: seanmiddleditch/gha-setup-vsdevenv@master - uses: seanmiddleditch/gha-setup-vsdevenv@master
- run: |
vcpkg install zlib:x64-uwp
- run: | - run: |
mkdir build mkdir build
cd 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 .. 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 -DUSE_ZLIB=0 ..
- run: cmake --build build - run: cmake --build build
# #

View File

@ -10,10 +10,11 @@ jobs:
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- uses: seanmiddleditch/gha-setup-vsdevenv@master - uses: seanmiddleditch/gha-setup-vsdevenv@master
- run: |
vcpkg install zlib:x64-windows
- run: | - run: |
mkdir build mkdir build
cd build cd build
cmake -DCMAKE_TOOLCHAIN_FILE=c:/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_CXX_COMPILER=cl.exe -DUSE_WS=1 -DUSE_TEST=1 .. cmake -DCMAKE_CXX_COMPILER=cl.exe -DUSE_WS=1 -DUSE_TEST=1 -DUSE_ZLIB=0 ..
- run: cmake --build build - run: cmake --build build
#- run: ../build/test/ixwebsocket_unittest.exe
# working-directory: test

View File

@ -190,10 +190,16 @@ if (USE_TLS)
endif() endif()
endif() endif()
# Use ZLIB_ROOT CMake variable if you need to use your own zlib option(USE_ZLIB "Enable zlib support" TRUE)
find_package(ZLIB REQUIRED)
include_directories(${ZLIB_INCLUDE_DIRS}) if (USE_ZLIB)
target_link_libraries(ixwebsocket ${ZLIB_LIBRARIES}) # 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})
target_compile_definitions(ixwebsocket PUBLIC IXWEBSOCKET_USE_ZLIB)
endif()
if (WIN32) if (WIN32)
target_link_libraries(ixwebsocket wsock32 ws2_32 shlwapi) target_link_libraries(ixwebsocket wsock32 ws2_32 shlwapi)

View File

@ -1,6 +1,10 @@
# Changelog # Changelog
All changes to this project will be documented in this file. All changes to this project will be documented in this file.
## [10.1.2] - 2020-07-31
(build) make using zlib optional, with the caveat that some http and websocket features are not available when zlib is absent
## [10.1.1] - 2020-07-29 ## [10.1.1] - 2020-07-29
(websocket client) onProgressCallback not called for short messages on a websocket (fix #233) (websocket client) onProgressCallback not called for short messages on a websocket (fix #233)

View File

@ -17,6 +17,7 @@ There is a unittest which can be executed by typing `make test`.
Options for building: Options for building:
* `-DUSE_ZLIB=1` will enable zlib support, required for http client + server + websocket per message deflate extension
* `-DUSE_TLS=1` will enable TLS support * `-DUSE_TLS=1` will enable TLS support
* `-DUSE_OPEN_SSL=1` will use [openssl](https://www.openssl.org/) for the TLS support (default on Linux and Windows) * `-DUSE_OPEN_SSL=1` will use [openssl](https://www.openssl.org/) for the TLS support (default on Linux and Windows)
* `-DUSE_MBED_TLS=1` will use [mbedlts](https://tls.mbed.org/) for the TLS support * `-DUSE_MBED_TLS=1` will use [mbedlts](https://tls.mbed.org/) for the TLS support

View File

@ -16,7 +16,10 @@
#include <random> #include <random>
#include <sstream> #include <sstream>
#include <vector> #include <vector>
#ifdef IXWEBSOCKET_USE_ZLIB
#include <zlib.h> #include <zlib.h>
#endif
namespace ix namespace ix
{ {
@ -174,11 +177,13 @@ namespace ix
ss << verb << " " << path << " HTTP/1.1\r\n"; ss << verb << " " << path << " HTTP/1.1\r\n";
ss << "Host: " << host << "\r\n"; ss << "Host: " << host << "\r\n";
#ifdef IXWEBSOCKET_USE_ZLIB
if (args->compress) if (args->compress)
{ {
ss << "Accept-Encoding: gzip" ss << "Accept-Encoding: gzip"
<< "\r\n"; << "\r\n";
} }
#endif
// Append extra headers // Append extra headers
for (auto&& it : args->extraHeaders) for (auto&& it : args->extraHeaders)
@ -495,6 +500,7 @@ namespace ix
downloadSize = payload.size(); downloadSize = payload.size();
#ifdef IXWEBSOCKET_USE_ZLIB
// If the content was compressed with gzip, decode it // If the content was compressed with gzip, decode it
if (headers["Content-Encoding"] == "gzip") if (headers["Content-Encoding"] == "gzip")
{ {
@ -513,6 +519,7 @@ namespace ix
} }
payload = decompressedPayload; payload = decompressedPayload;
} }
#endif
return std::make_shared<HttpResponse>(code, return std::make_shared<HttpResponse>(code,
description, description,
@ -672,6 +679,7 @@ namespace ix
return ss.str(); return ss.str();
} }
#ifdef IXWEBSOCKET_USE_ZLIB
bool HttpClient::gzipInflate(const std::string& in, std::string& out) bool HttpClient::gzipInflate(const std::string& in, std::string& out)
{ {
z_stream inflateState; z_stream inflateState;
@ -716,6 +724,7 @@ namespace ix
inflateEnd(&inflateState); inflateEnd(&inflateState);
return true; return true;
} }
#endif
void HttpClient::log(const std::string& msg, HttpRequestArgsPtr args) void HttpClient::log(const std::string& msg, HttpRequestArgsPtr args)
{ {

View File

@ -90,7 +90,9 @@ namespace ix
private: private:
void log(const std::string& msg, HttpRequestArgsPtr args); void log(const std::string& msg, HttpRequestArgsPtr args);
#ifdef IXWEBSOCKET_USE_ZLIB
bool gzipInflate(const std::string& in, std::string& out); bool gzipInflate(const std::string& in, std::string& out);
#endif
// Async API background thread runner // Async API background thread runner
void run(); void run();

View File

@ -13,7 +13,10 @@
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
#include <vector> #include <vector>
#ifdef IXWEBSOCKET_USE_ZLIB
#include <zlib.h> #include <zlib.h>
#endif
namespace namespace
{ {
@ -41,6 +44,7 @@ namespace
return std::make_pair(res.first, std::string(vec.begin(), vec.end())); return std::make_pair(res.first, std::string(vec.begin(), vec.end()));
} }
#ifdef IXWEBSOCKET_USE_ZLIB
std::string gzipCompress(const std::string& str) std::string gzipCompress(const std::string& str)
{ {
z_stream zs; // z_stream is zlib's control structure z_stream zs; // z_stream is zlib's control structure
@ -83,6 +87,7 @@ namespace
return outstring; return outstring;
} }
#endif
} // namespace } // namespace
namespace ix namespace ix
@ -168,12 +173,14 @@ namespace ix
std::string content = res.second; std::string content = res.second;
#ifdef IXWEBSOCKET_USE_ZLIB
std::string acceptEncoding = request->headers["Accept-encoding"]; std::string acceptEncoding = request->headers["Accept-encoding"];
if (acceptEncoding == "*" || acceptEncoding.find("gzip") != std::string::npos) if (acceptEncoding == "*" || acceptEncoding.find("gzip") != std::string::npos)
{ {
content = gzipCompress(content); content = gzipCompress(content);
headers["Content-Encoding"] = "gzip"; headers["Content-Encoding"] = "gzip";
} }
#endif
// Log request // Log request
std::stringstream ss; std::stringstream ss;

View File

@ -8,7 +8,9 @@
#include "IXWebSocketVersion.h" #include "IXWebSocketVersion.h"
#include <sstream> #include <sstream>
#ifdef IXWEBSOCKET_USE_ZLIB
#include <zlib.h> #include <zlib.h>
#endif
// Platform name // Platform name
#if defined(_WIN32) #if defined(_WIN32)
@ -77,8 +79,10 @@ namespace ix
ss << " nossl"; ss << " nossl";
#endif #endif
#ifdef IXWEBSOCKET_USE_ZLIB
// Zlib version // Zlib version
ss << " zlib " << ZLIB_VERSION; ss << " zlib " << ZLIB_VERSION;
#endif
return ss.str(); return ss.str();
} }

View File

@ -28,21 +28,26 @@ namespace ix
WebSocketPerMessageDeflateCompressor::WebSocketPerMessageDeflateCompressor() WebSocketPerMessageDeflateCompressor::WebSocketPerMessageDeflateCompressor()
: _compressBufferSize(kBufferSize) : _compressBufferSize(kBufferSize)
{ {
#ifdef IXWEBSOCKET_USE_ZLIB
memset(&_deflateState, 0, sizeof(_deflateState)); memset(&_deflateState, 0, sizeof(_deflateState));
_deflateState.zalloc = Z_NULL; _deflateState.zalloc = Z_NULL;
_deflateState.zfree = Z_NULL; _deflateState.zfree = Z_NULL;
_deflateState.opaque = Z_NULL; _deflateState.opaque = Z_NULL;
#endif
} }
WebSocketPerMessageDeflateCompressor::~WebSocketPerMessageDeflateCompressor() WebSocketPerMessageDeflateCompressor::~WebSocketPerMessageDeflateCompressor()
{ {
#ifdef IXWEBSOCKET_USE_ZLIB
deflateEnd(&_deflateState); deflateEnd(&_deflateState);
#endif
} }
bool WebSocketPerMessageDeflateCompressor::init(uint8_t deflateBits, bool WebSocketPerMessageDeflateCompressor::init(uint8_t deflateBits,
bool clientNoContextTakeOver) bool clientNoContextTakeOver)
{ {
#ifdef IXWEBSOCKET_USE_ZLIB
int ret = deflateInit2(&_deflateState, int ret = deflateInit2(&_deflateState,
Z_DEFAULT_COMPRESSION, Z_DEFAULT_COMPRESSION,
Z_DEFLATED, Z_DEFLATED,
@ -57,6 +62,9 @@ namespace ix
_flush = (clientNoContextTakeOver) ? Z_FULL_FLUSH : Z_SYNC_FLUSH; _flush = (clientNoContextTakeOver) ? Z_FULL_FLUSH : Z_SYNC_FLUSH;
return true; return true;
#else
return false;
#endif
} }
template<typename T> template<typename T>
@ -96,6 +104,7 @@ namespace ix
template<typename T, typename S> template<typename T, typename S>
bool WebSocketPerMessageDeflateCompressor::compressData(const T& in, S& out) bool WebSocketPerMessageDeflateCompressor::compressData(const T& in, S& out)
{ {
#ifdef IXWEBSOCKET_USE_ZLIB
// //
// 7.2.1. Compression // 7.2.1. Compression
// //
@ -152,6 +161,9 @@ namespace ix
} }
return true; return true;
#else
return false;
#endif
} }
// //
@ -160,6 +172,7 @@ namespace ix
WebSocketPerMessageDeflateDecompressor::WebSocketPerMessageDeflateDecompressor() WebSocketPerMessageDeflateDecompressor::WebSocketPerMessageDeflateDecompressor()
: _compressBufferSize(kBufferSize) : _compressBufferSize(kBufferSize)
{ {
#ifdef IXWEBSOCKET_USE_ZLIB
memset(&_inflateState, 0, sizeof(_inflateState)); memset(&_inflateState, 0, sizeof(_inflateState));
_inflateState.zalloc = Z_NULL; _inflateState.zalloc = Z_NULL;
@ -167,16 +180,20 @@ namespace ix
_inflateState.opaque = Z_NULL; _inflateState.opaque = Z_NULL;
_inflateState.avail_in = 0; _inflateState.avail_in = 0;
_inflateState.next_in = Z_NULL; _inflateState.next_in = Z_NULL;
#endif
} }
WebSocketPerMessageDeflateDecompressor::~WebSocketPerMessageDeflateDecompressor() WebSocketPerMessageDeflateDecompressor::~WebSocketPerMessageDeflateDecompressor()
{ {
#ifdef IXWEBSOCKET_USE_ZLIB
inflateEnd(&_inflateState); inflateEnd(&_inflateState);
#endif
} }
bool WebSocketPerMessageDeflateDecompressor::init(uint8_t inflateBits, bool WebSocketPerMessageDeflateDecompressor::init(uint8_t inflateBits,
bool clientNoContextTakeOver) bool clientNoContextTakeOver)
{ {
#ifdef IXWEBSOCKET_USE_ZLIB
int ret = inflateInit2(&_inflateState, -1 * inflateBits); int ret = inflateInit2(&_inflateState, -1 * inflateBits);
if (ret != Z_OK) return false; if (ret != Z_OK) return false;
@ -186,10 +203,14 @@ namespace ix
_flush = (clientNoContextTakeOver) ? Z_FULL_FLUSH : Z_SYNC_FLUSH; _flush = (clientNoContextTakeOver) ? Z_FULL_FLUSH : Z_SYNC_FLUSH;
return true; return true;
#else
return false;
#endif
} }
bool WebSocketPerMessageDeflateDecompressor::decompress(const std::string& in, std::string& out) bool WebSocketPerMessageDeflateDecompressor::decompress(const std::string& in, std::string& out)
{ {
#ifdef IXWEBSOCKET_USE_ZLIB
// //
// 7.2.2. Decompression // 7.2.2. Decompression
// //
@ -226,5 +247,8 @@ namespace ix
} while (_inflateState.avail_out == 0); } while (_inflateState.avail_out == 0);
return true; return true;
#else
return false;
#endif
} }
} // namespace ix } // namespace ix

View File

@ -6,7 +6,9 @@
#pragma once #pragma once
#ifdef IXWEBSOCKET_USE_ZLIB
#include "zlib.h" #include "zlib.h"
#endif
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
@ -34,7 +36,10 @@ namespace ix
int _flush; int _flush;
size_t _compressBufferSize; size_t _compressBufferSize;
std::unique_ptr<unsigned char[]> _compressBuffer; std::unique_ptr<unsigned char[]> _compressBuffer;
#ifdef IXWEBSOCKET_USE_ZLIB
z_stream _deflateState; z_stream _deflateState;
#endif
}; };
class WebSocketPerMessageDeflateDecompressor class WebSocketPerMessageDeflateDecompressor
@ -50,7 +55,10 @@ namespace ix
int _flush; int _flush;
size_t _compressBufferSize; size_t _compressBufferSize;
std::unique_ptr<unsigned char[]> _compressBuffer; std::unique_ptr<unsigned char[]> _compressBuffer;
#ifdef IXWEBSOCKET_USE_ZLIB
z_stream _inflateState; z_stream _inflateState;
#endif
}; };
} // namespace ix } // namespace ix

View File

@ -61,6 +61,7 @@ namespace ix
_clientMaxWindowBits = kDefaultClientMaxWindowBits; _clientMaxWindowBits = kDefaultClientMaxWindowBits;
_serverMaxWindowBits = kDefaultServerMaxWindowBits; _serverMaxWindowBits = kDefaultServerMaxWindowBits;
#ifdef IXWEBSOCKET_USE_ZLIB
// Split by ; // Split by ;
std::string token; std::string token;
std::stringstream tokenStream(extension); std::stringstream tokenStream(extension);
@ -112,6 +113,7 @@ namespace ix
sanitizeClientMaxWindowBits(); sanitizeClientMaxWindowBits();
} }
} }
#endif
} }
void WebSocketPerMessageDeflateOptions::sanitizeClientMaxWindowBits() void WebSocketPerMessageDeflateOptions::sanitizeClientMaxWindowBits()
@ -126,6 +128,7 @@ namespace ix
std::string WebSocketPerMessageDeflateOptions::generateHeader() std::string WebSocketPerMessageDeflateOptions::generateHeader()
{ {
#ifdef IXWEBSOCKET_USE_ZLIB
std::stringstream ss; std::stringstream ss;
ss << "Sec-WebSocket-Extensions: permessage-deflate"; ss << "Sec-WebSocket-Extensions: permessage-deflate";
@ -138,11 +141,18 @@ namespace ix
ss << "\r\n"; ss << "\r\n";
return ss.str(); return ss.str();
#else
return std::string();
#endif
} }
bool WebSocketPerMessageDeflateOptions::enabled() const bool WebSocketPerMessageDeflateOptions::enabled() const
{ {
#ifdef IXWEBSOCKET_USE_ZLIB
return _enabled; return _enabled;
#else
return false;
#endif
} }
bool WebSocketPerMessageDeflateOptions::getClientNoContextTakeover() const bool WebSocketPerMessageDeflateOptions::getClientNoContextTakeover() const

View File

@ -6,4 +6,4 @@
#pragma once #pragma once
#define IX_WEBSOCKET_VERSION "10.1.1" #define IX_WEBSOCKET_VERSION "10.1.2"