Commit 1ab983a4 authored by Yann Garcia's avatar Yann Garcia
Browse files

Add patch_abstract_socket

parent d699a649
Loading
Loading
Loading
Loading
Loading
Compare 3a49ddad to 5d967e0d
Original line number Diff line number Diff line
Subproject commit 3a49ddad6cc59694b4936d43dca49038325a01e7
Subproject commit 5d967e0d62cee074c4f6015697755cf8663f07fa
Compare 77bc2781 to 8a3c78b1
Original line number Diff line number Diff line
Subproject commit 77bc278184cc79ad11c08f2725718d5d50ff7e96
Subproject commit 8a3c78b1923182ea189af32178c8bde5523750f5
Compare 6962655b to 923bd588
Original line number Diff line number Diff line
Subproject commit 6962655b6bd18c147cd73bc5fcdd3647a11132ac
Subproject commit 923bd5882f5eb8824bd600bd16203e837848e0a7
+170 −0
Original line number Diff line number Diff line
diff --git a/src/Abstract_Socket.cc b/src/Abstract_Socket.cc
index 8b7b753..af41462 100644
--- a/src/Abstract_Socket.cc
+++ b/src/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 */