1 /*
2  * Copyright (C) 2005-2013 Michael Tuexen
3  * Copyright (C) 2011-2013 Irene Ruengeler
4  * Copyright (C) 2014-2019 Felix Weinrank
5  *
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the project nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.	IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 
33 #include <sys/types.h>
34 #ifdef _WIN32
35 #include <winsock2.h>
36 #include <ws2tcpip.h>
37 #include <stdlib.h>
38 #include <crtdbg.h>
39 #include <sys/timeb.h>
40 #else
41 #include <sys/socket.h>
42 #include <netinet/in.h>
43 #include <arpa/inet.h>
44 #include <sys/time.h>
45 #include <unistd.h>
46 #include <pthread.h>
47 #endif
48 #include <stdarg.h>
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <string.h>
52 #include <signal.h>
53 #include <errno.h>
54 #include <inttypes.h>
55 #ifdef LINUX
56 #include <getopt.h>
57 #endif
58 #include <usrsctp.h>
59 #include "programs_helper.h"
60 
61 #define TSCTP_CLIENT 1
62 #define TSCTP_SERVER 2
63 
64 #define DEFAULT_LENGTH             1024
65 #define DEFAULT_NUMBER_OF_MESSAGES 1024
66 #define DEFAULT_PORT               5001
67 #define BUFFERSIZE                 (1<<16)
68 
69 static int par_verbose = 0;
70 static int par_very_verbose = 0;
71 static unsigned int done = 0;
72 
73 struct tsctp_meta {
74 	uint8_t par_role;
75 	uint8_t par_stats_human;
76 	uint8_t par_ordered;
77 	uint64_t par_messages;
78 	uint64_t par_message_length;
79 	uint64_t par_runtime;
80 
81 	uint64_t stat_messages;
82 	uint64_t stat_message_length;
83 	uint64_t stat_notifications;
84 	uint64_t stat_recv_calls;
85 	struct timeval stat_start;
86 
87 	uint64_t stat_fragment_sum;
88 
89 	char *buffer;
90 };
91 
92 #ifndef timersub
93 #define timersub(tvp, uvp, vvp)                                   \
94 	do {                                                      \
95 		(vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec;    \
96 		(vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \
97 		if ((vvp)->tv_usec < 0) {                         \
98 			(vvp)->tv_sec--;                          \
99 			(vvp)->tv_usec += 1000000;                \
100 		}                                                 \
101 	} while (0)
102 #endif
103 
104 #ifdef _WIN32
105 static void
gettimeofday(struct timeval * tv,void * ignore)106 gettimeofday(struct timeval *tv, void *ignore)
107 {
108 	struct timeb tb;
109 
110 	ftime(&tb);
111 	tv->tv_sec = (long)tb.time;
112 	tv->tv_usec = tb.millitm * 1000;
113 }
114 #endif
115 
116 
117 char Usage[] =
118 "Usage: tsctp [options] [address]\n"
119 "Options:\n"
120 "        -a             set adaptation layer indication\n"
121 "        -E             local UDP encapsulation port (default 9899)\n"
122 "        -f             fragmentation point\n"
123 "        -H             human readable statistics"
124 "        -l             message length\n"
125 "        -L             bind to local IP (default INADDR_ANY)\n"
126 "        -n             number of messages sent (0 means infinite)/received\n"
127 "        -D             turns Nagle off\n"
128 "        -R             socket recv buffer\n"
129 "        -S             socket send buffer\n"
130 "        -T             time to send messages\n"
131 "        -u             use unordered user messages\n"
132 "        -U             remote UDP encapsulation port\n"
133 "        -v             verbose\n"
134 "        -V             very verbose\n"
135 ;
136 
137 static void handle_upcall(struct socket *upcall_socket, void *upcall_data, int upcall_flags);
138 
bytes2human(uint64_t bytes)139 static const char *bytes2human(uint64_t bytes)
140 {
141 	char *suffix[] = {"", "K", "M", "G", "T"};
142 	char suffix_length = sizeof(suffix) / sizeof(suffix[0]);
143 	int i = 0;
144 	double human_size = bytes;
145 	static char output[200];
146 
147 	if (bytes > 1024) {
148 		for (i = 0; (bytes / 1024) > 0 && i < suffix_length - 1; i++) {
149 			human_size = bytes / 1024.0;
150 			bytes /= 1024;
151 		}
152 	}
153 
154 	if (snprintf(output, sizeof(output), "%.02lf %s", human_size, suffix[i]) < 0) {
155 		output[0] = '\0';
156 	}
157 	return output;
158 }
159 
160 
161 static void
handle_accept(struct socket * upcall_socket,void * upcall_data,int upcall_flags)162 handle_accept(struct socket *upcall_socket, void *upcall_data, int upcall_flags)
163 {
164 	struct socket *conn_sock;
165 	struct sockaddr_in remote_addr;
166 	socklen_t addr_len = sizeof(struct sockaddr_in);
167 	struct tsctp_meta *meta_listening, *meta_accepted;
168 	char addrbuf[INET_ADDRSTRLEN];
169 
170 	meta_listening = (struct tsctp_meta *) upcall_data;
171 
172 	memset(&remote_addr, 0, sizeof(struct sockaddr_in));
173 	if (((conn_sock = usrsctp_accept(upcall_socket, (struct sockaddr *) &remote_addr, &addr_len)) == NULL) && (errno != EINPROGRESS)) {
174 		perror("usrsctp_accept");
175 		exit(EXIT_FAILURE);
176 	}
177 
178 	if (par_verbose) {
179 		printf("Connection accepted from %s:%d\n", inet_ntop(AF_INET, &(remote_addr.sin_addr), addrbuf, INET_ADDRSTRLEN), ntohs(remote_addr.sin_port));
180 	}
181 
182 	meta_accepted = malloc(sizeof(struct tsctp_meta));
183 	if (!meta_accepted) {
184 		printf("malloc() failed!\n");
185 		exit(EXIT_FAILURE);
186 	}
187 
188 	memset(meta_accepted, 0, sizeof(struct tsctp_meta));
189 
190 	meta_accepted->par_role = meta_listening->par_role;
191 	meta_accepted->par_stats_human = meta_listening->par_stats_human;
192 	meta_accepted->buffer = malloc(BUFFERSIZE);
193 
194 	if (!meta_accepted->buffer) {
195 		printf("malloc() failed!\n");
196 		exit(EXIT_FAILURE);
197 	}
198 
199 	usrsctp_set_upcall(conn_sock, handle_upcall, meta_accepted);
200 }
201 
202 static void
handle_upcall(struct socket * upcall_socket,void * upcall_data,int upcall_flags)203 handle_upcall(struct socket *upcall_socket, void *upcall_data, int upcall_flags)
204 {
205 	int events = usrsctp_get_events(upcall_socket);
206 	struct tsctp_meta* tsctp_meta = (struct tsctp_meta*) upcall_data;
207 
208 	struct sctp_recvv_rn rn;
209 	ssize_t n;
210 	struct sockaddr_storage addr;
211 	int recv_flags = 0;
212 	socklen_t len = (socklen_t)sizeof(struct sockaddr_storage);
213 	unsigned int infotype = 0;
214 	socklen_t infolen = sizeof(struct sctp_recvv_rn);
215 	struct sctp_rcvinfo *rcvinfo = (struct sctp_rcvinfo *) &rn;
216 	memset(&rn, 0, sizeof(struct sctp_recvv_rn));
217 	struct timeval note_time;
218 	union sctp_notification *snp;
219 	struct sctp_paddr_change *spc;
220 	struct timeval time_now;
221 	struct timeval time_diff;
222 	float seconds;
223 	struct sctp_sndinfo snd_info;
224 
225 	if (events & SCTP_EVENT_READ) {
226 		while ((n = usrsctp_recvv(upcall_socket, tsctp_meta->buffer, BUFFERSIZE, (struct sockaddr *) &addr, &len, (void *)&rn, &infolen, &infotype, &recv_flags)) > 0) {
227 
228 			if (!tsctp_meta->stat_recv_calls) {
229 				gettimeofday(&tsctp_meta->stat_start, NULL);
230 			}
231 			tsctp_meta->stat_recv_calls++;
232 
233 			if (recv_flags & MSG_NOTIFICATION) {
234 				tsctp_meta->stat_notifications++;
235 				gettimeofday(&note_time, NULL);
236 				if (par_verbose) {
237 					printf("notification arrived at %f\n", note_time.tv_sec + (double)note_time.tv_usec / 1000000.0);
238 
239 					snp = (union sctp_notification *)tsctp_meta->buffer;
240 					if (snp->sn_header.sn_type == SCTP_PEER_ADDR_CHANGE) {
241 						spc = &snp->sn_paddr_change;
242 						printf("SCTP_PEER_ADDR_CHANGE: state=%d, error=%d\n",spc->spc_state, spc->spc_error);
243 					}
244 				}
245 			} else {
246 				if (par_very_verbose) {
247 					if (infotype == SCTP_RECVV_RCVINFO) {
248 						printf("Message received - %zd bytes - %s - sid %u - tsn %u %s\n",
249 							n,
250 							(rcvinfo->rcv_flags & SCTP_UNORDERED) ? "unordered" : "ordered",
251 							rcvinfo->rcv_sid,
252 							rcvinfo->rcv_tsn,
253 							(recv_flags & MSG_EOR) ? "- EOR" : ""
254 						);
255 
256 					} else {
257 						printf("Message received - %zd bytes %s\n", n, (recv_flags & MSG_EOR) ? "- EOR" : "");
258 					}
259 				}
260 				tsctp_meta->stat_fragment_sum += n;
261 				if (recv_flags & MSG_EOR) {
262 					tsctp_meta->stat_messages++;
263 					if (tsctp_meta->stat_message_length == 0) {
264 						tsctp_meta->stat_message_length = tsctp_meta->stat_fragment_sum;
265 					}
266 				}
267 			}
268 		}
269 
270 		if (n < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
271 			perror("usrsctp_recvv");
272 			exit(EXIT_FAILURE);
273 		}
274 
275 		if (n == 0) {
276 			done = 1;
277 
278 			gettimeofday(&time_now, NULL);
279 			timersub(&time_now, &tsctp_meta->stat_start, &time_diff);
280 			seconds = time_diff.tv_sec + (double)time_diff.tv_usec / 1000000.0;
281 
282 			if (tsctp_meta->par_stats_human) {
283 				printf("Connection closed - statistics\n");
284 
285 				printf("\tmessage size  : %" PRIu64 "\n", tsctp_meta->stat_message_length);
286 				printf("\tmessages      : %" PRIu64 "\n", tsctp_meta->stat_messages);
287 				printf("\trecv() calls  : %" PRIu64 "\n", tsctp_meta->stat_recv_calls);
288 				printf("\tnotifications : %" PRIu64 "\n", tsctp_meta->stat_notifications);
289 				printf("\ttransferred   : %sByte\n", bytes2human(tsctp_meta->stat_message_length * tsctp_meta->stat_messages));
290 				printf("\truntime       : %.2f s\n", seconds);
291 				printf("\tgoodput       : %sBit/s\n", bytes2human((double) tsctp_meta->stat_message_length * (double) tsctp_meta->stat_messages / seconds * 8));
292 
293 			} else {
294 				printf("%" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %f, %f, %" PRIu64 "\n",
295 						tsctp_meta->stat_message_length,
296 						tsctp_meta->stat_messages,
297 						tsctp_meta->stat_recv_calls,
298 						tsctp_meta->stat_message_length * tsctp_meta->stat_messages,
299 						seconds,
300 						(double) tsctp_meta->stat_message_length * (double) tsctp_meta->stat_messages / seconds,
301 						tsctp_meta->stat_notifications);
302 			}
303 			fflush(stdout);
304 			usrsctp_close(upcall_socket);
305 
306 			free(tsctp_meta->buffer);
307 			free(tsctp_meta);
308 			return;
309 		}
310 	}
311 
312 	if ((events & SCTP_EVENT_WRITE) && tsctp_meta->par_role == TSCTP_CLIENT && !done) {
313 
314 		memset(&snd_info, 0, sizeof(struct sctp_sndinfo));
315 		if (tsctp_meta->par_ordered == 0) {
316 			snd_info.snd_flags |= SCTP_UNORDERED;
317 		}
318 
319 		while ((n = usrsctp_sendv(upcall_socket, tsctp_meta->buffer, tsctp_meta->par_message_length, NULL, 0, &snd_info, (socklen_t)sizeof(struct sctp_sndinfo), SCTP_SENDV_SNDINFO, 0)) > 0) {
320 			if (tsctp_meta->stat_messages == 0) {
321 				gettimeofday(&tsctp_meta->stat_start, NULL);
322 			}
323 			tsctp_meta->stat_messages++;
324 
325 			if (par_very_verbose) {
326 				printf("Message #%" PRIu64 " sent\n", tsctp_meta->stat_messages);
327 			}
328 
329 			if (tsctp_meta->par_messages && tsctp_meta->par_messages == tsctp_meta->stat_messages) {
330 				break;
331 			}
332 		}
333 
334 		if (errno != EAGAIN && errno != EWOULDBLOCK) {
335 			done = 1;
336 			usrsctp_close(upcall_socket);
337 			printf("client socket %p closed\n", (void *)upcall_socket);
338 			free(tsctp_meta->buffer);
339 			free(tsctp_meta);
340 			return;
341 		}
342 
343 		gettimeofday(&time_now, NULL);
344 		timersub(&time_now, &tsctp_meta->stat_start, &time_diff);
345 		seconds = time_diff.tv_sec + (double)time_diff.tv_usec / 1000000.0;
346 
347 		if ((tsctp_meta->par_messages && tsctp_meta->par_messages == tsctp_meta->stat_messages) ||
348 			(tsctp_meta->par_runtime && tsctp_meta->par_runtime <= seconds)) {
349 
350 			if (par_verbose) {
351 				printf("Runtime or max messages reached - finishing...\n");
352 			}
353 
354 			done = 1;
355 			usrsctp_close(upcall_socket);
356 			free(tsctp_meta->buffer);
357 			free(tsctp_meta);
358 			return;
359 		}
360 	}
361 
362 	return;
363 }
364 
main(int argc,char ** argv)365 int main(int argc, char **argv)
366 {
367 #ifndef _WIN32
368 	int c;
369 #endif
370 	struct socket *psock = NULL;
371 	struct sockaddr_in local_addr;
372 	struct sockaddr_in remote_addr;
373 	int optval;
374 	uint16_t local_port;
375 	uint16_t remote_port;
376 	uint16_t local_udp_port;
377 	uint16_t remote_udp_port;
378 	int rcvbufsize = 0;
379 	int sndbufsize = 0;
380 	socklen_t intlen;
381 	int nodelay = 0;
382 	struct sctp_assoc_value av;
383 	struct sctp_udpencaps encaps;
384 	struct tsctp_meta *meta;
385 
386 	uint16_t par_port = DEFAULT_PORT;
387 	uint8_t par_stats_human = 0;
388 	int par_ordered = 1;
389 	int par_message_length = DEFAULT_LENGTH;
390 	int par_messages = DEFAULT_NUMBER_OF_MESSAGES;
391 	int par_runtime = 0;
392 
393 #ifdef _WIN32
394 	unsigned long src_addr;
395 #else
396 	in_addr_t src_addr;
397 #endif
398 	int fragpoint = 0;
399 	struct sctp_setadaptation ind = {0};
400 #ifdef _WIN32
401 	char *opt;
402 	int optind;
403 #endif
404 
405 	remote_udp_port = 0;
406 	local_udp_port = 9899;
407 	src_addr = htonl(INADDR_ANY);
408 
409 	memset((void *) &remote_addr, 0, sizeof(struct sockaddr_in));
410 	memset((void *) &local_addr, 0, sizeof(struct sockaddr_in));
411 
412 #ifndef _WIN32
413 	while ((c = getopt(argc, argv, "a:DE:f:Hl:L:n:p:R:S:T:uU:vV")) != -1)
414 		switch(c) {
415 			case 'a':
416 				ind.ssb_adaptation_ind = atoi(optarg);
417 				break;
418 			case 'D':
419 				nodelay = 1;
420 				break;
421 			case 'E':
422 				local_udp_port = atoi(optarg);
423 				break;
424 			case 'f':
425 				fragpoint = atoi(optarg);
426 				break;
427 			case 'H':
428 				par_stats_human = 1;
429 				break;
430 			case 'l':
431 				par_message_length = atoi(optarg);
432 				break;
433 			case 'L':
434 				if (inet_pton(AF_INET, optarg, &src_addr) != 1) {
435 					printf("Can't parse %s\n", optarg);
436 					exit(EXIT_FAILURE);
437 				}
438 				break;
439 			case 'n':
440 				par_messages = atoi(optarg);
441 				break;
442 			case 'p':
443 				par_port = atoi(optarg);
444 				break;
445 			case 'R':
446 				rcvbufsize = atoi(optarg);
447 				break;
448 			case 'S':
449 				sndbufsize = atoi(optarg);
450 				break;
451 			case 'T':
452 				par_runtime = atoi(optarg);
453 				par_messages = 0;
454 				break;
455 			case 'u':
456 				par_ordered = 0;
457 				break;
458 			case 'U':
459 				remote_udp_port = atoi(optarg);
460 				break;
461 			case 'v':
462 				par_verbose = 1;
463 				break;
464 			case 'V':
465 				par_verbose = 1;
466 				par_very_verbose = 1;
467 				break;
468 			default:
469 				fprintf(stderr, "%s", Usage);
470 				exit(1);
471 		}
472 #else
473 	for (optind = 1; optind < argc; optind++) {
474 		if (argv[optind][0] == '-') {
475 			switch (argv[optind][1]) {
476 				case 'a':
477 					if (++optind >= argc) {
478 						printf("%s", Usage);
479 						exit(1);
480 					}
481 					opt = argv[optind];
482 					ind.ssb_adaptation_ind = atoi(opt);
483 					break;
484 				case 'D':
485 					nodelay = 1;
486 					break;
487 				case 'E':
488 					if (++optind >= argc) {
489 						printf("%s", Usage);
490 						exit(1);
491 					}
492 					opt = argv[optind];
493 					local_udp_port = atoi(opt);
494 					break;
495 				case 'f':
496 					if (++optind >= argc) {
497 						printf("%s", Usage);
498 						exit(1);
499 					}
500 					opt = argv[optind];
501 					fragpoint = atoi(opt);
502 					break;
503 				case 'H':
504 					par_stats_human = 1;
505 					break;
506 				case 'l':
507 					if (++optind >= argc) {
508 						printf("%s", Usage);
509 						exit(1);
510 					}
511 					opt = argv[optind];
512 					par_message_length = atoi(opt);
513 					break;
514 				case 'L':
515 					if (++optind >= argc) {
516 						printf("%s", Usage);
517 						exit(1);
518 					}
519 					opt = argv[optind];
520 					inet_pton(AF_INET, opt, &src_addr);
521 					break;
522 				case 'n':
523 					if (++optind >= argc) {
524 						printf("%s", Usage);
525 						exit(1);
526 					}
527 					opt = argv[optind];
528 					par_messages = atoi(opt);
529 					break;
530 				case 'p':
531 					if (++optind >= argc) {
532 						printf("%s", Usage);
533 						exit(1);
534 					}
535 					opt = argv[optind];
536 					par_port = atoi(opt);
537 					break;
538 				case 'R':
539 					if (++optind >= argc) {
540 						printf("%s", Usage);
541 						exit(1);
542 					}
543 					opt = argv[optind];
544 					rcvbufsize = atoi(opt);
545 					break;
546 				case 'S':
547 					if (++optind >= argc) {
548 						printf("%s", Usage);
549 						exit(1);
550 					}
551 					opt = argv[optind];
552 					sndbufsize = atoi(opt);
553 					break;
554 				case 'T':
555 					if (++optind >= argc) {
556 						printf("%s", Usage);
557 						exit(1);
558 					}
559 					opt = argv[optind];
560 					par_runtime = atoi(opt);
561 					par_messages = 0;
562 					break;
563 				case 'u':
564 					par_ordered = 0;
565 					break;
566 				case 'U':
567 					if (++optind >= argc) {
568 						printf("%s", Usage);
569 						exit(1);
570 					}
571 					opt = argv[optind];
572 					remote_udp_port = atoi(opt);
573 					break;
574 				case 'v':
575 					par_verbose = 1;
576 					break;
577 				case 'V':
578 					par_verbose = 1;
579 					par_very_verbose = 1;
580 					break;
581 				default:
582 					printf("%s", Usage);
583 					exit(1);
584 			}
585 		} else {
586 			break;
587 		}
588 	}
589 #endif
590 
591 	meta = malloc(sizeof(struct tsctp_meta));
592 	if (!meta) {
593 		printf("malloc() failed!\n");
594 		exit(EXIT_FAILURE);
595 	}
596 
597 	memset(meta, 0, sizeof(struct tsctp_meta));
598 
599 	meta->buffer = malloc(BUFFERSIZE);
600 	if (!meta->buffer) {
601 		printf("malloc() failed!\n");
602 		exit(EXIT_FAILURE);
603 	}
604 
605 	meta->par_stats_human = par_stats_human;
606 	meta->par_message_length = par_message_length;
607 	meta->par_messages = par_messages;
608 	meta->par_ordered = par_ordered;
609 	meta->par_runtime = par_runtime;
610 
611 	if (optind == argc) {
612 		meta->par_role = TSCTP_SERVER;
613 		local_port = par_port;
614 		remote_port = 0;
615 	} else {
616 		meta->par_role = TSCTP_CLIENT;
617 		local_port = 0;
618 		remote_port = par_port;
619 	}
620 	local_addr.sin_family = AF_INET;
621 #ifdef HAVE_SIN_LEN
622 	local_addr.sin_len = sizeof(struct sockaddr_in);
623 #endif
624 	local_addr.sin_port = htons(local_port);
625 	local_addr.sin_addr.s_addr = src_addr;
626 
627 	usrsctp_init(local_udp_port, NULL, debug_printf_stack);
628 #ifdef SCTP_DEBUG
629 	usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_ALL);
630 #endif
631 	usrsctp_sysctl_set_sctp_blackhole(2);
632 	usrsctp_sysctl_set_sctp_no_csum_on_loopback(0);
633 	usrsctp_sysctl_set_sctp_enable_sack_immediately(1);
634 
635 	if (!(psock = usrsctp_socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP, NULL, NULL, 0, NULL))) {
636 		perror("user_socket");
637 		exit(EXIT_FAILURE);
638 	}
639 
640 	optval = 1;
641 	if (usrsctp_setsockopt(psock, IPPROTO_SCTP, SCTP_RECVRCVINFO, &optval, sizeof(optval)) < 0) {
642 		perror("usrsctp_setsockopt SCTP_RECVRCVINFO");
643 	}
644 
645 	usrsctp_set_non_blocking(psock, 1);
646 
647 	if (usrsctp_bind(psock, (struct sockaddr *) &local_addr, sizeof(struct sockaddr_in)) == -1) {
648 		perror("usrsctp_bind");
649 		exit(1);
650 	}
651 
652 	if (usrsctp_setsockopt(psock, IPPROTO_SCTP, SCTP_ADAPTATION_LAYER, (const void*)&ind, (socklen_t)sizeof(struct sctp_setadaptation)) < 0) {
653 		perror("setsockopt");
654 	}
655 
656 	if (meta->par_role == TSCTP_SERVER) {
657 		if (rcvbufsize) {
658 			if (usrsctp_setsockopt(psock, SOL_SOCKET, SO_RCVBUF, &rcvbufsize, sizeof(int)) < 0) {
659 				perror("setsockopt: rcvbuf");
660 			}
661 		}
662 		if (par_verbose) {
663 			intlen = sizeof(int);
664 			if (usrsctp_getsockopt(psock, SOL_SOCKET, SO_RCVBUF, &rcvbufsize, (socklen_t *)&intlen) < 0) {
665 				perror("getsockopt: rcvbuf");
666 			} else {
667 				fprintf(stdout, "Receive buffer size: %d.\n", rcvbufsize);
668 			}
669 		}
670 
671 		if (usrsctp_listen(psock, 1) < 0) {
672 			perror("usrsctp_listen");
673 			exit(EXIT_FAILURE);
674 		}
675 
676 		usrsctp_set_upcall(psock, handle_accept, meta);
677 
678 		while (1) {
679 #ifdef _WIN32
680 			Sleep(1000);
681 #else
682 			sleep(1);
683 #endif
684 		}
685 
686 	} else {
687 		memset(&encaps, 0, sizeof(struct sctp_udpencaps));
688 		encaps.sue_address.ss_family = AF_INET;
689 		encaps.sue_port = htons(remote_udp_port);
690 		if (usrsctp_setsockopt(psock, IPPROTO_SCTP, SCTP_REMOTE_UDP_ENCAPS_PORT, (const void*)&encaps, (socklen_t)sizeof(struct sctp_udpencaps)) < 0) {
691 			perror("setsockopt");
692 		}
693 
694 		remote_addr.sin_family = AF_INET;
695 #ifdef HAVE_SIN_LEN
696 		remote_addr.sin_len = sizeof(struct sockaddr_in);
697 #endif
698 		if (!inet_pton(AF_INET, argv[optind], &remote_addr.sin_addr.s_addr)){
699 			printf("error: invalid destination address\n");
700 			exit(EXIT_FAILURE);
701 		}
702 		remote_addr.sin_port = htons(remote_port);
703 
704 		memset(meta->buffer, 'X', BUFFERSIZE);
705 
706 		usrsctp_set_upcall(psock, handle_upcall, meta);
707 
708 		usrsctp_setsockopt(psock, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, sizeof(nodelay));
709 
710 		if (fragpoint) {
711 			av.assoc_id = 0;
712 			av.assoc_value = fragpoint;
713 			if (usrsctp_setsockopt(psock, IPPROTO_SCTP, SCTP_MAXSEG, &av, sizeof(struct sctp_assoc_value)) < 0) {
714 				perror("setsockopt: SCTP_MAXSEG");
715 			}
716 		}
717 
718 		if (sndbufsize) {
719 			if (usrsctp_setsockopt(psock, SOL_SOCKET, SO_SNDBUF, &sndbufsize, sizeof(int)) < 0) {
720 				perror("setsockopt: sndbuf");
721 			}
722 		}
723 
724 		if (par_verbose) {
725 			intlen = sizeof(int);
726 			if (usrsctp_getsockopt(psock, SOL_SOCKET, SO_SNDBUF, &sndbufsize, (socklen_t *)&intlen) < 0) {
727 				perror("setsockopt: SO_SNDBUF");
728 			} else {
729 				fprintf(stdout,"Send buffer size: %d.\n", sndbufsize);
730 			}
731 		}
732 
733 		if (usrsctp_connect(psock, (struct sockaddr *) &remote_addr, sizeof(struct sockaddr_in)) == -1 ) {
734 			if (errno != EINPROGRESS) {
735 				perror("usrsctp_connect");
736 				exit(EXIT_FAILURE);
737 			}
738 		}
739 
740 		while (!done) {
741 #ifdef _WIN32
742 			Sleep(1000);
743 #else
744 			sleep(1);
745 #endif
746 		}
747 
748 		if (par_verbose) {
749 			printf("Finished... \n");
750 		}
751 	}
752 
753 	while (usrsctp_finish() != 0) {
754 #ifdef _WIN32
755 		Sleep(1000);
756 #else
757 		sleep(1);
758 #endif
759 	}
760 
761 	return 0;
762 }
763