Loading ccsrc/EncDec/LibItsHttp_Encdec.cc 0 → 100644 +20 −0 Original line number Diff line number Diff line #include "LibItsHttp_MessageBodyTypes.hh" #include "http_codec.hh" #include "loggers.hh" namespace LibItsHttp__EncdecDeclarations { BITSTRING fx__enc__http__message(const LibItsHttp__TypesAndValues::HttpMessage& p) { return BITSTRING(); } INTEGER fx__dec__http__message(BITSTRING& pdu, LibItsHttp__TypesAndValues::HttpMessage& p) { loggers::get_instance().log_msg(">>> fx__dec__http__response: ", pdu); OCTETSTRING os = bit2oct(pdu); http_codec codec; codec.decode(os, p); return 0; } } // End of namespace LibItsHttp__EncdecDeclarations ccsrc/Ports/LibIts_ports/Http_ports/HttpPort.cc 0 → 100644 +90 −0 Original line number Diff line number Diff line #include "HttpPort.hh" #include "http_layer_factory.hh" #include "loggers.hh" namespace LibItsHttp__TestSystem { HttpPort::HttpPort(const char *par_port_name): HttpPort_BASE(par_port_name), _cfg_params(), _layer_params(), _layer(nullptr), _time_key("HttpPort::outgoing_send") { // Nothing to do } // End of constructor HttpPort::~HttpPort() { loggers::get_instance().log(">>> HttpPort::~HttpPort"); if (_layer != nullptr) { delete _layer; } } // End of destructor void HttpPort::set_parameter(const char * parameter_name, const char * parameter_value) { loggers::get_instance().log("HttpPort::set_parameter: %s=%s", parameter_name, parameter_value); _cfg_params.insert(std::pair<std::string, std::string>(std::string(parameter_name), std::string(parameter_value))); } /*void HttpPort::Handle_Fd_Event(int fd, boolean is_readable, boolean is_writable, boolean is_error) {}*/ void HttpPort::Handle_Fd_Event_Error(int /*fd*/) { } void HttpPort::Handle_Fd_Event_Writable(int /*fd*/) { } void HttpPort::Handle_Fd_Event_Readable(int /*fd*/) { } /*void HttpPort::Handle_Timeout(double time_since_last_call) {}*/ void HttpPort::user_map(const char * system_port) { loggers::get_instance().log(">>> HttpPort::user_map: %s", system_port); // Build layer stack params::iterator it = _cfg_params.find(std::string("params")); if (it != _cfg_params.end()) { loggers::get_instance().log("HttpPort::user_map: %s", it->second.c_str()); // Setup parameters params::convert(_layer_params, it->second); // TODO This _layer_params seems to be useless // Create layer _layer = layer_stack_builder::get_instance()->create_layer_stack(it->second.c_str()); if (static_cast<http_layer *>(_layer) == nullptr) { loggers::get_instance().error("HttpPort::user_map: Invalid stack configuration: %s", it->second.c_str()); } static_cast<http_layer *>(_layer)->add_upper_port(this); } else { loggers::get_instance().error("HttpPort::user_map: No layers defined in configuration file"); } } // End of user_map method void HttpPort::user_unmap(const char * system_port) { loggers::get_instance().log(">>> HttpPort::user_unmap: %s", system_port); // Reset layers if (_layer != nullptr) { delete _layer; _layer = nullptr; } } // End of user_unmap method void HttpPort::user_start() { loggers::get_instance().log(">>> HttpPort::user_start"); } // End of user_start method void HttpPort::user_stop() { loggers::get_instance().log(">>> HttpPort::user_stop"); } // End of user_stop method } ccsrc/Ports/LibIts_ports/Http_ports/HttpPort.hh 0 → 100644 +46 −0 Original line number Diff line number Diff line #pragma once #include "LibItsHttp_TestSystem.hh" #include "layer.hh" #include "params.hh" namespace LibItsHttp__TypesAndValues { class REGISTER__Request; } namespace LibItsHttp__TestSystem { class HttpPort : public HttpPort_BASE { params _cfg_params; params _layer_params; layer* _layer; std::string _time_key; public: HttpPort(const char *par_port_name); ~HttpPort(); void set_parameter(const char *parameter_name, const char *parameter_value); void receiveMsg (const LibItsHttp__TypesAndValues::REGISTER__Request&, const params&); private: /* void Handle_Fd_Event(int fd, boolean is_readable, boolean is_writable, boolean is_error); */ void Handle_Fd_Event_Error(int fd); void Handle_Fd_Event_Writable(int fd); void Handle_Fd_Event_Readable(int fd); /* void Handle_Timeout(double time_since_last_call); */ protected: void user_map(const char *system_port); void user_unmap(const char *system_port); void user_start(); void user_stop(); protected: virtual void outgoing_send(const LibItsHttp__TypesAndValues::HttpMessage& send_par) { }; }; // End of class HttpPort } ccsrc/Protocols/Http/http_codec.cc +269 −132 Original line number Diff line number Diff line Loading @@ -7,6 +7,8 @@ #include "loggers.hh" #include "LibItsHttp_TypesAndValues.hh" #include "LibItsHttp_MessageBodyTypes.hh" #include "LibItsHttp_XmlMessageBodyTypes.hh" int http_codec::encode (const LibItsHttp__TypesAndValues::HttpMessage& msg, OCTETSTRING& data) { Loading @@ -19,7 +21,7 @@ int http_codec::encode (const LibItsHttp__TypesAndValues::HttpMessage& msg, OCTE if (msg.ischosen(LibItsHttp__TypesAndValues::HttpMessage::ALT_request)) { result = encode_request(msg.request(), encoding_buffer); } else if (msg.ischosen(LibItsHttp__TypesAndValues::HttpMessage::ALT_response)) { //result = encode_response(msg.response(), encoding_buffer); result = encode_response(msg.response(), encoding_buffer); } else { loggers::get_instance().warning("http_codec::encode: Unbound HttpMessage"); return -1; Loading Loading @@ -54,9 +56,10 @@ int http_codec::decode (const OCTETSTRING& data, LibItsHttp__TypesAndValues::Htt loggers::get_instance().log("http_codec::decode: %d - %s", m.size(), m[0].str().c_str()); if (m[0].str().compare("HTTP/") == 0) { // HTTP response LibItsHttp__TypesAndValues::Response response; std::regex rgx ("\\s*HTTP/(\\d)\\.(\\d)\\s+(\\d+)\\s+(\\w+)"); std::regex rgx ("\\s*HTTP/(\\d+)\\.(\\d+)\\s+(\\d+)\\s+(\\w+)*"); std::sregex_iterator begin(str.cbegin(), str.cend(), rgx); std::smatch m = *begin; loggers::get_instance().log("http_codec::decode: Process response: %d", m.size()); if (m.size() != 5) { loggers::get_instance().error("http_codec::decode: Unsupported tag"); return -1; Loading @@ -69,13 +72,11 @@ int http_codec::decode (const OCTETSTRING& data, LibItsHttp__TypesAndValues::Htt decode_headers(decoding_buffer, headers); response.header() = headers; loggers::get_instance().log_to_hexa("Before decoding Body: ", decoding_buffer); CHARSTRING body(""); LibItsHttp__MessageBodyTypes::HttpMessageBody body; if (decode_body(decoding_buffer, body) == -1) { response.body().set_to_omit(); } else if (body.lengthof() == 0) { response.body().set_to_omit(); } else { // TODO response.body() = OPTIONAL<LibItsHttp__MessageBodyTypes::HttpMessageBody>(body); } msg.response() = response; } else { // HTTP request Loading @@ -94,14 +95,12 @@ int http_codec::decode (const OCTETSTRING& data, LibItsHttp__TypesAndValues::Htt LibItsHttp__TypesAndValues::HeaderLines headers; decode_headers(decoding_buffer, headers); request.header() = headers; loggers::get_instance().log_to_hexa("Before decoding Body: ", decoding_buffer); CHARSTRING body(""); OPTIONAL<LibItsHttp__MessageBodyTypes::HttpMessageBody> body; body.set_to_omit(); if (decode_body(decoding_buffer, body) == -1) { request.body().set_to_omit(); } else if (body.lengthof() == 0) { request.body().set_to_omit(); } else { // TODO request.body() = body; } msg.request() = request; } Loading @@ -118,12 +117,21 @@ int http_codec::encode_request(const LibItsHttp__TypesAndValues::Request& p_requ { loggers::get_instance().log_msg(">>> http_codec::encode_request: ", (const Base_Type&)p_request); const OPTIONAL<CHARSTRING>& v = p_request.body(); CHARSTRING body(""); const OPTIONAL<LibItsHttp__MessageBodyTypes::HttpMessageBody>& v = p_request.body(); OCTETSTRING os; if (v.ispresent()) { body = static_cast<const CHARSTRING&>(*v.get_opt_value()); const LibItsHttp__MessageBodyTypes::HttpMessageBody& body = static_cast<const LibItsHttp__MessageBodyTypes::HttpMessageBody&>(*v.get_opt_value()); loggers::get_instance().log_msg("http_codec::encode_request: body: ", body); if (body.ischosen(LibItsHttp__MessageBodyTypes::HttpMessageBody::ALT_ms__body)) { os = body.ms__body(); } else { LibItsHttp__XmlMessageBodyTypes::XmlBody xml_body = body.xml__body(); if (xml_body.ischosen(LibItsHttp__XmlMessageBodyTypes::XmlBody::ALT_raw)) { os = OCTETSTRING(xml_body.raw().lengthof(), (unsigned char*)static_cast<const char*>(xml_body.raw())); } } } loggers::get_instance().log("http_codec::encode_request: HTTP message lenght: %d ", os.lengthof()); // Encode generic part p_encoding_buffer.put_cs(p_request.method()); Loading @@ -142,33 +150,106 @@ int http_codec::encode_request(const LibItsHttp__TypesAndValues::Request& p_requ p_encoding_buffer.put_cs(header.header__name()); p_encoding_buffer.put_cs(": "); if (std::string(static_cast<const char*>(header.header__name())).compare("Content-Length") == 0) { loggers::get_instance().log("http_codec::encode_request: body length: %d", body.lengthof()); p_encoding_buffer.put_cs(int2str(body.lengthof())); p_encoding_buffer.put_cs(int2str(os.lengthof() + 2/*Stand for the last CRLF*/)); _ec.is_content_length_present = 0x01; } else { if (header.header__value().size_of() > 0) { loggers::get_instance().log_msg("http_codec::encode_request: Processing value ", header.header__value()[0]); p_encoding_buffer.put_cs(header.header__value()[0]); const OPTIONAL<LibItsHttp__TypesAndValues::charstring__list>& o = header.header__value(); if (o.ispresent()) { const LibItsHttp__TypesAndValues::charstring__list& v = dynamic_cast<const OPTIONAL<LibItsHttp__TypesAndValues::charstring__list> &>(o); if (v.size_of() > 0) { loggers::get_instance().log_msg("http_codec::encode_request: Processing value ", v[0]); p_encoding_buffer.put_cs(v[0]); int j = 1; while (j < header.header__value().size_of()) { p_encoding_buffer.put_cs("; "); loggers::get_instance().log_msg("http_codec::encode_request: Processing value ", header.header__value()[j]); p_encoding_buffer.put_cs(header.header__value()[j]); while (j < v.size_of()) { p_encoding_buffer.put_cs(", "); loggers::get_instance().log_msg("http_codec::encode_request: Processing value ", v[j]); p_encoding_buffer.put_cs(v[j]); j += 1; } // End of 'while' statement } } // else, do not include it } p_encoding_buffer.put_cs("\r\n"); } // End of 'for' statement if (body.lengthof() != 0) { p_encoding_buffer.put_cs(body); p_encoding_buffer.put_cs("\r\n"); if (_ec.length != 0) { p_encoding_buffer.put_os(os); p_encoding_buffer.put_cs("\r\n"); } return 0; } int http_codec::encode_response (const LibItsHttp__TypesAndValues::Response& p_response, TTCN_Buffer& p_encoding_buffer) { loggers::get_instance().log_msg(">>> http_codec::encode_response: ", (const Base_Type&)p_response); const OPTIONAL<LibItsHttp__MessageBodyTypes::HttpMessageBody>& v = p_response.body(); OCTETSTRING os; if (v.ispresent()) { const LibItsHttp__MessageBodyTypes::HttpMessageBody& body = static_cast<const LibItsHttp__MessageBodyTypes::HttpMessageBody&>(*v.get_opt_value()); loggers::get_instance().log_msg("http_codec::encode_response: body: ", body); if (body.ischosen(LibItsHttp__MessageBodyTypes::HttpMessageBody::ALT_ms__body)) { os = body.ms__body(); } else { LibItsHttp__XmlMessageBodyTypes::XmlBody xml_body = body.xml__body(); if (xml_body.ischosen(LibItsHttp__XmlMessageBodyTypes::XmlBody::ALT_raw)) { os = OCTETSTRING(xml_body.raw().lengthof(), (unsigned char*)static_cast<const char*>(xml_body.raw())); } } } loggers::get_instance().log("http_codec::encode_response: HTTP message lenght: %d ", os.lengthof()); // Encode generic part p_encoding_buffer.put_cs("HTTP/"); p_encoding_buffer.put_cs(int2str(p_response.version__major())); p_encoding_buffer.put_c('.'); p_encoding_buffer.put_cs(int2str(p_response.version__minor())); p_encoding_buffer.put_cs(" "); p_encoding_buffer.put_cs(int2str(p_response.statuscode())); p_encoding_buffer.put_cs(" "); if (p_response.statustext().lengthof() != 0) { p_encoding_buffer.put_cs(p_response.statustext()); } p_encoding_buffer.put_cs("\r\n"); // Encode headers const LibItsHttp__TypesAndValues::HeaderLines& headers = p_response.header(); for (int i = 0; i < headers.size_of(); i++) { const LibItsHttp__TypesAndValues::HeaderLine& header = headers[i]; loggers::get_instance().log_msg("http_codec::encode_response: Processing header ", header.header__name()); p_encoding_buffer.put_cs(header.header__name()); p_encoding_buffer.put_cs(": "); if (std::string(static_cast<const char*>(header.header__name())).compare("Content-Length") == 0) { p_encoding_buffer.put_cs(int2str(os.lengthof() + 2/*Stand for the last CRLF*/)); _ec.is_content_length_present = 0x01; } else { const OPTIONAL<LibItsHttp__TypesAndValues::charstring__list>& o = header.header__value(); if (o.ispresent()) { const LibItsHttp__TypesAndValues::charstring__list& v = dynamic_cast<const OPTIONAL<LibItsHttp__TypesAndValues::charstring__list> &>(o); if (v.size_of() > 0) { loggers::get_instance().log_msg("http_codec::encode_response: Processing value ", v[0]); p_encoding_buffer.put_cs(v[0]); int j = 1; while (j < v.size_of()) { p_encoding_buffer.put_cs(", "); loggers::get_instance().log_msg("http_codec::encode_response: Processing value ", v[j]); p_encoding_buffer.put_cs(v[j]); j += 1; } // End of 'while' statement } } // else, do not include it } p_encoding_buffer.put_cs("\r\n"); } // End of 'for' statement return 0; p_encoding_buffer.put_cs("\r\n"); if (_ec.length != 0) { p_encoding_buffer.put_os(os); p_encoding_buffer.put_cs("\r\n"); } return 0; } int http_codec::decode_headers(TTCN_Buffer& decoding_buffer, LibItsHttp__TypesAndValues::HeaderLines& headers) { loggers::get_instance().log(">>> http_codec::decode_headers"); Loading @@ -194,7 +275,6 @@ int http_codec::decode_headers(TTCN_Buffer& decoding_buffer, LibItsHttp__TypesAn case -1: loggers::get_instance().warning("http_codec::decode_headers: Failed to decode headers"); return -1; } // End of 'switch' statement } // End of 'while' statement } Loading @@ -204,18 +284,28 @@ int http_codec::decode_header(CHARSTRING& header_line, LibItsHttp__TypesAndValue try { std::string str(static_cast<const char*>(header_line)); std::regex rgx ("([0-9a-zA-Z-]+)\\:\\s+(.+)(;(.+))*"); std::regex rgx ("([0-9a-zA-Z-]+)\\:\\s+(.+)(,(.+))*"); std::sregex_iterator begin(str.cbegin(), str.cend(), rgx); std::smatch m = *begin; if (m.size() < 5) { loggers::get_instance().warning("http_codec::decode_header: Failed to decode header %s", str.c_str()); return -1; } loggers::get_instance().log("http_codec::decode_header: %d", m.size()); header.header__name() = CHARSTRING(m[1].str().c_str()); LibItsHttp__TypesAndValues::charstring__list v; for (unsigned int j = 0; j < m.size(); j++) { if (m[j + 2].str().length() == 0) { break; } header.header__value()[j] = CHARSTRING(m[j + 2].str().c_str()); v[j] = CHARSTRING(m[j + 2].str().c_str()); } // End of 'for' statement header.header__value() = OPTIONAL<LibItsHttp__TypesAndValues::charstring__list>(v); if (m[1].str().compare("Content-Length") == 0) { // Save the the body length loggers::get_instance().log("http_codec::decode_header: decoded Content-Length %s", m[2].str().c_str()); _dc.length = std::stoi(m[2].str()); } return 0; } Loading @@ -224,17 +314,64 @@ int http_codec::decode_header(CHARSTRING& header_line, LibItsHttp__TypesAndValue } } int http_codec::decode_body(TTCN_Buffer& decoding_buffer, CHARSTRING& body) { int http_codec::decode_body(TTCN_Buffer& decoding_buffer, LibItsHttp__MessageBodyTypes::HttpMessageBody& message_body) { loggers::get_instance().log(">>> http_codec::decode_body"); loggers::get_instance().log_to_hexa("http_codec::decode_body", decoding_buffer); loggers::get_instance().log_msg("<<< http_codec::decode_body: ", body); // Sanity check if (decoding_buffer.get_len() - decoding_buffer.get_pos() <= 0) { return -1; } OCTETSTRING s(decoding_buffer.get_len() - decoding_buffer.get_pos(), decoding_buffer.get_data() + decoding_buffer.get_pos()); loggers::get_instance().log_msg("http_codec::decode_body: raw body=", s); // Align the payload length with the specified plLenght value loggers::get_instance().log("http_codec::decode_body: _dc.length=%d - body length=%d", _dc.length, s.lengthof()); OCTETSTRING body; if (_dc.length != 0) { const unsigned char* p = static_cast<const unsigned char *>(s); if ((unsigned int)s.lengthof() <= _dc.length) { body = OCTETSTRING(s.lengthof(), p); } else { body = OCTETSTRING(_dc.length, p); } } else { loggers::get_instance().warning("http_codec::decode_body: No Conten-Length header, process all remaining bytes"); body = s; } loggers::get_instance().log_msg("http_codec::decode_body: Aligned body=", body); // Remove CRLF if any int counter = 0; if ((body[body.lengthof() - 1].get_octet() == 0x0d) || (body[body.lengthof() - 1].get_octet() == 0x0a)) { counter += 1; if ((body[body.lengthof() - 2].get_octet() == 0x0d) || (body[body.lengthof() - 2].get_octet() == 0x0a)) { counter += 1; } } loggers::get_instance().log("http_codec::decode_body: Counter=%d", counter); body = OCTETSTRING(body.lengthof() - counter, static_cast<const unsigned char*>(body)); loggers::get_instance().log_msg("http_codec::decode_body: Finalised body=", body); // Check if HTTP message body contains binary characters for (int i = 0; i < body.lengthof(); i++) { unsigned char c = body[i].get_octet(); if (!std::isprint(c) && !std::isspace(c) && !std::ispunct(c)) { loggers::get_instance().log("http_codec::decode_body: Byte #%d is not printable: 0x%02x", i, body[i].get_octet()); _dc.is_binary = 0x01; break; } } // End of 'for' statement loggers::get_instance().log("http_codec::decode_body: Binary mode: %x", _dc.is_binary); LibItsHttp__MessageBodyTypes::HttpMessageBody v; if (_dc.is_binary == 0x01) { message_body.ms__body() = body; } else { LibItsHttp__XmlMessageBodyTypes::XmlBody xml_body; xml_body.raw() = CHARSTRING(body.lengthof(), (char*)static_cast<const unsigned char*>(body)); message_body.xml__body() = xml_body; } return 0; } int http_codec::get_line(TTCN_Buffer& buffer, CHARSTRING& to, const bool concatenate_header_lines) { unsigned int i = 0; Loading @@ -246,7 +383,7 @@ int http_codec::get_line(TTCN_Buffer& buffer, CHARSTRING& to, const bool concate } while (true) { // Skip spaces, and emplty lines // Skip spaces, and empty lines for( ; i < buffer.get_read_len() && cc_to[i] != '\0' && cc_to[i] != '\r' && cc_to[i] != '\n'; i++); if(i >= buffer.get_read_len()) { // No more characters to process to = CHARSTRING(""); Loading ccsrc/Protocols/Http/http_codec.hh +22 −3 Original line number Diff line number Diff line Loading @@ -14,13 +14,32 @@ namespace LibItsHttp__TypesAndValues { class HeaderLines; class HeaderLine; } namespace LibItsHttp__MessageBodyTypes { class HttpMessageBody; } struct encoding_context { unsigned int length; unsigned char is_content_length_present; encoding_context() { length = -1; is_content_length_present = 0x00; }; }; struct decoding_context { unsigned int length; unsigned char is_binary; decoding_context() { length = -1; is_binary = 0x00; }; }; class http_codec: public codec < LibItsHttp__TypesAndValues::HttpMessage, LibItsHttp__TypesAndValues::HttpMessage> { encoding_context _ec; decoding_context _dc; public: explicit http_codec() : codec<LibItsHttp__TypesAndValues::HttpMessage, LibItsHttp__TypesAndValues::HttpMessage>() { }; explicit http_codec() : codec<LibItsHttp__TypesAndValues::HttpMessage, LibItsHttp__TypesAndValues::HttpMessage>(), _ec(), _dc() { }; virtual ~http_codec() { }; virtual int encode (const LibItsHttp__TypesAndValues::HttpMessage&, OCTETSTRING& data); Loading @@ -28,11 +47,11 @@ public: private: int encode_request (const LibItsHttp__TypesAndValues::Request& p_request, TTCN_Buffer& p_encoding_buffer); // int encode_response (const LibItsHttp__TypesAndValues::Request&, TTCN_Buffer& p_encoding_buffer); int encode_response (const LibItsHttp__TypesAndValues::Response& p_response, TTCN_Buffer& p_encoding_buffer); int decode_headers(TTCN_Buffer& decoding_buffer, LibItsHttp__TypesAndValues::HeaderLines& headers); int decode_header(CHARSTRING& header_line, LibItsHttp__TypesAndValues::HeaderLine& header); int decode_body(TTCN_Buffer& decoding_buffer, CHARSTRING& body); int decode_body(TTCN_Buffer& decoding_buffer, LibItsHttp__MessageBodyTypes::HttpMessageBody& message_body); int get_line(TTCN_Buffer& buffer, CHARSTRING& to, const bool concatenate_header_lines = false); }; // End of class http_codec Loading
ccsrc/EncDec/LibItsHttp_Encdec.cc 0 → 100644 +20 −0 Original line number Diff line number Diff line #include "LibItsHttp_MessageBodyTypes.hh" #include "http_codec.hh" #include "loggers.hh" namespace LibItsHttp__EncdecDeclarations { BITSTRING fx__enc__http__message(const LibItsHttp__TypesAndValues::HttpMessage& p) { return BITSTRING(); } INTEGER fx__dec__http__message(BITSTRING& pdu, LibItsHttp__TypesAndValues::HttpMessage& p) { loggers::get_instance().log_msg(">>> fx__dec__http__response: ", pdu); OCTETSTRING os = bit2oct(pdu); http_codec codec; codec.decode(os, p); return 0; } } // End of namespace LibItsHttp__EncdecDeclarations
ccsrc/Ports/LibIts_ports/Http_ports/HttpPort.cc 0 → 100644 +90 −0 Original line number Diff line number Diff line #include "HttpPort.hh" #include "http_layer_factory.hh" #include "loggers.hh" namespace LibItsHttp__TestSystem { HttpPort::HttpPort(const char *par_port_name): HttpPort_BASE(par_port_name), _cfg_params(), _layer_params(), _layer(nullptr), _time_key("HttpPort::outgoing_send") { // Nothing to do } // End of constructor HttpPort::~HttpPort() { loggers::get_instance().log(">>> HttpPort::~HttpPort"); if (_layer != nullptr) { delete _layer; } } // End of destructor void HttpPort::set_parameter(const char * parameter_name, const char * parameter_value) { loggers::get_instance().log("HttpPort::set_parameter: %s=%s", parameter_name, parameter_value); _cfg_params.insert(std::pair<std::string, std::string>(std::string(parameter_name), std::string(parameter_value))); } /*void HttpPort::Handle_Fd_Event(int fd, boolean is_readable, boolean is_writable, boolean is_error) {}*/ void HttpPort::Handle_Fd_Event_Error(int /*fd*/) { } void HttpPort::Handle_Fd_Event_Writable(int /*fd*/) { } void HttpPort::Handle_Fd_Event_Readable(int /*fd*/) { } /*void HttpPort::Handle_Timeout(double time_since_last_call) {}*/ void HttpPort::user_map(const char * system_port) { loggers::get_instance().log(">>> HttpPort::user_map: %s", system_port); // Build layer stack params::iterator it = _cfg_params.find(std::string("params")); if (it != _cfg_params.end()) { loggers::get_instance().log("HttpPort::user_map: %s", it->second.c_str()); // Setup parameters params::convert(_layer_params, it->second); // TODO This _layer_params seems to be useless // Create layer _layer = layer_stack_builder::get_instance()->create_layer_stack(it->second.c_str()); if (static_cast<http_layer *>(_layer) == nullptr) { loggers::get_instance().error("HttpPort::user_map: Invalid stack configuration: %s", it->second.c_str()); } static_cast<http_layer *>(_layer)->add_upper_port(this); } else { loggers::get_instance().error("HttpPort::user_map: No layers defined in configuration file"); } } // End of user_map method void HttpPort::user_unmap(const char * system_port) { loggers::get_instance().log(">>> HttpPort::user_unmap: %s", system_port); // Reset layers if (_layer != nullptr) { delete _layer; _layer = nullptr; } } // End of user_unmap method void HttpPort::user_start() { loggers::get_instance().log(">>> HttpPort::user_start"); } // End of user_start method void HttpPort::user_stop() { loggers::get_instance().log(">>> HttpPort::user_stop"); } // End of user_stop method }
ccsrc/Ports/LibIts_ports/Http_ports/HttpPort.hh 0 → 100644 +46 −0 Original line number Diff line number Diff line #pragma once #include "LibItsHttp_TestSystem.hh" #include "layer.hh" #include "params.hh" namespace LibItsHttp__TypesAndValues { class REGISTER__Request; } namespace LibItsHttp__TestSystem { class HttpPort : public HttpPort_BASE { params _cfg_params; params _layer_params; layer* _layer; std::string _time_key; public: HttpPort(const char *par_port_name); ~HttpPort(); void set_parameter(const char *parameter_name, const char *parameter_value); void receiveMsg (const LibItsHttp__TypesAndValues::REGISTER__Request&, const params&); private: /* void Handle_Fd_Event(int fd, boolean is_readable, boolean is_writable, boolean is_error); */ void Handle_Fd_Event_Error(int fd); void Handle_Fd_Event_Writable(int fd); void Handle_Fd_Event_Readable(int fd); /* void Handle_Timeout(double time_since_last_call); */ protected: void user_map(const char *system_port); void user_unmap(const char *system_port); void user_start(); void user_stop(); protected: virtual void outgoing_send(const LibItsHttp__TypesAndValues::HttpMessage& send_par) { }; }; // End of class HttpPort }
ccsrc/Protocols/Http/http_codec.cc +269 −132 Original line number Diff line number Diff line Loading @@ -7,6 +7,8 @@ #include "loggers.hh" #include "LibItsHttp_TypesAndValues.hh" #include "LibItsHttp_MessageBodyTypes.hh" #include "LibItsHttp_XmlMessageBodyTypes.hh" int http_codec::encode (const LibItsHttp__TypesAndValues::HttpMessage& msg, OCTETSTRING& data) { Loading @@ -19,7 +21,7 @@ int http_codec::encode (const LibItsHttp__TypesAndValues::HttpMessage& msg, OCTE if (msg.ischosen(LibItsHttp__TypesAndValues::HttpMessage::ALT_request)) { result = encode_request(msg.request(), encoding_buffer); } else if (msg.ischosen(LibItsHttp__TypesAndValues::HttpMessage::ALT_response)) { //result = encode_response(msg.response(), encoding_buffer); result = encode_response(msg.response(), encoding_buffer); } else { loggers::get_instance().warning("http_codec::encode: Unbound HttpMessage"); return -1; Loading Loading @@ -54,9 +56,10 @@ int http_codec::decode (const OCTETSTRING& data, LibItsHttp__TypesAndValues::Htt loggers::get_instance().log("http_codec::decode: %d - %s", m.size(), m[0].str().c_str()); if (m[0].str().compare("HTTP/") == 0) { // HTTP response LibItsHttp__TypesAndValues::Response response; std::regex rgx ("\\s*HTTP/(\\d)\\.(\\d)\\s+(\\d+)\\s+(\\w+)"); std::regex rgx ("\\s*HTTP/(\\d+)\\.(\\d+)\\s+(\\d+)\\s+(\\w+)*"); std::sregex_iterator begin(str.cbegin(), str.cend(), rgx); std::smatch m = *begin; loggers::get_instance().log("http_codec::decode: Process response: %d", m.size()); if (m.size() != 5) { loggers::get_instance().error("http_codec::decode: Unsupported tag"); return -1; Loading @@ -69,13 +72,11 @@ int http_codec::decode (const OCTETSTRING& data, LibItsHttp__TypesAndValues::Htt decode_headers(decoding_buffer, headers); response.header() = headers; loggers::get_instance().log_to_hexa("Before decoding Body: ", decoding_buffer); CHARSTRING body(""); LibItsHttp__MessageBodyTypes::HttpMessageBody body; if (decode_body(decoding_buffer, body) == -1) { response.body().set_to_omit(); } else if (body.lengthof() == 0) { response.body().set_to_omit(); } else { // TODO response.body() = OPTIONAL<LibItsHttp__MessageBodyTypes::HttpMessageBody>(body); } msg.response() = response; } else { // HTTP request Loading @@ -94,14 +95,12 @@ int http_codec::decode (const OCTETSTRING& data, LibItsHttp__TypesAndValues::Htt LibItsHttp__TypesAndValues::HeaderLines headers; decode_headers(decoding_buffer, headers); request.header() = headers; loggers::get_instance().log_to_hexa("Before decoding Body: ", decoding_buffer); CHARSTRING body(""); OPTIONAL<LibItsHttp__MessageBodyTypes::HttpMessageBody> body; body.set_to_omit(); if (decode_body(decoding_buffer, body) == -1) { request.body().set_to_omit(); } else if (body.lengthof() == 0) { request.body().set_to_omit(); } else { // TODO request.body() = body; } msg.request() = request; } Loading @@ -118,12 +117,21 @@ int http_codec::encode_request(const LibItsHttp__TypesAndValues::Request& p_requ { loggers::get_instance().log_msg(">>> http_codec::encode_request: ", (const Base_Type&)p_request); const OPTIONAL<CHARSTRING>& v = p_request.body(); CHARSTRING body(""); const OPTIONAL<LibItsHttp__MessageBodyTypes::HttpMessageBody>& v = p_request.body(); OCTETSTRING os; if (v.ispresent()) { body = static_cast<const CHARSTRING&>(*v.get_opt_value()); const LibItsHttp__MessageBodyTypes::HttpMessageBody& body = static_cast<const LibItsHttp__MessageBodyTypes::HttpMessageBody&>(*v.get_opt_value()); loggers::get_instance().log_msg("http_codec::encode_request: body: ", body); if (body.ischosen(LibItsHttp__MessageBodyTypes::HttpMessageBody::ALT_ms__body)) { os = body.ms__body(); } else { LibItsHttp__XmlMessageBodyTypes::XmlBody xml_body = body.xml__body(); if (xml_body.ischosen(LibItsHttp__XmlMessageBodyTypes::XmlBody::ALT_raw)) { os = OCTETSTRING(xml_body.raw().lengthof(), (unsigned char*)static_cast<const char*>(xml_body.raw())); } } } loggers::get_instance().log("http_codec::encode_request: HTTP message lenght: %d ", os.lengthof()); // Encode generic part p_encoding_buffer.put_cs(p_request.method()); Loading @@ -142,33 +150,106 @@ int http_codec::encode_request(const LibItsHttp__TypesAndValues::Request& p_requ p_encoding_buffer.put_cs(header.header__name()); p_encoding_buffer.put_cs(": "); if (std::string(static_cast<const char*>(header.header__name())).compare("Content-Length") == 0) { loggers::get_instance().log("http_codec::encode_request: body length: %d", body.lengthof()); p_encoding_buffer.put_cs(int2str(body.lengthof())); p_encoding_buffer.put_cs(int2str(os.lengthof() + 2/*Stand for the last CRLF*/)); _ec.is_content_length_present = 0x01; } else { if (header.header__value().size_of() > 0) { loggers::get_instance().log_msg("http_codec::encode_request: Processing value ", header.header__value()[0]); p_encoding_buffer.put_cs(header.header__value()[0]); const OPTIONAL<LibItsHttp__TypesAndValues::charstring__list>& o = header.header__value(); if (o.ispresent()) { const LibItsHttp__TypesAndValues::charstring__list& v = dynamic_cast<const OPTIONAL<LibItsHttp__TypesAndValues::charstring__list> &>(o); if (v.size_of() > 0) { loggers::get_instance().log_msg("http_codec::encode_request: Processing value ", v[0]); p_encoding_buffer.put_cs(v[0]); int j = 1; while (j < header.header__value().size_of()) { p_encoding_buffer.put_cs("; "); loggers::get_instance().log_msg("http_codec::encode_request: Processing value ", header.header__value()[j]); p_encoding_buffer.put_cs(header.header__value()[j]); while (j < v.size_of()) { p_encoding_buffer.put_cs(", "); loggers::get_instance().log_msg("http_codec::encode_request: Processing value ", v[j]); p_encoding_buffer.put_cs(v[j]); j += 1; } // End of 'while' statement } } // else, do not include it } p_encoding_buffer.put_cs("\r\n"); } // End of 'for' statement if (body.lengthof() != 0) { p_encoding_buffer.put_cs(body); p_encoding_buffer.put_cs("\r\n"); if (_ec.length != 0) { p_encoding_buffer.put_os(os); p_encoding_buffer.put_cs("\r\n"); } return 0; } int http_codec::encode_response (const LibItsHttp__TypesAndValues::Response& p_response, TTCN_Buffer& p_encoding_buffer) { loggers::get_instance().log_msg(">>> http_codec::encode_response: ", (const Base_Type&)p_response); const OPTIONAL<LibItsHttp__MessageBodyTypes::HttpMessageBody>& v = p_response.body(); OCTETSTRING os; if (v.ispresent()) { const LibItsHttp__MessageBodyTypes::HttpMessageBody& body = static_cast<const LibItsHttp__MessageBodyTypes::HttpMessageBody&>(*v.get_opt_value()); loggers::get_instance().log_msg("http_codec::encode_response: body: ", body); if (body.ischosen(LibItsHttp__MessageBodyTypes::HttpMessageBody::ALT_ms__body)) { os = body.ms__body(); } else { LibItsHttp__XmlMessageBodyTypes::XmlBody xml_body = body.xml__body(); if (xml_body.ischosen(LibItsHttp__XmlMessageBodyTypes::XmlBody::ALT_raw)) { os = OCTETSTRING(xml_body.raw().lengthof(), (unsigned char*)static_cast<const char*>(xml_body.raw())); } } } loggers::get_instance().log("http_codec::encode_response: HTTP message lenght: %d ", os.lengthof()); // Encode generic part p_encoding_buffer.put_cs("HTTP/"); p_encoding_buffer.put_cs(int2str(p_response.version__major())); p_encoding_buffer.put_c('.'); p_encoding_buffer.put_cs(int2str(p_response.version__minor())); p_encoding_buffer.put_cs(" "); p_encoding_buffer.put_cs(int2str(p_response.statuscode())); p_encoding_buffer.put_cs(" "); if (p_response.statustext().lengthof() != 0) { p_encoding_buffer.put_cs(p_response.statustext()); } p_encoding_buffer.put_cs("\r\n"); // Encode headers const LibItsHttp__TypesAndValues::HeaderLines& headers = p_response.header(); for (int i = 0; i < headers.size_of(); i++) { const LibItsHttp__TypesAndValues::HeaderLine& header = headers[i]; loggers::get_instance().log_msg("http_codec::encode_response: Processing header ", header.header__name()); p_encoding_buffer.put_cs(header.header__name()); p_encoding_buffer.put_cs(": "); if (std::string(static_cast<const char*>(header.header__name())).compare("Content-Length") == 0) { p_encoding_buffer.put_cs(int2str(os.lengthof() + 2/*Stand for the last CRLF*/)); _ec.is_content_length_present = 0x01; } else { const OPTIONAL<LibItsHttp__TypesAndValues::charstring__list>& o = header.header__value(); if (o.ispresent()) { const LibItsHttp__TypesAndValues::charstring__list& v = dynamic_cast<const OPTIONAL<LibItsHttp__TypesAndValues::charstring__list> &>(o); if (v.size_of() > 0) { loggers::get_instance().log_msg("http_codec::encode_response: Processing value ", v[0]); p_encoding_buffer.put_cs(v[0]); int j = 1; while (j < v.size_of()) { p_encoding_buffer.put_cs(", "); loggers::get_instance().log_msg("http_codec::encode_response: Processing value ", v[j]); p_encoding_buffer.put_cs(v[j]); j += 1; } // End of 'while' statement } } // else, do not include it } p_encoding_buffer.put_cs("\r\n"); } // End of 'for' statement return 0; p_encoding_buffer.put_cs("\r\n"); if (_ec.length != 0) { p_encoding_buffer.put_os(os); p_encoding_buffer.put_cs("\r\n"); } return 0; } int http_codec::decode_headers(TTCN_Buffer& decoding_buffer, LibItsHttp__TypesAndValues::HeaderLines& headers) { loggers::get_instance().log(">>> http_codec::decode_headers"); Loading @@ -194,7 +275,6 @@ int http_codec::decode_headers(TTCN_Buffer& decoding_buffer, LibItsHttp__TypesAn case -1: loggers::get_instance().warning("http_codec::decode_headers: Failed to decode headers"); return -1; } // End of 'switch' statement } // End of 'while' statement } Loading @@ -204,18 +284,28 @@ int http_codec::decode_header(CHARSTRING& header_line, LibItsHttp__TypesAndValue try { std::string str(static_cast<const char*>(header_line)); std::regex rgx ("([0-9a-zA-Z-]+)\\:\\s+(.+)(;(.+))*"); std::regex rgx ("([0-9a-zA-Z-]+)\\:\\s+(.+)(,(.+))*"); std::sregex_iterator begin(str.cbegin(), str.cend(), rgx); std::smatch m = *begin; if (m.size() < 5) { loggers::get_instance().warning("http_codec::decode_header: Failed to decode header %s", str.c_str()); return -1; } loggers::get_instance().log("http_codec::decode_header: %d", m.size()); header.header__name() = CHARSTRING(m[1].str().c_str()); LibItsHttp__TypesAndValues::charstring__list v; for (unsigned int j = 0; j < m.size(); j++) { if (m[j + 2].str().length() == 0) { break; } header.header__value()[j] = CHARSTRING(m[j + 2].str().c_str()); v[j] = CHARSTRING(m[j + 2].str().c_str()); } // End of 'for' statement header.header__value() = OPTIONAL<LibItsHttp__TypesAndValues::charstring__list>(v); if (m[1].str().compare("Content-Length") == 0) { // Save the the body length loggers::get_instance().log("http_codec::decode_header: decoded Content-Length %s", m[2].str().c_str()); _dc.length = std::stoi(m[2].str()); } return 0; } Loading @@ -224,17 +314,64 @@ int http_codec::decode_header(CHARSTRING& header_line, LibItsHttp__TypesAndValue } } int http_codec::decode_body(TTCN_Buffer& decoding_buffer, CHARSTRING& body) { int http_codec::decode_body(TTCN_Buffer& decoding_buffer, LibItsHttp__MessageBodyTypes::HttpMessageBody& message_body) { loggers::get_instance().log(">>> http_codec::decode_body"); loggers::get_instance().log_to_hexa("http_codec::decode_body", decoding_buffer); loggers::get_instance().log_msg("<<< http_codec::decode_body: ", body); // Sanity check if (decoding_buffer.get_len() - decoding_buffer.get_pos() <= 0) { return -1; } OCTETSTRING s(decoding_buffer.get_len() - decoding_buffer.get_pos(), decoding_buffer.get_data() + decoding_buffer.get_pos()); loggers::get_instance().log_msg("http_codec::decode_body: raw body=", s); // Align the payload length with the specified plLenght value loggers::get_instance().log("http_codec::decode_body: _dc.length=%d - body length=%d", _dc.length, s.lengthof()); OCTETSTRING body; if (_dc.length != 0) { const unsigned char* p = static_cast<const unsigned char *>(s); if ((unsigned int)s.lengthof() <= _dc.length) { body = OCTETSTRING(s.lengthof(), p); } else { body = OCTETSTRING(_dc.length, p); } } else { loggers::get_instance().warning("http_codec::decode_body: No Conten-Length header, process all remaining bytes"); body = s; } loggers::get_instance().log_msg("http_codec::decode_body: Aligned body=", body); // Remove CRLF if any int counter = 0; if ((body[body.lengthof() - 1].get_octet() == 0x0d) || (body[body.lengthof() - 1].get_octet() == 0x0a)) { counter += 1; if ((body[body.lengthof() - 2].get_octet() == 0x0d) || (body[body.lengthof() - 2].get_octet() == 0x0a)) { counter += 1; } } loggers::get_instance().log("http_codec::decode_body: Counter=%d", counter); body = OCTETSTRING(body.lengthof() - counter, static_cast<const unsigned char*>(body)); loggers::get_instance().log_msg("http_codec::decode_body: Finalised body=", body); // Check if HTTP message body contains binary characters for (int i = 0; i < body.lengthof(); i++) { unsigned char c = body[i].get_octet(); if (!std::isprint(c) && !std::isspace(c) && !std::ispunct(c)) { loggers::get_instance().log("http_codec::decode_body: Byte #%d is not printable: 0x%02x", i, body[i].get_octet()); _dc.is_binary = 0x01; break; } } // End of 'for' statement loggers::get_instance().log("http_codec::decode_body: Binary mode: %x", _dc.is_binary); LibItsHttp__MessageBodyTypes::HttpMessageBody v; if (_dc.is_binary == 0x01) { message_body.ms__body() = body; } else { LibItsHttp__XmlMessageBodyTypes::XmlBody xml_body; xml_body.raw() = CHARSTRING(body.lengthof(), (char*)static_cast<const unsigned char*>(body)); message_body.xml__body() = xml_body; } return 0; } int http_codec::get_line(TTCN_Buffer& buffer, CHARSTRING& to, const bool concatenate_header_lines) { unsigned int i = 0; Loading @@ -246,7 +383,7 @@ int http_codec::get_line(TTCN_Buffer& buffer, CHARSTRING& to, const bool concate } while (true) { // Skip spaces, and emplty lines // Skip spaces, and empty lines for( ; i < buffer.get_read_len() && cc_to[i] != '\0' && cc_to[i] != '\r' && cc_to[i] != '\n'; i++); if(i >= buffer.get_read_len()) { // No more characters to process to = CHARSTRING(""); Loading
ccsrc/Protocols/Http/http_codec.hh +22 −3 Original line number Diff line number Diff line Loading @@ -14,13 +14,32 @@ namespace LibItsHttp__TypesAndValues { class HeaderLines; class HeaderLine; } namespace LibItsHttp__MessageBodyTypes { class HttpMessageBody; } struct encoding_context { unsigned int length; unsigned char is_content_length_present; encoding_context() { length = -1; is_content_length_present = 0x00; }; }; struct decoding_context { unsigned int length; unsigned char is_binary; decoding_context() { length = -1; is_binary = 0x00; }; }; class http_codec: public codec < LibItsHttp__TypesAndValues::HttpMessage, LibItsHttp__TypesAndValues::HttpMessage> { encoding_context _ec; decoding_context _dc; public: explicit http_codec() : codec<LibItsHttp__TypesAndValues::HttpMessage, LibItsHttp__TypesAndValues::HttpMessage>() { }; explicit http_codec() : codec<LibItsHttp__TypesAndValues::HttpMessage, LibItsHttp__TypesAndValues::HttpMessage>(), _ec(), _dc() { }; virtual ~http_codec() { }; virtual int encode (const LibItsHttp__TypesAndValues::HttpMessage&, OCTETSTRING& data); Loading @@ -28,11 +47,11 @@ public: private: int encode_request (const LibItsHttp__TypesAndValues::Request& p_request, TTCN_Buffer& p_encoding_buffer); // int encode_response (const LibItsHttp__TypesAndValues::Request&, TTCN_Buffer& p_encoding_buffer); int encode_response (const LibItsHttp__TypesAndValues::Response& p_response, TTCN_Buffer& p_encoding_buffer); int decode_headers(TTCN_Buffer& decoding_buffer, LibItsHttp__TypesAndValues::HeaderLines& headers); int decode_header(CHARSTRING& header_line, LibItsHttp__TypesAndValues::HeaderLine& header); int decode_body(TTCN_Buffer& decoding_buffer, CHARSTRING& body); int decode_body(TTCN_Buffer& decoding_buffer, LibItsHttp__MessageBodyTypes::HttpMessageBody& message_body); int get_line(TTCN_Buffer& buffer, CHARSTRING& to, const bool concatenate_header_lines = false); }; // End of class http_codec