Commit bd3ed556 authored by garciay's avatar garciay
Browse files

Update HTTP Ng112 to ITS

parent 35d05505
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -17,6 +17,9 @@ int geonetworking_codec::encode (const LibItsGeoNetworking__TypesAndValues::GeoN
  
  TTCN_EncDec::clear_error();
  TTCN_Buffer encoding_buffer;

  _ec.reset();
  
  encode_(msg, *msg.get_descriptor(), encoding_buffer);
  data = OCTETSTRING(encoding_buffer.get_len(), encoding_buffer.get_data());
  // Overwrite the payload length
@@ -51,7 +54,7 @@ int geonetworking_codec::encode (const LibItsGeoNetworking__TypesAndValues::GnNo
    data = replace(data, _ec.length_position, rpl.lengthof(), rpl);
    loggers::get_instance().log_msg("geonetworking_codec::encode: after replace: ", data);
  }
  loggers::get_instance().log_msg("geonetworking_codec::decode: After encoding: ", data);
  loggers::get_instance().log_msg("geonetworking_codec::encode: After encoding: ", data);

  loggers::get_instance().log("<<< geonetworking_codec::encode");
  return 0;
@@ -143,6 +146,9 @@ int geonetworking_codec::decode (const OCTETSTRING& data, LibItsGeoNetworking__T
{
  TTCN_EncDec::clear_error();
  TTCN_Buffer decoding_buffer(data);

  _dc.reset();
  
  _params = params;
  
  loggers::get_instance().log_to_hexa(">>> geonetworking_codec::decode: decoding_buffer=", decoding_buffer);
+4 −2
Original line number Diff line number Diff line
@@ -26,7 +26,8 @@ struct encoding_context {
  unsigned int  length_position;
  unsigned int  length;

  encoding_context() { basic_header = 0xff; next_header = 0xff; header_type = 0xff; length_position = -1; length = -1; }
  encoding_context() { reset(); }
  void reset() { basic_header = 0xff; next_header = 0xff; header_type = 0xff; length_position = -1; length = -1; }
};
//typedef struct encoding_context encoding_context;

@@ -39,7 +40,8 @@ struct decoding_context {
  unsigned int               length;
  std::string                payload;

  decoding_context() : payload() { next_header = 0xff; header_type = 0xff; header_sub_type = 0xff; lifetime = 0; length = -1; }
  decoding_context() : payload() { reset(); }
  void reset() { next_header = 0xff; header_type = 0xff; header_sub_type = 0xff; lifetime = 0; length = -1; payload.clear(); }
};
//typedef struct decoding_context decoding_context;

+65 −199
Original line number Diff line number Diff line
@@ -7,8 +7,6 @@
#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)
{
@@ -21,7 +19,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;
@@ -56,10 +54,9 @@ 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;
@@ -72,11 +69,13 @@ 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);
      LibItsHttp__MessageBodyTypes::HttpMessageBody body;
          CHARSTRING body("");
        if (decode_body(decoding_buffer, body) == -1) {
              response.body().set_to_omit();
        } else if (body.lengthof() == 0) {
              response.body().set_to_omit();
        } else {
        response.body() = OPTIONAL<LibItsHttp__MessageBodyTypes::HttpMessageBody>(body);
              // TODO
        }
          msg.response() = response;
    } else { // HTTP request
@@ -95,12 +94,14 @@ int http_codec::decode (const OCTETSTRING& data, LibItsHttp__TypesAndValues::Htt
      LibItsHttp__TypesAndValues::HeaderLines headers;
      decode_headers(decoding_buffer, headers);
      request.header() = headers;
      OPTIONAL<LibItsHttp__MessageBodyTypes::HttpMessageBody> body;
      body.set_to_omit();
      loggers::get_instance().log_to_hexa("Before decoding Body: ", decoding_buffer);
      CHARSTRING body("");
        if (decode_body(decoding_buffer, body) == -1) {
              request.body().set_to_omit();
        } else if (body.lengthof() == 0) {
              request.body().set_to_omit();
        } else {
        request.body() = body;
              // TODO
        }
      msg.request() = request;
    }
@@ -118,20 +119,11 @@ 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<LibItsHttp__MessageBodyTypes::HttpMessageBody>& v = p_request.body();
  OCTETSTRING os;
  CHARSTRING body("");
  if (v.ispresent()) {
    const LibItsHttp__MessageBodyTypes::HttpMessageBody& body = static_cast<const LibItsHttp__MessageBodyTypes::HttpMessageBody&>(*v.get_opt_value());
    // FIXME body = static_cast<const CHARSTRING&>(*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());
@@ -150,8 +142,8 @@ 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) {
      p_encoding_buffer.put_cs(int2str(os.lengthof() + 2/*Stand for the last CRLF*/));
      _ec.is_content_length_present = 0x01;
      loggers::get_instance().log("http_codec::encode_request: body length: %d", body.lengthof());
      p_encoding_buffer.put_cs(int2str(body.lengthof()));
    } else {
      const OPTIONAL<LibItsHttp__TypesAndValues::charstring__list>& o = header.header__value();
      if (o.ispresent()) {
@@ -161,7 +153,7 @@ int http_codec::encode_request(const LibItsHttp__TypesAndValues::Request& p_requ
		  p_encoding_buffer.put_cs(v[0]);
		  int j = 1;
		  while (j < v.size_of()) {
                p_encoding_buffer.put_cs(", ");
				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;
@@ -172,85 +164,16 @@ int http_codec::encode_request(const LibItsHttp__TypesAndValues::Request& p_requ
    p_encoding_buffer.put_cs("\r\n");
  } // End of 'for' statement

  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
  if (body.lengthof() != 0) {
    p_encoding_buffer.put_cs(body);
  }
      } // else, do not include it
    }
    p_encoding_buffer.put_cs("\r\n");
  } // End of 'for' statement

  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");
  loggers::get_instance().log_to_hexa("http_codec::decode_headers", decoding_buffer);
@@ -275,6 +198,7 @@ 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
}
@@ -284,14 +208,12 @@ 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++) {
@@ -300,13 +222,8 @@ int http_codec::decode_header(CHARSTRING& header_line, LibItsHttp__TypesAndValue
      }
      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());
    }
    header.header__value() = OPTIONAL<LibItsHttp__TypesAndValues::charstring__list>(v);
    return 0;
  }
  catch(const std::logic_error& e) {
@@ -314,65 +231,14 @@ int http_codec::decode_header(CHARSTRING& header_line, LibItsHttp__TypesAndValue
  }
}

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

  // Sanity check
  if (decoding_buffer.get_len() - decoding_buffer.get_pos() <= 0) {
  loggers::get_instance().log_msg("<<< http_codec::decode_body: ", body);
  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;
    const unsigned char *cc_to = buffer.get_read_data();
@@ -383,7 +249,7 @@ int http_codec::get_line(TTCN_Buffer& buffer, CHARSTRING& to, const bool concate
    }

    while (true) {
      // Skip spaces, and empty lines
      // Skip spaces, and emplty 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("");
+3 −22
Original line number Diff line number Diff line
@@ -14,32 +14,13 @@ 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>(), _ec(), _dc() { };
  explicit http_codec() : codec<LibItsHttp__TypesAndValues::HttpMessage, LibItsHttp__TypesAndValues::HttpMessage>() { };
  virtual ~http_codec() { };

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

private:
  int encode_request (const LibItsHttp__TypesAndValues::Request& p_request, TTCN_Buffer& p_encoding_buffer);
  int encode_response (const LibItsHttp__TypesAndValues::Response& p_response, TTCN_Buffer& p_encoding_buffer);
//  int encode_response (const LibItsHttp__TypesAndValues::Request&, 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, LibItsHttp__MessageBodyTypes::HttpMessageBody& message_body);
  int decode_body(TTCN_Buffer& decoding_buffer, CHARSTRING& body);
  int get_line(TTCN_Buffer& buffer, CHARSTRING& to, const bool concatenate_header_lines = false);

}; // End of class http_codec