(ws) add gzip and gunzip ws sub commands
This commit is contained in:
parent
6077f86af8
commit
6f188a5131
@ -31,6 +31,7 @@ set( IXWEBSOCKET_SOURCES
|
|||||||
ixwebsocket/IXDNSLookup.cpp
|
ixwebsocket/IXDNSLookup.cpp
|
||||||
ixwebsocket/IXExponentialBackoff.cpp
|
ixwebsocket/IXExponentialBackoff.cpp
|
||||||
ixwebsocket/IXGetFreePort.cpp
|
ixwebsocket/IXGetFreePort.cpp
|
||||||
|
ixwebsocket/IXGzipCodec.cpp
|
||||||
ixwebsocket/IXHttp.cpp
|
ixwebsocket/IXHttp.cpp
|
||||||
ixwebsocket/IXHttpClient.cpp
|
ixwebsocket/IXHttpClient.cpp
|
||||||
ixwebsocket/IXHttpServer.cpp
|
ixwebsocket/IXHttpServer.cpp
|
||||||
@ -66,6 +67,7 @@ set( IXWEBSOCKET_HEADERS
|
|||||||
ixwebsocket/IXDNSLookup.h
|
ixwebsocket/IXDNSLookup.h
|
||||||
ixwebsocket/IXExponentialBackoff.h
|
ixwebsocket/IXExponentialBackoff.h
|
||||||
ixwebsocket/IXGetFreePort.h
|
ixwebsocket/IXGetFreePort.h
|
||||||
|
ixwebsocket/IXGzipCodec.h
|
||||||
ixwebsocket/IXHttp.h
|
ixwebsocket/IXHttp.h
|
||||||
ixwebsocket/IXHttpClient.h
|
ixwebsocket/IXHttpClient.h
|
||||||
ixwebsocket/IXHttpServer.h
|
ixwebsocket/IXHttpServer.h
|
||||||
|
@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
All changes to this project will be documented in this file.
|
All changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
## [10.4.7] - 2020-09-28
|
||||||
|
|
||||||
|
(ws) add gzip and gunzip ws sub commands
|
||||||
|
|
||||||
## [10.4.6] - 2020-09-26
|
## [10.4.6] - 2020-09-26
|
||||||
|
|
||||||
(cmake) use FetchContent cmake module to retrieve jsoncpp third party dependency
|
(cmake) use FetchContent cmake module to retrieve jsoncpp third party dependency
|
||||||
|
@ -19,4 +19,16 @@ namespace ix
|
|||||||
|
|
||||||
return hashAddress;
|
return hashAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t djb2HashStr(const std::string& data)
|
||||||
|
{
|
||||||
|
uint64_t hashAddress = 5381;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < data.size(); ++i)
|
||||||
|
{
|
||||||
|
hashAddress = ((hashAddress << 5) + hashAddress) + data[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return hashAddress;
|
||||||
|
}
|
||||||
} // namespace ix
|
} // namespace ix
|
||||||
|
@ -8,8 +8,10 @@
|
|||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace ix
|
namespace ix
|
||||||
{
|
{
|
||||||
uint64_t djb2Hash(const std::vector<uint8_t>& data);
|
uint64_t djb2Hash(const std::vector<uint8_t>& data);
|
||||||
|
uint64_t djb2HashStr(const std::string& data);
|
||||||
}
|
}
|
||||||
|
104
ixwebsocket/IXGzipCodec.cpp
Normal file
104
ixwebsocket/IXGzipCodec.cpp
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* IXGzipCodec.cpp
|
||||||
|
* Author: Benjamin Sergeant
|
||||||
|
* Copyright (c) 2020 Machine Zone, Inc. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "IXGzipCodec.h"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
#ifdef IXWEBSOCKET_USE_ZLIB
|
||||||
|
#include <zlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ix
|
||||||
|
{
|
||||||
|
#ifdef IXWEBSOCKET_USE_ZLIB
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gzipDecompress(const std::string& in, std::string& out)
|
||||||
|
{
|
||||||
|
z_stream inflateState;
|
||||||
|
std::memset(&inflateState, 0, sizeof(inflateState));
|
||||||
|
|
||||||
|
inflateState.zalloc = Z_NULL;
|
||||||
|
inflateState.zfree = Z_NULL;
|
||||||
|
inflateState.opaque = Z_NULL;
|
||||||
|
inflateState.avail_in = 0;
|
||||||
|
inflateState.next_in = Z_NULL;
|
||||||
|
|
||||||
|
if (inflateInit2(&inflateState, 16 + MAX_WBITS) != Z_OK)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
inflateState.avail_in = (uInt) in.size();
|
||||||
|
inflateState.next_in = (unsigned char*) (const_cast<char*>(in.data()));
|
||||||
|
|
||||||
|
const int kBufferSize = 1 << 14;
|
||||||
|
std::array<unsigned char, kBufferSize> compressBuffer;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
inflateState.avail_out = (uInt) kBufferSize;
|
||||||
|
inflateState.next_out = &compressBuffer.front();
|
||||||
|
|
||||||
|
int ret = inflate(&inflateState, Z_SYNC_FLUSH);
|
||||||
|
|
||||||
|
if (ret == Z_NEED_DICT || ret == Z_DATA_ERROR || ret == Z_MEM_ERROR)
|
||||||
|
{
|
||||||
|
inflateEnd(&inflateState);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
out.append(reinterpret_cast<char*>(&compressBuffer.front()),
|
||||||
|
kBufferSize - inflateState.avail_out);
|
||||||
|
} while (inflateState.avail_out == 0);
|
||||||
|
|
||||||
|
inflateEnd(&inflateState);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} // namespace ix
|
15
ixwebsocket/IXGzipCodec.h
Normal file
15
ixwebsocket/IXGzipCodec.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* IXGzipCodec.h
|
||||||
|
* Author: Benjamin Sergeant
|
||||||
|
* Copyright (c) 2020 Machine Zone, Inc. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace ix
|
||||||
|
{
|
||||||
|
std::string gzipCompress(const std::string& str);
|
||||||
|
bool gzipDecompress(const std::string& in, std::string& out);
|
||||||
|
} // namespace ix
|
@ -6,11 +6,11 @@
|
|||||||
|
|
||||||
#include "IXHttpClient.h"
|
#include "IXHttpClient.h"
|
||||||
|
|
||||||
|
#include "IXGzipCodec.h"
|
||||||
#include "IXSocketFactory.h"
|
#include "IXSocketFactory.h"
|
||||||
#include "IXUrlParser.h"
|
#include "IXUrlParser.h"
|
||||||
#include "IXUserAgent.h"
|
#include "IXUserAgent.h"
|
||||||
#include "IXWebSocketHttpHeaders.h"
|
#include "IXWebSocketHttpHeaders.h"
|
||||||
#include <array>
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
@ -18,10 +18,6 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#ifdef IXWEBSOCKET_USE_ZLIB
|
|
||||||
#include <zlib.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace ix
|
namespace ix
|
||||||
{
|
{
|
||||||
const std::string HttpClient::kPost = "POST";
|
const std::string HttpClient::kPost = "POST";
|
||||||
@ -501,12 +497,12 @@ 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")
|
||||||
{
|
{
|
||||||
|
#ifdef IXWEBSOCKET_USE_ZLIB
|
||||||
std::string decompressedPayload;
|
std::string decompressedPayload;
|
||||||
if (!gzipInflate(payload, decompressedPayload))
|
if (!gzipDecompress(payload, decompressedPayload))
|
||||||
{
|
{
|
||||||
std::string errorMsg("Error decompressing payload");
|
std::string errorMsg("Error decompressing payload");
|
||||||
return std::make_shared<HttpResponse>(code,
|
return std::make_shared<HttpResponse>(code,
|
||||||
@ -519,8 +515,18 @@ namespace ix
|
|||||||
downloadSize);
|
downloadSize);
|
||||||
}
|
}
|
||||||
payload = decompressedPayload;
|
payload = decompressedPayload;
|
||||||
}
|
#else
|
||||||
|
std::string errorMsg("ixwebsocket was not compiled with gzip support on");
|
||||||
|
return std::make_shared<HttpResponse>(code,
|
||||||
|
description,
|
||||||
|
HttpErrorCode::Gzip,
|
||||||
|
headers,
|
||||||
|
payload,
|
||||||
|
errorMsg,
|
||||||
|
uploadSize,
|
||||||
|
downloadSize);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
return std::make_shared<HttpResponse>(code,
|
return std::make_shared<HttpResponse>(code,
|
||||||
description,
|
description,
|
||||||
@ -680,51 +686,6 @@ namespace ix
|
|||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef IXWEBSOCKET_USE_ZLIB
|
|
||||||
bool HttpClient::gzipInflate(const std::string& in, std::string& out)
|
|
||||||
{
|
|
||||||
z_stream inflateState;
|
|
||||||
std::memset(&inflateState, 0, sizeof(inflateState));
|
|
||||||
|
|
||||||
inflateState.zalloc = Z_NULL;
|
|
||||||
inflateState.zfree = Z_NULL;
|
|
||||||
inflateState.opaque = Z_NULL;
|
|
||||||
inflateState.avail_in = 0;
|
|
||||||
inflateState.next_in = Z_NULL;
|
|
||||||
|
|
||||||
if (inflateInit2(&inflateState, 16 + MAX_WBITS) != Z_OK)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
inflateState.avail_in = (uInt) in.size();
|
|
||||||
inflateState.next_in = (unsigned char*) (const_cast<char*>(in.data()));
|
|
||||||
|
|
||||||
const int kBufferSize = 1 << 14;
|
|
||||||
std::array<unsigned char, kBufferSize> compressBuffer;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
inflateState.avail_out = (uInt) kBufferSize;
|
|
||||||
inflateState.next_out = &compressBuffer.front();
|
|
||||||
|
|
||||||
int ret = inflate(&inflateState, Z_SYNC_FLUSH);
|
|
||||||
|
|
||||||
if (ret == Z_NEED_DICT || ret == Z_DATA_ERROR || ret == Z_MEM_ERROR)
|
|
||||||
{
|
|
||||||
inflateEnd(&inflateState);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
out.append(reinterpret_cast<char*>(&compressBuffer.front()),
|
|
||||||
kBufferSize - inflateState.avail_out);
|
|
||||||
} while (inflateState.avail_out == 0);
|
|
||||||
|
|
||||||
inflateEnd(&inflateState);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void HttpClient::log(const std::string& msg, HttpRequestArgsPtr args)
|
void HttpClient::log(const std::string& msg, HttpRequestArgsPtr args)
|
||||||
{
|
{
|
||||||
if (args->logger)
|
if (args->logger)
|
||||||
|
@ -90,10 +90,6 @@ 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);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Async API background thread runner
|
// Async API background thread runner
|
||||||
void run();
|
void run();
|
||||||
// Async API
|
// Async API
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "IXHttpServer.h"
|
#include "IXHttpServer.h"
|
||||||
|
|
||||||
|
#include "IXGzipCodec.h"
|
||||||
#include "IXNetSystem.h"
|
#include "IXNetSystem.h"
|
||||||
#include "IXSocketConnect.h"
|
#include "IXSocketConnect.h"
|
||||||
#include "IXUserAgent.h"
|
#include "IXUserAgent.h"
|
||||||
@ -14,10 +15,6 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#ifdef IXWEBSOCKET_USE_ZLIB
|
|
||||||
#include <zlib.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
std::pair<bool, std::vector<uint8_t>> load(const std::string& path)
|
std::pair<bool, std::vector<uint8_t>> load(const std::string& path)
|
||||||
@ -43,51 +40,6 @@ namespace
|
|||||||
auto vec = res.second;
|
auto vec = res.second;
|
||||||
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)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace ix
|
namespace ix
|
||||||
|
@ -6,4 +6,4 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define IX_WEBSOCKET_VERSION "10.4.6"
|
#define IX_WEBSOCKET_VERSION "10.4.7"
|
||||||
|
136
ws/ws.cpp
136
ws/ws.cpp
@ -33,6 +33,7 @@
|
|||||||
#include <ixsentry/IXSentryClient.h>
|
#include <ixsentry/IXSentryClient.h>
|
||||||
#include <ixsnake/IXSnakeServer.h>
|
#include <ixsnake/IXSnakeServer.h>
|
||||||
#include <ixwebsocket/IXDNSLookup.h>
|
#include <ixwebsocket/IXDNSLookup.h>
|
||||||
|
#include <ixwebsocket/IXGzipCodec.h>
|
||||||
#include <ixwebsocket/IXHttpClient.h>
|
#include <ixwebsocket/IXHttpClient.h>
|
||||||
#include <ixwebsocket/IXHttpServer.h>
|
#include <ixwebsocket/IXHttpServer.h>
|
||||||
#include <ixwebsocket/IXNetSystem.h>
|
#include <ixwebsocket/IXNetSystem.h>
|
||||||
@ -127,6 +128,38 @@ namespace
|
|||||||
std::ifstream infile(fileName);
|
std::ifstream infile(fileName);
|
||||||
return infile.good();
|
return infile.good();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string extractFilename(const std::string& path)
|
||||||
|
{
|
||||||
|
std::string::size_type idx;
|
||||||
|
|
||||||
|
idx = path.rfind('/');
|
||||||
|
if (idx != std::string::npos)
|
||||||
|
{
|
||||||
|
std::string filename = path.substr(idx + 1);
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string removeExtension(const std::string& path)
|
||||||
|
{
|
||||||
|
std::string::size_type idx;
|
||||||
|
|
||||||
|
idx = path.rfind('.');
|
||||||
|
if (idx != std::string::npos)
|
||||||
|
{
|
||||||
|
std::string filename = path.substr(idx + 1);
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace ix
|
namespace ix
|
||||||
@ -1103,6 +1136,76 @@ namespace ix
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ws_gzip(const std::string& filename)
|
||||||
|
{
|
||||||
|
auto res = readAsString(filename);
|
||||||
|
bool found = res.first;
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
spdlog::error("Cannot read content of {}", filename);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
spdlog::info("gzip input: {} cksum {}", filename, ix::djb2HashStr(res.second));
|
||||||
|
|
||||||
|
std::string compressedBytes;
|
||||||
|
|
||||||
|
{
|
||||||
|
Bench bench("compressing file");
|
||||||
|
compressedBytes = gzipCompress(res.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string outputFilename(filename);
|
||||||
|
outputFilename += ".gz";
|
||||||
|
|
||||||
|
std::ofstream f;
|
||||||
|
f.open(outputFilename);
|
||||||
|
f << compressedBytes;
|
||||||
|
f.close();
|
||||||
|
|
||||||
|
spdlog::info("gzip output: {} cksum {}", outputFilename, ix::djb2HashStr(compressedBytes));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ws_gunzip(const std::string& filename)
|
||||||
|
{
|
||||||
|
spdlog::info("filename to gunzip: {}", filename);
|
||||||
|
|
||||||
|
auto res = readAsString(filename);
|
||||||
|
bool found = res.first;
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
spdlog::error("Cannot read content of {}", filename);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
spdlog::info("gunzip input: {} cksum {}", filename, ix::djb2HashStr(res.second));
|
||||||
|
|
||||||
|
std::string decompressedBytes;
|
||||||
|
|
||||||
|
{
|
||||||
|
Bench bench("decompressing file");
|
||||||
|
if (!gzipDecompress(res.second, decompressedBytes))
|
||||||
|
{
|
||||||
|
spdlog::error("Cannot decompress content of {}", filename);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string outputFilename(removeExtension(filename));
|
||||||
|
|
||||||
|
std::ofstream f;
|
||||||
|
f.open(outputFilename);
|
||||||
|
f << decompressedBytes;
|
||||||
|
f.close();
|
||||||
|
|
||||||
|
spdlog::info(
|
||||||
|
"gunzip output: {} cksum {}", outputFilename, ix::djb2HashStr(decompressedBytes));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int ws_autoroute(const std::string& url,
|
int ws_autoroute(const std::string& url,
|
||||||
bool disablePerMessageDeflate,
|
bool disablePerMessageDeflate,
|
||||||
const ix::SocketTLSOptions& tlsOptions,
|
const ix::SocketTLSOptions& tlsOptions,
|
||||||
@ -1305,22 +1408,6 @@ namespace ix
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string extractFilename(const std::string& path)
|
|
||||||
{
|
|
||||||
std::string::size_type idx;
|
|
||||||
|
|
||||||
idx = path.rfind('/');
|
|
||||||
if (idx != std::string::npos)
|
|
||||||
{
|
|
||||||
std::string filename = path.substr(idx + 1);
|
|
||||||
return filename;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
WebSocketHttpHeaders parseHeaders(const std::string& data)
|
WebSocketHttpHeaders parseHeaders(const std::string& data)
|
||||||
{
|
{
|
||||||
WebSocketHttpHeaders headers;
|
WebSocketHttpHeaders headers;
|
||||||
@ -2848,6 +2935,7 @@ int main(int argc, char** argv)
|
|||||||
std::string publisherRolename;
|
std::string publisherRolename;
|
||||||
std::string publisherRolesecret;
|
std::string publisherRolesecret;
|
||||||
std::string sendMsg("hello world");
|
std::string sendMsg("hello world");
|
||||||
|
std::string filename;
|
||||||
ix::SocketTLSOptions tlsOptions;
|
ix::SocketTLSOptions tlsOptions;
|
||||||
ix::CobraConfig cobraConfig;
|
ix::CobraConfig cobraConfig;
|
||||||
ix::CobraBotConfig cobraBotConfig;
|
ix::CobraBotConfig cobraBotConfig;
|
||||||
@ -3206,6 +3294,14 @@ int main(int argc, char** argv)
|
|||||||
dnsLookupApp->fallthrough();
|
dnsLookupApp->fallthrough();
|
||||||
dnsLookupApp->add_option("host", hostname, "Hostname")->required();
|
dnsLookupApp->add_option("host", hostname, "Hostname")->required();
|
||||||
|
|
||||||
|
CLI::App* gzipApp = app.add_subcommand("gzip", "Gzip compressor");
|
||||||
|
gzipApp->fallthrough();
|
||||||
|
gzipApp->add_option("filename", filename, "Filename")->required();
|
||||||
|
|
||||||
|
CLI::App* gunzipApp = app.add_subcommand("gunzip", "Gzip decompressor");
|
||||||
|
gunzipApp->fallthrough();
|
||||||
|
gunzipApp->add_option("filename", filename, "Filename")->required();
|
||||||
|
|
||||||
CLI11_PARSE(app, argc, argv);
|
CLI11_PARSE(app, argc, argv);
|
||||||
|
|
||||||
// pid file handling
|
// pid file handling
|
||||||
@ -3502,6 +3598,14 @@ int main(int argc, char** argv)
|
|||||||
{
|
{
|
||||||
ret = ix::ws_dns_lookup(hostname);
|
ret = ix::ws_dns_lookup(hostname);
|
||||||
}
|
}
|
||||||
|
else if (app.got_subcommand("gzip"))
|
||||||
|
{
|
||||||
|
ret = ix::ws_gzip(filename);
|
||||||
|
}
|
||||||
|
else if (app.got_subcommand("gunzip"))
|
||||||
|
{
|
||||||
|
ret = ix::ws_gunzip(filename);
|
||||||
|
}
|
||||||
else if (version)
|
else if (version)
|
||||||
{
|
{
|
||||||
std::cout << "ws " << ix::userAgent() << std::endl;
|
std::cout << "ws " << ix::userAgent() << std::endl;
|
||||||
|
Loading…
Reference in New Issue
Block a user