Commit 5f57c369 authored by Yann Garcia's avatar Yann Garcia
Browse files

Adding ttcn/patch_abstract_socket

parent b544fc15
Loading
Loading
Loading
Loading
+170 −0
Original line number Diff line number Diff line
diff --git a/home/yann/tmp/titan.TestPorts.Common_Components.Abstract_Socket/src/Abstract_Socket.cc b/./Abstract_Socket.cc
index 8b7b753..af41462 100644
--- a/home/yann/tmp/titan.TestPorts.Common_Components.Abstract_Socket/src/Abstract_Socket.cc
+++ b/./Abstract_Socket.cc
@@ -40,6 +40,7 @@
 # include <signal.h>
 #endif
 
+#include <netinet/sctp.h>
 
 #define AS_TCP_CHUNCK_SIZE 4096
 #define AS_SSL_CHUNCK_SIZE 16384
@@ -171,6 +172,7 @@ Abstract_Socket::Abstract_Socket() {
   remote_host_name = NULL;
   remote_port_number = 0;
   ai_family = AF_UNSPEC; // default: Auto
+  ip_proto = IPPROTO_TCP; // default
   test_port_type=NULL;
   test_port_name=NULL;
   ttcn_buffer_usercontrol=false;
@@ -199,6 +201,7 @@ Abstract_Socket::Abstract_Socket(const char *tp_type, const char *tp_name) {
   remote_host_name = NULL;
   remote_port_number = 0;
   ai_family = AF_UNSPEC; // default: Auto
+  ip_proto = IPPROTO_TCP; // default
   test_port_type=tp_type;
   test_port_name=tp_name;
   ttcn_buffer_usercontrol=false;
@@ -261,6 +264,10 @@ bool Abstract_Socket::parameter_set(const char *parameter_name,
     else if (strcasecmp(parameter_value,"IPv4")==0 || strcasecmp(parameter_value,"AF_INET")==0) ai_family = AF_INET;
     else if (strcasecmp(parameter_value,"UNSPEC")==0 || strcasecmp(parameter_value,"AF_UNSPEC")==0) ai_family = AF_UNSPEC;
     else log_error("Parameter value '%s' not recognized for parameter '%s'", parameter_value, ai_family_name());
+  } else if(strcmp(parameter_name, ip_proto_name()) == 0){
+    if (strcasecmp(parameter_value,"IPPROTO_TCP")==0) ip_proto = IPPROTO_TCP;
+    else if (strcasecmp(parameter_value,"IPPROTO_SCTP")==0) ip_proto = IPPROTO_SCTP;
+    else log_error("Parameter value '%s' not recognized for parameter '%s'", parameter_value, ip_proto_name());
   } else if(strcmp(parameter_name, local_port_name()) == 0){
     int a;
     if (sscanf(parameter_value, "%d", &a)!=1) log_error("Invalid input as port number given: %s", parameter_value);
@@ -760,6 +767,7 @@ int Abstract_Socket::open_listen_port(const char* localHostname, const char* loc
   hints.ai_flags = /*AI_ALL|*/AI_ADDRCONFIG|AI_PASSIVE;
   hints.ai_socktype = SOCK_STREAM;
   hints.ai_family = ai_family;
+  hints.ai_protocol = ip_proto;
 
   error = getaddrinfo(localHostname, localServicename, &hints, &aip);
   if (error != 0) {
@@ -818,6 +826,26 @@ int Abstract_Socket::open_listen_port(const char* localHostname, const char* loc
       else log_error("Setsockopt failed");
     }
 
+     if (ip_proto==IPPROTO_SCTP){
+      // Subscribe to SCTP events
+      sctp_event_subscribe events{};
+      memset(&events, 0, sizeof(events));
+      events.sctp_data_io_event = 1;
+      //events.sctp_association_event = 1;
+      //events.sctp_shutdown_event = 1;
+      if (setsockopt(listen_fd, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof(events))==-1){
+        log_error("Setsockopt SCTP event failed");
+      }
+
+      linger l;
+      memset(&l, 0, sizeof(l));
+      l.l_onoff=1;  /* option on/off */
+      l.l_linger=0;
+      if (setsockopt(listen_fd, SOL_SOCKET, SO_LINGER, (void *)&l, sizeof (l)) == -1){
+        log_error("Setsockopt SCTP socket linger failed");
+      }
+    }
+
     if(!nagling) {
       int on = 1;
       setsockopt(listen_fd, IPPROTO_TCP, TCP_NODELAY, (const char*)&on, sizeof(on));
@@ -1143,6 +1171,7 @@ int Abstract_Socket::open_client_connection(const char* remoteHostname, const ch
   }
   hints.ai_socktype = SOCK_STREAM;
   hints.ai_family = ai_family;
+  hints.ai_protocol = ip_proto;
 
   error = getaddrinfo(remoteHostname, remoteServicename, &hints, &res);
   if (error != 0) {
@@ -1191,12 +1220,13 @@ int Abstract_Socket::open_client_connection(const char* remoteHostname, const ch
       }
     }
     
-    log_debug("Using address family for socket %d: %s",socket_fd,
+    log_debug("Using address family for socket %d: %s - %s",socket_fd,
       ((aip->ai_family==AF_INET)?"IPv4":
-       ((aip->ai_family==AF_INET6)?"IPv6":"unknown"))
+       ((aip->ai_family==AF_INET6)?"IPv6":"unknown")),
+      ((aip->ai_protocol==IPPROTO_TCP)?"IPPROTO_TCP":
+        ((aip->ai_protocol==IPPROTO_SCTP)?"IPPROTO_SCTP":"unknown"))
     );
-
-
+        
     if(!nagling) {
       int on = 1;
       setsockopt(socket_fd, IPPROTO_TCP, TCP_NODELAY, (const char*)&on, sizeof(on));
@@ -1225,6 +1255,7 @@ int Abstract_Socket::open_client_connection(const char* remoteHostname, const ch
       hints.ai_flags = AI_PASSIVE;
       hints.ai_socktype = SOCK_STREAM;
       hints.ai_family = ai_family;//aip->ai_family; // NOTE: On solaris 10 if is set to aip->ai_family, getaddrinfo will crash for IPv4-mapped addresses!
+      hints.ai_protocol = ip_proto;
 
       error = getaddrinfo(localHostname, localServicename, &hints, &localAddrinfo);
       if (error != 0) {
@@ -1390,10 +1421,35 @@ int Abstract_Socket::open_client_connection(const char* remoteHostname, const ch
     }
 
     log_debug(
-      "connected to: host %s service %s via address family %s\n",
+      "connected to: host %s service %s via address family %s with ip_proto %s\n",
       remoteHostname, remoteServicename,
       ((aip->ai_family==AF_INET)?"IPv4":
-        ((aip->ai_family==AF_INET6)?"IPv6":"unknown")));
+        ((aip->ai_family==AF_INET6)?"IPv6":"unknown")),
+      ((aip->ai_protocol==IPPROTO_TCP)?"IPPROTO_TCP":
+        ((aip->ai_protocol==IPPROTO_SCTP)?"IPPROTO_SCTP":"unknown"))
+        );
+    
+    if(ip_proto==IPPROTO_SCTP){
+    //if (aip->ai_protocol==IPPROTO_SCTP){
+      log_debug("Setting events,linger for SCTP socket!");
+      // Subscribe to SCTP events
+      sctp_event_subscribe events{};
+      memset(&events, 0, sizeof(events));
+      events.sctp_data_io_event = 1;
+      //events.sctp_association_event = 1;
+      //events.sctp_shutdown_event = 1;
+      if (setsockopt(socket_fd, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof(events))==-1){
+        log_error("Setsockopt SCTP event failed");
+      }
+
+      linger l;
+      memset(&l, 0, sizeof(l));
+      l.l_onoff=1;  /* option on/off */
+      l.l_linger=0;
+      if (setsockopt(socket_fd, SOL_SOCKET, SO_LINGER, (void *)&l, sizeof (l)) == -1){
+        log_error("Setsockopt SCTP socket linger failed");
+      }
+    }//else{log_debug("not ipproto sctp!");}
     break;
   }
   if (aip==NULL) {
@@ -1774,18 +1830,19 @@ const char* Abstract_Socket::remote_address_name()          { return "destIPAddr
 const char* Abstract_Socket::local_address_name()           { return "serverIPAddr";}
 const char* Abstract_Socket::remote_port_name()             { return "destPort";}
 const char* Abstract_Socket::ai_family_name()               { return "ai_family";}
+const char* Abstract_Socket::ip_proto_name()                { return "ip_proto";}
 const char* Abstract_Socket::use_connection_ASPs_name()     { return "use_connection_ASPs";}
 const char* Abstract_Socket::halt_on_connection_reset_name(){ return "halt_on_connection_reset";}
-const char* Abstract_Socket::client_TCP_reconnect_name()	{ return "client_TCP_reconnect";}
+const char* Abstract_Socket::client_TCP_reconnect_name()	  { return "client_TCP_reconnect";}
 const char* Abstract_Socket::TCP_reconnect_attempts_name()	{ return "TCP_reconnect_attempts";}
-const char* Abstract_Socket::TCP_reconnect_delay_name()		{ return "TCP_reconnect_delay";}
+const char* Abstract_Socket::TCP_reconnect_delay_name()	  	{ return "TCP_reconnect_delay";}
 const char* Abstract_Socket::server_mode_name()             { return "server_mode";}
 const char* Abstract_Socket::socket_debugging_name()        { return "socket_debugging";}
 const char* Abstract_Socket::nagling_name()                 { return "nagling";}
 const char* Abstract_Socket::use_non_blocking_socket_name() { return "use_non_blocking_socket";}
 const char* Abstract_Socket::server_backlog_name()          { return "server_backlog";}
-bool Abstract_Socket::add_user_data(int) {return true;}
-bool Abstract_Socket::remove_user_data(int) {return true;}
+bool Abstract_Socket::add_user_data(int)                    {return true;}
+bool Abstract_Socket::remove_user_data(int)                 {return true;}
 bool Abstract_Socket::user_all_mandatory_configparameters_present() { return true; }
 
 
+38 −0
Original line number Diff line number Diff line
diff --git a/src/Abstract_Socket.hh b/src/Abstract_Socket.hh
index 6d7bc3d..a068662 100644
--- a/src/Abstract_Socket.hh
+++ b/src/Abstract_Socket.hh
@@ -134,7 +134,7 @@ protected:
   bool get_handle_half_close() const {return handle_half_close;}
   int  get_socket_fd() const;
   int  get_listen_fd() const {return listen_fd;}
-    
+
   //set non-blocking mode
   int set_non_block_mode(int fd, bool enable_nonblock);
 
@@ -149,6 +149,8 @@ protected:
   const struct sockaddr_in & get_local_addr() {return localAddr; };   /* FIXME: This function is deprecated and should be removed! */
   const int& get_ai_family() const {return ai_family;}
   void set_ai_family(int parameter_value) {ai_family=parameter_value;}
+  const int& get_ip_proto() const {return ip_proto;}
+  void set_ip_proto(int parameter_value) {ip_proto=parameter_value;}
   bool get_ttcn_buffer_usercontrol() const {return ttcn_buffer_usercontrol; }
   void set_nagling(bool parameter_value) {nagling=parameter_value;}
   void set_server_mode(bool parameter_value) {server_mode=parameter_value;}
@@ -204,6 +206,7 @@ protected:
   virtual const char* local_address_name();
   virtual const char* remote_port_name();
   virtual const char* ai_family_name();
+  virtual const char* ip_proto_name();
   virtual const char* use_connection_ASPs_name();
   virtual const char* halt_on_connection_reset_name();
   virtual const char* client_TCP_reconnect_name();
@@ -269,6 +272,7 @@ private:
   char* remote_host_name;
   unsigned int remote_port_number;
   int ai_family; // address family to use
+  int ip_proto; // protocol to use (e.g. IPPROTO_TCP, IPPROTO_SCTP)
   // remoteAddr and localAddr is filled when map_user is called
   struct sockaddr_in remoteAddr; /* FIXME: not used! should be removed */
   struct sockaddr_in localAddr;  /* FIXME: not used! should be removed */