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