Commit 35d05505 authored by garciay's avatar garciay
Browse files

Update HTTP Ng112 to ITS

parent 195467ce
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line

#include "LibItsHttp_MessageBodyTypes.hh"

#include "http_codec.hh"

#include "loggers.hh"

namespace LibItsHttp__EncdecDeclarations {

    BITSTRING fx__enc__http__message(const LibItsHttp__TypesAndValues::HttpMessage& p) { return BITSTRING(); }
    INTEGER fx__dec__http__message(BITSTRING& pdu, LibItsHttp__TypesAndValues::HttpMessage& p) {
        loggers::get_instance().log_msg(">>> fx__dec__http__response: ", pdu);

        OCTETSTRING os = bit2oct(pdu);
        http_codec codec;
        codec.decode(os, p);

        return 0;
    }
} // End of namespace LibItsHttp__EncdecDeclarations
+90 −0
Original line number Diff line number Diff line
#include "HttpPort.hh"
#include "http_layer_factory.hh"
#include "loggers.hh"

namespace LibItsHttp__TestSystem {

  HttpPort::HttpPort(const char *par_port_name): HttpPort_BASE(par_port_name), _cfg_params(), _layer_params(), _layer(nullptr), _time_key("HttpPort::outgoing_send") {
    // Nothing to do
  } // End of constructor

  HttpPort::~HttpPort() {
    loggers::get_instance().log(">>> HttpPort::~HttpPort");

    if (_layer != nullptr) {
      delete _layer;
    }
  } // End of destructor

  void HttpPort::set_parameter(const char * parameter_name, const char * parameter_value)
  {
    loggers::get_instance().log("HttpPort::set_parameter: %s=%s", parameter_name, parameter_value);
    _cfg_params.insert(std::pair<std::string, std::string>(std::string(parameter_name), std::string(parameter_value)));
  }

  /*void HttpPort::Handle_Fd_Event(int fd, boolean is_readable,
    boolean is_writable, boolean is_error) {}*/

  void HttpPort::Handle_Fd_Event_Error(int /*fd*/)
  {

  }

  void HttpPort::Handle_Fd_Event_Writable(int /*fd*/)
  {

  }

  void HttpPort::Handle_Fd_Event_Readable(int /*fd*/)
  {

  }

  /*void HttpPort::Handle_Timeout(double time_since_last_call) {}*/

  void HttpPort::user_map(const char * system_port)
  {
    loggers::get_instance().log(">>> HttpPort::user_map: %s", system_port);
    // Build layer stack
    params::iterator it = _cfg_params.find(std::string("params"));
    if (it != _cfg_params.end()) {
      loggers::get_instance().log("HttpPort::user_map: %s", it->second.c_str());
      // Setup parameters
      params::convert(_layer_params, it->second); // TODO This _layer_params seems to be useless
      // Create layer
      _layer = layer_stack_builder::get_instance()->create_layer_stack(it->second.c_str());
      if (static_cast<http_layer *>(_layer) == nullptr) {
        loggers::get_instance().error("HttpPort::user_map: Invalid stack configuration: %s", it->second.c_str());
      }
      static_cast<http_layer *>(_layer)->add_upper_port(this);

    } else {
      loggers::get_instance().error("HttpPort::user_map: No layers defined in configuration file");
    }
  } // End of user_map method

  void HttpPort::user_unmap(const char * system_port)
  {
    loggers::get_instance().log(">>> HttpPort::user_unmap: %s", system_port);

    // Reset layers
    if (_layer != nullptr) {
      delete _layer;
      _layer = nullptr;
    }
  } // End of user_unmap method

  void HttpPort::user_start()
  {
    loggers::get_instance().log(">>> HttpPort::user_start");

  } // End of user_start method

  void HttpPort::user_stop()
  {
    loggers::get_instance().log(">>> HttpPort::user_stop");

  } // End of user_stop method

}
+46 −0
Original line number Diff line number Diff line
#pragma once

#include "LibItsHttp_TestSystem.hh"

#include "layer.hh"
#include "params.hh"

namespace LibItsHttp__TypesAndValues {
  class REGISTER__Request;
}

namespace LibItsHttp__TestSystem {

  class HttpPort : public HttpPort_BASE {
    params _cfg_params;
    params _layer_params;
    layer* _layer;
    std::string _time_key;
  public:
    HttpPort(const char *par_port_name);
    ~HttpPort();

    void set_parameter(const char *parameter_name, const char *parameter_value);
    void receiveMsg (const LibItsHttp__TypesAndValues::REGISTER__Request&, const params&);

  private:
    /* void Handle_Fd_Event(int fd, boolean is_readable,
       boolean is_writable, boolean is_error); */
    void Handle_Fd_Event_Error(int fd);
    void Handle_Fd_Event_Writable(int fd);
    void Handle_Fd_Event_Readable(int fd);
    /* void Handle_Timeout(double time_since_last_call); */

  protected:
    void user_map(const char *system_port);
    void user_unmap(const char *system_port);

    void user_start();
    void user_stop();

  protected:
    virtual void outgoing_send(const LibItsHttp__TypesAndValues::HttpMessage& send_par) { };
  }; // End of class HttpPort

}
+269 −132
Original line number Diff line number Diff line
@@ -7,6 +7,8 @@
#include "loggers.hh"

#include "LibItsHttp_TypesAndValues.hh"
#include "LibItsHttp_MessageBodyTypes.hh"
#include "LibItsHttp_XmlMessageBodyTypes.hh"

int http_codec::encode (const LibItsHttp__TypesAndValues::HttpMessage& msg, OCTETSTRING& data)
{
@@ -19,7 +21,7 @@ int http_codec::encode (const LibItsHttp__TypesAndValues::HttpMessage& msg, OCTE
  if (msg.ischosen(LibItsHttp__TypesAndValues::HttpMessage::ALT_request)) {
    result = encode_request(msg.request(), encoding_buffer);
  } else if (msg.ischosen(LibItsHttp__TypesAndValues::HttpMessage::ALT_response)) {
    //result = encode_response(msg.response(), encoding_buffer);
    result = encode_response(msg.response(), encoding_buffer);
  } else {
    loggers::get_instance().warning("http_codec::encode: Unbound HttpMessage");
    return -1;
@@ -54,9 +56,10 @@ int http_codec::decode (const OCTETSTRING& data, LibItsHttp__TypesAndValues::Htt
    loggers::get_instance().log("http_codec::decode: %d - %s", m.size(), m[0].str().c_str());
    if (m[0].str().compare("HTTP/") == 0) { // HTTP response
      LibItsHttp__TypesAndValues::Response response;
		std::regex rgx ("\\s*HTTP/(\\d)\\.(\\d)\\s+(\\d+)\\s+(\\w+)");
      std::regex rgx ("\\s*HTTP/(\\d+)\\.(\\d+)\\s+(\\d+)\\s+(\\w+)*");
      std::sregex_iterator begin(str.cbegin(), str.cend(), rgx);
      std::smatch m = *begin;
      loggers::get_instance().log("http_codec::decode: Process response: %d", m.size());
      if (m.size() != 5) {
        loggers::get_instance().error("http_codec::decode: Unsupported tag");
        return -1;
@@ -69,13 +72,11 @@ int http_codec::decode (const OCTETSTRING& data, LibItsHttp__TypesAndValues::Htt
      decode_headers(decoding_buffer, headers);
      response.header() = headers;
      loggers::get_instance().log_to_hexa("Before decoding Body: ", decoding_buffer);
    	CHARSTRING body("");
      LibItsHttp__MessageBodyTypes::HttpMessageBody body;
      if (decode_body(decoding_buffer, body) == -1) {
        response.body().set_to_omit();
        } else if (body.lengthof() == 0) {
        	response.body().set_to_omit();
      } else {
        	// TODO
        response.body() = OPTIONAL<LibItsHttp__MessageBodyTypes::HttpMessageBody>(body);
      }
       msg.response() = response;
    } else { // HTTP request
@@ -94,14 +95,12 @@ int http_codec::decode (const OCTETSTRING& data, LibItsHttp__TypesAndValues::Htt
      LibItsHttp__TypesAndValues::HeaderLines headers;
      decode_headers(decoding_buffer, headers);
      request.header() = headers;
		loggers::get_instance().log_to_hexa("Before decoding Body: ", decoding_buffer);
    	CHARSTRING body("");
      OPTIONAL<LibItsHttp__MessageBodyTypes::HttpMessageBody> body;
      body.set_to_omit();
      if (decode_body(decoding_buffer, body) == -1) {
        request.body().set_to_omit();
        } else if (body.lengthof() == 0) {
        	request.body().set_to_omit();
      } else {
        	// TODO
        request.body() = body;
      }
      msg.request() = request;
    }
@@ -118,12 +117,21 @@ int http_codec::encode_request(const LibItsHttp__TypesAndValues::Request& p_requ
{
  loggers::get_instance().log_msg(">>> http_codec::encode_request: ", (const Base_Type&)p_request);

  const OPTIONAL<CHARSTRING>& v = p_request.body();
  CHARSTRING body("");
  const OPTIONAL<LibItsHttp__MessageBodyTypes::HttpMessageBody>& v = p_request.body();
  OCTETSTRING os;
  if (v.ispresent()) {
    body = static_cast<const CHARSTRING&>(*v.get_opt_value());
    const LibItsHttp__MessageBodyTypes::HttpMessageBody& body = static_cast<const LibItsHttp__MessageBodyTypes::HttpMessageBody&>(*v.get_opt_value());
    loggers::get_instance().log_msg("http_codec::encode_request: body: ", body);
    if (body.ischosen(LibItsHttp__MessageBodyTypes::HttpMessageBody::ALT_ms__body)) {
      os = body.ms__body();
    } else {
      LibItsHttp__XmlMessageBodyTypes::XmlBody xml_body = body.xml__body();
      if (xml_body.ischosen(LibItsHttp__XmlMessageBodyTypes::XmlBody::ALT_raw)) {
        os = OCTETSTRING(xml_body.raw().lengthof(), (unsigned char*)static_cast<const char*>(xml_body.raw()));
      }
    }
  }
  loggers::get_instance().log("http_codec::encode_request: HTTP message lenght: %d ", os.lengthof());

  // Encode generic part
  p_encoding_buffer.put_cs(p_request.method());
@@ -142,33 +150,106 @@ int http_codec::encode_request(const LibItsHttp__TypesAndValues::Request& p_requ
    p_encoding_buffer.put_cs(header.header__name());
    p_encoding_buffer.put_cs(": ");
    if (std::string(static_cast<const char*>(header.header__name())).compare("Content-Length") == 0) {
      loggers::get_instance().log("http_codec::encode_request: body length: %d", body.lengthof());
      p_encoding_buffer.put_cs(int2str(body.lengthof()));
      p_encoding_buffer.put_cs(int2str(os.lengthof() + 2/*Stand for the last CRLF*/));
      _ec.is_content_length_present = 0x01;
    } else {
		if (header.header__value().size_of() > 0) {
		  loggers::get_instance().log_msg("http_codec::encode_request: Processing value ", header.header__value()[0]);
		  p_encoding_buffer.put_cs(header.header__value()[0]);
      const OPTIONAL<LibItsHttp__TypesAndValues::charstring__list>& o = header.header__value();
      if (o.ispresent()) {
        const LibItsHttp__TypesAndValues::charstring__list& v = dynamic_cast<const OPTIONAL<LibItsHttp__TypesAndValues::charstring__list> &>(o);
        if (v.size_of() > 0) {
          loggers::get_instance().log_msg("http_codec::encode_request: Processing value ", v[0]);
          p_encoding_buffer.put_cs(v[0]);
          int j = 1;
		  while (j < header.header__value().size_of()) {
			  p_encoding_buffer.put_cs("; ");
			  loggers::get_instance().log_msg("http_codec::encode_request: Processing value ", header.header__value()[j]);
			  p_encoding_buffer.put_cs(header.header__value()[j]);
          while (j < v.size_of()) {
                p_encoding_buffer.put_cs(", ");
                loggers::get_instance().log_msg("http_codec::encode_request: Processing value ", v[j]);
                p_encoding_buffer.put_cs(v[j]);
                j += 1;
          } // End of 'while' statement
        }
      } // else, do not include it
    }
    p_encoding_buffer.put_cs("\r\n");
  } // End of 'for' statement

  if (body.lengthof() != 0) {
    p_encoding_buffer.put_cs(body);
  p_encoding_buffer.put_cs("\r\n");
  if (_ec.length != 0) {
    p_encoding_buffer.put_os(os);
    p_encoding_buffer.put_cs("\r\n");
  }

  return 0;
}

int http_codec::encode_response (const LibItsHttp__TypesAndValues::Response& p_response, TTCN_Buffer& p_encoding_buffer) {
  loggers::get_instance().log_msg(">>> http_codec::encode_response: ", (const Base_Type&)p_response);

  const OPTIONAL<LibItsHttp__MessageBodyTypes::HttpMessageBody>& v = p_response.body();
  OCTETSTRING os;
  if (v.ispresent()) {
    const LibItsHttp__MessageBodyTypes::HttpMessageBody& body = static_cast<const LibItsHttp__MessageBodyTypes::HttpMessageBody&>(*v.get_opt_value());
    loggers::get_instance().log_msg("http_codec::encode_response: body: ", body);
    if (body.ischosen(LibItsHttp__MessageBodyTypes::HttpMessageBody::ALT_ms__body)) {
      os = body.ms__body();
    } else {
      LibItsHttp__XmlMessageBodyTypes::XmlBody xml_body = body.xml__body();
      if (xml_body.ischosen(LibItsHttp__XmlMessageBodyTypes::XmlBody::ALT_raw)) {
        os = OCTETSTRING(xml_body.raw().lengthof(), (unsigned char*)static_cast<const char*>(xml_body.raw()));
      }
    }
  }
  loggers::get_instance().log("http_codec::encode_response: HTTP message lenght: %d ", os.lengthof());

  // Encode generic part
  p_encoding_buffer.put_cs("HTTP/");
  p_encoding_buffer.put_cs(int2str(p_response.version__major()));
  p_encoding_buffer.put_c('.');
  p_encoding_buffer.put_cs(int2str(p_response.version__minor()));
  p_encoding_buffer.put_cs(" ");
  p_encoding_buffer.put_cs(int2str(p_response.statuscode()));
  p_encoding_buffer.put_cs(" ");
  if (p_response.statustext().lengthof() != 0) {
    p_encoding_buffer.put_cs(p_response.statustext());
  }
  p_encoding_buffer.put_cs("\r\n");
  // Encode headers
  const LibItsHttp__TypesAndValues::HeaderLines& headers = p_response.header();
  for (int i = 0; i < headers.size_of(); i++) {
    const LibItsHttp__TypesAndValues::HeaderLine& header = headers[i];
    loggers::get_instance().log_msg("http_codec::encode_response: Processing header ", header.header__name());
    p_encoding_buffer.put_cs(header.header__name());
    p_encoding_buffer.put_cs(": ");
    if (std::string(static_cast<const char*>(header.header__name())).compare("Content-Length") == 0) {
      p_encoding_buffer.put_cs(int2str(os.lengthof() + 2/*Stand for the last CRLF*/));
      _ec.is_content_length_present = 0x01;
    } else {
      const OPTIONAL<LibItsHttp__TypesAndValues::charstring__list>& o = header.header__value();
      if (o.ispresent()) {
        const LibItsHttp__TypesAndValues::charstring__list& v = dynamic_cast<const OPTIONAL<LibItsHttp__TypesAndValues::charstring__list> &>(o);
        if (v.size_of() > 0) {
          loggers::get_instance().log_msg("http_codec::encode_response: Processing value ", v[0]);
          p_encoding_buffer.put_cs(v[0]);
          int j = 1;
          while (j < v.size_of()) {
                p_encoding_buffer.put_cs(", ");
                loggers::get_instance().log_msg("http_codec::encode_response: Processing value ", v[j]);
                p_encoding_buffer.put_cs(v[j]);
                j += 1;
          } // End of 'while' statement
        }
      } // else, do not include it
    }
    p_encoding_buffer.put_cs("\r\n");
  } // End of 'for' statement

  return 0;
  p_encoding_buffer.put_cs("\r\n");
  if (_ec.length != 0) {
    p_encoding_buffer.put_os(os);
    p_encoding_buffer.put_cs("\r\n");
  }

  return 0;
}

int http_codec::decode_headers(TTCN_Buffer& decoding_buffer, LibItsHttp__TypesAndValues::HeaderLines& headers) {
  loggers::get_instance().log(">>> http_codec::decode_headers");
@@ -194,7 +275,6 @@ int http_codec::decode_headers(TTCN_Buffer& decoding_buffer, LibItsHttp__TypesAn
      case -1:
        loggers::get_instance().warning("http_codec::decode_headers: Failed to decode headers");
        return -1;

    } // End of 'switch' statement
  } // End of 'while' statement
}
@@ -204,18 +284,28 @@ int http_codec::decode_header(CHARSTRING& header_line, LibItsHttp__TypesAndValue

  try {
    std::string str(static_cast<const char*>(header_line));
	std::regex rgx ("([0-9a-zA-Z-]+)\\:\\s+(.+)(;(.+))*");
    std::regex rgx ("([0-9a-zA-Z-]+)\\:\\s+(.+)(,(.+))*");
    std::sregex_iterator begin(str.cbegin(), str.cend(), rgx);
    std::smatch m = *begin;
    if (m.size() < 5) {
      loggers::get_instance().warning("http_codec::decode_header: Failed to decode header %s", str.c_str());
      return -1;
    }
    loggers::get_instance().log("http_codec::decode_header: %d", m.size());
    header.header__name() = CHARSTRING(m[1].str().c_str());
    LibItsHttp__TypesAndValues::charstring__list v;
    for (unsigned int j = 0; j < m.size(); j++) {
      if (m[j + 2].str().length() == 0) {
        break;
      }
		header.header__value()[j] = CHARSTRING(m[j + 2].str().c_str());
      v[j] = CHARSTRING(m[j + 2].str().c_str());
    } // End of 'for' statement
    header.header__value() = OPTIONAL<LibItsHttp__TypesAndValues::charstring__list>(v);

    if (m[1].str().compare("Content-Length") == 0) {
      // Save the the body length
      loggers::get_instance().log("http_codec::decode_header: decoded Content-Length %s", m[2].str().c_str());
      _dc.length = std::stoi(m[2].str());
    }
    return 0;
  }
@@ -224,17 +314,64 @@ int http_codec::decode_header(CHARSTRING& header_line, LibItsHttp__TypesAndValue
  }
}

int http_codec::decode_body(TTCN_Buffer& decoding_buffer, CHARSTRING& body) {
int http_codec::decode_body(TTCN_Buffer& decoding_buffer, LibItsHttp__MessageBodyTypes::HttpMessageBody& message_body) {
  loggers::get_instance().log(">>> http_codec::decode_body");
  loggers::get_instance().log_to_hexa("http_codec::decode_body", decoding_buffer);

  loggers::get_instance().log_msg("<<< http_codec::decode_body: ", body);
  // Sanity check
  if (decoding_buffer.get_len() - decoding_buffer.get_pos() <= 0) {
    return -1;
  }

  OCTETSTRING s(decoding_buffer.get_len() - decoding_buffer.get_pos(), decoding_buffer.get_data() + decoding_buffer.get_pos());
  loggers::get_instance().log_msg("http_codec::decode_body: raw body=", s);
  // Align the payload length with the specified plLenght value
  loggers::get_instance().log("http_codec::decode_body: _dc.length=%d - body length=%d", _dc.length, s.lengthof());
  OCTETSTRING body;
  if (_dc.length != 0) {
    const unsigned char* p = static_cast<const unsigned char *>(s);
    if ((unsigned int)s.lengthof() <= _dc.length) {
      body = OCTETSTRING(s.lengthof(), p);
    } else {
      body = OCTETSTRING(_dc.length, p);
    }
  } else {
    loggers::get_instance().warning("http_codec::decode_body: No Conten-Length header, process all remaining bytes");
    body = s;
  }
  loggers::get_instance().log_msg("http_codec::decode_body: Aligned body=", body);
  // Remove CRLF if any
  int counter = 0;
  if ((body[body.lengthof() - 1].get_octet() == 0x0d) || (body[body.lengthof() - 1].get_octet() == 0x0a)) {
    counter += 1;
    if ((body[body.lengthof() - 2].get_octet() == 0x0d) || (body[body.lengthof() - 2].get_octet() == 0x0a)) {
      counter += 1;
    }
  }
  loggers::get_instance().log("http_codec::decode_body: Counter=%d", counter);
  body = OCTETSTRING(body.lengthof() - counter, static_cast<const unsigned char*>(body));
  loggers::get_instance().log_msg("http_codec::decode_body: Finalised body=", body);
  // Check if HTTP message body contains binary characters
  for (int i = 0; i < body.lengthof(); i++) {
    unsigned char c = body[i].get_octet();
    if (!std::isprint(c) && !std::isspace(c) && !std::ispunct(c)) {
      loggers::get_instance().log("http_codec::decode_body: Byte #%d is not printable: 0x%02x", i, body[i].get_octet());
      _dc.is_binary = 0x01;
      break;
    }
  } // End of 'for' statement
  loggers::get_instance().log("http_codec::decode_body: Binary mode: %x", _dc.is_binary);
  LibItsHttp__MessageBodyTypes::HttpMessageBody v;
  if (_dc.is_binary == 0x01) {
    message_body.ms__body() = body;
  } else {
    LibItsHttp__XmlMessageBodyTypes::XmlBody xml_body;
    xml_body.raw() = CHARSTRING(body.lengthof(), (char*)static_cast<const unsigned char*>(body));
    message_body.xml__body() = xml_body;
  }
  


  return 0;
}

int http_codec::get_line(TTCN_Buffer& buffer, CHARSTRING& to, const bool concatenate_header_lines) {
    unsigned int i = 0;
@@ -246,7 +383,7 @@ int http_codec::get_line(TTCN_Buffer& buffer, CHARSTRING& to, const bool concate
    }

    while (true) {
      // Skip spaces, and emplty lines
      // Skip spaces, and empty lines
        for( ; i < buffer.get_read_len() && cc_to[i] != '\0' && cc_to[i] != '\r' && cc_to[i] != '\n'; i++);
        if(i >= buffer.get_read_len()) { // No more characters to process
            to = CHARSTRING("");
+22 −3
Original line number Diff line number Diff line
@@ -14,13 +14,32 @@ namespace LibItsHttp__TypesAndValues {
  class HeaderLines;
  class HeaderLine;
}
namespace LibItsHttp__MessageBodyTypes {
  class HttpMessageBody;
}

struct encoding_context {
  unsigned int length;
  unsigned char is_content_length_present;

  encoding_context() { length = -1; is_content_length_present = 0x00; };
};

struct decoding_context {
  unsigned int length;
  unsigned char is_binary;

  decoding_context() { length = -1; is_binary = 0x00; };
};

class http_codec: public codec <
LibItsHttp__TypesAndValues::HttpMessage,
LibItsHttp__TypesAndValues::HttpMessage>
{
  encoding_context _ec;
  decoding_context _dc;
public:
  explicit http_codec() : codec<LibItsHttp__TypesAndValues::HttpMessage, LibItsHttp__TypesAndValues::HttpMessage>() { };
  explicit http_codec() : codec<LibItsHttp__TypesAndValues::HttpMessage, LibItsHttp__TypesAndValues::HttpMessage>(), _ec(), _dc() { };
  virtual ~http_codec() { };

  virtual int encode (const LibItsHttp__TypesAndValues::HttpMessage&, OCTETSTRING& data);
@@ -28,11 +47,11 @@ public:

private:
  int encode_request (const LibItsHttp__TypesAndValues::Request& p_request, TTCN_Buffer& p_encoding_buffer);
//  int encode_response (const LibItsHttp__TypesAndValues::Request&, TTCN_Buffer& p_encoding_buffer);
  int encode_response (const LibItsHttp__TypesAndValues::Response& p_response, TTCN_Buffer& p_encoding_buffer);

  int decode_headers(TTCN_Buffer& decoding_buffer, LibItsHttp__TypesAndValues::HeaderLines& headers);
  int decode_header(CHARSTRING& header_line, LibItsHttp__TypesAndValues::HeaderLine& header);
  int decode_body(TTCN_Buffer& decoding_buffer, CHARSTRING& body);
  int decode_body(TTCN_Buffer& decoding_buffer, LibItsHttp__MessageBodyTypes::HttpMessageBody& message_body);
  int get_line(TTCN_Buffer& buffer, CHARSTRING& to, const bool concatenate_header_lines = false);

}; // End of class http_codec
Loading