diff --git a/ccsrc/Protocols/Http/http_codec.cc b/ccsrc/Protocols/Http/http_codec.cc index 270c6c19e65c8b76211eb7c6d96bd9ebecf51d22..cdf4ab7e4303b92ec0534b5929613503d47cf1af 100644 --- a/ccsrc/Protocols/Http/http_codec.cc +++ b/ccsrc/Protocols/Http/http_codec.cc @@ -41,20 +41,47 @@ int http_codec::encode(const LibHttp__TypesAndValues::HttpMessage &msg, OCTETSTR int http_codec::decode(const OCTETSTRING &data, LibHttp__TypesAndValues::HttpMessage &msg, params *params) { loggers::get_instance().log_msg(">>> http_codec::decode: data=", data); - // Sanity checks - if ((data[0].get_octet() & 0x80) == 0x80) { - loggers::get_instance().warning("http_codec::decode: Unicode format not supported"); - return -1; - } - TTCN_EncDec::clear_error(); - TTCN_Buffer decoding_buffer(data); - loggers::get_instance().log_to_hexa("http_codec::decode: decoding_buffer=", decoding_buffer); + TTCN_Buffer decoding_buffer; + + if (_initial_content_length != 0) { // Check if the data is a new fragment of the response + loggers::get_instance().warning("http_codec::decode: Need to bufferize and wait for all fragments received"); + _bufferized_buffers.push_back(data); + _current_content_length += data.lengthof(); // FIXME Need to calculate the size of the header buffer, do not assume th first fragmwnt is the header buffer + loggers::get_instance().log("http_codec::decode: _bufferized_buffers size: %d - _current_content_length: %d - _initial_content_length: %d", _bufferized_buffers.size(), _current_content_length, _initial_content_length); + if (_current_content_length < _initial_content_length) { // Wait for the next fragment + loggers::get_instance().warning("http_codec::decode: Wait for the next fragment"); + return -2; + } else { // Rebuild the wall message and continue the decoding + loggers::get_instance().log("http_codec::decode: All the fragments were received, rebuild message"); + // Concatenate the fragments + loggers::get_instance().log("http_codec::decode: Concatenate bufferized datas"); + for (size_t i = 0; i < _bufferized_buffers.size(); i++) { + decoding_buffer.put_string(_bufferized_buffers[i]); + } // End of 'for' statement + _bufferized_buffers.clear(); + loggers::get_instance().log("http_codec::decode: _bufferized_buffers cleared: %d", _bufferized_buffers.size()); + // Reset counters + loggers::get_instance().log("http_codec::decode: Reset bufferization counters"); + _initial_content_length = 0; + _current_content_length = 0; + // Continue the decoding + } + } else { // It can be a full HTTP response or the first gragment of the HTTP response + decoding_buffer.put_string(data); + } + loggers::get_instance().log("http_codec::decode: decoding_buffer size: %d", decoding_buffer.get_len()); + loggers::get_instance().log_to_hexa("http_codec::decode: Before decoding_buffer Body: ", decoding_buffer); _dc.reset(); _params = params; + if ((*decoding_buffer.get_data() & 0x80) == 0x80) { + loggers::get_instance().warning("http_codec::decode: Unicode format not supported"); + return -1; + } + // Get the first line (e.g. HTTP/1.1 302 Found or POST / HTTP/1.1) CHARSTRING message_id; if (get_line(decoding_buffer, message_id) == -1) { @@ -84,10 +111,30 @@ int http_codec::decode(const OCTETSTRING &data, LibHttp__TypesAndValues::HttpMes response.statuscode() = std::stoi(m[3].str().c_str()); response.statustext() = CHARSTRING(m[4].str().c_str()); LibHttp__TypesAndValues::Headers headers; - std::string content_type; + std::string content_type; decode_headers(decoding_buffer, headers, content_type); + if (_dc.length > decoding_buffer.get_len()) { // HTTP response is fragmented + // Need to bufferize the first packet and wait for the other fragments tp be received + loggers::get_instance().warning("http_codec::decode: Need to bufferize the first packet and wait for the other fragments tp be received"); + // Set counters + loggers::get_instance().log("http_codec::decode: Set bufferization counters"); + _initial_content_length = _dc.length; + _current_content_length = 0; + _bufferized_buffers.push_back(data); + _current_content_length += data.lengthof(); + loggers::get_instance().log("http_codec::decode: _bufferized_buffers size: %d - _current_content_length: %d", _bufferized_buffers.size(), _current_content_length); + return -2; + } else { + // Force reset counters + loggers::get_instance().log("http_codec::decode: Force reset bufferization counters"); + _initial_content_length = 0; + _current_content_length = 0; + } + response.header() = headers; loggers::get_instance().log_to_hexa("Before decoding Body: ", decoding_buffer); + loggers::get_instance().log("http_codec::decode: _initial_content_length = %d", _initial_content_length); + loggers::get_instance().log("http_codec::decode: headers().content_length (_dc.length) = %d - decoding_buffer.get_len() = %d", _dc.length, decoding_buffer.get_len()); LibHttp__MessageBodyTypes::HttpMessageBody body; if (decode_body(decoding_buffer, body, content_type) == -1) { response.body().set_to_omit(); diff --git a/ccsrc/Protocols/Http/http_codec.hh b/ccsrc/Protocols/Http/http_codec.hh index 04079e616934887046926aa07454902db70ac05e..37f313cc9c3fccfe4e6e2544d6dc3953c509b2a1 100644 --- a/ccsrc/Protocols/Http/http_codec.hh +++ b/ccsrc/Protocols/Http/http_codec.hh @@ -9,6 +9,7 @@ class Base_Type; class Record_Type; class TTCN_Typedescriptor_t; class TTCN_Buffer; +class OCTETSTRING; namespace LibHttp__TypesAndValues { class HttpMessage; @@ -60,9 +61,12 @@ class http_codec : public codec_gen<LibHttp__TypesAndValues::HttpMessage, LibHtt protected: std::map<std::string, std::unique_ptr<codec_gen<Record_Type, Record_Type>>> _codecs; + std::vector<OCTETSTRING> _bufferized_buffers; + unsigned int _initial_content_length; + unsigned int _current_content_length; public: - explicit http_codec() : codec_gen<LibHttp__TypesAndValues::HttpMessage, LibHttp__TypesAndValues::HttpMessage>(), _ec(), _dc(), _codecs(){}; + explicit http_codec() : codec_gen<LibHttp__TypesAndValues::HttpMessage, LibHttp__TypesAndValues::HttpMessage>(), _ec(), _dc(), _codecs(), _bufferized_buffers(), _initial_content_length{0}, _current_content_length{0} {}; virtual ~http_codec(){}; virtual int encode(const LibHttp__TypesAndValues::HttpMessage &, OCTETSTRING &data); diff --git a/ccsrc/Protocols/Http/http_layer.cc b/ccsrc/Protocols/Http/http_layer.cc index bf4da9f92d5c7edb135b1cd2aae8f0daab9929c9..8d83cbc02d4d0adb75ea78486c932e1497081e6b 100644 --- a/ccsrc/Protocols/Http/http_layer.cc +++ b/ccsrc/Protocols/Http/http_layer.cc @@ -95,9 +95,14 @@ void http_layer::receive_data(OCTETSTRING &data, params ¶ms) { // Decode HTTP message LibHttp__TypesAndValues::HttpMessage http_message; - if (_codec->decode(data, http_message, ¶ms) == -1) { + int ret_code = _codec->decode(data, http_message, ¶ms); + if (ret_code == -1) { loggers::get_instance().warning("http_layer::receive_data: Failed to decode data"); return; + } else if (ret_code == -2) { // Need to wait for next data + loggers::get_instance().log("http_layer::receive_data: Set Buffurizing to 1"); + params.insert(std::make_pair<std::string, std::string>("Buffurizing", "1")); + return; } if (_device_mode) { OCTETSTRING os; diff --git a/ccsrc/Protocols/Tcp/tcp_layer.cc b/ccsrc/Protocols/Tcp/tcp_layer.cc index 2c49ef915b70bb0b6fe0cf0dc5b11e85ba117cc2..632ec3bd79f21f044a7fd24c250d85a6f45510af 100644 --- a/ccsrc/Protocols/Tcp/tcp_layer.cc +++ b/ccsrc/Protocols/Tcp/tcp_layer.cc @@ -210,6 +210,10 @@ void tcp_layer::message_incoming(const unsigned char* message_buffer, int length std::string("timestamp"), std::to_string(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count()))); this->receive_data(data, params); // TODO Check execution time for decoding operation + params::const_iterator it = params.find(std::string("Buffurizing")); + if (it != params.end()) { + loggers::get_instance().log("tcp_layer::message_incoming: Buffurizing requested"); + } loggers::get_instance().set_stop_time(_time_key, duration); }