Commit 0035ae54 authored by Garcia's avatar Garcia
Browse files

Add TestAdapter/Codecs

parent 3625b55a
Loading
Loading
Loading
Loading
+64 −0
Original line number Diff line number Diff line
/*!
 * \file      codec.hh
 * \brief     Header file for ITS abstract codec definition.
 * \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 "params.hh"

class OCTETSTRING; //! Declare TITAN class
class CHARSTRING;  //! Declare TITAN class
class BITSTRING;   //! Declare TITAN class

/*!
 * \class codec
 * \brief  This class provides the interface for all ITS codecs, include UT and AC codecs
 * \abstract
 */
template<typename TPDUEnc, typename TPDUDec>
class codec
{
protected:
  params* _params; //! Reference to params stack
                   // \todo Use smart pointer std::unique_ptr<params>
  
public: //! \publicsection
  /*!
   * \fn codec();
   * \brief  Default constructor
   * \todo Remove logs
   */
  explicit codec() : _params(nullptr) { };
  /*!
   * \fn ~codec();
   * \brief  Default destructor
   * \virtual
   * \todo Remove logs
   */
  virtual ~codec() { };
  /*!
   * \fn int encode(const TPDUEnc& msg, OCTETSTRING& data);
   * \brief  Encode typed message into an octet string
   * \param[in] p_message The typed message to be encoded
   * \param[out] p_data The encoding result
   * \return 0 on success, -1 otherwise
   * \pure
   */
  virtual int encode(const TPDUEnc& p_message, OCTETSTRING& p_data) = 0;
  /*!
   * \fn int decode(const OCTETSTRING& p_, TPDUDec& p_message, params* p_params = NULL);
   * \brief  Encode typed message into an octet string format
   * \param[in] p_data The message in its octet string
   * \param[out] p_message The decoded typed message
   * \return 0 on success, -1 otherwise
   * \pure
   */
  virtual int decode(const OCTETSTRING& p_, TPDUDec& p_message, params* p_params = NULL) = 0;
}; // End of class codec
+356 −0
Original line number Diff line number Diff line
/*!
 * \file      converter.hh
 * \brief     Helper class for types converter.
 * \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 <iostream>
#include <iomanip>
#include <sstream>

#include <string>
#include <vector>
#include <algorithm>

#include <cstdint>
#include <cctype>
#include <climits> // LONG_MAX, LLONG_MAX
#include <ctime>   // time_t, struct tm, difftime, time, mktime

/*!
 * \class converter
 * \brief This class provide a set of methods for types conversions
 * \remark Singleton pattern
 */
class converter {
    
  /*!
   * \brief Unique static object reference of this class
   */
  static converter * instance;
    
  /*!
   * \brief Default private ctor
   */
  converter() {};
  /*!
   * \brief Default private dtor
   */
  ~converter() {
    if (instance != NULL) {
      delete instance;
      instance = NULL;
    }
  };
    
public: /*! \publicsection */
  /*!
   * \brief Public accessor to the single object reference
   */
  inline static converter & get_instance() {
    if (instance == NULL) instance = new converter();
    return *instance;
  };
    
public:
  /*!
   * \enum endian_t
   * \brief Endianess style
   */
  typedef enum {
    big_endian,
    little_endian
  } endian_t;

public:
  /*!
   * \brief Convert a Binary Coded Decimal value into a binary value
   * \param[in] p_value The BDC value
   * \return The binary value
   * \inline
   */
  inline uint8_t bcd_to_bin(const uint8_t p_value) {
    return ((p_value / 16 * 10) + (p_value % 16));
  };

  /*!
   * \brief Convert a binary value into a Binary Coded Decimal value
   * \param[in] p_value The binary value
   * \return The BCD value
   * \inline
   */
  inline uint8_t bin_to_bcd(const uint8_t p_value) {
    return ((p_value / 10 * 16) + (p_value % 10));
  };
    
  /*!
   * \brief Swap two bytes length value (e.g. 0xCAFE becomes 0xFECA)
   * \param[in] p_value The value to swap
   * \return The swapped value
   * \inline
   */
  uint16_t swap(const uint16_t p_value);
  inline int16_t swap(const int16_t p_value) {
    return static_cast<short>(swap(static_cast<uint16_t>(p_value)));
  };
  /*!
   * \brief Swap four bytes length value (used for littel endian / big endian)
   * \param[in] p_value The value to swap
   * \return The swapped value
   */
  uint32_t swap(const uint32_t p_value);
  inline int32_t swap(const int32_t p_value) {
    return static_cast<int>(swap(static_cast<uint32_t>(p_value)));
  };
    
  /*!
   * \brief Convert a string into an hexadecimal string
   * \param[in] p_value The string value
   * \return The hexadecimal value
   */
  std::string string_to_hexa(const std::string & p_value);
  /*!
   * \brief Convert a bytes array int32_t an hexadecimal string
   * \param[in] p_value The bytes array value
   * \return The hexadecimal value
   */
  std::string bytes_to_hexa(const std::vector<uint8_t> & p_value);
  /*!
   * \brief Convert an hexadecimal string into a bytes array
   * \param[in] p_value The hexadecimal value
   * \return The bytes array value
   */
  std::vector<uint8_t> hexa_to_bytes(const std::string & p_value);
    
  /*!
   * \brief Convert a time in time_t format into a string formated according to RFC 822, 1036, 1123, 2822
   * \param[in] p_time The time to convert in time_t format
   * \return The time string formated
   * \see http://www.unixtimestamp.com/
   * @code
   * std::string result = time_to_string(1489755780);
   * result.compare("Fri, 17 Mar 2017 13:03:00 +0000") == 0 // When time zone is set to UTC
   * @endcode
   * \remark Use commands 1) timedatectl to change your machine timezone (e.g. sudo timedatectl set-timezone UTC to change machine timezone to UTC, 2) timedatectl list-timezones to get the list of the timezones)
   */
  std::string time_to_string(const time_t p_time);
  /*!
   * \brief Convert a time in struct tm format into a string formated according to RFC 822, 1036, 1123, 2822
   * \param[in] p_time The time to convert in struct tm format
   * \return The time string formated
   * \see http://www.unixtimestamp.com/
   */
  std::string time_to_string(const struct tm & p_time);
    
  /*!
   * \brief Convert a 16-bits integer (int16_t) into a bytes array
   * \param[in] p_value The 16-bits integer value
   * \param[in] p_endianess Endianess style. Default: big_endian
   * \return The bytes array value
   */
  inline std::vector<uint8_t> short_to_bytes(const int16_t p_value, const endian_t p_endianess = big_endian) const {
    std::vector<uint8_t> result(sizeof(short), 0x00);
    for (int i = sizeof(short) - 1; i >= 0; i--) {
      int offset = (sizeof(short) - 1 - i) * 8;
      result[i] = static_cast<uint8_t>((p_value >> offset) & 0xFF);
    } // End of 'for' statement
    return result;
  }; // End of short_to_bytes

  /*!
   * \brief Convert a bytes array into a 16-bits integer (int16_t)
   * \param[in] p_value The bytes array
   * \param[in] p_endianess Endianess style. Default: big_endian
   * \return The 16-bits integer on success, SHRT_MAX on error (wrong bytes array size)
   */
  inline int16_t bytes_to_short(const std::vector<uint8_t> & p_value, const endian_t p_endianess = big_endian) const {
    // Sanity check
    if (p_value.size() > sizeof(short)) {
      return SHRT_MAX;
    }
    int16_t value = 0;
    for (size_t i = 0; i < p_value.size(); i++) {
      value = (value << 8) + (p_value[i] & 0xff);
    } // End of 'for' statement
    return value;
  }; // End of bytes_to_short
    
  /*!
   * \brief Convert a 32-bits integer (int32_t) into a bytes array
   * \param[in] p_value The 32-bits integer value
   * \param[in] p_endianess Endianess style. Default: big_endian
   * \return The bytes array value
   */
  inline std::vector<uint8_t> int_to_bytes(const int32_t p_value, const endian_t p_endianess = big_endian) const {
    /*uint8_t bytes[sizeof(p_value)];
      std::copy(
      static_cast<const uint8_t *>(static_cast<const void *>(&p_value)),
      static_cast<const uint8_t *>(static_cast<const void *>(&p_value)) + sizeof(p_value),
      bytes
      );
      std::vector<uint8_t> result(bytes, bytes + sizeof(bytes) / sizeof(uint8_t));*/
    std::vector<uint8_t> result(sizeof(int), 0x00);
    for (int i = sizeof(int) - 1; i >= 0; i--) {
      int offset = (sizeof(int) - 1 - i) * 8;
      result[i] = static_cast<uint8_t>((p_value >> offset) & 0xFF);
    } // End of 'for' statement
    return result;
  }; // End of int_to_bytes

  /*!
   * \brief Convert a bytes array into a 32-bits integer (int32_t)
   * \param[in] p_value The bytes array
   * \param[in] p_endianess Endianess style. Default: big_endian
   * \return The 32-bits integer on success, LONG_MAX on error (wrong bytes array size)
   */
  inline int32_t bytes_to_int(const std::vector<uint8_t> & p_value, const endian_t p_endianess = big_endian) const {
    // Sanity check
    if (p_value.size() > sizeof(int)) {
      return INT_MAX;
    }
    int32_t value = 0;
    for (size_t i = 0; i < p_value.size(); i++) {
      value = (value << 8) + (p_value[i] & 0xff);
    } // End of 'for' statement
    return value;
    //      return *((int *)(&p_value[0]));
  }; // End of bytes_to_int
    
  /*!
   * \brief Convert a 64-bits integer (int64_t) into a bytes array
   * \param[in] p_value The 64-bits integer value
   * \param[in] p_endianess Endianess style. Default: big_endian
   * \return The bytes array value
   */
  inline std::vector<uint8_t> long_to_bytes(const int64_t p_value, const endian_t p_endianess = big_endian) const {
    /*uint8_t bytes[sizeof(p_value)];
      std::copy(
      static_cast<const uint8_t *>(static_cast<const void *>(&p_value)),
      static_cast<const uint8_t *>(static_cast<const void *>(&p_value)) + sizeof(p_value),
      bytes
      );
      std::vector<uint8_t> result(bytes, bytes + sizeof(bytes) / sizeof(uint8_t));*/
    std::vector<uint8_t> result(sizeof(int64_t), 0x00);
    for (int i = sizeof(int64_t) - 1; i >= 0; i--) {
      int offset = (sizeof(int64_t) - 1 - i) * 8;
      result[i] = static_cast<uint8_t>((p_value >> offset) & 0xFF);
    } // End of 'for' statement
    return result;
  }; // End of long_to_bytes

  /*!
   * \brief Convert a bytes array into a 64-bits integer (int64_t)
   * \param[in] p_value The bytes array
   * \param[in] p_endianess Endianess style. Default: big_endian
   * \return The 64-bits integer on success, LLONG_MAX on error (wrong bytes array size)
   */
  inline int64_t bytes_to_long(const std::vector<uint8_t> & p_value, const endian_t p_endianess = big_endian) const {
    // Sanity check
    if (p_value.size() > sizeof(int64_t)) {
      return LLONG_MAX;
    }
    int64_t value = 0;
    for (size_t i = 0; i < p_value.size(); i++) {
      value = (value << 8) + (p_value[i] & 0xff);
    } // End of 'for' statement
    return value;
    //      return *((long *)(&p_value[0]));
  }; // End of bytes_to_long
    
  /*!
   * \brief Convert a float value into a bytes array
   * \param[in] p_value The float value
   * \return The bytes array value
   */
  inline std::vector<uint8_t> float_to_bytes(const float p_value) const {
    uint8_t bytes[sizeof(p_value)];
    std::copy(
              static_cast<const uint8_t *>(static_cast<const void *>(&p_value)),
              static_cast<const uint8_t *>(static_cast<const void *>(&p_value)) + sizeof(p_value),
              bytes
              );
    std::vector<uint8_t> result(bytes, bytes + sizeof(bytes) / sizeof(uint8_t));
    return result;
  }; // End of float_to_long

  /*!
   * \brief Convert a bytes array into a float
   * \param[in] p_value The bytes array
   * \return The float value
   */
  inline float bytes_to_float(const std::vector<uint8_t> & p_value) const {
    return *((float *)(&p_value[0]));
  }; // End of bytes_to_float
    
  /*!
   * \brief Convert a string into a bytes array
   * \param[in] p_value The string value
   * \return The bytes array value
   */
  inline std::vector<uint8_t> string_to_bytes(const std::string & p_value) const {
    return std::vector<uint8_t>(p_value.begin(), p_value.end());
  }; // End of string_to_bytes
    
  /*!
   * \brief Convert a bytes array into a string
   * \param[in] p_value The bytes array value
   * \return The string value
   */
  inline std::string bytes_to_string(const std::vector<uint8_t> & p_value) const {
    return std::string(p_value.begin(), p_value.end());
  }; // End of bytes_to_string
    
public:
  /*!
   * \brief Convert a string into an integer
   * \param[in] p_value The string value
   * \return The integer value
   */
  inline int32_t string_to_int(const std::string & p_value) const {
    return std::stoi(p_value);
    //return atoi(p_value.c_str());
  }; // End of string_to_int

  /*!
   * \brief Convert an integer into a string
   * \param[in] p_value The integer value
   * \return The string value
   */
  inline std::string int_to_string(const int32_t & p_value) const {
    std::ostringstream ss;
    ss << p_value;
    return ss.str();
  }; // End of string_to_bytes

public:
        
  /*!
   * \brief Returns a copy of the string, with leading and trailing special characters omitted
   * \param[in] p_value The string value
   * \param[in] p_trim_chars The special characters to be omitted. Default: ' ' and TAB
   * \return The new string value
   */
  std::string trim(const std::string& p_value, const std::string& p_trim_chars = " \t");
    
  /*!
   * \brief Convert the provided string into a list of arguments
   * \param[in] p_value The string value
   * \return The arguments list
   * \code{.cc}
   *     std::string str = "--host localhost --port 12345 --duration -1";
   *     std::vector<std::string> tokens = converter::get_instance().split_arguments_line(str);
   *     std::clog << "Tokens: " << std::endl;
   *     for (auto it = tokens.begin(); it != tokens.end(); ++it) {
   *       std::clog << "   " << *it << std::endl;
   *     }
   * \endcode
   */
  std::vector<std::string> split_arguments_line(const std::string & p_value);
                  
}; // End of class converter
+144 −0
Original line number Diff line number Diff line
/*!
 * \file      layer.hh
 * \brief     Header file for ITS abstract protocol layer definition.
 * \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 <string>
#include <map>
#include <vector>
#include <algorithm>

#include "params.hh"

class OCTETSTRING; //! Forward declaration of TITAN class
class BITSTRING;   //! Forward declaration of TITAN class
class CHARSTRING;  //! Forward declaration of TITAN class
class INTEGER;     //! Forward declaration of TITAN class

/*!
 * \class layer
 * \brief  This class provides basic description of an ITS protocol layer
 */
class layer {
  std::vector<layer*> upperLayers; //! List of the upper protocol layers
  std::vector<layer*> lowerLayers; //! List of the lower protocol layers

protected:
  std::string type; //! Type description, it indicates the protocol type (e.g. CAM, DENM, GN, ETH, PCAP...)

public: //! \publicsection
  /*!
   * \brief Default constructor
   *        Create a new instance of the layer class
   */
  explicit layer() : upperLayers(), lowerLayers(), type(std::string("")) { };

  /*!
   * \brief Specialized constructor
   *        Create a new instance of the layer class with its type description
   * \param[in] p_type The port type name (e.g. GN for the GeoNetworking layer)
   * \remark This constructor is called by the layer factory
   * \see layer_factory
   */
  explicit layer(const std::string& p_type) : upperLayers(), lowerLayers(), type(std::string(p_type.begin(), p_type.end())) { };

  /*!
   * \brief Default destructor
   * \todo Remove logs
   */
  virtual ~layer() {
    // Double linked list, only remove layers in lowerLayers from the lowest one
    std::for_each(lowerLayers.rbegin(), lowerLayers.rend(), [](layer* it) { delete it; } );
    lowerLayers.clear();
    upperLayers.clear();
  };

  /*!
   * \fn void delete_layer();
   * \brief Delete this layer
   * \todo To be implemented
   */
  void delete_layer() { };

public: //! \publicsection
  /*!
   * \inline
   * \fn void add_upper_layer(layer* p_layer);
   * \brief Add a new layer in the list of the upper layer
   * \param[in] p_layer The layer protocol to be removed
   */
  inline void add_upper_layer(layer* p_layer) {
    if (p_layer != NULL) {
      upperLayers.push_back(p_layer);
      p_layer->lowerLayers.push_back(this);
    };
  };

  /*!
   * \fn void remove_upper_layer(layer* p_layer);
   * \brief Remove the specified upper layer protocol from the list of the upper layer
   * \param[in] p_layer The layer protocol to be removed
   * \todo To be implemented
   */
  void remove_upper_layer(layer* p_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
   * \todo Remove the logs
   * \virtual
   */
  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
   * \todo Remove the logs
   * \virtual
   */
  virtual void receive_data(OCTETSTRING& p_data, params& p_params) { }

  /*!
   * \inline
   * \fn const std::string& to_string();
   * \brief Remove the specified upper layer protocol from the list of the upper layer
   * \param[in] The layer protocol to be removed
   */
  inline const std::string& to_string() const { return type; };

protected: //! \protectedsection
  inline void to_all_layers(std::vector<layer*>&layers, OCTETSTRING& data, params& params) {
    for (std::vector<layer*>::const_iterator it = layers.cbegin(); it != layers.cend(); ++it) {
      layer* p = *it;
      p->receive_data(data, params); // FIXME BUG I 
    } // End of 'for' statement
  };

  inline void receive_to_all_layers(OCTETSTRING& data, params& params) {
    for (std::vector<layer*>::const_iterator it = upperLayers.cbegin(); it != upperLayers.cend(); ++it) {
      layer* p = *it;
      p->receive_data(data, params);
    } // End of 'for' statement
  };

  inline void send_to_all_layers(OCTETSTRING& data, params& params)  {
    for (std::vector<layer*>::const_iterator it = lowerLayers.cbegin(); it != lowerLayers.cend(); ++it) {
      layer* p = *it;
      p->send_data(data, params);
    } // End of 'for' statement
  };
}; // End of class layer
+114 −0

File added.

Preview size limit exceeded, changes collapsed.

+67 −0
Original line number Diff line number Diff line
/*!
 * \file      layer_stack_builder.hh
 * \brief     Header file for ITS protocol stack builder.
 * \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_factory.hh"

/*!
 * \class layer_stack_builder
 * \brief  This class provides a factory class to create Layer class instances
 */
class layer_stack_builder {
private: //! \privatesection
  typedef std::map<std::string, layer_factory*> LayerFactoryMap;

  static layer_stack_builder * _instance;                        //! Smart pointer to the unique instance of the logger framework
  std::map<std::string, layer_factory*> _layer_factories; //! The list of the registered \see t_layer factories

  /*!
   * \brief Default constructor
   *        Create a new instance of the layer_stack_builder class
   * \private
   */
  layer_stack_builder(); // can not be created manually
public: //! \publicsection
  /*!
   * \fn layer_stack_builder* get_instance();
   * \brief Accessor for the unique instance of the logger framework
   * \static
   */
  static layer_stack_builder* get_instance();

  /*!
   * \fn void register_layer_factory(const std::string & p_type, layer_factory* p_layer_factory);
   * \brief Add a new layer factory
   * \param[in] p_type          The layer identifier (e.g. GN for the GeoNetworking layer...)
   * \param[in] p_layer_factory A reference to the \see layer_factory
   * \static
   */
  static void register_layer_factory(const std::string & p_type, layer_factory* p_layer_factory);

private: //! \privatesection
  /*!
   * \fn void _register_layer_factory(const std::string & p_type, layer_factory* p_layer_factory);
   * \brief Add a new layer factory
   * \param[in] p_type          The layer identifier (e.g. GN for the GeoNetworking layer...)
   * \param[in] p_layer_factory A reference to the \see layer_factory
   */
  void _register_layer_factory(const std::string & p_type, layer_factory* p_layer_factory);

public: //! \publicsection
  /*!
   * \fn layer* create_layer_stack(const char* p_layer_stack_description);
   * \brief Add a new layer factory
   * \param[in] p_layer_stack_description A textual description of the layer to create
   * \return The created layer object on success, nullptr otherwise
   */
  layer* create_layer_stack(const char* p_layer_stack_description);
}; // End of class layer_stack_builder
Loading