diff options
author | Harald Welte <laforge@gnumonks.org> | 2017-04-12 12:13:44 +0200 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2017-04-12 12:13:44 +0200 |
commit | ac3598008390c5185f6b71feffe31cb7fa61b9a7 (patch) | |
tree | 66422bb31538595c3e70a7042f986b9653ecd3be /SCTPasp_CNL113469 |
initial chekin of code received by Ericsson on 20170410
Diffstat (limited to 'SCTPasp_CNL113469')
-rw-r--r-- | SCTPasp_CNL113469/SCTPasp_CNL113469.tpd | 50 | ||||
-rw-r--r-- | SCTPasp_CNL113469/doc/SCTPasp_CNL113469_PRI.doc | bin | 0 -> 64512 bytes | |||
-rw-r--r-- | SCTPasp_CNL113469/doc/SCTPasp_CNL113469_UG.doc | bin | 0 -> 162816 bytes | |||
-rw-r--r-- | SCTPasp_CNL113469/doc/SCTPasp_FS.pdf | bin | 0 -> 167590 bytes | |||
-rw-r--r-- | SCTPasp_CNL113469/src/SCTPasp_PT.cc | 1549 | ||||
-rw-r--r-- | SCTPasp_CNL113469/src/SCTPasp_PT.hh | 157 | ||||
-rw-r--r-- | SCTPasp_CNL113469/src/SCTPasp_PortType.ttcn | 62 | ||||
-rw-r--r-- | SCTPasp_CNL113469/src/SCTPasp_Types.ttcn | 201 |
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 Binary files differnew file mode 100644 index 0000000..5923989 --- /dev/null +++ b/SCTPasp_CNL113469/doc/SCTPasp_CNL113469_PRI.doc diff --git a/SCTPasp_CNL113469/doc/SCTPasp_CNL113469_UG.doc b/SCTPasp_CNL113469/doc/SCTPasp_CNL113469_UG.doc Binary files differnew file mode 100644 index 0000000..e0c17fe --- /dev/null +++ b/SCTPasp_CNL113469/doc/SCTPasp_CNL113469_UG.doc diff --git a/SCTPasp_CNL113469/doc/SCTPasp_FS.pdf b/SCTPasp_CNL113469/doc/SCTPasp_FS.pdf Binary files differnew file mode 100644 index 0000000..0e66447 --- /dev/null +++ b/SCTPasp_CNL113469/doc/SCTPasp_FS.pdf 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" +} + |