From 5bb431939198c76048c9d5a2553d406fdfabd16e Mon Sep 17 00:00:00 2001
From: garciay <yann.garcia@fscom.fr>
Date: Wed, 8 Jan 2025 16:52:13 +0100
Subject: [PATCH] Add bases for offline send_data

---
 ccsrc/Protocols/IP/ip_offline_layer.cc     | 62 ++++++++++++++++++++--
 ccsrc/Protocols/IP/ip_offline_layer.hh     |  3 ++
 ccsrc/Protocols/Sctp/sctp_offline_layer.cc | 46 ++++++++++++++--
 3 files changed, 103 insertions(+), 8 deletions(-)

diff --git a/ccsrc/Protocols/IP/ip_offline_layer.cc b/ccsrc/Protocols/IP/ip_offline_layer.cc
index 3070210..2a66d0f 100644
--- a/ccsrc/Protocols/IP/ip_offline_layer.cc
+++ b/ccsrc/Protocols/IP/ip_offline_layer.cc
@@ -1,3 +1,6 @@
+#include <netdb.h>
+#include <arpa/inet.h>
+
 #include "ip_offline_layer_factory.hh"
 
 #include "loggers.hh"
@@ -10,12 +13,33 @@ ip_offline_layer::ip_offline_layer(const std::string&  p_type, const std::string
 
 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();
 
-  //OCTETSTRING ip;
   // FIXME FSCOM: To be done
-  loggers::get_instance().error("ip_offline_layer::send_data: Not implemented. On;ly for offline mode");
-  //ip    += p_data;
-  //send_to_all_layers(ip, static_cast<params&>(p_params));
+  loggers::get_instance().warning("ip_offline_layer::send_data: Not implemented. Only for offline mode");
+  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<const unsigned char*>(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<const unsigned char*>(ip_addr));
+  ip_addr = int2oct(addr, 4); // Destination address
+  ip.put_s(ip_addr.lengthof(), static_cast<const unsigned char*>(ip_addr));
+
+  OCTETSTRING ip_pdu(ip.get_read_len(), ip.get_data());
+  ip_pdu += p_data;
+
+  send_to_all_layers(ip_pdu, static_cast<params&>(p_params));
 }
 
 void ip_offline_layer::receive_data(OCTETSTRING& p_data, params& p_params) {
@@ -70,4 +94,34 @@ void ip_offline_layer::receive_data(OCTETSTRING& p_data, params& p_params) {
   receive_to_all_layers(data, static_cast<params&>(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
index 3b31a80..352ddbc 100644
--- a/ccsrc/Protocols/IP/ip_offline_layer.hh
+++ b/ccsrc/Protocols/IP/ip_offline_layer.hh
@@ -16,6 +16,9 @@
 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
diff --git a/ccsrc/Protocols/Sctp/sctp_offline_layer.cc b/ccsrc/Protocols/Sctp/sctp_offline_layer.cc
index c6dbccb..051bdcf 100644
--- a/ccsrc/Protocols/Sctp/sctp_offline_layer.cc
+++ b/ccsrc/Protocols/Sctp/sctp_offline_layer.cc
@@ -24,12 +24,44 @@ sctp_offline_layer::~sctp_offline_layer() {
 
 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();
 
-  //OCTETSTRING sctp;
   // FIXME FSCOM: To be done
-  loggers::get_instance().error("sctp_offline_layer::send_data: Not implemented. On;ly for offline mode");
-  //sctp    += p_data;
-  //send_to_all_layers(sctp, static_cast<params&>(p_params));
+  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<const unsigned char*>(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<const unsigned char*>(protocol));
+  chunk.put_s(p_data.lengthof(), static_cast<const unsigned char*>(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<const unsigned char*>(vt));
+  OCTETSTRING checksum = int2oct(0, 4); // Checksum
+  sctp.put_s(checksum.lengthof(), static_cast<const unsigned char*>(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<params&>(p_params));
 }
 
 void sctp_offline_layer::receive_data(OCTETSTRING &p_data, params &p_params) {
@@ -104,6 +136,12 @@ void sctp_offline_layer::process_chunk(const OCTETSTRING& p_chunk, params &p_par
       break;
     case 0x02: // INIT_ACK chunk
       break;
+    case 0x03: // SACK
+      break;
+    case 0x04: // HEARTBEAT
+      break;
+    case 0x05: // HEARTBEAT_ACK
+      break;
     case 0x0a: // COOKIE_ECHO chunk
       break;
     case 0x0b: // COOKIE_ACK chunk
-- 
GitLab