mirror of
https://github.com/XRPLF/rippled.git
synced 2026-04-29 15:37:57 +00:00
add basic compression/decompression implimentation
This commit is contained in:
@@ -10,7 +10,7 @@ Import('polyfill_libs')
|
||||
env = env.Clone ()
|
||||
env_cpp11 = env_cpp11.Clone ()
|
||||
|
||||
BOOST_LIBS = boostlibs(['unit_test_framework','system','regex'],env) + [platform_libs]
|
||||
BOOST_LIBS = boostlibs(['unit_test_framework','system','regex'],env) + [platform_libs] + ['z']
|
||||
|
||||
objs = env.Object('extension_boost.o', ["extension.cpp"], LIBS = BOOST_LIBS)
|
||||
objs += env.Object('permessage_deflate_boost.o', ["permessage_deflate.cpp"], LIBS = BOOST_LIBS)
|
||||
@@ -18,7 +18,7 @@ prgs = env.Program('test_extension_boost', ["extension_boost.o"], LIBS = BOOST_L
|
||||
prgs += env.Program('test_permessage_deflate_boost', ["permessage_deflate_boost.o"], LIBS = BOOST_LIBS)
|
||||
|
||||
if env_cpp11.has_key('WSPP_CPP11_ENABLED'):
|
||||
BOOST_LIBS_CPP11 = boostlibs(['unit_test_framework'],env_cpp11) + [platform_libs] + [polyfill_libs]
|
||||
BOOST_LIBS_CPP11 = boostlibs(['unit_test_framework'],env_cpp11) + [platform_libs] + [polyfill_libs] + ['z']
|
||||
objs += env_cpp11.Object('extension_stl.o', ["extension.cpp"], LIBS = BOOST_LIBS_CPP11)
|
||||
objs += env_cpp11.Object('permessage_deflate_stl.o', ["permessage_deflate.cpp"], LIBS = BOOST_LIBS_CPP11)
|
||||
prgs += env_cpp11.Program('test_extension_stl', ["extension_stl.o"], LIBS = BOOST_LIBS_CPP11)
|
||||
|
||||
@@ -36,6 +36,9 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <websocketpp/utilities.hpp>
|
||||
#include <iostream>
|
||||
|
||||
class config {};
|
||||
|
||||
typedef websocketpp::extensions::permessage_deflate::enabled<config> enabled_type;
|
||||
@@ -495,3 +498,46 @@ BOOST_AUTO_TEST_CASE( negotiate_four_client_initiated ) {
|
||||
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; s2c_no_context_takeover; c2s_no_context_takeover; s2c_max_window_bits=10; c2s_max_window_bits=10");
|
||||
}
|
||||
|
||||
// Compression
|
||||
/*
|
||||
BOOST_AUTO_TEST_CASE( compress_data ) {
|
||||
ext_vars v;
|
||||
|
||||
std::string in = "Hello";
|
||||
std::string out;
|
||||
std::string in2;
|
||||
std::string out2;
|
||||
|
||||
v.exts.init();
|
||||
|
||||
v.ec = v.exts.compress(in,out);
|
||||
|
||||
std::cout << "in : " << websocketpp::utility::to_hex(in) << std::endl;
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
std::cout << "out: " << websocketpp::utility::to_hex(out) << std::endl;
|
||||
|
||||
in2 = out;
|
||||
|
||||
v.ec = v.exts.decompress(reinterpret_cast<const uint8_t *>(in2.data()),in2.size(),out2);
|
||||
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
std::cout << "out: " << websocketpp::utility::to_hex(out2) << std::endl;
|
||||
BOOST_CHECK_EQUAL( out, out2 );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( decompress_data ) {
|
||||
ext_vars v;
|
||||
|
||||
uint8_t in[12] = {0xf2, 0x48, 0xcd, 0xc9, 0xc9, 0x07, 0x00, 0x00, 0x00, 0xff, 0xff};
|
||||
std::string out;
|
||||
|
||||
v.exts.init();
|
||||
|
||||
v.ec = v.exts.decompress(in,12,out);
|
||||
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
std::cout << "out: " << websocketpp::utility::to_hex(out) << std::endl;
|
||||
BOOST_CHECK( false );
|
||||
}
|
||||
*/
|
||||
@@ -10,7 +10,7 @@ Import('polyfill_libs')
|
||||
env = env.Clone ()
|
||||
env_cpp11 = env_cpp11.Clone ()
|
||||
|
||||
BOOST_LIBS = boostlibs(['unit_test_framework','regex','system'],env) + [platform_libs]
|
||||
BOOST_LIBS = boostlibs(['unit_test_framework','regex','system'],env) + [platform_libs] + ['z']
|
||||
|
||||
objs = env.Object('test_processor_boost.o', ["processor.cpp"], LIBS = BOOST_LIBS)
|
||||
objs += env.Object('test_hybi13_boost.o', ["hybi13.cpp"], LIBS = BOOST_LIBS)
|
||||
@@ -27,7 +27,7 @@ prgs += env.Program('test_hybi00_boost', ["test_hybi00_boost.o"], LIBS = BOOST_L
|
||||
prgs += env.Program('test_extension_permessage_compress_boost', ["test_extension_permessage_compress_boost.o"], LIBS = BOOST_LIBS + ['z'])
|
||||
|
||||
if env_cpp11.has_key('WSPP_CPP11_ENABLED'):
|
||||
BOOST_LIBS_CPP11 = boostlibs(['unit_test_framework'],env_cpp11) + [platform_libs] + [polyfill_libs]
|
||||
BOOST_LIBS_CPP11 = boostlibs(['unit_test_framework'],env_cpp11) + [platform_libs] + [polyfill_libs] + ['z']
|
||||
# no C++11 features are used in processor so there are no C++11 versions of
|
||||
# these tests.
|
||||
objs += env_cpp11.Object('test_processor_stl.o', ["processor.cpp"], LIBS = BOOST_LIBS_CPP11)
|
||||
|
||||
@@ -205,7 +205,85 @@ public:
|
||||
, m_s2c_max_window_bits(15)
|
||||
, m_c2s_max_window_bits(15)
|
||||
, m_s2c_max_window_bits_mode(mode::accept)
|
||||
, m_c2s_max_window_bits_mode(mode::accept) {}
|
||||
, m_c2s_max_window_bits_mode(mode::accept)
|
||||
, m_initialized(false)
|
||||
, m_compress_buffer_size(16384)
|
||||
{
|
||||
m_dstate.zalloc = Z_NULL;
|
||||
m_dstate.zfree = Z_NULL;
|
||||
m_dstate.opaque = Z_NULL;
|
||||
|
||||
m_istate.zalloc = Z_NULL;
|
||||
m_istate.zfree = Z_NULL;
|
||||
m_istate.opaque = Z_NULL;
|
||||
m_istate.avail_in = 0;
|
||||
m_istate.next_in = Z_NULL;
|
||||
}
|
||||
|
||||
~enabled() {
|
||||
if (!m_initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
int ret = deflateEnd(&m_dstate);
|
||||
|
||||
if (ret != Z_OK) {
|
||||
//std::cout << "error cleaning up zlib compression state"
|
||||
// << std::endl;
|
||||
}
|
||||
|
||||
ret = inflateEnd(&m_istate);
|
||||
|
||||
if (ret != Z_OK) {
|
||||
//std::cout << "error cleaning up zlib decompression state"
|
||||
// << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
/// Initialize zlib state
|
||||
/**
|
||||
*
|
||||
* @todo memory level, strategy, etc are hardcoded
|
||||
* @todo server detection is hardcoded
|
||||
*/
|
||||
lib::error_code init() {
|
||||
uint8_t deflate_bits;
|
||||
uint8_t inflate_bits;
|
||||
|
||||
if (true /*is_server*/) {
|
||||
deflate_bits = m_s2c_max_window_bits;
|
||||
inflate_bits = m_c2s_max_window_bits;
|
||||
} else {
|
||||
deflate_bits = m_c2s_max_window_bits;
|
||||
inflate_bits = m_s2c_max_window_bits;
|
||||
}
|
||||
|
||||
int ret = deflateInit2(
|
||||
&m_dstate,
|
||||
Z_DEFAULT_COMPRESSION,
|
||||
Z_DEFLATED,
|
||||
-1*deflate_bits,
|
||||
8, // memory level 1-9
|
||||
/*Z_DEFAULT_STRATEGY*/Z_FIXED
|
||||
);
|
||||
|
||||
if (ret != Z_OK) {
|
||||
return make_error_code(error::zlib_error);
|
||||
}
|
||||
|
||||
ret = inflateInit2(
|
||||
&m_istate,
|
||||
-1*inflate_bits
|
||||
);
|
||||
|
||||
if (ret != Z_OK) {
|
||||
return make_error_code(error::zlib_error);
|
||||
}
|
||||
|
||||
m_compress_buffer.reset(new unsigned char[m_compress_buffer_size]);
|
||||
m_initialized = true;
|
||||
return lib::error_code();
|
||||
}
|
||||
|
||||
/// Test if this object impliments the permessage-deflate specification
|
||||
/**
|
||||
@@ -404,7 +482,29 @@ public:
|
||||
* @return Error or status code
|
||||
*/
|
||||
lib::error_code compress(std::string const & in, std::string & out) {
|
||||
return make_error_code(error::uninitialized);
|
||||
if (!m_initialized) {
|
||||
return make_error_code(error::uninitialized);
|
||||
}
|
||||
|
||||
size_t output;
|
||||
int ret;
|
||||
|
||||
m_dstate.avail_out = m_compress_buffer_size;
|
||||
m_dstate.next_in = (unsigned char *)(const_cast<char *>(in.data()));
|
||||
|
||||
do {
|
||||
// Output to local buffer
|
||||
m_dstate.avail_out = m_compress_buffer_size;
|
||||
m_dstate.next_out = m_compress_buffer.get();
|
||||
|
||||
ret = deflate(&m_dstate, Z_SYNC_FLUSH);
|
||||
|
||||
output = m_compress_buffer_size - m_dstate.avail_out;
|
||||
|
||||
out.append((char *)(m_compress_buffer.get()),output);
|
||||
} while (m_dstate.avail_out == 0);
|
||||
|
||||
return lib::error_code();
|
||||
}
|
||||
|
||||
/// Decompress bytes
|
||||
@@ -417,7 +517,32 @@ public:
|
||||
lib::error_code decompress(uint8_t const * buf, size_t len, std::string &
|
||||
out)
|
||||
{
|
||||
return make_error_code(error::uninitialized);
|
||||
if (!m_initialized) {
|
||||
return make_error_code(error::uninitialized);
|
||||
}
|
||||
|
||||
int ret;
|
||||
|
||||
m_istate.avail_in = len;
|
||||
m_istate.next_in = const_cast<unsigned char *>(buf);
|
||||
|
||||
do {
|
||||
m_istate.avail_out = m_compress_buffer_size;
|
||||
m_istate.next_out = m_compress_buffer.get();
|
||||
|
||||
ret = inflate(&m_istate, Z_SYNC_FLUSH);
|
||||
|
||||
if (ret == Z_NEED_DICT || ret == Z_DATA_ERROR || ret == Z_MEM_ERROR) {
|
||||
return make_error_code(error::zlib_error);
|
||||
}
|
||||
|
||||
out.append(
|
||||
reinterpret_cast<char *>(m_compress_buffer.get()),
|
||||
m_compress_buffer_size - m_istate.avail_out
|
||||
);
|
||||
} while (m_istate.avail_out == 0);
|
||||
|
||||
return lib::error_code();
|
||||
}
|
||||
private:
|
||||
/// Generate negotiation response
|
||||
@@ -584,6 +709,12 @@ private:
|
||||
uint8_t m_c2s_max_window_bits;
|
||||
mode::value m_s2c_max_window_bits_mode;
|
||||
mode::value m_c2s_max_window_bits_mode;
|
||||
|
||||
bool m_initialized;
|
||||
size_t m_compress_buffer_size;
|
||||
lib::unique_ptr_uchar_array m_compress_buffer;
|
||||
z_stream m_dstate;
|
||||
z_stream m_istate;
|
||||
};
|
||||
|
||||
} // namespace permessage_deflate
|
||||
|
||||
Reference in New Issue
Block a user