blob: 6d7b02b4a981a276e37e740ac3b39ab799f8af79 [file] [log] [blame]
Harald Welteac359802017-04-12 12:13:44 +02001/******************************************************************************
2* Copyright (c) 2005, 2014 Ericsson AB
3* All rights reserved. This program and the accompanying materials
4* are made available under the terms of the Eclipse Public License v1.0
5* which accompanies this distribution, and is available at
6* http://www.eclipse.org/legal/epl-v10.html
7*
8* Contributors:
9* Peter Dimitrov- initial implementation and initial documentation
10* Adam Delic
11* Eduard Czimbalmos
12* Endre Kulcsar
13* Gabor Bettesch
14* Gabor Szalai
15* Tamas Buti
16* Zoltan Medve
17******************************************************************************/
18//
19// File: SCTPasp_PT.cc
20// Description: SCTPasp test port source
21// Rev: R11A
22// Prodnr: CNL 113 469
23//
24
25
26#include "SCTPasp_PT.hh"
27
28#include <sys/types.h>
29#include <arpa/inet.h>
30#include <unistd.h>
31#include <netdb.h>
32#include <stdarg.h>
33#include <memory.h>
34#include <fcntl.h>
35#include <string.h>
36#include <errno.h>
37#include <limits.h>
38
39#define BUFLEN 1024
40#define MAP_LENGTH 10
41#ifdef SCTP_ADAPTION_LAYER
42 #ifdef LKSCTP_1_0_7
43 #undef LKSCTP_1_0_7
44 #error LKSCTP_1_0_7 defined but the lksctp older than 1.0.7. Use only -DUSE_SCTP, version is automatically selected
45 #endif
46 #ifdef LKSCTP_1_0_9
47 #error LKSCTP_1_0_9 defined but the lksctp older than 1.0.7. Use only -DUSE_SCTP, version is automatically selected
48 #undef LKSCTP_1_0_9
49 #endif
50#else
51// 1.0.7 or newer
52 #ifdef SCTP_AUTH_CHUNK
53 // 1.0.9 or newer
54 #ifdef LKSCTP_1_0_7
55 #undef LKSCTP_1_0_7
56 #error LKSCTP_1_0_7 defined but the lksctp newer than 1.0.7. Use only -DUSE_SCTP, version is automatically selected
57 #endif
58 #ifndef LKSCTP_1_0_9
59 #define LKSCTP_1_0_9
60 #endif
61 #else
62 // 1.0.7
63 #ifdef LKSCTP_1_0_9
64 #undef LKSCTP_1_0_9
65 #error LKSCTP_1_0_9 defined but the lksctp older than 1.0.9. Use only -DUSE_SCTP, version is automatically selected
66 #endif
67 #ifndef LKSCTP_1_0_7
68 #define LKSCTP_1_0_7
69 #endif
70
71 #endif
72
73#endif
74
75namespace SCTPasp__PortType {
76
77struct SCTPasp__PT_PROVIDER::fd_map_item
78{ // used by map operations
79 int fd; // socket descriptor
80 boolean erased;
81 boolean processing_message; // if true only part of the message is received
82 boolean einprogress; // connection establishment is in progress
83 void * buf; // buffer
84 ssize_t buflen; // length of the buffer
85 ssize_t nr; // number of received bytes
86 struct sockaddr_in sin; // storing remote address
87};
88
89
90struct SCTPasp__PT_PROVIDER::fd_map_server_item // server item
91{ // used by map operations
92 int fd; // socket descriptor
93 boolean erased;
94 struct in_addr local_IP_address;
95 unsigned short local_port;
96};
97
98
99SCTPasp__PT_PROVIDER::SCTPasp__PT_PROVIDER(const char *par_port_name)
100 : PORT(par_port_name)
101{
102 simple_mode = FALSE;
103 reconnect = FALSE;
104 reconnect_max_attempts = 6;
105 server_mode = FALSE;
106 debug = FALSE;
107 server_backlog = 1;
108 local_IP_address.s_addr = INADDR_ANY;
109 (void) memset(&initmsg, 0, sizeof(struct sctp_initmsg));
110 initmsg.sinit_num_ostreams = 64;
111 initmsg.sinit_max_instreams = 64;
112 initmsg.sinit_max_attempts = 0;
113 initmsg.sinit_max_init_timeo = 0;
114 (void) memset(&events, 0, sizeof (events));
115 events.sctp_data_io_event = TRUE;
116 events.sctp_association_event = TRUE;
117 events.sctp_address_event = TRUE;
118 events.sctp_send_failure_event = TRUE;
119 events.sctp_peer_error_event = TRUE;
120 events.sctp_shutdown_event = TRUE;
121 events.sctp_partial_delivery_event = TRUE;
122#if defined(LKSCTP_1_0_7) || defined(LKSCTP_1_0_9)
123 events.sctp_adaptation_layer_event = TRUE;
124#else
125 events.sctp_adaption_layer_event = TRUE;
126#endif
127 local_port_is_present = FALSE;
128 peer_IP_address_is_present = FALSE;
129 peer_port_is_present = FALSE;
130
131 fd_map=NULL;
132 list_len=0;
133
134 fd_map_server=NULL;
135 list_len_server=0;
136
137 fd = -1;
138 FD_ZERO(&readfds);
139 FD_ZERO(&writefds);
140 local_port=-1;
141 peer_port=-1;
142 receiving_fd=-1;
143}
144
145
146SCTPasp__PT_PROVIDER::~SCTPasp__PT_PROVIDER()
147{
148 for(int i=0;i<list_len;i++) map_delete_item(i);
149 Free(fd_map);
150
151 if(!simple_mode)
152 {
153 for(int i=0;i<list_len_server;i++) map_delete_item_server(i);
154 Free(fd_map_server);
155 }
156}
157
158
159void SCTPasp__PT_PROVIDER::set_parameter(const char *parameter_name,
160 const char *parameter_value)
161{
162
163 if(strcmp(parameter_name, "simple_mode") == 0)
164 {
165 if (strcasecmp(parameter_value,"yes") == 0)
166 simple_mode = TRUE;
167 else if(strcasecmp(parameter_value,"no") == 0)
168 simple_mode = FALSE;
169 else
170 error("set_parameter(): Invalid parameter value: %s for parameter %s. Only yes and no can be used!" ,
171 parameter_value, parameter_name);
172 }
173 else if(strcmp(parameter_name, "reconnect") == 0)
174 {
175 if (strcasecmp(parameter_value,"yes") == 0)
176 reconnect = TRUE;
177 else if(strcasecmp(parameter_value,"no") == 0)
178 reconnect = FALSE;
179 else
180 error("set_parameter(): Invalid parameter value: %s for parameter %s. Only yes and no can be used!" ,
181 parameter_value, parameter_name);
182 }
183 else if(strcmp(parameter_name, "reconnect_max_attempts") == 0)
184 {
185 int value;
186 if ( (sscanf(parameter_value, "%d", &value) == 1) && (value>=0) )
187 reconnect_max_attempts = value;
188 else
189 error("set_parameter(): Invalid parameter value: %s for parameter %s. It should be positive integer!" ,
190 parameter_value, parameter_name);
191 }
192 else if(strcmp(parameter_name, "server_mode") == 0)
193 {
194 if (strcasecmp(parameter_value,"yes") == 0)
195 server_mode = TRUE;
196 else if(strcasecmp(parameter_value,"no") == 0)
197 server_mode = FALSE;
198 else
199 error("set_parameter(): Invalid parameter value: %s for parameter %s. Only yes and no can be used!" ,
200 parameter_value, parameter_name);
201 }
202 else if(strcmp(parameter_name, "debug") == 0)
203 {
204 if (strcasecmp(parameter_value,"yes") == 0)
205 debug = TRUE;
206 else if(strcasecmp(parameter_value,"no") == 0)
207 debug = FALSE;
208 else
209 error("set_parameter(): Invalid parameter value: %s for parameter %s. Only yes and no can be used!" ,
210 parameter_value, parameter_name);
211 }
212 else if(strcmp(parameter_name, "server_backlog") == 0)
213 {
214 int value;
215 if ( (sscanf(parameter_value, "%d", &value) == 1) && (value>=0) )
216 server_backlog = value;
217 else
218 error("set_parameter(): Invalid parameter value: %s for parameter %s. It should be positive integer!" ,
219 parameter_value, parameter_name);
220 }
221 else if(strcmp(parameter_name, "local_IP_address") == 0)
222 {
223 local_IP_address = get_in_addr((const char *) parameter_value);
224 }
225 else if(strcmp(parameter_name, "local_port") == 0)
226 {
227 unsigned short value;
228 if (sscanf(parameter_value, "%hu", &value) == 1)
229 {
230 local_port = value;
231 local_port_is_present = TRUE;
232 }
233 else
234 error("set_parameter(): Invalid parameter value: %s for parameter %s. It should be positive integer!" ,
235 parameter_value, parameter_name);
236 }
237 else if(strcmp(parameter_name, "peer_IP_address") == 0)
238 {
239 peer_IP_address = get_in_addr((const char *) parameter_value);
240 peer_IP_address_is_present = TRUE;
241 }
242 else if(strcmp(parameter_name, "peer_port") == 0)
243 {
244 unsigned short value;
245 if (sscanf(parameter_value, "%hu", &value) == 1)
246 {
247 peer_port = value;
248 peer_port_is_present = TRUE;
249 }
250 else
251 error("set_parameter(): Invalid parameter value: %s for parameter %s. It should be positive integer!" ,
252 parameter_value, parameter_name);
253 }
254 else if(strcmp(parameter_name, "sinit_num_ostreams") == 0)
255 {
256 long value;
257 if ( (sscanf(parameter_value, "%ld", &value) == 1) && (value>=0) )
258 initmsg.sinit_num_ostreams = value;
259 else
260 error("set_parameter(): Invalid parameter value: %s for parameter %s. It should be positive integer!" ,
261 parameter_value, parameter_name);
262 }
263 else if(strcmp(parameter_name, "sinit_max_instreams") == 0)
264 {
265 long value;
266 if ( (sscanf(parameter_value, "%ld", &value) == 1) && (value>=0) )
267 initmsg.sinit_max_instreams = value;
268 else
269 error("set_parameter(): Invalid parameter value: %s for parameter %s. It should be positive integer!" ,
270 parameter_value, parameter_name);
271 }
272 else if(strcmp(parameter_name, "sinit_max_attempts") == 0)
273 {
274 long value;
275 if ( (sscanf(parameter_value, "%ld", &value) == 1) && (value>=0) )
276 initmsg.sinit_max_attempts = value;
277 else
278 error("set_parameter(): Invalid parameter value: %s for parameter %s. It should be positive integer!" ,
279 parameter_value, parameter_name);
280 }
281 else if(strcmp(parameter_name, "sinit_max_init_timeo") == 0)
282 {
283 long value;
284 if ( (sscanf(parameter_value, "%ld", &value) == 1) && (value>=0) )
285 initmsg.sinit_max_init_timeo = value;
286 else
287 error("set_parameter(): Invalid parameter value: %s for parameter %s. It should be positive integer!" ,
288 parameter_value, parameter_name);
289 }
290 else if(strcmp(parameter_name, "sctp_association_event") == 0)
291 {
292 if (strcasecmp(parameter_value,"enabled") == 0)
293 events.sctp_association_event = TRUE;
294 else if(strcasecmp(parameter_value,"disabled") == 0)
295 events.sctp_association_event = FALSE;
296 else
297 error("set_parameter(): Invalid parameter value: %s for parameter %s. It should be enabled or disabled!" ,
298 parameter_value, parameter_name);
299 }
300 else if(strcmp(parameter_name, "sctp_address_event") == 0)
301 {
302 if (strcasecmp(parameter_value,"enabled") == 0)
303 events.sctp_address_event = TRUE;
304 else if(strcasecmp(parameter_value,"disabled") == 0)
305 events.sctp_address_event = FALSE;
306 else
307 error("set_parameter(): Invalid parameter value: %s for parameter %s. It should be enabled or disabled!" ,
308 parameter_value, parameter_name);
309 }
310 else if(strcmp(parameter_name, "sctp_send_failure_event") == 0)
311 {
312 if (strcasecmp(parameter_value,"enabled") == 0)
313 events.sctp_send_failure_event = TRUE;
314 else if(strcasecmp(parameter_value,"disabled") == 0)
315 events.sctp_send_failure_event = FALSE;
316 else
317 error("set_parameter(): Invalid parameter value: %s for parameter %s. It should be enabled or disabled!" ,
318 parameter_value, parameter_name);
319 }
320 else if(strcmp(parameter_name, "sctp_peer_error_event") == 0)
321 {
322 if (strcasecmp(parameter_value,"enabled") == 0)
323 events.sctp_peer_error_event = TRUE;
324 else if(strcasecmp(parameter_value,"disabled") == 0)
325 events.sctp_peer_error_event = FALSE;
326 else
327 error("set_parameter(): Invalid parameter value: %s for parameter %s. It should be enabled or disabled!" ,
328 parameter_value, parameter_name);
329 }
330 else if(strcmp(parameter_name, "sctp_shutdown_event") == 0)
331 {
332 if (strcasecmp(parameter_value,"enabled") == 0)
333 events.sctp_shutdown_event = TRUE;
334 else if(strcasecmp(parameter_value,"disabled") == 0)
335 events.sctp_shutdown_event = FALSE;
336 else
337 error("set_parameter(): Invalid parameter value: %s for parameter %s. It should be enabled or disabled!" ,
338 parameter_value, parameter_name);
339 }
340 else if(strcmp(parameter_name, "sctp_partial_delivery_event") == 0)
341 {
342 if (strcasecmp(parameter_value,"enabled") == 0)
343 events.sctp_partial_delivery_event = TRUE;
344 else if(strcasecmp(parameter_value,"disabled") == 0)
345 events.sctp_partial_delivery_event = FALSE;
346 else
347 error("set_parameter(): Invalid parameter value: %s for parameter %s. It should be enabled or disabled!" ,
348 parameter_value, parameter_name);
349 }
350 else if(strcmp(parameter_name, "sctp_adaption_layer_event") == 0)
351 {
352 if (strcasecmp(parameter_value,"enabled") == 0)
353#if defined(LKSCTP_1_0_7) || defined(LKSCTP_1_0_9)
354 events.sctp_adaptation_layer_event = TRUE;
355#else
356 events.sctp_adaption_layer_event = TRUE;
357#endif
358 else if(strcasecmp(parameter_value,"disabled") == 0)
359#if defined(LKSCTP_1_0_7) || defined(LKSCTP_1_0_9)
360 events.sctp_adaptation_layer_event = FALSE;
361#else
362 events.sctp_adaption_layer_event = FALSE;
363#endif
364 else
365 error("set_parameter(): Invalid parameter value: %s for parameter %s. It should be enabled or disabled!" ,
366 parameter_value, parameter_name);
367 }
368 else
369 TTCN_warning("%s: unknown & unhandled parameter: %s",
370 get_name(), parameter_name);
371 errno = 0;
372}
373
374
375void SCTPasp__PT_PROVIDER::Event_Handler(const fd_set *read_fds,
376 const fd_set *write_fds, const fd_set */*error_fds*/,
377 double /*time_since_last_call*/)
378{
379 // Accepting new client
380 if(!simple_mode)
381 {
382 for(int i=0;i<list_len_server;i++)
383 {
384 if(!fd_map_server[i].erased && FD_ISSET(fd_map_server[i].fd, read_fds))
385 {
386 int newclient_fd;
387 struct sockaddr_in peer_address;
388 socklen_t addrlen = sizeof(peer_address);
389 if ((newclient_fd = accept(fd_map_server[i].fd, (struct sockaddr *)&peer_address, &addrlen)) == -1)
390 error("Event handler: accept error (server mode)!");
391 else
392 {
393 map_put_item(newclient_fd);
394 setNonBlocking(newclient_fd);
395 FD_SET(newclient_fd, &readfds);
396 incoming_message(SCTPasp__Types::ASP__SCTP__Connected(
397 INTEGER(newclient_fd),
398 CHARSTRING(inet_ntoa(fd_map_server[i].local_IP_address)),
399 INTEGER(fd_map_server[i].local_port),
400 CHARSTRING(inet_ntoa(peer_address.sin_addr)),
401 INTEGER(ntohs(peer_address.sin_port))));
402 Install_Handler(&readfds, NULL, NULL, 0.0);
403 }
404 }
405 }
406 }
407 else
408 {
409 if(server_mode && FD_ISSET(fd, read_fds))
410 {
411 int newclient_fd;
412 struct sockaddr_in peer_address;
413 socklen_t addrlen = sizeof(peer_address);
414 if ((newclient_fd = accept(fd, (struct sockaddr *)&peer_address, &addrlen)) == -1)
415 error("Event handler: accept error (server mode)!");
416 else
417 {
418 map_put_item(newclient_fd);
419 setNonBlocking(newclient_fd);
420 FD_SET(newclient_fd, &readfds);
421 Install_Handler(&readfds, NULL, NULL, 0.0);
422 }
423 }
424 }
425 // Receiving data
426 for(int i=0;i<list_len;i++)
427 {
428 if(!simple_mode && !fd_map[i].erased && fd_map[i].einprogress &&
429 FD_ISSET(fd_map[i].fd, write_fds))
430 {
431 if (connect(fd_map[i].fd, (struct sockaddr *)&fd_map[i].sin,
432 sizeof (fd_map[i].sin)) == -1)
433 {
434 if(errno == EISCONN)
435 {
436 SCTPasp__Types::ASP__SCTP__RESULT asp_sctp_result;
437 asp_sctp_result.client__id() = fd_map[i].fd;
438 asp_sctp_result.error__status() = FALSE;
439 asp_sctp_result.error__message() = OMIT_VALUE;
440 incoming_message(asp_sctp_result);
441 fd_map[i].einprogress = FALSE;
442 FD_CLR(fd_map[i].fd, &writefds);
443 FD_SET(fd_map[i].fd, &readfds);
444 Install_Handler(&readfds, &writefds, NULL, 0.0);
445 errno = 0;
446 log("Connection successfully established to (%s):(%d)",
447 inet_ntoa(peer_IP_address), peer_port);
448 }
449 else
450 {
451 close(fd_map[i].fd);
452 fd = -1;
453 TTCN_warning("Connect error!");
454 SCTPasp__Types::ASP__SCTP__RESULT asp_sctp_result;
455 asp_sctp_result.client__id() = fd_map[i].fd;
456 asp_sctp_result.error__status() = TRUE;
457 asp_sctp_result.error__message() = strerror(errno);
458 incoming_message(asp_sctp_result);
459 FD_CLR(fd_map[i].fd, &writefds);
460 map_delete_item_fd(fd_map[i].fd);
461 Install_Handler(&readfds, &writefds, NULL, 0.0);
462 errno = 0;
463 log("Connection establishment to (%s):(%d) failed !",
464 inet_ntoa(peer_IP_address), peer_port);
465 }
466 }
467 }
468
469 if(!fd_map[i].erased && FD_ISSET(fd_map[i].fd, read_fds))
470 {
471 log("Calling Event_Handler.");
472 receiving_fd = fd_map[i].fd;
473
474 struct cmsghdr *cmsg;
475 struct sctp_sndrcvinfo *sri;
476 char cbuf[sizeof (*cmsg) + sizeof (*sri)];
477 struct msghdr msg;
478 struct iovec iov;
479 size_t cmsglen = sizeof (*cmsg) + sizeof (*sri);
480
481 if ( !fd_map[i].processing_message )
482 {
483 fd_map[i].buf = Malloc(BUFLEN);
484 fd_map[i].buflen = BUFLEN;
485 iov.iov_base = fd_map[i].buf;
486 iov.iov_len = fd_map[i].buflen;
487 }
488 else
489 {
490 // Set the next read offset
491 log("Event_Handler: setting the next read offset.");
492 iov.iov_base = (char *)fd_map[i].buf + fd_map[i].nr;
493 iov.iov_len = fd_map[i].buflen - fd_map[i].nr;
494 }
495
496 // Set up the msghdr structure for receiving
497 memset(&msg, 0, sizeof (msg));
498 msg.msg_iov = &iov;
499 msg.msg_iovlen = 1;
500 msg.msg_control = cbuf;
501 msg.msg_controllen = cmsglen;
502
503 memset(cbuf, 0, sizeof (*cmsg) + sizeof (*sri));
504 cmsg = (struct cmsghdr *)cbuf;
505 sri = (struct sctp_sndrcvinfo *)(cmsg + 1);
506
507 return_value_t value = getmsg(receiving_fd, &msg);
508 switch(value)
509 {
510 case WHOLE_MESSAGE_RECEIVED:
511 fd_map[i].processing_message = FALSE;
512 // Intercept notifications here
513 if (msg.msg_flags & MSG_NOTIFICATION)
514 {
515 log("Calling event_handler for an incoming notification.");
516 handle_event(fd_map[i].buf);
517 }
518 else
519 {
520 log("Incoming data.");
521 unsigned int ui = ntohl(sri->sinfo_ppid);
522 INTEGER i_ppid;
523 if (ui <= (unsigned long)INT_MAX)
524 i_ppid = ui;
525 else {
526 char sbuf[16];
527 sprintf(sbuf, "%u", ui);
528 i_ppid = INTEGER(sbuf);
529 }
530 incoming_message(SCTPasp__Types::ASP__SCTP(
531 INTEGER(receiving_fd),
532 INTEGER(sri->sinfo_stream),
533 i_ppid,
534 OCTETSTRING(fd_map[i].nr,(const unsigned char *)fd_map[i].buf)));
535 }
536 Free(fd_map[i].buf);
537 fd_map[i].buf = NULL;
538 break;
539 case PARTIAL_RECEIVE:
540 fd_map[i].processing_message = TRUE;
541 break;
542 case EOF_OR_ERROR:
543 if (!server_mode) fd = -1; // setting closed socket to -1 in client mode (and reconnect mode)
544 FD_CLR(receiving_fd, &readfds);
545 Install_Handler(&readfds, NULL, NULL, 0.0);
546 map_delete_item(i);
547 if (events.sctp_association_event) incoming_message(SCTPasp__Types::ASP__SCTP__ASSOC__CHANGE(
548 INTEGER(receiving_fd),
549 SCTPasp__Types::SAC__STATE(SCTP_COMM_LOST)));
550 log("getmsg() returned with NULL. Socket is closed.");
551 if (reconnect) forced_reconnect(reconnect_max_attempts);
552
553 break;
554 }//endswitch
555 }// endif
556 }// endfor
557}
558
559
560void SCTPasp__PT_PROVIDER::user_map(const char *system_port)
561{
562 log("Calling user_map(%s).",system_port);
563 if(simple_mode)
564 {
565 if ( server_mode && reconnect )
566 {
567 error("user_map(): server mode and reconnect mode are mutually exclusive!");
568 }
569 if ( server_mode && !local_port_is_present )
570 {
571 error("user_map(): in server mode local_port must be defined!");
572 }
573
574 // Server mode: turns on listening
575 if (server_mode)
576 {
577 log("Running in SERVER_MODE.");
578 create_socket();
579 if (listen(fd, server_backlog) == -1) error("Listen error!");
580 log("Listening @ (%s):(%d)", inet_ntoa(local_IP_address), local_port);
581 FD_SET(fd, &readfds);
582 Install_Handler(&readfds, NULL, NULL, 0.0);
583 } else if (reconnect) {
584 log("Running in RECONNECT MODE.");
585 forced_reconnect(reconnect_max_attempts+1);
586 } else {
587 log("Running in CLIENT MODE.");
588 }
589 }
590 else
591 {
592 log("Running in NORMAL MODE.");
593 }
594 log("Leaving user_map().");
595}
596
597
598void SCTPasp__PT_PROVIDER::user_unmap(const char *system_port)
599{
600 log("Calling user_unmap(%s).",system_port);
601 Uninstall_Handler();
602 FD_ZERO(&readfds);
603 FD_ZERO(&writefds);
604 if(!simple_mode)
605 {
606 for(int i=0;i<list_len;i++) map_delete_item(i);
607 for(int i=0;i<list_len_server;i++) map_delete_item_server(i);
608 }
609 else
610 {
611 for(int i=0;i<list_len;i++) map_delete_item(i);
612 if(server_mode) close(fd);
613 }
614 log("Leaving user_unmap().");
615}
616
617
618void SCTPasp__PT_PROVIDER::user_start()
619{
620 log("Calling user_start().");
621 log("Leaving user_start().");
622}
623
624
625void SCTPasp__PT_PROVIDER::user_stop()
626{
627 log("Calling user_stop().");
628 log("Leaving user_stop().");
629}
630
631
632void SCTPasp__PT_PROVIDER::outgoing_send(const SCTPasp__Types::ASP__SCTP__Connect& send_par)
633{
634 log("Calling outgoing_send (ASP_SCTP_CONNECT).");
635 if(simple_mode)
636 {
637 if (server_mode)
638 error("ASP_SCTP_CONNECT is not allowed in server mode!");
639 }
640 if( !peer_IP_address_is_present && !send_par.peer__hostname().ispresent() )
641 error("Peer IP address should be defined!");
642
643 if( !peer_port_is_present && !send_par.peer__portnumber().ispresent() )
644 error("Peer port should be defined!");
645 if(!simple_mode)
646 {
647 boolean temp_bool = local_port_is_present;
648 local_port_is_present = FALSE;
649 create_socket(); // creating client socket
650 local_port_is_present = temp_bool;
651 }
652 else
653 {
654 if (fd == -1) create_socket(); // checking if there is an open socket
655 else if(FD_ISSET(fd, &readfds)) // Active connection
656 error("ASP_SCTP_CONNECT called during active connection.");
657 }
658 struct sockaddr_in sin;
659 if(send_par.peer__hostname().ispresent())
660 {
661 peer_IP_address = get_in_addr((const char *)(const CHARSTRING&)send_par.peer__hostname());
662 }
663 if(send_par.peer__portnumber().ispresent())
664 peer_port = (int) (const INTEGER&) send_par.peer__portnumber();
665
666 sin.sin_family = AF_INET;
667 sin.sin_port = htons(peer_port);
668 sin.sin_addr.s_addr = peer_IP_address.s_addr;
669 log("Connecting to (%s):(%d)", inet_ntoa(peer_IP_address), peer_port);
670 // setting non-blocking mode
671 if(!simple_mode) setNonBlocking(fd);
672 if (connect(fd, (struct sockaddr *)&sin, sizeof (sin)) == -1)
673 {
674 if(errno == EINPROGRESS && !simple_mode)
675 {
676 map_put_item(fd);
677 int i = map_get_item(fd);
678 fd_map[i].einprogress = TRUE;
679 fd_map[i].sin.sin_family = AF_INET;
680 fd_map[i].sin.sin_port = htons(peer_port);;
681 fd_map[i].sin.sin_addr.s_addr= peer_IP_address.s_addr;
682 FD_SET(fd, &writefds);
683 Install_Handler(&readfds, &writefds, NULL, 0.0);
684 log("Connection in progress to (%s):(%d)", inet_ntoa(peer_IP_address),
685 peer_port);
686 }
687 else
688 {
689 close(fd);
690 fd = -1;
691 TTCN_warning("Connect error!");
692 SCTPasp__Types::ASP__SCTP__RESULT asp_sctp_result;
693 asp_sctp_result.client__id() = OMIT_VALUE;
694 asp_sctp_result.error__status() = TRUE;
695 asp_sctp_result.error__message() = strerror(errno);
696 incoming_message(asp_sctp_result);
697 }
698 errno = 0;
699 }
700 else
701 {
702 SCTPasp__Types::ASP__SCTP__RESULT asp_sctp_result;
703 asp_sctp_result.client__id() = fd;
704 asp_sctp_result.error__status() = FALSE;
705 asp_sctp_result.error__message() = OMIT_VALUE;
706 incoming_message(asp_sctp_result);
707 map_put_item(fd);
708 if(simple_mode) setNonBlocking(fd);
709 FD_SET(fd, &readfds);
710 Install_Handler(&readfds, NULL, NULL, 0.0);
711 log("Connection successfully established to (%s):(%d)", inet_ntoa(peer_IP_address), peer_port);
712 }
713 log("Leaving outgoing_send (ASP_SCTP_CONNECT).");
714}
715
716
717void SCTPasp__PT_PROVIDER::outgoing_send(const SCTPasp__Types::ASP__SCTP__ConnectFrom& send_par)
718{
719 log("Calling outgoing_send (ASP_SCTP_CONNECTFROM).");
720 if(!simple_mode)
721 {
722 if( !peer_IP_address_is_present && !send_par.peer__hostname().ispresent() )
723 error("Peer IP address should be defined!");
724 if( !peer_port_is_present && !send_par.peer__portnumber().ispresent() )
725 error("Peer port should be defined!");
726 // work around for create_socket()
727 unsigned short temp = local_port; // saving global variables
728 boolean temp_bool = local_port_is_present;
729 struct in_addr temp_local_IP_address = local_IP_address;
730 local_port = (int) (const INTEGER&) send_par.local__portnumber();
731 local_port_is_present = TRUE;
732 if(send_par.local__hostname().ispresent())
733 {
734 local_IP_address = get_in_addr((const char *)(const CHARSTRING&)send_par.local__hostname());
735 }
736 create_socket(); // creating client socket
737
738 struct sockaddr_in sin;
739 if(send_par.peer__hostname().ispresent())
740 {
741 peer_IP_address = get_in_addr((const char *)(const CHARSTRING&)send_par.peer__hostname());
742 }
743 if(send_par.peer__portnumber().ispresent())
744 peer_port = (int) (const INTEGER&) send_par.peer__portnumber();
745
746 sin.sin_family = AF_INET;
747 sin.sin_port = htons(peer_port);
748 sin.sin_addr.s_addr = peer_IP_address.s_addr;
749 log("Connecting to (%s):(%d)", inet_ntoa(peer_IP_address), peer_port);
750 // setting non-blocking mode
751 setNonBlocking(fd);
752 if (connect(fd, (struct sockaddr *)&sin, sizeof (sin)) == -1)
753 {
754 if(errno == EINPROGRESS)
755 {
756 map_put_item(fd);
757 int i = map_get_item(fd);
758 fd_map[i].einprogress = TRUE;
759 fd_map[i].sin.sin_family = AF_INET;
760 fd_map[i].sin.sin_port = htons(peer_port);;
761 fd_map[i].sin.sin_addr.s_addr= peer_IP_address.s_addr;
762 FD_SET(fd, &writefds);
763 Install_Handler(&readfds, &writefds, NULL, 0.0);
764 log("Connection in progress to (%s):(%d)", inet_ntoa(peer_IP_address),
765 peer_port);
766 }
767 else
768 {
769 close(fd);
770 fd = -1;
771 TTCN_warning("Connect error!");
772 SCTPasp__Types::ASP__SCTP__RESULT asp_sctp_result;
773 asp_sctp_result.client__id() = OMIT_VALUE;
774 asp_sctp_result.error__status() = TRUE;
775 asp_sctp_result.error__message() = strerror(errno);
776 incoming_message(asp_sctp_result);
777 }
778 errno = 0;
779 }
780 else
781 {
782 SCTPasp__Types::ASP__SCTP__RESULT asp_sctp_result;
783 asp_sctp_result.client__id() = fd;
784 asp_sctp_result.error__status() = FALSE;
785 asp_sctp_result.error__message() = OMIT_VALUE;
786 incoming_message(asp_sctp_result);
787 map_put_item(fd);
788 FD_SET(fd, &readfds);
789 Install_Handler(&readfds, NULL, NULL, 0.0);
790 log("Connection successfully established to (%s):(%d)", inet_ntoa(peer_IP_address), peer_port);
791 }
792 local_port = temp; // restoring global variables
793 local_port_is_present = temp_bool;
794 local_IP_address = temp_local_IP_address;
795 }
796 log("Leaving outgoing_send (ASP_SCTP_CONNECTFROM).");
797}
798
799
800void SCTPasp__PT_PROVIDER::outgoing_send(const SCTPasp__Types::ASP__SCTP__Listen& send_par)
801{
802 log("Calling outgoing_send (ASP_SCTP_LISTEN).");
803 if(!simple_mode)
804 {
805 // work around for create_socket()
806 unsigned short temp = local_port; // saving global variables
807 boolean temp_bool = local_port_is_present;
808 struct in_addr temp_local_IP_address = local_IP_address;
809 local_port = (int) (const INTEGER&) send_par.local__portnumber();
810 local_port_is_present = TRUE;
811 if(send_par.local__hostname().ispresent())
812 {
813 local_IP_address = get_in_addr((const char *)(const CHARSTRING&)send_par.local__hostname());
814 }
815 create_socket();
816 if (listen(fd, server_backlog) == -1) error("Listen error!");
817 map_put_item_server(fd, local_IP_address, local_port);
818 log("Listening @ (%s):(%d)", inet_ntoa(local_IP_address), local_port);
819 local_port = temp; // restoring global variables
820 local_port_is_present = temp_bool;
821 local_IP_address = temp_local_IP_address;
822 FD_SET(fd, &readfds);
823 Install_Handler(&readfds, NULL, NULL, 0.0);
824#ifdef SCTP_REPORT_LISTEN_RESULT
825 SCTPasp__Types::ASP__SCTP__RESULT asp_sctp_result;
826 asp_sctp_result.client__id() = fd;
827 asp_sctp_result.error__status() = FALSE;
828 asp_sctp_result.error__message() = OMIT_VALUE;
829 incoming_message(asp_sctp_result);
830#endif
831 }
832 log("Leaving outgoing_send (ASP_SCTP_LISTEN).");
833}
834
835
836void SCTPasp__PT_PROVIDER::outgoing_send(const SCTPasp__Types::ASP__SCTP__SetSocketOptions& send_par)
837{
838 log("Calling outgoing_send (ASP_SCTP_SETSOCKETOPTIONS).");
839 if(simple_mode)
840 {
841 if (fd == -1) create_socket(); // checking if there is an open socket
842 }
843 switch (send_par.get_selection())
844 {
845 case SCTPasp__Types::ASP__SCTP__SetSocketOptions::ALT_Sctp__init:
846 {
847 (void) memset(&initmsg, 0, sizeof(struct sctp_initmsg));
848 const SCTPasp__Types::SCTP__INIT& init = send_par.Sctp__init();
849 initmsg.sinit_num_ostreams = (int) init.sinit__num__ostreams();
850 initmsg.sinit_max_instreams = (int) init.sinit__max__instreams();
851 initmsg.sinit_max_attempts = (int) init.sinit__max__attempts();
852 initmsg.sinit_max_init_timeo = (int) init.sinit__max__init__timeo();
853 log("Setting SCTP socket options (initmsg).");
854 if (setsockopt(fd, IPPROTO_SCTP, SCTP_INITMSG, &initmsg,
855 sizeof(struct sctp_initmsg)) < 0)
856 {
857 TTCN_warning("Setsockopt error!");
858 SCTPasp__Types::ASP__SCTP__RESULT asp_sctp_result;
859 asp_sctp_result.client__id() = fd;
860 asp_sctp_result.error__status() = TRUE;
861 asp_sctp_result.error__message() = strerror(errno);
862 incoming_message(asp_sctp_result);
863 errno = 0;
864 }
865 else
866 {
867 SCTPasp__Types::ASP__SCTP__RESULT asp_sctp_result;
868 asp_sctp_result.client__id() = fd;
869 asp_sctp_result.error__status() = FALSE;
870 asp_sctp_result.error__message() = OMIT_VALUE;
871 incoming_message(asp_sctp_result);
872 }
873 break;
874 }
875 case SCTPasp__Types::ASP__SCTP__SetSocketOptions::ALT_Sctp__events:
876 {
877 const SCTPasp__Types::SCTP__EVENTS& event = send_par.Sctp__events();
878 events.sctp_data_io_event = (boolean) event.sctp__data__io__event();
879 events.sctp_association_event = (boolean) event.sctp__association__event();
880 events.sctp_address_event = (boolean) event.sctp__address__event();
881 events.sctp_send_failure_event = (boolean) event.sctp__send__failure__event();
882 events.sctp_peer_error_event = (boolean) event.sctp__peer__error__event();
883 events.sctp_shutdown_event = (boolean) event.sctp__shutdown__event();
884 events.sctp_partial_delivery_event = (boolean) event.sctp__partial__delivery__event();
885#if defined(LKSCTP_1_0_7) || defined(LKSCTP_1_0_9)
886 events.sctp_adaptation_layer_event = (boolean) event.sctp__adaption__layer__event();
887#else
888 events.sctp_adaption_layer_event = (boolean) event.sctp__adaption__layer__event();
889#endif
890 break;
891 }
892 case SCTPasp__Types::ASP__SCTP__SetSocketOptions::ALT_So__linger:
893 {
894 struct linger so_linger;
895 (void) memset(&so_linger, 0, sizeof (so_linger));
896 const SCTPasp__Types::SO__LINGER& so = send_par.So__linger();
897 so_linger.l_onoff = (int) so.l__onoff();
898 so_linger.l_linger = (int) so.l__linger();
899 // Setting a socket level option
900 log("Setting SCTP socket options (so_linger).");
901 if (setsockopt(fd, SOL_SOCKET, SCTP_EVENTS, &so_linger, sizeof (so_linger)) < 0)
902 {
903 TTCN_warning("Setsockopt error!");
904 SCTPasp__Types::ASP__SCTP__RESULT asp_sctp_result;
905 asp_sctp_result.client__id() = fd;
906 asp_sctp_result.error__status() = TRUE;
907 asp_sctp_result.error__message() = strerror(errno);
908 incoming_message(asp_sctp_result);
909 errno = 0;
910 }
911 else
912 {
913 SCTPasp__Types::ASP__SCTP__RESULT asp_sctp_result;
914 asp_sctp_result.client__id() = fd;
915 asp_sctp_result.error__status() = FALSE;
916 asp_sctp_result.error__message() = OMIT_VALUE;
917 incoming_message(asp_sctp_result);
918 }
919 break;
920 }
921 case SCTPasp__Types::ASP__SCTP__SetSocketOptions::ALT_Sctp__rtoinfo:
922 {
923 struct sctp_rtoinfo sctp_rtoinfo;
924 (void) memset(&sctp_rtoinfo, 0, sizeof (sctp_rtoinfo));
925 const SCTPasp__Types::SCTP__RTOINFO& rto = send_par.Sctp__rtoinfo();
926 int local_fd = (int) rto.client__id();
927 sctp_rtoinfo.srto_initial = (int) rto.srto__initial();
928 sctp_rtoinfo.srto_max = (int) rto.srto__max();
929 sctp_rtoinfo.srto_min = (int) rto.srto__min();
930 // Setting a SCTP level socket option
931 log("Setting SCTP socket options (sctp_rtoinfo).");
932 if (setsockopt(local_fd, IPPROTO_SCTP, SCTP_RTOINFO, &sctp_rtoinfo,
933 sizeof (sctp_rtoinfo)) < 0)
934 {
935 TTCN_warning("Setsockopt error!");
936 SCTPasp__Types::ASP__SCTP__RESULT asp_sctp_result;
937 asp_sctp_result.client__id() = local_fd;
938 asp_sctp_result.error__status() = TRUE;
939 asp_sctp_result.error__message() = strerror(errno);
940 incoming_message(asp_sctp_result);
941 errno = 0;
942 }
943 else
944 {
945 SCTPasp__Types::ASP__SCTP__RESULT asp_sctp_result;
946 asp_sctp_result.client__id() = local_fd;
947 asp_sctp_result.error__status() = FALSE;
948 asp_sctp_result.error__message() = OMIT_VALUE;
949 incoming_message(asp_sctp_result);
950 }
951 break;
952 }
953 default:
954 error("Setsocketoptions error: UNBOUND value!");
955 break;
956 }
957 log("Leaving outgoing_send (ASP_SCTP_SETSOCKETOPTIONS).");
958}
959
960
961void SCTPasp__PT_PROVIDER::outgoing_send(const SCTPasp__Types::ASP__SCTP__Close& send_par)
962{
963 log("Calling outgoing_send (ASP_SCTP_CLOSE).");
964 if(!simple_mode)
965 {
966 if(send_par.client__id().ispresent())
967 {
968 int local_fd = (int) (const INTEGER&) send_par.client__id();
969 log("NORMAL MODE: closing client/server socket (fd = %d).", local_fd);
970 map_delete_item_fd(local_fd);
971 map_delete_item_fd_server(local_fd);
972 FD_CLR(local_fd, &readfds);
973 Install_Handler(&readfds, &writefds, NULL, 0.0);
974 }
975 else
976 { // if OMIT is given then all sockets will be closed
977 log("NORMAL MODE: closing all sockets.");
978 for(int i=0;i<list_len;i++) map_delete_item(i);
979 for(int i=0;i<list_len_server;i++) map_delete_item_server(i);
980 FD_ZERO(&readfds);
981 FD_ZERO(&writefds);
982 Install_Handler(&readfds, &writefds, NULL, 0.0); // ???
983 }
984 }
985 else
986 {
987 if (server_mode)
988 { // closing the given connection
989 if(send_par.client__id().ispresent())
990 {
991 int local_fd = (int) (const INTEGER&) send_par.client__id();
992 log("SERVER MODE: closing client socket (fd = %d).", local_fd);
993 map_delete_item_fd(local_fd);
994 FD_CLR(local_fd, &readfds);
995 Install_Handler(&readfds, NULL, NULL, 0.0);
996 }
997 else
998 { // if OMIT is given in server mode then all clients will be closed
999 log("SERVER MODE: closing all client sockets.");
1000 for(int i=0;i<list_len;i++) map_delete_item(i);
1001 FD_ZERO(&readfds);
1002 FD_SET(fd, &readfds); // leaving only the listening socket in the fdset
1003 Install_Handler(&readfds, NULL, NULL, 0.0);
1004 }
1005 }
1006 else
1007 { // closing the connection to the server
1008 if ( send_par.client__id().ispresent() )
1009 error("In client mode the client_id field of ASP_SCTP_Close should be set to OMIT!");
1010 log("CLIENT MODE: closing socket (fd = %d).", fd);
1011 map_delete_item_fd(fd);
1012 FD_CLR(fd, &readfds);
1013 fd=-1;
1014 Install_Handler(&readfds, NULL, NULL, 0.0);
1015 }
1016 }
1017 log("Leaving outgoing_send (ASP_SCTP_CLOSE).");
1018}
1019
1020
1021void SCTPasp__PT_PROVIDER::outgoing_send(const SCTPasp__Types::ASP__SCTP& send_par)
1022{
1023 log("Calling outgoing_send (ASP_SCTP).");
1024 struct cmsghdr *cmsg;
1025 struct sctp_sndrcvinfo *sri;
1026 char cbuf[sizeof (*cmsg) + sizeof (*sri)];
1027 struct msghdr msg;
1028 struct iovec iov;
1029 const unsigned char *buf;
1030
1031 buf = (const unsigned char *)send_par.data();
1032 iov.iov_len = send_par.data().lengthof();
1033
1034 memset(&msg, 0, sizeof (msg));
1035 iov.iov_base = (char *)buf;
1036 msg.msg_iov = &iov;
1037 msg.msg_iovlen = 1;
1038 msg.msg_control = cbuf;
1039 msg.msg_controllen = sizeof (*cmsg) + sizeof (*sri);
1040
1041 memset(cbuf, 0, sizeof (*cmsg) + sizeof (*sri));
1042 cmsg = (struct cmsghdr *)cbuf;
1043 sri = (struct sctp_sndrcvinfo *)(cmsg + 1);
1044
1045 cmsg->cmsg_len = sizeof (*cmsg) + sizeof (*sri);
1046 cmsg->cmsg_level = IPPROTO_SCTP;
1047 cmsg->cmsg_type = SCTP_SNDRCV;
1048
1049 sri->sinfo_stream = (int) send_par.sinfo__stream();
1050
1051 int target;
1052 if(!simple_mode)
1053 {
1054 if (!send_par.client__id().ispresent())
1055 error("In NORMAL mode the client_id field of ASP_SCTP should be set to a valid value and not to omit!");
1056 target = (int) (const INTEGER&) send_par.client__id();
1057 if ( (map_get_item(target)==-1) && (map_get_item_server(target)==-1)) error("Bad client id! %d",target);
1058 }
1059 else
1060 {
1061 if (server_mode)
1062 {
1063 if (!send_par.client__id().ispresent())
1064 error("In server mode the client_id field of ASP_SCTP should be set to a valid value and not to omit!");
1065 }
1066 else // client mode
1067 {
1068 if (send_par.client__id().ispresent())
1069 error("In client mode the client_id field of ASP_SCTP should be set to OMIT!");
1070 }
1071 target = fd;
1072 if (server_mode)
1073 target = (int) (const INTEGER&) send_par.client__id();
1074 if (map_get_item(target)==-1) error("Bad client id! %d",target);
1075 }
1076
1077 uint32_t ui;
1078 if (send_par.sinfo__ppid().get_val().is_native() && send_par.sinfo__ppid() > 0)
1079 ui = (int)send_par.sinfo__ppid();
1080 else {
1081 OCTETSTRING os = int2oct(send_par.sinfo__ppid(), 4);
1082 unsigned char* p = (unsigned char*)&ui;
1083 *(p++) = os[3].get_octet();
1084 *(p++) = os[2].get_octet();
1085 *(p++) = os[1].get_octet();
1086 *(p++) = os[0].get_octet();
1087 }
1088 sri->sinfo_ppid = htonl(ui);
1089
1090 log("Sending SCTP message to file descriptor %d.", target);
1091 if (sendmsg(target, &msg, 0) < 0)
1092 {
1093 SCTPasp__Types::ASP__SCTP__SENDMSG__ERROR asp_sctp_sendmsg_error;
1094 if (server_mode) asp_sctp_sendmsg_error.client__id() = target;
1095 else asp_sctp_sendmsg_error.client__id() = OMIT_VALUE;
1096 asp_sctp_sendmsg_error.sinfo__stream() = send_par.sinfo__stream();
1097 asp_sctp_sendmsg_error.sinfo__ppid() = send_par.sinfo__ppid();
1098 asp_sctp_sendmsg_error.data() = send_par.data();
1099 incoming_message(asp_sctp_sendmsg_error);
1100 TTCN_warning("Sendmsg error! Strerror=%s", strerror(errno));
1101
1102 errno = 0;
1103 }
1104 log("Leaving outgoing_send (ASP_SCTP).");
1105}
1106
1107
1108SCTPasp__PT_PROVIDER::return_value_t SCTPasp__PT_PROVIDER::getmsg(int fd, struct msghdr *msg)
1109{
1110 log("Calling getmsg().");
1111 int index = map_get_item(fd);
1112 if ( !fd_map[index].processing_message ) fd_map[index].nr = 0;
1113
1114 ssize_t value = recvmsg(fd, msg, 0);
1115 if (value <= 0) // EOF or error
1116 {
1117 log("Leaving getmsg(): EOF or error.");
1118 errno = 0;
1119 return EOF_OR_ERROR;
1120 }
1121 fd_map[index].nr += value;
1122 log("getmsg(): [%d] bytes received. Receiving buffer now has [%d] bytes.", value, fd_map[index].nr);
1123 // Whole message is received, return it.
1124 if (msg->msg_flags & MSG_EOR)
1125 {
1126 log("Leaving getmsg(): whole message is received.");
1127 return WHOLE_MESSAGE_RECEIVED;
1128 }
1129
1130 // Maybe we need a bigger buffer, do realloc().
1131 if (fd_map[index].buflen == fd_map[index].nr)
1132 {
1133 log("getmsg(): resizing receiving buffer: [%d] bytes -> [%d] bytes",
1134 fd_map[index].buflen, (fd_map[index].buflen * 2));
1135 fd_map[index].buf = Realloc(fd_map[index].buf, fd_map[index].buflen * 2);
1136 fd_map[index].buflen *= 2;
1137 }
1138 log("Leaving getmsg(): part of the message is received.");
1139 return PARTIAL_RECEIVE;
1140}
1141
1142
1143void SCTPasp__PT_PROVIDER::handle_event(void *buf)
1144{
1145 union sctp_notification *snp;
1146 snp = (sctp_notification *)buf;
1147 switch (snp->sn_header.sn_type)
1148 {
1149 case SCTP_ASSOC_CHANGE:
1150 {
1151 log("incoming SCTP_ASSOC_CHANGE event.");
1152 struct sctp_assoc_change *sac;
1153 sac = &snp->sn_assoc_change;
1154
1155// #ifdef LKSCTP_1_0_7
1156 SCTPasp__Types::SAC__STATE sac_state_ttcn;
1157 switch(sac->sac_state)
1158 {
1159 case SCTP_COMM_UP:
1160 sac_state_ttcn = SCTPasp__Types::SAC__STATE::SCTP__COMM__UP;
1161 break;
1162
1163 case SCTP_COMM_LOST:
1164 sac_state_ttcn = SCTPasp__Types::SAC__STATE::SCTP__COMM__LOST;
1165 break;
1166
1167 case SCTP_RESTART:
1168 sac_state_ttcn = SCTPasp__Types::SAC__STATE::SCTP__RESTART;
1169 break;
1170
1171 case SCTP_SHUTDOWN_COMP:
1172 sac_state_ttcn = SCTPasp__Types::SAC__STATE::SCTP__SHUTDOWN__COMP;
1173 break;
1174
1175 case SCTP_CANT_STR_ASSOC:
1176 sac_state_ttcn = SCTPasp__Types::SAC__STATE::SCTP__CANT__STR__ASSOC;
1177 break;
1178
1179 default:
1180 sac_state_ttcn = SCTPasp__Types::SAC__STATE::SCTP__UNKNOWN__SAC__STATE;
1181 TTCN_warning("Unexpected sac_state value received %d", sac->sac_state);
1182 break;
1183 }
1184// #endif
1185
1186 if(sac->sac_state == SCTP_COMM_LOST)
1187 {
1188 if(simple_mode)
1189 {
1190 if (!server_mode) fd = -1; // setting closed socket to -1 in client mode (and reconnect mode)
1191 FD_CLR(receiving_fd, &readfds);
1192 Install_Handler(&readfds, NULL, NULL, 0.0);
1193 map_delete_item_fd(receiving_fd);
1194 }
1195 else
1196 {
1197 FD_CLR(receiving_fd, &readfds);
1198 Install_Handler(&readfds, NULL, NULL, 0.0);
1199 map_delete_item_fd(receiving_fd);
1200 map_delete_item_fd_server(receiving_fd);
1201 }
1202 }
1203 if (events.sctp_association_event) incoming_message(SCTPasp__Types::ASP__SCTP__ASSOC__CHANGE(
1204 INTEGER(receiving_fd),
1205 sac_state_ttcn
1206 ));
1207
1208 if(simple_mode)
1209 {
1210 if (reconnect && (sac->sac_state == SCTP_COMM_LOST) ) forced_reconnect(reconnect_max_attempts);
1211 }
1212 break;
1213 }
1214 case SCTP_PEER_ADDR_CHANGE:{
1215 log("incoming SCTP_PEER_ADDR_CHANGE event.");
1216 struct sctp_paddr_change *spc;
1217 spc = &snp->sn_paddr_change;
1218// #ifdef LKSCTP_1_0_7
1219 SCTPasp__Types::SPC__STATE spc_state_ttcn;
1220 switch(spc->spc_state)
1221 {
1222 case SCTP_ADDR_AVAILABLE:
1223 spc_state_ttcn = SCTPasp__Types::SPC__STATE::SCTP__ADDR__AVAILABLE;
1224 break;
1225
1226 case SCTP_ADDR_UNREACHABLE:
1227 spc_state_ttcn = SCTPasp__Types::SPC__STATE::SCTP__ADDR__UNREACHABLE;
1228 break;
1229
1230 case SCTP_ADDR_REMOVED:
1231 spc_state_ttcn = SCTPasp__Types::SPC__STATE::SCTP__ADDR__REMOVED;
1232 break;
1233
1234 case SCTP_ADDR_ADDED:
1235 spc_state_ttcn = SCTPasp__Types::SPC__STATE::SCTP__ADDR__ADDED;
1236 break;
1237
1238 case SCTP_ADDR_MADE_PRIM:
1239 spc_state_ttcn = SCTPasp__Types::SPC__STATE::SCTP__ADDR__MADE__PRIM;
1240 break;
1241#if defined(LKSCTP_1_0_7) || defined(LKSCTP_1_0_9)
1242 case SCTP_ADDR_CONFIRMED:
1243 spc_state_ttcn = SCTPasp__Types::SPC__STATE::SCTP__ADDR__CONFIRMED;
1244 break;
1245#endif
1246 default:
1247 spc_state_ttcn = SCTPasp__Types::SPC__STATE::SCTP__UNKNOWN__SPC__STATE;
1248 TTCN_warning("Unexpected spc_state value received %d", spc->spc_state);
1249 break;
1250 }
1251// #endif
1252 if (events.sctp_address_event) incoming_message(SCTPasp__Types::ASP__SCTP__PEER__ADDR__CHANGE(
1253 INTEGER(receiving_fd),
1254 spc_state_ttcn
1255 ));
1256 break;
1257 }
1258 case SCTP_REMOTE_ERROR:
1259 log("incoming SCTP_REMOTE_ERROR event.");
1260 //struct sctp_remote_error *sre;
1261 //sre = &snp->sn_remote_error;
1262 if (events.sctp_peer_error_event) incoming_message(SCTPasp__Types::ASP__SCTP__REMOTE__ERROR(INTEGER(receiving_fd)));
1263 break;
1264 case SCTP_SEND_FAILED:
1265 log("incoming SCTP_SEND_FAILED event.");
1266 //struct sctp_send_failed *ssf;
1267 //ssf = &snp->sn_send_failed;
1268 if (events.sctp_send_failure_event) incoming_message(SCTPasp__Types::ASP__SCTP__SEND__FAILED(INTEGER(receiving_fd)));
1269 break;
1270 case SCTP_SHUTDOWN_EVENT:
1271 log("incoming SCTP_SHUTDOWN_EVENT event.");
1272 //struct sctp_shutdown_event *sse;
1273 //sse = &snp->sn_shutdown_event;
1274 if (events.sctp_shutdown_event) incoming_message(SCTPasp__Types::ASP__SCTP__SHUTDOWN__EVENT(INTEGER(receiving_fd)));
1275 break;
1276#if defined(LKSCTP_1_0_7) || defined(LKSCTP_1_0_9)
1277 case SCTP_ADAPTATION_INDICATION:
1278 log("incoming SCTP_ADAPTION_INDICATION event.");
1279 //struct sctp_adaptation_event *sai;
1280 //sai = &snp->sn_adaptation_event;
1281 if (events.sctp_adaptation_layer_event) incoming_message(SCTPasp__Types::ASP__SCTP__ADAPTION__INDICATION(INTEGER(receiving_fd)));
1282 break;
1283#else
1284 case SCTP_ADAPTION_INDICATION:
1285 log("incoming SCTP_ADAPTION_INDICATION event.");
1286 //struct sctp_adaption_event *sai;
1287 //sai = &snp->sn_adaption_event;
1288 if (events.sctp_adaption_layer_event) incoming_message(SCTPasp__Types::ASP__SCTP__ADAPTION__INDICATION(INTEGER(receiving_fd)));
1289 break;
1290#endif
1291 case SCTP_PARTIAL_DELIVERY_EVENT:
1292 log("incoming SCTP_PARTIAL_DELIVERY_EVENT event.");
1293 //struct sctp_pdapi_event *pdapi;
1294 //pdapi = &snp->sn_pdapi_event;
1295 if (events.sctp_partial_delivery_event) incoming_message(SCTPasp__Types::ASP__SCTP__PARTIAL__DELIVERY__EVENT(INTEGER(receiving_fd)));
1296 break;
1297 default:
1298 TTCN_warning("Unknown notification type!");
1299 break;
1300 }
1301}
1302
1303
1304void SCTPasp__PT_PROVIDER::log(const char *fmt, ...)
1305{
1306 if(debug)
1307 {
1308 va_list ap;
1309 va_start(ap, fmt);
1310 TTCN_Logger::begin_event(TTCN_DEBUG);
1311 TTCN_Logger::log_event("SCTPasp Test Port (%s): ", get_name());
1312 TTCN_Logger::log_event_va_list(fmt, ap);
1313 TTCN_Logger::end_event();
1314 va_end(ap);
1315
1316 }
1317}
1318
1319
1320void SCTPasp__PT_PROVIDER::error(const char *fmt, ...)
1321{
1322 va_list ap;
1323 va_start(ap, fmt);
1324 TTCN_Logger::begin_event(TTCN_ERROR);
1325 TTCN_Logger::log_event("SCTPasp Test Port (%s): ", get_name());
1326 TTCN_Logger::log_event_va_list(fmt, ap);
1327 TTCN_Logger::end_event();
1328 va_end(ap);
1329 TTCN_error("Fatal error in SCTPasp Test Port %s (see above).", get_name());
1330}
1331
1332
1333void SCTPasp__PT_PROVIDER::forced_reconnect(int attempts)
1334{
1335 struct sockaddr_in sin;
1336 sin.sin_family = AF_INET;
1337 sin.sin_port = htons(peer_port);
1338 sin.sin_addr.s_addr = peer_IP_address.s_addr;
1339 log("[reconnect] Connecting to (%s):(%d)", inet_ntoa(peer_IP_address), peer_port);
1340 unsigned int sleep_interval = 1;
1341 int i;
1342 for(i = 0; i < attempts; i++)
1343 {
1344 create_socket();
1345 if (connect(fd, (struct sockaddr *)&sin, sizeof (sin)) == -1)
1346 {
1347 close(fd);
1348 fd = -1;
1349 TTCN_warning("Connect error!");
1350 errno = 0;
1351 if( ((i % 2 ) == 0) && (i != 0)) sleep_interval *= 2;
1352 sleep(sleep_interval);
1353
1354 }
1355 else
1356 {
1357 map_put_item(fd);
1358 setNonBlocking(fd);
1359 FD_SET(fd, &readfds);
1360 Install_Handler(&readfds, NULL, NULL, 0.0);
1361 log("[reconnect] Connection successfully established to (%s):(%d)", inet_ntoa(peer_IP_address), peer_port);
1362 break;
1363 }
1364 }
1365 if (i == attempts) error("Forced reconnect failed! Remote end is unreachable!");
1366
1367}
1368
1369
1370void SCTPasp__PT_PROVIDER::map_put_item(int fd)
1371{
1372 int i=0;
1373 while((i<list_len) && !fd_map[i].erased) i++; // searching for the free item
1374 if(i==list_len)
1375 { // list is full add new elemnts
1376 list_len+=MAP_LENGTH;
1377 fd_map=(fd_map_item *)Realloc(fd_map,(list_len)*sizeof(fd_map_item));
1378 for(int k=i;k<list_len;k++)
1379 { // init new elements
1380 fd_map[k].fd=-1;
1381 fd_map[k].erased=TRUE;
1382 fd_map[k].einprogress=FALSE;
1383 fd_map[k].buf=NULL;
1384 fd_map[k].buflen=0;
1385 fd_map[k].processing_message=FALSE;
1386 fd_map[k].nr=0;
1387 fd_map[k].sin.sin_family=AF_INET;
1388 fd_map[k].sin.sin_port=0;
1389 fd_map[k].sin.sin_addr.s_addr=0;
1390 }
1391 }
1392 fd_map[i].fd=fd; // adding new connection
1393 fd_map[i].erased=FALSE;
1394}
1395
1396
1397int SCTPasp__PT_PROVIDER::map_get_item(int fd)
1398{
1399 for(int i = 0; i < list_len; i++)
1400 if( !(fd_map[i].erased) && (fd_map[i].fd == fd) ) return i;
1401 return(-1);
1402}
1403
1404
1405void SCTPasp__PT_PROVIDER::map_delete_item_fd(int fd)
1406{
1407 if(fd!=-1)
1408 for(int i = 0; i < list_len; i++)
1409 if( fd_map[i].fd == fd )
1410 {
1411 map_delete_item(i);
1412 break;
1413 }
1414}
1415
1416
1417void SCTPasp__PT_PROVIDER::map_delete_item(int index)
1418{
1419 if((index>=list_len) || (index<0)) error("map_delete_item: index out of range (0-%d): %d",list_len-1,index);
1420
1421 if(fd_map[index].fd!=-1) close(fd_map[index].fd);
1422 fd_map[index].fd=-1;
1423 fd_map[index].erased=TRUE;
1424 fd_map[index].einprogress=FALSE;
1425 if(fd_map[index].buf) Free(fd_map[index].buf);
1426 fd_map[index].buf=NULL;
1427 fd_map[index].buflen=0;
1428 fd_map[index].processing_message=FALSE;
1429 fd_map[index].nr=0;
1430 fd_map[index].sin.sin_family=AF_INET;
1431 fd_map[index].sin.sin_port=0;
1432 fd_map[index].sin.sin_addr.s_addr=0;
1433}
1434
1435
1436void SCTPasp__PT_PROVIDER::map_put_item_server(int fd, struct in_addr local_IP_address, unsigned short local_port)
1437{
1438 int i=0;
1439 while((i<list_len_server) && !fd_map_server[i].erased) i++; // searching for the free item
1440 if(i==list_len_server)
1441 { // list is full add new elemnts
1442 list_len_server+=MAP_LENGTH;
1443 fd_map_server=(fd_map_server_item *)Realloc(fd_map_server,(list_len_server)*sizeof(fd_map_server_item));
1444 for(int k=i;k<list_len_server;k++)
1445 { // init new elements
1446 fd_map_server[k].fd=-1;
1447 fd_map_server[k].erased=TRUE;
1448 fd_map_server[k].local_IP_address.s_addr = INADDR_ANY;
1449 fd_map_server[k].local_port = 0;
1450 }
1451 }
1452 fd_map_server[i].fd=fd; // adding new connection
1453 fd_map_server[i].erased=FALSE;
1454 fd_map_server[i].local_IP_address = local_IP_address;
1455 fd_map_server[i].local_port = local_port;
1456
1457}
1458
1459
1460int SCTPasp__PT_PROVIDER::map_get_item_server(int fd)
1461{
1462 for(int i = 0; i < list_len_server; i++)
1463 if( !(fd_map_server[i].erased) && (fd_map_server[i].fd == fd) ) return i;
1464 return(-1);
1465}
1466
1467
1468void SCTPasp__PT_PROVIDER::map_delete_item_fd_server(int fd)
1469{
1470 if(fd!=-1)
1471 for(int i = 0; i < list_len_server; i++)
1472 if( fd_map_server[i].fd == fd )
1473 {
1474 map_delete_item_server(i);
1475 break;
1476 }
1477}
1478
1479
1480void SCTPasp__PT_PROVIDER::map_delete_item_server(int index)
1481{
1482 if((index>=list_len_server) || (index<0)) error("map_delete_item: index out of range (0-%d): %d",list_len_server-1,index);
1483
1484 if(fd_map_server[index].fd!=-1) close(fd_map_server[index].fd);
1485 fd_map_server[index].fd=-1;
1486 fd_map_server[index].erased=TRUE;
1487 fd_map_server[index].local_IP_address.s_addr = INADDR_ANY;
1488 fd_map_server[index].local_port = 0;
1489}
1490
1491
1492void SCTPasp__PT_PROVIDER::create_socket()
1493{
1494 struct sockaddr_in sin;
1495
1496 log("Creating SCTP socket.");
1497 if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP)) == -1)
1498 error("Socket error: cannot create socket!");
1499
1500 if ( local_port_is_present ) {
1501 sin.sin_family = AF_INET;
1502 sin.sin_port = htons(local_port);
1503 sin.sin_addr.s_addr = local_IP_address.s_addr;
1504 log("Binding SCTP socket: bind address (%s):(%d)",
1505 inet_ntoa(local_IP_address),local_port);
1506 if (bind(fd, (struct sockaddr *)&sin, sizeof (sin)) == -1)
1507 {
1508 close(fd);
1509 fd = -1;
1510 error("Bind error!");
1511 }
1512 }
1513
1514 log("Setting SCTP socket options (initmsg).");
1515 if (setsockopt(fd, IPPROTO_SCTP, SCTP_INITMSG, &initmsg,
1516 sizeof(struct sctp_initmsg)) < 0)
1517 {
1518 TTCN_warning("Setsockopt error!");
1519 errno = 0;
1520 }
1521
1522 log("Setting SCTP socket options (events).");
1523 if (setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof (events)) < 0)
1524 {
1525 TTCN_warning("Setsockopt error!");
1526 errno = 0;
1527 }
1528}
1529
1530
1531in_addr SCTPasp__PT_PROVIDER::get_in_addr(const char *hostname)
1532{
1533 struct hostent *h;
1534 if ((h=gethostbyname(hostname)) == NULL)
1535 error("Gethostbyname error!");
1536 if(h->h_addr == NULL) error("Gethostbyname error! h->h_addr is NULL!");
1537 return *((struct in_addr *)h->h_addr);
1538}
1539
1540void SCTPasp__PT_PROVIDER::setNonBlocking(int fd)
1541{
1542 int flags = fcntl(fd, F_GETFL);
1543 flags |= O_NONBLOCK;
1544 int result = fcntl(fd, F_SETFL, flags);
1545 if (result==-1) error("SCTPasp__PT::setNonBlocking(): Fcntl() error!");
1546}
1547
1548
1549}