diff --git a/LICENSE b/LICENSE index 2df8cd5739a1fe4d30ffbd6173ee851da799218a..064741ac0f59516ebe155c4a85cb177e19312e99 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright 2022 ETSI +Copyright 2019-2024 ETSI Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/README.md b/README.md index a34e5d3e2725885ac55453c49cf7bece4f146475..83a0b519d109807e62c79bb38dedf0d4b2106742 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,61 @@ # TITAN Test System Framework +## Introduction This module provides the bases to start the development of any Conformance Testing project or Interoperability Testing project. It contains: - A set C/C++ modules such as logging, codec support, -- A set of TTCN-3 modules such as LibHttp +- A set of TTCN-3 modules such as LibHelper or LibHttp +## How to use it +### The layers + +The purpose of a lower test adapter is to prepare and adapt the protocol messages used by TTCN-3 test suites so that they can be transmitted successfully to the SUT. +The lower layers implement and encapsulate protocol messages accordingly. For instance, TCP need to be encapsulated into IP layer and ETHERNET layer. +Each Layer is responsible for encapsulating and decapsulating packets and transmitting result to lower using send_data()/receive_data() methods + +#### Final layers + +The final layer is where the physical communication is done. PCAP is an example a the final layer: this layer read and write data to the network interface controller (NIC). +Some final layer such as PCAP, PCAP_OFFLINE, SCTP are provided by this framework to facilitate the development of the Test Adapter. + +#### Layers + +Some layers such as ETHERNET, IP, TCP or UDP are provided by this framework to facilitate the development of the Test Adapter. + +### The C++ libraries + +This framework provides some C++ and TTCN-3 libraries such as layer parameters processor (class params), base time (class base_time), basic data convertions (class converter). +These classes can be derived to enhance and add new functionalities. + +### The external functions + +This framework provides some useful TTCN-3 external function such as time access (e.g. fx__getCurrentTimeUtc) or base 64 encoding/decoding. + +### The logger class + +This class provides a logging framework with log levels and some special features such as hexadecimal dump of TITAN data structure logging (e.g. RECORD...). + +### The TTCN-3 libraries + +This framework provides some TTCN-3 libraries such as LibXSD, libHTTP or LibJson. +These libraries provides the typing and the templates to manipulate these protocols. +They can be used and extend to enhance and add new typings and functionalities. + +### The LibSecurity + +This libraries provides the minimal set of functionalities such SHA and HMAC computing, Signature and Certificates manipulations. + +## How to add it in your project + +When you create your project, you just need to add it as a GIT submodule: + +```bash +$ git submodule add --branch devel https://labs.etsi.org/rep/cti-tools/titan-test-system-framework.git ./titan-test-system-framework +$ git submodule init +$ git submodule update +$ git add . +$ git commit -a -m "Added submodule titan-test-system-framework" +$ git push +``` diff --git a/ccsrc/Framework/include/converter.hh b/ccsrc/Framework/include/converter.hh index cdb29e94bc4cfa2d5adcff218c8198d93ce6091b..3b06379b5f6b66db7bef9c93636b11c1c4eb2400 100644 --- a/ccsrc/Framework/include/converter.hh +++ b/ccsrc/Framework/include/converter.hh @@ -380,14 +380,22 @@ public: * \param[in] p_value The buffer value * \return The Base64 encoded buffert */ - std::vector buffer_to_base64(const std::vector &p_value, const bool p_is_url = false); + std::vector buffer_to_base64(const std::vector &p_value, const bool p_is_url = false); /*! * \brief Convert the provided Base64 buffer * \param[in] p_value The buffer value * \return The Base64 encoded buffert */ - std::vector base64_to_buffer(const std::vector &p_value, const bool p_remove_crlf = true); + std::vector base64_to_buffer(const std::vector &p_value, const bool p_remove_crlf = true); + + /*! + * \brief Split a string line by line + * \param[in] p_input The buffer value + * \return The lines list + */ + std::vector split_lines(const std::string& p_input); + static const std::string lut_u; static const std::string lut_l; diff --git a/ccsrc/Framework/include/params.hh b/ccsrc/Framework/include/params.hh index bc683cfe98daed266062f38488ccb8722c3bc5e1..9dc4b61c9f62d2e5e61e6b9e9a35a62a0e9843a2 100644 --- a/ccsrc/Framework/include/params.hh +++ b/ccsrc/Framework/include/params.hh @@ -35,6 +35,10 @@ public: //! \publicsection static const std::string& nic; //! Network Interface Card parameter name + static const std::string& ip_src; //! Source IP address parameter name + static const std::string& ip_dst; //! Destination IP address parameter name + static const std::string& ip_proto; //! IP proto parameter name + static const std::string& server; //! Remote server address (e.g. www.etsi.org) static const std::string& port; //! Remote server port. Default: 80 static const std::string& use_ssl; //! Set to 1 to use SSL to communicate with the HTTP server. Default: false diff --git a/ccsrc/Framework/src/converter.cc b/ccsrc/Framework/src/converter.cc index 9df0ad962ba26aa7ebd97530983c22be8d3ecfc5..55dec95c02e9b403c07735eb51155e8366faaf4c 100644 --- a/ccsrc/Framework/src/converter.cc +++ b/ccsrc/Framework/src/converter.cc @@ -159,13 +159,13 @@ const std::string converter::base64_enc_map[2] = { * @param[in] chr * @return Return the position of chr within base64_encode() */ -static unsigned char pos_of_char(const unsigned char chr) { +static uint8_t pos_of_char(const uint8_t chr) { if ((chr >= 'A' && chr <= 'Z')) { - return static_cast(chr - 'A'); + return static_cast(chr - 'A'); } else if ((chr >= 'a' && chr <= 'z')) { - return static_cast(chr - 'a' + ('Z' - 'A') + 1); + return static_cast(chr - 'a' + ('Z' - 'A') + 1); } else if ((chr >= '0' && chr <= '9')) { - return static_cast(chr - '0' + ('Z' - 'A') + ('z' - 'a') + 2); + return static_cast(chr - '0' + ('Z' - 'A') + ('z' - 'a') + 2); } else if ((chr == '+' || chr == '-')) { return 62; // Be liberal with input and accept both url ('-') and non-url ('+') base 64 characters ( } else if ((chr == '/' || chr == '_')) { @@ -197,11 +197,11 @@ std::string converter::replace(const std::string& p_value, const std::string& p_ return str; } -std::vector converter::buffer_to_base64(const std::vector &p_value, const bool p_is_url) { +std::vector converter::buffer_to_base64(const std::vector &p_value, const bool p_is_url) { const std::string& base64_enc_map_ = converter::base64_enc_map[(p_is_url) ? 1 : 0]; - const unsigned char trailing_char = (p_is_url) ? '.' : '='; + const uint8_t trailing_char = (p_is_url) ? '.' : '='; - std::vector out; + std::vector out; //out.resize((p_value.size() + 2) / 3 * 4); unsigned int pos = 0; @@ -229,19 +229,19 @@ std::vector converter::buffer_to_base64(const std::vector converter::base64_to_buffer(const std::vector &p_value, const bool p_remove_crlf) { +std::vector converter::base64_to_buffer(const std::vector &p_value, const bool p_remove_crlf) { if (p_value.size() == 0) { - return std::vector(); + return std::vector(); } - std::vector value(p_value); + std::vector value(p_value); if (p_remove_crlf) { value.erase(std::remove(value.begin(), value.end(), '\r'), value.end()); value.erase(std::remove(value.begin(), value.end(), '\n'), value.end()); } - std::vector out; + std::vector out; //out.resize(value.size() / 4 * 3); size_t pos = 0; @@ -268,3 +268,17 @@ std::vector converter::base64_to_buffer(const std::vector +#include +#include + +std::vector converter::split_lines(const std::string& p_input) { + std::vector lines; + std::istringstream stream(p_input); + std::string line; + while (std::getline(stream, line)) { + lines.push_back(line); + } + return lines; +} diff --git a/ccsrc/Framework/src/params.cc b/ccsrc/Framework/src/params.cc index a18371414d5992bb40be3c8733784f0666d323cf..bc4ebb8d166da75dcb147c8d53efd7d5cd78cfb1 100644 --- a/ccsrc/Framework/src/params.cc +++ b/ccsrc/Framework/src/params.cc @@ -28,6 +28,10 @@ const std::string& params::filter = std::string("filter"); const std::string& params::nic = std::string("nic"); +const std::string& params::ip_src = std::string("ip_src"); +const std::string& params::ip_dst = std::string("ip_dst"); +const std::string& params::ip_proto = std::string("ip_proto"); + const std::string& params::server = std::string("server"); const std::string& params::port = std::string("port"); const std::string& params::use_ssl = std::string("use_ssl"); diff --git a/ccsrc/Helpers/helpers_externals.cc b/ccsrc/Helpers/helpers_externals.cc index 37d1f3e62e5096219539d0b6e8ac4573edf85b84..bd77abc2355999418bcb8eaef219ce0e10506474 100644 --- a/ccsrc/Helpers/helpers_externals.cc +++ b/ccsrc/Helpers/helpers_externals.cc @@ -57,8 +57,8 @@ namespace LibHelpers__Functions { OCTETSTRING fx__enc__base64(const OCTETSTRING& p_to_encode) { loggers::get_instance().log_msg(">>> fx__enc__base64: ", p_to_encode); - const std::vector to_encode(static_cast(p_to_encode), static_cast(p_to_encode) + p_to_encode.lengthof()); - std::vector b64 = converter::get_instance().buffer_to_base64(to_encode); + const std::vector to_encode(static_cast(p_to_encode), static_cast(p_to_encode) + p_to_encode.lengthof()); + std::vector b64 = converter::get_instance().buffer_to_base64(to_encode); OCTETSTRING os(b64.size(), b64.data()); loggers::get_instance().log_msg("<<< fx__enc__base64: ", os); return os; @@ -72,18 +72,18 @@ namespace LibHelpers__Functions { OCTETSTRING fx__dec__base64(const OCTETSTRING& p_to_decode) { loggers::get_instance().log_msg(">>> fx__dec__base64: ", p_to_decode); - const std::vector to_decode(static_cast(p_to_decode), static_cast(p_to_decode) + p_to_decode.lengthof()); - std::vector b64 = converter::get_instance().base64_to_buffer(to_decode); + const std::vector to_decode(static_cast(p_to_decode), static_cast(p_to_decode) + p_to_decode.lengthof()); + std::vector b64 = converter::get_instance().base64_to_buffer(to_decode); OCTETSTRING os(b64.size(), b64.data()); loggers::get_instance().log_msg("<<< fx__dec__base64: ", os); return os; } - static unsigned char random_char() { + static uint8_t random_char() { std::random_device rd; std::mt19937 gen(rd()); std::uniform_int_distribution<> dis(0, 255); - return static_cast(dis(gen)); + return static_cast(dis(gen)); } static std::string generate_hex(const unsigned int len) { diff --git a/ccsrc/Protocols/ETH/ethernet_layer.cc b/ccsrc/Protocols/ETH/ethernet_layer.cc index 0b6bff730f4ffb7a8aea986f5be4727a50d6a1a0..1261675cf4fc5e3b5dab4237c74f6fd46ce9fc67 100644 --- a/ccsrc/Protocols/ETH/ethernet_layer.cc +++ b/ccsrc/Protocols/ETH/ethernet_layer.cc @@ -60,15 +60,15 @@ void ethernet_layer::receive_data(OCTETSTRING& p_data, params& p_params) { loggers::get_instance().log_msg(">>> ethernet_layer::receive_data: ", p_data); // Extract dest MAC Address - OCTETSTRING dst = OCTETSTRING(6, static_cast(p_data)); + OCTETSTRING dst = OCTETSTRING(6, static_cast(p_data)); //loggers::get_instance().log_msg("ethernet_layer::receive_data: dst: ", dst); // Extract source MAC Address - OCTETSTRING src = OCTETSTRING(6, 6 + static_cast(p_data)); + OCTETSTRING src = OCTETSTRING(6, 6 + static_cast(p_data)); //loggers::get_instance().log_msg("ethernet_layer::receive_data: src: ", src); // Extract ethertype - OCTETSTRING proto = OCTETSTRING(2, 2 + static_cast(p_data)); + OCTETSTRING proto = OCTETSTRING(2, 2 + static_cast(p_data)); //loggers::get_instance().log_msg("ethernet_layer::receive_data: proto: ", proto); - OCTETSTRING data = OCTETSTRING(p_data.lengthof() - 14, 14 + static_cast(p_data)); + OCTETSTRING data = OCTETSTRING(p_data.lengthof() - 14, 14 + static_cast(p_data)); // Update params CHARSTRING s = oct2str(dst); p_params.insert(std::pair(params::mac_dst, std::string(static_cast(s)))); diff --git a/ccsrc/Protocols/ETH/ethernet_layer.hh b/ccsrc/Protocols/ETH/ethernet_layer.hh index 57ae7c2e203d3dcab61aa2887afb041ef1a2cfab..4267421b18436620ba59030172888e4c46ad4b5f 100644 --- a/ccsrc/Protocols/ETH/ethernet_layer.hh +++ b/ccsrc/Protocols/ETH/ethernet_layer.hh @@ -1,7 +1,7 @@ /*! - * \file udp_layer.hh - * \brief Header file for ITS UDP/IP protocol layer definition. - * \author ETSI STF525 + * \file ethernet_layer.hh + * \brief Header file for Ethernet protocol layer definition. + * \author ETSI TTF T048 * \copyright ETSI Copyright Notification * No part may be reproduced except as authorized by written permission. * The copyright and the foregoing restriction extend to reproduction in all media. diff --git a/ccsrc/Protocols/Http/http_codec.cc b/ccsrc/Protocols/Http/http_codec.cc index bd1363218fd9b5ee87ea487782877a5132ad4648..8db299f898325cccd8d0b4353a760fff070b1174 100644 --- a/ccsrc/Protocols/Http/http_codec.cc +++ b/ccsrc/Protocols/Http/http_codec.cc @@ -512,7 +512,7 @@ int http_codec::encode_body(const LibHttp__MessageBodyTypes::HttpMessageBody &p_ if (p_message_body.ischosen(LibHttp__MessageBodyTypes::HttpMessageBody::ALT_binary__body)) { const LibHttp__BinaryMessageBodyTypes::BinaryBody &binary_body = p_message_body.binary__body(); if (binary_body.ischosen(LibHttp__BinaryMessageBodyTypes::BinaryBody::ALT_raw)) { - p_encoding_buffer = OCTETSTRING(binary_body.raw().lengthof(), (unsigned char *)static_cast(binary_body.raw())); + p_encoding_buffer = OCTETSTRING(binary_body.raw().lengthof(), (uint8_t *)static_cast(binary_body.raw())); } else { encode_body_binary(binary_body, p_encoding_buffer, p_content_type); } @@ -526,14 +526,14 @@ int http_codec::encode_body(const LibHttp__MessageBodyTypes::HttpMessageBody &p_ } else if (p_message_body.ischosen(LibHttp__MessageBodyTypes::HttpMessageBody::ALT_xml__body)) { const LibHttp__XmlMessageBodyTypes::XmlBody &xml_body = p_message_body.xml__body(); if (xml_body.msg().ischosen(LibHttp__XmlMessageBodyTypes::XmlBodyMsg::ALT_raw)) { - p_encoding_buffer = OCTETSTRING(xml_body.msg().raw().lengthof(), (unsigned char *)static_cast(xml_body.msg().raw())); + p_encoding_buffer = OCTETSTRING(xml_body.msg().raw().lengthof(), (uint8_t *)static_cast(xml_body.msg().raw())); } else { encode_body_xml(xml_body, p_encoding_buffer, p_content_type); } } else if (p_message_body.ischosen(LibHttp__MessageBodyTypes::HttpMessageBody::ALT_html__body)) { - p_encoding_buffer = OCTETSTRING(p_message_body.html__body().lengthof(), (unsigned char *)static_cast(p_message_body.html__body())); + p_encoding_buffer = OCTETSTRING(p_message_body.html__body().lengthof(), (uint8_t *)static_cast(p_message_body.html__body())); } else if (p_message_body.ischosen(LibHttp__MessageBodyTypes::HttpMessageBody::ALT_text__body)) { - p_encoding_buffer = OCTETSTRING(p_message_body.text__body().lengthof(), (unsigned char *)static_cast(p_message_body.text__body())); + p_encoding_buffer = OCTETSTRING(p_message_body.text__body().lengthof(), (uint8_t *)static_cast(p_message_body.text__body())); } else { loggers::get_instance().warning("http_codec::encode_body: Failed to encode HTTP message body"); return -1; @@ -567,7 +567,7 @@ int http_codec::decode_body(TTCN_Buffer &decoding_buffer, LibHttp__MessageBodyTy 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(s); + const uint8_t *p = static_cast(s); if ((unsigned int)s.lengthof() <= _dc.length) { body = OCTETSTRING(s.lengthof(), p); } else { @@ -589,7 +589,7 @@ int http_codec::decode_body(TTCN_Buffer &decoding_buffer, LibHttp__MessageBodyTy } } loggers::get_instance().log("http_codec::decode_body: counter=%d", counter); - body = OCTETSTRING(body.lengthof() - counter, static_cast(body)); + body = OCTETSTRING(body.lengthof() - counter, static_cast(body)); */ if (_dc.chunked) { int counter = 0; @@ -605,9 +605,9 @@ int http_codec::decode_body(TTCN_Buffer &decoding_buffer, LibHttp__MessageBodyTy loggers::get_instance().log("http_codec::decode_body: Chunked(0): prev = %d, counter=%d / %d", prev, counter, body.lengthof()); if (counter < body.lengthof()) { int idx = counter - prev; - OCTETSTRING trunk(idx, static_cast(body)); + OCTETSTRING trunk(idx, static_cast(body)); loggers::get_instance().log_msg("http_codec::decode_body: trunk: ", trunk); - std::string str((const char *)static_cast(trunk), idx); + std::string str((const char *)static_cast(trunk), idx); loggers::get_instance().log("http_codec::decode_body: str: '%s'", str.c_str()); int len = std::stoi(str, nullptr, 16); // converter::get_instance().string_to_int(str); loggers::get_instance().log("http_codec::decode_body: Chunk len: %d", len); @@ -616,7 +616,7 @@ int http_codec::decode_body(TTCN_Buffer &decoding_buffer, LibHttp__MessageBodyTy } // End of 'while' statement if (counter < body.lengthof()) { loggers::get_instance().log("http_codec::decode_body: Chunked (1): prev = %d, counter=%d / %d", prev, counter, body.lengthof()); - os += OCTETSTRING(len, counter + static_cast(body)); + os += OCTETSTRING(len, counter + static_cast(body)); loggers::get_instance().log_msg("http_codec::decode_body: os=", os); counter += len; loggers::get_instance().log("http_codec::decode_body: Chunked: %02x %02x %02x", body[counter].get_octet(), body[counter + 1].get_octet(), @@ -635,7 +635,7 @@ int http_codec::decode_body(TTCN_Buffer &decoding_buffer, LibHttp__MessageBodyTy } // Check if HTTP message body contains binary characters for (int i = 0; i < body.lengthof(); i++) { - unsigned char c = body[i].get_octet(); + uint8_t 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; @@ -651,7 +651,7 @@ int http_codec::decode_body(TTCN_Buffer &decoding_buffer, LibHttp__MessageBodyTy } else { // Convert into string params p; - p["decode_str"] = std::string(static_cast(body), body.lengthof() + static_cast(body)); + p["decode_str"] = std::string(static_cast(body), body.lengthof() + static_cast(body)); loggers::get_instance().log("http_codec::decode_body: decode_str: '%s'", p["decode_str"].c_str()); // Try to identify xml if (p["decode_str"].find("") != std::string::npos) { // Try to identify HTML + } else if (p["decode_str"].find("(body)); + message_body.text__body() = CHARSTRING(body.lengthof(), (char *)static_cast(body)); } } @@ -681,7 +681,7 @@ int http_codec::decode_body(TTCN_Buffer &decoding_buffer, LibHttp__MessageBodyTy int http_codec::get_line(TTCN_Buffer &buffer, CHARSTRING &to, const bool concatenate_header_lines) { unsigned int i = 0; - const unsigned char *cc_to = buffer.get_read_data(); + const uint8_t *cc_to = buffer.get_read_data(); // Sanity checks if (buffer.get_read_len() == 0) { @@ -755,6 +755,6 @@ void http_codec::set_payload_codecs(const std::string& p_codecs) { } bool http_codec::decode_body_html(const OCTETSTRING &p_data, CHARSTRING &p_html_body, const std::string& p_content_type, params* p_params) { - p_html_body = CHARSTRING(p_data.lengthof(), (char*)static_cast(p_data)); + p_html_body = CHARSTRING(p_data.lengthof(), (char*)static_cast(p_data)); return true; } diff --git a/ccsrc/Protocols/Http/http_codec.hh b/ccsrc/Protocols/Http/http_codec.hh index 37f313cc9c3fccfe4e6e2544d6dc3953c509b2a1..2e675c96405df6bd16123a410c2dbd762160b60e 100644 --- a/ccsrc/Protocols/Http/http_codec.hh +++ b/ccsrc/Protocols/Http/http_codec.hh @@ -33,7 +33,7 @@ namespace LibHttp__JsonMessageBodyTypes { struct encoding_context { unsigned int length; - unsigned char is_content_length_present; + uint8_t is_content_length_present; encoding_context() { reset(); }; void reset() { @@ -44,7 +44,7 @@ struct encoding_context { struct decoding_context { unsigned int length; - unsigned char is_binary; + uint8_t is_binary; bool chunked; decoding_context() { reset(); }; diff --git a/ccsrc/Protocols/IP/ip_offline_layer.cc b/ccsrc/Protocols/IP/ip_offline_layer.cc new file mode 100644 index 0000000000000000000000000000000000000000..8dd8b8d9c5acd531c777f3ddc321383bc102f017 --- /dev/null +++ b/ccsrc/Protocols/IP/ip_offline_layer.cc @@ -0,0 +1,126 @@ +#include +#include + +#include "ip_offline_layer_factory.hh" + +#include "loggers.hh" + +ip_offline_layer::ip_offline_layer(const std::string& p_type, const std::string& p_param) : layer(p_type), _params() { + loggers::get_instance().log(">>> ip_offline_layer::ip_offline_layer: '%s', %s", to_string().c_str(), p_param.c_str()); + // Setup parameters + params::convert(_params, p_param); +} + +void ip_offline_layer::send_data(OCTETSTRING& p_data, params& p_params) { + loggers::get_instance().log_msg(">>> ip_offline_layer::send_data: ", p_data); + p_params.log(); + + // FIXME FSCOM: To be done + TTCN_Buffer ip; + ip.put_c(0x45); // Protocol version + ip.put_c(0x02); // Flags + unsigned short l = p_data.lengthof(); + ip.put_c(l >> 8 & 0xFF); // Data length + ip.put_c(l & 0xFF); // Data length + ip.put_c(0x00); ip.put_c(0x00); // Identification + ip.put_c(0x40); ip.put_c(0x00); // Flags (Don't fragment) + ip.put_c(0x40); // TTL + ip.put_c(132); // Protocol is SCTP + OCTETSTRING checksum = int2oct(0, 2); // Checksum + ip.put_s(checksum.lengthof(), static_cast(checksum)); + + int addr = htonl(get_host_id("localhost"/*_params["dst_ip"]*/)); + OCTETSTRING ip_addr = int2oct(addr, 4); // Source address + ip.put_s(ip_addr.lengthof(), static_cast(ip_addr)); + ip_addr = int2oct(addr, 4); // Destination address + ip.put_s(ip_addr.lengthof(), static_cast(ip_addr)); + + OCTETSTRING ip_pdu(ip.get_read_len(), ip.get_data()); + ip_pdu += p_data; + + send_to_all_layers(ip_pdu, static_cast(p_params)); +} + +void ip_offline_layer::receive_data(OCTETSTRING& p_data, params& p_params) { + loggers::get_instance().log_msg(">>> ip_offline_layer::receive_data: ", p_data); + + // Version + uint8_t v = static_cast(*p_data); + OCTETSTRING version = int2oct((v >> 4) & 0x0f, 1); + loggers::get_instance().log_msg("ip_offline_layer::receive_data: verion: ", version); + // Length in bytes + uint8_t length = (v & 0x0f) * 4; + loggers::get_instance().log("ip_offline_layer::receive_data: length: %d", length); + // DSF + OCTETSTRING dsf = OCTETSTRING(1, 1 + static_cast(p_data)); + loggers::get_instance().log_msg("ip_offline_layer::receive_data: dsf: ", dsf); + // Total Length + OCTETSTRING total_length = OCTETSTRING(2, 2 + static_cast(p_data)); + loggers::get_instance().log_msg("ip_offline_layer::receive_data: total_length: ", total_length); + // Identification + OCTETSTRING id = OCTETSTRING(2, 4 + static_cast(p_data)); + loggers::get_instance().log_msg("ip_offline_layer::receive_data: id: ", id); + // Flags + OCTETSTRING flags = OCTETSTRING(2, 6 + static_cast(p_data)); + loggers::get_instance().log_msg("ip_offline_layer::receive_data: id: ", flags); + // TTL + OCTETSTRING ttl = OCTETSTRING(1, 8 + static_cast(p_data)); + loggers::get_instance().log_msg("ip_offline_layer::receive_data: ttl: ", ttl); + // Protocol + OCTETSTRING protocol = OCTETSTRING(1, 9 + static_cast(p_data)); + loggers::get_instance().log_msg("ip_offline_layer::receive_data: protocol: ", protocol); + // checksum + OCTETSTRING checksum = OCTETSTRING(2, 10 + static_cast(p_data)); + loggers::get_instance().log_msg("ip_offline_layer::receive_data: checksum: ", checksum); + // src + OCTETSTRING src = OCTETSTRING(4, 12 + static_cast(p_data)); + loggers::get_instance().log_msg("ip_offline_layer::receive_data: src: ", src); + // dst + OCTETSTRING dst = OCTETSTRING(4, 16 + static_cast(p_data)); + loggers::get_instance().log_msg("ip_offline_layer::receive_data: dst: ", dst); + + OCTETSTRING data = OCTETSTRING(p_data.lengthof() - length, length + static_cast(p_data)); + loggers::get_instance().log_msg("ip_offline_layer::receive_data: payload for upper layer:", data); + + // Update params + CHARSTRING s = oct2str(dst); + p_params.insert(std::pair(params::ip_dst, std::string(static_cast(s)))); + s = oct2str(src); + p_params.insert(std::pair(params::ip_src, std::string(static_cast(s)))); + s = oct2str(protocol); + p_params.insert(std::pair(params::ip_proto, std::string(static_cast(s)))); + + receive_to_all_layers(data, static_cast(p_params)); +} + +unsigned long ip_offline_layer::get_host_id(const std::string& p_host_name) { + loggers::get_instance().log(">>> ip_offline_layer::get_host_id"); + + if (p_host_name.empty()) { + loggers::get_instance().warning("ip_offline_layer::get_host_id: Wrong parameter"); + return INADDR_ANY; + } + + unsigned long ip_addr = 0; + if (p_host_name.compare("255.255.255.255") == 0) { + loggers::get_instance().warning("ip_offline_layer::get_host_id: Host ip is 255.255.255.255"); + ip_addr = 0xffffffff; + } else { + in_addr_t addr = ::inet_addr(p_host_name.c_str()); + if (addr != (in_addr_t)-1) { // host name in XX:XX:XX:XX form + ip_addr = addr; + } else { // host name in domain.com form + struct hostent *hptr; + if ((hptr = ::gethostbyname(p_host_name.c_str())) == 0) { + loggers::get_instance().error("ip_offline_layer::get_host_id: Invalid host name: '%s'", p_host_name.c_str()); + } + ip_addr = *((unsigned long *)hptr->h_addr_list[0]); + } + } + + loggers::get_instance().log("ip_offline_layer::get_host_id: Host name: '%s', Host address: %u", p_host_name.c_str(), ip_addr); + + return htonl(ip_addr); +} + +ip_offline_layer_factory ip_offline_layer_factory::_f; diff --git a/ccsrc/Protocols/IP/ip_offline_layer.hh b/ccsrc/Protocols/IP/ip_offline_layer.hh new file mode 100644 index 0000000000000000000000000000000000000000..352ddbc871f5f3997346fc5d3f85f44b9319eb0d --- /dev/null +++ b/ccsrc/Protocols/IP/ip_offline_layer.hh @@ -0,0 +1,51 @@ +/*! + * \file ip_offline_layer.hh + * \brief Header file for ITS IP protocol layer definition. + * \author ETSI TTF T041 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#pragma once + +#include "params.hh" +#include "t_layer.hh" + +class ip_offline_layer : public layer { + params _params; //! Layer parameters + +private: //! \privatesection + unsigned long get_host_id(const std::string& p_host_name); + +public: //! \publicsection + /*! + * \brief Specialised constructor + * Create a new instance of the ip_offline_layer class + * \param[in] p_type \todo + * \param[in] p_param \todo + */ + ip_offline_layer(const std::string& p_type, const std::string& p_param); + /*! + * \brief Default destructor + */ + virtual ~ip_offline_layer(){}; + + /*! + * \virtual + * \fn void send_data(OCTETSTRING& data, params& p_params); + * \brief Send bytes formated data to the lower layers + * \param[in] p_data The data to be sent + * \param[in] p_params Some parameters to overwrite default value of the lower layers parameters + */ + virtual void send_data(OCTETSTRING& p_data, params& p_params); + /*! + * \virtual + * \fn void receive_data(OCTETSTRING& data, params& p_params); + * \brief Receive bytes formated data from the lower layers + * \param[in] p_data The bytes formated data received + * \param[in] p_params Some lower layers parameters values when data was received + */ + virtual void receive_data(OCTETSTRING& p_data, params& p_params); +}; // End of class ip_offline_layer diff --git a/ccsrc/Protocols/IP/ip_offline_layer_factory.hh b/ccsrc/Protocols/IP/ip_offline_layer_factory.hh new file mode 100644 index 0000000000000000000000000000000000000000..9a408415b36886fb40343dcf3bc023de83629037 --- /dev/null +++ b/ccsrc/Protocols/IP/ip_offline_layer_factory.hh @@ -0,0 +1,42 @@ +/*! + * \file ip_offline_layer_factory.hh + * \brief Header file for ITS Ethernet protocol layer factory. + * \author ETSI TTF T041 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#pragma once + +#include "layer_stack_builder.hh" + +#include "ip_offline_layer.hh" + +/*! + * \class ip_offline_layer_factory + * \brief This class provides a factory class to create an ip_offline_layer class instance + */ +class ip_offline_layer_factory : public layer_factory { + static ip_offline_layer_factory _f; //! Reference to the unique instance of this class +public: //! \publicsection + /*! + * \brief Default constructor + * Create a new instance of the ip_offline_layer_factory class + * \remark The ETH layer identifier is ETH + */ + ip_offline_layer_factory() { + // register factory + layer_stack_builder::register_layer_factory("IP_OFFLINE", this); + }; + /*! + * \fn layer* create_layer(const std::string& type, const std::string& param); + * \brief Create the layers stack based on the provided layers stack description + * \param[in] p_type The provided layers stack description + * \param[in] p_params Optional parameters + * \return 0 on success, -1 otherwise + * \inline + */ + inline virtual layer *create_layer(const std::string& p_type, const std::string& p_param) { return new ip_offline_layer(p_type, p_param); }; +}; // End of class ip_offline_layer_factory diff --git a/ccsrc/Protocols/IP/module.mk b/ccsrc/Protocols/IP/module.mk new file mode 100644 index 0000000000000000000000000000000000000000..d53608b8ba96269fc58381b726346300cc7b5760 --- /dev/null +++ b/ccsrc/Protocols/IP/module.mk @@ -0,0 +1,3 @@ +sources := ip_offline_layer.cc +includes := . + diff --git a/ccsrc/Protocols/Json/json_codec.cc b/ccsrc/Protocols/Json/json_codec.cc new file mode 100644 index 0000000000000000000000000000000000000000..c4c1e39dbf577a08d3b8dbd0f654cfe0794639dd --- /dev/null +++ b/ccsrc/Protocols/Json/json_codec.cc @@ -0,0 +1,69 @@ +#include +#include +#include + +#include "json_codec_factory.hh" + +#include "loggers.hh" + +#include "LibHttp_JsonMessageBodyTypes.hh" + +int json_codec::encode(const LibHttp__JsonMessageBodyTypes::JsonBody &msg, OCTETSTRING &data) +{ + loggers::get_instance().log_msg(">>> json_codec::encode: ", (const Base_Type &)msg); + + TTCN_EncDec::clear_error(); + TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_DEFAULT); + TTCN_Buffer encoding_buffer; + + loggers::get_instance().error("json_codec::encode: Not supported"); + + loggers::get_instance().log("<<< json_codec::encode"); + return 0; +} + +int json_codec::decode(const OCTETSTRING &p_data, LibHttp__JsonMessageBodyTypes::JsonBody &msg, params *p_params) +{ + loggers::get_instance().log_msg(">>> json_codec::decode: p_data=", p_data); + + // Sanity checks + params::const_iterator it; + if (p_params == nullptr) + { + loggers::get_instance().warning("json_codec::decode: Failed to access p_params (null pointer)"); + return -1; // TODO Use p_data instead of return -1 + } + else + { + it = p_params->find("decode_str"); + if (it == p_params->cend()) + { + loggers::get_instance().warning("json_codec::decode: Failed to access p_params item (decode_str)"); + return -1; // TODO Use p_data instead of return -1 + } + loggers::get_instance().log("json_codec::decode: it->second='%c' / '%s'", it->second.c_str()[0], it->second.c_str()); + } + + // Remove data structure name (if present) ... + std::string str; + if ((it->second[0] != '[') && (it->second[0] != '{')) + { + int idx_begin = it->second.find(":"); + int idx_end = it->second.rfind("}") - 1; // Remove the last '}' + str = it->second.substr(idx_begin + 1, idx_end - idx_begin); + } + else + { + str = it->second; + } + // ..and create the decoding buffer + TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_DEFAULT); + TTCN_EncDec::clear_error(); + loggers::get_instance().log("json_codec::decode: decoding_buffer='%c' / '%s'", str[0], str.c_str()); + TTCN_Buffer decoding_buffer(OCTETSTRING(str.length(), (const unsigned char *)str.c_str())); + + loggers::get_instance().warning("json_codec::decode: Unsupported variant"); + return -1; +} + +json_codec_factory json_codec_factory::_f; diff --git a/ccsrc/Protocols/Json/json_codec.hh b/ccsrc/Protocols/Json/json_codec.hh new file mode 100644 index 0000000000000000000000000000000000000000..a245e8261a7df3a7fb342e2b114e05bc510bc354 --- /dev/null +++ b/ccsrc/Protocols/Json/json_codec.hh @@ -0,0 +1,23 @@ +#pragma once + +#include "codec_gen.hh" +#include "params.hh" + +class Base_Type; +class TTCN_Typedescriptor_t; +class TTCN_Buffer; + +namespace LibHttp__JsonMessageBodyTypes { + class JsonBody; +} + +class json_codec: public codec_gen +{ +public: + explicit json_codec() : codec_gen() { }; + virtual ~json_codec() { }; + + virtual int encode (const LibHttp__JsonMessageBodyTypes::JsonBody&, OCTETSTRING& data); + virtual int decode (const OCTETSTRING& p_data, LibHttp__JsonMessageBodyTypes::JsonBody&, params* p_params = NULL); + +}; // End of class json_codec diff --git a/ccsrc/Protocols/Json/module.mk b/ccsrc/Protocols/Json/module.mk new file mode 100644 index 0000000000000000000000000000000000000000..711b37e9c6cdf9af746b7ef559abe22e28d4e9ec --- /dev/null +++ b/ccsrc/Protocols/Json/module.mk @@ -0,0 +1,4 @@ +sources := json_codec.json_codec + +includes := . + diff --git a/ccsrc/Protocols/LinuxFrame/linux_frame_layer.cc b/ccsrc/Protocols/LinuxFrame/linux_frame_layer.cc new file mode 100644 index 0000000000000000000000000000000000000000..44351198ceb094b922521f1f101729636f520541 --- /dev/null +++ b/ccsrc/Protocols/LinuxFrame/linux_frame_layer.cc @@ -0,0 +1,26 @@ +#include "linux_frame_layer_factory.hh" + +#include "loggers.hh" + +linux_frame_layer::linux_frame_layer(const std::string& p_type, const std::string& p_param) : layer(p_type), _params() { + loggers::get_instance().log(">>> linux_frame_layer::linux_frame_layer: '%s', %s", to_string().c_str(), p_param.c_str()); + +} + +void linux_frame_layer::send_data(OCTETSTRING& p_data, params& p_params) { + loggers::get_instance().log_msg(">>> linux_frame_layer::send_data: ", p_data); + + send_to_all_layers(p_data, static_cast(p_params)); +} + +void linux_frame_layer::receive_data(OCTETSTRING& p_data, params& p_params) { + loggers::get_instance().log_msg(">>> linux_frame_layer::receive_data: ", p_data); + + // 080000000000000400010406fa163ee964230000 + OCTETSTRING data = OCTETSTRING(p_data.lengthof() - 20, 20 + static_cast(p_data)); + //loggers::get_instance().log_msg("linux_frame_layer::receive_data: payload for upper layer:", data); + + receive_to_all_layers(data, static_cast(p_params)); +} + +linux_frame_layer_factory linux_frame_layer_factory::_f; diff --git a/ccsrc/Protocols/LinuxFrame/linux_frame_layer.hh b/ccsrc/Protocols/LinuxFrame/linux_frame_layer.hh new file mode 100644 index 0000000000000000000000000000000000000000..d03d7821ea7e23319161f8789ee2fa46b88afdfd --- /dev/null +++ b/ccsrc/Protocols/LinuxFrame/linux_frame_layer.hh @@ -0,0 +1,48 @@ +/*! + * \file linux_frame_layer.hh + * \brief Header file for Wireshark Linux Frame protocol layer definition. + * \author ETSI TTF T048 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#pragma once + +#include "params.hh" +#include "t_layer.hh" + +class linux_frame_layer : public layer { + params _params; //! Layer parameters + +public: //! \publicsection + /*! + * \brief Specialised constructor + * Create a new instance of the linux_frame_layer class + * \param[in] p_type \todo + * \param[in] p_param \todo + */ + linux_frame_layer(const std::string& p_type, const std::string& p_param); + /*! + * \brief Default destructor + */ + virtual ~linux_frame_layer(){}; + + /*! + * \virtual + * \fn void send_data(OCTETSTRING& data, params& p_params); + * \brief Send bytes formated data to the lower layers + * \param[in] p_data The data to be sent + * \param[in] p_params Some parameters to overwrite default value of the lower layers parameters + */ + virtual void send_data(OCTETSTRING& p_data, params& p_params); + /*! + * \virtual + * \fn void receive_data(OCTETSTRING& data, params& p_params); + * \brief Receive bytes formated data from the lower layers + * \param[in] p_data The bytes formated data received + * \param[in] p_params Some lower layers parameters values when data was received + */ + virtual void receive_data(OCTETSTRING& p_data, params& p_params); +}; // End of class linux_frame_layer diff --git a/ccsrc/Protocols/LinuxFrame/linux_frame_layer_factory.hh b/ccsrc/Protocols/LinuxFrame/linux_frame_layer_factory.hh new file mode 100644 index 0000000000000000000000000000000000000000..7a2c2a649adf9959a3925862e73b3a6b2d21f0dc --- /dev/null +++ b/ccsrc/Protocols/LinuxFrame/linux_frame_layer_factory.hh @@ -0,0 +1,42 @@ +/*! + * \file linux_frame_layer_factory.hh + * \brief Header file for ITS Ethernet protocol layer factory. + * \author ETSI STF525 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#pragma once + +#include "layer_stack_builder.hh" + +#include "linux_frame_layer.hh" + +/*! + * \class linux_frame_layer_factory + * \brief This class provides a factory class to create an linux_frame_layer class instance + */ +class linux_frame_layer_factory : public layer_factory { + static linux_frame_layer_factory _f; //! Reference to the unique instance of this class +public: //! \publicsection + /*! + * \brief Default constructor + * Create a new instance of the linux_frame_layer_factory class + * \remark The ETH layer identifier is ETH + */ + linux_frame_layer_factory() { + // register factory + layer_stack_builder::register_layer_factory("LINUX_FRAME", this); + }; + /*! + * \fn layer* create_layer(const std::string& type, const std::string& param); + * \brief Create the layers stack based on the provided layers stack description + * \param[in] p_type The provided layers stack description + * \param[in] p_params Optional parameters + * \return 0 on success, -1 otherwise + * \inline + */ + inline virtual layer *create_layer(const std::string& p_type, const std::string& p_param) { return new linux_frame_layer(p_type, p_param); }; +}; // End of class linux_frame_layer_factory diff --git a/ccsrc/Protocols/LinuxFrame/module.mk b/ccsrc/Protocols/LinuxFrame/module.mk new file mode 100644 index 0000000000000000000000000000000000000000..abbdf90854b87701a1ffe839ab98e11bcc15c8d9 --- /dev/null +++ b/ccsrc/Protocols/LinuxFrame/module.mk @@ -0,0 +1,3 @@ +sources := linux_frame_layer.cc +includes := . + diff --git a/ccsrc/Protocols/Pcap/pcap_cygwin_layer.cc b/ccsrc/Protocols/Pcap/pcap_cygwin_layer.cc index dca0cfab7cf07580dbd4ff3c0f9f8b02dcb213f6..1478b64e4016114475836b989b38d575e436ba2f 100644 --- a/ccsrc/Protocols/Pcap/pcap_cygwin_layer.cc +++ b/ccsrc/Protocols/Pcap/pcap_cygwin_layer.cc @@ -33,14 +33,14 @@ extern "C" int pcap_oid_get_request(pcap_t *p, bpf_u_int32 oid, void *data, size static const char *_hexDigits = "0123456789ABCDEF"; static char * _bin2hex(char *hex, size_t hlen, const char *bin, size_t blen) { - const unsigned char *b, *e; + const uint8_t *b, *e; char * s; // sanity check if (hlen >= 0 && hlen < blen * 2) return NULL; - b = (const unsigned char *)bin; + b = (const uint8_t *)bin; e = b + blen - 1; s = hex + blen * 2; if (s < hex + hlen) @@ -191,7 +191,7 @@ void *pcap_layer::run(void *p_this) { void *pcap_layer::thread() { pcap_o_pkthdr *pkt_header; const u_char * pkt_data; - unsigned char pkt_count = 0; + uint8_t pkt_count = 0; // loggers::get_instance().log(">>> pcap_layer::run"); @@ -237,7 +237,7 @@ void *pcap_layer::thread() { void pcap_layer::send_data(OCTETSTRING &data, params ¶ms) { loggers::get_instance().log_msg(">>> pcap_layer::send_data: ", data); - if (pcap_sendpacket(_device, static_cast(data), data.lengthof()) == -1) { + if (pcap_sendpacket(_device, static_cast(data), data.lengthof()) == -1) { loggers::get_instance().error("pcap_layer::send_data: Failed to send packet: '%s'", pcap_geterr(_device)); } } diff --git a/ccsrc/Protocols/Pcap/pcap_layer.cc b/ccsrc/Protocols/Pcap/pcap_layer.cc index 94f7e8b65b4e587082eaf47dbad5726e440a80db..6e258d02a7867b65e90ba53c13e2445573063d31 100644 --- a/ccsrc/Protocols/Pcap/pcap_layer.cc +++ b/ccsrc/Protocols/Pcap/pcap_layer.cc @@ -211,7 +211,7 @@ void pcap_layer::send_data(OCTETSTRING& data, params& params) { loggers::get_instance().log_msg(">>> pcap_layer::send_data: ", data); if (_pcap_h != -1) { // Check if offline mode is used - if (pcap_sendpacket(_device, static_cast(data), data.lengthof()) == -1) { + if (pcap_sendpacket(_device, static_cast(data), data.lengthof()) == -1) { loggers::get_instance().error("pcap_layer::send_data: Failed to send packet: '%s'", pcap_geterr(_device)); } } else if (_sent_file != NULL) { @@ -222,7 +222,7 @@ void pcap_layer::send_data(OCTETSTRING& data, params& params) { hdr.ts.tv_usec = (ms.count() % 1000) * 1000; hdr.caplen = data.lengthof(); hdr.len = hdr.caplen; - pcap_dump((u_char *)_sent_file, &hdr, static_cast(data)); + pcap_dump((u_char *)_sent_file, &hdr, static_cast(data)); } else { loggers::get_instance().log("pcap_layer::send_data: Offline mode, operation was skipped"); } diff --git a/ccsrc/Protocols/Pcap/pcap_linux_layer.cc b/ccsrc/Protocols/Pcap/pcap_linux_layer.cc index 27ce633d9d040a21730d4855b48338de7205a042..ff4487949c99ffb2166e59e155fb4a5e77155ce6 100644 --- a/ccsrc/Protocols/Pcap/pcap_linux_layer.cc +++ b/ccsrc/Protocols/Pcap/pcap_linux_layer.cc @@ -17,14 +17,14 @@ static const char *_hexDigits = "0123456789ABCDEF"; static char * _bin2hex(char *hex, size_t hlen, const char *bin, size_t blen) { - const unsigned char *b, *e; + const uint8_t *b, *e; char * s; // sanity check if (hlen >= 0 && hlen < blen * 2) return NULL; - b = (const unsigned char *)bin; + b = (const uint8_t *)bin; e = b + blen - 1; s = hex + blen * 2; if (s < hex + hlen) @@ -36,6 +36,46 @@ static char * _bin2hex(char *hex, size_t hlen, const char *bin, size_t blen return hex + blen * 2; } +char* _hex2bin(char* bin, size_t blen, const char* hex, size_t hlen, const char * charstoskip) +{ + // check + const char * h = hex; + const char * e = hex+hlen; + char * b = bin; + int n = 0; + while (h= '0' && ch <= '9') continue; + if (ch >= 'A' && ch <= 'F') continue; + if (ch >= 'a' && ch <= 'f') continue; + return NULL; + } + h = hex; + while (h < e){ + char ch = *h++; + if (ch >= '0' && ch <= '9') ch -= '0'; + else if (ch >= 'A' && ch <= 'F') ch -= 'A' - 0x0A; + else if (ch >= 'a' && ch <= 'f') ch -= 'a' - 0x0A; + else continue; + if (!n){ + *b = ch; + } + else{ + char ch1 = *b; + *b++ = (ch1 << 4) | ch; + } + n = !n; + } + if (n){ + char ch1 = *b; + *b++ = (ch1 << 4); + n = 0; + } + return b; +} + + pcap_layer::pcap_layer(const std::string& p_type, const std::string& param) : layer(p_type), PORT(p_type.c_str()), _params(), _device(NULL), _pcap_h(-1), _time_key("pcap_layer::Handle_Fd_Event_Readable") { char error_buffer[PCAP_ERRBUF_SIZE]; @@ -61,6 +101,7 @@ pcap_layer::pcap_layer(const std::string& p_type, const std::string& param) loggers::get_instance().log("pcap_layer::pcap_layer: Device %s Network address: %d", nic.c_str(), net); } } + // Open the device in promiscuous mode _device = pcap_open_live(nic.c_str(), 65536 /*64*1024*/, 1, 100, error_buffer); // TODO Replace hard coded values by pcap_layer:: if (_device == NULL) { @@ -127,17 +168,16 @@ pcap_layer::pcap_layer(const std::string& p_type, const std::string& param) // Log final PCAP filter loggers::get_instance().user("pcap_layer::pcap_layer: Filter: '%s'", filter.c_str()); - { - struct bpf_program f = {0}; - if (pcap_compile(_device, &f, filter.c_str(), 1, PCAP_NETMASK_UNKNOWN) != 0) { - loggers::get_instance().error("pcap_layer::pcap_layer: Failed to compile PCAP filter"); - } else { - if (pcap_setfilter(_device, &f) != 0) { - loggers::get_instance().error("pcap_layer::pcap_layer: Failed to set PCAP filter"); - } + struct bpf_program f = {0}; + int res; + if ((res = pcap_compile(_device, &f, filter.c_str(), 1, PCAP_NETMASK_UNKNOWN)) != 0) { + loggers::get_instance().error("pcap_layer::pcap_layer: Failed to compile PCAP filter: %s", pcap_strerror(res)); + } else { + if (pcap_setfilter(_device, &f) != 0) { + loggers::get_instance().error("pcap_layer::pcap_layer: Failed to set PCAP filter"); } - pcap_freecode(&f); } + pcap_freecode(&f); // Pass the device file handler to the polling procedure Handler_Add_Fd_Read(_pcap_h); @@ -154,7 +194,7 @@ pcap_layer::~pcap_layer() { void pcap_layer::send_data(OCTETSTRING &data, params ¶ms) { loggers::get_instance().log_msg(">>> pcap_layer::send_data: ", data); - if (pcap_sendpacket(_device, static_cast(data), data.lengthof()) == -1) { + if (pcap_sendpacket(_device, static_cast(data), data.lengthof()) == -1) { loggers::get_instance().error("pcap_layer::send_data: Failed to send packet: '%s'", pcap_geterr(_device)); } } diff --git a/ccsrc/Protocols/Pcap/pcap_linux_layer.hh b/ccsrc/Protocols/Pcap/pcap_linux_layer.hh index 90c45dd7c8b32b32d2554755001002175093cb80..d3e96b07faaef9b77b4b38a6382c4eb77317e0ae 100644 --- a/ccsrc/Protocols/Pcap/pcap_linux_layer.hh +++ b/ccsrc/Protocols/Pcap/pcap_linux_layer.hh @@ -27,7 +27,6 @@ class pcap_layer : public layer, public PORT { int _pcap_h; //! PCAP instance handle pcap_dumper_t *_sent_file; //! Write file handle to save sent packet, used in file mode std::string _time_key; //! \todo - public: //! \publicsection /*! * \brief Specialised constructor diff --git a/ccsrc/Protocols/Pcap/pcap_offline_layer.cc b/ccsrc/Protocols/Pcap/pcap_offline_layer.cc index 0f8808c5ad138fa6fe8a509752c81f37e0ba92d2..2530f7d0f2d538dae324faecdc02d1ec6b487d3d 100644 --- a/ccsrc/Protocols/Pcap/pcap_offline_layer.cc +++ b/ccsrc/Protocols/Pcap/pcap_offline_layer.cc @@ -1,227 +1,236 @@ -#if defined(__CYGWIN__) -#define _GNU_SOURCE -#endif -#include -#include -#include -#include -#include - -#include - -#include "pcap_offline_layer_factory.hh" - -#include "loggers.hh" - -#include - -#ifdef __CYGWIN__ -typedef struct { - bpf_int32 tv_sec; /* seconds */ - bpf_int32 tv_usec; /* microseconds */ -} pcap_o_timeval; - -typedef struct pcap_o_pkthdr { - pcap_o_timeval ts; /* time stamp */ - bpf_u_int32 caplen; /* length of portion present */ - bpf_u_int32 len; /* length this packet (off wire) */ -} pcap_o_pkthdr; -#else -typedef struct pcap_pkthdr pcap_o_pkthdr; -typedef struct timeval pcap_o_timeval; -#endif - -pcap_offline_layer::pcap_offline_layer(const std::string& p_type, const std::string& param) - : layer(p_type), PORT(p_type.c_str()), _params(), _device(NULL), _running(FALSE), _time_key("pcap_offline_layer::Handle_Fd_Event_Readable") { - loggers::get_instance().log(">>> pcap_offline_layer::pcap_offline_layer: '%s', %s", p_type.c_str(), param.c_str()); - params::convert(_params, param); - - _o_params.insert(std::pair(std::string("timestamp"), std::string())); - - char error_buffer[PCAP_ERRBUF_SIZE]; - params::const_iterator it; - - it = _params.find(std::string("realtime")); - _realtime = ((it != _params.end()) && !it->second.empty()); - - it = _params.find(std::string("loop")); - _loop = ((it != _params.end()) && !it->second.empty()); - - it = _params.find(std::string("file")); - if ((it != _params.end()) && !it->second.empty()) { - const std::string& file = it->second; - _device = pcap_open_offline(file.c_str(), error_buffer); - if (_device) { - - // Add user defined filter - it = _params.find(params::filter); - if ((it != _params.end()) && !it->second.empty()) { - const std::string& filter = it->second; - // Log final PCAP filter - loggers::get_instance().user("pcap_offline_layer::pcap_offline_layer: Filter: '%s'", filter.c_str()); - struct bpf_program f = {0}; - if (pcap_compile(_device, &f, filter.c_str(), 1, PCAP_NETMASK_UNKNOWN) != 0) { - loggers::get_instance().error("pcap_offline_layer::pcap_offline_layer: Failed to compile PCAP filter"); - } else { - if (pcap_setfilter(_device, &f) != 0) { - loggers::get_instance().error("pcap_offline_layer::pcap_offline_layer: Failed to set PCAP filter"); - } - } - pcap_freecode(&f); - } - - // create pipe and run thread - if (pipe2(_fd, O_NONBLOCK) == -1) { - loggers::get_instance().error("pcap_offline_layer::pcap_offline_layer: Failed to create a pipe: '%s'", ::strerror(errno)); - } - // Pass the pipe handler to the polling procedure - loggers::get_instance().log("pcap_offline_layer::pcap_offline_layer: Call handler with descriptor %d", _fd[0]); - Handler_Add_Fd_Read(_fd[0]); - // Create the offline reader thread - _thread = new std::thread(&pcap_offline_layer::run, (void *)this); - if (_thread == NULL) { - loggers::get_instance().error("pcap_offline_layer::pcap_offline_layer: Failed to start offline thread"); - } - while (_running == FALSE) { - std::this_thread::sleep_for(std::chrono::milliseconds(500)); - } - // Thread was started - loggers::get_instance().log("<<< pcap_offline_layer::pcap_offline_layer"); - } - } -} // End of ctor - -pcap_offline_layer::~pcap_offline_layer() { - loggers::get_instance().log(">>> pcap_offline_layer::~pcap_offline_layer"); - - if (_device != NULL) { - if (_thread != NULL) { - _running = FALSE; - // Wait for the working thread to terminate - _thread->join(); - loggers::get_instance().log("pcap_offline_layer::~pcap_offline_layer: Thread were stops"); - // Cleanup - delete _thread; - close(_fd[0]); - close(_fd[1]); - } - pcap_close(_device); - } -} // End of dtor - -void *pcap_offline_layer::run(void *p_this) { - pcap_offline_layer &p = *static_cast(p_this); - return p.thread(); -} - -static long timeval_diff(const pcap_o_timeval &x, const pcap_o_timeval &y) { - pcap_o_timeval z = y; - /* Perform the carry for the later subtraction by updating y. */ - if (x.tv_usec < y.tv_usec) { - int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1; - z.tv_usec -= 1000000 * nsec; - z.tv_sec += nsec; - } - if (x.tv_usec - z.tv_usec > 1000000) { - int nsec = (x.tv_usec - z.tv_usec) / 1000000; - z.tv_usec += 1000000 * nsec; - z.tv_sec -= nsec; - } - - return (x.tv_sec - z.tv_sec) * 1000 + ((x.tv_usec - z.tv_usec) / 1000); -} - -void *pcap_offline_layer::thread() { - pcap_o_pkthdr *pkt_header; - pcap_o_pkthdr lh; - const u_char * pkt_data; - unsigned char pkt_count = 0; - - // loggers::get_instance().log(">>> pcap_offline_layer::run"); - - memset(&lh, 0, sizeof(lh)); - - _running = TRUE; - - int delay = 1000; - params::const_iterator it; - it = _params.find(std::string("delay")); - if (it != _params.cend()) { - delay = std::stoi(it->second); - } - - // wait a bit before sending first packet - std::this_thread::sleep_for(std::chrono::milliseconds(delay)); - - while (_running) { // Loop while _running flag is up - // get next frame - int result = pcap_next_ex(_device, (struct pcap_pkthdr **)&pkt_header, &pkt_data); - if (result == 2) { - if (_loop) { - - } else { - _running = FALSE; - return NULL; - } - } - if (_realtime) { - // wait for next packet timestamp - if (lh.ts.tv_sec | lh.ts.tv_usec) { - long diff = timeval_diff(pkt_header->ts, lh.ts); - if (diff > 0) { - loggers::get_instance().log("<<< pcap_offline_layer::run: Wait %d msec", diff); - std::this_thread::sleep_for(std::chrono::milliseconds(diff)); - loggers::get_instance().log("<<< pcap_offline_layer::run: Wait done"); - } - } - } - while (_running && !_resume.try_lock()) { - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - } - lh = *pkt_header; -#if 0 - { - char buf[128]; - std::time_t t = pkt_header->ts.tv_sec; - std::tm * pt = std::localtime( &t ); - t = std::strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", pt); - std::sprintf(buf+t, ".%06ld", pkt_header->ts.tv_usec); - _o_params["timestamp"] = std::string(buf); - } -#else - _o_params["timestamp"] = std::to_string(pkt_header->ts.tv_usec); -#endif - _o_data = OCTETSTRING(pkt_header->len, pkt_data); - write(_fd[1], &pkt_count, 1); - pkt_count++; - } - - // loggers::get_instance().log("<<< pcap_offline_layer::run"); - return NULL; -} - -void pcap_offline_layer::send_data(OCTETSTRING &data, params ¶ms) { - loggers::get_instance().log("pcap_offline_layer::send_data: Offline mode, operation was skipped"); -} - -void pcap_offline_layer::receive_data(OCTETSTRING &data, params ¶ms) { - loggers::get_instance().log(">>> pcap_offline_layer::receive_data: Received %d bytes", data.lengthof()); - loggers::get_instance().log_to_hexa("Packet dump", data); - - // Pass the packet to the upper layers - receive_to_all_layers(data, params); -} - -void pcap_offline_layer::Handle_Fd_Event_Readable(int fd) { - // loggers::get_instance().log(">>> pcap_offline_layer::Handle_Fd_Event_Readable: %d", fd); - char c[2]; - float duration; - // Process the packet at this layer - loggers::get_instance().set_start_time(_time_key); - this->receive_data(_o_data, _o_params); - loggers::get_instance().set_stop_time(_time_key, duration); - read(_fd[0], &c, 1); - _resume.unlock(); -} - -pcap_offline_layer_factory pcap_offline_layer_factory::_f; +#if defined(__CYGWIN__) +#define _GNU_SOURCE +#endif +#include +#include +#include +#include +#include + +#include + +#include "pcap_offline_layer_factory.hh" + +#include "loggers.hh" + +#include + +#ifdef __CYGWIN__ +typedef struct { + bpf_int32 tv_sec; /* seconds */ + bpf_int32 tv_usec; /* microseconds */ +} pcap_o_timeval; + +typedef struct pcap_o_pkthdr { + pcap_o_timeval ts; /* time stamp */ + bpf_u_int32 caplen; /* length of portion present */ + bpf_u_int32 len; /* length this packet (off wire) */ +} pcap_o_pkthdr; +#else +typedef struct pcap_pkthdr pcap_o_pkthdr; +typedef struct timeval pcap_o_timeval; +#endif + +pcap_offline_layer::pcap_offline_layer(const std::string& p_type, const std::string& param) + : layer(p_type), PORT(p_type.c_str()), _params(), _device(NULL), _running(FALSE), _time_key("pcap_offline_layer::Handle_Fd_Event_Readable") { + loggers::get_instance().log(">>> pcap_offline_layer::pcap_offline_layer: '%s', %s", p_type.c_str(), param.c_str()); + params::convert(_params, param); + + _o_params.insert(std::pair(std::string("timestamp"), std::string())); + + char error_buffer[PCAP_ERRBUF_SIZE]; + params::const_iterator it; + + it = _params.find(std::string("realtime")); + _realtime = ((it != _params.end()) && !it->second.empty()); + + it = _params.find(std::string("loop")); + _loop = ((it != _params.end()) && !it->second.empty()); + + it = _params.find(std::string("file")); + if ((it != _params.end()) && !it->second.empty()) { + const std::string& file = it->second; + _device = pcap_open_offline(file.c_str(), error_buffer); + if (_device) { + + // Add user defined filter + it = _params.find(params::filter); + if ((it != _params.end()) && !it->second.empty()) { + const std::string& filter = it->second; + // Log final PCAP filter + loggers::get_instance().user("pcap_offline_layer::pcap_offline_layer: Filter: '%s'", filter.c_str()); + struct bpf_program f = {0}; + if (pcap_compile(_device, &f, filter.c_str(), 1, PCAP_NETMASK_UNKNOWN) != 0) { + loggers::get_instance().error("pcap_offline_layer::pcap_offline_layer: Failed to compile PCAP filter"); + } else { + if (pcap_setfilter(_device, &f) != 0) { + loggers::get_instance().error("pcap_offline_layer::pcap_offline_layer: Failed to set PCAP filter"); + } + } + pcap_freecode(&f); + } + + // create pipe and run thread + if (pipe2(_fd, O_NONBLOCK) == -1) { + loggers::get_instance().error("pcap_offline_layer::pcap_offline_layer: Failed to create a pipe: '%s'", ::strerror(errno)); + } + // Pass the pipe handler to the polling procedure + loggers::get_instance().log("pcap_offline_layer::pcap_offline_layer: Call handler with descriptor %d", _fd[0]); + Handler_Add_Fd_Read(_fd[0]); + // Create the offline reader thread + _thread = new std::thread(&pcap_offline_layer::run, (void *)this); + if (_thread == NULL) { + loggers::get_instance().error("pcap_offline_layer::pcap_offline_layer: Failed to start offline thread"); + } + while (_running == FALSE) { + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + } + // Thread was started + loggers::get_instance().log("<<< pcap_offline_layer::pcap_offline_layer"); + } else { + loggers::get_instance().error("pcap_offline_layer::pcap_offline_layer: Failed to create device: '%s'", error_buffer); + } + } +} // End of ctor + +pcap_offline_layer::~pcap_offline_layer() { + loggers::get_instance().log(">>> pcap_offline_layer::~pcap_offline_layer"); + + if (_device != NULL) { + if (_thread != NULL) { + _running = FALSE; + // Wait for the working thread to terminate + _thread->join(); + loggers::get_instance().log("pcap_offline_layer::~pcap_offline_layer: Thread were stops"); + // Cleanup + delete _thread; + close(_fd[0]); + close(_fd[1]); + } + pcap_close(_device); + } +} // End of dtor + +void *pcap_offline_layer::run(void *p_this) { + pcap_offline_layer &p = *static_cast(p_this); + return p.thread(); +} + +static long timeval_diff(const pcap_o_timeval &x, const pcap_o_timeval &y) { + pcap_o_timeval z = y; + /* Perform the carry for the later subtraction by updating y. */ + if (x.tv_usec < y.tv_usec) { + int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1; + z.tv_usec -= 1000000 * nsec; + z.tv_sec += nsec; + } + if (x.tv_usec - z.tv_usec > 1000000) { + int nsec = (x.tv_usec - z.tv_usec) / 1000000; + z.tv_usec += 1000000 * nsec; + z.tv_sec -= nsec; + } + + return (x.tv_sec - z.tv_sec) * 1000 + ((x.tv_usec - z.tv_usec) / 1000); +} + +void *pcap_offline_layer::thread() { + pcap_o_pkthdr *pkt_header; + pcap_o_pkthdr lh; + const u_char * pkt_data; + uint8_t pkt_count = 0; + + // loggers::get_instance().log(">>> pcap_offline_layer::run"); + + memset(&lh, 0, sizeof(lh)); + + _running = TRUE; + + int delay = 1000; + params::const_iterator it; + it = _params.find(std::string("delay")); + if (it != _params.cend()) { + delay = std::stoi(it->second); + } + + // wait a bit before sending first packet + std::this_thread::sleep_for(std::chrono::milliseconds(delay)); + + while (_running) { // Loop while _running flag is up + // get next frame + int result = pcap_next_ex(_device, (struct pcap_pkthdr **)&pkt_header, &pkt_data); + if (result == 2) { + if (_loop) { + + } else { + _running = FALSE; + return NULL; + } + } + if (_realtime) { + // wait for next packet timestamp + if (lh.ts.tv_sec | lh.ts.tv_usec) { + long diff = timeval_diff(pkt_header->ts, lh.ts); + if (diff > 0) { + loggers::get_instance().log("<<< pcap_offline_layer::run: Wait %d msec", diff); + std::this_thread::sleep_for(std::chrono::milliseconds(diff)); + loggers::get_instance().log("<<< pcap_offline_layer::run: Wait done"); + } + } + } + while (_running && !_resume.try_lock()) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + lh = *pkt_header; +#if 0 + { + char buf[128]; + std::time_t t = pkt_header->ts.tv_sec; + std::tm * pt = std::localtime( &t ); + t = std::strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", pt); + std::sprintf(buf+t, ".%06ld", pkt_header->ts.tv_usec); + _o_params["timestamp"] = std::string(buf); + } +#else + _o_params["timestamp"] = std::to_string(pkt_header->ts.tv_usec); +#endif + _o_data = OCTETSTRING(pkt_header->len, pkt_data); + write(_fd[1], &pkt_count, 1); + pkt_count++; + } + + // loggers::get_instance().log("<<< pcap_offline_layer::run"); + return NULL; +} + +void pcap_offline_layer::send_data(OCTETSTRING &data, params ¶ms) { + loggers::get_instance().log("pcap_offline_layer::send_data: Offline mode, operation was skipped"); +} + +void pcap_offline_layer::receive_data(OCTETSTRING &data, params ¶ms) { + loggers::get_instance().log(">>> pcap_offline_layer::receive_data: Received %d bytes", data.lengthof()); + + const uint8_t *p = static_cast(data); + if ((*p == 0x00) && ((*(p + 1) == 0x00) || (*(p + 1) == 0x04))) { // Linux PCAP header to be skipped + // It's up to the user to know the protocol (IPv4/IPv6) and the source MAC address + loggers::get_instance().log_to_hexa("Skipping Linux PCAP header.", data); + data = OCTETSTRING(data.lengthof() - 16, 16 + static_cast(data)); + } + + // Pass the packet to the upper layers + loggers::get_instance().log_to_hexa("Packet dump", data); + receive_to_all_layers(data, params); +} + +void pcap_offline_layer::Handle_Fd_Event_Readable(int fd) { + // loggers::get_instance().log(">>> pcap_offline_layer::Handle_Fd_Event_Readable: %d", fd); + char c[2]; + float duration; + // Process the packet at this layer + loggers::get_instance().set_start_time(_time_key); + this->receive_data(_o_data, _o_params); + loggers::get_instance().set_stop_time(_time_key, duration); + read(_fd[0], &c, 1); + _resume.unlock(); +} + +pcap_offline_layer_factory pcap_offline_layer_factory::_f; diff --git a/ccsrc/Protocols/Sctp/module.mk b/ccsrc/Protocols/Sctp/module.mk new file mode 100644 index 0000000000000000000000000000000000000000..a711a9f7a32ff24187d8cb9001c440474612ae70 --- /dev/null +++ b/ccsrc/Protocols/Sctp/module.mk @@ -0,0 +1,2 @@ +sources := sctp_layer.cc sctp_offline_layer.cc +includes := . diff --git a/ccsrc/Protocols/Sctp/sctp_layer.cc b/ccsrc/Protocols/Sctp/sctp_layer.cc new file mode 100644 index 0000000000000000000000000000000000000000..3b53bd33602a7dfa8419adf47da5f1a9226bc1a9 --- /dev/null +++ b/ccsrc/Protocols/Sctp/sctp_layer.cc @@ -0,0 +1,285 @@ +#include +#include +#include +#include +#include + +#include "sctp_layer_factory.hh" + +#include "loggers.hh" + +sctp_layer::sctp_layer(const std::string& p_type, const std::string& param) : layer(p_type), SSL_Socket(), PORT(p_type.c_str()), _params(), _client_id{-1}, _time_key("sctp_layer::Handle_Fd_Event_Readable"), _reconnect_on_send{false} { + loggers::get_instance().log(">>> sctp_layer::sctp_layer (1): '%s', %s", to_string().c_str(), param.c_str()); + // Setup parameters + params::convert(_params, param); + _params.log(); + + init(); } + +sctp_layer::sctp_layer(const std::string& p_type, const params & param) : layer(p_type), SSL_Socket(), PORT(p_type.c_str()), _params(), _client_id{-1}, _time_key("sctp_layer::Handle_Fd_Event_Readable"), _reconnect_on_send{false} { + loggers::get_instance().log(">>> sctp_layer::sctp_layer (2): '%s'", to_string().c_str()); + // Setup parameters + _params = param; + + init(); +} + +void sctp_layer::init() { + loggers::get_instance().log(">>> sctp_layer::init"); + + set_ip_proto(IPPROTO_SCTP); + + set_socket_debugging(false); + params::const_iterator it = _params.find(params::debug); + if (it == _params.cend()) { + _params.insert(std::pair(std::string("debug"), "0")); + } else if (it->second.compare("1") == 0) { + set_socket_debugging(true); + } + bool server_mode = false; + it = _params.find(params::server_mode); + if (it != _params.cend()) { + server_mode = (1 == std::stoi(it->second)); + } else { + _params.insert(std::pair(std::string("server_mode"), "0")); + } + it = _params.find(params::server); + if (it == _params.cend()) { + _params.insert(std::pair(std::string("server"), "127.0.0.1")); // TODO Try using params::server instead of std::string("server") + } + if (!parameter_set(remote_address_name(), _params[params::server].c_str())) { + loggers::get_instance().warning("sctp_layer::set_parameter: Unprocessed parameter: 'remote_address_name()'"); + } + bool ssl_mode = false; + it = _params.find(params::use_ssl); + if (it == _params.cend()) { + _params.insert(std::pair(std::string("use_ssl"), "0")); + } else if (it->second.compare("1") == 0) { + _params.insert(std::pair(std::string("use_ssl"), "1")); + ssl_mode = true; + } + set_ssl_use_ssl(ssl_mode); + it = _params.find(params::port); + if (it == _params.cend()) { + if (_params[params::use_ssl].compare("0") == 0) { // Use standard SCTP port + _params.insert(std::pair(std::string("port"), "13")); + } else { // Use standard HTTPS port + _params.insert(std::pair(std::string("port"), "22")); + } + } + if (!parameter_set(remote_port_name(), _params[params::port].c_str())) { + loggers::get_instance().warning("sctp_layer::set_parameter: Unprocessed parameter: '%s'", params::port.c_str()); + } + it = _params.find(params::local_port); + if (it == _params.cend()) { + if (_params[params::use_ssl].compare("0") == 0) { // Use standard SCTP port + _params.insert(std::pair(std::string("local_port"), "13")); + } else { // Use standard HTTPS local_port + _params.insert(std::pair(std::string("local_port"), "22")); + } + } + if (!parameter_set(local_port_name(), _params[params::local_port].c_str())) { + loggers::get_instance().warning("sctp_layer::set_parameter: Unprocessed parameter: '%s'", params::local_port.c_str()); + } + + it = _params.find(params::local_server); + if (it == _params.cend()) { + _params.insert(std::pair(std::string("local_server"), "0.0.0.0")); + } + if (!parameter_set(local_address_name(), _params[params::local_server].c_str())) { + loggers::get_instance().warning("sctp_layer::set_parameter: Unprocessed parameter: '%s'", params::local_server.c_str()); + } + + parameter_set(use_connection_ASPs_name(), (!server_mode) ? "yes" : "no"); + loggers::get_instance().warning("sctp_layer::set_parameter: Limit to one simultanneous accepted connection (server_backlog == 1)"); + parameter_set(server_backlog_name(), "1"); // Limit to one simultanneous accepted connection + loggers::get_instance().log("sctp_layer::init: server_mode=%x", server_mode); + set_server_mode(server_mode); + if (server_mode) { // Apply default values or specified ones + parameter_set(local_port_name(), _params[params::local_port].c_str()); + parameter_set(local_address_name(), _params[params::local_server].c_str()); + } + if (ssl_mode) { // Add certificate bundle + // Check mutual authentication param + _params.insert(std::pair(std::string("mutual_tls"), "0")); + parameter_set(ssl_verifycertificate_name(), "no"); + it = _params.find(params::mutual_auth); + if (it != _params.cend()) { + if (_params[params::mutual_auth].compare("1") == 0) { // Use mutual authentication + parameter_set(ssl_verifycertificate_name(), "yes"); + _params.insert(std::pair(std::string("mutual_tls"), "1")); + } + } + // Set trusted CA file + it = _params.find(params::trusted_ca_list); + if (it != _params.cend()) { + parameter_set(ssl_trustedCAlist_file_name(), it->second.c_str()); + } else { + // Use Let's Encrypt to generate your certificates + // https://manpages.ubuntu.com/manpages/impish/en/man1/certbot.1.html + loggers::get_instance().error("sctp_layer::set_parameter: Trusted CA list is required for TLS"); + } + // Set additional certificates + it = _params.find(params::privkey); + if (it != _params.cend()) { + parameter_set(ssl_private_key_file_name(), it->second.c_str()); + } else { + // Use Let's Encrypt to generate your certificates + // https://manpages.ubuntu.com/manpages/impish/en/man1/certbot.1.html + loggers::get_instance().error("sctp_layer::set_parameter: Certificate private key is required for TLS"); + } + it = _params.find(params::certificate); + if (it != _params.cend()) { + parameter_set(ssl_certificate_file_name(), it->second.c_str()); + } else { + // Use Let's Encrypt to generate your certificates + // https://manpages.ubuntu.com/manpages/impish/en/man1/certbot.1.html + loggers::get_instance().error("sctp_layer::set_parameter: Certificate is required for TLS"); + } + } + set_ttcn_buffer_usercontrol(false); + set_handle_half_close(true); + + map_user(); + + parameter_set(client_TCP_reconnect_name(), "yes"); + + if (server_mode == 0) { + loggers::get_instance().log("sctp_layer::init: Establish connection: '%s'/%s", _params[params::server].c_str(), _params[params::port].c_str()); + open_client_connection(_params[params::server].c_str(), _params[params::port].c_str(), NULL, NULL); + } +} + +sctp_layer::~sctp_layer() { + loggers::get_instance().log(">>> sctp_layer::~sctp_layer: %d", _client_id); + if (_client_id != -1) { + remove_client(_client_id); + } + + unmap_user(); +} + +void sctp_layer::Handle_Fd_Event(int fd, boolean is_readable, boolean is_writable, boolean is_error) +{ + loggers::get_instance().log(">>> sctp_layer::Handle_Fd_Event: %d - _client_id: %d", fd, _client_id); + Handle_Socket_Event(fd, is_readable, is_writable, is_error); + log_debug("<<< sctp_layer::Handle_Fd_Event"); +} + +void sctp_layer::Handle_Timeout(double time_since_last_call) +{ + loggers::get_instance().log(">>> sctp_layer::Handle_Timeout: %f", time_since_last_call); + Handle_Timeout_Event(time_since_last_call); + loggers::get_instance().log("<<< sctp_layer::Handle_Timeout"); +} + +void sctp_layer::send_data(OCTETSTRING& data, params& params) { + loggers::get_instance().log_msg(">>> sctp_layer::send_data: ", data); + + loggers::get_instance().log("sctp_layer::send_data: SSL mode: %x", get_ssl_use_ssl()); + loggers::get_instance().log("sctp_layer::send_data: server_mode: '%s'", _params[params::server_mode].c_str()); + loggers::get_instance().log("sctp_layer::send_data: peer_list_get_nr_of_peers: %d", peer_list_get_nr_of_peers()); + + if ((_params[params::server_mode].compare("0") == 0) && (peer_list_get_nr_of_peers() == 0)) { + // Reconnect (e.g. HTTP connection lost + loggers::get_instance().log("sctp_layer::send_data: Re-establish connection: '%s'/%s", _params[params::server].c_str(), _params[params::port].c_str()); + open_client_connection(_params[params::server].c_str(), _params[params::port].c_str(), NULL, NULL); + } + send_outgoing(static_cast(data), data.lengthof(), _client_id); +} + +void sctp_layer::receive_data(OCTETSTRING& data, params& params) { + loggers::get_instance().log_msg(">>> sctp_layer::receive_data: ", data); + + receive_to_all_layers(data, params); +} + +void sctp_layer::message_incoming(const uint8_t* message_buffer, int length, int client_id) { + loggers::get_instance().log(">>> sctp_layer::message_incoming"); + loggers::get_instance().log_to_hexa("sctp_layer::message_incoming: ", message_buffer, length); + + float duration; + loggers::get_instance().set_start_time(_time_key); + OCTETSTRING data(length, message_buffer); + params params; + params.insert(std::pair( + std::string("timestamp"), + std::to_string(std::chrono::duration_cast(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("sctp_layer::message_incoming: Buffurizing requested"); + } + loggers::get_instance().set_stop_time(_time_key, duration); +} + +void sctp_layer::client_connection_opened(int p_client_id) +{ + loggers::get_instance().log(">>> sctp_layer::client_connection_opened - _client_id: %d: %d", p_client_id, _client_id); +} + +bool sctp_layer::add_user_data(int p_client_id) +{ + loggers::get_instance().log(">>> sctp_layer::add_user_data: %d - _client_id: %d", p_client_id, _client_id); + _client_id = p_client_id; + if (_params[params::use_ssl].compare("0") == 0) { + loggers::get_instance().log("sctp_layer::add_user_data: Non secured mode"); + return Abstract_Socket::add_user_data(p_client_id); + } + loggers::get_instance().log("sctp_layer::add_user_data: SSL mode"); + return SSL_Socket::add_user_data(p_client_id); +} + +int sctp_layer::send_message_on_fd(int p_client_id, const uint8_t * message_buffer, int length_of_message) +{ + loggers::get_instance().log(">>> sctp_layer::send_message_on_fd: %d", p_client_id); + + if(get_user_data(p_client_id)) { + loggers::get_instance().log("sctp_layer::send_message_on_fd: SSL mode"); + return SSL_Socket::send_message_on_fd(p_client_id, message_buffer, length_of_message); + } + + loggers::get_instance().log("sctp_layer::send_message_on_fd: Non secured mode"); + return Abstract_Socket::send_message_on_fd(p_client_id, message_buffer, length_of_message); +} + +int sctp_layer::send_message_on_nonblocking_fd(int p_client_id, const uint8_t * message_buffer, int length_of_message) +{ + loggers::get_instance().log(">>> sctp_layer::send_message_on_nonblocking_fd: %d", p_client_id); + + if(get_user_data(p_client_id)) { + loggers::get_instance().log("sctp_layer::send_message_on_nonblocking_fd: SSL mode"); + return SSL_Socket::send_message_on_nonblocking_fd(p_client_id, message_buffer, length_of_message); + } + + loggers::get_instance().log("sctp_layer::send_message_on_nonblocking_fd: Non secured mode"); + return Abstract_Socket::send_message_on_nonblocking_fd(p_client_id, message_buffer, length_of_message); +} + +int sctp_layer::receive_message_on_fd(int p_client_id) +{ + loggers::get_instance().log(">>> sctp_layer::receive_message_on_fd: %d", p_client_id); + + if(get_user_data(p_client_id)) { + // INFO: it is assumed that only SSL_Socket assigns user data to each peer + loggers::get_instance().log("sctp_layer::receive_message_on_fd: SSL mode"); + return SSL_Socket::receive_message_on_fd(p_client_id); + } + + loggers::get_instance().log("sctp_layer::receive_message_on_fd: Non secured mode"); + if (_params[std::string("sctp_fragmented")].compare("1") == 0) { + sleep(4); // FIXME When HTTP paquet is fragmented into several TCP packets, a timer is required. This is a Q&D solution + } + return Abstract_Socket::receive_message_on_fd(p_client_id); +} + +void sctp_layer::peer_disconnected(int p_client_id) +{ + loggers::get_instance().log(">>> sctp_layer::peer_disconnected: %d", p_client_id); + + Abstract_Socket::peer_disconnected(p_client_id); + _client_id = -1; +} + +sctp_layer_factory sctp_layer_factory::_f; + diff --git a/ccsrc/Protocols/Sctp/sctp_layer.hh b/ccsrc/Protocols/Sctp/sctp_layer.hh new file mode 100644 index 0000000000000000000000000000000000000000..8b91550eecb94ee5749a881b5643dbf017a766cf --- /dev/null +++ b/ccsrc/Protocols/Sctp/sctp_layer.hh @@ -0,0 +1,108 @@ +/*! + * \file sctp_layer.hh + * \brief Header file for ITS TCP socket based protocol port layer. + * \author ETSI TTF T041 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#pragma once + +#include "layer.hh" + +using namespace std; // Required for isnan() +#include "Abstract_Socket.hh" + +class PORT; //! Forward declaration of TITAN class + +/*! + * \class sctp_layer + * \brief This class provides description of ITS TCP port protocol layer + */ +class sctp_layer : public layer, public SSL_Socket, public PORT { + params _params; //! Layer parameters + int _client_id; //! Connection identifier + std::string _time_key; //! \todo + bool _reconnect_on_send; //! Set to true if connection shall be done when sending data. Otherwise, connection is established by the \see constructor + +public: //! \publicsection + //sctp_layer(): PORT("TCP") {}; + /*! + * \brief Specialised constructor + * Create a new instance of the sctp_layer class + * \param[in] p_type \todo + * \param[in] p_param \todo + */ + sctp_layer(const std::string& p_type, const std::string& p_param); + /*! + * \brief Specialised constructor + * Create a new instance of the sctp_layer class + * \param[in] p_type \todo + * \param[in] p_param \todo + */ + sctp_layer(const std::string& p_type, const params &p_param); + /*! + * \brief Default destructor + * \remark If \see _reconnect_on_send is set to false, the disconnection is done by the destructor + */ + virtual ~sctp_layer(); + + /*! + * \virtual + * \fn void send_data(OCTETSTRING& data, params& params); + * \brief Send bytes formated data to the lower layers + * \param[in] p_data The data to be sent + * \param[in] p_params Some parameters to overwrite default value of the lower layers parameters + * \virtual + */ + virtual void send_data(OCTETSTRING &data, params ¶ms); + /*! + * \virtual + * \fn void receive_data(OCTETSTRING& data, params& params); + * \brief Receive bytes formated data from the lower layers + * \param[in] p_data The bytes formated data received + * \param[in] p_params Some lower layers parameters values when data was received + */ + virtual void receive_data(OCTETSTRING &data, params &info); + + /*! + * \virtual + * \fn void message_incoming(const unsigned char* message_buffer, int length, int client_id = -1); + * \brief Receive bytes formated data from the lower layers + * \param[in] p_buffer The bytes formated data received + * \param[in] p_length The number of bytes received + * \param[in] p_client_id The connection identifier.Default: -1 + */ + virtual void message_incoming(const unsigned char *p_buffer, int p_length, int p_client_id = -1); + +protected: //! \protectedsection + void init(); + + void Add_Fd_Read_Handler(int fd) { Handler_Add_Fd_Read(fd); }; + void Add_Fd_Write_Handler(int fd) { Handler_Add_Fd_Write(fd); }; + void Remove_Fd_Read_Handler(int fd) { Handler_Remove_Fd_Read(fd); }; + void Remove_Fd_Write_Handler(int fd) { Handler_Remove_Fd_Write(fd); }; + void Remove_Fd_All_Handlers(int fd) { Handler_Remove_Fd(fd); }; + void Handler_Uninstall() { Uninstall_Handler(); } + void Timer_Set_Handler(double call_interval, boolean is_timeout = TRUE, boolean call_anyway = TRUE, boolean is_periodic = TRUE) { + Handler_Set_Timer(call_interval, is_timeout, call_anyway, is_periodic); + }; + + const char *remote_address_name() { return params::server.c_str(); }; + const char *remote_port_name() { return params::port.c_str(); }; + const char *socket_debugging_name() { return params::debug.c_str(); }; + const char *ssl_use_ssl_name() { return params::use_ssl.c_str(); }; + + void client_connection_opened(int p_client_id); + bool add_user_data(int p_client_id); + int send_message_on_fd(int p_client_id, const unsigned char *message_buffer, int length_of_message); + int send_message_on_nonblocking_fd(int client_id, const unsigned char *message_buffer, int length_of_message); + int receive_message_on_fd(int p_client_id); + void peer_disconnected(int p_client_id); + +private: //! \privatesection + void Handle_Fd_Event(int fd, boolean is_readable, boolean is_writable, boolean is_error); + void Handle_Timeout(double time_since_last_call); +}; // End of class sctp_layer diff --git a/ccsrc/Protocols/Sctp/sctp_layer_factory.hh b/ccsrc/Protocols/Sctp/sctp_layer_factory.hh new file mode 100644 index 0000000000000000000000000000000000000000..59fa0f68402f4fa8a91ed8dd895799c548c82ef6 --- /dev/null +++ b/ccsrc/Protocols/Sctp/sctp_layer_factory.hh @@ -0,0 +1,41 @@ +/*! + * \file sctp_layer_factory.hh + * \brief Header file for ITS TCP socket based protocol layer factory. + * \author ETSI TTF T010 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#pragma once + +#include "layer_stack_builder.hh" + +#include "sctp_layer.hh" + +/*! + * \class sctp_layer_factory + * \brief This class provides a factory class to create an sctp_layer class instance + */ +class sctp_layer_factory : public layer_factory { + static sctp_layer_factory _f; //! Reference to the unique instance of this class +public: //! \publicsection + /*! + * \brief Default constructor + * Create a new instance of the sctp_layer class + * \remark The TCP socket based layer identifier is TCP + */ + sctp_layer_factory() { + // Register factory + layer_stack_builder::register_layer_factory("SCTP", this); + }; + /*! + * \fn layer* create_layer(const std::string& type, const std::string& param); + * \brief Create the layers stack based on the provided layers stack description + * \param[in] p_type The provided layers stack description + * \param[in] p_params Optional parameters + * \return 0 on success, -1 otherwise + */ + inline virtual layer *create_layer(const std::string& p_type, const std::string& p_param) { return new sctp_layer(p_type, p_param); }; +}; // End of class sctp_layer_factory diff --git a/ccsrc/Protocols/Sctp/sctp_offline_layer.cc b/ccsrc/Protocols/Sctp/sctp_offline_layer.cc new file mode 100644 index 0000000000000000000000000000000000000000..2ae3e455b8ffd76b013fb99d4baf5bdfa9546482 --- /dev/null +++ b/ccsrc/Protocols/Sctp/sctp_offline_layer.cc @@ -0,0 +1,168 @@ +#include +#include +#include +#include +#include + +#include "sctp_offline_layer_factory.hh" + +#include "loggers.hh" + +sctp_offline_layer::sctp_offline_layer(const std::string& p_type, const std::string& param) + : layer(p_type), _params(), _time_key("sctp_offline_layer::Handle_Fd_Event_Readable") { + loggers::get_instance().log(">>> sctp_offline_layer::sctp_offline_layer: '%s', %s", p_type.c_str(), param.c_str()); + params::convert(_params, param); + + _o_params.insert(std::pair(std::string("timestamp"), std::string())); + +} // End of ctor + +sctp_offline_layer::~sctp_offline_layer() { + loggers::get_instance().log(">>> sctp_offline_layer::~sctp_offline_layer"); +} // End of dtor + + +void sctp_offline_layer::send_data(OCTETSTRING &p_data, params &p_params) { + loggers::get_instance().log_msg(">>> sctp_offline_layer::send_data: ", p_data); + p_params.log(); + + // FIXME FSCOM: To be done + loggers::get_instance().warning("sctp_offline_layer::send_data: Not implemented. Only for offline mode"); + TTCN_Buffer chunk; + chunk.put_c(0x00); // DATA chunk + chunk.put_c(0x03); // Flags + unsigned short l = p_data.lengthof(); + chunk.put_c(l >> 8 & 0xFF); // Data length + chunk.put_c(l & 0xFF); // Data length + OCTETSTRING tsn = int2oct(0, 4); // Transmission sequence number + chunk.put_s(tsn.lengthof(), static_cast(tsn)); + l = 7; // Stream sequence identifier + chunk.put_c(l >> 8 & 0xFF); // Stream sequence identifier + chunk.put_c(l & 0xFF); // Stream sequence identifier + chunk.put_c(0x00); // Stream sequence number + chunk.put_c(0x00); // Stream sequence number + OCTETSTRING protocol = int2oct(60, 4); // Protocol is NGAP + chunk.put_s(protocol.lengthof(), static_cast(protocol)); + chunk.put_s(p_data.lengthof(), static_cast(p_data)); + // FIXME FSCOM: Add padding + + TTCN_Buffer sctp; + l = 12345; // SCTP Source port + sctp.put_c(l >> 8 & 0xFF); // Stream sequence identifier + sctp.put_c(l & 0xFF); // Stream sequence identifier + l = 12345; // SCTP Destination port + sctp.put_c(l >> 8 & 0xFF); // Stream sequence identifier + sctp.put_c(l & 0xFF); // Stream sequence identifier + OCTETSTRING vt = int2oct(0, 4); // Verification tag + sctp.put_s(vt.lengthof(), static_cast(vt)); + OCTETSTRING checksum = int2oct(0, 4); // Checksum + sctp.put_s(checksum.lengthof(), static_cast(checksum)); + + OCTETSTRING sctp_pdu(sctp.get_read_len(), sctp.get_data()); + sctp_pdu += OCTETSTRING(chunk.get_read_len(), chunk.get_data()); + + send_to_all_layers(sctp_pdu, static_cast(p_params)); +} + +void sctp_offline_layer::receive_data(OCTETSTRING &p_data, params &p_params) { + loggers::get_instance().log(">>> sctp_offline_layer::receive_data: Received %d bytes", p_data.lengthof()); + loggers::get_instance().log_to_hexa("Packet dump", p_data); + + // Source port + OCTETSTRING src_port = OCTETSTRING(2, static_cast(p_data)); + loggers::get_instance().log_msg("sctp_offline_layer::receive_data: src_port: ", src_port); + // Dst port + OCTETSTRING dst_port = OCTETSTRING(2, 2 + static_cast(p_data)); + loggers::get_instance().log_msg("sctp_offline_layer::receive_data: dst_port: ", dst_port); + // Verification tag + OCTETSTRING vtag = OCTETSTRING(4, 4 + static_cast(p_data)); + loggers::get_instance().log_msg("sctp_offline_layer::receive_data: vtag: ", vtag); + // checksum + OCTETSTRING checksum = OCTETSTRING(4, 8 + static_cast(p_data)); + loggers::get_instance().log_msg("sctp_offline_layer::receive_data: checksum: ", checksum); + // Chunk + OCTETSTRING chunk = OCTETSTRING(p_data.lengthof() - 12, 12 + static_cast(p_data)); + loggers::get_instance().log_msg("sctp_offline_layer::receive_data: chunk: ", chunk); + + OCTETSTRING payload(0, nullptr); + process_chunk(chunk, p_params, payload); + if (payload.lengthof() == 0) { + loggers::get_instance().log("sctp_offline_layer::receive_data: SCTP chunk, skip it"); + return; + } + + // Update params + // CHARSTRING s = oct2str(dst); + // p_params.insert(std::pair(params::ip_dst, std::string(static_cast(s)))); + // s = oct2str(src); + // p_params.insert(std::pair(params::ip_src, std::string(static_cast(s)))); + // s = oct2str(protocol); + // p_params.insert(std::pair(params::ip_proto, std::string(static_cast(s)))); + // Pass the packet to the upper layers + receive_to_all_layers(payload, p_params); +} + +void sctp_offline_layer::process_chunk(const OCTETSTRING& p_chunk, params &p_params, OCTETSTRING& p_payload) { + loggers::get_instance().log_msg(">>> sctp_offline_layer::process_chunk: ", p_chunk); + + const uint8_t* p = static_cast(p_chunk); // Chunk type + switch (static_cast(*p)) { + case 0x00: { // DATA chunk + p += 2; // Skip Chunk type + Chunk flag + // Chunk length + uint16_t l = (*p << 8 | *(p + 1)) & 0xffff; + loggers::get_instance().log("sctp_offline_layer::process_chunk: l: %d", l); + p += 2; + + p += 4; // Skip Transmission sequence number + + // Stream identifier + OCTETSTRING stream_id = OCTETSTRING(2, p); + loggers::get_instance().log_msg("sctp_offline_layer::process_chunk: stream_id: ", stream_id); + p += 2; + // Stream sequence number + OCTETSTRING stream_num = OCTETSTRING(2, p); + loggers::get_instance().log_msg("sctp_offline_layer::process_chunk: stream_num: ", stream_num); + p += 2; + // Protocol + uint32_t protocol = (*p << 24 | *(p + 1) << 16 | *(p + 2) << 8 | *(p + 3)) & 0xffffffff; + loggers::get_instance().log("sctp_offline_layer::process_chunk: protocol: %d", protocol); + p += 4; + loggers::get_instance().log("sctp_offline_layer::process_chunk: pointer offset: %d", (uint32_t)(p - static_cast(p_chunk))); + p_payload = OCTETSTRING(p_chunk.lengthof() - (uint32_t)(p - static_cast(p_chunk)), p); + } + break; + case 0x01: // INIT chunk + break; + case 0x02: // INIT_ACK chunk + break; + case 0x03: { // SACK + loggers::get_instance().log("sctp_offline_layer::process_chunk (SACK): position: %02x", static_cast(*(p))); + const uint8_t f = static_cast(*(p + 1)); + loggers::get_instance().log("sctp_offline_layer::process_chunk (SACK): flags: %04x", f); + const uint16_t l = static_cast((*(p + 2) << 8 | *(p + 3)) & 0xffff); + loggers::get_instance().log("sctp_offline_layer::process_chunk (SACK): length: %d", l); + loggers::get_instance().log("sctp_offline_layer::process_chunk (SACK): p_chunk.lengthof(): %d", p_chunk.lengthof()); + if (p_chunk.lengthof() > l) { + // Extract and process the next chunk + OCTETSTRING chunk(p_chunk.lengthof() - l, p + l); + process_chunk(chunk, p_params, p_payload); + } + } + break; + case 0x04: // HEARTBEAT + break; + case 0x05: // HEARTBEAT_ACK + break; + case 0x0a: // COOKIE_ECHO chunk + break; + case 0x0b: // COOKIE_ACK chunk + break; + default: // + loggers::get_instance().warning("sctp_offline_layer::process_chunk: Unprocessed chunk: 0x%02x", *p); + } + + loggers::get_instance().log_msg("<<< sctp_offline_layer::process_chunk: p_payload: ", p_payload); +} + +sctp_offline_layer_factory sctp_offline_layer_factory::_f; diff --git a/ccsrc/Protocols/Sctp/sctp_offline_layer.hh b/ccsrc/Protocols/Sctp/sctp_offline_layer.hh new file mode 100644 index 0000000000000000000000000000000000000000..c78204b3865a5b6718fc3190ae436b4abce31a54 --- /dev/null +++ b/ccsrc/Protocols/Sctp/sctp_offline_layer.hh @@ -0,0 +1,76 @@ +/*! + * \file sctp_offline_layer.hh + * \brief Header file for offline Sctp layer. + * \author ETSI TTF T041 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#pragma once + +#include "params.hh" +#include "t_layer.hh" + +#include + +/*! + * \class sctp_offline_layer + * \brief This class provides description of offline Sctp layer protocol layer + */ +class sctp_offline_layer : public layer { + params _params; //! Layer parameters + + params _o_params; + OCTETSTRING _o_data; + + std::string _time_key; + + static void *run(void *p_this); + +public: + void *thread(void); + +public: //! \publicsection + /*! + * \brief Specialised constructor + * Create a new instance of the sctp_offline_layer class + * \param[in] p_type \todo + * \param[in] p_param \todo + */ + sctp_offline_layer(const std::string& p_type, const std::string& param); + /*! + * \brief Default destructor + */ + virtual ~sctp_offline_layer(); + + /*! + * \virtual + * \fn void send_data(OCTETSTRING& data, params& params); + * \brief Send bytes formated data to the lower layers + * \param[in] p_data The data to be sent + * \param[in] p_params Some parameters to overwrite default value of the lower layers parameters + */ + virtual void send_data(OCTETSTRING &p_data, params &p_params); + /*! + * \virtual + * \fn void receive_data(OCTETSTRING& data, params& params); + * \brief Receive bytes formated data from the lower layers + * \param[in] p_data The bytes formated data received + * \param[in] p_params Some lower layers parameters values when data was received + */ + virtual void receive_data(OCTETSTRING &p_data, params &p_params); + +private: //! \privatesection + /*! + * \fn void process_chunk(const OCTETSTRING& p_chunk, OCTETSTRING& p_payload); + * \brief Process SCTP chunk and extrat the payload if the chunck is of DATA type + * \param[in] p_data The bytes formated data received + * \param[inout] p_params Some lower layers parameters values when data was received + * \param[out] p_payload The payload if the chunck is of DATA type, unchanged otherwise + */ + void process_chunk(const OCTETSTRING& p_chunk, params &p_params, OCTETSTRING& p_payload); + + void Handle_Fd_Event_Readable(int fd); +}; diff --git a/ccsrc/Protocols/Sctp/sctp_offline_layer_factory.hh b/ccsrc/Protocols/Sctp/sctp_offline_layer_factory.hh new file mode 100644 index 0000000000000000000000000000000000000000..dda767420f816082f3b848fae4c3771ad00bbb20 --- /dev/null +++ b/ccsrc/Protocols/Sctp/sctp_offline_layer_factory.hh @@ -0,0 +1,42 @@ +/*! + * \file sctp_offline_layer_factory.hh + * \brief Header file for Sctp layer factory. + * \author ETSI TTF T041 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#pragma once + +#include "layer_stack_builder.hh" + +#include "sctp_offline_layer.hh" + +/*! + * \class sctp_offline_layer_factory + * \brief This class provides a factory class to create an sctp_offline_layer class instance + */ +class sctp_offline_layer_factory : public layer_factory { + static sctp_offline_layer_factory _f; //! Reference to the unique instance of this class +public: //! \publicsection + /*! + * \brief Default constructor + * Create a new instance of the udp_layer_factory class + * \remark The SCTP layer identifier is SCTP + */ + sctp_offline_layer_factory() { + // register factory + layer_stack_builder::register_layer_factory("SCTP_FILE", this); + }; + /*! + * \fn layer* create_layer(const std::string& type, const std::string& param); + * \brief Create the layers stack based on the provided layers stack description + * \param[in] p_type The provided layers stack description + * \param[in] p_params Optional parameters + * \return 0 on success, -1 otherwise + * \inline + */ + inline virtual layer *create_layer(const std::string& p_type, const std::string& p_param) { return new sctp_offline_layer(p_type, p_param); }; +}; // End of class sctp_offline_layer_factory diff --git a/ccsrc/Protocols/Tcp/module.mk b/ccsrc/Protocols/Tcp/module.mk index 44d6c5606d15d682d68a77c6c5c15a72b0ba3b45..c2d78a697a35e0fd2b3c48db811f19fa51afc488 100644 --- a/ccsrc/Protocols/Tcp/module.mk +++ b/ccsrc/Protocols/Tcp/module.mk @@ -1,3 +1,3 @@ -sources := tcp_layer.cc +sources := tcp_layer.cc tcp_offline_layer.cc includes := . diff --git a/ccsrc/Protocols/Tcp/tcp_layer.cc b/ccsrc/Protocols/Tcp/tcp_layer.cc index 632ec3bd79f21f044a7fd24c250d85a6f45510af..5a15ffd977de10b24af81b06e7234b4b2c257432 100644 --- a/ccsrc/Protocols/Tcp/tcp_layer.cc +++ b/ccsrc/Protocols/Tcp/tcp_layer.cc @@ -189,7 +189,7 @@ void tcp_layer::send_data(OCTETSTRING& data, params& params) { loggers::get_instance().log("tcp_layer::send_data: Re-establish connection: '%s'/%s", _params[params::server].c_str(), _params[params::port].c_str()); open_client_connection(_params[params::server].c_str(), _params[params::port].c_str(), NULL, NULL); } - send_outgoing(static_cast(data), data.lengthof(), _client_id); + send_outgoing(static_cast(data), data.lengthof(), _client_id); } void tcp_layer::receive_data(OCTETSTRING& data, params& params) { @@ -198,7 +198,7 @@ void tcp_layer::receive_data(OCTETSTRING& data, params& params) { receive_to_all_layers(data, params); } -void tcp_layer::message_incoming(const unsigned char* message_buffer, int length, int client_id) { +void tcp_layer::message_incoming(const uint8_t* message_buffer, int length, int client_id) { loggers::get_instance().log(">>> tcp_layer::message_incoming"); loggers::get_instance().log_to_hexa("tcp_layer::message_incoming: ", message_buffer, length); @@ -234,7 +234,7 @@ bool tcp_layer::add_user_data(int p_client_id) return SSL_Socket::add_user_data(p_client_id); } -int tcp_layer::send_message_on_fd(int p_client_id, const unsigned char * message_buffer, int length_of_message) +int tcp_layer::send_message_on_fd(int p_client_id, const uint8_t * message_buffer, int length_of_message) { loggers::get_instance().log(">>> tcp_layer::send_message_on_fd: %d", p_client_id); @@ -247,7 +247,7 @@ int tcp_layer::send_message_on_fd(int p_client_id, const unsigned char * message return Abstract_Socket::send_message_on_fd(p_client_id, message_buffer, length_of_message); } -int tcp_layer::send_message_on_nonblocking_fd(int p_client_id, const unsigned char * message_buffer, int length_of_message) +int tcp_layer::send_message_on_nonblocking_fd(int p_client_id, const uint8_t * message_buffer, int length_of_message) { loggers::get_instance().log(">>> tcp_layer::send_message_on_nonblocking_fd: %d", p_client_id); diff --git a/ccsrc/Protocols/Tcp/tcp_layer.hh b/ccsrc/Protocols/Tcp/tcp_layer.hh index 8db788c5b003f15665dbcc19cbc8400f368991fe..d13fa57ed9af94de38f5186554e0b6938ccd3e32 100644 --- a/ccsrc/Protocols/Tcp/tcp_layer.hh +++ b/ccsrc/Protocols/Tcp/tcp_layer.hh @@ -69,13 +69,13 @@ public: //! \publicsection /*! * \virtual - * \fn void message_incoming(const unsigned char* message_buffer, int length, int client_id = -1); + * \fn void message_incoming(const uint8_t* message_buffer, int length, int client_id = -1); * \brief Receive bytes formated data from the lower layers * \param[in] p_buffer The bytes formated data received * \param[in] p_length The number of bytes received * \param[in] p_client_id The connection identifier.Default: -1 */ - virtual void message_incoming(const unsigned char *p_buffer, int p_length, int p_client_id = -1); + virtual void message_incoming(const uint8_t *p_buffer, int p_length, int p_client_id = -1); protected: //! \protectedsection void init(); @@ -97,8 +97,8 @@ protected: //! \protectedsection void client_connection_opened(int p_client_id); bool add_user_data(int p_client_id); - int send_message_on_fd(int p_client_id, const unsigned char *message_buffer, int length_of_message); - int send_message_on_nonblocking_fd(int client_id, const unsigned char *message_buffer, int length_of_message); + int send_message_on_fd(int p_client_id, const uint8_t *message_buffer, int length_of_message); + int send_message_on_nonblocking_fd(int client_id, const uint8_t *message_buffer, int length_of_message); int receive_message_on_fd(int p_client_id); void peer_disconnected(int p_client_id); diff --git a/ccsrc/Protocols/Tcp/tcp_offline_layer.cc b/ccsrc/Protocols/Tcp/tcp_offline_layer.cc new file mode 100644 index 0000000000000000000000000000000000000000..f3c3267ed69e51b51862b76b4d9cebedea6144de --- /dev/null +++ b/ccsrc/Protocols/Tcp/tcp_offline_layer.cc @@ -0,0 +1,75 @@ +#include +#include + +#include "tcp_offline_layer_factory.hh" + +#include "loggers.hh" + +tcp_offline_layer::tcp_offline_layer(const std::string& p_type, const std::string& p_param) : layer(p_type), _params() { + loggers::get_instance().log(">>> tcp_offline_layer::tcp_offline_layer: '%s', %s", to_string().c_str(), p_param.c_str()); + // Setup parameters + params::convert(_params, p_param); +} + +void tcp_offline_layer::send_data(OCTETSTRING& p_data, params& p_params) { + loggers::get_instance().log_msg(">>> tcp_offline_layer::send_data: ", p_data); + p_params.log(); + + // FIXME FSCOM: To be done + loggers::get_instance().warning("tcp_offline_layer::send_data: Not implemented. Only for offline mode"); +} + +void tcp_offline_layer::receive_data(OCTETSTRING& p_data, params& p_params) { + loggers::get_instance().log_msg(">>> tcp_offline_layer::receive_data: ", p_data); + + // // Version + // uint8_t v = static_cast(*p_data); + // OCTETSTRING version = int2oct((v >> 4) & 0x0f, 1); + // loggers::get_instance().log_msg("tcp_offline_layer::receive_data: verion: ", version); + // // Length in bytes + // uint8_t length = (v & 0x0f) * 4; + // loggers::get_instance().log("tcp_offline_layer::receive_data: length: %d", length); + // // DSF + // OCTETSTRING dsf = OCTETSTRING(1, 1 + static_cast(p_data)); + // loggers::get_instance().log_msg("tcp_offline_layer::receive_data: dsf: ", dsf); + // // Total Length + // OCTETSTRING total_length = OCTETSTRING(2, 2 + static_cast(p_data)); + // loggers::get_instance().log_msg("tcp_offline_layer::receive_data: total_length: ", total_length); + // // Identification + // OCTETSTRING id = OCTETSTRING(2, 4 + static_cast(p_data)); + // loggers::get_instance().log_msg("tcp_offline_layer::receive_data: id: ", id); + // // Flags + // OCTETSTRING flags = OCTETSTRING(2, 6 + static_cast(p_data)); + // loggers::get_instance().log_msg("tcp_offline_layer::receive_data: id: ", flags); + // // TTL + // OCTETSTRING ttl = OCTETSTRING(1, 8 + static_cast(p_data)); + // loggers::get_instance().log_msg("tcp_offline_layer::receive_data: ttl: ", ttl); + // // Protocol + // OCTETSTRING protocol = OCTETSTRING(1, 9 + static_cast(p_data)); + // loggers::get_instance().log_msg("tcp_offline_layer::receive_data: protocol: ", protocol); + // // checksum + // OCTETSTRING checksum = OCTETSTRING(2, 10 + static_cast(p_data)); + // loggers::get_instance().log_msg("tcp_offline_layer::receive_data: checksum: ", checksum); + // // src + // OCTETSTRING src = OCTETSTRING(4, 12 + static_cast(p_data)); + // loggers::get_instance().log_msg("tcp_offline_layer::receive_data: src: ", src); + // // dst + // OCTETSTRING dst = OCTETSTRING(4, 16 + static_cast(p_data)); + // loggers::get_instance().log_msg("tcp_offline_layer::receive_data: dst: ", dst); + + // OCTETSTRING data = OCTETSTRING(p_data.lengthof() - length, length + static_cast(p_data)); + // loggers::get_instance().log_msg("tcp_offline_layer::receive_data: payload for upper layer:", data); + + // // Update params + // CHARSTRING s = oct2str(dst); + // p_params.insert(std::pair(params::tcp_dst, std::string(static_cast(s)))); + // s = oct2str(src); + // p_params.insert(std::pair(params::tcp_src, std::string(static_cast(s)))); + // s = oct2str(protocol); + // p_params.insert(std::pair(params::tcp_proto, std::string(static_cast(s)))); + + OCTETSTRING data; + receive_to_all_layers(data, static_cast(p_params)); +} + +tcp_offline_layer_factory tcp_offline_layer_factory::_f; diff --git a/ccsrc/Protocols/Tcp/tcp_offline_layer.hh b/ccsrc/Protocols/Tcp/tcp_offline_layer.hh new file mode 100644 index 0000000000000000000000000000000000000000..fc7b5bbdf36fc12d837b51a407fcd725f1a6e1b5 --- /dev/null +++ b/ccsrc/Protocols/Tcp/tcp_offline_layer.hh @@ -0,0 +1,64 @@ +/*! + * \file tcp_offline_layer.hh + * \brief Header file for offline Tcp layer. + * \author ETSI TTF T041/TTF T044 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#pragma once + +#include "params.hh" +#include "t_layer.hh" + +#include + +/*! + * \class tcp_offline_layer + * \brief This class provides description of offline Tcp layer protocol layer + */ +class tcp_offline_layer : public layer { + params _params; //! Layer parameters + + params _o_params; + OCTETSTRING _o_data; + + std::string _time_key; + + static void *run(void *p_this); + +public: + void *thread(void); + +public: //! \publicsection + /*! + * \brief Specialised constructor + * Create a new instance of the tcp_offline_layer class + * \param[in] p_type \todo + * \param[in] p_param \todo + */ + tcp_offline_layer(const std::string& p_type, const std::string& param); + /*! + * \brief Default destructor + */ + virtual ~tcp_offline_layer(){}; + + /*! + * \virtual + * \fn void send_data(OCTETSTRING& data, params& params); + * \brief Send bytes formated data to the lower layers + * \param[in] p_data The data to be sent + * \param[in] p_params Some parameters to overwrite default value of the lower layers parameters + */ + virtual void send_data(OCTETSTRING &p_data, params &p_params); + /*! + * \virtual + * \fn void receive_data(OCTETSTRING& data, params& params); + * \brief Receive bytes formated data from the lower layers + * \param[in] p_data The bytes formated data received + * \param[in] p_params Some lower layers parameters values when data was received + */ + virtual void receive_data(OCTETSTRING &p_data, params &p_params); +}; diff --git a/ccsrc/Protocols/Tcp/tcp_offline_layer_factory.hh b/ccsrc/Protocols/Tcp/tcp_offline_layer_factory.hh new file mode 100644 index 0000000000000000000000000000000000000000..9cea375d1dd9a390038ccf5caa6afe2bd9d5862d --- /dev/null +++ b/ccsrc/Protocols/Tcp/tcp_offline_layer_factory.hh @@ -0,0 +1,42 @@ +/*! + * \file tcp_offline_layer_factory.hh + * \brief Header file for Sctp layer factory. + * \author ETSI TTF T041/TTF T044 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#pragma once + +#include "layer_stack_builder.hh" + +#include "tcp_offline_layer.hh" + +/*! + * \class tcp_offline_layer_factory + * \brief This class provides a factory class to create an tcp_offline_layer class instance + */ +class tcp_offline_layer_factory : public layer_factory { + static tcp_offline_layer_factory _f; //! Reference to the unique instance of this class +public: //! \publicsection + /*! + * \brief Default constructor + * Create a new instance of the udp_layer_factory class + * \remark The TCP layer identifier is TCP + */ + tcp_offline_layer_factory() { + // register factory + layer_stack_builder::register_layer_factory("TCP_OFFLINE", this); + }; + /*! + * \fn layer* create_layer(const std::string& type, const std::string& param); + * \brief Create the layers stack based on the provided layers stack description + * \param[in] p_type The provided layers stack description + * \param[in] p_params Optional parameters + * \return 0 on success, -1 otherwise + * \inline + */ + inline virtual layer *create_layer(const std::string& p_type, const std::string& p_param) { return new tcp_offline_layer(p_type, p_param); }; +}; // End of class tcp_offline_layer_factory diff --git a/ccsrc/Protocols/UDP/udp_layer.cc b/ccsrc/Protocols/UDP/udp_layer.cc index e17c530dfe6f87ee18dc4f7396d12de144a27537..ff0c3d17365cdeb68ff0b0da99efe14f3330213d 100644 --- a/ccsrc/Protocols/UDP/udp_layer.cc +++ b/ccsrc/Protocols/UDP/udp_layer.cc @@ -114,7 +114,7 @@ void udp_layer::send_data(OCTETSTRING &data, params ¶ms) { loggers::get_instance().log(">>> udp_layer::send_data: %d", _fd); loggers::get_instance().log_msg(">>> udp_layer::send_data: ", data); - int result = ::sendto(_fd, (const char *)static_cast(data), data.lengthof(), 0, (struct sockaddr *)&_daddr, sizeof(_daddr)); + int result = ::sendto(_fd, (const char *)static_cast(data), data.lengthof(), 0, (struct sockaddr *)&_daddr, sizeof(_daddr)); loggers::get_instance().log("udp_layer::send_data: #bytes sent: %d to %s:%d", result, ::inet_ntoa(_daddr.sin_addr), ntohs(_daddr.sin_port)); } @@ -127,16 +127,16 @@ void udp_layer::receive_data(OCTETSTRING& p_data, params& p_params) { void udp_layer::Handle_Fd_Event_Readable(int fd) { loggers::get_instance().log(">>> udp_layer::Handle_Fd_Event_Readable: %d", fd); - unsigned char buffer[3072] = {0}; + uint8_t buffer[3072] = {0}; struct sockaddr_in from = {0}; socklen_t len = sizeof(struct sockaddr_in); // Length of sender's address params params; - std::vector acc; + std::vector acc; int result = ::recvfrom(fd, buffer, 3072, 0, (struct sockaddr *)&from, &len); loggers::get_instance().log("udp_layer::Handle_Fd_Event_Readable: src_port = %s:%d, payload length = %d, errno = %d", ::inet_ntoa(from.sin_addr), ntohs(from.sin_port), result, errno); while ((result == 3072) && (errno == 0)) { - std::copy((unsigned char *)buffer, (unsigned char *)((unsigned char *)buffer + result), std::back_inserter(acc)); + std::copy((uint8_t *)buffer, (uint8_t *)((uint8_t *)buffer + result), std::back_inserter(acc)); result = ::recvfrom(fd, buffer, 3072, 0, (struct sockaddr *)&from, &len); loggers::get_instance().log("udp_layer::Handle_Fd_Event_Readable: src_port = %s:%d, payload length = %d, errno = %d", ::inet_ntoa(from.sin_addr), ntohs(from.sin_port), result, errno); @@ -145,7 +145,7 @@ void udp_layer::Handle_Fd_Event_Readable(int fd) { loggers::get_instance().warning("udp_layer::Handle_Fd_Event_Readable: Failed to read data, discard them: errno=%d", errno); return; } else { - std::copy((unsigned char *)buffer, (unsigned char *)((unsigned char *)buffer + result), std::back_inserter(acc)); + std::copy((uint8_t *)buffer, (uint8_t *)((uint8_t *)buffer + result), std::back_inserter(acc)); if (_reuse_incoming_source_adddress) { // Reuse the incoming address/port for sending memcpy((void *)&_daddr, (const void *)&from, sizeof(struct sockaddr_in)); loggers::get_instance().log("udp_layer::Handle_Fd_Event_Readable: New _daddr: '%s':%d", ::inet_ntoa(_daddr.sin_addr), ntohs(_daddr.sin_port)); diff --git a/ccsrc/loggers/loggers.hh b/ccsrc/loggers/loggers.hh index 035f2d12d5d4244748cf99b962e397e92a7bff2f..d786cc455848786dd8f67dacee65092c12779b28 100644 --- a/ccsrc/loggers/loggers.hh +++ b/ccsrc/loggers/loggers.hh @@ -1,273 +1,297 @@ -/*! - * \file loogers.hh - * \brief Header file for the logger framework. - * \author ETSI STF525 - * \copyright ETSI Copyright Notification - * No part may be reproduced except as authorized by written permission. - * The copyright and the foregoing restriction extend to reproduction in all media. - * All rights reserved. - * \version 0.1 - */ -#pragma once - -#include -#include -#include -#include -#include - -/** -class Base_Type; -class OCTETSTRING; -class TTCN_Buffer; -class TTCN_Logger; -enum TTCN_Logger::Severity; -extern void TTCN_error(const char *err_msg, ...) __attribute__ ((__format__ (__printf__, 1, 2), __noreturn__)); -extern void TTCN_error_begin(const char *err_msg, ...) __attribute__ ((__format__ (__printf__, 1, 2))); -extern void TTCN_error_end() __attribute__ ((__noreturn__)); -void TTCN_warning(const char *warning_msg, ...) __attribute__ ((__format__ (__printf__, 1, 2))); -extern void TTCN_warning_begin(const char *warning_msg, ...) __attribute__ ((__format__ (__printf__, 1, 2))); -extern void TTCN_warning_end(); -**/ - -using namespace std; // Required for isnan() -#include - -/*! - * \class loggers - * \brief This class provides basic functionalities for an ITS dictionary - * \implements Singleton pattern - * \todo Remove reference to TTCN3.hh - */ -class loggers { -private: //! \privatesection - static std::unique_ptr _instance; //! Smart pointer to the unique instance of the logger framework - std::map - _times; //! Timer used to measure execution time between calls to methods \loggers::set_start_time and \loggers::set_stop_time - - /*! - * \brief Default constructor - * Create a new instance of the loggers class - * \private - */ - explicit loggers() : _times(){}; - - inline void log_time_exec(const char *p_fmt, ...); - -public: //! \publicsection - /*! - * \brief Default destructor - */ - virtual ~loggers(){}; - - /*! - * \fn static loggers& get_instance(); - * \brief Accessor for the unique instance of the logger framework - * \inline - */ - static inline loggers &get_instance() { return *_instance.get(); }; - - /*! - * \fn void log_to_hexa(const char *p_prompt, const TTCN_Buffer& buffer); - * \brief Hexa dump of the \see TTCN_Buffer buffer - * \param[in] p_prompt Label of the log to be produced - * \param[in] buffer The TTCN_Buffer buffer to dump - * \inline - */ - inline void log_to_hexa(const char *p_prompt, const TTCN_Buffer &buffer); - /*! - * \fn void log_to_hexa(const char *p_prompt, const OCTETSTRING& msg); - * \brief Hexa dump of the \see OCTETSTRING buffer - * \param[in] p_prompt Label of the log to be produced - * \param[in] msg The OCTETSTRING buffer to dump - * \inline - */ - inline void log_to_hexa(const char *p_prompt, const OCTETSTRING &msg); - /*! - * \fn void log_to_hexa(const char *p_prompt, const unsigned char* msg, const size_t msg_size); - * \brief Hexa dump of the provided buffer - * \param[in] p_prompt Label of the log to be produced - * \param[in] msg The buffer to dump - * \inline - */ - inline void log_to_hexa(const char *p_prompt, const unsigned char *msg, const size_t msg_size); - /*! - * \fn void log_msg(const char *p_prompt, const Base_Type& p_type); - * \brief Debug log of TITAN data structures - * \param[in] p_prompt Label of the log to be produced - * \param[in] msg The TITAN data structure to log - * \inline - */ - inline void log_msg(const char *p_prompt, const Base_Type &p_type); - /*! - * \fn void log(const char *p_fmt, ...); - * \brief Debug message based on printf-compliant formatting message - * \param[in] p_fmt The printf-compliant format of the message to log - * \param[in] ... The arguments - * \inline - */ - inline void log(const char *p_fmt, ...); - - /*! - * \fn void user_msg(const char *p_prompt, const Base_Type& p_type); - * \brief User message of TITAN data structures - * \param[in] p_prompt Label of the log to be produced - * \param[in] msg The TITAN data structure to log - * \inline - */ - inline void user_msg(const char *p_prompt, const Base_Type &p_type); - /*! - * \fn void user(const char *p_fmt, ...); - * \brief User message based on printf-compliant formatting message - * \param[in] p_fmt The printf-compliant format of the message to log - * \param[in] ... The arguments - * \inline - */ - inline void user(const char *p_fmt, ...); - - /*! - * \fn void user_msg(const char *p_prompt, const Base_Type& p_type); - * \brief Warning message of TITAN data structures - * \param[in] p_prompt Label of the log to be produced - * \param[in] msg The TITAN data structure to log - * \inline - */ - inline void warning_msg(const char *p_prompt, const Base_Type &p_type); - /*! - * \fn void user(const char *p_fmt, ...); - * \brief Warning message based on printf-compliant formatting message - * \param[in] p_fmt The printf-compliant format of the message to log - * \param[in] ... The arguments - * \inline - */ - inline void warning(const char *p_fmt, ...); - - /*! - * \fn void user(const char *p_fmt, ...); - * \brief Error message based on printf-compliant formatting message - * \param[in] p_fmt The printf-compliant format of the message to log - * \param[in] ... The arguments - * \inline - */ - inline void error(const char *p_fmt, ...); - - /*! - * \fn void set_start_time(std::string& p_time_key); - * \brief Start execution time measurement - * \param[in] p_time_key A timer identifier (any string) - * \inline - */ - inline void set_start_time(std::string& p_time_key); - /*! - * \fn void set_stop_time(std::string& p_time_key, float& p_time); - * \brief Stop execution time measurement - * \param[in] p_time_key The timer identifier provided while calling \see loggers::set_start_time method - * \param[out] p_time The execution time measured in milliseconds - * \inline - */ - inline void set_stop_time(std::string& p_time_key, float &p_time); -}; // End of class loggers - -void loggers::log_to_hexa(const char *p_prompt, const TTCN_Buffer &buffer) { - TTCN_Logger::begin_event(TTCN_Logger::DEBUG_UNQUALIFIED); - TTCN_Logger::log_event_str(p_prompt); - buffer.log(); - TTCN_Logger::end_event(); -} - -void loggers::log_to_hexa(const char *p_prompt, const OCTETSTRING &msg) { - TTCN_Logger::begin_event(TTCN_Logger::DEBUG_UNQUALIFIED); - TTCN_Logger::log_event_str(p_prompt); - TTCN_Logger::log_event("Size: %d,\nMsg: ", msg.lengthof()); - - for (int i = 0; i < msg.lengthof(); i++) { - TTCN_Logger::log_event(" %02x", ((const unsigned char *)msg)[i]); - } - TTCN_Logger::log_event("\n"); - TTCN_Logger::end_event(); -} - -void loggers::log_to_hexa(const char *p_prompt, const unsigned char *msg, const size_t msg_size) { - TTCN_Logger::begin_event(TTCN_Logger::DEBUG_UNQUALIFIED); - TTCN_Logger::log_event_str(p_prompt); - for (size_t i = 0; i < msg_size; i++) { - TTCN_Logger::log_event(" %02x", *(msg + i)); - } - TTCN_Logger::log_event("\n"); - TTCN_Logger::end_event(); -} - -void loggers::log_msg(const char *p_prompt, const Base_Type &p_type) { - TTCN_Logger::begin_event(TTCN_Logger::DEBUG_UNQUALIFIED); - TTCN_Logger::log_event_str(p_prompt); - p_type.log(); - TTCN_Logger::end_event(); -} - -void loggers::log(const char *p_fmt, ...) { - TTCN_Logger::begin_event(TTCN_Logger::DEBUG_UNQUALIFIED); - va_list args; - va_start(args, p_fmt); - TTCN_Logger::log_event_va_list(p_fmt, args); - va_end(args); - TTCN_Logger::end_event(); -} - -void loggers::user_msg(const char *p_prompt, const Base_Type &p_type) { - TTCN_Logger::begin_event(TTCN_Logger::USER_UNQUALIFIED); - TTCN_Logger::log_event_str(p_prompt); - p_type.log(); - TTCN_Logger::end_event(); -} - -void loggers::user(const char *p_fmt, ...) { - TTCN_Logger::begin_event(TTCN_Logger::USER_UNQUALIFIED); - va_list args; - va_start(args, p_fmt); - TTCN_Logger::log_event_va_list(p_fmt, args); - va_end(args); - TTCN_Logger::end_event(); -} - -void loggers::warning(const char *p_fmt, ...) { - TTCN_Logger::begin_event(TTCN_Logger::WARNING_UNQUALIFIED); - va_list args; - va_start(args, p_fmt); - TTCN_Logger::log_event_va_list(p_fmt, args); - va_end(args); - TTCN_Logger::end_event(); -} - -void loggers::warning_msg(const char *p_prompt, const Base_Type &p_type) { - TTCN_Logger::begin_event(TTCN_Logger::WARNING_UNQUALIFIED); - TTCN_Logger::log_event_str(p_prompt); - p_type.log(); - TTCN_Logger::end_event(); -} - -void loggers::error(const char *p_fmt, ...) { - va_list args; - va_start(args, p_fmt); - TTCN_error(p_fmt, args); - va_end(args); -} - -void loggers::set_start_time(std::string& p_time_key) { _times[p_time_key] = std::clock(); } - -void loggers::set_stop_time(std::string& p_time_key, float &p_time) { - std::map::iterator it = _times.find(p_time_key); - if (it != loggers::_times.end()) { - p_time = (std::clock() - _times[p_time_key]) * 1000.0 / CLOCKS_PER_SEC; // in milliseconds - _times.erase(it); - loggers::get_instance().log_time_exec("%s: Execution duration: %f ms", p_time_key.c_str(), p_time); - } -} - -void loggers::log_time_exec(const char *p_fmt, ...) { - TTCN_Logger::begin_event(TTCN_Logger::EXECUTOR_RUNTIME); - va_list args; - va_start(args, p_fmt); - TTCN_Logger::log_event_va_list(p_fmt, args); - va_end(args); - TTCN_Logger::end_event(); -} +/*! + * \file loogers.hh + * \brief Header file for the logger framework. + * \author ETSI STF525 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#pragma once + +#include +#include +#include + +#include +#include +#include +#include +#include + +/** +class Base_Type; +class OCTETSTRING; +class TTCN_Buffer; +class TTCN_Logger; +enum TTCN_Logger::Severity; +extern void TTCN_error(const char *err_msg, ...) __attribute__ ((__format__ (__printf__, 1, 2), __noreturn__)); +extern void TTCN_error_begin(const char *err_msg, ...) __attribute__ ((__format__ (__printf__, 1, 2))); +extern void TTCN_error_end() __attribute__ ((__noreturn__)); +void TTCN_warning(const char *warning_msg, ...) __attribute__ ((__format__ (__printf__, 1, 2))); +extern void TTCN_warning_begin(const char *warning_msg, ...) __attribute__ ((__format__ (__printf__, 1, 2))); +extern void TTCN_warning_end(); +**/ + +using namespace std; // Required for isnan() +#include + +/*! + * \class loggers + * \brief This class provides basic functionalities for an ITS dictionary + * \implements Singleton pattern + * \todo Remove reference to TTCN3.hh + */ +class loggers { +private: //! \privatesection + static std::unique_ptr _instance; //! Smart pointer to the unique instance of the logger framework + std::map + _times; //! Timer used to measure execution time between calls to methods \loggers::set_start_time and \loggers::set_stop_time + + /*! + * \brief Default constructor + * Create a new instance of the loggers class + * \private + */ + explicit loggers() : _times(){}; + + inline void log_time_exec(const char *p_fmt, ...); + +public: //! \publicsection + /*! + * \brief Default destructor + */ + virtual ~loggers(){}; + + /*! + * \fn static loggers& get_instance(); + * \brief Accessor for the unique instance of the logger framework + * \inline + */ + static inline loggers &get_instance() { return *_instance.get(); }; + + /*! + * \fn void log_to_hexa(const char *p_prompt, const TTCN_Buffer& buffer); + * \brief Hexa dump of the \see TTCN_Buffer buffer + * \param[in] p_prompt Label of the log to be produced + * \param[in] buffer The TTCN_Buffer buffer to dump + * \inline + */ + inline void log_to_hexa(const char *p_prompt, const TTCN_Buffer &buffer); + /*! + * \fn void log_to_hexa(const char *p_prompt, const OCTETSTRING& msg); + * \brief Hexa dump of the \see OCTETSTRING buffer + * \param[in] p_prompt Label of the log to be produced + * \param[in] msg The OCTETSTRING buffer to dump + * \inline + */ + inline void log_to_hexa(const char *p_prompt, const OCTETSTRING &msg); + /*! + * \fn void log_to_hexa(const char *p_prompt, const uint8_t* msg, const size_t msg_size); + * \brief Hexa dump of the provided buffer + * \param[in] p_prompt Label of the log to be produced + * \param[in] msg The buffer to dump + * \inline + */ + inline void log_to_hexa(const char *p_prompt, const uint8_t *msg, const size_t msg_size); + /*! + * \fn void log_msg(const char *p_prompt, const Base_Type& p_type); + * \brief Debug log of TITAN data structures + * \param[in] p_prompt Label of the log to be produced + * \param[in] msg The TITAN data structure to log + * \inline + */ + inline void log_msg(const char *p_prompt, const Base_Type &p_type); + /*! + * \fn void log(const char *p_fmt, ...); + * \brief Debug message based on printf-compliant formatting message + * \param[in] p_fmt The printf-compliant format of the message to log + * \param[in] ... The arguments + * \inline + */ + inline void log(const char *p_fmt, ...); + + /*! + * \fn void user_msg(const char *p_prompt, const Base_Type& p_type); + * \brief User message of TITAN data structures + * \param[in] p_prompt Label of the log to be produced + * \param[in] msg The TITAN data structure to log + * \inline + */ + inline void user_msg(const char *p_prompt, const Base_Type &p_type); + /*! + * \fn void user(const char *p_fmt, ...); + * \brief User message based on printf-compliant formatting message + * \param[in] p_fmt The printf-compliant format of the message to log + * \param[in] ... The arguments + * \inline + */ + inline void user(const char *p_fmt, ...); + + /*! + * \fn void user_msg(const char *p_prompt, const Base_Type& p_type); + * \brief Warning message of TITAN data structures + * \param[in] p_prompt Label of the log to be produced + * \param[in] msg The TITAN data structure to log + * \inline + */ + inline void warning_msg(const char *p_prompt, const Base_Type &p_type); + /*! + * \fn void user(const char *p_fmt, ...); + * \brief Warning message based on printf-compliant formatting message + * \param[in] p_fmt The printf-compliant format of the message to log + * \param[in] ... The arguments + * \inline + */ + inline void warning(const char *p_fmt, ...); + + /*! + * \fn void user(const char *p_fmt, ...); + * \brief Error message based on printf-compliant formatting message + * \param[in] p_fmt The printf-compliant format of the message to log + * \param[in] ... The arguments + * \inline + */ + inline void error(const char *p_fmt, ...); + + /*! + * \fn void set_start_time(std::string& p_time_key); + * \brief Start execution time measurement + * \param[in] p_time_key A timer identifier (any string) + * \inline + */ + inline void set_start_time(std::string& p_time_key); + /*! + * \fn void set_stop_time(std::string& p_time_key, float& p_time); + * \brief Stop execution time measurement + * \param[in] p_time_key The timer identifier provided while calling \see loggers::set_start_time method + * \param[out] p_time The execution time measured in milliseconds + * \inline + */ + inline void set_stop_time(std::string& p_time_key, float &p_time); + /*! + * \fn void log_rijndael_state(const std::string p_label, const uint8_t p_state[4][4]); + * \brief Display the state table of the Rijndael encryption algorithm as defined in ETSI TS 135 207 V16.0.0 (2020-08) Clause 3.2 Format + * \param[in] p_time_key The timer identifier provided while calling \see loggers::set_start_time method + * \param[out] p_time The execution time measured in milliseconds + * \inline + */ + inline void log_rijndael_state(const std::string p_label, const uint8_t p_state[4][4]); +}; // End of class loggers + +void loggers::log_to_hexa(const char *p_prompt, const TTCN_Buffer &buffer) { + TTCN_Logger::begin_event(TTCN_Logger::DEBUG_UNQUALIFIED); + TTCN_Logger::log_event_str(p_prompt); + buffer.log(); + TTCN_Logger::end_event(); +} + +void loggers::log_to_hexa(const char *p_prompt, const OCTETSTRING &msg) { + TTCN_Logger::begin_event(TTCN_Logger::DEBUG_UNQUALIFIED); + TTCN_Logger::log_event_str(p_prompt); + TTCN_Logger::log_event("Size: %d,\nMsg: ", msg.lengthof()); + + for (int i = 0; i < msg.lengthof(); i++) { + TTCN_Logger::log_event(" %02x", ((const uint8_t *)msg)[i]); + } + TTCN_Logger::log_event("\n"); + TTCN_Logger::end_event(); +} + +void loggers::log_to_hexa(const char *p_prompt, const uint8_t *msg, const size_t msg_size) { + TTCN_Logger::begin_event(TTCN_Logger::DEBUG_UNQUALIFIED); + TTCN_Logger::log_event_str(p_prompt); + for (size_t i = 0; i < msg_size; i++) { + TTCN_Logger::log_event(" %02x", *(msg + i)); + } + TTCN_Logger::log_event("\n"); + TTCN_Logger::end_event(); +} + +void loggers::log_msg(const char *p_prompt, const Base_Type &p_type) { + TTCN_Logger::begin_event(TTCN_Logger::DEBUG_UNQUALIFIED); + TTCN_Logger::log_event_str(p_prompt); + p_type.log(); + TTCN_Logger::end_event(); +} + +void loggers::log(const char *p_fmt, ...) { + TTCN_Logger::begin_event(TTCN_Logger::DEBUG_UNQUALIFIED); + va_list args; + va_start(args, p_fmt); + TTCN_Logger::log_event_va_list(p_fmt, args); + va_end(args); + TTCN_Logger::end_event(); +} + +void loggers::user_msg(const char *p_prompt, const Base_Type &p_type) { + TTCN_Logger::begin_event(TTCN_Logger::USER_UNQUALIFIED); + TTCN_Logger::log_event_str(p_prompt); + p_type.log(); + TTCN_Logger::end_event(); +} + +void loggers::user(const char *p_fmt, ...) { + TTCN_Logger::begin_event(TTCN_Logger::USER_UNQUALIFIED); + va_list args; + va_start(args, p_fmt); + TTCN_Logger::log_event_va_list(p_fmt, args); + va_end(args); + TTCN_Logger::end_event(); +} + +void loggers::warning(const char *p_fmt, ...) { + TTCN_Logger::begin_event(TTCN_Logger::WARNING_UNQUALIFIED); + va_list args; + va_start(args, p_fmt); + TTCN_Logger::log_event_va_list(p_fmt, args); + va_end(args); + TTCN_Logger::end_event(); +} + +void loggers::warning_msg(const char *p_prompt, const Base_Type &p_type) { + TTCN_Logger::begin_event(TTCN_Logger::WARNING_UNQUALIFIED); + TTCN_Logger::log_event_str(p_prompt); + p_type.log(); + TTCN_Logger::end_event(); +} + +void loggers::error(const char *p_fmt, ...) { + va_list args; + va_start(args, p_fmt); + TTCN_error(p_fmt, args); + va_end(args); +} + +void loggers::set_start_time(std::string& p_time_key) { _times[p_time_key] = std::clock(); } + +void loggers::set_stop_time(std::string& p_time_key, float &p_time) { + std::map::iterator it = _times.find(p_time_key); + if (it != loggers::_times.end()) { + p_time = (std::clock() - _times[p_time_key]) * 1000.0 / CLOCKS_PER_SEC; // in milliseconds + _times.erase(it); + loggers::get_instance().log_time_exec("%s: Execution duration: %f ms", p_time_key.c_str(), p_time); + } +} + +void loggers::log_time_exec(const char *p_fmt, ...) { + TTCN_Logger::begin_event(TTCN_Logger::EXECUTOR_RUNTIME); + va_list args; + va_start(args, p_fmt); + TTCN_Logger::log_event_va_list(p_fmt, args); + va_end(args); + TTCN_Logger::end_event(); +} + +void loggers::log_rijndael_state(const std::string p_label, const uint8_t p_state[4][4]) { + std::ostringstream oss; + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + oss << std::setw(2) << std::setfill('0') << std::hex << static_cast(p_state[j][i]); + } // End of 'for' statement + oss << " "; + } // End of 'for' statement + loggers::get_instance().log("%s:%s", p_label.c_str(), oss.str().c_str()); +} + diff --git a/ccsrc/security/include/certs_cache.hh b/ccsrc/security/include/certs_cache.hh index 5e55c713bcc435230fcdbe11caa0bee71056070a..97889dc906104da91a9a49adab812aec1678c888 100644 --- a/ccsrc/security/include/certs_cache.hh +++ b/ccsrc/security/include/certs_cache.hh @@ -87,7 +87,7 @@ public: /*! \publicsection */ const std::string cert_to_string(const std::string& p_certificate_id); // For debug purpose. To be removed - int publickey_to_string(const EVP_PKEY* p_public_kep, std::vector& p_buffer); // For debug purpose. To be removed + int publickey_to_string(const EVP_PKEY* p_public_kep, std::vector& p_buffer); // For debug purpose. To be removed private: /*! \privatesection */ diff --git a/ccsrc/security/include/hmac.hh b/ccsrc/security/include/hmac.hh index cbd1ccd985edbb18026279ecf9e186a3cd290cbe..3fceb2b9d8b401059360d30216ae32aefe53db5c 100644 --- a/ccsrc/security/include/hmac.hh +++ b/ccsrc/security/include/hmac.hh @@ -1,69 +1,70 @@ -/*! - * \file hmac.hh - * \brief Header file for HMAC helper methods. - * \author ETSI STF637 - * \copyright ETSI Copyright Notification - * No part may be reproduced except as authorized by written permission. - * The copyright and the foregoing restriction extend to reproduction in all media. - * All rights reserved. - * \version 0.1 - */ -#pragma once - -#include - -#include - -class OCTETSTRING; //! TITAN forward declaration - -/*! - * \enum Supported hash algorithms - */ -enum class hash_algorithms : unsigned char { - sha_256, /*!< HMAC with SHA-256 */ - sha_384 /*!< HMAC with SHA-384 */ -}; // End of class hash_algorithms - -/*! - * \class hmac - * \brief This class provides description of HMAC helper methods - */ -class hmac { - HMAC_CTX * _ctx; //! HMAC context - hash_algorithms _hash_algorithms; //! HMAC hash algorithm to use -public: - /*! - * \brief Default constructor - * Create a new instance of the hmac class - * \param[in] p_hash_algorithms The hash algorithm to be used to compute the HMAC. Default: sha_256 - */ - hmac(const hash_algorithms p_hash_algorithms = hash_algorithms::sha_256) : _ctx{::HMAC_CTX_new()}, _hash_algorithms(p_hash_algorithms){}; - /*! - * \brief Default destructor - */ - virtual ~hmac() { - if (_ctx != nullptr) { - ::HMAC_CTX_free(_ctx); - }; - }; - - /*! - * \fn int generate(const OCTETSTRING p_buffer, const OCTETSTRING p_secret_key, OCTETSTRING& p_hmac); - * \brief Generate the HMAC of data using a secret key - * \Param[in] p_buffer The data tobe hashed - * \param[in] p_secret_key The secret key to be used to generate the HMAC - * \param[out] p_hmac The HMAC value based of the provided data - * \return 0 on success, -1 otherwise - */ - int generate(const OCTETSTRING p_buffer, const OCTETSTRING p_secret_key, OCTETSTRING &p_hmac); // TODO Use reference & - - /*! - * \fn int generate(const unsigned char* p_buffer, const size_t p_buffer_length, const unsigned char* p_secret_key, const size_t p_secret_key_length, - * OCTETSTRING& p_hmac); \brief Generate the HMAC of data using a secret key \param[in] p_buffer The data to be hashed \param[in] p_buffer_length The size of - * the data \param[in] p_secret_key The secret key to be used to generate the HMAC \param[in] p_secret_key_length The size of the secret key \param[out] - * p_hmac The HMAC value based of the provided data \return 0 on success, -1 otherwise - */ - int generate(const unsigned char *p_buffer, const size_t p_buffer_length, const unsigned char *p_secret_key, const size_t p_secret_key_length, - OCTETSTRING &p_hmac); - -}; // End of class hmac +/*! + * \file hmac.hh + * \brief Header file for HMAC helper methods. + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#pragma once + +#include + +#include + +class OCTETSTRING; //! TITAN forward declaration +class BOOLEAN; //! TITAN forward declaration + +/*! + * \enum Supported hash algorithms + */ +enum class hash_algorithms : uint8_t { + sha_256, /*!< HMAC with SHA-256 */ + sha_384 /*!< HMAC with SHA-384 */ +}; // End of class hash_algorithms + +/*! + * \class hmac + * \brief This class provides description of HMAC helper methods + */ +class hmac { + HMAC_CTX * _ctx; //! HMAC context + hash_algorithms _hash_algorithms; //! HMAC hash algorithm to use +public: + /*! + * \brief Default constructor + * Create a new instance of the hmac class + * \param[in] p_hash_algorithms The hash algorithm to be used to compute the HMAC. Default: sha_256 + */ + hmac(const hash_algorithms p_hash_algorithms = hash_algorithms::sha_256) : _ctx{::HMAC_CTX_new()}, _hash_algorithms(p_hash_algorithms){}; + /*! + * \brief Default destructor + */ + virtual ~hmac() { + if (_ctx != nullptr) { + ::HMAC_CTX_free(_ctx); + }; + }; + + /*! + * \fn int generate(const OCTETSTRING& p_buffer, const OCTETSTRING& p_secret_key, OCTETSTRING& p_hmac); + * \brief Generate the HMAC of data using a secret key + * \Param[in] p_buffer The data tobe hashed + * \param[in] p_secret_key The secret key to be used to generate the HMAC + * \param[out] p_hmac The HMAC value based of the provided data + * \return 0 on success, -1 otherwise + */ + int generate(const OCTETSTRING& p_buffer, const OCTETSTRING& p_secret_key, OCTETSTRING& p_hmac, const BOOLEAN& p_resize = true); + + /*! + * \fn int generate(const uint8_t* p_buffer, const size_t p_buffer_length, const uint8_t* p_secret_key, const size_t p_secret_key_length, + * OCTETSTRING& p_hmac); \brief Generate the HMAC of data using a secret key \param[in] p_buffer The data to be hashed \param[in] p_buffer_length The size of + * the data \param[in] p_secret_key The secret key to be used to generate the HMAC \param[in] p_secret_key_length The size of the secret key \param[out] + * p_hmac The HMAC value based of the provided data \return 0 on success, -1 otherwise + */ + int generate(const uint8_t *p_buffer, const size_t p_buffer_length, const uint8_t *p_secret_key, const size_t p_secret_key_length, + OCTETSTRING &p_hmac, const BOOLEAN& p_resize = true); + +}; // End of class hmac diff --git a/ccsrc/security/include/sha1.hh b/ccsrc/security/include/sha1.hh index e053544a88354affce96dc3a2e028a012df946ee..1fa6ccfae015595eecc20a6fa0bb38d54c95ae07 100644 --- a/ccsrc/security/include/sha1.hh +++ b/ccsrc/security/include/sha1.hh @@ -42,14 +42,14 @@ public: int generate(const OCTETSTRING &p_buffer, OCTETSTRING &p_hash); /*! - * \fn int generate(const unsigned char* p_buffer, OCTETSTRING& p_hash); + * \fn int generate(const uint8_t* p_buffer, OCTETSTRING& p_hash); * \brief Receive bytes formated data from the lower layers * \param[in] p_buffer The data used to generate the SHA-1 hash * \param[in] The length of the data buffer * \param[out] p_hash The SHA-1 hash value based of the provided data * \return 0 on success, -1 otherwise */ - int generate(const unsigned char *p_buffer, const size_t p_length, OCTETSTRING &p_hash); + int generate(const uint8_t *p_buffer, const size_t p_length, OCTETSTRING &p_hash); /*! * \fn const OCTETSTRING get_sha1_empty_string() const; @@ -57,7 +57,7 @@ public: * \return The SHA-1 of an empty string */ inline const OCTETSTRING get_sha1_empty_string() const { - static unsigned char sha1_empty_string[] = { + static uint8_t sha1_empty_string[] = { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09}; //! SHA-1 of an empty string return OCTETSTRING(20, sha1_empty_string); diff --git a/ccsrc/security/include/sha256.hh b/ccsrc/security/include/sha256.hh index 4973a2efd1f9c73d8bbab1b073e2d8d095cb453a..d8e62519d3fce757df2fa905770fc13d7cca189b 100644 --- a/ccsrc/security/include/sha256.hh +++ b/ccsrc/security/include/sha256.hh @@ -42,14 +42,14 @@ public: int generate(const OCTETSTRING &p_buffer, OCTETSTRING &p_hash); /*! - * \fn int generate(const unsigned char* p_buffer, OCTETSTRING& p_hash); + * \fn int generate(const uint8_t* p_buffer, OCTETSTRING& p_hash); * \brief Receive bytes formated data from the lower layers * \param[in] p_buffer The data used to generate the SHA-256 hash * \param[in] The length of the data buffer * \param[out] p_hash The SHA-256 hash value based of the provided data * \return 0 on success, -1 otherwise */ - int generate(const unsigned char *p_buffer, const size_t p_length, OCTETSTRING &p_hash); + int generate(const uint8_t *p_buffer, const size_t p_length, OCTETSTRING &p_hash); /*! * \fn const OCTETSTRING get_sha256_empty_string() const; @@ -57,7 +57,7 @@ public: * \return The SHA-256 of an empty string */ inline const OCTETSTRING get_sha256_empty_string() const { - static unsigned char sha256_empty_string[] = { + static uint8_t sha256_empty_string[] = { 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}; //! SHA-256 of an empty string return OCTETSTRING(32, sha256_empty_string); diff --git a/ccsrc/security/include/sha384.hh b/ccsrc/security/include/sha384.hh index 67f2d19ad643aa114d08f0c343723c8f56682e22..dbb77d465aac2c71836e92c51c99da8ea01c8619 100644 --- a/ccsrc/security/include/sha384.hh +++ b/ccsrc/security/include/sha384.hh @@ -49,7 +49,7 @@ public: //! \publicsection * \param[out] p_hash The SHA-384 hash value based of the provided data * \return 0 on success, -1 otherwise */ - int generate(const unsigned char *p_buffer, const size_t p_length, OCTETSTRING &p_hash); + int generate(const uint8_t *p_buffer, const size_t p_length, OCTETSTRING &p_hash); /*! * \fn const OCTETSTRING get_sha384_empty_string() const; diff --git a/ccsrc/security/src/certs_cache.cc b/ccsrc/security/src/certs_cache.cc index 1d7bcf7fd066357456d83c5e480a6fb447cbba87..f801962817bca7a2b25f5d06832915060e7158c4 100644 --- a/ccsrc/security/src/certs_cache.cc +++ b/ccsrc/security/src/certs_cache.cc @@ -243,10 +243,10 @@ const std::string certs_cache::cert_to_string(const std::string& p_certificate_i return s; } -int certs_cache::publickey_to_string(const EVP_PKEY* p_public_kep, std::vector& p_buffer) { +int certs_cache::publickey_to_string(const EVP_PKEY* p_public_kep, std::vector& p_buffer) { loggers::get_instance().log(">>> certs_cache::publickey_to_string: '%p'", p_public_kep); - unsigned char* buffer = nullptr; + uint8_t* buffer = nullptr; int ret = ::i2d_PublicKey((EVP_PKEY*)p_public_kep, &buffer); loggers::get_instance().log("certs_cache::publickey_to_string: ret: '%d'", ret); if (ret < 0) { @@ -255,7 +255,7 @@ int certs_cache::publickey_to_string(const EVP_PKEY* p_public_kep, std::vector - -#include "hmac.hh" - -#include "loggers.hh" - -int hmac::generate(const OCTETSTRING p_buffer, const OCTETSTRING p_secret_key, OCTETSTRING &p_hmac) { - // Sanity check - if (p_buffer.lengthof() == 0) { - return -1; - } - - return generate(static_cast(p_buffer), p_buffer.lengthof(), static_cast(p_secret_key), p_secret_key.lengthof(), - p_hmac); -} - -int hmac::generate(const unsigned char *p_buffer, const size_t p_buffer_length, const unsigned char *p_secret_key, const size_t p_secret_key_length, - OCTETSTRING &p_hmac) { - // Sanity check - if ((p_buffer == nullptr) || (p_secret_key == nullptr)) { - return -1; - } - ::HMAC_CTX_reset(_ctx); - - p_hmac = int2oct(0, EVP_MAX_MD_SIZE); - if (_hash_algorithms == hash_algorithms::sha_256) { - ::HMAC_Init_ex(_ctx, (const void *)p_secret_key, (long unsigned int)p_secret_key_length, EVP_sha256(), NULL); - } else if (_hash_algorithms == hash_algorithms::sha_384) { - ::HMAC_Init_ex(_ctx, (const void *)p_secret_key, (long unsigned int)p_secret_key_length, EVP_sha384(), NULL); - } else { // TODO To be continued - return -1; - } - // Compute the hash value - ::HMAC_Update(_ctx, p_buffer, p_buffer_length); - unsigned int length = p_hmac.lengthof(); - ::HMAC_Final(_ctx, (unsigned char *)static_cast(p_hmac), &length); - loggers::get_instance().log_to_hexa("hmac::generate: ", (unsigned char *)static_cast(p_hmac), length); - // Resize the hmac - if (_hash_algorithms == hash_algorithms::sha_256) { - p_hmac = OCTETSTRING(16, static_cast(p_hmac)); - } // FIXME Check length for the other hash algorithm - - return 0; -} +/*! + * \file hmac.cc + * \brief Source file for HMAC helper methods. + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#include + +#include "hmac.hh" + +#include "loggers.hh" + +int hmac::generate(const OCTETSTRING& p_buffer, const OCTETSTRING& p_secret_key, OCTETSTRING& p_hmac, const BOOLEAN& p_resize) { + // Sanity check + if (p_buffer.lengthof() == 0) { + return -1; + } + + return generate(static_cast(p_buffer), p_buffer.lengthof(), static_cast(p_secret_key), p_secret_key.lengthof(), + p_hmac, p_resize); +} + +int hmac::generate(const uint8_t *p_buffer, const size_t p_buffer_length, const uint8_t *p_secret_key, const size_t p_secret_key_length, + OCTETSTRING &p_hmac, const BOOLEAN& p_resize) { + // Sanity check + if ((p_buffer == nullptr) || (p_secret_key == nullptr)) { + return -1; + } + ::HMAC_CTX_reset(_ctx); + + p_hmac = int2oct(0, EVP_MAX_MD_SIZE); + if (_hash_algorithms == hash_algorithms::sha_256) { + ::HMAC_Init_ex(_ctx, (const void *)p_secret_key, (long unsigned int)p_secret_key_length, EVP_sha256(), NULL); + } else if (_hash_algorithms == hash_algorithms::sha_384) { + ::HMAC_Init_ex(_ctx, (const void *)p_secret_key, (long unsigned int)p_secret_key_length, EVP_sha384(), NULL); + } else { // TODO To be continued + return -1; + } + // Compute the hash value + ::HMAC_Update(_ctx, p_buffer, p_buffer_length); + unsigned int length = p_hmac.lengthof(); + ::HMAC_Final(_ctx, (uint8_t *)static_cast(p_hmac), &length); + loggers::get_instance().log_to_hexa("hmac::generate: ", (uint8_t *)static_cast(p_hmac), length); + // Resize the hmac + if ((_hash_algorithms == hash_algorithms::sha_256) && (p_resize == true)) { + p_hmac = OCTETSTRING(16, static_cast(p_hmac)); + } else { + p_hmac = OCTETSTRING(length, static_cast(p_hmac)); + } // FIXME Check length for the other hash algorithm + + return 0; +} diff --git a/ccsrc/security/src/security_externals.cc b/ccsrc/security/src/security_externals.cc index 641c9f538c66c0b566f4d91f93352098c6499a81..ce6312a9a02023a2af9aaed8744f840b97aeca8b 100644 --- a/ccsrc/security/src/security_externals.cc +++ b/ccsrc/security/src/security_externals.cc @@ -191,7 +191,7 @@ INTEGER LibSecurity__Signature::fx__dec__xmldsig(BITSTRING& bs, http__www__w3__o TTCN_EncDec::clear_error(); TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_DEFAULT); - TTCN_Buffer decoding_buffer(OCTETSTRING(str.length(), (const unsigned char*)str.c_str())); + TTCN_Buffer decoding_buffer(OCTETSTRING(str.length(), (const uint8_t*)str.c_str())); s.decode(http__www__w3__org__2000__09__xmldsig::Signature_descr_, decoding_buffer, TTCN_EncDec::CT_XER, XER_EXTENDED); diff --git a/ccsrc/security/src/securty_services.cc b/ccsrc/security/src/securty_services.cc index eb459f6986850b9ae0a0aa6bf5d09daf96310f5d..2e256e7ac4818210b433b4a682c502e01ce638fa 100644 --- a/ccsrc/security/src/securty_services.cc +++ b/ccsrc/security/src/securty_services.cc @@ -49,7 +49,7 @@ int security_services::do_sign(const OCTETSTRING& p_encoded_message, const OCTET // Transform and canonicalize the message // Transform: Remove all CR, LS, TAB and SPACE outside of the tags std::string transformed; - xml_converters::get_instance().xml_transform(std::string((const char*)(static_cast(p_encoded_message)), p_encoded_message.lengthof()), transformed); + xml_converters::get_instance().xml_transform(std::string((const char*)(static_cast(p_encoded_message)), p_encoded_message.lengthof()), transformed); loggers::get_instance().log("security_services::do_sign: p_pull_request_transormed: '%s'", transformed.c_str()); // Canonicalization std::string canonicalized; @@ -62,7 +62,7 @@ int security_services::do_sign(const OCTETSTRING& p_encoded_message, const OCTET // Transform and canonicalize the empty signature // Transform: Remove all CR, LS, TAB and SPACE outside of the tags transformed.clear(); - xml_converters::get_instance().xml_transform(std::string((const char*)(static_cast(p_empty_signature)), p_empty_signature.lengthof()), transformed); + xml_converters::get_instance().xml_transform(std::string((const char*)(static_cast(p_empty_signature)), p_empty_signature.lengthof()), transformed); loggers::get_instance().log("security_services::do_sign: p_empty_signature transormed: '%s'", transformed.c_str()); // Canonicalization canonicalized.clear(); @@ -98,7 +98,7 @@ int security_services::do_sign(const OCTETSTRING& p_encoded_message, const OCTET } } loggers::get_instance().log_msg("security_services::do_sign: digest: ", p_digest); - std::vector to64 = converter::get_instance().buffer_to_base64(std::vector(static_cast(p_digest), p_digest.lengthof() + static_cast(p_digest))); + std::vector to64 = converter::get_instance().buffer_to_base64(std::vector(static_cast(p_digest), p_digest.lengthof() + static_cast(p_digest))); p_digest = OCTETSTRING(to64.size(), to64.data()); loggers::get_instance().log_msg("security_services::do_sign: digest (64): ", p_digest); @@ -133,7 +133,7 @@ int security_services::do_sign(const OCTETSTRING& p_encoded_message, const OCTET canonicalized = canonicalized.substr(0, i + 13) + std::string(to64.cbegin(), to64.cend()) + canonicalized.substr(i + 13, canonicalized.length() - i - 13); OCTETSTRING to_be_signed(char2oct(CHARSTRING(canonicalized.c_str()))); loggers::get_instance().log_msg("security_services::do_sign: to_be_signed: ", to_be_signed); - to64 = converter::get_instance().buffer_to_base64(std::vector(static_cast(to_be_signed), to_be_signed.lengthof() + static_cast(to_be_signed))); + to64 = converter::get_instance().buffer_to_base64(std::vector(static_cast(to_be_signed), to_be_signed.lengthof() + static_cast(to_be_signed))); loggers::get_instance().log("security_services::do_sign: Data to be signed/verified: '%s'", converter::get_instance().bytes_to_string(to64).c_str()); // Retrieve the private key @@ -156,7 +156,7 @@ int security_services::do_sign(const OCTETSTRING& p_encoded_message, const OCTET ::EVP_MD_CTX_free(ctx); return -1; } - if (::EVP_DigestSignUpdate(ctx, (const unsigned char*)canonicalized.c_str(), canonicalized.length()) != 1) { + if (::EVP_DigestSignUpdate(ctx, (const uint8_t*)canonicalized.c_str(), canonicalized.length()) != 1) { loggers::get_instance().warning("security_services::do_sign: EVP_DigestSignUpdate failed, error 0x%lx", ::ERR_get_error()); ::EVP_MD_CTX_free(ctx); return -1; @@ -174,7 +174,7 @@ int security_services::do_sign(const OCTETSTRING& p_encoded_message, const OCTET return -1; } loggers::get_instance().log("security_services::do_sign: signature_length: %d", signature_length); - std::vector s(signature_length, 0x00); + std::vector s(signature_length, 0x00); if (::EVP_DigestSignFinal(ctx, s.data(), &signature_length) != 1) { loggers::get_instance().warning("security_services::do_sign: EVP_DigestSignUpdate failed, error 0x%lx", ::ERR_get_error()); ::EVP_MD_CTX_free(ctx); @@ -191,11 +191,11 @@ int security_services::do_sign(const OCTETSTRING& p_encoded_message, const OCTET // return -1; // } // loggers::get_instance().log("security_services::do_sign: public_key: '%p'", public_key); - // std::vector buffer; + // std::vector buffer; // _certs_db->publickey_to_string(public_key, buffer); // ctx = ::EVP_MD_CTX_new(); // if (!::EVP_DigestVerifyInit(ctx, NULL, sign_digest, NULL, (EVP_PKEY*)public_key) || - // !::EVP_DigestVerifyUpdate(ctx, (const unsigned char*)canonicalized.c_str(), canonicalized.length()) || + // !::EVP_DigestVerifyUpdate(ctx, (const uint8_t*)canonicalized.c_str(), canonicalized.length()) || // !::EVP_DigestVerifyFinal(ctx, s.data(), s.size())) { // loggers::get_instance().warning("security_services::do_sign: Failed to verify signature, error 0x%lx", ::ERR_get_error()); // ::EVP_MD_CTX_free(ctx); @@ -207,7 +207,7 @@ int security_services::do_sign(const OCTETSTRING& p_encoded_message, const OCTET p_signature = OCTETSTRING(signature_length, s.data()); loggers::get_instance().log_msg("security_services::do_sign: signature: ", p_signature); - to64 = converter::get_instance().buffer_to_base64(std::vector(static_cast(p_signature), p_signature.lengthof() + static_cast(p_signature))); + to64 = converter::get_instance().buffer_to_base64(std::vector(static_cast(p_signature), p_signature.lengthof() + static_cast(p_signature))); p_signature = OCTETSTRING(to64.size(), to64.data()); loggers::get_instance().log_msg("security_services::do_sign: signature (64): ", p_signature); @@ -239,7 +239,7 @@ bool security_services::do_sign_verify(const CHARSTRING& p_message, const OCTETS // Transform and canonicalize the empty signature // Transform: Remove all CR, LS, TAB and SPACE outside of the tags transformed.clear(); - xml_converters::get_instance().xml_transform(std::string((const char*)(static_cast(p_empty_signature)), p_empty_signature.lengthof()), transformed); + xml_converters::get_instance().xml_transform(std::string((const char*)(static_cast(p_empty_signature)), p_empty_signature.lengthof()), transformed); loggers::get_instance().log("security_services::do_sign_verify: p_empty_signature transormed: '%s'", transformed.c_str()); // Canonicalization canonicalized.clear(); @@ -276,7 +276,7 @@ bool security_services::do_sign_verify(const CHARSTRING& p_message, const OCTETS } } loggers::get_instance().log_msg("security_services::do_sign_verify: digest: ", dg); - std::vector to64 = converter::get_instance().buffer_to_base64(std::vector(static_cast(dg), dg.lengthof() + static_cast(dg))); + std::vector to64 = converter::get_instance().buffer_to_base64(std::vector(static_cast(dg), dg.lengthof() + static_cast(dg))); loggers::get_instance().log_msg("security_services::do_sign_verify: digest (64): ", OCTETSTRING(to64.size(), to64.data())); // Retrieve certificate @@ -318,7 +318,7 @@ bool security_services::do_sign_verify(const CHARSTRING& p_message, const OCTETS return false; } loggers::get_instance().log("security_services::do_sign_verify: public_key: '%p'", public_key); - std::vector buffer; + std::vector buffer; ret = _certs_db->publickey_to_string(public_key, buffer); if (ret == 1) { loggers::get_instance().warning("security_services::do_sign_verify: Failed to convert public key into string"); @@ -336,7 +336,7 @@ bool security_services::do_sign_verify(const CHARSTRING& p_message, const OCTETS canonicalized = canonicalized.substr(0, i + 13) + std::string(to64.cbegin(), to64.cend()) + canonicalized.substr(i + 13, canonicalized.length() - i - 13); OCTETSTRING to_be_signed(char2oct(CHARSTRING(canonicalized.c_str()))); loggers::get_instance().log_msg("security_services::do_sign_verify: to_be_signed: ", to_be_signed); - to64 = converter::get_instance().buffer_to_base64(std::vector(static_cast(to_be_signed), to_be_signed.lengthof() + static_cast(to_be_signed))); + to64 = converter::get_instance().buffer_to_base64(std::vector(static_cast(to_be_signed), to_be_signed.lengthof() + static_cast(to_be_signed))); loggers::get_instance().log("security_services::do_sign_verify: Data to be signed/verified: '%s'", converter::get_instance().bytes_to_string(to64).c_str()); // Convert signature @@ -346,8 +346,8 @@ bool security_services::do_sign_verify(const CHARSTRING& p_message, const OCTETS //signature_value.erase(std::remove(signature_value.begin(), signature_value.end(), '\n'), signature_value.end()); loggers::get_instance().log("security_services::do_sign_verify: Before B64 decoded: '%s'", signature_value.c_str()); // Convert into bytes buffer - const std::vector to_decode((const unsigned char*)signature_value.c_str(), static_cast((const unsigned char*)signature_value.c_str() + signature_value.length())); - std::vector s = converter::get_instance().base64_to_buffer(to_decode); + const std::vector to_decode((const uint8_t*)signature_value.c_str(), static_cast((const uint8_t*)signature_value.c_str() + signature_value.length())); + std::vector s = converter::get_instance().base64_to_buffer(to_decode); loggers::get_instance().log("security_services::do_sign_verify: B64 decoded: '%s'", converter::get_instance().bytes_to_hexa(s, true).c_str()); loggers::get_instance().log("security_services::do_sign_verify: B64 decoded len: '%d'", s.size()); @@ -359,7 +359,7 @@ bool security_services::do_sign_verify(const CHARSTRING& p_message, const OCTETS } // Check signature if (!::EVP_DigestVerifyInit(ctx, NULL, sign_digest, NULL, (EVP_PKEY*)public_key) || - !::EVP_DigestVerifyUpdate(ctx, (const unsigned char*)canonicalized.c_str(), canonicalized.length()) || + !::EVP_DigestVerifyUpdate(ctx, (const uint8_t*)canonicalized.c_str(), canonicalized.length()) || !::EVP_DigestVerifyFinal(ctx, s.data(), s.size())) { loggers::get_instance().warning("security_services::do_sign_verify: Failed to verify signature, error 0x%lx", ::ERR_get_error()); ::EVP_MD_CTX_free(ctx); diff --git a/ccsrc/security/src/sha1.cc b/ccsrc/security/src/sha1.cc index 21b051410669f6463093ef418ef8ba85915be1d0..1a7f83483668ce8f2364b678d2f2195f130e567c 100644 --- a/ccsrc/security/src/sha1.cc +++ b/ccsrc/security/src/sha1.cc @@ -19,10 +19,10 @@ int sha1::generate(const OCTETSTRING& p_buffer, OCTETSTRING& p_hash) { return 0; } - return generate(static_cast(p_buffer), p_buffer.lengthof(), p_hash); + return generate(static_cast(p_buffer), p_buffer.lengthof(), p_hash); } -int sha1::generate(const unsigned char* p_buffer, const size_t p_length, OCTETSTRING& p_hash) { +int sha1::generate(const uint8_t* p_buffer, const size_t p_length, OCTETSTRING& p_hash) { // Sanity check if ((p_buffer == nullptr) || (p_length == 0)) { p_hash = get_sha1_empty_string(); @@ -34,6 +34,6 @@ int sha1::generate(const unsigned char* p_buffer, const size_t p_length, OCTETST // Compute the hash value ::SHA1_Init(&_ctx); ::SHA1_Update(&_ctx, p_buffer, p_length); - ::SHA1_Final((unsigned char*)static_cast(p_hash), &_ctx); + ::SHA1_Final((uint8_t*)static_cast(p_hash), &_ctx); return 0; }; diff --git a/ccsrc/security/src/sha256.cc b/ccsrc/security/src/sha256.cc index 2238f0973236d5f43ddd9c53cc1a4213adf9c19b..f09d07ec8ada4e7cb29b3d25aa2faa438fe6b71e 100644 --- a/ccsrc/security/src/sha256.cc +++ b/ccsrc/security/src/sha256.cc @@ -19,10 +19,10 @@ int sha256::generate(const OCTETSTRING& p_buffer, OCTETSTRING& p_hash) { return 0; } - return generate(static_cast(p_buffer), p_buffer.lengthof(), p_hash); + return generate(static_cast(p_buffer), p_buffer.lengthof(), p_hash); } -int sha256::generate(const unsigned char* p_buffer, const size_t p_length, OCTETSTRING& p_hash) { +int sha256::generate(const uint8_t* p_buffer, const size_t p_length, OCTETSTRING& p_hash) { // Sanity check if ((p_buffer == nullptr) || (p_length == 0)) { p_hash = get_sha256_empty_string(); @@ -34,6 +34,6 @@ int sha256::generate(const unsigned char* p_buffer, const size_t p_length, OCTET // Compute the hash value ::SHA256_Init(&_ctx); ::SHA256_Update(&_ctx, p_buffer, p_length); - ::SHA256_Final((unsigned char*)static_cast(p_hash), &_ctx); + ::SHA256_Final((uint8_t*)static_cast(p_hash), &_ctx); return 0; }; diff --git a/ccsrc/security/src/sha384.cc b/ccsrc/security/src/sha384.cc index b32e4c252555d3044c10d45a3f30291939bdceca..fd40e18fc9fa1f917c82d672c0c002b454c7f230 100644 --- a/ccsrc/security/src/sha384.cc +++ b/ccsrc/security/src/sha384.cc @@ -19,10 +19,10 @@ int sha384::generate(const OCTETSTRING &p_buffer, OCTETSTRING &p_hash) { return 0; } - return generate(static_cast(p_buffer), p_buffer.lengthof(), p_hash); + return generate(static_cast(p_buffer), p_buffer.lengthof(), p_hash); } -int sha384::generate(const unsigned char *p_buffer, const size_t p_length, OCTETSTRING &p_hash) { +int sha384::generate(const uint8_t *p_buffer, const size_t p_length, OCTETSTRING &p_hash) { // Sanity check if ((p_buffer == nullptr) || (p_length == 0)) { p_hash = get_sha384_empty_string(); @@ -34,12 +34,12 @@ int sha384::generate(const unsigned char *p_buffer, const size_t p_length, OCTET // Compute the hash value ::SHA384_Init(&_ctx); ::SHA384_Update(&_ctx, p_buffer, p_length); - ::SHA384_Final((unsigned char *)static_cast(p_hash), &_ctx); + ::SHA384_Final((uint8_t *)static_cast(p_hash), &_ctx); return 0; } const OCTETSTRING sha384::get_sha384_empty_string() const { - static unsigned char + static uint8_t sha384_empty_string[] = {0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38, 0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3, 0x6a, 0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43, 0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda, 0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb, 0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b}; //! SHA-384 of an empty string diff --git a/ttcn/LibHelpers/ttcn/LibHelpers_Functions.ttcn b/ttcn/LibHelpers/ttcn/LibHelpers_Functions.ttcn index b5c6bd5f6c21a4cd4206ee5176f6c42ff75be37c..a0393818ec788a34249ff3488ab6de6829d6eaf2 100644 --- a/ttcn/LibHelpers/ttcn/LibHelpers_Functions.ttcn +++ b/ttcn/LibHelpers/ttcn/LibHelpers_Functions.ttcn @@ -1,5 +1,5 @@ /** - * @author ETSI / STF405 / STF449 / STF484 / STF517 + * @author ETSI / STF405 / STF449 / STF484 / STF517 / TTF T036 * @version $Url$ * $Id$ * @desc Module containing common functions for ITS diff --git a/ttcn/LibHttp/module_ims.mk b/ttcn/LibHttp/module_ims.mk new file mode 100644 index 0000000000000000000000000000000000000000..3525eb45616c7db55a52ef057e90f96b3061000f --- /dev/null +++ b/ttcn/LibHttp/module_ims.mk @@ -0,0 +1,22 @@ +sources := \ + ttcn/LibHttp_BinaryMessageBodyTypes.ttcn \ + ttcn/LibHttp_EncdecDeclarations.ttcn \ + ttcn/LibHttp_JSONTypes.ttcn \ + ttcn/LibHttp_MessageBodyTypes.ttcn \ + ttcn/LibHttp_Pics.ttcn \ + ttcn/LibHttp_Pixits.ttcn \ + ttcn/LibHttp_TypesAndValues.ttcn \ + ttcn/LibHttp_XMLTypes.ttcn \ + ttcn/LibHttp_TestSystem.ttcn \ + ttcn/LibHttp_Functions.ttcn \ + ttcn/LibHttp_Templates.ttcn \ + + +# Please, move and comment the module you need to overwrite tofit your project +# ttcn/LibHttp_XmlMessageBodyTypes.ttcn \ +# ttcn/LibHttp_XmlTemplates.ttcn +# ttcn/LibHttp_JsonMessageBodyTypes.ttcn \ +# ttcn/LibHttp_JsonTemplates.ttcn \ +# ttcn/LibHttp_Templates.ttcn \ +# ttcn/LibHttp_TestSystem.ttcn \ +# ttcn/LibHttp_Functions.ttcn \ diff --git a/ttcn/LibHttp/ttcn/LibHttp_TestSystem.ttcn b/ttcn/LibHttp/ttcn/LibHttp_TestSystem.ttcn index 945a87e3937e4fe82ae57d5348e496c9523a0e0c..be90e74fe653fe8305272e5a2ffa291263645a38 100644 --- a/ttcn/LibHttp/ttcn/LibHttp_TestSystem.ttcn +++ b/ttcn/LibHttp/ttcn/LibHttp_TestSystem.ttcn @@ -26,7 +26,6 @@ module LibHttp_TestSystem { port HttpPort httpPort; port HttpPort httpPort_notif; // timers - timer tc_wait := PX_TWAIT; timer tc_ac := PX_TAC; timer tc_noac := PX_TNOAC; } // End of component HttpComponent