diff --git a/sdk/base/basic/variant.cpp b/sdk/base/basic/variant.cpp index 8345c98e..619a7c32 100644 --- a/sdk/base/basic/variant.cpp +++ b/sdk/base/basic/variant.cpp @@ -327,7 +327,7 @@ variant& variant::set_binary_new(const binary_t& bin) { return *this; } -int variant::to_int() const { return t_variant_to_int(_vt); } +int variant::to_int() const { return t_to_int(_vt); } return_t variant::to_binary(binary_t& target) const { return_t ret = errorcode_t::success; diff --git a/sdk/base/basic/variant.hpp b/sdk/base/basic/variant.hpp index 33f5e4c7..25ad8470 100644 --- a/sdk/base/basic/variant.hpp +++ b/sdk/base/basic/variant.hpp @@ -174,7 +174,7 @@ typedef struct __variant_t { } variant_t; template -T t_variant_to_int(const variant_t& vt) { +T t_to_int(const variant_t& vt) { T i = 0; switch (vt.type) { diff --git a/sdk/base/stream/basic_stream.cpp b/sdk/base/stream/basic_stream.cpp index b1b19a3b..46ed702b 100644 --- a/sdk/base/stream/basic_stream.cpp +++ b/sdk/base/stream/basic_stream.cpp @@ -14,18 +14,24 @@ namespace hotplace { -basic_stream::basic_stream(size_t allocsize, uint32 flags) : _handle(nullptr) { _bio.open(&_handle, allocsize, 1, flags); } +basic_stream::basic_stream() : _handle(nullptr) { + size_t allocsize = stream_policy::get_instance()->get_allocsize(); + _bio.open(&_handle, allocsize, 1); +} basic_stream::basic_stream(const char* data, ...) : _handle(nullptr) { + size_t allocsize = stream_policy::get_instance()->get_allocsize(); va_list ap; va_start(ap, data); - _bio.open(&_handle, 1 << 10, 1); + _bio.open(&_handle, allocsize, 1); _bio.vprintf(_handle, data, ap); va_end(ap); } basic_stream::basic_stream(const basic_stream& stream) : _handle(nullptr) { - _bio.open(&_handle, 1 << 10, 1); + size_t allocsize = stream_policy::get_instance()->get_allocsize(); + + _bio.open(&_handle, allocsize, 1); byte_t* data = nullptr; size_t size = 0; diff --git a/sdk/base/stream/basic_stream.hpp b/sdk/base/stream/basic_stream.hpp index 94214ef7..96b0eb95 100644 --- a/sdk/base/stream/basic_stream.hpp +++ b/sdk/base/stream/basic_stream.hpp @@ -26,12 +26,7 @@ namespace hotplace { */ class basic_stream : public stream_t { public: - /** - * @brief constructor - * @param size_t allocsize [inopt] default 4K - * @param uint32 flags [inopt] default 0 - */ - basic_stream(size_t allocsize = (1 << 12), uint32 flags = 0); + basic_stream(); /** * @brief constructor * @param const char* data [in] @@ -146,6 +141,28 @@ class basic_stream : public stream_t { bufferio_context_t* _handle; }; +/** + * @remarks + * stream_policy* pol = stream_policy::get_instance(); + * pol->set_allocsize(1 << 5); + * + * basic_stream bs; + * bs << "hello world"; + */ +class stream_policy { + public: + static stream_policy* get_instance(); + stream_policy& set_allocsize(size_t allocsize); + size_t get_allocsize(); + + private: + static stream_policy _instance; + stream_policy(); + + typedef std::map basic_stream_policy_map_t; + basic_stream_policy_map_t _config; +}; + } // namespace hotplace #endif diff --git a/sdk/base/stream/stream_policy.cpp b/sdk/base/stream/stream_policy.cpp new file mode 100644 index 00000000..36ca6283 --- /dev/null +++ b/sdk/base/stream/stream_policy.cpp @@ -0,0 +1,39 @@ +/* vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab smarttab : */ +/** + * @file {file} + * @author Soo Han, Kim (princeb612.kr@gmail.com) + * @desc + * + * Revision History + * Date Name Description + */ + +#include + +#include + +namespace hotplace { + +const uint32 basic_stream_policy_minsize = 1 << 3; +const uint32 basic_stream_policy_allocsize = 1 << 12; + +stream_policy stream_policy::_instance; + +stream_policy::stream_policy() { _config.insert(std::make_pair("allocsize", basic_stream_policy_allocsize)); } + +stream_policy* stream_policy::get_instance() { return &_instance; } + +stream_policy& stream_policy::set_allocsize(size_t allocsize) { + if (allocsize < basic_stream_policy_minsize) { + allocsize = basic_stream_policy_minsize; + } + std::pair pib = _config.insert(std::make_pair("allocsize", allocsize)); + if (false == pib.second) { + pib.first->second = allocsize; + } + return *this; +} + +size_t stream_policy::get_allocsize() { return _config["allocsize"]; } + +} // namespace hotplace diff --git a/sdk/io/basic/payload.cpp b/sdk/io/basic/payload.cpp index 50a81143..15d5afb6 100644 --- a/sdk/io/basic/payload.cpp +++ b/sdk/io/basic/payload.cpp @@ -98,7 +98,7 @@ size_t payload_member::get_space() { } else if (variant_flag_t::flag_int == get_variant().flag()) { space = get_variant().size(); } else if (ref) { - space = t_variant_to_int(ref->get_variant().content()); + space = t_to_int(ref); } return space; } @@ -109,7 +109,7 @@ size_t payload_member::get_capacity() { if (_reserve) { space = _reserve; } else if (ref) { - space = t_variant_to_int(ref->get_variant().content()); + space = t_to_int(ref); } else { space = get_variant().size(); } @@ -195,7 +195,7 @@ payload_member& payload_member::read(byte_t* ptr, size_t size_ptr, size_t* size_ if (_reserve) { size = _reserve; } else if (ref) { - size = t_variant_to_int(ref->get_variant().content()); + size = t_to_int(ref); } if (size_ptr >= size) { diff --git a/sdk/io/basic/payload.hpp b/sdk/io/basic/payload.hpp index bd7f846f..5a9a5d78 100644 --- a/sdk/io/basic/payload.hpp +++ b/sdk/io/basic/payload.hpp @@ -141,6 +141,15 @@ class payload { std::map _option; // map }; +template +T t_to_int(payload_member* v) { + T i = 0; + if (v) { + i = t_to_int(v->get_variant().content()); + } + return i; +} + } // namespace io } // namespace hotplace diff --git a/sdk/io/cbor/cbor_map.hpp b/sdk/io/cbor/cbor_map.hpp index 21fa3fe3..2b4f9565 100644 --- a/sdk/io/cbor/cbor_map.hpp +++ b/sdk/io/cbor/cbor_map.hpp @@ -131,7 +131,7 @@ class cbor_map : public cbor_object { template struct cbor_map_int_binder { - KTY bind(variant vt) { return t_variant_to_int(vt.content()); } + KTY bind(variant vt) { return t_to_int(vt.content()); } }; template diff --git a/sdk/io/stream/ansi_string.cpp b/sdk/io/stream/ansi_string.cpp index 6c07aa2c..15099f73 100644 --- a/sdk/io/stream/ansi_string.cpp +++ b/sdk/io/stream/ansi_string.cpp @@ -15,15 +15,22 @@ namespace hotplace { namespace io { -ansi_string::ansi_string(size_t allocsize, uint32 flags) { _bio.open(&_handle, allocsize, sizeof(char), flags | bufferio_context_flag_t::memzero_free); } +ansi_string::ansi_string() { + size_t allocsize = stream_policy::get_instance()->get_allocsize(); + _bio.open(&_handle, allocsize, sizeof(char), bufferio_context_flag_t::memzero_free); +} ansi_string::ansi_string(const char* data) { - _bio.open(&_handle, 1 << 10, sizeof(char), bufferio_context_flag_t::memzero_free); + size_t allocsize = stream_policy::get_instance()->get_allocsize(); + + _bio.open(&_handle, allocsize, sizeof(char), bufferio_context_flag_t::memzero_free); _bio.write(_handle, data, strlen(data)); } ansi_string::ansi_string(const ansi_string& stream) { - _bio.open(&_handle, 1 << 10, sizeof(char), bufferio_context_flag_t::memzero_free); + size_t allocsize = stream_policy::get_instance()->get_allocsize(); + + _bio.open(&_handle, allocsize, sizeof(char), bufferio_context_flag_t::memzero_free); byte_t* data = nullptr; size_t size = 0; diff --git a/sdk/io/stream/string.hpp b/sdk/io/stream/string.hpp index 0a90b609..7246ad04 100644 --- a/sdk/io/stream/string.hpp +++ b/sdk/io/stream/string.hpp @@ -20,7 +20,7 @@ namespace io { class ansi_string : public stream_t { public: - ansi_string(size_t allocsize = (1 << 12), uint32 flags = 0); + ansi_string(); ansi_string(const char* data); ansi_string(const ansi_string& stream); virtual ~ansi_string(); @@ -148,7 +148,7 @@ class ansi_string : public stream_t { #if defined _WIN32 || defined _WIN64 class wide_string : public stream_t { public: - wide_string(size_t allocsize = (1 << 12), uint32 flags = 0); + wide_string(); wide_string(const wchar_t* data); wide_string(const wide_string& stream); virtual ~wide_string(); diff --git a/sdk/io/stream/unicode/wide_string.cpp b/sdk/io/stream/unicode/wide_string.cpp index 95f83d58..18ab6409 100644 --- a/sdk/io/stream/unicode/wide_string.cpp +++ b/sdk/io/stream/unicode/wide_string.cpp @@ -16,15 +16,22 @@ namespace hotplace { namespace io { -wide_string::wide_string(size_t allocsize, uint32 flags) { _bio.open(&_handle, allocsize, sizeof(wchar_t), flags | bufferio_context_flag_t::memzero_free); } +wide_string::wide_string() { + size_t allocsize = stream_policy::get_instance()->get_allocsize(); + _bio.open(&_handle, allocsize, sizeof(wchar_t), bufferio_context_flag_t::memzero_free); +} wide_string::wide_string(const wchar_t* data) { - _bio.open(&_handle, 1 << 10, sizeof(wchar_t), bufferio_context_flag_t::memzero_free); + size_t allocsize = stream_policy::get_instance()->get_allocsize(); + + _bio.open(&_handle, allocsize, sizeof(wchar_t), bufferio_context_flag_t::memzero_free); _bio.write(_handle, data, wcslen(data) * sizeof(wchar_t)); } wide_string::wide_string(const wide_string& stream) { - _bio.open(&_handle, 1 << 10, sizeof(wchar_t), bufferio_context_flag_t::memzero_free); + size_t allocsize = stream_policy::get_instance()->get_allocsize(); + + _bio.open(&_handle, allocsize, sizeof(wchar_t), bufferio_context_flag_t::memzero_free); byte_t* data = nullptr; size_t size = 0; diff --git a/sdk/net/basic/client_socket.hpp b/sdk/net/basic/client_socket.hpp index e3244229..ec648047 100644 --- a/sdk/net/basic/client_socket.hpp +++ b/sdk/net/basic/client_socket.hpp @@ -32,14 +32,14 @@ class tcp_client_socket { * @param const char* address [IN] * @param uint16 port [IN] * @param uint32 timeout [IN] - * @return error code (see error.hpp) + * @return error code (see error.hpp) */ virtual return_t connect(socket_t* sock, tls_context_t** tls_handle, const char* address, uint16 port, uint32 timeout); /** * @brief close * @param socket_t sock [IN] see connect * @param tls_context_t* tls_handle [IN] - * @return error code (see error.hpp) + * @return error code (see error.hpp) */ virtual return_t close(socket_t sock, tls_context_t* tls_handle); @@ -50,7 +50,7 @@ class tcp_client_socket { * @param char* ptr_data [OUT] * @param size_t size_data [IN] * @param size_t* cbread [OUT] - * @return error code (see error.hpp) + * @return error code (see error.hpp) */ virtual return_t read(socket_t sock, tls_context_t* tls_handle, char* ptr_data, size_t size_data, size_t* cbread); virtual return_t more(socket_t sock, tls_context_t* tls_handle, char* ptr_data, size_t size_data, size_t* cbread); @@ -61,7 +61,7 @@ class tcp_client_socket { * @param const char* ptr_data [IN] * @param size_t size_data [IN] * @param size_t* size_sent [OUT] - * @return error code (see error.hpp) + * @return error code (see error.hpp) */ virtual return_t send(socket_t sock, tls_context_t* tls_handle, const char* ptr_data, size_t size_data, size_t* size_sent); diff --git a/sdk/net/http/http2/hpack.cpp b/sdk/net/http/http2/hpack.cpp index d0687c42..147ff0fc 100644 --- a/sdk/net/http/http2/hpack.cpp +++ b/sdk/net/http/http2/hpack.cpp @@ -34,9 +34,9 @@ hpack& hpack::set_encode_flags(uint32 flags) { return *this; } -hpack& hpack::encode_header(const std::string& name, const std::string& value) { +hpack& hpack::encode_header(const std::string& name, const std::string& value, uint32 flags) { if (_session) { - (*_encoder).encode_header(_session, _bin, name, value, _flags); + (*_encoder).encode_header(_session, _bin, name, value, flags ? flags : _flags); } return *this; } @@ -50,568 +50,5 @@ hpack& hpack::decode_header(const byte_t* source, size_t size, size_t& pos, std: binary_t& hpack::get_binary() { return _bin; } -hpack_encoder::hpack_encoder() : _safe_mask(false) { - // RFC 7541 Appendix B. Huffman Code - _hc.imports(_h2hcodes); - - // RFC 7541 Appendix A. Static Table Definition - // if (_static_table.empty()) ... - http_resource::get_instance()->for_each_hpack_static_table([&](uint32 index, const char* name, const char* value) -> void { - _static_table.insert(std::make_pair(name, std::make_pair(value ? value : "", index))); - _static_table_index.insert(std::make_pair(index, std::make_pair(name, value ? value : ""))); - }); -} - -hpack_encoder& hpack_encoder::encode_int(binary_t& target, uint8 mask, uint8 prefix, size_t value) { - if ((1 <= prefix) && (prefix <= 8)) { - // RFC 7541 5.1. Integer Representation - // RFC 7541 C.1. Integer Representation Examples - // RFC 7541 Figure 3: Integer Value Encoded after the Prefix (Shown for N = 5) - // - // 0 1 2 3 4 5 6 7 - // +---+---+---+---+---+---+---+---+ - // | ? | ? | ? | 1 1 1 1 1 | - // +---+---+---+-------------------+ - // | 1 | Value-(2^N-1) LSB | - // +---+---------------------------+ - // ... - // +---+---------------------------+ - // | 0 | Value-(2^N-1) MSB | - // +---+---------------------------+ - - uint8 n = (1 << prefix) - 1; - - // safety mask - if (_safe_mask && mask) { - uint8 temp = 0; - for (int t = 0; t < prefix; t++) { - temp |= (1 << t); - } - mask &= ~temp; - } - - uint8 i = 0; - if (value < n) { - target.insert(target.end(), value | mask); - } else { - target.insert(target.end(), n | mask); - value -= n; - // 128 (0x80) - // 1 value - // 1 value - // 0 value - while (value >= 0x80) { - i = (value % 0x80) | 0x80; - target.insert(target.end(), i); - value /= 0x80; - } - target.insert(target.end(), value); - } - } - return *this; -} - -hpack_encoder& hpack_encoder::encode_string(binary_t& target, uint32 flags, const char* value) { - __try2 { - if (nullptr == value) { - __leave2; - } - encode_string(target, flags, value, strlen(value)); - } - __finally2 { - // do nothing - } - return *this; -} - -hpack_encoder& hpack_encoder::encode_string(binary_t& target, uint32 flags, const char* value, size_t size) { - __try2 { - if (nullptr == value) { - __leave2; - } - - // RFC 7541 Figure 4: String Literal Representation - // - // 0 1 2 3 4 5 6 7 - // +---+---+---+---+---+---+---+---+ - // | H | String Length (7+) | - // +---+---------------------------+ - // | String Data (Length octets) | - // +-------------------------------+ - - if (hpack_huffman & flags) { - size_t size_expected = 0; - _hc.expect(value, size, size_expected); - encode_int(target, 0x80, 7, size_expected); - _hc.encode(target, value, size); - } else { - encode_int(target, 0x00, 7, size); - target.insert(target.end(), value, value + size); - } - } - __finally2 { - // do nothing - } - return *this; -} - -hpack_encoder& hpack_encoder::encode_string(binary_t& target, uint32 flags, const std::string& value) { - return encode_string(target, flags, value.c_str(), value.size()); -} - -hpack_encoder& hpack_encoder::encode_index(binary_t& target, uint8 index) { - // RFC 7541 Figure 5: Indexed Header Field - // - // 0 1 2 3 4 5 6 7 - // +---+---+---+---+---+---+---+---+ - // | 1 | Index (7+) | - // +---+---------------------------+ - - encode_int(target, 0x80, 7, index); - return *this; -} - -hpack_encoder& hpack_encoder::encode_indexed_name(binary_t& target, uint32 flags, uint8 index, const char* value) { - __try2 { - if (nullptr == value) { - __leave2; - } - encode_indexed_name(target, flags, index, value, strlen(value)); - } - __finally2 { - // do nothing - } - return *this; -} - -hpack_encoder& hpack_encoder::encode_indexed_name(binary_t& target, uint32 flags, uint8 index, const char* value, size_t size) { - __try2 { - if (nullptr == value) { - __leave2; - } - - if (hpack_indexing & flags) { - // RFC 7541 Figure 6: Literal Header Field with Incremental Indexing -- Indexed Name - // - // 0 1 2 3 4 5 6 7 - // +---+---+---+---+---+---+---+---+ - // | 0 | 1 | Index (6+) | - // +---+---+-----------------------+ - encode_int(target, 0x40, 6, index); - } else if (hpack_wo_indexing & flags) { - // RFC 7541 Figure 8: Literal Header Field without Indexing -- Indexed Name - // - // 0 1 2 3 4 5 6 7 - // +---+---+---+---+---+---+---+---+ - // | 0 | 0 | 0 | 0 | Index (4+) | - // +---+---+-----------------------+ - encode_int(target, 0x00, 4, index); - } else if (hpack_never_indexed & flags) { - // RFC 7541 Figure 10: Literal Header Field Never Indexed -- Indexed Name - // - // 0 1 2 3 4 5 6 7 - // +---+---+---+---+---+---+---+---+ - // | 0 | 0 | 0 | 1 | Index (4+) | - // +---+---+-----------------------+ - encode_int(target, 0x10, 4, index); - } else { - __leave2; - } - - // +-------------------------------+ - // | H | Value Length (7+) | - // +---+---------------------------+ - // | Value String (Length octets) | - // +-------------------------------+ - encode_string(target, flags, value, size); - } - __finally2 { - // do nothing - } - return *this; -} - -hpack_encoder& hpack_encoder::encode_indexed_name(binary_t& target, uint32 flags, uint8 index, const std::string& value) { - return encode_indexed_name(target, flags, index, value.c_str(), value.size()); -} - -hpack_encoder& hpack_encoder::encode_name_value(binary_t& target, uint32 flags, const char* name, const char* value) { - __try2 { - if (nullptr == name || nullptr == value) { - __leave2; - } - - if (hpack_indexing & flags) { - // RFC 7541 Figure 7: Literal Header Field with Incremental Indexing -- New Name - // - // 0 1 2 3 4 5 6 7 - // +---+---+---+---+---+---+---+---+ - // | 0 | 1 | 0 | - // +---+---+-----------------------+ - target.insert(target.end(), 0x40); - } else if (hpack_wo_indexing & flags) { - // RFC 7541 Figure 9: Literal Header Field without Indexing -- New Name - // - // 0 1 2 3 4 5 6 7 - // +---+---+---+---+---+---+---+---+ - // | 0 | 0 | 0 | 0 | 0 | - // +---+---+-----------------------+ - target.insert(target.end(), 0); - } else if (hpack_never_indexed & flags) { - // RFC 7541 Figure 11: Literal Header Field Never Indexed -- New Name - // - // 0 1 2 3 4 5 6 7 - // +---+---+---+---+---+---+---+---+ - // | 0 | 0 | 0 | 1 | 0 | - // +---+---+-----------------------+ - target.insert(target.end(), 0x10); - } else { - __leave2; - } - - // +---+---------------------------+ - // | H | Name Length (7+) | - // +---+---------------------------+ - // | Name String (Length octets) | - // +---+---------------------------+ - // | H | Value Length (7+) | - // +---+---------------------------+ - // | Value String (Length octets) | - // +-------------------------------+ - encode_string(target, flags, name); - encode_string(target, flags, value); - } - __finally2 { - // do nothing - } - return *this; -} - -hpack_encoder& hpack_encoder::encode_name_value(binary_t& target, uint32 flags, const std::string& name, const std::string& value) { - return encode_name_value(target, flags, name.c_str(), value.c_str()); -} - -hpack_encoder& hpack_encoder::encode_dyntablesize(binary_t& target, uint8 maxsize) { - // RFC 7541 Figure 12: Maximum Dynamic Table Size Change - encode_int(target, 0x20, 5, maxsize); - return *this; -} - -return_t hpack_encoder::decode_int(const byte_t* p, size_t& pos, uint8 mask, uint8 prefix, size_t& value) { - // 5.1. Integer Representation - // C.1. Integer Representation Examples - return_t ret = errorcode_t::success; - __try2 { - if (nullptr == p) { - ret = errorcode_t::success; - __leave2; - } - - value = 0; - if ((1 <= prefix) && (prefix <= 8)) { - uint8 n = (1 << prefix) - 1; - uint8 b = p[pos++]; - - if (_safe_mask) { - uint8 temp = 0; - for (int t = 0; t < prefix; t++) { - temp |= (1 << t); - } - mask &= ~temp; - } - b &= ~mask; - - if (b < n) { - value = b; - } else { - size_t m = 0; - size_t i = b; - do { - b = p[pos++]; - i += (b & 0x7f) << m; - m += 7; - } while (0x80 == (b & 0x80)); - value = i; - } - } - } - __finally2 { - // do nothing - } - return ret; -} - -return_t hpack_encoder::decode_string(const byte_t* p, size_t& pos, uint8 flags, std::string& value) { - return_t ret = errorcode_t::success; - __try2 { - value.clear(); - if (nullptr == p) { - ret = errorcode_t::invalid_parameter; - __leave2; - } - - byte_t b = p[pos]; - - size_t len = 0; - if (0x80 & b) { - // huffman - decode_int(p, pos, 0x80, 7, len); - basic_stream bs; - _hc.decode(&bs, p + pos, len); - value = bs.c_str(); - } else { - // string - decode_int(p, pos, 0x80, 7, len); - value.assign((char*)p + pos, len); - } - pos += len; - } - __finally2 { - // do nothing - } - return ret; -} - -match_result_t hpack_encoder::match(hpack_session* session, const std::string& name, const std::string& value, size_t& index) { - match_result_t state = match_result_t::not_matched; - index = 0; - - if (session) { - state = session->match(name, value, index); - if (match_result_t::all_matched == state) { - index += _static_table.size() + 1; - } - } - if (match_result_t::not_matched == state) { - static_table_t::iterator iter; - static_table_t::iterator liter; - static_table_t::iterator uiter; - - liter = _static_table.lower_bound(name); - uiter = _static_table.upper_bound(name); - - for (iter = liter; iter != uiter; iter++) { - if (iter == liter) { - index = iter->second.second; // :path: /sample/path - state = match_result_t::key_matched; - } - if (value == iter->second.first) { - index = iter->second.second; - state = match_result_t::all_matched; - break; - } - } - } - return state; -} - -return_t hpack_encoder::select(hpack_session* session, uint32 flags, size_t index, std::string& name, std::string& value) { - return_t ret = errorcode_t::success; - __try2 { - name.clear(); - value.clear(); - - if (nullptr == session) { - ret = errorcode_t::invalid_parameter; - __leave2; - } - - if (index > _static_table.size()) { - index -= (_static_table.size() + 1); - ret = session->select(flags, index, name, value); - } else { - static_table_index_t::iterator iter = _static_table_index.find(index); - if (_static_table_index.end() == iter) { - ret = errorcode_t::not_found; - __leave2; - } else { - name = iter->second.first; - if ((hpack_index | hpack_name_value) & flags) { - value = iter->second.second; - } - } - } - } - __finally2 { - // do nothing - } - return ret; -} - -return_t hpack_encoder::insert(hpack_session* session, const std::string& name, const std::string& value) { - // RFC 7541 Figure 1: Index Address Space - // - // <---------- Index Address Space ----------> - // <-- Static Table --> <-- Dynamic Table --> - // +---+-----------+---+ +---+-----------+---+ - // | 1 | ... | s | |s+1| ... |s+k| - // +---+-----------+---+ +---+-----------+---+ - // ^ | - // | V - // Insertion Point Dropping Point - // - // Figure 1: Index Address Space - return_t ret = errorcode_t::success; - __try2 { - if (nullptr == session) { - ret = errorcode_t::invalid_parameter; - __leave2; - } - session->insert(name, value); - } - __finally2 { - // do nothing - } - return ret; -} - -hpack_encoder& hpack_encoder::encode_header(hpack_session* session, binary_t& target, const std::string& name, const std::string& value, uint32 flags) { - match_result_t state = match_result_t::not_matched; - if (session) { - size_t index = 0; - - state = match(session, name, value, index); - switch (state) { - case match_result_t::all_matched: - encode_index(target, index); - break; - case match_result_t::key_matched: - encode_indexed_name(target, flags, index, value); - if (hpack_indexing & flags) { - session->insert(name, value); - } - break; - default: - encode_name_value(target, flags, name, value); - if (hpack_indexing & flags) { - session->insert(name, value); - } - break; - } - } - return *this; -} - -hpack_encoder& hpack_encoder::decode_header(hpack_session* session, const byte_t* source, size_t size, size_t& pos, std::string& name, std::string& value) { - if (session && source) { - byte_t b = source[pos]; - uint8 mask = 0; - uint8 prefix = 0; - uint32 flags = 0; - if (0x80 & b) { - // index - mask = 0x80; - prefix = 7; - flags |= hpack_index; - } else if (0x40 & b) { - // indexing - mask = 0x40; - prefix = 6; - flags |= hpack_indexing; - if (0x3f & b) { - flags |= hpack_indexed_name; - } else { - flags |= hpack_name_value; - } - } else if (0xf0 & ~b) { - // without indexing - mask = 0x00; - prefix = 4; - flags |= hpack_wo_indexing; - if (0x0f & b) { - flags |= hpack_indexed_name; - } else { - flags |= hpack_name_value; - } - } else if (0x10 & b) { - // never indexed - mask = 0x10; - prefix = 4; - flags |= hpack_never_indexed; - if (0x0f & b) { - flags |= hpack_indexed_name; - } else { - flags |= hpack_name_value; - } - } - - size_t i = 0; - size_t idx = 0; - if (hpack_index & flags) { - decode_int(source, pos, mask, prefix, i); - select(session, flags, i, name, value); - } else if (hpack_indexed_name & flags) { - decode_int(source, pos, mask, prefix, i); - select(session, flags, i, name, value); - decode_string(source, pos, flags, value); - } else if (hpack_name_value & flags) { - pos++; - decode_string(source, pos, flags, name); - decode_string(source, pos, flags, value); - } - - if (hpack_indexing & flags) { - if (all_matched != match(session, name, value, idx)) { - insert(session, name, value); - } - } - } - return *this; -} - -hpack_encoder& hpack_encoder::safe_mask(bool enable) { - _safe_mask = enable; - return *this; -} - -hpack_session::hpack_session() {} - -hpack_session::hpack_session(const hpack_session& rhs) : _dynamic_table(rhs._dynamic_table) {} - -bool hpack_session::operator==(const hpack_session& rhs) { return _dynamic_table == rhs._dynamic_table; } - -bool hpack_session::operator!=(const hpack_session& rhs) { return _dynamic_table != rhs._dynamic_table; } - -void hpack_session::for_each(std::function v) { - if (v) { - for (auto item : _dynamic_table) { - v(item.first, item.second.first); - } - } -} - -match_result_t hpack_session::match(const std::string& name, const std::string& value, size_t& index) { - match_result_t state = match_result_t::not_matched; - size_t idx = 0; - for (dynamic_table_t::iterator iter = _dynamic_table.begin(); iter != _dynamic_table.end(); iter++, idx++) { - if ((name == iter->first) && (value == iter->second.first)) { - state = match_result_t::all_matched; - index = idx; - break; - } - } - return state; -} - -return_t hpack_session::select(uint32 flags, size_t index, std::string& name, std::string& value) { - return_t ret = errorcode_t::not_found; - size_t idx = 0; - for (dynamic_table_t::iterator iter = _dynamic_table.begin(); iter != _dynamic_table.end(); iter++, idx++) { - if (index == idx) { - name = iter->first; - value = iter->second.first; - ret = errorcode_t::success; - break; - } - } - return ret; -} - -return_t hpack_session::insert(const std::string& name, const std::string& value) { - return_t ret = errorcode_t::success; - _dynamic_table.push_front(std::make_pair(name, std::make_pair(value, 0))); - return ret; -} - } // namespace net } // namespace hotplace diff --git a/sdk/net/http/http2/hpack.hpp b/sdk/net/http/http2/hpack.hpp index 3860ddf5..e1dba377 100644 --- a/sdk/net/http/http2/hpack.hpp +++ b/sdk/net/http/http2/hpack.hpp @@ -66,10 +66,29 @@ class hpack { hpack& set_session(hpack_session* session); /** - * @brief encode + * @brief set flags for encoding */ hpack& set_encode_flags(uint32 flags); - hpack& encode_header(const std::string& name, const std::string& value); + /** + * @brief encode + * @param const std::string& name [in] + * @param const std::string& value [in] + * @param uint32 flags [inopt] if zero, follows set_encode_flags + * @sample + * hpack hp; + * hpack_session session; + * hp + * .set_encoder(encoder) + * .set_session(&session) + * .set_encode_flags(hpack_indexing | hpack_huffman) + * .encode_header(name1, value1) + * .encode_header(name2, value2); + * .encode_header("content-length", "123", hpack_wo_indexing | hpack_huffman); + */ + hpack& encode_header(const std::string& name, const std::string& value, uint32 flags = 0); + /** + * @brief encoded data + */ binary_t& get_binary(); /** diff --git a/sdk/net/http/http2/hpack_encoder.cpp b/sdk/net/http/http2/hpack_encoder.cpp new file mode 100644 index 00000000..b5ee9e87 --- /dev/null +++ b/sdk/net/http/http2/hpack_encoder.cpp @@ -0,0 +1,533 @@ +/* vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab smarttab : */ +/** + * @file {file} + * @author Soo Han, Kim (princeb612.kr@gmail.com) + * @desc + * + * Revision History + * Date Name Description + */ + +#include +#include +#include + +namespace hotplace { +namespace net { + +hpack_encoder::hpack_encoder() : _safe_mask(false) { + // RFC 7541 Appendix B. Huffman Code + _hc.imports(_h2hcodes); + + // RFC 7541 Appendix A. Static Table Definition + // if (_static_table.empty()) ... + http_resource::get_instance()->for_each_hpack_static_table([&](uint32 index, const char* name, const char* value) -> void { + _static_table.insert(std::make_pair(name, std::make_pair(value ? value : "", index))); + _static_table_index.insert(std::make_pair(index, std::make_pair(name, value ? value : ""))); + }); +} + +hpack_encoder& hpack_encoder::encode_int(binary_t& target, uint8 mask, uint8 prefix, size_t value) { + if ((1 <= prefix) && (prefix <= 8)) { + // RFC 7541 5.1. Integer Representation + // RFC 7541 C.1. Integer Representation Examples + // RFC 7541 Figure 3: Integer Value Encoded after the Prefix (Shown for N = 5) + // + // 0 1 2 3 4 5 6 7 + // +---+---+---+---+---+---+---+---+ + // | ? | ? | ? | 1 1 1 1 1 | + // +---+---+---+-------------------+ + // | 1 | Value-(2^N-1) LSB | + // +---+---------------------------+ + // ... + // +---+---------------------------+ + // | 0 | Value-(2^N-1) MSB | + // +---+---------------------------+ + + uint8 n = (1 << prefix) - 1; + + // safety mask + if (_safe_mask && mask) { + uint8 temp = 0; + for (int t = 0; t < prefix; t++) { + temp |= (1 << t); + } + mask &= ~temp; + } + + uint8 i = 0; + if (value < n) { + target.insert(target.end(), value | mask); + } else { + target.insert(target.end(), n | mask); + value -= n; + // 128 (0x80) + // 1 value + // 1 value + // 0 value + while (value >= 0x80) { + i = (value % 0x80) | 0x80; + target.insert(target.end(), i); + value /= 0x80; + } + target.insert(target.end(), value); + } + } + return *this; +} + +hpack_encoder& hpack_encoder::encode_string(binary_t& target, uint32 flags, const char* value) { + __try2 { + if (nullptr == value) { + __leave2; + } + encode_string(target, flags, value, strlen(value)); + } + __finally2 { + // do nothing + } + return *this; +} + +hpack_encoder& hpack_encoder::encode_string(binary_t& target, uint32 flags, const char* value, size_t size) { + __try2 { + if (nullptr == value) { + __leave2; + } + + // RFC 7541 Figure 4: String Literal Representation + // + // 0 1 2 3 4 5 6 7 + // +---+---+---+---+---+---+---+---+ + // | H | String Length (7+) | + // +---+---------------------------+ + // | String Data (Length octets) | + // +-------------------------------+ + + if (hpack_huffman & flags) { + size_t size_expected = 0; + _hc.expect(value, size, size_expected); + encode_int(target, 0x80, 7, size_expected); + _hc.encode(target, value, size); + } else { + encode_int(target, 0x00, 7, size); + target.insert(target.end(), value, value + size); + } + } + __finally2 { + // do nothing + } + return *this; +} + +hpack_encoder& hpack_encoder::encode_string(binary_t& target, uint32 flags, const std::string& value) { + return encode_string(target, flags, value.c_str(), value.size()); +} + +hpack_encoder& hpack_encoder::encode_index(binary_t& target, uint8 index) { + // RFC 7541 Figure 5: Indexed Header Field + // + // 0 1 2 3 4 5 6 7 + // +---+---+---+---+---+---+---+---+ + // | 1 | Index (7+) | + // +---+---------------------------+ + + encode_int(target, 0x80, 7, index); + return *this; +} + +hpack_encoder& hpack_encoder::encode_indexed_name(binary_t& target, uint32 flags, uint8 index, const char* value) { + __try2 { + if (nullptr == value) { + __leave2; + } + encode_indexed_name(target, flags, index, value, strlen(value)); + } + __finally2 { + // do nothing + } + return *this; +} + +hpack_encoder& hpack_encoder::encode_indexed_name(binary_t& target, uint32 flags, uint8 index, const char* value, size_t size) { + __try2 { + if (nullptr == value) { + __leave2; + } + + if (hpack_indexing & flags) { + // RFC 7541 Figure 6: Literal Header Field with Incremental Indexing -- Indexed Name + // + // 0 1 2 3 4 5 6 7 + // +---+---+---+---+---+---+---+---+ + // | 0 | 1 | Index (6+) | + // +---+---+-----------------------+ + encode_int(target, 0x40, 6, index); + } else if (hpack_wo_indexing & flags) { + // RFC 7541 Figure 8: Literal Header Field without Indexing -- Indexed Name + // + // 0 1 2 3 4 5 6 7 + // +---+---+---+---+---+---+---+---+ + // | 0 | 0 | 0 | 0 | Index (4+) | + // +---+---+-----------------------+ + encode_int(target, 0x00, 4, index); + } else if (hpack_never_indexed & flags) { + // RFC 7541 Figure 10: Literal Header Field Never Indexed -- Indexed Name + // + // 0 1 2 3 4 5 6 7 + // +---+---+---+---+---+---+---+---+ + // | 0 | 0 | 0 | 1 | Index (4+) | + // +---+---+-----------------------+ + encode_int(target, 0x10, 4, index); + } else { + __leave2; + } + + // +-------------------------------+ + // | H | Value Length (7+) | + // +---+---------------------------+ + // | Value String (Length octets) | + // +-------------------------------+ + encode_string(target, flags, value, size); + } + __finally2 { + // do nothing + } + return *this; +} + +hpack_encoder& hpack_encoder::encode_indexed_name(binary_t& target, uint32 flags, uint8 index, const std::string& value) { + return encode_indexed_name(target, flags, index, value.c_str(), value.size()); +} + +hpack_encoder& hpack_encoder::encode_name_value(binary_t& target, uint32 flags, const char* name, const char* value) { + __try2 { + if (nullptr == name || nullptr == value) { + __leave2; + } + + if (hpack_indexing & flags) { + // RFC 7541 Figure 7: Literal Header Field with Incremental Indexing -- New Name + // + // 0 1 2 3 4 5 6 7 + // +---+---+---+---+---+---+---+---+ + // | 0 | 1 | 0 | + // +---+---+-----------------------+ + target.insert(target.end(), 0x40); + } else if (hpack_wo_indexing & flags) { + // RFC 7541 Figure 9: Literal Header Field without Indexing -- New Name + // + // 0 1 2 3 4 5 6 7 + // +---+---+---+---+---+---+---+---+ + // | 0 | 0 | 0 | 0 | 0 | + // +---+---+-----------------------+ + target.insert(target.end(), 0); + } else if (hpack_never_indexed & flags) { + // RFC 7541 Figure 11: Literal Header Field Never Indexed -- New Name + // + // 0 1 2 3 4 5 6 7 + // +---+---+---+---+---+---+---+---+ + // | 0 | 0 | 0 | 1 | 0 | + // +---+---+-----------------------+ + target.insert(target.end(), 0x10); + } else { + __leave2; + } + + // +---+---------------------------+ + // | H | Name Length (7+) | + // +---+---------------------------+ + // | Name String (Length octets) | + // +---+---------------------------+ + // | H | Value Length (7+) | + // +---+---------------------------+ + // | Value String (Length octets) | + // +-------------------------------+ + encode_string(target, flags, name); + encode_string(target, flags, value); + } + __finally2 { + // do nothing + } + return *this; +} + +hpack_encoder& hpack_encoder::encode_name_value(binary_t& target, uint32 flags, const std::string& name, const std::string& value) { + return encode_name_value(target, flags, name.c_str(), value.c_str()); +} + +hpack_encoder& hpack_encoder::encode_dyntablesize(binary_t& target, uint8 maxsize) { + // RFC 7541 Figure 12: Maximum Dynamic Table Size Change + encode_int(target, 0x20, 5, maxsize); + return *this; +} + +return_t hpack_encoder::decode_int(const byte_t* p, size_t& pos, uint8 mask, uint8 prefix, size_t& value) { + // 5.1. Integer Representation + // C.1. Integer Representation Examples + return_t ret = errorcode_t::success; + __try2 { + if (nullptr == p) { + ret = errorcode_t::success; + __leave2; + } + + value = 0; + if ((1 <= prefix) && (prefix <= 8)) { + uint8 n = (1 << prefix) - 1; + uint8 b = p[pos++]; + + if (_safe_mask) { + uint8 temp = 0; + for (int t = 0; t < prefix; t++) { + temp |= (1 << t); + } + mask &= ~temp; + } + b &= ~mask; + + if (b < n) { + value = b; + } else { + size_t m = 0; + size_t i = b; + do { + b = p[pos++]; + i += (b & 0x7f) << m; + m += 7; + } while (0x80 == (b & 0x80)); + value = i; + } + } + } + __finally2 { + // do nothing + } + return ret; +} + +return_t hpack_encoder::decode_string(const byte_t* p, size_t& pos, uint8 flags, std::string& value) { + return_t ret = errorcode_t::success; + __try2 { + value.clear(); + if (nullptr == p) { + ret = errorcode_t::invalid_parameter; + __leave2; + } + + byte_t b = p[pos]; + + size_t len = 0; + if (0x80 & b) { + // huffman + decode_int(p, pos, 0x80, 7, len); + basic_stream bs; + _hc.decode(&bs, p + pos, len); + value = bs.c_str(); + } else { + // string + decode_int(p, pos, 0x80, 7, len); + value.assign((char*)p + pos, len); + } + pos += len; + } + __finally2 { + // do nothing + } + return ret; +} + +match_result_t hpack_encoder::match(hpack_session* session, const std::string& name, const std::string& value, size_t& index) { + match_result_t state = match_result_t::not_matched; + index = 0; + + if (session) { + state = session->match(name, value, index); + if (match_result_t::all_matched == state) { + index += _static_table.size() + 1; + } + } + if (match_result_t::not_matched == state) { + static_table_t::iterator iter; + static_table_t::iterator liter; + static_table_t::iterator uiter; + + liter = _static_table.lower_bound(name); + uiter = _static_table.upper_bound(name); + + for (iter = liter; iter != uiter; iter++) { + if (iter == liter) { + index = iter->second.second; // :path: /sample/path + state = match_result_t::key_matched; + } + if (value == iter->second.first) { + index = iter->second.second; + state = match_result_t::all_matched; + break; + } + } + } + return state; +} + +return_t hpack_encoder::select(hpack_session* session, uint32 flags, size_t index, std::string& name, std::string& value) { + return_t ret = errorcode_t::success; + __try2 { + name.clear(); + value.clear(); + + if (nullptr == session) { + ret = errorcode_t::invalid_parameter; + __leave2; + } + + if (index > _static_table.size()) { + index -= (_static_table.size() + 1); + ret = session->select(flags, index, name, value); + } else { + static_table_index_t::iterator iter = _static_table_index.find(index); + if (_static_table_index.end() == iter) { + ret = errorcode_t::not_found; + __leave2; + } else { + name = iter->second.first; + if ((hpack_index | hpack_name_value) & flags) { + value = iter->second.second; + } + } + } + } + __finally2 { + // do nothing + } + return ret; +} + +return_t hpack_encoder::insert(hpack_session* session, const std::string& name, const std::string& value) { + // RFC 7541 Figure 1: Index Address Space + // + // <---------- Index Address Space ----------> + // <-- Static Table --> <-- Dynamic Table --> + // +---+-----------+---+ +---+-----------+---+ + // | 1 | ... | s | |s+1| ... |s+k| + // +---+-----------+---+ +---+-----------+---+ + // ^ | + // | V + // Insertion Point Dropping Point + // + // Figure 1: Index Address Space + return_t ret = errorcode_t::success; + __try2 { + if (nullptr == session) { + ret = errorcode_t::invalid_parameter; + __leave2; + } + session->insert(name, value); + } + __finally2 { + // do nothing + } + return ret; +} + +hpack_encoder& hpack_encoder::encode_header(hpack_session* session, binary_t& target, const std::string& name, const std::string& value, uint32 flags) { + match_result_t state = match_result_t::not_matched; + if (session) { + size_t index = 0; + + state = match(session, name, value, index); + switch (state) { + case match_result_t::all_matched: + encode_index(target, index); + break; + case match_result_t::key_matched: + encode_indexed_name(target, flags, index, value); + if (hpack_indexing & flags) { + session->insert(name, value); + } + break; + default: + encode_name_value(target, flags, name, value); + if (hpack_indexing & flags) { + session->insert(name, value); + } + break; + } + } + return *this; +} + +hpack_encoder& hpack_encoder::decode_header(hpack_session* session, const byte_t* source, size_t size, size_t& pos, std::string& name, std::string& value) { + if (session && source) { + byte_t b = source[pos]; + uint8 mask = 0; + uint8 prefix = 0; + uint32 flags = 0; + if (0x80 & b) { + // index + mask = 0x80; + prefix = 7; + flags |= hpack_index; + } else if (0x40 & b) { + // indexing + mask = 0x40; + prefix = 6; + flags |= hpack_indexing; + if (0x3f & b) { + flags |= hpack_indexed_name; + } else { + flags |= hpack_name_value; + } + } else if (0xf0 & ~b) { + // without indexing + mask = 0x00; + prefix = 4; + flags |= hpack_wo_indexing; + if (0x0f & b) { + flags |= hpack_indexed_name; + } else { + flags |= hpack_name_value; + } + } else if (0x10 & b) { + // never indexed + mask = 0x10; + prefix = 4; + flags |= hpack_never_indexed; + if (0x0f & b) { + flags |= hpack_indexed_name; + } else { + flags |= hpack_name_value; + } + } + + size_t i = 0; + size_t idx = 0; + if (hpack_index & flags) { + decode_int(source, pos, mask, prefix, i); + select(session, flags, i, name, value); + } else if (hpack_indexed_name & flags) { + decode_int(source, pos, mask, prefix, i); + select(session, flags, i, name, value); + decode_string(source, pos, flags, value); + } else if (hpack_name_value & flags) { + pos++; + decode_string(source, pos, flags, name); + decode_string(source, pos, flags, value); + } + + if (hpack_indexing & flags) { + if (all_matched != match(session, name, value, idx)) { + insert(session, name, value); + } + } + } + return *this; +} + +hpack_encoder& hpack_encoder::safe_mask(bool enable) { + _safe_mask = enable; + return *this; +} + +} // namespace net +} // namespace hotplace diff --git a/sdk/net/http/http2/hpack_session.cpp b/sdk/net/http/http2/hpack_session.cpp new file mode 100644 index 00000000..434cb639 --- /dev/null +++ b/sdk/net/http/http2/hpack_session.cpp @@ -0,0 +1,68 @@ +/* vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab smarttab : */ +/** + * @file {file} + * @author Soo Han, Kim (princeb612.kr@gmail.com) + * @desc + * + * Revision History + * Date Name Description + */ + +#include +#include +#include + +namespace hotplace { +namespace net { + +hpack_session::hpack_session() {} + +hpack_session::hpack_session(const hpack_session& rhs) : _dynamic_table(rhs._dynamic_table) {} + +bool hpack_session::operator==(const hpack_session& rhs) { return _dynamic_table == rhs._dynamic_table; } + +bool hpack_session::operator!=(const hpack_session& rhs) { return _dynamic_table != rhs._dynamic_table; } + +void hpack_session::for_each(std::function v) { + if (v) { + for (auto item : _dynamic_table) { + v(item.first, item.second.first); + } + } +} + +match_result_t hpack_session::match(const std::string& name, const std::string& value, size_t& index) { + match_result_t state = match_result_t::not_matched; + size_t idx = 0; + for (dynamic_table_t::iterator iter = _dynamic_table.begin(); iter != _dynamic_table.end(); iter++, idx++) { + if ((name == iter->first) && (value == iter->second.first)) { + state = match_result_t::all_matched; + index = idx; + break; + } + } + return state; +} + +return_t hpack_session::select(uint32 flags, size_t index, std::string& name, std::string& value) { + return_t ret = errorcode_t::not_found; + size_t idx = 0; + for (dynamic_table_t::iterator iter = _dynamic_table.begin(); iter != _dynamic_table.end(); iter++, idx++) { + if (index == idx) { + name = iter->first; + value = iter->second.first; + ret = errorcode_t::success; + break; + } + } + return ret; +} + +return_t hpack_session::insert(const std::string& name, const std::string& value) { + return_t ret = errorcode_t::success; + _dynamic_table.push_front(std::make_pair(name, std::make_pair(value, 0))); + return ret; +} + +} // namespace net +} // namespace hotplace diff --git a/sdk/net/http/http2/http2_frame.cpp b/sdk/net/http/http2/http2_frame.cpp index b5eeaef5..8e0a18ae 100644 --- a/sdk/net/http/http2/http2_frame.cpp +++ b/sdk/net/http/http2/http2_frame.cpp @@ -44,14 +44,13 @@ constexpr char constexpr_frame_exclusive[] = "exclusive"; constexpr char constexpr_frame_identifier[] = "identifier"; constexpr char constexpr_frame_value[] = "value"; -http2_frame_header::http2_frame_header() : _payload_size(0), _type(0), _flags(0), _stream_id(0), _hpack_encoder(nullptr), _hpack_session(nullptr) {} +http2_frame::http2_frame() : _payload_size(0), _type(0), _flags(0), _stream_id(0), _hpack_encoder(nullptr), _hpack_session(nullptr) {} -http2_frame_header::http2_frame_header(h2_frame_t type) - : _payload_size(0), _type(type), _flags(0), _stream_id(0), _hpack_encoder(nullptr), _hpack_session(nullptr) {} +http2_frame::http2_frame(h2_frame_t type) : _payload_size(0), _type(type), _flags(0), _stream_id(0), _hpack_encoder(nullptr), _hpack_session(nullptr) {} -http2_frame_header::http2_frame_header(const http2_frame_header_t& header) { read(&header, sizeof(http2_frame_header_t)); } +http2_frame::http2_frame(const http2_frame_header_t& header) { read(&header, sizeof(http2_frame_header_t)); } -http2_frame_header::http2_frame_header(const http2_frame_header& rhs) { +http2_frame::http2_frame(const http2_frame& rhs) { _payload_size = rhs._payload_size; _type = rhs._type; _flags = rhs._flags; @@ -60,17 +59,17 @@ http2_frame_header::http2_frame_header(const http2_frame_header& rhs) { _hpack_session = rhs._hpack_session; } -uint32 http2_frame_header::get_frame_size() { return sizeof(http2_frame_header_t) + get_payload_size(); } +uint32 http2_frame::get_frame_size() { return sizeof(http2_frame_header_t) + get_payload_size(); } -uint32 http2_frame_header::get_payload_size() { return _payload_size; } +uint32 http2_frame::get_payload_size() { return _payload_size; } -uint8 http2_frame_header::get_type() { return _type; } +uint8 http2_frame::get_type() { return _type; } -uint8 http2_frame_header::get_flags() { return _flags; } +uint8 http2_frame::get_flags() { return _flags; } -uint32 http2_frame_header::get_stream_id() { return _stream_id; } +uint32 http2_frame::get_stream_id() { return _stream_id; } -return_t http2_frame_header::get_payload(http2_frame_header_t const* header, size_t size, byte_t** payload) { +return_t http2_frame::get_payload(http2_frame_header_t const* header, size_t size, byte_t** payload) { return_t ret = errorcode_t::success; __try2 { if (nullptr == header || nullptr == payload) { @@ -86,7 +85,7 @@ return_t http2_frame_header::get_payload(http2_frame_header_t const* header, siz return ret; } -return_t http2_frame_header::set_payload_size(uint32 size) { +return_t http2_frame::set_payload_size(uint32 size) { return_t ret = errorcode_t::success; if (size > 0x00ffffff) { ret = errorcode_t::bad_data; @@ -96,36 +95,36 @@ return_t http2_frame_header::set_payload_size(uint32 size) { return ret; } -http2_frame_header& http2_frame_header::set_type(h2_frame_t type) { +http2_frame& http2_frame::set_type(h2_frame_t type) { _type = type; return *this; } -http2_frame_header& http2_frame_header::set_flags(uint8 flags) { +http2_frame& http2_frame::set_flags(uint8 flags) { _flags = flags; return *this; } -http2_frame_header& http2_frame_header::set_stream_id(uint32 id) { +http2_frame& http2_frame::set_stream_id(uint32 id) { _stream_id = id; return *this; } -http2_frame_header& http2_frame_header::set_hpack_encoder(hpack_encoder* encoder) { +http2_frame& http2_frame::set_hpack_encoder(hpack_encoder* encoder) { _hpack_encoder = encoder; return *this; } -http2_frame_header& http2_frame_header::set_hpack_session(hpack_session* session) { +http2_frame& http2_frame::set_hpack_session(hpack_session* session) { _hpack_session = session; return *this; } -hpack_encoder* http2_frame_header::get_hpack_encoder() { return _hpack_encoder; } +hpack_encoder* http2_frame::get_hpack_encoder() { return _hpack_encoder; } -hpack_session* http2_frame_header::get_hpack_session() { return _hpack_session; } +hpack_session* http2_frame::get_hpack_session() { return _hpack_session; } -return_t http2_frame_header::read(http2_frame_header_t const* header, size_t size) { +return_t http2_frame::read(http2_frame_header_t const* header, size_t size) { return_t ret = errorcode_t::success; __try2 { if (nullptr == header) { @@ -144,10 +143,10 @@ return_t http2_frame_header::read(http2_frame_header_t const* header, size_t siz pl.read((byte_t*)header, size); - _payload_size = t_variant_to_int(pl.select(constexpr_frame_length)->get_variant().content()); - _type = t_variant_to_int(pl.select(constexpr_frame_type)->get_variant().content()); - _flags = t_variant_to_int(pl.select(constexpr_frame_flags)->get_variant().content()); - _stream_id = t_variant_to_int(pl.select(constexpr_frame_stream_identifier)->get_variant().content()); + _payload_size = t_to_int(pl.select(constexpr_frame_length)); + _type = t_to_int(pl.select(constexpr_frame_type)); + _flags = t_to_int(pl.select(constexpr_frame_flags)); + _stream_id = t_to_int(pl.select(constexpr_frame_stream_identifier)); } __finally2 { // do nothing @@ -155,7 +154,7 @@ return_t http2_frame_header::read(http2_frame_header_t const* header, size_t siz return ret; } -return_t http2_frame_header::write(binary_t& frame) { +return_t http2_frame::write(binary_t& frame) { return_t ret = errorcode_t::success; payload pl; @@ -167,19 +166,19 @@ return_t http2_frame_header::write(binary_t& frame) { return ret; } -void http2_frame_header::dump(stream_t* s) { +void http2_frame::dump(stream_t* s) { if (s) { http_resource* resource = http_resource::get_instance(); std::string frame_name = resource->get_frame_name(get_type()); s->printf("- http/2 frame type %d %s\n", get_type(), frame_name.c_str()); - s->printf("> "); - s->printf("%s %u ", constexpr_frame_length, get_payload_size()); + s->printf(" > "); + s->printf("%s 0x%02x(%u) ", constexpr_frame_length, get_payload_size(), get_payload_size()); s->printf("%s %u ", constexpr_frame_type, get_type()); s->printf("%s %02x ", constexpr_frame_flags, get_flags()); s->printf("%s %08x ", constexpr_frame_stream_identifier, get_stream_id()); s->printf("\n"); - s->printf("> %s [ ", constexpr_frame_flags); + s->printf(" > %s [ ", constexpr_frame_flags); resource->for_each_frame_flag_names(get_type(), get_flags(), [&](uint8 flag, const std::string& name) -> void { s->printf("%s ", name.c_str()); }); @@ -187,18 +186,22 @@ void http2_frame_header::dump(stream_t* s) { } } -void http2_frame_header::dump_hpack(stream_t* s, const binary_t& b) { - if (s && get_hpack_encoder() && get_hpack_session()) { +void http2_frame::read_compressed_header(const byte_t* buf, size_t size, std::function v) { + if (buf && v && get_hpack_encoder() && get_hpack_session()) { size_t pos = 0; std::string name; std::string value; - while (pos < b.size()) { - get_hpack_encoder()->decode_header(get_hpack_session(), &b[0], b.size(), pos, name, value); - s->printf("> %s: %s\n", name.c_str(), value.c_str()); + while (pos < size) { + get_hpack_encoder()->decode_header(get_hpack_session(), buf, size, pos, name, value); + v(name, value); } } } +void http2_frame::read_compressed_header(const binary_t& b, std::function v) { + read_compressed_header(&b[0], b.size(), v); +} + } // namespace net } // namespace hotplace diff --git a/sdk/net/http/http2/http2_frame.hpp b/sdk/net/http/http2/http2_frame.hpp index d9cd3942..754e44f9 100644 --- a/sdk/net/http/http2/http2_frame.hpp +++ b/sdk/net/http/http2/http2_frame.hpp @@ -112,12 +112,12 @@ typedef struct _http2_setting_t { #pragma pack(pop) -class http2_frame_header { +class http2_frame { public: - http2_frame_header(); - http2_frame_header(h2_frame_t type); - http2_frame_header(const http2_frame_header_t& header); - http2_frame_header(const http2_frame_header& rhs); + http2_frame(); + http2_frame(h2_frame_t type); + http2_frame(const http2_frame_header_t& header); + http2_frame(const http2_frame& rhs); uint32 get_frame_size(); uint32 get_payload_size(); @@ -126,19 +126,20 @@ class http2_frame_header { uint32 get_stream_id(); return_t get_payload(http2_frame_header_t const* header, size_t size, byte_t** payload); - http2_frame_header& set_type(h2_frame_t type); - http2_frame_header& set_flags(uint8 flags); - http2_frame_header& set_stream_id(uint32 id); + http2_frame& set_type(h2_frame_t type); + http2_frame& set_flags(uint8 flags); + http2_frame& set_stream_id(uint32 id); - http2_frame_header& set_hpack_encoder(hpack_encoder* encoder); - http2_frame_header& set_hpack_session(hpack_session* session); + http2_frame& set_hpack_encoder(hpack_encoder* encoder); + http2_frame& set_hpack_session(hpack_session* session); hpack_encoder* get_hpack_encoder(); hpack_session* get_hpack_session(); virtual return_t read(http2_frame_header_t const* header, size_t size); virtual return_t write(binary_t& frame); virtual void dump(stream_t* s); - virtual void dump_hpack(stream_t* s, const binary_t& b); + virtual void read_compressed_header(const byte_t* buf, size_t size, std::function v); + virtual void read_compressed_header(const binary_t& b, std::function v); protected: return_t set_payload_size(uint32 size); @@ -159,7 +160,7 @@ class http2_frame_header { * RFC 7540 6.1. DATA * RFC 7540 Figure 6: DATA Frame Payload */ -class http2_frame_data : public http2_frame_header { +class http2_frame_data : public http2_frame { public: http2_frame_data(); http2_frame_data(const http2_frame_data& rhs); @@ -180,7 +181,7 @@ class http2_frame_data : public http2_frame_header { * @see * RFC 7540 6.2 HEADERS */ -class http2_frame_headers : public http2_frame_header { +class http2_frame_headers : public http2_frame { public: http2_frame_headers(); http2_frame_headers(const http2_frame_headers& rhs); @@ -205,7 +206,7 @@ class http2_frame_headers : public http2_frame_header { * RFC 7540 6.3. PRIORITY * RFC 7540 Figure 8: PRIORITY Frame Payload */ -class http2_frame_priority : public http2_frame_header { +class http2_frame_priority : public http2_frame { public: http2_frame_priority(); http2_frame_priority(const http2_frame_priority& rhs); @@ -226,7 +227,7 @@ class http2_frame_priority : public http2_frame_header { * RFC 7540 6.4. RST_STREAM * RFC 7540 Figure 9: RST_STREAM Frame Payload */ -class http2_frame_rst_stream : public http2_frame_header { +class http2_frame_rst_stream : public http2_frame { public: http2_frame_rst_stream(); http2_frame_rst_stream(const http2_frame_rst_stream& rhs); @@ -244,7 +245,7 @@ class http2_frame_rst_stream : public http2_frame_header { * @see * RFC 7540 6.5. SETTINGS */ -class http2_frame_settings : public http2_frame_header { +class http2_frame_settings : public http2_frame { public: http2_frame_settings(); http2_frame_settings(const http2_frame_settings& rhs); @@ -266,7 +267,7 @@ class http2_frame_settings : public http2_frame_header { * @see * RFC 7540 6.6. PUSH_PROMISE */ -class http2_frame_push_promise : public http2_frame_header { +class http2_frame_push_promise : public http2_frame { public: http2_frame_push_promise(); http2_frame_push_promise(const http2_frame_push_promise& rhs); @@ -288,7 +289,7 @@ class http2_frame_push_promise : public http2_frame_header { * @see * RFC 7540 6.7. PING */ -class http2_frame_ping : public http2_frame_header { +class http2_frame_ping : public http2_frame { public: http2_frame_ping(); http2_frame_ping(const http2_frame_ping& rhs); @@ -306,7 +307,7 @@ class http2_frame_ping : public http2_frame_header { * @see * RFC 7540 6.8. GOAWAY */ -class http2_frame_goaway : public http2_frame_header { +class http2_frame_goaway : public http2_frame { public: http2_frame_goaway(); http2_frame_goaway(const http2_frame_goaway& rhs); @@ -329,7 +330,7 @@ class http2_frame_goaway : public http2_frame_header { * @see * RFC 7540 6.9. WINDOW_UPDATE */ -class http2_frame_window_update : public http2_frame_header { +class http2_frame_window_update : public http2_frame { public: http2_frame_window_update(); http2_frame_window_update(const http2_frame_window_update& rhs); @@ -347,7 +348,7 @@ class http2_frame_window_update : public http2_frame_header { * @see * RFC 7540 6.10. CONTINUATION */ -class http2_frame_continuation : public http2_frame_header { +class http2_frame_continuation : public http2_frame { public: http2_frame_continuation(); http2_frame_continuation(const http2_frame_continuation& rhs); @@ -362,6 +363,27 @@ class http2_frame_continuation : public http2_frame_header { binary_t _fragment; }; +extern const char constexpr_frame_length[]; +extern const char constexpr_frame_type[]; +extern const char constexpr_frame_flags[]; +extern const char constexpr_frame_stream_identifier[]; +extern const char constexpr_frame_pad_length[]; +extern const char constexpr_frame_data[]; +extern const char constexpr_frame_padding[]; +extern const char constexpr_frame_stream_dependency[]; +extern const char constexpr_frame_weight[]; +extern const char constexpr_frame_fragment[]; +extern const char constexpr_frame_priority[]; +extern const char constexpr_frame_error_code[]; +extern const char constexpr_frame_promised_stream_id[]; +extern const char constexpr_frame_opaque[]; +extern const char constexpr_frame_last_stream_id[]; +extern const char constexpr_frame_debug_data[]; +extern const char constexpr_frame_window_size_increment[]; +extern const char constexpr_frame_exclusive[]; +extern const char constexpr_frame_identifier[]; +extern const char constexpr_frame_value[]; + } // namespace net } // namespace hotplace diff --git a/sdk/net/http/http2/http2_frame_continuation.cpp b/sdk/net/http/http2/http2_frame_continuation.cpp index cc1e84b1..fc75cbd5 100644 --- a/sdk/net/http/http2/http2_frame_continuation.cpp +++ b/sdk/net/http/http2/http2_frame_continuation.cpp @@ -22,31 +22,9 @@ namespace hotplace { using namespace io; namespace net { -constexpr char constexpr_frame_length[] = "length"; -constexpr char constexpr_frame_type[] = "type"; -constexpr char constexpr_frame_flags[] = "flags"; -constexpr char constexpr_frame_stream_identifier[] = "stream identifier"; -constexpr char constexpr_frame_pad_length[] = "pad length"; -constexpr char constexpr_frame_data[] = "data"; -constexpr char constexpr_frame_padding[] = "padding"; -constexpr char constexpr_frame_stream_dependency[] = "stream dependency"; -constexpr char constexpr_frame_weight[] = "weight"; -constexpr char constexpr_frame_fragment[] = "fragment"; -constexpr char constexpr_frame_priority[] = "priority"; -constexpr char constexpr_frame_error_code[] = "error code"; -constexpr char constexpr_frame_promised_stream_id[] = "promised stream id"; -constexpr char constexpr_frame_opaque[] = "opaque"; -constexpr char constexpr_frame_last_stream_id[] = "last stream id"; -constexpr char constexpr_frame_debug_data[] = "debug data"; -constexpr char constexpr_frame_window_size_increment[] = "window size increment"; - -constexpr char constexpr_frame_exclusive[] = "exclusive"; -constexpr char constexpr_frame_identifier[] = "identifier"; -constexpr char constexpr_frame_value[] = "value"; - -http2_frame_continuation::http2_frame_continuation() : http2_frame_header(h2_frame_t::h2_frame_continuation) {} - -http2_frame_continuation::http2_frame_continuation(const http2_frame_continuation& rhs) : http2_frame_header(rhs) { _fragment = rhs._fragment; } +http2_frame_continuation::http2_frame_continuation() : http2_frame(h2_frame_t::h2_frame_continuation) {} + +http2_frame_continuation::http2_frame_continuation(const http2_frame_continuation& rhs) : http2_frame(rhs) { _fragment = rhs._fragment; } return_t http2_frame_continuation::read(http2_frame_header_t const* header, size_t size) { return_t ret = errorcode_t::success; @@ -57,7 +35,7 @@ return_t http2_frame_continuation::read(http2_frame_header_t const* header, size } // check size and then read header - ret = http2_frame_header::read(header, size); + ret = http2_frame::read(header, size); if (errorcode_t::success != ret) { __leave2; } @@ -92,7 +70,7 @@ return_t http2_frame_continuation::write(binary_t& frame) { set_payload_size(bin_payload.size()); - http2_frame_header::write(frame); + http2_frame::write(frame); frame.insert(frame.end(), bin_payload.begin(), bin_payload.end()); return ret; @@ -100,13 +78,14 @@ return_t http2_frame_continuation::write(binary_t& frame) { void http2_frame_continuation::dump(stream_t* s) { if (s) { - http2_frame_header::dump(s); + http2_frame::dump(s); - s->printf("> %s\n", constexpr_frame_fragment); - dump_memory(_fragment, s, 16, 2, 0x0, dump_memory_flag_t::dump_notrunc); + s->printf(" > %s\n", constexpr_frame_fragment); + dump_memory(_fragment, s, 16, 3, 0x0, dump_memory_flag_t::dump_notrunc); s->printf("\n"); - http2_frame_header::dump_hpack(s, _fragment); + http2_frame::read_compressed_header( + _fragment, [&](const std::string& name, const std::string& value) -> void { s->printf(" > %s: %s\n", name.c_str(), value.c_str()); }); } } diff --git a/sdk/net/http/http2/http2_frame_data.cpp b/sdk/net/http/http2/http2_frame_data.cpp index b13e2ddf..ee35c825 100644 --- a/sdk/net/http/http2/http2_frame_data.cpp +++ b/sdk/net/http/http2/http2_frame_data.cpp @@ -22,31 +22,9 @@ namespace hotplace { using namespace io; namespace net { -constexpr char constexpr_frame_length[] = "length"; -constexpr char constexpr_frame_type[] = "type"; -constexpr char constexpr_frame_flags[] = "flags"; -constexpr char constexpr_frame_stream_identifier[] = "stream identifier"; -constexpr char constexpr_frame_pad_length[] = "pad length"; -constexpr char constexpr_frame_data[] = "data"; -constexpr char constexpr_frame_padding[] = "padding"; -constexpr char constexpr_frame_stream_dependency[] = "stream dependency"; -constexpr char constexpr_frame_weight[] = "weight"; -constexpr char constexpr_frame_fragment[] = "fragment"; -constexpr char constexpr_frame_priority[] = "priority"; -constexpr char constexpr_frame_error_code[] = "error code"; -constexpr char constexpr_frame_promised_stream_id[] = "promised stream id"; -constexpr char constexpr_frame_opaque[] = "opaque"; -constexpr char constexpr_frame_last_stream_id[] = "last stream id"; -constexpr char constexpr_frame_debug_data[] = "debug data"; -constexpr char constexpr_frame_window_size_increment[] = "window size increment"; - -constexpr char constexpr_frame_exclusive[] = "exclusive"; -constexpr char constexpr_frame_identifier[] = "identifier"; -constexpr char constexpr_frame_value[] = "value"; - -http2_frame_data::http2_frame_data() : http2_frame_header(h2_frame_t::h2_frame_data), _padlen(0) {} - -http2_frame_data::http2_frame_data(const http2_frame_data& rhs) : http2_frame_header(rhs), _padlen(rhs._padlen) { _data = rhs._data; } +http2_frame_data::http2_frame_data() : http2_frame(h2_frame_t::h2_frame_data), _padlen(0) {} + +http2_frame_data::http2_frame_data(const http2_frame_data& rhs) : http2_frame(rhs), _padlen(rhs._padlen) { _data = rhs._data; } return_t http2_frame_data::read(http2_frame_header_t const* header, size_t size) { return_t ret = errorcode_t::success; @@ -58,7 +36,7 @@ return_t http2_frame_data::read(http2_frame_header_t const* header, size_t size) } // check size and then read header - ret = http2_frame_header::read(header, size); + ret = http2_frame::read(header, size); if (errorcode_t::success != ret) { __leave2; } @@ -80,7 +58,7 @@ return_t http2_frame_data::read(http2_frame_header_t const* header, size_t size) pl.read(ptr_payload, get_payload_size()); - _padlen = t_variant_to_int(pl.select(constexpr_frame_pad_length)->get_variant().content()); + _padlen = t_to_int(pl.select(constexpr_frame_pad_length)); pl.select(constexpr_frame_data)->get_variant().dump(_data, true); } __finally2 { @@ -110,7 +88,7 @@ return_t http2_frame_data::write(binary_t& frame) { set_flags(flags); set_payload_size(bin_payload.size()); - http2_frame_header::write(frame); + http2_frame::write(frame); frame.insert(frame.end(), bin_payload.begin(), bin_payload.end()); return ret; @@ -118,9 +96,9 @@ return_t http2_frame_data::write(binary_t& frame) { void http2_frame_data::dump(stream_t* s) { if (s) { - http2_frame_header::dump(s); - s->printf("> %s\n", constexpr_frame_data); - dump_memory(_data, s, 16, 2, 0x0, dump_memory_flag_t::dump_notrunc); + http2_frame::dump(s); + s->printf(" > %s\n", constexpr_frame_data); + dump_memory(_data, s, 16, 3, 0x0, dump_memory_flag_t::dump_notrunc); s->printf("\n"); } } diff --git a/sdk/net/http/http2/http2_frame_goaway.cpp b/sdk/net/http/http2/http2_frame_goaway.cpp index 007a2867..ad652e68 100644 --- a/sdk/net/http/http2/http2_frame_goaway.cpp +++ b/sdk/net/http/http2/http2_frame_goaway.cpp @@ -22,31 +22,9 @@ namespace hotplace { using namespace io; namespace net { -constexpr char constexpr_frame_length[] = "length"; -constexpr char constexpr_frame_type[] = "type"; -constexpr char constexpr_frame_flags[] = "flags"; -constexpr char constexpr_frame_stream_identifier[] = "stream identifier"; -constexpr char constexpr_frame_pad_length[] = "pad length"; -constexpr char constexpr_frame_data[] = "data"; -constexpr char constexpr_frame_padding[] = "padding"; -constexpr char constexpr_frame_stream_dependency[] = "stream dependency"; -constexpr char constexpr_frame_weight[] = "weight"; -constexpr char constexpr_frame_fragment[] = "fragment"; -constexpr char constexpr_frame_priority[] = "priority"; -constexpr char constexpr_frame_error_code[] = "error code"; -constexpr char constexpr_frame_promised_stream_id[] = "promised stream id"; -constexpr char constexpr_frame_opaque[] = "opaque"; -constexpr char constexpr_frame_last_stream_id[] = "last stream id"; -constexpr char constexpr_frame_debug_data[] = "debug data"; -constexpr char constexpr_frame_window_size_increment[] = "window size increment"; - -constexpr char constexpr_frame_exclusive[] = "exclusive"; -constexpr char constexpr_frame_identifier[] = "identifier"; -constexpr char constexpr_frame_value[] = "value"; - -http2_frame_goaway::http2_frame_goaway() : http2_frame_header(h2_frame_t::h2_frame_goaway), _last_id(0), _errorcode(0) {} - -http2_frame_goaway::http2_frame_goaway(const http2_frame_goaway& rhs) : http2_frame_header(rhs), _last_id(rhs._last_id), _errorcode(rhs._errorcode) { +http2_frame_goaway::http2_frame_goaway() : http2_frame(h2_frame_t::h2_frame_goaway), _last_id(0), _errorcode(0) {} + +http2_frame_goaway::http2_frame_goaway(const http2_frame_goaway& rhs) : http2_frame(rhs), _last_id(rhs._last_id), _errorcode(rhs._errorcode) { _debug = rhs._debug; } @@ -59,7 +37,7 @@ return_t http2_frame_goaway::read(http2_frame_header_t const* header, size_t siz } // check size and then read header - ret = http2_frame_header::read(header, size); + ret = http2_frame::read(header, size); if (errorcode_t::success != ret) { __leave2; } @@ -76,8 +54,8 @@ return_t http2_frame_goaway::read(http2_frame_header_t const* header, size_t siz pl.read(ptr_payload, get_payload_size()); - _last_id = t_variant_to_int(pl.select(constexpr_frame_last_stream_id)->get_variant().content()); - _errorcode = t_variant_to_int(pl.select(constexpr_frame_error_code)->get_variant().content()); + _last_id = t_to_int(pl.select(constexpr_frame_last_stream_id)); + _errorcode = t_to_int(pl.select(constexpr_frame_error_code)); pl.select(constexpr_frame_debug_data)->get_variant().dump(_debug, true); } __finally2 { @@ -98,7 +76,7 @@ return_t http2_frame_goaway::write(binary_t& frame) { set_payload_size(bin_payload.size()); - http2_frame_header::write(frame); + http2_frame::write(frame); frame.insert(frame.end(), bin_payload.begin(), bin_payload.end()); return ret; @@ -106,12 +84,12 @@ return_t http2_frame_goaway::write(binary_t& frame) { void http2_frame_goaway::dump(stream_t* s) { if (s) { - http2_frame_header::dump(s); + http2_frame::dump(s); - s->printf("> %s %u\n", constexpr_frame_last_stream_id, _last_id); - s->printf("> %s %u\n", constexpr_frame_error_code, _errorcode); - s->printf("> %s\n", constexpr_frame_debug_data); - dump_memory(_debug, s, 16, 2, 0x0, dump_memory_flag_t::dump_notrunc); + s->printf(" > %s %u\n", constexpr_frame_last_stream_id, _last_id); + s->printf(" > %s %u\n", constexpr_frame_error_code, _errorcode); + s->printf(" > %s\n", constexpr_frame_debug_data); + dump_memory(_debug, s, 16, 3, 0x0, dump_memory_flag_t::dump_notrunc); s->printf("\n"); } } diff --git a/sdk/net/http/http2/http2_frame_headers.cpp b/sdk/net/http/http2/http2_frame_headers.cpp index 82105258..2c4b363e 100644 --- a/sdk/net/http/http2/http2_frame_headers.cpp +++ b/sdk/net/http/http2/http2_frame_headers.cpp @@ -22,32 +22,10 @@ namespace hotplace { using namespace io; namespace net { -constexpr char constexpr_frame_length[] = "length"; -constexpr char constexpr_frame_type[] = "type"; -constexpr char constexpr_frame_flags[] = "flags"; -constexpr char constexpr_frame_stream_identifier[] = "stream identifier"; -constexpr char constexpr_frame_pad_length[] = "pad length"; -constexpr char constexpr_frame_data[] = "data"; -constexpr char constexpr_frame_padding[] = "padding"; -constexpr char constexpr_frame_stream_dependency[] = "stream dependency"; -constexpr char constexpr_frame_weight[] = "weight"; -constexpr char constexpr_frame_fragment[] = "fragment"; -constexpr char constexpr_frame_priority[] = "priority"; -constexpr char constexpr_frame_error_code[] = "error code"; -constexpr char constexpr_frame_promised_stream_id[] = "promised stream id"; -constexpr char constexpr_frame_opaque[] = "opaque"; -constexpr char constexpr_frame_last_stream_id[] = "last stream id"; -constexpr char constexpr_frame_debug_data[] = "debug data"; -constexpr char constexpr_frame_window_size_increment[] = "window size increment"; - -constexpr char constexpr_frame_exclusive[] = "exclusive"; -constexpr char constexpr_frame_identifier[] = "identifier"; -constexpr char constexpr_frame_value[] = "value"; - -http2_frame_headers::http2_frame_headers() : http2_frame_header(h2_frame_t::h2_frame_headers), _padlen(0), _exclusive(false), _dependency(0), _weight(0) {} +http2_frame_headers::http2_frame_headers() : http2_frame(h2_frame_t::h2_frame_headers), _padlen(0), _exclusive(false), _dependency(0), _weight(0) {} http2_frame_headers::http2_frame_headers(const http2_frame_headers& rhs) - : http2_frame_header(rhs), _padlen(rhs._padlen), _exclusive(rhs._exclusive), _dependency(rhs._dependency), _weight(rhs._weight) { + : http2_frame(rhs), _padlen(rhs._padlen), _exclusive(rhs._exclusive), _dependency(rhs._dependency), _weight(rhs._weight) { _fragment = rhs._fragment; } @@ -60,7 +38,7 @@ return_t http2_frame_headers::read(http2_frame_header_t const* header, size_t si } // check size and then read header - ret = http2_frame_header::read(header, size); + ret = http2_frame::read(header, size); if (errorcode_t::success != ret) { __leave2; } @@ -84,13 +62,13 @@ return_t http2_frame_headers::read(http2_frame_header_t const* header, size_t si pl.read(ptr_payload, get_payload_size()); if (get_flags() & h2_flag_t::h2_flag_padded) { - _padlen = t_variant_to_int(pl.select(constexpr_frame_pad_length)->get_variant().content()); + _padlen = t_to_int(pl.select(constexpr_frame_pad_length)); } if (get_flags() & h2_flag_t::h2_flag_priority) { - uint32 temp = t_variant_to_int(pl.select(constexpr_frame_stream_dependency)->get_variant().content()); + uint32 temp = t_to_int(pl.select(constexpr_frame_stream_dependency)); _exclusive = (temp & 0x80000000) ? true : false; _dependency = (temp & 0x7fffffff); - _weight = t_variant_to_int(pl.select(constexpr_frame_weight)->get_variant().content()); + _weight = t_to_int(pl.select(constexpr_frame_weight)); } pl.select(constexpr_frame_fragment)->get_variant().dump(_fragment, true); } @@ -134,7 +112,7 @@ return_t http2_frame_headers::write(binary_t& frame) { set_flags(flags); set_payload_size(bin_payload.size()); - http2_frame_header::write(frame); + http2_frame::write(frame); frame.insert(frame.end(), bin_payload.begin(), bin_payload.end()); return ret; @@ -142,16 +120,17 @@ return_t http2_frame_headers::write(binary_t& frame) { void http2_frame_headers::dump(stream_t* s) { if (s) { - http2_frame_header::dump(s); + http2_frame::dump(s); if (get_flags() & h2_flag_t::h2_flag_priority) { - s->printf("> %s E:%u %08x\n", constexpr_frame_stream_dependency, _exclusive ? 1 : 0, _dependency); - s->printf("> %s %02x\n", constexpr_frame_weight, _weight); + s->printf(" > %s E:%u %08x\n", constexpr_frame_stream_dependency, _exclusive ? 1 : 0, _dependency); + s->printf(" > %s %02x\n", constexpr_frame_weight, _weight); } - s->printf("> %s\n", constexpr_frame_fragment); - dump_memory(_fragment, s, 16, 2, 0x0, dump_memory_flag_t::dump_notrunc); + s->printf(" > %s\n", constexpr_frame_fragment); + dump_memory(_fragment, s, 16, 3, 0x0, dump_memory_flag_t::dump_notrunc); s->printf("\n"); - http2_frame_header::dump_hpack(s, _fragment); + http2_frame::read_compressed_header( + _fragment, [&](const std::string& name, const std::string& value) -> void { s->printf(" > %s: %s\n", name.c_str(), value.c_str()); }); } } diff --git a/sdk/net/http/http2/http2_frame_ping.cpp b/sdk/net/http/http2/http2_frame_ping.cpp index 68fe8b71..a0a293fe 100644 --- a/sdk/net/http/http2/http2_frame_ping.cpp +++ b/sdk/net/http/http2/http2_frame_ping.cpp @@ -22,31 +22,9 @@ namespace hotplace { using namespace io; namespace net { -constexpr char constexpr_frame_length[] = "length"; -constexpr char constexpr_frame_type[] = "type"; -constexpr char constexpr_frame_flags[] = "flags"; -constexpr char constexpr_frame_stream_identifier[] = "stream identifier"; -constexpr char constexpr_frame_pad_length[] = "pad length"; -constexpr char constexpr_frame_data[] = "data"; -constexpr char constexpr_frame_padding[] = "padding"; -constexpr char constexpr_frame_stream_dependency[] = "stream dependency"; -constexpr char constexpr_frame_weight[] = "weight"; -constexpr char constexpr_frame_fragment[] = "fragment"; -constexpr char constexpr_frame_priority[] = "priority"; -constexpr char constexpr_frame_error_code[] = "error code"; -constexpr char constexpr_frame_promised_stream_id[] = "promised stream id"; -constexpr char constexpr_frame_opaque[] = "opaque"; -constexpr char constexpr_frame_last_stream_id[] = "last stream id"; -constexpr char constexpr_frame_debug_data[] = "debug data"; -constexpr char constexpr_frame_window_size_increment[] = "window size increment"; - -constexpr char constexpr_frame_exclusive[] = "exclusive"; -constexpr char constexpr_frame_identifier[] = "identifier"; -constexpr char constexpr_frame_value[] = "value"; - -http2_frame_ping::http2_frame_ping() : http2_frame_header(h2_frame_t::h2_frame_ping), _opaque(0) {} - -http2_frame_ping::http2_frame_ping(const http2_frame_ping& rhs) : http2_frame_header(rhs), _opaque(rhs._opaque) {} +http2_frame_ping::http2_frame_ping() : http2_frame(h2_frame_t::h2_frame_ping), _opaque(0) {} + +http2_frame_ping::http2_frame_ping(const http2_frame_ping& rhs) : http2_frame(rhs), _opaque(rhs._opaque) {} return_t http2_frame_ping::read(http2_frame_header_t const* header, size_t size) { return_t ret = errorcode_t::success; @@ -57,7 +35,7 @@ return_t http2_frame_ping::read(http2_frame_header_t const* header, size_t size) } // check size and then read header - ret = http2_frame_header::read(header, size); + ret = http2_frame::read(header, size); if (errorcode_t::success != ret) { __leave2; } @@ -74,7 +52,7 @@ return_t http2_frame_ping::read(http2_frame_header_t const* header, size_t size) pl.read(ptr_payload, get_payload_size()); - _opaque = t_variant_to_int(pl.select(constexpr_frame_opaque)->get_variant().content()); + _opaque = t_to_int(pl.select(constexpr_frame_opaque)); } __finally2 { // do nothing @@ -93,7 +71,7 @@ return_t http2_frame_ping::write(binary_t& frame) { set_payload_size(bin_payload.size()); - http2_frame_header::write(frame); + http2_frame::write(frame); frame.insert(frame.end(), bin_payload.begin(), bin_payload.end()); return ret; @@ -101,9 +79,9 @@ return_t http2_frame_ping::write(binary_t& frame) { void http2_frame_ping::dump(stream_t* s) { if (s) { - http2_frame_header::dump(s); + http2_frame::dump(s); - s->printf("> %s %I64u\n", constexpr_frame_opaque, _opaque); + s->printf(" > %s %I64u\n", constexpr_frame_opaque, _opaque); } } diff --git a/sdk/net/http/http2/http2_frame_priority.cpp b/sdk/net/http/http2/http2_frame_priority.cpp index 813dab65..84803cd1 100644 --- a/sdk/net/http/http2/http2_frame_priority.cpp +++ b/sdk/net/http/http2/http2_frame_priority.cpp @@ -22,32 +22,10 @@ namespace hotplace { using namespace io; namespace net { -constexpr char constexpr_frame_length[] = "length"; -constexpr char constexpr_frame_type[] = "type"; -constexpr char constexpr_frame_flags[] = "flags"; -constexpr char constexpr_frame_stream_identifier[] = "stream identifier"; -constexpr char constexpr_frame_pad_length[] = "pad length"; -constexpr char constexpr_frame_data[] = "data"; -constexpr char constexpr_frame_padding[] = "padding"; -constexpr char constexpr_frame_stream_dependency[] = "stream dependency"; -constexpr char constexpr_frame_weight[] = "weight"; -constexpr char constexpr_frame_fragment[] = "fragment"; -constexpr char constexpr_frame_priority[] = "priority"; -constexpr char constexpr_frame_error_code[] = "error code"; -constexpr char constexpr_frame_promised_stream_id[] = "promised stream id"; -constexpr char constexpr_frame_opaque[] = "opaque"; -constexpr char constexpr_frame_last_stream_id[] = "last stream id"; -constexpr char constexpr_frame_debug_data[] = "debug data"; -constexpr char constexpr_frame_window_size_increment[] = "window size increment"; - -constexpr char constexpr_frame_exclusive[] = "exclusive"; -constexpr char constexpr_frame_identifier[] = "identifier"; -constexpr char constexpr_frame_value[] = "value"; - -http2_frame_priority::http2_frame_priority() : http2_frame_header(h2_frame_t::h2_frame_priority), _exclusive(false), _dependency(0), _weight(0) {} +http2_frame_priority::http2_frame_priority() : http2_frame(h2_frame_t::h2_frame_priority), _exclusive(false), _dependency(0), _weight(0) {} http2_frame_priority::http2_frame_priority(const http2_frame_priority& rhs) - : http2_frame_header(rhs), _exclusive(rhs._exclusive), _dependency(rhs._dependency), _weight(rhs._weight) {} + : http2_frame(rhs), _exclusive(rhs._exclusive), _dependency(rhs._dependency), _weight(rhs._weight) {} return_t http2_frame_priority::read(http2_frame_header_t const* header, size_t size) { return_t ret = errorcode_t::success; @@ -59,7 +37,7 @@ return_t http2_frame_priority::read(http2_frame_header_t const* header, size_t s } // check size and then read header - ret = http2_frame_header::read(header, size); + ret = http2_frame::read(header, size); if (errorcode_t::success != ret) { __leave2; } @@ -77,10 +55,10 @@ return_t http2_frame_priority::read(http2_frame_header_t const* header, size_t s pl.read(ptr_payload, get_payload_size()); - uint32 temp = t_variant_to_int(pl.select(constexpr_frame_stream_dependency)->get_variant().content()); + uint32 temp = t_to_int(pl.select(constexpr_frame_stream_dependency)); _exclusive = (temp & 0x80000000) ? true : false; _dependency = (temp & 0x7fffffff); - _weight = t_variant_to_int(pl.select(constexpr_frame_weight)->get_variant().content()); + _weight = t_to_int(pl.select(constexpr_frame_weight)); } __finally2 { // do nothing @@ -104,7 +82,7 @@ return_t http2_frame_priority::write(binary_t& frame) { set_payload_size(bin_payload.size()); - http2_frame_header::write(frame); + http2_frame::write(frame); frame.insert(frame.end(), bin_payload.begin(), bin_payload.end()); return ret; @@ -112,11 +90,11 @@ return_t http2_frame_priority::write(binary_t& frame) { void http2_frame_priority::dump(stream_t* s) { if (s) { - http2_frame_header::dump(s); + http2_frame::dump(s); - s->printf("> %s %u\n", constexpr_frame_exclusive, _exclusive ? 1 : 0); - s->printf("> %s %u\n", constexpr_frame_stream_dependency, _dependency); - s->printf("> %s %u\n", constexpr_frame_weight, _weight); + s->printf(" > %s %u\n", constexpr_frame_exclusive, _exclusive ? 1 : 0); + s->printf(" > %s %u\n", constexpr_frame_stream_dependency, _dependency); + s->printf(" > %s %u\n", constexpr_frame_weight, _weight); } } diff --git a/sdk/net/http/http2/http2_frame_push_promise.cpp b/sdk/net/http/http2/http2_frame_push_promise.cpp index 85d6befe..00b2e1e2 100644 --- a/sdk/net/http/http2/http2_frame_push_promise.cpp +++ b/sdk/net/http/http2/http2_frame_push_promise.cpp @@ -22,32 +22,10 @@ namespace hotplace { using namespace io; namespace net { -constexpr char constexpr_frame_length[] = "length"; -constexpr char constexpr_frame_type[] = "type"; -constexpr char constexpr_frame_flags[] = "flags"; -constexpr char constexpr_frame_stream_identifier[] = "stream identifier"; -constexpr char constexpr_frame_pad_length[] = "pad length"; -constexpr char constexpr_frame_data[] = "data"; -constexpr char constexpr_frame_padding[] = "padding"; -constexpr char constexpr_frame_stream_dependency[] = "stream dependency"; -constexpr char constexpr_frame_weight[] = "weight"; -constexpr char constexpr_frame_fragment[] = "fragment"; -constexpr char constexpr_frame_priority[] = "priority"; -constexpr char constexpr_frame_error_code[] = "error code"; -constexpr char constexpr_frame_promised_stream_id[] = "promised stream id"; -constexpr char constexpr_frame_opaque[] = "opaque"; -constexpr char constexpr_frame_last_stream_id[] = "last stream id"; -constexpr char constexpr_frame_debug_data[] = "debug data"; -constexpr char constexpr_frame_window_size_increment[] = "window size increment"; - -constexpr char constexpr_frame_exclusive[] = "exclusive"; -constexpr char constexpr_frame_identifier[] = "identifier"; -constexpr char constexpr_frame_value[] = "value"; - -http2_frame_push_promise::http2_frame_push_promise() : http2_frame_header(h2_frame_t::h2_frame_push_promise), _padlen(0), _promised_id(0) {} +http2_frame_push_promise::http2_frame_push_promise() : http2_frame(h2_frame_t::h2_frame_push_promise), _padlen(0), _promised_id(0) {} http2_frame_push_promise::http2_frame_push_promise(const http2_frame_push_promise& rhs) - : http2_frame_header(rhs), _padlen(rhs._padlen), _promised_id(rhs._promised_id) { + : http2_frame(rhs), _padlen(rhs._padlen), _promised_id(rhs._promised_id) { _fragment = rhs._fragment; } @@ -60,7 +38,7 @@ return_t http2_frame_push_promise::read(http2_frame_header_t const* header, size } // check size and then read header - ret = http2_frame_header::read(header, size); + ret = http2_frame::read(header, size); if (errorcode_t::success != ret) { __leave2; } @@ -82,10 +60,10 @@ return_t http2_frame_push_promise::read(http2_frame_header_t const* header, size pl.read(ptr_payload, get_payload_size()); if (get_flags() & h2_flag_t::h2_flag_padded) { - _padlen = t_variant_to_int(pl.select(constexpr_frame_pad_length)->get_variant().content()); + _padlen = t_to_int(pl.select(constexpr_frame_pad_length)); } - _promised_id = t_variant_to_int(pl.select(constexpr_frame_promised_stream_id)->get_variant().content()); + _promised_id = t_to_int(pl.select(constexpr_frame_promised_stream_id)); pl.select(constexpr_frame_fragment)->get_variant().dump(_fragment, true); } __finally2 { @@ -116,7 +94,7 @@ return_t http2_frame_push_promise::write(binary_t& frame) { set_flags(flags); set_payload_size(bin_payload.size()); - http2_frame_header::write(frame); + http2_frame::write(frame); frame.insert(frame.end(), bin_payload.begin(), bin_payload.end()); return ret; @@ -124,13 +102,14 @@ return_t http2_frame_push_promise::write(binary_t& frame) { void http2_frame_push_promise::dump(stream_t* s) { if (s) { - http2_frame_header::dump(s); - s->printf("> %s %u\n", constexpr_frame_promised_stream_id, _promised_id); - s->printf("> %s\n", constexpr_frame_fragment); - dump_memory(_fragment, s, 16, 2, 0x0, dump_memory_flag_t::dump_notrunc); + http2_frame::dump(s); + s->printf(" > %s %u\n", constexpr_frame_promised_stream_id, _promised_id); + s->printf(" > %s\n", constexpr_frame_fragment); + dump_memory(_fragment, s, 16, 3, 0x0, dump_memory_flag_t::dump_notrunc); s->printf("\n"); - http2_frame_header::dump_hpack(s, _fragment); + http2_frame::read_compressed_header( + _fragment, [&](const std::string& name, const std::string& value) -> void { s->printf(" > %s: %s\n", name.c_str(), value.c_str()); }); } } diff --git a/sdk/net/http/http2/http2_frame_rst_stream.cpp b/sdk/net/http/http2/http2_frame_rst_stream.cpp index ba9c2417..2e6db5c7 100644 --- a/sdk/net/http/http2/http2_frame_rst_stream.cpp +++ b/sdk/net/http/http2/http2_frame_rst_stream.cpp @@ -22,31 +22,9 @@ namespace hotplace { using namespace io; namespace net { -constexpr char constexpr_frame_length[] = "length"; -constexpr char constexpr_frame_type[] = "type"; -constexpr char constexpr_frame_flags[] = "flags"; -constexpr char constexpr_frame_stream_identifier[] = "stream identifier"; -constexpr char constexpr_frame_pad_length[] = "pad length"; -constexpr char constexpr_frame_data[] = "data"; -constexpr char constexpr_frame_padding[] = "padding"; -constexpr char constexpr_frame_stream_dependency[] = "stream dependency"; -constexpr char constexpr_frame_weight[] = "weight"; -constexpr char constexpr_frame_fragment[] = "fragment"; -constexpr char constexpr_frame_priority[] = "priority"; -constexpr char constexpr_frame_error_code[] = "error code"; -constexpr char constexpr_frame_promised_stream_id[] = "promised stream id"; -constexpr char constexpr_frame_opaque[] = "opaque"; -constexpr char constexpr_frame_last_stream_id[] = "last stream id"; -constexpr char constexpr_frame_debug_data[] = "debug data"; -constexpr char constexpr_frame_window_size_increment[] = "window size increment"; - -constexpr char constexpr_frame_exclusive[] = "exclusive"; -constexpr char constexpr_frame_identifier[] = "identifier"; -constexpr char constexpr_frame_value[] = "value"; - -http2_frame_rst_stream::http2_frame_rst_stream() : http2_frame_header(h2_frame_t::h2_frame_rst_stream), _errorcode(0) {} - -http2_frame_rst_stream::http2_frame_rst_stream(const http2_frame_rst_stream& rhs) : http2_frame_header(rhs), _errorcode(rhs._errorcode) {} +http2_frame_rst_stream::http2_frame_rst_stream() : http2_frame(h2_frame_t::h2_frame_rst_stream), _errorcode(0) {} + +http2_frame_rst_stream::http2_frame_rst_stream(const http2_frame_rst_stream& rhs) : http2_frame(rhs), _errorcode(rhs._errorcode) {} return_t http2_frame_rst_stream::read(http2_frame_header_t const* header, size_t size) { return_t ret = errorcode_t::success; @@ -58,7 +36,7 @@ return_t http2_frame_rst_stream::read(http2_frame_header_t const* header, size_t } // check size and then read header - ret = http2_frame_header::read(header, size); + ret = http2_frame::read(header, size); if (errorcode_t::success != ret) { __leave2; } @@ -74,7 +52,7 @@ return_t http2_frame_rst_stream::read(http2_frame_header_t const* header, size_t pl.read(ptr_payload, get_payload_size()); - _errorcode = t_variant_to_int(pl.select(constexpr_frame_error_code)->get_variant().content()); + _errorcode = t_to_int(pl.select(constexpr_frame_error_code)); } __finally2 { // do nothing @@ -93,7 +71,7 @@ return_t http2_frame_rst_stream::write(binary_t& frame) { set_payload_size(bin_payload.size()); - http2_frame_header::write(frame); + http2_frame::write(frame); frame.insert(frame.end(), bin_payload.begin(), bin_payload.end()); return ret; @@ -101,9 +79,9 @@ return_t http2_frame_rst_stream::write(binary_t& frame) { void http2_frame_rst_stream::dump(stream_t* s) { if (s) { - http2_frame_header::dump(s); + http2_frame::dump(s); - s->printf("> %s %u\n", constexpr_frame_error_code, _errorcode); + s->printf(" > %s %u\n", constexpr_frame_error_code, _errorcode); } } diff --git a/sdk/net/http/http2/http2_frame_settings.cpp b/sdk/net/http/http2/http2_frame_settings.cpp index a0cb42f9..2213a26a 100644 --- a/sdk/net/http/http2/http2_frame_settings.cpp +++ b/sdk/net/http/http2/http2_frame_settings.cpp @@ -22,31 +22,9 @@ namespace hotplace { using namespace io; namespace net { -constexpr char constexpr_frame_length[] = "length"; -constexpr char constexpr_frame_type[] = "type"; -constexpr char constexpr_frame_flags[] = "flags"; -constexpr char constexpr_frame_stream_identifier[] = "stream identifier"; -constexpr char constexpr_frame_pad_length[] = "pad length"; -constexpr char constexpr_frame_data[] = "data"; -constexpr char constexpr_frame_padding[] = "padding"; -constexpr char constexpr_frame_stream_dependency[] = "stream dependency"; -constexpr char constexpr_frame_weight[] = "weight"; -constexpr char constexpr_frame_fragment[] = "fragment"; -constexpr char constexpr_frame_priority[] = "priority"; -constexpr char constexpr_frame_error_code[] = "error code"; -constexpr char constexpr_frame_promised_stream_id[] = "promised stream id"; -constexpr char constexpr_frame_opaque[] = "opaque"; -constexpr char constexpr_frame_last_stream_id[] = "last stream id"; -constexpr char constexpr_frame_debug_data[] = "debug data"; -constexpr char constexpr_frame_window_size_increment[] = "window size increment"; - -constexpr char constexpr_frame_exclusive[] = "exclusive"; -constexpr char constexpr_frame_identifier[] = "identifier"; -constexpr char constexpr_frame_value[] = "value"; - -http2_frame_settings::http2_frame_settings() : http2_frame_header(h2_frame_t::h2_frame_settings) {} - -http2_frame_settings::http2_frame_settings(const http2_frame_settings& rhs) : http2_frame_header(rhs) { _settings = rhs._settings; } +http2_frame_settings::http2_frame_settings() : http2_frame(h2_frame_t::h2_frame_settings) {} + +http2_frame_settings::http2_frame_settings(const http2_frame_settings& rhs) : http2_frame(rhs) { _settings = rhs._settings; } http2_frame_settings& http2_frame_settings::add(uint16 id, uint32 value) { h2_setting_map_pib_t pib = _settings.insert(std::make_pair(id, value)); @@ -64,7 +42,7 @@ return_t http2_frame_settings::read(http2_frame_header_t const* header, size_t s __leave2; } - ret = http2_frame_header::read(header, size); + ret = http2_frame::read(header, size); if (errorcode_t::success != ret) { __leave2; } @@ -105,7 +83,7 @@ return_t http2_frame_settings::write(binary_t& frame) { ret = set_payload_size(len); if (errorcode_t::success == ret) { - http2_frame_header::write(frame); + http2_frame::write(frame); // RFC 7540 Figure 10: Setting Format h2_setting_map_t::iterator iter; @@ -120,11 +98,11 @@ return_t http2_frame_settings::write(binary_t& frame) { void http2_frame_settings::dump(stream_t* s) { if (s) { - http2_frame_header::dump(s); + http2_frame::dump(s); h2_setting_map_t::iterator iter; for (iter = _settings.begin(); iter != _settings.end(); iter++) { - s->printf("> "); + s->printf(" > "); s->printf("%s %u ", constexpr_frame_identifier, iter->first); s->printf("%s %u (0x%08x) ", constexpr_frame_value, iter->second, iter->second); s->printf("\n"); diff --git a/sdk/net/http/http2/http2_frame_window_update.cpp b/sdk/net/http/http2/http2_frame_window_update.cpp index 9c667f1d..3b1e9240 100644 --- a/sdk/net/http/http2/http2_frame_window_update.cpp +++ b/sdk/net/http/http2/http2_frame_window_update.cpp @@ -22,31 +22,9 @@ namespace hotplace { using namespace io; namespace net { -constexpr char constexpr_frame_length[] = "length"; -constexpr char constexpr_frame_type[] = "type"; -constexpr char constexpr_frame_flags[] = "flags"; -constexpr char constexpr_frame_stream_identifier[] = "stream identifier"; -constexpr char constexpr_frame_pad_length[] = "pad length"; -constexpr char constexpr_frame_data[] = "data"; -constexpr char constexpr_frame_padding[] = "padding"; -constexpr char constexpr_frame_stream_dependency[] = "stream dependency"; -constexpr char constexpr_frame_weight[] = "weight"; -constexpr char constexpr_frame_fragment[] = "fragment"; -constexpr char constexpr_frame_priority[] = "priority"; -constexpr char constexpr_frame_error_code[] = "error code"; -constexpr char constexpr_frame_promised_stream_id[] = "promised stream id"; -constexpr char constexpr_frame_opaque[] = "opaque"; -constexpr char constexpr_frame_last_stream_id[] = "last stream id"; -constexpr char constexpr_frame_debug_data[] = "debug data"; -constexpr char constexpr_frame_window_size_increment[] = "window size increment"; - -constexpr char constexpr_frame_exclusive[] = "exclusive"; -constexpr char constexpr_frame_identifier[] = "identifier"; -constexpr char constexpr_frame_value[] = "value"; - -http2_frame_window_update::http2_frame_window_update() : http2_frame_header(h2_frame_t::h2_frame_window_update), _increment(0) {} - -http2_frame_window_update::http2_frame_window_update(const http2_frame_window_update& rhs) : http2_frame_header(rhs), _increment(rhs._increment) {} +http2_frame_window_update::http2_frame_window_update() : http2_frame(h2_frame_t::h2_frame_window_update), _increment(0) {} + +http2_frame_window_update::http2_frame_window_update(const http2_frame_window_update& rhs) : http2_frame(rhs), _increment(rhs._increment) {} return_t http2_frame_window_update::read(http2_frame_header_t const* header, size_t size) { return_t ret = errorcode_t::success; @@ -58,7 +36,7 @@ return_t http2_frame_window_update::read(http2_frame_header_t const* header, siz } // check size and then read header - ret = http2_frame_header::read(header, size); + ret = http2_frame::read(header, size); if (errorcode_t::success != ret) { __leave2; } @@ -74,7 +52,7 @@ return_t http2_frame_window_update::read(http2_frame_header_t const* header, siz pl.read(ptr_payload, get_payload_size()); - _increment = t_variant_to_int(pl.select(constexpr_frame_window_size_increment)->get_variant().content()); + _increment = t_to_int(pl.select(constexpr_frame_window_size_increment)); } __finally2 { // do nothing @@ -93,7 +71,7 @@ return_t http2_frame_window_update::write(binary_t& frame) { set_payload_size(bin_payload.size()); - http2_frame_header::write(frame); + http2_frame::write(frame); frame.insert(frame.end(), bin_payload.begin(), bin_payload.end()); return ret; @@ -101,9 +79,9 @@ return_t http2_frame_window_update::write(binary_t& frame) { void http2_frame_window_update::dump(stream_t* s) { if (s) { - http2_frame_header::dump(s); + http2_frame::dump(s); - s->printf("> %s %u\n", constexpr_frame_window_size_increment, _increment); + s->printf(" > %s %u\n", constexpr_frame_window_size_increment, _increment); } } diff --git a/sdk/net/http/http2/http2_protocol.cpp b/sdk/net/http/http2/http2_protocol.cpp index 16fa1f9a..621ccc55 100644 --- a/sdk/net/http/http2/http2_protocol.cpp +++ b/sdk/net/http/http2/http2_protocol.cpp @@ -103,11 +103,13 @@ return_t http2_protocol::read_stream(basic_stream* stream, size_t* request_size, if (0 == strncmp(preface, (char*)stream_data, sampling_size)) { if ((stream_size >= sizeof_preface) && (0 == strncmp(preface, (char*)stream_data, sizeof_preface))) { + // connection preface http2_frame_header_t* frame = (http2_frame_header_t*)(stream_data + sizeof_preface); if (stream_size >= sizeof_preface + RTL_FIELD_SIZE(http2_frame_header_t, len)) { if (h2_frame_t::h2_frame_settings == frame->type) { pos = sizeof_preface; } else { + // This sequence MUST be followed by a SETTINGS frame (Section 6.5), which MAY be empty. *state = protocol_state_t::protocol_state_crash; __leave2; } @@ -149,7 +151,7 @@ return_t http2_protocol::read_stream(basic_stream* stream, size_t* request_size, return ret; } -uint32 http2_protocol::protocol_id() { return protocol_id_t::proto_http2; } +const char* http2_protocol::protocol_id() { return "h2"; } } // namespace net } // namespace hotplace diff --git a/sdk/net/http/http2/http2_protocol.hpp b/sdk/net/http/http2/http2_protocol.hpp index 28332ca8..4bd1180d 100644 --- a/sdk/net/http/http2/http2_protocol.hpp +++ b/sdk/net/http/http2/http2_protocol.hpp @@ -47,9 +47,8 @@ class http2_protocol : public network_protocol { virtual return_t read_stream(basic_stream* stream, size_t* request_size, protocol_state_t* state, int* priority = nullptr); /** * @brief id - * @remarks default port number */ - virtual uint32 protocol_id(); + virtual const char* protocol_id(); }; } // namespace net diff --git a/sdk/net/http/http2/http2_session.cpp b/sdk/net/http/http2/http2_session.cpp new file mode 100644 index 00000000..965f56d4 --- /dev/null +++ b/sdk/net/http/http2/http2_session.cpp @@ -0,0 +1,227 @@ +/* vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab smarttab : */ +/** + * @file {file} + * @author Soo Han, Kim (princeb612.kr@gmail.com) + * @desc + * + * Revision History + * Date Name Description + * + * + * TODO + * priority + */ + +#include +#include +#include +#include +#include +#include + +namespace hotplace { +namespace net { + +http2_session::http2_session() {} + +http2_session& http2_session::consume(uint32 type, uint32 data_count, void* data_array[], http_server* server, http_request** request) { + return_t ret = errorcode_t::success; + http_request* req = nullptr; + + __try2 { + if (nullptr == data_array || nullptr == server || nullptr == request) { + ret = errorcode_t::invalid_parameter; + __leave2; + } + + if (_df) { + net_session_socket_t* session_socket = (net_session_socket_t*)data_array[0]; + basic_stream bs; + + switch (type) { + case mux_connect: + bs.printf("connect %i\n", session_socket->cli_socket); + break; + case mux_read: { + bs.printf("read %i\n", session_socket->cli_socket); + byte_t* buf = (byte_t*)data_array[1]; + size_t bufsize = (size_t)data_array[2]; + dump_memory((byte_t*)buf, bufsize, &bs, 16, 2, 0, dump_memory_flag_t::dump_notrunc); + bs.printf("\n"); + } break; + case mux_disconnect: + bs.printf("disconnect %i\n", session_socket->cli_socket); + break; + default: + break; + } + _df(&bs); + } + + net_session_socket_t* session_socket = (net_session_socket_t*)data_array[0]; + byte_t* buf = (byte_t*)data_array[1]; + size_t bufsize = (size_t)data_array[2]; + basic_stream bs; + + network_session* session = (network_session*)data_array[3]; + hpack_encoder* encoder = &server->get_hpack_encoder(); + + constexpr char preface[] = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"; + const uint16 sizeof_preface = 24; + bool stage_preface = false; + uint32 pos_frame = 0; + if (bufsize > sizeof_preface) { + if (0 == strncmp((char*)buf, preface, sizeof_preface)) { + stage_preface = true; + pos_frame = sizeof_preface; + } + } + + http2_frame_header_t* hdr = (http2_frame_header_t*)(buf + pos_frame); + size_t frame_size = bufsize - pos_frame; + uint32_24_t i32_24((byte_t*)hdr, frame_size); + uint32 payload_size = i32_24.get(); + uint32 packet_size = sizeof(http2_frame_header_t) + payload_size; + uint8 flags = hdr->flags; + uint32 stream_id = ntoh32(hdr->stream_id); + uint32 mask = (h2_flag_end_stream | h2_flag_end_headers); + + uint8 f = 0; + flags_pib_t flags_pib = _flags.insert(std::make_pair(stream_id, flags)); + if (false == flags_pib.second) { + flags_pib.first->second |= flags; + flags = flags_pib.first->second; + } + headers_t ::iterator iter = _headers.find(stream_id); + if (_headers.end() != iter) { + req = &iter->second; + } else { + req = &_headers[stream_id]; // insert + req->set_stream_id(stream_id); + } + bool completion = (mask == (mask & flags)) ? true : false; + + if (h2_frame_t::h2_frame_data == hdr->type) { + http2_frame_data frame; + frame.read(hdr, frame_size); + if (_df) { + frame.dump(&bs); + _df(&bs); + } + + req->add_content(frame.get_data()); + } else if (h2_frame_t::h2_frame_headers == hdr->type) { + http2_frame_headers frame; + frame.read(hdr, frame_size); + if (_df) { + frame.dump(&bs); + _df(&bs); + } + + frame.set_hpack_encoder(encoder).set_hpack_session(&get_hpack_session()); + frame.read_compressed_header(frame.get_fragment(), + [&](const std::string& name, const std::string& value) -> void { req->get_http_header().add(name, value); }); + + } else if (h2_frame_t::h2_frame_priority == hdr->type) { + http2_frame_priority frame; + frame.read(hdr, frame_size); + if (_df) { + frame.dump(&bs); + _df(&bs); + } + } else if (h2_frame_t::h2_frame_rst_stream == hdr->type) { + http2_frame_rst_stream frame; + frame.read(hdr, frame_size); + if (_df) { + frame.dump(&bs); + _df(&bs); + } + } else if (h2_frame_t::h2_frame_settings == hdr->type) { + http2_frame_settings frame; + frame.read(hdr, frame_size); + if (_df) { + frame.dump(&bs); + _df(&bs); + } + + binary_t bin_resp; + http2_frame_settings resp_settings; + + if (frame.get_flags()) { + resp_settings.set_flags(h2_flag_ack); + } else { + resp_settings.add(h2_settings_enable_push, 0).add(h2_settings_max_concurrent_streams, 100).add(h2_settings_initial_window_size, 0xa00000); + } + + resp_settings.write(bin_resp); + + session->send((char*)&bin_resp[0], bin_resp.size()); + + } else if (h2_frame_t::h2_frame_push_promise == hdr->type) { + http2_frame_push_promise frame; + frame.read(hdr, frame_size); + if (_df) { + frame.dump(&bs); + _df(&bs); + } + } else if (h2_frame_t::h2_frame_ping == hdr->type) { + http2_frame_ping frame; + frame.read(hdr, frame_size); + if (_df) { + frame.dump(&bs); + _df(&bs); + } + } else if (h2_frame_t::h2_frame_goaway == hdr->type) { + http2_frame_goaway frame; + frame.read(hdr, frame_size); + if (_df) { + frame.dump(&bs); + _df(&bs); + } + } else if (h2_frame_t::h2_frame_window_update == hdr->type) { + http2_frame_window_update frame; + frame.read(hdr, frame_size); + if (_df) { + frame.dump(&bs); + _df(&bs); + } + } else if (h2_frame_t::h2_frame_continuation == hdr->type) { + http2_frame_continuation frame; + frame.read(hdr, frame_size); + if (_df) { + frame.dump(&bs); + _df(&bs); + } + + frame.set_hpack_encoder(encoder).set_hpack_session(&get_hpack_session()); + frame.read_compressed_header(frame.get_fragment(), + [&](const std::string& name, const std::string& value) -> void { req->get_http_header().add(name, value); }); + } + + if (completion) { + http_request* r = new http_request(*req); + r->set_version(2); + // get_http_header().get(":method") + // get_http_header().get(":path") + r->get_http_uri().open(r->get_http_header().get(":path")); + *request = r; + + _flags.erase(stream_id); + _headers.erase(stream_id); + } + } + __finally2 { + // do nothing + } + return *this; +} + +hpack_session& http2_session::get_hpack_session() { return _hpack_session; } + +http2_session& http2_session::set_debug(std::function f) { + _df = f; + return *this; +} + +} // namespace net +} // namespace hotplace diff --git a/sdk/net/http/http2/http2_session.hpp b/sdk/net/http/http2/http2_session.hpp new file mode 100644 index 00000000..647ce4a8 --- /dev/null +++ b/sdk/net/http/http2/http2_session.hpp @@ -0,0 +1,53 @@ +/* vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab smarttab : */ +/** + * @file {file} + * @author Soo Han, Kim (princeb612.kr@gmail.com) + * @desc + * + * Revision History + * Date Name Description + */ + +#ifndef __HOTPLACE_SDK_NET_HTTP_HTTP2_SESSION__ +#define __HOTPLACE_SDK_NET_HTTP_HTTP2_SESSION__ + +#include +#include +#include + +namespace hotplace { +namespace net { + +class http_server; +class http2_session { + public: + http2_session(); + + /** + * @brief consume + */ + http2_session& consume(uint32 type, uint32 data_count, void* data_array[], http_server* server, http_request** request); + + hpack_session& get_hpack_session(); + + http2_session& set_debug(std::function f); + + protected: + private: + critical_section _lock; + typedef std::map flags_t; + typedef std::map headers_t; + typedef std::pair flags_pib_t; + typedef std::pair headers_pib_t; + flags_t _flags; + headers_t _headers; // map + hpack_session _hpack_session; + + // debug + std::function _df; +}; + +} // namespace net +} // namespace hotplace + +#endif diff --git a/sdk/net/http/http_protocol.cpp b/sdk/net/http/http_protocol.cpp index 28670462..7bfd699b 100644 --- a/sdk/net/http/http_protocol.cpp +++ b/sdk/net/http/http_protocol.cpp @@ -120,7 +120,7 @@ return_t http_protocol::read_stream(basic_stream* stream, size_t* request_size, return errorcode_t::success; } -uint32 http_protocol::protocol_id() { return protocol_id_t::proto_http; } +const char* http_protocol::protocol_id() { return "http"; } } // namespace net } // namespace hotplace diff --git a/sdk/net/http/http_protocol.hpp b/sdk/net/http/http_protocol.hpp index 15add0f8..e37b39f0 100644 --- a/sdk/net/http/http_protocol.hpp +++ b/sdk/net/http/http_protocol.hpp @@ -45,9 +45,8 @@ class http_protocol : public network_protocol { virtual return_t read_stream(basic_stream* stream, size_t* request_size, protocol_state_t* state, int* priority = nullptr); /** * @brief id - * @remarks default port number */ - virtual uint32 protocol_id(); + virtual const char* protocol_id(); }; } // namespace net diff --git a/sdk/net/http/http_request.cpp b/sdk/net/http/http_request.cpp index 9c7c2eb4..0c8ccdc1 100644 --- a/sdk/net/http/http_request.cpp +++ b/sdk/net/http/http_request.cpp @@ -17,10 +17,12 @@ namespace hotplace { using namespace io; namespace net { -http_request::http_request() { _shared.make_share(this); } +http_request::http_request() : _version(1), _stream_id(0) { _shared.make_share(this); } http_request::http_request(const http_request& object) { _shared.make_share(this); + _version = object._version; + _stream_id = object._stream_id; _method = object._method; _content = object._content; _header = object._header; @@ -34,6 +36,11 @@ return_t http_request::open(const char* request, size_t size_request, uint32 fla return_t ret_getline = errorcode_t::success; __try2 { + if (1 != _version) { + ret = errorcode_t::not_supported; + __leave2; + } + if (nullptr == request) { ret = errorcode_t::invalid_parameter; __leave2; @@ -159,36 +166,98 @@ http_header& http_request::get_http_header() { return _header; } http_uri& http_request::get_http_uri() { return _uri; } -const char* http_request::get_method() { return _method.c_str(); } +const char* http_request::get_method() { + const char* m = nullptr; + if (1 == _version) { + m = _method.c_str(); + } else if (2 == _version) { + m = get_http_header().get(":method").c_str(); // HTTP/2 + } + return m; +} http_request& http_request::compose(http_method_t method, const std::string& uri, const std::string& body) { - http_resource* resource = http_resource::get_instance(); - basic_stream stream; + if (1 == _version) { + http_resource* resource = http_resource::get_instance(); + basic_stream stream; - stream << resource->get_method(method) << " " << uri << " " << get_version() << "\r\n"; - if (body.size()) { - stream << "Content-Length: " << body.size() << "\r\n"; - } - stream << "\r\n" << body; - - open(stream, http_request_flag_t::http_request_compose); // reform if body is empty + stream << resource->get_method(method) << " " << uri << " " << get_version() << "\r\n"; + if (body.size()) { + stream << "Content-Length: " << body.size() << "\r\n"; + } + stream << "\r\n" << body; + open(stream, http_request_flag_t::http_request_compose); // reform if body is empty + } else { + // TODO + } return *this; } std::string http_request::get_content() { return _content; } http_request& http_request::get_request(basic_stream& bs) { - std::string headers; - bs.clear(); - get_http_header().add("Content-Length", format("%zi", _content.size())).add("Connection", "Keep-Alive").get_headers(headers); + if (1 == _version) { + std::string headers; + bs.clear(); + get_http_header().add("Content-Length", format("%zi", _content.size())).add("Connection", "Keep-Alive").get_headers(headers); + + bs << get_method() << " " << get_http_uri().get_uri() << " " << get_version() << "\r\n" << headers << "\r\n" << get_content(); + } + return *this; +} + +std::string http_request::get_version_str() { + constexpr char ver1[] = "HTTP/1.1"; + constexpr char ver2[] = "HTTP/2"; + + return (1 == _version) ? ver1 : ver2; +} + +http_request& http_request::operator=(const http_request& rhs) { + _method = rhs._method; + _content = rhs._content; - bs << get_method() << " " << get_http_uri().get_uri() << " " << get_version() << "\r\n" << headers << "\r\n" << get_content(); + _header = rhs._header; + _uri = rhs._uri; return *this; } -std::string http_request::get_version() { return "HTTP/1.1"; } +http_request& http_request::add_content(const char* buf, size_t bufsize) { + for (size_t i = 0; buf && (i < bufsize); i++) { + _content += buf[i]; + } + return *this; +} + +http_request& http_request::add_content(const binary_t& bin) { return add_content((char*)&bin[0], bin.size()); } + +http_request& http_request::clear_content() { + _content.clear(); + return *this; +} + +http_request& http_request::set_version(uint8 version) { + switch (version) { + case 2: + case 1: + _version = version; + break; + default: + break; + } + return *this; +} + +http_request& http_request::set_stream_id(uint32 stream_id) { + _stream_id = stream_id; + return *this; +} + +uint8 http_request::get_version() { return _version; } + +uint32 http_request::get_stream_id() { return _stream_id; } void http_request::addref() { _shared.addref(); } diff --git a/sdk/net/http/http_request.hpp b/sdk/net/http/http_request.hpp index c360e0d9..0e59cb0b 100644 --- a/sdk/net/http/http_request.hpp +++ b/sdk/net/http/http_request.hpp @@ -91,7 +91,22 @@ class http_request { */ http_request& get_request(basic_stream& stream); - virtual std::string get_version(); + virtual std::string get_version_str(); + + http_request& operator=(const http_request& rhs); + + http_request& add_content(const char* buf, size_t bufsize); + http_request& add_content(const binary_t& bin); + http_request& clear_content(); + + /* + * @brief version + * @param uint8 version [in] 1 HTTP/1.1, 2 HTTP/2 + */ + http_request& set_version(uint8 version); + http_request& set_stream_id(uint32 stream_id); + uint8 get_version(); + uint32 get_stream_id(); void addref(); void release(); @@ -100,6 +115,8 @@ class http_request { t_shared_reference _shared; private: + uint8 _version; + uint32 _stream_id; std::string _method; std::string _content; diff --git a/sdk/net/http/http_response.hpp b/sdk/net/http/http_response.hpp index f9e3411f..fcd1fa75 100644 --- a/sdk/net/http/http_response.hpp +++ b/sdk/net/http/http_response.hpp @@ -50,7 +50,7 @@ class http_response { return_t open(const std::string& response); /* * * @brief close - * @return error code (see error.hpp) + * @return error code (see error.hpp) */ return_t close(); diff --git a/sdk/net/http/http_server.cpp b/sdk/net/http/http_server.cpp index de2a07a3..09a4d976 100644 --- a/sdk/net/http/http_server.cpp +++ b/sdk/net/http/http_server.cpp @@ -96,7 +96,7 @@ return_t http_server::shutdown_tls() { return ret; } -return_t http_server::startup_server(uint16 tls, uint16 family, uint16 port, http_server_handler_t handler) { +return_t http_server::startup_server(uint16 tls, uint16 family, uint16 port, http_server_handler_t handler, void* user_context) { return_t ret = errorcode_t::success; network_multiplexer_context_t* handle = nullptr; tcp_server_socket* socket = nullptr; @@ -106,6 +106,8 @@ return_t http_server::startup_server(uint16 tls, uint16 family, uint16 port, htt ret = errorcode_t::invalid_parameter; __leave2; } + _consumer = handler; + _user_context = user_context; if (tls) { socket = _tls_server_socket; @@ -113,7 +115,8 @@ return_t http_server::startup_server(uint16 tls, uint16 family, uint16 port, htt socket = &_server_socket; } - ret = get_network_server().open(&handle, family, IPPROTO_TCP, port, 1024, handler, this, socket); + uint16 epoll_concurrent_event = get_server_conf().get(netserver_config_t::serverconf_concurrent_event); // 1024 + ret = get_network_server().open(&handle, family, IPPROTO_TCP, port, epoll_concurrent_event, &consume_routine, this, socket); if (errorcode_t::success != ret) { __leave2; } @@ -147,6 +150,74 @@ void http_server::shutdown() { shutdown_tls(); } +return_t http_server::consume_routine(uint32 type, uint32 data_count, void* data_array[], CALLBACK_CONTROL* callback_control, void* server_context) { + http_server* server = (http_server*)server_context; + return server->consume(type, data_count, data_array, callback_control, server->_user_context); +} + +return_t http_server::consume(uint32 type, uint32 data_count, void* data_array[], CALLBACK_CONTROL* callback_control, void* user_context) { + return_t ret = errorcode_t::success; + http_request request; + http_request* h2request = nullptr; + + void* dispatch_data[5] = {data_array[0], data_array[1], data_array[2], data_array[3], nullptr}; + char* buf = (char*)data_array[1]; + size_t bufsize = (size_t)data_array[2]; + +#if 0 + if (_df) { + net_session_socket_t* session_socket = (net_session_socket_t*)data_array[0]; + basic_stream bs; + + switch (type) { + case mux_connect: + bs.printf("connect %i\n", session_socket->cli_socket); + break; + case mux_read: { + bs.printf("read %i\n", session_socket->cli_socket); + byte_t* buf = (byte_t*)data_array[1]; + size_t bufsize = (size_t)data_array[2]; + dump_memory((byte_t*)buf, bufsize, &bs, 16, 2, 0, dump_memory_flag_t::dump_notrunc); + bs.printf("\n"); + } break; + case mux_disconnect: + bs.printf("disconnect %i\n", session_socket->cli_socket); + break; + default: + break; + } + _df(&bs); + } +#endif + + if (errorcode_t::success == get_http_protocol().is_kind_of(buf, bufsize)) { // HTTP/1.1 + request.open(buf, bufsize); + dispatch_data[4] = &request; + } else if (get_server_conf().get(netserver_config_t::serverconf_enable_h2)) { + network_session* session = (network_session*)data_array[3]; + if (session) { + if (get_server_conf().get(netserver_config_t::serverconf_debug_h2)) { + session->get_http2_session().set_debug(_df); + } + session->get_http2_session().consume(type, data_count, data_array, this, &h2request); + } + dispatch_data[4] = h2request; + } + + ret = _consumer(type, RTL_NUMBER_OF(dispatch_data), dispatch_data, callback_control, user_context); + + if (h2request) { + h2request->release(); + } + + return ret; +} + +http_server& http_server::set_debug(std::function f) { + _df = f; + return *this; +} + network_server& http_server::get_network_server() { return _server; } http_protocol& http_server::get_http_protocol() { return _protocol; } diff --git a/sdk/net/http/http_server.hpp b/sdk/net/http/http_server.hpp index 49e64d83..618d276b 100644 --- a/sdk/net/http/http_server.hpp +++ b/sdk/net/http/http_server.hpp @@ -55,6 +55,8 @@ class http_server { ipaddr_acl& get_ipaddr_acl(); server_conf& get_server_conf(); + http_server& set_debug(std::function f); + protected: http_server(); @@ -62,11 +64,27 @@ class http_server { return_t startup_tls(const std::string& server_cert, const std::string& server_key, const std::string& cipher_list, int verify_peer); return_t shutdown_tls(); - return_t startup_server(uint16 tls, uint16 family, uint16 port, http_server_handler_t handler); + return_t startup_server(uint16 tls, uint16 family, uint16 port, http_server_handler_t handler, void* user_context = nullptr); return_t shutdown_server(); void shutdown(); + /** + * @brief server handler + * @param uint32 type [in] multiplexer_event_type_t + * @param uint32 data_count [in] 5 + * @param void* data_array[] [in] + * data_array[0] net_session_socket_t* + * data_array[1] transfered buffer + * data_array[2] transfered size + * data_array[3] network_session* + * data_array[4] http_server* + * @param CALLBACK_CONTROL* callback_control [in] nullptr + * @param void* server_context [in] http_server* + */ + static return_t consume_routine(uint32 type, uint32 data_count, void* data_array[], CALLBACK_CONTROL* callback_control, void* server_context); + return_t consume(uint32 type, uint32 data_count, void* data_array[], CALLBACK_CONTROL* callback_control, void* user_context); + private: network_server _server; @@ -88,10 +106,17 @@ class http_server { http2_protocol _protocol2; hpack_encoder _hpack_encoder; + // consume handler + http_server_handler_t _consumer; + void* _user_context; + // route http_router _router; typedef std::list http_handles_t; http_handles_t _http_handles; + + // debug + std::function _df; }; } // namespace net diff --git a/sdk/net/http/http_server_builder.cpp b/sdk/net/http/http_server_builder.cpp index af46bc16..71cea38c 100644 --- a/sdk/net/http/http_server_builder.cpp +++ b/sdk/net/http/http_server_builder.cpp @@ -16,7 +16,7 @@ namespace hotplace { using namespace io; namespace net { -http_server_builder::http_server_builder() : _handler(nullptr) { +http_server_builder::http_server_builder() : _handler(nullptr), _user_context(nullptr) { get_server_conf() .set(netserver_config_t::serverconf_enable_ipv4, 0) .set(netserver_config_t::serverconf_enable_ipv6, 0) @@ -84,8 +84,9 @@ http_server_builder& http_server_builder::enable_h2(bool enable) { return *this; } -http_server_builder& http_server_builder::set_handler(http_server_handler_t handler) { +http_server_builder& http_server_builder::set_handler(http_server_handler_t handler, void* user_context) { _handler = handler; + _user_context = user_context; return *this; } diff --git a/sdk/net/http/http_server_builder.hpp b/sdk/net/http/http_server_builder.hpp index 5bb2f425..74646228 100644 --- a/sdk/net/http/http_server_builder.hpp +++ b/sdk/net/http/http_server_builder.hpp @@ -61,7 +61,7 @@ class http_server_builder { http_server_builder& enable_h2(bool enable); - http_server_builder& set_handler(http_server_handler_t handler); + http_server_builder& set_handler(http_server_handler_t handler, void* user_context = nullptr); http_server* build(); server_conf& get_server_conf(); @@ -75,6 +75,7 @@ class http_server_builder { server_conf _config; http_server_handler_t _handler; + void* _user_context; }; } // namespace net diff --git a/sdk/net/http/http_uri.cpp b/sdk/net/http/http_uri.cpp index fa73abbc..b0eef146 100644 --- a/sdk/net/http/http_uri.cpp +++ b/sdk/net/http/http_uri.cpp @@ -153,6 +153,14 @@ return_t http_uri::to_keyvalue(const std::string& value, key_value& kv) { key_value& http_uri::get_query_keyvalue() { return _query_kv; } +http_uri& http_uri::operator=(const http_uri& rhs) { + _uri = rhs._uri; + _uripath = rhs._uripath; + _query = rhs._query; + _query_kv = rhs._query_kv; + return *this; +} + void http_uri::addref() { _shared.addref(); } void http_uri::release() { _shared.delref(); } diff --git a/sdk/net/http/http_uri.hpp b/sdk/net/http/http_uri.hpp index 3c5653c4..0dda7cf1 100644 --- a/sdk/net/http/http_uri.hpp +++ b/sdk/net/http/http_uri.hpp @@ -91,6 +91,8 @@ class http_uri { */ key_value& get_query_keyvalue(); + http_uri& operator=(const http_uri& rhs); + void addref(); void release(); diff --git a/sdk/net/server/network_protocol.cpp b/sdk/net/server/network_protocol.cpp index 8227b7b8..c0154056 100644 --- a/sdk/net/server/network_protocol.cpp +++ b/sdk/net/server/network_protocol.cpp @@ -45,7 +45,7 @@ network_protocol_group& network_protocol_group::operator<<(network_protocol* pro return *this; } -return_t network_protocol_group::find(uint32 protocol_id, network_protocol** ptr_protocol) { +return_t network_protocol_group::find(const std::string& protocol_id, network_protocol** ptr_protocol) { return_t ret = errorcode_t::success; __try2 { @@ -71,7 +71,7 @@ return_t network_protocol_group::find(uint32 protocol_id, network_protocol** ptr return ret; } -network_protocol* network_protocol_group::operator[](uint32 protocol_id) { +network_protocol* network_protocol_group::operator[](const std::string& protocol_id) { network_protocol* protocol = nullptr; find(protocol_id, &protocol); diff --git a/sdk/net/server/network_protocol.hpp b/sdk/net/server/network_protocol.hpp index b168aaa9..6559a029 100644 --- a/sdk/net/server/network_protocol.hpp +++ b/sdk/net/server/network_protocol.hpp @@ -34,11 +34,6 @@ enum protocol_constraints_t { protocol_constraints_the_end, }; -enum protocol_id_t { - proto_http = 2068, // RFC 2068, 2616 - proto_http2 = 7540, // RFC 7540, 9113 -}; - /** * @brief protocol interpreter */ @@ -91,9 +86,8 @@ class network_protocol { /** * @brief id - * @remarks default port number */ - virtual uint32 protocol_id() = 0; + virtual const char* protocol_id() = 0; int addref() { return _shared.addref(); } int release() { return _shared.delref(); } @@ -109,45 +103,45 @@ class network_protocol_group { virtual ~network_protocol_group(); /** - * @brief add protocol + * @brief add protocol * @param network_protocol* protocol [IN] add protocol and increase reference counter - * @return error code (see error.hpp) + * @return error code (see error.hpp) */ virtual return_t add(network_protocol* protocol); /** - * @brief operator << + * @brief operator << * @param network_protocol* protocol [IN] * @remarks * add method replacement wo checking return code */ virtual network_protocol_group& operator<<(network_protocol* protocol); /** - * @brief find - * @param uint32 protocol_id [IN] + * @brief find + * @param const std::string& protocol_id [IN] * @param network_protocol** ptr_protocol [OUT] referenced, call release - * @return error code (see error.hpp) + * @return error code (see error.hpp) */ - virtual return_t find(uint32 protocol_id, network_protocol** ptr_protocol); + virtual return_t find(const std::string& protocol_id, network_protocol** ptr_protocol); /** - * @brief operator[protocol_id] + * @brief operator[protocol_id] * @example - * network_protocol* protocol = protocol_group[80]; + * network_protocol* protocol = protocol_group["http"]; * if (nullptr != protocol) * { * //... * prtotocol->release (); // decrease reference counter * } */ - virtual network_protocol* operator[](uint32 protocol_id); + virtual network_protocol* operator[](const std::string& protocol_id); /** - * @brief remove protocol - * @param network_protocol* protocol [IN] remove protocol and decrease reference counter - * @return error code (see error.hpp) + * @brief remove protocol + * @param network_protocol* protocol [IN] remove protocol and decrease reference counter + * @return error code (see error.hpp) */ virtual return_t remove(network_protocol* protocol); /** - * @brief remove all protocol - * @return error code (see error.hpp) + * @brief remove all protocols + * @return error code (see error.hpp) */ virtual return_t clear(); /** @@ -156,29 +150,29 @@ class network_protocol_group { virtual bool empty(); /** - * @brief find appropriate protocol - * @param void* stream [IN] - * @param size_t stream_size [IN] - * @param network_protocol** ptr_protocol [OUT] referenced, use release to free (important) - * @return error code (see error.hpp) + * @brief find appropriate protocol + * @param void* stream [IN] + * @param size_t stream_size [IN] + * @param network_protocol** ptr_protocol [OUT] referenced, use release to free (important) + * @return error code (see error.hpp) * @remarks * if input stream is too short, return errorcode_t::more_data */ virtual return_t is_kind_of(void* stream, size_t stream_size, network_protocol** ptr_protocol); /** - * @brief increase reference counter + * @brief increase reference counter */ int addref(); /** - * @brief decrease reference counter. if reference counter 0, delete object. + * @brief decrease reference counter. if reference counter 0, delete object. */ int release(); protected: t_shared_reference _shared; - typedef std::map protocol_map_t; + typedef std::map protocol_map_t; typedef std::pair protocol_map_pib_t; critical_section _lock; diff --git a/sdk/net/server/network_server.cpp b/sdk/net/server/network_server.cpp index a3a72eef..7f931d26 100644 --- a/sdk/net/server/network_server.cpp +++ b/sdk/net/server/network_server.cpp @@ -961,10 +961,10 @@ return_t network_server::consumer_routine(network_multiplexer_context_t* handle) void* dispatch_data[4] = { nullptr, }; - dispatch_data[0] = session_object->socket_info(); /* netserver_callback_type_t::netserver_callback_type_socket */ - dispatch_data[1] = buffer_object->content(); /* netserver_callback_type_t::netserver_callback_type_dataptr */ - dispatch_data[2] = (void*)buffer_object->size(); /* netserver_callback_type_t::netserver_callback_type_datasize */ - dispatch_data[3] = session_object; /* netserver_callback_type_t::netserver_callback_type_session */ + dispatch_data[0] = session_object->socket_info(); /* netserver_cb_type_t::netserver_cb_socket */ + dispatch_data[1] = buffer_object->content(); /* netserver_cb_type_t::netserver_cb_dataptr */ + dispatch_data[2] = (void*)buffer_object->size(); /* netserver_cb_type_t::netserver_cb_datasize */ + dispatch_data[3] = session_object; /* netserver_cb_type_t::netserver_cb_session */ handle->callback_routine(multiplexer_event_type_t::mux_read, 4, dispatch_data, nullptr, handle->callback_param); @@ -975,10 +975,10 @@ return_t network_server::consumer_routine(network_multiplexer_context_t* handle) void* dispatch_data[4] = { nullptr, }; - dispatch_data[0] = session_object->socket_info(); /* netserver_callback_type_t::netserver_callback_type_socket */ - dispatch_data[1] = buffer_object->content(); /* netserver_callback_type_t::netserver_callback_type_dataptr */ - dispatch_data[2] = (void*)buffer_object->size(); /* netserver_callback_type_t::netserver_callback_type_datasize */ - dispatch_data[3] = session_object; /* netserver_callback_type_t::netserver_callback_type_session */ + dispatch_data[0] = session_object->socket_info(); /* netserver_cb_type_t::netserver_cb_socket */ + dispatch_data[1] = buffer_object->content(); /* netserver_cb_type_t::netserver_cb_dataptr */ + dispatch_data[2] = (void*)buffer_object->size(); /* netserver_cb_type_t::netserver_cb_datasize */ + dispatch_data[3] = session_object; /* netserver_cb_type_t::netserver_cb_session */ handle->callback_routine(multiplexer_event_type_t::mux_read, 4, dispatch_data, nullptr, handle->callback_param); diff --git a/sdk/net/server/network_server.hpp b/sdk/net/server/network_server.hpp index 978aa74e..ef95b7a8 100644 --- a/sdk/net/server/network_server.hpp +++ b/sdk/net/server/network_server.hpp @@ -41,6 +41,10 @@ enum netserver_config_t { serverconf_port_https = 12, serverconf_enable_h2 = 13, serverconf_enable_h3 = 14, + + serverconf_debug_ns = 1000, + serverconf_debug_h1 = 1001, + serverconf_debug_h2 = 1002, }; class server_conf { @@ -58,11 +62,12 @@ class server_conf { config_map_t _config_map; }; -enum netserver_callback_type_t { - netserver_callback_type_socket = 0, - netserver_callback_type_dataptr = 1, - netserver_callback_type_datasize = 2, - netserver_callback_type_session = 3, +enum netserver_cb_type_t { + netserver_cb_socket = 0, // net_session_socket_t* + netserver_cb_dataptr = 1, // char*, byte_t* + netserver_cb_datasize = 2, // size_t + netserver_cb_session = 3, // network_session* + netserver_cb_http_request = 4, // http_request* }; typedef return_t (*ACCEPT_CONTROL_CALLBACK_ROUTINE)(socket_t socket, sockaddr_storage_t* client_addr, CALLBACK_CONTROL* control, void* parameter); @@ -106,9 +111,9 @@ typedef struct _network_multiplexer_context_t network_multiplexer_context_t; * uint16 NetworkRoutine (uint32 type, uint32 data_count, void* data_array[], CALLBACK_CONTROL* callback_control, void* user_context) * { * uint32 ret = errorcode_t::success; - * net_session_socket_t* pSession = (net_session_socket_t*)data_array[netserver_callback_type_t::netserver_callback_type_socket]; // [0] - * char* buf = (char*)data_array[netserver_callback_type_t::netserver_callback_type_dataptr]; // [1] - * size_t bufsize = (size_t)data_array[netserver_callback_type_t::netserver_callback_type_datasize]; // [2] + * net_session_socket_t* pSession = (net_session_socket_t*)data_array[netserver_cb_type_t::netserver_cb_socket]; // [0] + * char* buf = (char*)data_array[netserver_cb_type_t::netserver_cb_dataptr]; // [1] + * size_t bufsize = (size_t)data_array[netserver_cb_type_t::netserver_cb_datasize]; // [2] * * switch(type) * { @@ -151,13 +156,13 @@ class network_server { * RTL_NUMBER_OF(third parameter) * parameter 3 * data_array[0] net_session_socket_t* - * equivalant data_array[netserver_callback_type_t::netserver_callback_type_socket] + * equivalant data_array[netserver_cb_type_t::netserver_cb_socket] * data_array[1] transfered buffer - * equivalant data_array[netserver_callback_type_t::netserver_callback_type_dataptr] + * equivalant data_array[netserver_cb_type_t::netserver_cb_dataptr] * data_array[2] transfered size - * equivalant data_array[netserver_callback_type_t::netserver_callback_type_datasize] + * equivalant data_array[netserver_cb_type_t::netserver_cb_datasize] * data_array[3] network_session* - * equivalant data_array[netserver_callback_type_t::netserver_callback_type_session] + * equivalant data_array[netserver_cb_type_t::netserver_cb_session] * parameter 4 * CALLBACK_CONTROL* is always null * parameter 5 @@ -179,7 +184,7 @@ class network_server { * see tls_accept_loop_run/tls_accept_loop_break */ return_t open(network_multiplexer_context_t** handle, unsigned int family, unsigned int type, uint16 port, uint32 concurent, - TYPE_CALLBACK_HANDLEREXV lpfnEventHandler, void* lpParameter, tcp_server_socket* svr_socket); + TYPE_CALLBACK_HANDLEREXV callback_routine, void* callback_param, tcp_server_socket* svr_socket); /** * @brief access control or handle tcp before tls upgrade diff --git a/sdk/net/server/network_session.cpp b/sdk/net/server/network_session.cpp index cc436521..a1cd5775 100644 --- a/sdk/net/server/network_session.cpp +++ b/sdk/net/server/network_session.cpp @@ -161,7 +161,7 @@ tcp_server_socket* network_session::get_server_socket() { return _session.svr_so network_session_data* network_session::get_session_data() { return &_session_data; } -hpack_session* network_session::get_hpack_session() { return &_hpack_session; } +http2_session& network_session::get_http2_session() { return _http2_session; } network_session_manager::network_session_manager() { // do nothing diff --git a/sdk/net/server/network_session.hpp b/sdk/net/server/network_session.hpp index 296be8d9..52147166 100644 --- a/sdk/net/server/network_session.hpp +++ b/sdk/net/server/network_session.hpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -99,7 +100,7 @@ class network_session { return_t connected(handle_t client_socket, sockaddr_storage_t* sockaddr, tls_context_t* tls_handle); /** * @brief in windows call wsarecv to read asynchronously - * @return error code (see error.hpp) + * @return error code (see error.hpp) */ return_t ready_to_read(); @@ -107,7 +108,7 @@ class network_session { * @brief send * @param const char* data_ptr [IN] * @param size_t size_data [IN] - * @return error code (see error.hpp) + * @return error code (see error.hpp) */ return_t send(const char* data_ptr, size_t size_data); @@ -162,14 +163,15 @@ class network_session { tcp_server_socket* get_server_socket(); network_session_data* get_session_data(); - hpack_session* get_hpack_session(); + http2_session& get_http2_session(); protected: net_session_t _session; network_stream _stream; network_stream _request; network_session_data _session_data; - hpack_session _hpack_session; + + http2_session _http2_session; t_shared_reference _shared; critical_section _lock; diff --git a/sdk/net/server/network_stream.cpp b/sdk/net/server/network_stream.cpp index 8ad59ee3..80578f52 100644 --- a/sdk/net/server/network_stream.cpp +++ b/sdk/net/server/network_stream.cpp @@ -108,6 +108,45 @@ return_t network_stream::read(network_protocol_group* protocol_group, network_st return ret; } +return_t network_stream::write(network_protocol_group* protocol_group, network_stream* target) { + return_t ret = errorcode_t::success; + + __try2 { + if (nullptr == target || nullptr == protocol_group) { + ret = errorcode_t::invalid_parameter; + __leave2; + } + + critical_section_guard guard(_lock); + + if (true == _queue.empty()) { + ret = errorcode_t::empty; + } else { + if (true == protocol_group->empty()) { + do_write(target); + } else { + /* + * after processing one request, check remains + * before do_write + * request packet 1 || request packet 2 || ... + * after do_write + * request packet 1 in target + * request packet 2 || ... remains + * to resolve + * check more_data + */ + while (errorcode_t::more_data == do_writep(protocol_group, target)) + ; + } + } + } + __finally2 { + // do nothing + } + + return ret; +} + return_t network_stream::do_write(network_stream* target) { return_t ret = errorcode_t::success; @@ -130,7 +169,7 @@ return_t network_stream::do_write(network_stream* target) { return ret; } -return_t network_stream::do_write(network_protocol_group* protocol_group, network_stream* target) { +return_t network_stream::do_writep(network_protocol_group* protocol_group, network_stream* target) { return_t ret = errorcode_t::success; return_t test = errorcode_t::success; network_stream_data* buffer_object = nullptr; @@ -138,9 +177,7 @@ return_t network_stream::do_write(network_protocol_group* protocol_group, networ basic_stream bufstream; protocol_state_t state = protocol_state_t::protocol_state_invalid; - size_t content_pos = 0; - size_t content_size = 0; - size_t request_size = 0; + size_t message_size = 0; size_t roll_count = 0; bool _run = true; int priority = 0; @@ -165,10 +202,10 @@ return_t network_stream::do_write(network_protocol_group* protocol_group, networ if (errorcode_t::more_data == test) { // do nothing } else if (errorcode_t::success == test) { - protocol->read_stream(&bufstream, &request_size, &state, &priority); + protocol->read_stream(&bufstream, &message_size, &state, &priority); switch (state) { case protocol_state_t::protocol_state_complete: - target->produce(bufstream.data(), request_size); + target->produce(bufstream.data(), message_size); _run = false; break; case protocol_state_t::protocol_state_forged: @@ -195,31 +232,36 @@ return_t network_stream::do_write(network_protocol_group* protocol_group, networ } } // for-loop - network_stream_list_t::iterator iter_netstream; switch (state) { - case protocol_state_t::protocol_state_complete: - for (iter_netstream = _queue.begin(); iter_netstream != _queue.end();) { - buffer_object = *iter_netstream; + case protocol_state_t::protocol_state_complete: { + size_t content_pos = 0; + size_t content_size = 0; + for (network_stream_list_t::iterator iter = _queue.begin(); iter != _queue.end();) { + buffer_object = *iter; content_pos = content_size; content_size += buffer_object->size(); - if (request_size >= content_size) { + if (message_size >= content_size) { buffer_object->release(); - _queue.erase(iter_netstream++); - } else if ((content_pos <= request_size) && (request_size < content_size)) { - size_t remain = content_size - request_size; - byte_t* ptr = bufstream.data() + request_size; + _queue.erase(iter++); + + if (message_size == content_size) { + break; + } + } else if ((content_pos <= message_size) && (message_size < content_size)) { + size_t remain = content_size - message_size; + byte_t* ptr = bufstream.data() + message_size; buffer_object->assign(ptr, remain); buffer_object->set_priority(priority); // set stream priority ret = errorcode_t::more_data; // while (more_data == do_write(...)); break; } } - break; + } break; case protocol_state_t::protocol_state_forged: case protocol_state_t::protocol_state_crash: case protocol_state_t::protocol_state_large: - for (network_stream_list_t::iterator iter_netstream = _queue.begin(); iter_netstream != _queue.end(); iter_netstream++) { - buffer_object = *iter_netstream; + for (network_stream_list_t::iterator iter = _queue.begin(); iter != _queue.end(); iter++) { + buffer_object = *iter; buffer_object->release(); } _queue.clear(); @@ -231,45 +273,6 @@ return_t network_stream::do_write(network_protocol_group* protocol_group, networ return ret; } -return_t network_stream::write(network_protocol_group* protocol_group, network_stream* target) { - return_t ret = errorcode_t::success; - - __try2 { - if (nullptr == target || nullptr == protocol_group) { - ret = errorcode_t::invalid_parameter; - __leave2; - } - - critical_section_guard guard(_lock); - - if (true == _queue.empty()) { - ret = errorcode_t::empty; - } else { - if (true == protocol_group->empty()) { - do_write(target); - } else { - /* - * after processing one request, check remains - * before do_write - * request packet 1 || request packet 2 || ... - * after do_write - * request packet 1 in target - * request packet 2 || ... remains - * to resolve - * check more_data - */ - while (errorcode_t::more_data == do_write(protocol_group, target)) - ; - } - } - } - __finally2 { - // do nothing - } - - return ret; -} - network_stream_data::network_stream_data() : _ptr(nullptr), _size(0), _next(nullptr), _priority(0) { _instance.make_share(this); } network_stream_data::~network_stream_data() { diff --git a/sdk/net/server/network_stream.hpp b/sdk/net/server/network_stream.hpp index fd89ebfd..6f06bf7a 100644 --- a/sdk/net/server/network_stream.hpp +++ b/sdk/net/server/network_stream.hpp @@ -127,7 +127,7 @@ class network_stream { * @param network_stream* target [OUT] * @return error code (see error.hpp) */ - return_t do_write(network_protocol_group* protocol, network_stream* target); + return_t do_writep(network_protocol_group* protocol, network_stream* target); typedef std::list network_stream_list_t; diff --git a/test/httpauth/sample.cpp b/test/httpauth/sample.cpp index eda8dec4..c5a713fd 100644 --- a/test/httpauth/sample.cpp +++ b/test/httpauth/sample.cpp @@ -59,9 +59,10 @@ void cprint(const char* text, ...) { return_t consume_routine(uint32 type, uint32 data_count, void* data_array[], CALLBACK_CONTROL* callback_control, void* user_context) { return_t ret = errorcode_t::success; net_session_socket_t* session_socket = (net_session_socket_t*)data_array[0]; - network_session* session = (network_session*)data_array[3]; char* buf = (char*)data_array[1]; size_t bufsize = (size_t)data_array[2]; + network_session* session = (network_session*)data_array[3]; + http_request* request = (http_request*)data_array[4]; basic_stream bs; std::string message; @@ -81,20 +82,18 @@ return_t consume_routine(uint32 type, uint32 data_count, void* data_array[], CAL { bool use_tls = session->get_server_socket()->support_tls(); - http_request request; - http_response response(&request); + http_response response(request); basic_stream bs; - request.open(buf, bufsize); if (use_tls) { // using http_router - _http_server->get_http_router().route(session, &request, &response); + _http_server->get_http_router().route(session, request, &response); } else { // handle wo http_router response.get_http_header().add("Upgrade", "TLS/1.2, HTTP/1.1").add("Connection", "Upgrade"); int status_code = 426; response.compose(status_code, "text/html", "%d %s
", option.port_tls, - request.get_http_uri().get_uri(), status_code, http_resource::get_instance()->load(status_code).c_str()); + request->get_http_uri().get_uri(), status_code, http_resource::get_instance()->load(status_code).c_str()); } if (option.verbose) { diff --git a/test/httpserver/sample.cpp b/test/httpserver/sample.cpp index a1e82a55..0270e2d9 100644 --- a/test/httpserver/sample.cpp +++ b/test/httpserver/sample.cpp @@ -59,9 +59,10 @@ void cprint(const char* text, ...) { return_t consume_routine(uint32 type, uint32 data_count, void* data_array[], CALLBACK_CONTROL* callback_control, void* user_context) { return_t ret = errorcode_t::success; net_session_socket_t* session_socket = (net_session_socket_t*)data_array[0]; - network_session* session = (network_session*)data_array[3]; char* buf = (char*)data_array[1]; size_t bufsize = (size_t)data_array[2]; + network_session* session = (network_session*)data_array[3]; + http_request* request = (http_request*)data_array[4]; basic_stream bs; std::string message; @@ -81,20 +82,18 @@ return_t consume_routine(uint32 type, uint32 data_count, void* data_array[], CAL { bool use_tls = session->get_server_socket()->support_tls(); - http_request request; - http_response response(&request); + http_response response(request); basic_stream bs; - request.open(buf, bufsize); if (use_tls) { // using http_router - _http_server->get_http_router().route(session, &request, &response); + _http_server->get_http_router().route(session, request, &response); } else { // handle wo http_router response.get_http_header().add("Upgrade", "TLS/1.2, HTTP/1.1").add("Connection", "Upgrade"); int status_code = 426; response.compose(status_code, "text/html", "%d %s
", option.port_tls, - request.get_http_uri().get_uri(), status_code, http_resource::get_instance()->load(status_code).c_str()); + request->get_http_uri().get_uri(), status_code, http_resource::get_instance()->load(status_code).c_str()); } if (option.verbose) { diff --git a/test/httpserver2/sample.cpp b/test/httpserver2/sample.cpp index da9be721..5cbc62fa 100644 --- a/test/httpserver2/sample.cpp +++ b/test/httpserver2/sample.cpp @@ -61,11 +61,10 @@ void print(const char* text, ...) { va_start(ap, text); vprintf(text, ap); va_end(ap); - printf("\n"); fflush(stdout); } -void dump_frame(http2_frame_header* base, http2_frame_header_t* hdr, size_t size, hpack_encoder* encoder = nullptr, hpack_session* session = nullptr) { +void dump_frame(http2_frame* base, http2_frame_header_t* hdr, size_t size, hpack_encoder* encoder = nullptr, hpack_session* session = nullptr) { basic_stream bs; base->read(hdr, size); base->dump(&bs); @@ -76,9 +75,10 @@ void dump_frame(http2_frame_header* base, http2_frame_header_t* hdr, size_t size return_t consume_routine(uint32 type, uint32 data_count, void* data_array[], CALLBACK_CONTROL* callback_control, void* user_context) { return_t ret = errorcode_t::success; net_session_socket_t* session_socket = (net_session_socket_t*)data_array[0]; - network_session* session = (network_session*)data_array[3]; char* buf = (char*)data_array[1]; size_t bufsize = (size_t)data_array[2]; + network_session* session = (network_session*)data_array[3]; + http_request* request = (http_request*)data_array[4]; binary_t bin; basic_stream bs; @@ -86,182 +86,86 @@ return_t consume_routine(uint32 type, uint32 data_count, void* data_array[], CAL OPTION& option = cmdline->value(); - switch (type) { - case mux_connect: - cprint("connect %i", session_socket->cli_socket); - break; - case mux_read: - cprint("read %i", session_socket->cli_socket); - if (option.verbose) { - dump_memory((byte_t*)buf, bufsize, &bs, 16, 2); - print("consume\n%s", bs.c_str()); - bs.clear(); + // switch (type) { + // case mux_connect: + // // cprint("connect %i", session_socket->cli_socket); + // break; + // case mux_read: + // // cprint("read %i", session_socket->cli_socket); + // break; + // case mux_disconnect: + // // cprint("disconnect %i", session_socket->cli_socket); + // break; + // } + + if (request) { // in case of mux_read + if (2 == request->get_version()) { // HTTP/2, END_HEADERS and END_HEADERS + uint32 stream_id = request->get_stream_id(); + + hpack_encoder* encoder = &_http_server->get_hpack_encoder(); + hpack_session* hpsess = &session->get_http2_session().get_hpack_session(); + + hpack hp; + binary_t bin_resp; + const char* resp = "hello"; + + // header compression + { + hp.set_encoder(encoder) + .set_session(hpsess) + .set_encode_flags(hpack_indexing | hpack_huffman) + .encode_header(":status", "200") + .encode_header("content-type", "text/html") + .encode_header("content-length", format("%zi", strlen(resp)).c_str(), hpack_wo_indexing | hpack_huffman); + if (option.verbose) { + dump_memory(hp.get_binary(), &bs, 16, 2); + print("dump HPACK\n%s\n", bs.c_str()); + } } - // studying .... debug frames ... - - if (errorcode_t::success == _http_server->get_http2_protocol().is_kind_of(buf, bufsize)) { - constexpr char preface[] = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"; - const uint16 sizeof_preface = 24; - bool stage_preface = false; - uint32 pos_frame = 0; - if (bufsize > sizeof_preface) { - if (0 == strncmp(buf, preface, sizeof_preface)) { - print("- http/2 connecton preface"); - stage_preface = true; - pos_frame = sizeof_preface; - } - } + // response headers + { + // - END_STREAM + // + END_HEADERS + http2_frame_headers resp_headers; + resp_headers.set_hpack_encoder(encoder).set_hpack_session(hpsess).set_flags(h2_flag_end_headers).set_stream_id(stream_id); + resp_headers.get_fragment() = hp.get_binary(); + resp_headers.write(bin_resp); + } - http2_frame_header_t* hdr = (http2_frame_header_t*)(buf + pos_frame); - size_t checksize = bufsize - pos_frame; - uint32_24_t i32_24((byte_t*)hdr, checksize); - uint32 payload_size = i32_24.get(); - uint32 packet_size = sizeof(http2_frame_header_t) + payload_size; - - if (h2_frame_t::h2_frame_data == hdr->type) { - http2_frame_data frame; - dump_frame(&frame, hdr, checksize); - - if (0 == frame.get_stream_id()) { - // DATA frames MUST be associated with a stream. If a DATA frame is - // received whose stream identifier field is 0x0, the recipient MUST - // respond with a connection error (Section 5.4.1) of type - // PROTOCOL_ERROR. - - http2_frame_goaway resp_goaway; - resp_goaway.set_errorcode(h2_connect_error); - resp_goaway.get_debug() = convert("connection error"); - - binary_t bin_resp; - resp_goaway.write(bin_resp); - - session->send((char*)&bin_resp[0], bin_resp.size()); - } - - } else if (h2_frame_t::h2_frame_headers == hdr->type) { - http2_frame_headers frame; - frame.set_hpack_encoder(&_http_server->get_hpack_encoder()).set_hpack_session(session->get_hpack_session()); - dump_frame(&frame, hdr, checksize); - - uint32 stream_id = frame.get_stream_id(); - - hpack hp; - binary_t bin_resp; - const char* resp = "hello"; - - // header compression - { - hp.set_encoder(&_http_server->get_hpack_encoder()) - .set_session(session->get_hpack_session()) - .set_encode_flags(hpack_indexing | hpack_huffman) - .encode_header(":status", "200") - // HPACK_INVALID_INDEX - //.encode_header("content-type", "text/html") - //.encode_header("content-length", format("%zi", strlen(resp)).c_str()) - ; - if (option.verbose) { - dump_memory(hp.get_binary(), &bs, 16, 2); - printf("dump HPACK\n%s\n", bs.c_str()); - } - } - - // response headers - { - // - END_STREAM - // + END_HEADERS - http2_frame_headers resp_headers; - resp_headers.set_hpack_encoder(&_http_server->get_hpack_encoder()) - .set_hpack_session(session->get_hpack_session()) - .set_flags(h2_flag_end_headers) - .set_stream_id(stream_id); - resp_headers.get_fragment() = hp.get_binary(); - resp_headers.write(bin_resp); - } - - // response data - { - // + END_STREAM - http2_frame_data resp_data; - resp_data.set_flags(h2_flag_end_stream).set_stream_id(stream_id); - - resp_data.get_data() = convert(resp); - resp_data.write(bin_resp); - } - - // response - { - // + END_STREAM - // + END_HEADERS - http2_frame_headers resp_headers2; - resp_headers2.set_flags(h2_flag_end_stream | h2_flag_end_headers).set_stream_id(stream_id); - resp_headers2.write(bin_resp); - } - - // dump response - if (option.verbose) { - dump_memory(bin_resp, &bs, 16, 2); - printf("dump (headers+data)\n%s\n", bs.c_str()); - } - - session->send((char*)&bin_resp[0], bin_resp.size()); - fflush(stdout); - - } else if (h2_frame_t::h2_frame_priority == hdr->type) { - http2_frame_priority frame; - dump_frame(&frame, hdr, checksize); - } else if (h2_frame_t::h2_frame_rst_stream == hdr->type) { - http2_frame_rst_stream frame; - dump_frame(&frame, hdr, checksize); - } else if (h2_frame_t::h2_frame_settings == hdr->type) { - http2_frame_settings frame; - dump_frame(&frame, hdr, checksize); - - binary_t bin_resp; - http2_frame_settings resp_settings; - - if (frame.get_flags()) { - resp_settings.set_flags(h2_flag_ack); - - resp_settings.write(bin_resp); - - dump_memory(bin_resp, &bs, 16, 2); - printf("dump (settings)\n%s\n", bs.c_str()); - - session->send((char*)&bin_resp[0], bin_resp.size()); - - } else { - // resp_settings.add(h2_settings_enable_push, 0).add(h2_settings_max_concurrent_streams, 100); - } - - } else if (h2_frame_t::h2_frame_push_promise == hdr->type) { - http2_frame_push_promise frame; - frame.set_hpack_encoder(&_http_server->get_hpack_encoder()).set_hpack_session(session->get_hpack_session()); - dump_frame(&frame, hdr, checksize); - } else if (h2_frame_t::h2_frame_ping == hdr->type) { - http2_frame_ping frame; - dump_frame(&frame, hdr, checksize); - } else if (h2_frame_t::h2_frame_goaway == hdr->type) { - http2_frame_goaway frame; - dump_frame(&frame, hdr, checksize); - } else if (h2_frame_t::h2_frame_window_update == hdr->type) { - http2_frame_window_update frame; - dump_frame(&frame, hdr, checksize); - } else if (h2_frame_t::h2_frame_continuation == hdr->type) { - http2_frame_continuation frame; - frame.set_hpack_encoder(&_http_server->get_hpack_encoder()).set_hpack_session(session->get_hpack_session()); - dump_frame(&frame, hdr, checksize); - } - } else { - http_response resp; - resp.compose(200, "text/html", "
hello
"); - resp.respond(session); + // response data + { + // + END_STREAM + http2_frame_data resp_data; + resp_data.set_flags(h2_flag_end_stream).set_stream_id(stream_id); + + resp_data.get_data() = convert(resp); + resp_data.write(bin_resp); + } + + // response + { + // + END_STREAM + // + END_HEADERS + http2_frame_headers resp_headers2; + resp_headers2.set_flags(h2_flag_end_stream | h2_flag_end_headers).set_stream_id(stream_id); + resp_headers2.write(bin_resp); } - break; - case mux_disconnect: - cprint("disconnect %i", session_socket->cli_socket); - break; + + // dump response + if (option.verbose) { + dump_memory(bin_resp, &bs, 16, 2); + print("dump (headers+data)\n%s\n", bs.c_str()); + } + + session->send((char*)&bin_resp[0], bin_resp.size()); + } else { // HTTP/1.1 + http_response resp; + resp.compose(200, "text/html", "
hello
"); + resp.respond(session); + } } + return ret; } @@ -288,14 +192,19 @@ return_t echo_server(void*) { .enable_h2(true) // enable HTTP/2 .set_handler(consume_routine); builder.get_server_conf() - .set(netserver_config_t::serverconf_concurrent_tls_accept, 2) - .set(netserver_config_t::serverconf_concurrent_network, 4) - .set(netserver_config_t::serverconf_concurrent_consume, 4); + .set(netserver_config_t::serverconf_concurrent_tls_accept, 1) + .set(netserver_config_t::serverconf_concurrent_network, 2) + .set(netserver_config_t::serverconf_concurrent_consume, 2); _http_server.make_share(builder.build()); _http_server->get_http_protocol().set_constraints(protocol_constraints_t::protocol_packet_size, 1 << 14); _http_server->get_http2_protocol().set_constraints(protocol_constraints_t::protocol_packet_size, 1 << 14); + if (option.verbose) { + _http_server->get_server_conf().set(netserver_config_t::serverconf_debug_h2, 1); + _http_server->set_debug([](stream_t* s) -> void { print("%.*s", s->size(), s->data()); }); + } + _http_server->start(); while (true) { diff --git a/test/payload/sample.cpp b/test/payload/sample.cpp index 66876c04..e286b730 100644 --- a/test/payload/sample.cpp +++ b/test/payload/sample.cpp @@ -134,9 +134,9 @@ void test_payload_uint24() { pl.read(expect); - uint8 padlen = t_variant_to_int(pl.select("padlen")->get_variant().content()); - uint32_24_t i24 = t_variant_to_int(pl.select("int32_24")->get_variant().content()); - uint32 i32 = t_variant_to_int(pl.select("int32_32")->get_variant().content()); + uint8 padlen = t_to_int(pl.select("padlen")); + uint32_24_t i24 = t_to_int(pl.select("int32_24")); + uint32 i32 = t_to_int(pl.select("int32_32")); if (option.verbose) { uint32 i24_value = i24.get();