summaryrefslogtreecommitdiffstats
path: root/SCTPasp_CNL113469
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2017-04-12 12:13:44 +0200
committerHarald Welte <laforge@gnumonks.org>2017-04-12 12:13:44 +0200
commitac3598008390c5185f6b71feffe31cb7fa61b9a7 (patch)
tree66422bb31538595c3e70a7042f986b9653ecd3be /SCTPasp_CNL113469
initial chekin of code received by Ericsson on 20170410
Diffstat (limited to 'SCTPasp_CNL113469')
-rw-r--r--SCTPasp_CNL113469/SCTPasp_CNL113469.tpd50
-rw-r--r--SCTPasp_CNL113469/doc/SCTPasp_CNL113469_PRI.docbin0 -> 64512 bytes
-rw-r--r--SCTPasp_CNL113469/doc/SCTPasp_CNL113469_UG.docbin0 -> 162816 bytes
-rw-r--r--SCTPasp_CNL113469/doc/SCTPasp_FS.pdfbin0 -> 167590 bytes
-rw-r--r--SCTPasp_CNL113469/src/SCTPasp_PT.cc1549
-rw-r--r--SCTPasp_CNL113469/src/SCTPasp_PT.hh157
-rw-r--r--SCTPasp_CNL113469/src/SCTPasp_PortType.ttcn62
-rw-r--r--SCTPasp_CNL113469/src/SCTPasp_Types.ttcn201
8 files changed, 2019 insertions, 0 deletions
diff --git a/SCTPasp_CNL113469/SCTPasp_CNL113469.tpd b/SCTPasp_CNL113469/SCTPasp_CNL113469.tpd
new file mode 100644
index 0000000..125ad9f
--- /dev/null
+++ b/SCTPasp_CNL113469/SCTPasp_CNL113469.tpd
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2014 Ericsson
+
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Eclipse Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/epl-v10.html
+
+
+ File: SCTPasp_CNL113469.tpd
+ Description: tpd project file
+ Rev: R11A
+ Prodnr: CNL 113 469
+ Updated: 2014-09-24
+ Contact: http://ttcn.ericsson.se
+
+ -->
+<TITAN_Project_File_Information version="1.0">
+ <ProjectName>SCTPasp_CNL113469</ProjectName>
+ <Folders>
+ <FolderResource projectRelativePath="src" relativeURI="src"/>
+ </Folders>
+ <Files>
+ <FileResource projectRelativePath="src/SCTPasp_PT.cc" relativeURI="src/SCTPasp_PT.cc"/>
+ <FileResource projectRelativePath="src/SCTPasp_PT.hh" relativeURI="src/SCTPasp_PT.hh"/>
+ <FileResource projectRelativePath="src/SCTPasp_PortType.ttcn" relativeURI="src/SCTPasp_PortType.ttcn"/>
+ <FileResource projectRelativePath="src/SCTPasp_Types.ttcn" relativeURI="src/SCTPasp_Types.ttcn"/>
+ </Files>
+ <ActiveConfiguration>Default</ActiveConfiguration>
+ <Configurations>
+ <Configuration name="Default">
+ <ProjectProperties>
+ <MakefileSettings>
+ <generateInternalMakefile>true</generateInternalMakefile>
+ <GNUMake>true</GNUMake>
+ <incrementalDependencyRefresh>true</incrementalDependencyRefresh>
+ <targetExecutable>bin/SCTPasp_CNL113469</targetExecutable>
+ <preprocessorDefines>
+ <listItem>USE_SCTP</listItem>
+ </preprocessorDefines>
+ <buildLevel>Level 3 - Creating object files with dependency update</buildLevel>
+ </MakefileSettings>
+ <LocalBuildSettings>
+ <workingDirectory>bin</workingDirectory>
+ </LocalBuildSettings>
+ </ProjectProperties>
+ </Configuration>
+ </Configurations>
+</TITAN_Project_File_Information>
diff --git a/SCTPasp_CNL113469/doc/SCTPasp_CNL113469_PRI.doc b/SCTPasp_CNL113469/doc/SCTPasp_CNL113469_PRI.doc
new file mode 100644
index 0000000..5923989
--- /dev/null
+++ b/SCTPasp_CNL113469/doc/SCTPasp_CNL113469_PRI.doc
Binary files differ
diff --git a/SCTPasp_CNL113469/doc/SCTPasp_CNL113469_UG.doc b/SCTPasp_CNL113469/doc/SCTPasp_CNL113469_UG.doc
new file mode 100644
index 0000000..e0c17fe
--- /dev/null
+++ b/SCTPasp_CNL113469/doc/SCTPasp_CNL113469_UG.doc
Binary files differ
diff --git a/SCTPasp_CNL113469/doc/SCTPasp_FS.pdf b/SCTPasp_CNL113469/doc/SCTPasp_FS.pdf
new file mode 100644
index 0000000..0e66447
--- /dev/null
+++ b/SCTPasp_CNL113469/doc/SCTPasp_FS.pdf
Binary files differ
diff --git a/SCTPasp_CNL113469/src/SCTPasp_PT.cc b/SCTPasp_CNL113469/src/SCTPasp_PT.cc
new file mode 100644
index 0000000..6d7b02b
--- /dev/null
+++ b/SCTPasp_CNL113469/src/SCTPasp_PT.cc
@@ -0,0 +1,1549 @@
+/******************************************************************************
+* Copyright (c) 2005, 2014 Ericsson AB
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/epl-v10.html
+*
+* Contributors:
+* Peter Dimitrov- initial implementation and initial documentation
+* Adam Delic
+* Eduard Czimbalmos
+* Endre Kulcsar
+* Gabor Bettesch
+* Gabor Szalai
+* Tamas Buti
+* Zoltan Medve
+******************************************************************************/
+//
+// File: SCTPasp_PT.cc
+// Description: SCTPasp test port source
+// Rev: R11A
+// Prodnr: CNL 113 469
+//
+
+
+#include "SCTPasp_PT.hh"
+
+#include <sys/types.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <stdarg.h>
+#include <memory.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+
+#define BUFLEN 1024
+#define MAP_LENGTH 10
+#ifdef SCTP_ADAPTION_LAYER
+ #ifdef LKSCTP_1_0_7
+ #undef LKSCTP_1_0_7
+ #error LKSCTP_1_0_7 defined but the lksctp older than 1.0.7. Use only -DUSE_SCTP, version is automatically selected
+ #endif
+ #ifdef LKSCTP_1_0_9
+ #error LKSCTP_1_0_9 defined but the lksctp older than 1.0.7. Use only -DUSE_SCTP, version is automatically selected
+ #undef LKSCTP_1_0_9
+ #endif
+#else
+// 1.0.7 or newer
+ #ifdef SCTP_AUTH_CHUNK
+ // 1.0.9 or newer
+ #ifdef LKSCTP_1_0_7
+ #undef LKSCTP_1_0_7
+ #error LKSCTP_1_0_7 defined but the lksctp newer than 1.0.7. Use only -DUSE_SCTP, version is automatically selected
+ #endif
+ #ifndef LKSCTP_1_0_9
+ #define LKSCTP_1_0_9
+ #endif
+ #else
+ // 1.0.7
+ #ifdef LKSCTP_1_0_9
+ #undef LKSCTP_1_0_9
+ #error LKSCTP_1_0_9 defined but the lksctp older than 1.0.9. Use only -DUSE_SCTP, version is automatically selected
+ #endif
+ #ifndef LKSCTP_1_0_7
+ #define LKSCTP_1_0_7
+ #endif
+
+ #endif
+
+#endif
+
+namespace SCTPasp__PortType {
+
+struct SCTPasp__PT_PROVIDER::fd_map_item
+{ // used by map operations
+ int fd; // socket descriptor
+ boolean erased;
+ boolean processing_message; // if true only part of the message is received
+ boolean einprogress; // connection establishment is in progress
+ void * buf; // buffer
+ ssize_t buflen; // length of the buffer
+ ssize_t nr; // number of received bytes
+ struct sockaddr_in sin; // storing remote address
+};
+
+
+struct SCTPasp__PT_PROVIDER::fd_map_server_item // server item
+{ // used by map operations
+ int fd; // socket descriptor
+ boolean erased;
+ struct in_addr local_IP_address;
+ unsigned short local_port;
+};
+
+
+SCTPasp__PT_PROVIDER::SCTPasp__PT_PROVIDER(const char *par_port_name)
+ : PORT(par_port_name)
+{
+ simple_mode = FALSE;
+ reconnect = FALSE;
+ reconnect_max_attempts = 6;
+ server_mode = FALSE;
+ debug = FALSE;
+ server_backlog = 1;
+ local_IP_address.s_addr = INADDR_ANY;
+ (void) memset(&initmsg, 0, sizeof(struct sctp_initmsg));
+ initmsg.sinit_num_ostreams = 64;
+ initmsg.sinit_max_instreams = 64;
+ initmsg.sinit_max_attempts = 0;
+ initmsg.sinit_max_init_timeo = 0;
+ (void) memset(&events, 0, sizeof (events));
+ events.sctp_data_io_event = TRUE;
+ events.sctp_association_event = TRUE;
+ events.sctp_address_event = TRUE;
+ events.sctp_send_failure_event = TRUE;
+ events.sctp_peer_error_event = TRUE;
+ events.sctp_shutdown_event = TRUE;
+ events.sctp_partial_delivery_event = TRUE;
+#if defined(LKSCTP_1_0_7) || defined(LKSCTP_1_0_9)
+ events.sctp_adaptation_layer_event = TRUE;
+#else
+ events.sctp_adaption_layer_event = TRUE;
+#endif
+ local_port_is_present = FALSE;
+ peer_IP_address_is_present = FALSE;
+ peer_port_is_present = FALSE;
+
+ fd_map=NULL;
+ list_len=0;
+
+ fd_map_server=NULL;
+ list_len_server=0;
+
+ fd = -1;
+ FD_ZERO(&readfds);
+ FD_ZERO(&writefds);
+ local_port=-1;
+ peer_port=-1;
+ receiving_fd=-1;
+}
+
+
+SCTPasp__PT_PROVIDER::~SCTPasp__PT_PROVIDER()
+{
+ for(int i=0;i<list_len;i++) map_delete_item(i);
+ Free(fd_map);
+
+ if(!simple_mode)
+ {
+ for(int i=0;i<list_len_server;i++) map_delete_item_server(i);
+ Free(fd_map_server);
+ }
+}
+
+
+void SCTPasp__PT_PROVIDER::set_parameter(const char *parameter_name,
+ const char *parameter_value)
+{
+
+ if(strcmp(parameter_name, "simple_mode") == 0)
+ {
+ if (strcasecmp(parameter_value,"yes") == 0)
+ simple_mode = TRUE;
+ else if(strcasecmp(parameter_value,"no") == 0)
+ simple_mode = FALSE;
+ else
+ error("set_parameter(): Invalid parameter value: %s for parameter %s. Only yes and no can be used!" ,
+ parameter_value, parameter_name);
+ }
+ else if(strcmp(parameter_name, "reconnect") == 0)
+ {
+ if (strcasecmp(parameter_value,"yes") == 0)
+ reconnect = TRUE;
+ else if(strcasecmp(parameter_value,"no") == 0)
+ reconnect = FALSE;
+ else
+ error("set_parameter(): Invalid parameter value: %s for parameter %s. Only yes and no can be used!" ,
+ parameter_value, parameter_name);
+ }
+ else if(strcmp(parameter_name, "reconnect_max_attempts") == 0)
+ {
+ int value;
+ if ( (sscanf(parameter_value, "%d", &value) == 1) && (value>=0) )
+ reconnect_max_attempts = value;
+ else
+ error("set_parameter(): Invalid parameter value: %s for parameter %s. It should be positive integer!" ,
+ parameter_value, parameter_name);
+ }
+ else if(strcmp(parameter_name, "server_mode") == 0)
+ {
+ if (strcasecmp(parameter_value,"yes") == 0)
+ server_mode = TRUE;
+ else if(strcasecmp(parameter_value,"no") == 0)
+ server_mode = FALSE;
+ else
+ error("set_parameter(): Invalid parameter value: %s for parameter %s. Only yes and no can be used!" ,
+ parameter_value, parameter_name);
+ }
+ else if(strcmp(parameter_name, "debug") == 0)
+ {
+ if (strcasecmp(parameter_value,"yes") == 0)
+ debug = TRUE;
+ else if(strcasecmp(parameter_value,"no") == 0)
+ debug = FALSE;
+ else
+ error("set_parameter(): Invalid parameter value: %s for parameter %s. Only yes and no can be used!" ,
+ parameter_value, parameter_name);
+ }
+ else if(strcmp(parameter_name, "server_backlog") == 0)
+ {
+ int value;
+ if ( (sscanf(parameter_value, "%d", &value) == 1) && (value>=0) )
+ server_backlog = value;
+ else
+ error("set_parameter(): Invalid parameter value: %s for parameter %s. It should be positive integer!" ,
+ parameter_value, parameter_name);
+ }
+ else if(strcmp(parameter_name, "local_IP_address") == 0)
+ {
+ local_IP_address = get_in_addr((const char *) parameter_value);
+ }
+ else if(strcmp(parameter_name, "local_port") == 0)
+ {
+ unsigned short value;
+ if (sscanf(parameter_value, "%hu", &value) == 1)
+ {
+ local_port = value;
+ local_port_is_present = TRUE;
+ }
+ else
+ error("set_parameter(): Invalid parameter value: %s for parameter %s. It should be positive integer!" ,
+ parameter_value, parameter_name);
+ }
+ else if(strcmp(parameter_name, "peer_IP_address") == 0)
+ {
+ peer_IP_address = get_in_addr((const char *) parameter_value);
+ peer_IP_address_is_present = TRUE;
+ }
+ else if(strcmp(parameter_name, "peer_port") == 0)
+ {
+ unsigned short value;
+ if (sscanf(parameter_value, "%hu", &value) == 1)
+ {
+ peer_port = value;
+ peer_port_is_present = TRUE;
+ }
+ else
+ error("set_parameter(): Invalid parameter value: %s for parameter %s. It should be positive integer!" ,
+ parameter_value, parameter_name);
+ }
+ else if(strcmp(parameter_name, "sinit_num_ostreams") == 0)
+ {
+ long value;
+ if ( (sscanf(parameter_value, "%ld", &value) == 1) && (value>=0) )
+ initmsg.sinit_num_ostreams = value;
+ else
+ error("set_parameter(): Invalid parameter value: %s for parameter %s. It should be positive integer!" ,
+ parameter_value, parameter_name);
+ }
+ else if(strcmp(parameter_name, "sinit_max_instreams") == 0)
+ {
+ long value;
+ if ( (sscanf(parameter_value, "%ld", &value) == 1) && (value>=0) )
+ initmsg.sinit_max_instreams = value;
+ else
+ error("set_parameter(): Invalid parameter value: %s for parameter %s. It should be positive integer!" ,
+ parameter_value, parameter_name);
+ }
+ else if(strcmp(parameter_name, "sinit_max_attempts") == 0)
+ {
+ long value;
+ if ( (sscanf(parameter_value, "%ld", &value) == 1) && (value>=0) )
+ initmsg.sinit_max_attempts = value;
+ else
+ error("set_parameter(): Invalid parameter value: %s for parameter %s. It should be positive integer!" ,
+ parameter_value, parameter_name);
+ }
+ else if(strcmp(parameter_name, "sinit_max_init_timeo") == 0)
+ {
+ long value;
+ if ( (sscanf(parameter_value, "%ld", &value) == 1) && (value>=0) )
+ initmsg.sinit_max_init_timeo = value;
+ else
+ error("set_parameter(): Invalid parameter value: %s for parameter %s. It should be positive integer!" ,
+ parameter_value, parameter_name);
+ }
+ else if(strcmp(parameter_name, "sctp_association_event") == 0)
+ {
+ if (strcasecmp(parameter_value,"enabled") == 0)
+ events.sctp_association_event = TRUE;
+ else if(strcasecmp(parameter_value,"disabled") == 0)
+ events.sctp_association_event = FALSE;
+ else
+ error("set_parameter(): Invalid parameter value: %s for parameter %s. It should be enabled or disabled!" ,
+ parameter_value, parameter_name);
+ }
+ else if(strcmp(parameter_name, "sctp_address_event") == 0)
+ {
+ if (strcasecmp(parameter_value,"enabled") == 0)
+ events.sctp_address_event = TRUE;
+ else if(strcasecmp(parameter_value,"disabled") == 0)
+ events.sctp_address_event = FALSE;
+ else
+ error("set_parameter(): Invalid parameter value: %s for parameter %s. It should be enabled or disabled!" ,
+ parameter_value, parameter_name);
+ }
+ else if(strcmp(parameter_name, "sctp_send_failure_event") == 0)
+ {
+ if (strcasecmp(parameter_value,"enabled") == 0)
+ events.sctp_send_failure_event = TRUE;
+ else if(strcasecmp(parameter_value,"disabled") == 0)
+ events.sctp_send_failure_event = FALSE;
+ else
+ error("set_parameter(): Invalid parameter value: %s for parameter %s. It should be enabled or disabled!" ,
+ parameter_value, parameter_name);
+ }
+ else if(strcmp(parameter_name, "sctp_peer_error_event") == 0)
+ {
+ if (strcasecmp(parameter_value,"enabled") == 0)
+ events.sctp_peer_error_event = TRUE;
+ else if(strcasecmp(parameter_value,"disabled") == 0)
+ events.sctp_peer_error_event = FALSE;
+ else
+ error("set_parameter(): Invalid parameter value: %s for parameter %s. It should be enabled or disabled!" ,
+ parameter_value, parameter_name);
+ }
+ else if(strcmp(parameter_name, "sctp_shutdown_event") == 0)
+ {
+ if (strcasecmp(parameter_value,"enabled") == 0)
+ events.sctp_shutdown_event = TRUE;
+ else if(strcasecmp(parameter_value,"disabled") == 0)
+ events.sctp_shutdown_event = FALSE;
+ else
+ error("set_parameter(): Invalid parameter value: %s for parameter %s. It should be enabled or disabled!" ,
+ parameter_value, parameter_name);
+ }
+ else if(strcmp(parameter_name, "sctp_partial_delivery_event") == 0)
+ {
+ if (strcasecmp(parameter_value,"enabled") == 0)
+ events.sctp_partial_delivery_event = TRUE;
+ else if(strcasecmp(parameter_value,"disabled") == 0)
+ events.sctp_partial_delivery_event = FALSE;
+ else
+ error("set_parameter(): Invalid parameter value: %s for parameter %s. It should be enabled or disabled!" ,
+ parameter_value, parameter_name);
+ }
+ else if(strcmp(parameter_name, "sctp_adaption_layer_event") == 0)
+ {
+ if (strcasecmp(parameter_value,"enabled") == 0)
+#if defined(LKSCTP_1_0_7) || defined(LKSCTP_1_0_9)
+ events.sctp_adaptation_layer_event = TRUE;
+#else
+ events.sctp_adaption_layer_event = TRUE;
+#endif
+ else if(strcasecmp(parameter_value,"disabled") == 0)
+#if defined(LKSCTP_1_0_7) || defined(LKSCTP_1_0_9)
+ events.sctp_adaptation_layer_event = FALSE;
+#else
+ events.sctp_adaption_layer_event = FALSE;
+#endif
+ else
+ error("set_parameter(): Invalid parameter value: %s for parameter %s. It should be enabled or disabled!" ,
+ parameter_value, parameter_name);
+ }
+ else
+ TTCN_warning("%s: unknown & unhandled parameter: %s",
+ get_name(), parameter_name);
+ errno = 0;
+}
+
+
+void SCTPasp__PT_PROVIDER::Event_Handler(const fd_set *read_fds,
+ const fd_set *write_fds, const fd_set */*error_fds*/,
+ double /*time_since_last_call*/)
+{
+ // Accepting new client
+ if(!simple_mode)
+ {
+ for(int i=0;i<list_len_server;i++)
+ {
+ if(!fd_map_server[i].erased && FD_ISSET(fd_map_server[i].fd, read_fds))
+ {
+ int newclient_fd;
+ struct sockaddr_in peer_address;
+ socklen_t addrlen = sizeof(peer_address);
+ if ((newclient_fd = accept(fd_map_server[i].fd, (struct sockaddr *)&peer_address, &addrlen)) == -1)
+ error("Event handler: accept error (server mode)!");
+ else
+ {
+ map_put_item(newclient_fd);
+ setNonBlocking(newclient_fd);
+ FD_SET(newclient_fd, &readfds);
+ incoming_message(SCTPasp__Types::ASP__SCTP__Connected(
+ INTEGER(newclient_fd),
+ CHARSTRING(inet_ntoa(fd_map_server[i].local_IP_address)),
+ INTEGER(fd_map_server[i].local_port),
+ CHARSTRING(inet_ntoa(peer_address.sin_addr)),
+ INTEGER(ntohs(peer_address.sin_port))));
+ Install_Handler(&readfds, NULL, NULL, 0.0);
+ }
+ }
+ }
+ }
+ else
+ {
+ if(server_mode && FD_ISSET(fd, read_fds))
+ {
+ int newclient_fd;
+ struct sockaddr_in peer_address;
+ socklen_t addrlen = sizeof(peer_address);
+ if ((newclient_fd = accept(fd, (struct sockaddr *)&peer_address, &addrlen)) == -1)
+ error("Event handler: accept error (server mode)!");
+ else
+ {
+ map_put_item(newclient_fd);
+ setNonBlocking(newclient_fd);
+ FD_SET(newclient_fd, &readfds);
+ Install_Handler(&readfds, NULL, NULL, 0.0);
+ }
+ }
+ }
+ // Receiving data
+ for(int i=0;i<list_len;i++)
+ {
+ if(!simple_mode && !fd_map[i].erased && fd_map[i].einprogress &&
+ FD_ISSET(fd_map[i].fd, write_fds))
+ {
+ if (connect(fd_map[i].fd, (struct sockaddr *)&fd_map[i].sin,
+ sizeof (fd_map[i].sin)) == -1)
+ {
+ if(errno == EISCONN)
+ {
+ SCTPasp__Types::ASP__SCTP__RESULT asp_sctp_result;
+ asp_sctp_result.client__id() = fd_map[i].fd;
+ asp_sctp_result.error__status() = FALSE;
+ asp_sctp_result.error__message() = OMIT_VALUE;
+ incoming_message(asp_sctp_result);
+ fd_map[i].einprogress = FALSE;
+ FD_CLR(fd_map[i].fd, &writefds);
+ FD_SET(fd_map[i].fd, &readfds);
+ Install_Handler(&readfds, &writefds, NULL, 0.0);
+ errno = 0;
+ log("Connection successfully established to (%s):(%d)",
+ inet_ntoa(peer_IP_address), peer_port);
+ }
+ else
+ {
+ close(fd_map[i].fd);
+ fd = -1;
+ TTCN_warning("Connect error!");
+ SCTPasp__Types::ASP__SCTP__RESULT asp_sctp_result;
+ asp_sctp_result.client__id() = fd_map[i].fd;
+ asp_sctp_result.error__status() = TRUE;
+ asp_sctp_result.error__message() = strerror(errno);
+ incoming_message(asp_sctp_result);
+ FD_CLR(fd_map[i].fd, &writefds);
+ map_delete_item_fd(fd_map[i].fd);
+ Install_Handler(&readfds, &writefds, NULL, 0.0);
+ errno = 0;
+ log("Connection establishment to (%s):(%d) failed !",
+ inet_ntoa(peer_IP_address), peer_port);
+ }
+ }
+ }
+
+ if(!fd_map[i].erased && FD_ISSET(fd_map[i].fd, read_fds))
+ {
+ log("Calling Event_Handler.");
+ receiving_fd = fd_map[i].fd;
+
+ struct cmsghdr *cmsg;
+ struct sctp_sndrcvinfo *sri;
+ char cbuf[sizeof (*cmsg) + sizeof (*sri)];
+ struct msghdr msg;
+ struct iovec iov;
+ size_t cmsglen = sizeof (*cmsg) + sizeof (*sri);
+
+ if ( !fd_map[i].processing_message )
+ {
+ fd_map[i].buf = Malloc(BUFLEN);
+ fd_map[i].buflen = BUFLEN;
+ iov.iov_base = fd_map[i].buf;
+ iov.iov_len = fd_map[i].buflen;
+ }
+ else
+ {
+ // Set the next read offset
+ log("Event_Handler: setting the next read offset.");
+ iov.iov_base = (char *)fd_map[i].buf + fd_map[i].nr;
+ iov.iov_len = fd_map[i].buflen - fd_map[i].nr;
+ }
+
+ // Set up the msghdr structure for receiving
+ memset(&msg, 0, sizeof (msg));
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = cbuf;
+ msg.msg_controllen = cmsglen;
+
+ memset(cbuf, 0, sizeof (*cmsg) + sizeof (*sri));
+ cmsg = (struct cmsghdr *)cbuf;
+ sri = (struct sctp_sndrcvinfo *)(cmsg + 1);
+
+ return_value_t value = getmsg(receiving_fd, &msg);
+ switch(value)
+ {
+ case WHOLE_MESSAGE_RECEIVED:
+ fd_map[i].processing_message = FALSE;
+ // Intercept notifications here
+ if (msg.msg_flags & MSG_NOTIFICATION)
+ {
+ log("Calling event_handler for an incoming notification.");
+ handle_event(fd_map[i].buf);
+ }
+ else
+ {
+ log("Incoming data.");
+ unsigned int ui = ntohl(sri->sinfo_ppid);
+ INTEGER i_ppid;
+ if (ui <= (unsigned long)INT_MAX)
+ i_ppid = ui;
+ else {
+ char sbuf[16];
+ sprintf(sbuf, "%u", ui);
+ i_ppid = INTEGER(sbuf);
+ }
+ incoming_message(SCTPasp__Types::ASP__SCTP(
+ INTEGER(receiving_fd),
+ INTEGER(sri->sinfo_stream),
+ i_ppid,
+ OCTETSTRING(fd_map[i].nr,(const unsigned char *)fd_map[i].buf)));
+ }
+ Free(fd_map[i].buf);
+ fd_map[i].buf = NULL;
+ break;
+ case PARTIAL_RECEIVE:
+ fd_map[i].processing_message = TRUE;
+ break;
+ case EOF_OR_ERROR:
+ if (!server_mode) fd = -1; // setting closed socket to -1 in client mode (and reconnect mode)
+ FD_CLR(receiving_fd, &readfds);
+ Install_Handler(&readfds, NULL, NULL, 0.0);
+ map_delete_item(i);
+ if (events.sctp_association_event) incoming_message(SCTPasp__Types::ASP__SCTP__ASSOC__CHANGE(
+ INTEGER(receiving_fd),
+ SCTPasp__Types::SAC__STATE(SCTP_COMM_LOST)));
+ log("getmsg() returned with NULL. Socket is closed.");
+ if (reconnect) forced_reconnect(reconnect_max_attempts);
+
+ break;
+ }//endswitch
+ }// endif
+ }// endfor
+}
+
+
+void SCTPasp__PT_PROVIDER::user_map(const char *system_port)
+{
+ log("Calling user_map(%s).",system_port);
+ if(simple_mode)
+ {
+ if ( server_mode && reconnect )
+ {
+ error("user_map(): server mode and reconnect mode are mutually exclusive!");
+ }
+ if ( server_mode && !local_port_is_present )
+ {
+ error("user_map(): in server mode local_port must be defined!");
+ }
+
+ // Server mode: turns on listening
+ if (server_mode)
+ {
+ log("Running in SERVER_MODE.");
+ create_socket();
+ if (listen(fd, server_backlog) == -1) error("Listen error!");
+ log("Listening @ (%s):(%d)", inet_ntoa(local_IP_address), local_port);
+ FD_SET(fd, &readfds);
+ Install_Handler(&readfds, NULL, NULL, 0.0);
+ } else if (reconnect) {
+ log("Running in RECONNECT MODE.");
+ forced_reconnect(reconnect_max_attempts+1);
+ } else {
+ log("Running in CLIENT MODE.");
+ }
+ }
+ else
+ {
+ log("Running in NORMAL MODE.");
+ }
+ log("Leaving user_map().");
+}
+
+
+void SCTPasp__PT_PROVIDER::user_unmap(const char *system_port)
+{
+ log("Calling user_unmap(%s).",system_port);
+ Uninstall_Handler();
+ FD_ZERO(&readfds);
+ FD_ZERO(&writefds);
+ if(!simple_mode)
+ {
+ for(int i=0;i<list_len;i++) map_delete_item(i);
+ for(int i=0;i<list_len_server;i++) map_delete_item_server(i);
+ }
+ else
+ {
+ for(int i=0;i<list_len;i++) map_delete_item(i);
+ if(server_mode) close(fd);
+ }
+ log("Leaving user_unmap().");
+}
+
+
+void SCTPasp__PT_PROVIDER::user_start()
+{
+ log("Calling user_start().");
+ log("Leaving user_start().");
+}
+
+
+void SCTPasp__PT_PROVIDER::user_stop()
+{
+ log("Calling user_stop().");
+ log("Leaving user_stop().");
+}
+
+
+void SCTPasp__PT_PROVIDER::outgoing_send(const SCTPasp__Types::ASP__SCTP__Connect& send_par)
+{
+ log("Calling outgoing_send (ASP_SCTP_CONNECT).");
+ if(simple_mode)
+ {
+ if (server_mode)
+ error("ASP_SCTP_CONNECT is not allowed in server mode!");
+ }
+ if( !peer_IP_address_is_present && !send_par.peer__hostname().ispresent() )
+ error("Peer IP address should be defined!");
+
+ if( !peer_port_is_present && !send_par.peer__portnumber().ispresent() )
+ error("Peer port should be defined!");
+ if(!simple_mode)
+ {
+ boolean temp_bool = local_port_is_present;
+ local_port_is_present = FALSE;
+ create_socket(); // creating client socket
+ local_port_is_present = temp_bool;
+ }
+ else
+ {
+ if (fd == -1) create_socket(); // checking if there is an open socket
+ else if(FD_ISSET(fd, &readfds)) // Active connection
+ error("ASP_SCTP_CONNECT called during active connection.");
+ }
+ struct sockaddr_in sin;
+ if(send_par.peer__hostname().ispresent())
+ {
+ peer_IP_address = get_in_addr((const char *)(const CHARSTRING&)send_par.peer__hostname());
+ }
+ if(send_par.peer__portnumber().ispresent())
+ peer_port = (int) (const INTEGER&) send_par.peer__portnumber();
+
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(peer_port);
+ sin.sin_addr.s_addr = peer_IP_address.s_addr;
+ log("Connecting to (%s):(%d)", inet_ntoa(peer_IP_address), peer_port);
+ // setting non-blocking mode
+ if(!simple_mode) setNonBlocking(fd);
+ if (connect(fd, (struct sockaddr *)&sin, sizeof (sin)) == -1)
+ {
+ if(errno == EINPROGRESS && !simple_mode)
+ {
+ map_put_item(fd);
+ int i = map_get_item(fd);
+ fd_map[i].einprogress = TRUE;
+ fd_map[i].sin.sin_family = AF_INET;
+ fd_map[i].sin.sin_port = htons(peer_port);;
+ fd_map[i].sin.sin_addr.s_addr= peer_IP_address.s_addr;
+ FD_SET(fd, &writefds);
+ Install_Handler(&readfds, &writefds, NULL, 0.0);
+ log("Connection in progress to (%s):(%d)", inet_ntoa(peer_IP_address),
+ peer_port);
+ }
+ else
+ {
+ close(fd);
+ fd = -1;
+ TTCN_warning("Connect error!");
+ SCTPasp__Types::ASP__SCTP__RESULT asp_sctp_result;
+ asp_sctp_result.client__id() = OMIT_VALUE;
+ asp_sctp_result.error__status() = TRUE;
+ asp_sctp_result.error__message() = strerror(errno);
+ incoming_message(asp_sctp_result);
+ }
+ errno = 0;
+ }
+ else
+ {
+ SCTPasp__Types::ASP__SCTP__RESULT asp_sctp_result;
+ asp_sctp_result.client__id() = fd;
+ asp_sctp_result.error__status() = FALSE;
+ asp_sctp_result.error__message() = OMIT_VALUE;
+ incoming_message(asp_sctp_result);
+ map_put_item(fd);
+ if(simple_mode) setNonBlocking(fd);
+ FD_SET(fd, &readfds);
+ Install_Handler(&readfds, NULL, NULL, 0.0);
+ log("Connection successfully established to (%s):(%d)", inet_ntoa(peer_IP_address), peer_port);
+ }
+ log("Leaving outgoing_send (ASP_SCTP_CONNECT).");
+}
+
+
+void SCTPasp__PT_PROVIDER::outgoing_send(const SCTPasp__Types::ASP__SCTP__ConnectFrom& send_par)
+{
+ log("Calling outgoing_send (ASP_SCTP_CONNECTFROM).");
+ if(!simple_mode)
+ {
+ if( !peer_IP_address_is_present && !send_par.peer__hostname().ispresent() )
+ error("Peer IP address should be defined!");
+ if( !peer_port_is_present && !send_par.peer__portnumber().ispresent() )
+ error("Peer port should be defined!");
+ // work around for create_socket()
+ unsigned short temp = local_port; // saving global variables
+ boolean temp_bool = local_port_is_present;
+ struct in_addr temp_local_IP_address = local_IP_address;
+ local_port = (int) (const INTEGER&) send_par.local__portnumber();
+ local_port_is_present = TRUE;
+ if(send_par.local__hostname().ispresent())
+ {
+ local_IP_address = get_in_addr((const char *)(const CHARSTRING&)send_par.local__hostname());
+ }
+ create_socket(); // creating client socket
+
+ struct sockaddr_in sin;
+ if(send_par.peer__hostname().ispresent())
+ {
+ peer_IP_address = get_in_addr((const char *)(const CHARSTRING&)send_par.peer__hostname());
+ }
+ if(send_par.peer__portnumber().ispresent())
+ peer_port = (int) (const INTEGER&) send_par.peer__portnumber();
+
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(peer_port);
+ sin.sin_addr.s_addr = peer_IP_address.s_addr;
+ log("Connecting to (%s):(%d)", inet_ntoa(peer_IP_address), peer_port);
+ // setting non-blocking mode
+ setNonBlocking(fd);
+ if (connect(fd, (struct sockaddr *)&sin, sizeof (sin)) == -1)
+ {
+ if(errno == EINPROGRESS)
+ {
+ map_put_item(fd);
+ int i = map_get_item(fd);
+ fd_map[i].einprogress = TRUE;
+ fd_map[i].sin.sin_family = AF_INET;
+ fd_map[i].sin.sin_port = htons(peer_port);;
+ fd_map[i].sin.sin_addr.s_addr= peer_IP_address.s_addr;
+ FD_SET(fd, &writefds);
+ Install_Handler(&readfds, &writefds, NULL, 0.0);
+ log("Connection in progress to (%s):(%d)", inet_ntoa(peer_IP_address),
+ peer_port);
+ }
+ else
+ {
+ close(fd);
+ fd = -1;
+ TTCN_warning("Connect error!");
+ SCTPasp__Types::ASP__SCTP__RESULT asp_sctp_result;
+ asp_sctp_result.client__id() = OMIT_VALUE;
+ asp_sctp_result.error__status() = TRUE;
+ asp_sctp_result.error__message() = strerror(errno);
+ incoming_message(asp_sctp_result);
+ }
+ errno = 0;
+ }
+ else
+ {
+ SCTPasp__Types::ASP__SCTP__RESULT asp_sctp_result;
+ asp_sctp_result.client__id() = fd;
+ asp_sctp_result.error__status() = FALSE;
+ asp_sctp_result.error__message() = OMIT_VALUE;
+ incoming_message(asp_sctp_result);
+ map_put_item(fd);
+ FD_SET(fd, &readfds);
+ Install_Handler(&readfds, NULL, NULL, 0.0);
+ log("Connection successfully established to (%s):(%d)", inet_ntoa(peer_IP_address), peer_port);
+ }
+ local_port = temp; // restoring global variables
+ local_port_is_present = temp_bool;
+ local_IP_address = temp_local_IP_address;
+ }
+ log("Leaving outgoing_send (ASP_SCTP_CONNECTFROM).");
+}
+
+
+void SCTPasp__PT_PROVIDER::outgoing_send(const SCTPasp__Types::ASP__SCTP__Listen& send_par)
+{
+ log("Calling outgoing_send (ASP_SCTP_LISTEN).");
+ if(!simple_mode)
+ {
+ // work around for create_socket()
+ unsigned short temp = local_port; // saving global variables
+ boolean temp_bool = local_port_is_present;
+ struct in_addr temp_local_IP_address = local_IP_address;
+ local_port = (int) (const INTEGER&) send_par.local__portnumber();
+ local_port_is_present = TRUE;
+ if(send_par.local__hostname().ispresent())
+ {
+ local_IP_address = get_in_addr((const char *)(const CHARSTRING&)send_par.local__hostname());
+ }
+ create_socket();
+ if (listen(fd, server_backlog) == -1) error("Listen error!");
+ map_put_item_server(fd, local_IP_address, local_port);
+ log("Listening @ (%s):(%d)", inet_ntoa(local_IP_address), local_port);
+ local_port = temp; // restoring global variables
+ local_port_is_present = temp_bool;
+ local_IP_address = temp_local_IP_address;
+ FD_SET(fd, &readfds);
+ Install_Handler(&readfds, NULL, NULL, 0.0);
+#ifdef SCTP_REPORT_LISTEN_RESULT
+ SCTPasp__Types::ASP__SCTP__RESULT asp_sctp_result;
+ asp_sctp_result.client__id() = fd;
+ asp_sctp_result.error__status() = FALSE;
+ asp_sctp_result.error__message() = OMIT_VALUE;
+ incoming_message(asp_sctp_result);
+#endif
+ }
+ log("Leaving outgoing_send (ASP_SCTP_LISTEN).");
+}
+
+
+void SCTPasp__PT_PROVIDER::outgoing_send(const SCTPasp__Types::ASP__SCTP__SetSocketOptions& send_par)
+{
+ log("Calling outgoing_send (ASP_SCTP_SETSOCKETOPTIONS).");
+ if(simple_mode)
+ {
+ if (fd == -1) create_socket(); // checking if there is an open socket
+ }
+ switch (send_par.get_selection())
+ {
+ case SCTPasp__Types::ASP__SCTP__SetSocketOptions::ALT_Sctp__init:
+ {
+ (void) memset(&initmsg, 0, sizeof(struct sctp_initmsg));
+ const SCTPasp__Types::SCTP__INIT& init = send_par.Sctp__init();
+ initmsg.sinit_num_ostreams = (int) init.sinit__num__ostreams();
+ initmsg.sinit_max_instreams = (int) init.sinit__max__instreams();
+ initmsg.sinit_max_attempts = (int) init.sinit__max__attempts();
+ initmsg.sinit_max_init_timeo = (int) init.sinit__max__init__timeo();
+ log("Setting SCTP socket options (initmsg).");
+ if (setsockopt(fd, IPPROTO_SCTP, SCTP_INITMSG, &initmsg,
+ sizeof(struct sctp_initmsg)) < 0)
+ {
+ TTCN_warning("Setsockopt error!");
+ SCTPasp__Types::ASP__SCTP__RESULT asp_sctp_result;
+ asp_sctp_result.client__id() = fd;
+ asp_sctp_result.error__status() = TRUE;
+ asp_sctp_result.error__message() = strerror(errno);
+ incoming_message(asp_sctp_result);
+ errno = 0;
+ }
+ else
+ {
+ SCTPasp__Types::ASP__SCTP__RESULT asp_sctp_result;
+ asp_sctp_result.client__id() = fd;
+ asp_sctp_result.error__status() = FALSE;
+ asp_sctp_result.error__message() = OMIT_VALUE;
+ incoming_message(asp_sctp_result);
+ }
+ break;
+ }
+ case SCTPasp__Types::ASP__SCTP__SetSocketOptions::ALT_Sctp__events:
+ {
+ const SCTPasp__Types::SCTP__EVENTS& event = send_par.Sctp__events();
+ events.sctp_data_io_event = (boolean) event.sctp__data__io__event();
+ events.sctp_association_event = (boolean) event.sctp__association__event();
+ events.sctp_address_event = (boolean) event.sctp__address__event();
+ events.sctp_send_failure_event = (boolean) event.sctp__send__failure__event();
+ events.sctp_peer_error_event = (boolean) event.sctp__peer__error__event();
+ events.sctp_shutdown_event = (boolean) event.sctp__shutdown__event();
+ events.sctp_partial_delivery_event = (boolean) event.sctp__partial__delivery__event();
+#if defined(LKSCTP_1_0_7) || defined(LKSCTP_1_0_9)
+ events.sctp_adaptation_layer_event = (boolean) event.sctp__adaption__layer__event();
+#else
+ events.sctp_adaption_layer_event = (boolean) event.sctp__adaption__layer__event();
+#endif
+ break;
+ }
+ case SCTPasp__Types::ASP__SCTP__SetSocketOptions::ALT_So__linger:
+ {
+ struct linger so_linger;
+ (void) memset(&so_linger, 0, sizeof (so_linger));
+ const SCTPasp__Types::SO__LINGER& so = send_par.So__linger();
+ so_linger.l_onoff = (int) so.l__onoff();
+ so_linger.l_linger = (int) so.l__linger();
+ // Setting a socket level option
+ log("Setting SCTP socket options (so_linger).");
+ if (setsockopt(fd, SOL_SOCKET, SCTP_EVENTS, &so_linger, sizeof (so_linger)) < 0)
+ {
+ TTCN_warning("Setsockopt error!");
+ SCTPasp__Types::ASP__SCTP__RESULT asp_sctp_result;
+ asp_sctp_result.client__id() = fd;
+ asp_sctp_result.error__status() = TRUE;
+ asp_sctp_result.error__message() = strerror(errno);
+ incoming_message(asp_sctp_result);
+ errno = 0;
+ }
+ else
+ {
+ SCTPasp__Types::ASP__SCTP__RESULT asp_sctp_result;
+ asp_sctp_result.client__id() = fd;
+ asp_sctp_result.error__status() = FALSE;
+ asp_sctp_result.error__message() = OMIT_VALUE;
+ incoming_message(asp_sctp_result);
+ }
+ break;
+ }
+ case SCTPasp__Types::ASP__SCTP__SetSocketOptions::ALT_Sctp__rtoinfo:
+ {
+ struct sctp_rtoinfo sctp_rtoinfo;
+ (void) memset(&sctp_rtoinfo, 0, sizeof (sctp_rtoinfo));
+ const SCTPasp__Types::SCTP__RTOINFO& rto = send_par.Sctp__rtoinfo();
+ int local_fd = (int) rto.client__id();
+ sctp_rtoinfo.srto_initial = (int) rto.srto__initial();
+ sctp_rtoinfo.srto_max = (int) rto.srto__max();
+ sctp_rtoinfo.srto_min = (int) rto.srto__min();
+ // Setting a SCTP level socket option
+ log("Setting SCTP socket options (sctp_rtoinfo).");
+ if (setsockopt(local_fd, IPPROTO_SCTP, SCTP_RTOINFO, &sctp_rtoinfo,
+ sizeof (sctp_rtoinfo)) < 0)
+ {
+ TTCN_warning("Setsockopt error!");
+ SCTPasp__Types::ASP__SCTP__RESULT asp_sctp_result;
+ asp_sctp_result.client__id() = local_fd;
+ asp_sctp_result.error__status() = TRUE;
+ asp_sctp_result.error__message() = strerror(errno);
+ incoming_message(asp_sctp_result);
+ errno = 0;
+ }
+ else
+ {
+ SCTPasp__Types::ASP__SCTP__RESULT asp_sctp_result;
+ asp_sctp_result.client__id() = local_fd;
+ asp_sctp_result.error__status() = FALSE;
+ asp_sctp_result.error__message() = OMIT_VALUE;
+ incoming_message(asp_sctp_result);
+ }
+ break;
+ }
+ default:
+ error("Setsocketoptions error: UNBOUND value!");
+ break;
+ }
+ log("Leaving outgoing_send (ASP_SCTP_SETSOCKETOPTIONS).");
+}
+
+
+void SCTPasp__PT_PROVIDER::outgoing_send(const SCTPasp__Types::ASP__SCTP__Close& send_par)
+{
+ log("Calling outgoing_send (ASP_SCTP_CLOSE).");
+ if(!simple_mode)
+ {
+ if(send_par.client__id().ispresent())
+ {
+ int local_fd = (int) (const INTEGER&) send_par.client__id();
+ log("NORMAL MODE: closing client/server socket (fd = %d).", local_fd);
+ map_delete_item_fd(local_fd);
+ map_delete_item_fd_server(local_fd);
+ FD_CLR(local_fd, &readfds);
+ Install_Handler(&readfds, &writefds, NULL, 0.0);
+ }
+ else
+ { // if OMIT is given then all sockets will be closed
+ log("NORMAL MODE: closing all sockets.");
+ for(int i=0;i<list_len;i++) map_delete_item(i);
+ for(int i=0;i<list_len_server;i++) map_delete_item_server(i);
+ FD_ZERO(&readfds);
+ FD_ZERO(&writefds);
+ Install_Handler(&readfds, &writefds, NULL, 0.0); // ???
+ }
+ }
+ else
+ {
+ if (server_mode)
+ { // closing the given connection
+ if(send_par.client__id().ispresent())
+ {
+ int local_fd = (int) (const INTEGER&) send_par.client__id();
+ log("SERVER MODE: closing client socket (fd = %d).", local_fd);
+ map_delete_item_fd(local_fd);
+ FD_CLR(local_fd, &readfds);
+ Install_Handler(&readfds, NULL, NULL, 0.0);
+ }
+ else
+ { // if OMIT is given in server mode then all clients will be closed
+ log("SERVER MODE: closing all client sockets.");
+ for(int i=0;i<list_len;i++) map_delete_item(i);
+ FD_ZERO(&readfds);
+ FD_SET(fd, &readfds); // leaving only the listening socket in the fdset
+ Install_Handler(&readfds, NULL, NULL, 0.0);
+ }
+ }
+ else
+ { // closing the connection to the server
+ if ( send_par.client__id().ispresent() )
+ error("In client mode the client_id field of ASP_SCTP_Close should be set to OMIT!");
+ log("CLIENT MODE: closing socket (fd = %d).", fd);
+ map_delete_item_fd(fd);
+ FD_CLR(fd, &readfds);
+ fd=-1;
+ Install_Handler(&readfds, NULL, NULL, 0.0);
+ }
+ }
+ log("Leaving outgoing_send (ASP_SCTP_CLOSE).");
+}
+
+
+void SCTPasp__PT_PROVIDER::outgoing_send(const SCTPasp__Types::ASP__SCTP& send_par)
+{
+ log("Calling outgoing_send (ASP_SCTP).");
+ struct cmsghdr *cmsg;
+ struct sctp_sndrcvinfo *sri;
+ char cbuf[sizeof (*cmsg) + sizeof (*sri)];
+ struct msghdr msg;
+ struct iovec iov;
+ const unsigned char *buf;
+
+ buf = (const unsigned char *)send_par.data();
+ iov.iov_len = send_par.data().lengthof();
+
+ memset(&msg, 0, sizeof (msg));
+ iov.iov_base = (char *)buf;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = cbuf;
+ msg.msg_controllen = sizeof (*cmsg) + sizeof (*sri);
+
+ memset(cbuf, 0, sizeof (*cmsg) + sizeof (*sri));
+ cmsg = (struct cmsghdr *)cbuf;
+ sri = (struct sctp_sndrcvinfo *)(cmsg + 1);
+
+ cmsg->cmsg_len = sizeof (*cmsg) + sizeof (*sri);
+ cmsg->cmsg_level = IPPROTO_SCTP;
+ cmsg->cmsg_type = SCTP_SNDRCV;
+
+ sri->sinfo_stream = (int) send_par.sinfo__stream();
+
+ int target;
+ if(!simple_mode)
+ {
+ if (!send_par.client__id().ispresent())
+ error("In NORMAL mode the client_id field of ASP_SCTP should be set to a valid value and not to omit!");
+ target = (int) (const INTEGER&) send_par.client__id();
+ if ( (map_get_item(target)==-1) && (map_get_item_server(target)==-1)) error("Bad client id! %d",target);
+ }
+ else
+ {
+ if (server_mode)
+ {
+ if (!send_par.client__id().ispresent())
+ error("In server mode the client_id field of ASP_SCTP should be set to a valid value and not to omit!");
+ }
+ else // client mode
+ {
+ if (send_par.client__id().ispresent())
+ error("In client mode the client_id field of ASP_SCTP should be set to OMIT!");
+ }
+ target = fd;
+ if (server_mode)
+ target = (int) (const INTEGER&) send_par.client__id();
+ if (map_get_item(target)==-1) error("Bad client id! %d",target);
+ }
+
+ uint32_t ui;
+ if (send_par.sinfo__ppid().get_val().is_native() && send_par.sinfo__ppid() > 0)
+ ui = (int)send_par.sinfo__ppid();
+ else {
+ OCTETSTRING os = int2oct(send_par.sinfo__ppid(), 4);
+ unsigned char* p = (unsigned char*)&ui;
+ *(p++) = os[3].get_octet();
+ *(p++) = os[2].get_octet();
+ *(p++) = os[1].get_octet();
+ *(p++) = os[0].get_octet();
+ }
+ sri->sinfo_ppid = htonl(ui);
+
+ log("Sending SCTP message to file descriptor %d.", target);
+ if (sendmsg(target, &msg, 0) < 0)
+ {
+ SCTPasp__Types::ASP__SCTP__SENDMSG__ERROR asp_sctp_sendmsg_error;
+ if (server_mode) asp_sctp_sendmsg_error.client__id() = target;
+ else asp_sctp_sendmsg_error.client__id() = OMIT_VALUE;
+ asp_sctp_sendmsg_error.sinfo__stream() = send_par.sinfo__stream();
+ asp_sctp_sendmsg_error.sinfo__ppid() = send_par.sinfo__ppid();
+ asp_sctp_sendmsg_error.data() = send_par.data();
+ incoming_message(asp_sctp_sendmsg_error);
+ TTCN_warning("Sendmsg error! Strerror=%s", strerror(errno));
+
+ errno = 0;
+ }
+ log("Leaving outgoing_send (ASP_SCTP).");
+}
+
+
+SCTPasp__PT_PROVIDER::return_value_t SCTPasp__PT_PROVIDER::getmsg(int fd, struct msghdr *msg)
+{
+ log("Calling getmsg().");
+ int index = map_get_item(fd);
+ if ( !fd_map[index].processing_message ) fd_map[index].nr = 0;
+
+ ssize_t value = recvmsg(fd, msg, 0);
+ if (value <= 0) // EOF or error
+ {
+ log("Leaving getmsg(): EOF or error.");
+ errno = 0;
+ return EOF_OR_ERROR;
+ }
+ fd_map[index].nr += value;
+ log("getmsg(): [%d] bytes received. Receiving buffer now has [%d] bytes.", value, fd_map[index].nr);
+ // Whole message is received, return it.
+ if (msg->msg_flags & MSG_EOR)
+ {
+ log("Leaving getmsg(): whole message is received.");
+ return WHOLE_MESSAGE_RECEIVED;
+ }
+
+ // Maybe we need a bigger buffer, do realloc().
+ if (fd_map[index].buflen == fd_map[index].nr)
+ {
+ log("getmsg(): resizing receiving buffer: [%d] bytes -> [%d] bytes",
+ fd_map[index].buflen, (fd_map[index].buflen * 2));
+ fd_map[index].buf = Realloc(fd_map[index].buf, fd_map[index].buflen * 2);
+ fd_map[index].buflen *= 2;
+ }
+ log("Leaving getmsg(): part of the message is received.");
+ return PARTIAL_RECEIVE;
+}
+
+
+void SCTPasp__PT_PROVIDER::handle_event(void *buf)
+{
+ union sctp_notification *snp;
+ snp = (sctp_notification *)buf;
+ switch (snp->sn_header.sn_type)
+ {
+ case SCTP_ASSOC_CHANGE:
+ {
+ log("incoming SCTP_ASSOC_CHANGE event.");
+ struct sctp_assoc_change *sac;
+ sac = &snp->sn_assoc_change;
+
+// #ifdef LKSCTP_1_0_7
+ SCTPasp__Types::SAC__STATE sac_state_ttcn;
+ switch(sac->sac_state)
+ {
+ case SCTP_COMM_UP:
+ sac_state_ttcn = SCTPasp__Types::SAC__STATE::SCTP__COMM__UP;
+ break;
+
+ case SCTP_COMM_LOST:
+ sac_state_ttcn = SCTPasp__Types::SAC__STATE::SCTP__COMM__LOST;
+ break;
+
+ case SCTP_RESTART:
+ sac_state_ttcn = SCTPasp__Types::SAC__STATE::SCTP__RESTART;
+ break;
+
+ case SCTP_SHUTDOWN_COMP:
+ sac_state_ttcn = SCTPasp__Types::SAC__STATE::SCTP__SHUTDOWN__COMP;
+ break;
+
+ case SCTP_CANT_STR_ASSOC:
+ sac_state_ttcn = SCTPasp__Types::SAC__STATE::SCTP__CANT__STR__ASSOC;
+ break;
+
+ default:
+ sac_state_ttcn = SCTPasp__Types::SAC__STATE::SCTP__UNKNOWN__SAC__STATE;
+ TTCN_warning("Unexpected sac_state value received %d", sac->sac_state);
+ break;
+ }
+// #endif
+
+ if(sac->sac_state == SCTP_COMM_LOST)
+ {
+ if(simple_mode)
+ {
+ if (!server_mode) fd = -1; // setting closed socket to -1 in client mode (and reconnect mode)
+ FD_CLR(receiving_fd, &readfds);
+ Install_Handler(&readfds, NULL, NULL, 0.0);
+ map_delete_item_fd(receiving_fd);
+ }
+ else
+ {
+ FD_CLR(receiving_fd, &readfds);
+ Install_Handler(&readfds, NULL, NULL, 0.0);
+ map_delete_item_fd(receiving_fd);
+ map_delete_item_fd_server(receiving_fd);
+ }
+ }
+ if (events.sctp_association_event) incoming_message(SCTPasp__Types::ASP__SCTP__ASSOC__CHANGE(
+ INTEGER(receiving_fd),
+ sac_state_ttcn
+ ));
+
+ if(simple_mode)
+ {
+ if (reconnect && (sac->sac_state == SCTP_COMM_LOST) ) forced_reconnect(reconnect_max_attempts);
+ }
+ break;
+ }
+ case SCTP_PEER_ADDR_CHANGE:{
+ log("incoming SCTP_PEER_ADDR_CHANGE event.");
+ struct sctp_paddr_change *spc;
+ spc = &snp->sn_paddr_change;
+// #ifdef LKSCTP_1_0_7
+ SCTPasp__Types::SPC__STATE spc_state_ttcn;
+ switch(spc->spc_state)
+ {
+ case SCTP_ADDR_AVAILABLE:
+ spc_state_ttcn = SCTPasp__Types::SPC__STATE::SCTP__ADDR__AVAILABLE;
+ break;
+
+ case SCTP_ADDR_UNREACHABLE:
+ spc_state_ttcn = SCTPasp__Types::SPC__STATE::SCTP__ADDR__UNREACHABLE;
+ break;
+
+ case SCTP_ADDR_REMOVED:
+ spc_state_ttcn = SCTPasp__Types::SPC__STATE::SCTP__ADDR__REMOVED;
+ break;
+
+ case SCTP_ADDR_ADDED:
+ spc_state_ttcn = SCTPasp__Types::SPC__STATE::SCTP__ADDR__ADDED;
+ break;
+
+ case SCTP_ADDR_MADE_PRIM:
+ spc_state_ttcn = SCTPasp__Types::SPC__STATE::SCTP__ADDR__MADE__PRIM;
+ break;
+#if defined(LKSCTP_1_0_7) || defined(LKSCTP_1_0_9)
+ case SCTP_ADDR_CONFIRMED:
+ spc_state_ttcn = SCTPasp__Types::SPC__STATE::SCTP__ADDR__CONFIRMED;
+ break;
+#endif
+ default:
+ spc_state_ttcn = SCTPasp__Types::SPC__STATE::SCTP__UNKNOWN__SPC__STATE;
+ TTCN_warning("Unexpected spc_state value received %d", spc->spc_state);
+ break;
+ }
+// #endif
+ if (events.sctp_address_event) incoming_message(SCTPasp__Types::ASP__SCTP__PEER__ADDR__CHANGE(
+ INTEGER(receiving_fd),
+ spc_state_ttcn
+ ));
+ break;
+ }
+ case SCTP_REMOTE_ERROR:
+ log("incoming SCTP_REMOTE_ERROR event.");
+ //struct sctp_remote_error *sre;
+ //sre = &snp->sn_remote_error;
+ if (events.sctp_peer_error_event) incoming_message(SCTPasp__Types::ASP__SCTP__REMOTE__ERROR(INTEGER(receiving_fd)));
+ break;
+ case SCTP_SEND_FAILED:
+ log("incoming SCTP_SEND_FAILED event.");
+ //struct sctp_send_failed *ssf;
+ //ssf = &snp->sn_send_failed;
+ if (events.sctp_send_failure_event) incoming_message(SCTPasp__Types::ASP__SCTP__SEND__FAILED(INTEGER(receiving_fd)));
+ break;
+ case SCTP_SHUTDOWN_EVENT:
+ log("incoming SCTP_SHUTDOWN_EVENT event.");
+ //struct sctp_shutdown_event *sse;
+ //sse = &snp->sn_shutdown_event;
+ if (events.sctp_shutdown_event) incoming_message(SCTPasp__Types::ASP__SCTP__SHUTDOWN__EVENT(INTEGER(receiving_fd)));
+ break;
+#if defined(LKSCTP_1_0_7) || defined(LKSCTP_1_0_9)
+ case SCTP_ADAPTATION_INDICATION:
+ log("incoming SCTP_ADAPTION_INDICATION event.");
+ //struct sctp_adaptation_event *sai;
+ //sai = &snp->sn_adaptation_event;
+ if (events.sctp_adaptation_layer_event) incoming_message(SCTPasp__Types::ASP__SCTP__ADAPTION__INDICATION(INTEGER(receiving_fd)));
+ break;
+#else
+ case SCTP_ADAPTION_INDICATION:
+ log("incoming SCTP_ADAPTION_INDICATION event.");
+ //struct sctp_adaption_event *sai;
+ //sai = &snp->sn_adaption_event;
+ if (events.sctp_adaption_layer_event) incoming_message(SCTPasp__Types::ASP__SCTP__ADAPTION__INDICATION(INTEGER(receiving_fd)));
+ break;
+#endif
+ case SCTP_PARTIAL_DELIVERY_EVENT:
+ log("incoming SCTP_PARTIAL_DELIVERY_EVENT event.");
+ //struct sctp_pdapi_event *pdapi;
+ //pdapi = &snp->sn_pdapi_event;
+ if (events.sctp_partial_delivery_event) incoming_message(SCTPasp__Types::ASP__SCTP__PARTIAL__DELIVERY__EVENT(INTEGER(receiving_fd)));
+ break;
+ default:
+ TTCN_warning("Unknown notification type!");
+ break;
+ }
+}
+
+
+void SCTPasp__PT_PROVIDER::log(const char *fmt, ...)
+{
+ if(debug)
+ {
+ va_list ap;
+ va_start(ap, fmt);
+ TTCN_Logger::begin_event(TTCN_DEBUG);
+ TTCN_Logger::log_event("SCTPasp Test Port (%s): ", get_name());
+ TTCN_Logger::log_event_va_list(fmt, ap);
+ TTCN_Logger::end_event();
+ va_end(ap);
+
+ }
+}
+
+
+void SCTPasp__PT_PROVIDER::error(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ TTCN_Logger::begin_event(TTCN_ERROR);
+ TTCN_Logger::log_event("SCTPasp Test Port (%s): ", get_name());
+ TTCN_Logger::log_event_va_list(fmt, ap);
+ TTCN_Logger::end_event();
+ va_end(ap);
+ TTCN_error("Fatal error in SCTPasp Test Port %s (see above).", get_name());
+}
+
+
+void SCTPasp__PT_PROVIDER::forced_reconnect(int attempts)
+{
+ struct sockaddr_in sin;
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(peer_port);
+ sin.sin_addr.s_addr = peer_IP_address.s_addr;
+ log("[reconnect] Connecting to (%s):(%d)", inet_ntoa(peer_IP_address), peer_port);
+ unsigned int sleep_interval = 1;
+ int i;
+ for(i = 0; i < attempts; i++)
+ {
+ create_socket();
+ if (connect(fd, (struct sockaddr *)&sin, sizeof (sin)) == -1)
+ {
+ close(fd);
+ fd = -1;
+ TTCN_warning("Connect error!");
+ errno = 0;
+ if( ((i % 2 ) == 0) && (i != 0)) sleep_interval *= 2;
+ sleep(sleep_interval);
+
+ }
+ else
+ {
+ map_put_item(fd);
+ setNonBlocking(fd);
+ FD_SET(fd, &readfds);
+ Install_Handler(&readfds, NULL, NULL, 0.0);
+ log("[reconnect] Connection successfully established to (%s):(%d)", inet_ntoa(peer_IP_address), peer_port);
+ break;
+ }
+ }
+ if (i == attempts) error("Forced reconnect failed! Remote end is unreachable!");
+
+}
+
+
+void SCTPasp__PT_PROVIDER::map_put_item(int fd)
+{
+ int i=0;
+ while((i<list_len) && !fd_map[i].erased) i++; // searching for the free item
+ if(i==list_len)
+ { // list is full add new elemnts
+ list_len+=MAP_LENGTH;
+ fd_map=(fd_map_item *)Realloc(fd_map,(list_len)*sizeof(fd_map_item));
+ for(int k=i;k<list_len;k++)
+ { // init new elements
+ fd_map[k].fd=-1;
+ fd_map[k].erased=TRUE;
+ fd_map[k].einprogress=FALSE;
+ fd_map[k].buf=NULL;
+ fd_map[k].buflen=0;
+ fd_map[k].processing_message=FALSE;
+ fd_map[k].nr=0;
+ fd_map[k].sin.sin_family=AF_INET;
+ fd_map[k].sin.sin_port=0;
+ fd_map[k].sin.sin_addr.s_addr=0;
+ }
+ }
+ fd_map[i].fd=fd; // adding new connection
+ fd_map[i].erased=FALSE;
+}
+
+
+int SCTPasp__PT_PROVIDER::map_get_item(int fd)
+{
+ for(int i = 0; i < list_len; i++)
+ if( !(fd_map[i].erased) && (fd_map[i].fd == fd) ) return i;
+ return(-1);
+}
+
+
+void SCTPasp__PT_PROVIDER::map_delete_item_fd(int fd)
+{
+ if(fd!=-1)
+ for(int i = 0; i < list_len; i++)
+ if( fd_map[i].fd == fd )
+ {
+ map_delete_item(i);
+ break;
+ }
+}
+
+
+void SCTPasp__PT_PROVIDER::map_delete_item(int index)
+{
+ if((index>=list_len) || (index<0)) error("map_delete_item: index out of range (0-%d): %d",list_len-1,index);
+
+ if(fd_map[index].fd!=-1) close(fd_map[index].fd);
+ fd_map[index].fd=-1;
+ fd_map[index].erased=TRUE;
+ fd_map[index].einprogress=FALSE;
+ if(fd_map[index].buf) Free(fd_map[index].buf);
+ fd_map[index].buf=NULL;
+ fd_map[index].buflen=0;
+ fd_map[index].processing_message=FALSE;
+ fd_map[index].nr=0;
+ fd_map[index].sin.sin_family=AF_INET;
+ fd_map[index].sin.sin_port=0;
+ fd_map[index].sin.sin_addr.s_addr=0;
+}
+
+
+void SCTPasp__PT_PROVIDER::map_put_item_server(int fd, struct in_addr local_IP_address, unsigned short local_port)
+{
+ int i=0;
+ while((i<list_len_server) && !fd_map_server[i].erased) i++; // searching for the free item
+ if(i==list_len_server)
+ { // list is full add new elemnts
+ list_len_server+=MAP_LENGTH;
+ fd_map_server=(fd_map_server_item *)Realloc(fd_map_server,(list_len_server)*sizeof(fd_map_server_item));
+ for(int k=i;k<list_len_server;k++)
+ { // init new elements
+ fd_map_server[k].fd=-1;
+ fd_map_server[k].erased=TRUE;
+ fd_map_server[k].local_IP_address.s_addr = INADDR_ANY;
+ fd_map_server[k].local_port = 0;
+ }
+ }
+ fd_map_server[i].fd=fd; // adding new connection
+ fd_map_server[i].erased=FALSE;
+ fd_map_server[i].local_IP_address = local_IP_address;
+ fd_map_server[i].local_port = local_port;
+
+}
+
+
+int SCTPasp__PT_PROVIDER::map_get_item_server(int fd)
+{
+ for(int i = 0; i < list_len_server; i++)
+ if( !(fd_map_server[i].erased) && (fd_map_server[i].fd == fd) ) return i;
+ return(-1);
+}
+
+
+void SCTPasp__PT_PROVIDER::map_delete_item_fd_server(int fd)
+{
+ if(fd!=-1)
+ for(int i = 0; i < list_len_server; i++)
+ if( fd_map_server[i].fd == fd )
+ {
+ map_delete_item_server(i);
+ break;
+ }
+}
+
+
+void SCTPasp__PT_PROVIDER::map_delete_item_server(int index)
+{
+ if((index>=list_len_server) || (index<0)) error("map_delete_item: index out of range (0-%d): %d",list_len_server-1,index);
+
+ if(fd_map_server[index].fd!=-1) close(fd_map_server[index].fd);
+ fd_map_server[index].fd=-1;
+ fd_map_server[index].erased=TRUE;
+ fd_map_server[index].local_IP_address.s_addr = INADDR_ANY;
+ fd_map_server[index].local_port = 0;
+}
+
+
+void SCTPasp__PT_PROVIDER::create_socket()
+{
+ struct sockaddr_in sin;
+
+ log("Creating SCTP socket.");
+ if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP)) == -1)
+ error("Socket error: cannot create socket!");
+
+ if ( local_port_is_present ) {
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(local_port);
+ sin.sin_addr.s_addr = local_IP_address.s_addr;
+ log("Binding SCTP socket: bind address (%s):(%d)",
+ inet_ntoa(local_IP_address),local_port);
+ if (bind(fd, (struct sockaddr *)&sin, sizeof (sin)) == -1)
+ {
+ close(fd);
+ fd = -1;
+ error("Bind error!");
+ }
+ }
+
+ log("Setting SCTP socket options (initmsg).");
+ if (setsockopt(fd, IPPROTO_SCTP, SCTP_INITMSG, &initmsg,
+ sizeof(struct sctp_initmsg)) < 0)
+ {
+ TTCN_warning("Setsockopt error!");
+ errno = 0;
+ }
+
+ log("Setting SCTP socket options (events).");
+ if (setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof (events)) < 0)
+ {
+ TTCN_warning("Setsockopt error!");
+ errno = 0;
+ }
+}
+
+
+in_addr SCTPasp__PT_PROVIDER::get_in_addr(const char *hostname)
+{
+ struct hostent *h;
+ if ((h=gethostbyname(hostname)) == NULL)
+ error("Gethostbyname error!");
+ if(h->h_addr == NULL) error("Gethostbyname error! h->h_addr is NULL!");
+ return *((struct in_addr *)h->h_addr);
+}
+
+void SCTPasp__PT_PROVIDER::setNonBlocking(int fd)
+{
+ int flags = fcntl(fd, F_GETFL);
+ flags |= O_NONBLOCK;
+ int result = fcntl(fd, F_SETFL, flags);
+ if (result==-1) error("SCTPasp__PT::setNonBlocking(): Fcntl() error!");
+}
+
+
+}
diff --git a/SCTPasp_CNL113469/src/SCTPasp_PT.hh b/SCTPasp_CNL113469/src/SCTPasp_PT.hh
new file mode 100644
index 0000000..7d6311d
--- /dev/null
+++ b/SCTPasp_CNL113469/src/SCTPasp_PT.hh
@@ -0,0 +1,157 @@
+/******************************************************************************
+* Copyright (c) 2005, 2014 Ericsson AB
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/epl-v10.html
+*
+* Contributors:
+* Peter Dimitrov- initial implementation and initial documentation
+* Adam Delic
+* Eduard Czimbalmos
+* Endre Kulcsar
+* Gabor Bettesch
+* Gabor Szalai
+* Tamas Buti
+* Zoltan Medve
+******************************************************************************/
+//
+// File: SCTPasp_PT.hh
+// Description: SCTPasp test port header
+// Rev: R11A
+// Prodnr: CNL 113 469
+//
+
+
+#ifndef SCTPasp__PT_HH
+#define SCTPasp__PT_HH
+
+#include <TTCN3.hh>
+#include "SCTPasp_Types.hh"
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/sctp.h>
+
+namespace SCTPasp__Types {
+ class ASP__SCTP;
+ class ASP__SCTP__Connect;
+ class ASP__SCTP__ConnectFrom;
+ class ASP__SCTP__Listen;
+
+ class SCTP__INIT;
+ class SCTP__EVENTS;
+ class SO__LINGER;
+ class SCTP__RTOINFO;
+ class SAC__STATE;
+ class SPC__STATE;
+
+ class ASP__SCTP__SetSocketOptions;
+ class ASP__SCTP__Close;
+ class ASP__SCTP__ASSOC__CHANGE;
+ class ASP__SCTP__PEER__ADDR__CHANGE;
+ class ASP__SCTP__SEND__FAILED;
+ class ASP__SCTP__REMOTE__ERROR;
+ class ASP__SCTP__SHUTDOWN__EVENT;
+ class ASP__SCTP__PARTIAL__DELIVERY__EVENT;
+ class ASP__SCTP__ADAPTION__INDICATION;
+ class ASP__SCTP__Connected;
+ class ASP__SCTP__SENDMSG__ERROR;
+ class ASP__SCTP__RESULT;
+}
+
+namespace SCTPasp__PortType {
+class SCTPasp__PT_PROVIDER : public PORT {
+public:
+ SCTPasp__PT_PROVIDER(const char *par_port_name = NULL);
+ ~SCTPasp__PT_PROVIDER();
+
+ void set_parameter(const char *parameter_name,
+ const char *parameter_value);
+
+ void Event_Handler(const fd_set *read_fds,
+ const fd_set *write_fds, const fd_set *error_fds,
+ 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();
+
+ void outgoing_send(const SCTPasp__Types::ASP__SCTP__Connect& send_par);
+ void outgoing_send(const SCTPasp__Types::ASP__SCTP__ConnectFrom& send_par);
+ void outgoing_send(const SCTPasp__Types::ASP__SCTP__Listen& send_par);
+ void outgoing_send(const SCTPasp__Types::ASP__SCTP__SetSocketOptions& send_par);
+ void outgoing_send(const SCTPasp__Types::ASP__SCTP__Close& send_par);
+ void outgoing_send(const SCTPasp__Types::ASP__SCTP& send_par);
+
+ virtual void incoming_message(const SCTPasp__Types::ASP__SCTP& incoming_par) = 0;
+ virtual void incoming_message(const SCTPasp__Types::ASP__SCTP__ASSOC__CHANGE& incoming_par) = 0;
+ virtual void incoming_message(const SCTPasp__Types::ASP__SCTP__PEER__ADDR__CHANGE& incoming_par) = 0;
+ virtual void incoming_message(const SCTPasp__Types::ASP__SCTP__SEND__FAILED& incoming_par) = 0;
+ virtual void incoming_message(const SCTPasp__Types::ASP__SCTP__REMOTE__ERROR& incoming_par) = 0;
+ virtual void incoming_message(const SCTPasp__Types::ASP__SCTP__SHUTDOWN__EVENT& incoming_par) = 0;
+ virtual void incoming_message(const SCTPasp__Types::ASP__SCTP__PARTIAL__DELIVERY__EVENT& incoming_par) = 0;
+ virtual void incoming_message(const SCTPasp__Types::ASP__SCTP__ADAPTION__INDICATION& incoming_par) = 0;
+ virtual void incoming_message(const SCTPasp__Types::ASP__SCTP__Connected& incoming_par) = 0;
+ virtual void incoming_message(const SCTPasp__Types::ASP__SCTP__SENDMSG__ERROR& incoming_par) = 0;
+ virtual void incoming_message(const SCTPasp__Types::ASP__SCTP__RESULT& incoming_par) = 0;
+
+private:
+ enum return_value_t { WHOLE_MESSAGE_RECEIVED, PARTIAL_RECEIVE, EOF_OR_ERROR };
+ return_value_t getmsg(int fd, struct msghdr *msg);
+ void handle_event(void *buf);
+ void log(const char *fmt, ...);
+ void error(const char *fmt, ...);
+ void handle_event_reconnect(void *buf);
+ void forced_reconnect(int attempts);
+ // map operations
+ void map_put_item(int fd);
+ int map_get_item(int fd);
+ void map_delete_item_fd(int fd);
+ void map_delete_item(int index);
+
+ void map_put_item_server(int fd, struct in_addr local_IP_address, unsigned short local_port);
+ int map_get_item_server(int fd);
+ void map_delete_item_fd_server(int fd);
+ void map_delete_item_server(int index);
+
+ void create_socket();
+ in_addr get_in_addr(const char *hostname);
+ void setNonBlocking(int fd);
+
+ boolean simple_mode;
+ boolean reconnect;
+ int reconnect_max_attempts;
+ boolean server_mode;
+ boolean debug;
+ int server_backlog;
+ struct in_addr local_IP_address;
+ struct in_addr peer_IP_address;
+ unsigned short local_port;
+ unsigned short peer_port;
+
+ struct sctp_event_subscribe events;
+ struct sctp_initmsg initmsg;
+
+ boolean local_port_is_present;
+ boolean peer_IP_address_is_present;
+ boolean peer_port_is_present;
+
+ int fd;
+ fd_set readfds, writefds;
+ int receiving_fd;
+
+ struct fd_map_item;
+ fd_map_item *fd_map;
+ int list_len;
+
+ struct fd_map_server_item;
+ fd_map_server_item *fd_map_server;
+ int list_len_server;
+
+
+};
+}
+#endif
diff --git a/SCTPasp_CNL113469/src/SCTPasp_PortType.ttcn b/SCTPasp_CNL113469/src/SCTPasp_PortType.ttcn
new file mode 100644
index 0000000..27aae08
--- /dev/null
+++ b/SCTPasp_CNL113469/src/SCTPasp_PortType.ttcn
@@ -0,0 +1,62 @@
+/******************************************************************************
+* Copyright (c) 2005, 2014 Ericsson AB
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/epl-v10.html
+*
+* Contributors:
+* Peter Dimitrov- initial implementation and initial documentation
+* Adam Delic
+* Eduard Czimbalmos
+* Endre Kulcsar
+* Gabor Bettesch
+* Gabor Szalai
+* Tamas Buti
+* Zoltan Medve
+******************************************************************************/
+//
+// File: SCTPasp_PortType.ttcn
+// Description: SCTPasp testport definition file
+// Rev: R11A
+// Prodnr: CNL 113 469
+//
+
+module SCTPasp_PortType
+{
+
+import from SCTPasp_Types all;
+
+//=========================================================================
+//Port Types
+//=========================================================================
+
+type port SCTPasp_PT message
+{
+ inout ASP_SCTP;
+
+ out ASP_SCTP_Connect;
+ out ASP_SCTP_ConnectFrom;
+ out ASP_SCTP_Listen;
+ out ASP_SCTP_SetSocketOptions;
+ out ASP_SCTP_Close;
+
+ in ASP_SCTP_ASSOC_CHANGE;
+ in ASP_SCTP_PEER_ADDR_CHANGE;
+ in ASP_SCTP_SEND_FAILED;
+ in ASP_SCTP_REMOTE_ERROR;
+ in ASP_SCTP_SHUTDOWN_EVENT;
+ in ASP_SCTP_PARTIAL_DELIVERY_EVENT;
+ in ASP_SCTP_ADAPTION_INDICATION;
+
+ in ASP_SCTP_Connected;
+ in ASP_SCTP_SENDMSG_ERROR;
+ in ASP_SCTP_RESULT;
+
+} with { extension "provider" }
+
+}//end of module
+with {
+extension "version R11A"
+}
+
diff --git a/SCTPasp_CNL113469/src/SCTPasp_Types.ttcn b/SCTPasp_CNL113469/src/SCTPasp_Types.ttcn
new file mode 100644
index 0000000..f10fc58
--- /dev/null
+++ b/SCTPasp_CNL113469/src/SCTPasp_Types.ttcn
@@ -0,0 +1,201 @@
+/******************************************************************************
+* Copyright (c) 2005, 2014 Ericsson AB
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/epl-v10.html
+*
+* Contributors:
+* Peter Dimitrov- initial implementation and initial documentation
+* Adam Delic
+* Eduard Czimbalmos
+* Endre Kulcsar
+* Gabor Bettesch
+* Gabor Szalai
+* Tamas Buti
+* Zoltan Medve
+******************************************************************************/
+//
+// File: SCTPasp_Types.ttcn
+// Description: SCTP ASP definition file
+// Rev: R11A
+// Prodnr: CNL 113 469
+//
+
+
+module SCTPasp_Types
+{
+
+//=========================================================================
+// Data Types
+//=========================================================================
+
+type octetstring PDU_SCTP;
+
+type record ASP_SCTP
+{
+ integer client_id optional,
+ integer sinfo_stream,
+ integer sinfo_ppid,
+ PDU_SCTP data
+}
+
+
+type record ASP_SCTP_Connect
+{
+ charstring peer_hostname optional,
+ integer peer_portnumber (1..65535) optional
+}
+
+
+type record ASP_SCTP_ConnectFrom
+{
+ charstring local_hostname optional,
+ integer local_portnumber (1..65535),
+ charstring peer_hostname optional,
+ integer peer_portnumber (1..65535) optional
+}
+
+
+type record ASP_SCTP_Listen
+{
+ charstring local_hostname optional,
+ integer local_portnumber (1..65535)
+}
+
+
+type record SCTP_INIT
+{
+ integer sinit_num_ostreams,
+ integer sinit_max_instreams,
+ integer sinit_max_attempts,
+ integer sinit_max_init_timeo
+}
+
+type record SCTP_EVENTS
+{
+ boolean sctp_data_io_event,
+ boolean sctp_association_event,
+ boolean sctp_address_event,
+ boolean sctp_send_failure_event,
+ boolean sctp_peer_error_event,
+ boolean sctp_shutdown_event,
+ boolean sctp_partial_delivery_event,
+ boolean sctp_adaption_layer_event
+}
+
+type record SO_LINGER
+{
+ integer l_onoff,
+ integer l_linger
+}
+
+type record SCTP_RTOINFO
+{
+ integer client_id,
+ integer srto_initial,
+ integer srto_max,
+ integer srto_min
+}
+
+type union ASP_SCTP_SetSocketOptions
+{
+ SCTP_INIT Sctp_init,
+ SCTP_EVENTS Sctp_events,
+ SO_LINGER So_linger,
+ SCTP_RTOINFO Sctp_rtoinfo
+}
+
+
+type record ASP_SCTP_Close
+{
+ integer client_id optional
+}
+
+
+type enumerated SAC_STATE
+{
+ SCTP_COMM_UP, SCTP_COMM_LOST, SCTP_RESTART,
+ SCTP_SHUTDOWN_COMP, SCTP_CANT_STR_ASSOC, SCTP_UNKNOWN_SAC_STATE
+}
+
+type record ASP_SCTP_ASSOC_CHANGE
+{
+ integer client_id,
+ SAC_STATE sac_state
+}
+
+
+type enumerated SPC_STATE
+{
+ SCTP_ADDR_AVAILABLE, SCTP_ADDR_UNREACHABLE, SCTP_ADDR_REMOVED,
+ SCTP_ADDR_ADDED, SCTP_ADDR_MADE_PRIM, SCTP_ADDR_CONFIRMED, SCTP_UNKNOWN_SPC_STATE
+}
+
+type record ASP_SCTP_PEER_ADDR_CHANGE
+{
+ integer client_id,
+ SPC_STATE spc_state
+}
+
+
+type record ASP_SCTP_SEND_FAILED
+{
+ integer client_id
+}
+
+
+type record ASP_SCTP_REMOTE_ERROR
+{
+ integer client_id
+}
+
+
+type record ASP_SCTP_SHUTDOWN_EVENT
+{
+ integer client_id
+}
+
+
+type record ASP_SCTP_PARTIAL_DELIVERY_EVENT
+{
+ integer client_id
+}
+
+
+type record ASP_SCTP_ADAPTION_INDICATION
+{
+ integer client_id
+}
+
+
+type record ASP_SCTP_Connected
+{
+ integer client_id,
+ charstring local_hostname,
+ integer local_portnumber (1..65535),
+ charstring peer_hostname,
+ integer peer_portnumber (1..65535)
+}
+
+
+type record ASP_SCTP_SENDMSG_ERROR
+{
+ integer client_id optional,
+ integer sinfo_stream,
+ integer sinfo_ppid,
+ PDU_SCTP data
+}
+
+type record ASP_SCTP_RESULT
+{
+ integer client_id optional,
+ boolean error_status,
+ charstring error_message optional
+}
+
+}//end of module
+with {
+extension "version R11A"
+}
+