diff options
Diffstat (limited to 'programs/tsctp.c')
-rw-r--r-- | programs/tsctp.c | 816 |
1 files changed, 816 insertions, 0 deletions
diff --git a/programs/tsctp.c b/programs/tsctp.c new file mode 100644 index 00000000..b94f5016 --- /dev/null +++ b/programs/tsctp.c @@ -0,0 +1,816 @@ +/* + * Copyright (C) 2005-2013 Michael Tuexen + * Copyright (C) 2011-2013 Irene Ruengeler + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/types.h> +#ifdef _WIN32 +#include <winsock2.h> +#include <ws2tcpip.h> +#include <stdlib.h> +#include <crtdbg.h> +#include <sys/timeb.h> +#else +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <sys/time.h> +#include <unistd.h> +#include <pthread.h> +#endif +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <signal.h> +#include <errno.h> +#ifdef LINUX +#include <getopt.h> +#endif +#include <usrsctp.h> +#include "programs_helper.h" + +/* global for the send callback, but used in kernel version as well */ +static unsigned long number_of_messages; +static char *buffer; +static int length; +static struct sockaddr_in remote_addr; +static int unordered; +uint32_t optval = 1; +struct socket *psock = NULL; + +static struct timeval start_time; +unsigned int runtime = 0; +static unsigned long cb_messages = 0; +static unsigned long long cb_first_length = 0; +static unsigned long long cb_sum = 0; +static unsigned int use_cb = 0; + +#ifdef _WIN32 +static void +gettimeofday(struct timeval *tv, void *ignore) +{ + struct timeb tb; + + ftime(&tb); + tv->tv_sec = (long)tb.time; + tv->tv_usec = tb.millitm * 1000; +} +#endif + + +char Usage[] = +"Usage: tsctp [options] [address]\n" +"Options:\n" +" -a set adaptation layer indication\n" +" -c use callback API\n" +" -E local UDP encapsulation port (default 9899)\n" +" -f fragmentation point\n" +" -l message length\n" +" -L bind to local IP (default INADDR_ANY)\n" +" -n number of messages sent (0 means infinite)/received\n" +" -D turns Nagle off\n" +" -R socket recv buffer\n" +" -S socket send buffer\n" +" -T time to send messages\n" +" -u use unordered user messages\n" +" -U remote UDP encapsulation port\n" +" -v verbose\n" +" -V very verbose\n" +; + +#define DEFAULT_LENGTH 1024 +#define DEFAULT_NUMBER_OF_MESSAGES 1024 +#define DEFAULT_PORT 5001 +#define BUFFERSIZE (1<<16) + +static int verbose, very_verbose; +static unsigned int done; + +void stop_sender(int sig) +{ + done = 1; +} + +#ifdef _WIN32 +static DWORD WINAPI +#else +static void * +#endif +handle_connection(void *arg) +{ + ssize_t n; + char *buf; + +#if !defined(_WIN32) + pthread_t tid; +#endif + struct socket *conn_sock; + struct timeval time_start, time_now, time_diff; + double seconds; + unsigned long recv_calls = 0; + unsigned long notifications = 0; + int flags; + struct sockaddr_in addr; + socklen_t len; + union sctp_notification *snp; + struct sctp_paddr_change *spc; + struct timeval note_time; + unsigned int infotype; + struct sctp_recvv_rn rn; + socklen_t infolen = sizeof(struct sctp_recvv_rn); + unsigned long messages = 0; + unsigned long long first_length = 0; + unsigned long long sum = 0; + + conn_sock = *(struct socket **)arg; + +#if !defined(_WIN32) + tid = pthread_self(); + pthread_detach(tid); +#endif + + buf = malloc(BUFFERSIZE); + flags = 0; + len = (socklen_t)sizeof(struct sockaddr_in); + infotype = 0; + memset(&rn, 0, sizeof(struct sctp_recvv_rn)); + n = usrsctp_recvv(conn_sock, buf, BUFFERSIZE, (struct sockaddr *) &addr, &len, (void *)&rn, + &infolen, &infotype, &flags); + + gettimeofday(&time_start, NULL); + while (n > 0) { + recv_calls++; + if (flags & MSG_NOTIFICATION) { + notifications++; + gettimeofday(¬e_time, NULL); + printf("notification arrived at %f\n", note_time.tv_sec+(double)note_time.tv_usec/1000000.0); + snp = (union sctp_notification *)buf; + if (snp->sn_header.sn_type == SCTP_PEER_ADDR_CHANGE) { + spc = &snp->sn_paddr_change; + printf("SCTP_PEER_ADDR_CHANGE: state=%d, error=%d\n",spc->spc_state, spc->spc_error); + } + } else { + if (very_verbose) { + printf("Message received\n"); + } + sum += n; + if (flags & MSG_EOR) { + messages++; + if (first_length == 0) { + first_length = sum; + } + } + } + flags = 0; + len = (socklen_t)sizeof(struct sockaddr_in); + infolen = sizeof(struct sctp_recvv_rn); + infotype = 0; + memset(&rn, 0, sizeof(struct sctp_recvv_rn)); + n = usrsctp_recvv(conn_sock, (void *) buf, BUFFERSIZE, (struct sockaddr *) &addr, &len, (void *)&rn, + &infolen, &infotype, &flags); + } + if (n < 0) { + perror("sctp_recvv"); + } + gettimeofday(&time_now, NULL); + timersub(&time_now, &time_start, &time_diff); + seconds = time_diff.tv_sec + (double)time_diff.tv_usec/1000000.0; + printf("%llu, %lu, %lu, %llu, %f, %f, %lu\n", + first_length, messages, recv_calls, sum, seconds, (double)first_length * (double)messages / seconds, notifications); + fflush(stdout); + usrsctp_close(conn_sock); + free(buf); +#ifdef _WIN32 + return 0; +#else + return (NULL); +#endif +} + +static int +send_cb(struct socket *sock, uint32_t sb_free) { + struct sctp_sndinfo sndinfo; + + if ((cb_messages == 0) && verbose) { + printf("Start sending "); + if (number_of_messages > 0) { + printf("%ld messages ", (long)number_of_messages); + } + if (runtime > 0) { + printf("for %u seconds ...", runtime); + } + printf("\n"); + fflush(stdout); + } + + sndinfo.snd_sid = 0; + sndinfo.snd_flags = 0; + if (unordered != 0) { + sndinfo.snd_flags |= SCTP_UNORDERED; + } + sndinfo.snd_ppid = 0; + sndinfo.snd_context = 0; + sndinfo.snd_assoc_id = 0; + + while (!done && ((number_of_messages == 0) || (cb_messages < (number_of_messages - 1)))) { + if (very_verbose) { + printf("Sending message number %lu.\n", cb_messages + 1); + } + + if (usrsctp_sendv(psock, buffer, length, + (struct sockaddr *) &remote_addr, 1, + (void *)&sndinfo, (socklen_t)sizeof(struct sctp_sndinfo), SCTP_SENDV_SNDINFO, + 0) < 0) { + if (errno != EWOULDBLOCK && errno != EAGAIN) { + perror("usrsctp_sendv (cb)"); + exit(1); + } else { + if (very_verbose){ + printf("EWOULDBLOCK or EAGAIN for message number %lu - will retry\n", cb_messages + 1); + } + /* send until EWOULDBLOCK then exit callback. */ + return (1); + } + } + cb_messages++; + } + if ((done == 1) || (cb_messages == (number_of_messages - 1))) { + if (very_verbose) { + printf("Sending final message number %lu.\n", cb_messages + 1); + } + + sndinfo.snd_flags |= SCTP_EOF; + if (usrsctp_sendv(psock, buffer, length, (struct sockaddr *) &remote_addr, 1, + (void *)&sndinfo, (socklen_t)sizeof(struct sctp_sndinfo), SCTP_SENDV_SNDINFO, + 0) < 0) { + if (errno != EWOULDBLOCK && errno != EAGAIN) { + perror("usrsctp_sendv (cb)"); + exit(1); + } else { + if (very_verbose){ + printf("EWOULDBLOCK or EAGAIN for final message number %lu - will retry\n", cb_messages + 1); + } + /* send until EWOULDBLOCK then exit callback. */ + return (1); + } + } + cb_messages++; + done = 2; + } + + return (1); +} + +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) +{ + struct timeval now, diff_time; + double seconds; + + if (data == NULL) { + gettimeofday(&now, NULL); + timersub(&now, &start_time, &diff_time); + seconds = diff_time.tv_sec + (double)diff_time.tv_usec / 1000000.0; + printf("%llu, %lu, %llu, %f, %f\n", + cb_first_length, cb_messages, cb_sum, seconds, (double)cb_first_length * (double)cb_messages / seconds); + usrsctp_close(sock); + cb_first_length = 0; + cb_sum = 0; + cb_messages = 0; + return (1); + } + if (cb_first_length == 0) { + cb_first_length = (unsigned int)datalen; + gettimeofday(&start_time, NULL); + } + cb_sum += datalen; + cb_messages++; + + free(data); + return (1); +} + +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) +{ + free(data); + return (1); +} + +int main(int argc, char **argv) +{ +#ifndef _WIN32 + int c, rc; +#endif + socklen_t addr_len; + struct sockaddr_in local_addr; + struct timeval time_start, time_now, time_diff; + int client; + uint16_t local_port, remote_port, port, local_udp_port, remote_udp_port; + int rcvbufsize=0, sndbufsize=0, myrcvbufsize, mysndbufsize; + socklen_t intlen; + double seconds; + double throughput; + int nodelay = 0; + struct sctp_assoc_value av; + struct sctp_udpencaps encaps; + struct sctp_sndinfo sndinfo; + unsigned long messages = 0; +#ifdef _WIN32 + unsigned long srcAddr; + HANDLE tid; +#else + in_addr_t srcAddr; + pthread_t tid; +#endif + int fragpoint = 0; + struct sctp_setadaptation ind = {0}; +#ifdef _WIN32 + char *opt; + int optind; +#endif + unordered = 0; + + length = DEFAULT_LENGTH; + number_of_messages = DEFAULT_NUMBER_OF_MESSAGES; + port = DEFAULT_PORT; + remote_udp_port = 0; + local_udp_port = 9899; + verbose = 0; + very_verbose = 0; + srcAddr = htonl(INADDR_ANY); + + memset((void *) &remote_addr, 0, sizeof(struct sockaddr_in)); + memset((void *) &local_addr, 0, sizeof(struct sockaddr_in)); + +#ifndef _WIN32 + while ((c = getopt(argc, argv, "a:cp:l:E:f:L:n:R:S:T:uU:vVD")) != -1) + switch(c) { + case 'a': + ind.ssb_adaptation_ind = atoi(optarg); + break; + case 'c': + use_cb = 1; + break; + case 'l': + length = atoi(optarg); + break; + case 'n': + number_of_messages = atoi(optarg); + break; + case 'p': + port = atoi(optarg); + break; + case 'E': + local_udp_port = atoi(optarg); + break; + case 'f': + fragpoint = atoi(optarg); + break; + case 'L': + if (inet_pton(AF_INET, optarg, &srcAddr) != 1) { + printf("Can't parse %s\n", optarg); + } + break; + case 'R': + rcvbufsize = atoi(optarg); + break; + case 'S': + sndbufsize = atoi(optarg); + break; + case 'T': + runtime = atoi(optarg); + number_of_messages = 0; + break; + case 'u': + unordered = 1; + break; + case 'U': + remote_udp_port = atoi(optarg); + break; + case 'v': + verbose = 1; + break; + case 'V': + verbose = 1; + very_verbose = 1; + break; + case 'D': + nodelay = 1; + break; + default: + fprintf(stderr, "%s", Usage); + exit(1); + } +#else + for (optind = 1; optind < argc; optind++) { + if (argv[optind][0] == '-') { + switch (argv[optind][1]) { + case 'a': + if (++optind >= argc) { + printf("%s", Usage); + exit(1); + } + opt = argv[optind]; + ind.ssb_adaptation_ind = atoi(opt); + break; + case 'c': + use_cb = 1; + break; + case 'l': + if (++optind >= argc) { + printf("%s", Usage); + exit(1); + } + opt = argv[optind]; + length = atoi(opt); + break; + case 'p': + if (++optind >= argc) { + printf("%s", Usage); + exit(1); + } + opt = argv[optind]; + port = atoi(opt); + break; + case 'n': + if (++optind >= argc) { + printf("%s", Usage); + exit(1); + } + opt = argv[optind]; + number_of_messages = atoi(opt); + break; + case 'f': + if (++optind >= argc) { + printf("%s", Usage); + exit(1); + } + opt = argv[optind]; + fragpoint = atoi(opt); + break; + case 'L': + if (++optind >= argc) { + printf("%s", Usage); + exit(1); + } + opt = argv[optind]; + inet_pton(AF_INET, opt, &srcAddr); + break; + case 'U': + if (++optind >= argc) { + printf("%s", Usage); + exit(1); + } + opt = argv[optind]; + remote_udp_port = atoi(opt); + break; + case 'E': + if (++optind >= argc) { + printf("%s", Usage); + exit(1); + } + opt = argv[optind]; + local_udp_port = atoi(opt); + break; + case 'R': + if (++optind >= argc) { + printf("%s", Usage); + exit(1); + } + opt = argv[optind]; + rcvbufsize = atoi(opt); + break; + case 'S': + if (++optind >= argc) { + printf("%s", Usage); + exit(1); + } + opt = argv[optind]; + sndbufsize = atoi(opt); + break; + case 'T': + if (++optind >= argc) { + printf("%s", Usage); + exit(1); + } + opt = argv[optind]; + runtime = atoi(opt); + number_of_messages = 0; + break; + case 'u': + unordered = 1; + break; + case 'v': + verbose = 1; + break; + case 'V': + verbose = 1; + very_verbose = 1; + break; + case 'D': + nodelay = 1; + break; + default: + printf("%s", Usage); + exit(1); + } + } else { + break; + } + } +#endif + if (optind == argc) { + client = 0; + local_port = port; + remote_port = 0; + } else { + client = 1; + local_port = 0; + remote_port = port; + } + local_addr.sin_family = AF_INET; +#ifdef HAVE_SIN_LEN + local_addr.sin_len = sizeof(struct sockaddr_in); +#endif + local_addr.sin_port = htons(local_port); + local_addr.sin_addr.s_addr = srcAddr; + + usrsctp_init(local_udp_port, NULL, debug_printf_stack); +#ifdef SCTP_DEBUG + usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_ALL); +#endif + usrsctp_sysctl_set_sctp_blackhole(2); + usrsctp_sysctl_set_sctp_no_csum_on_loopback(0); + usrsctp_sysctl_set_sctp_enable_sack_immediately(1); + + if (client) { + if (use_cb) { + if (!(psock = usrsctp_socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP, client_receive_cb, send_cb, length, NULL))) { + perror("user_socket"); + exit(1); + } + } else { + if (!(psock = usrsctp_socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP, NULL, NULL, 0, NULL))) { + perror("user_socket"); + exit(1); + } + } + } else { + if (use_cb) { + if (!(psock = usrsctp_socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP, server_receive_cb, NULL, 0, NULL))) { + perror("user_socket"); + exit(1); + } + } else { + if (!(psock = usrsctp_socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP, NULL, NULL, 0, NULL))) { + perror("user_socket"); + exit(1); + } + } + } + + if (usrsctp_bind(psock, (struct sockaddr *)&local_addr, sizeof(struct sockaddr_in)) == -1) { + perror("usrsctp_bind"); + exit(1); + } + + if (usrsctp_setsockopt(psock, IPPROTO_SCTP, SCTP_ADAPTATION_LAYER, (const void*)&ind, (socklen_t)sizeof(struct sctp_setadaptation)) < 0) { + perror("setsockopt"); + } + + if (!client) { + if (rcvbufsize) { + if (usrsctp_setsockopt(psock, SOL_SOCKET, SO_RCVBUF, &rcvbufsize, sizeof(int)) < 0) { + perror("setsockopt: rcvbuf"); + } + } + if (verbose) { + intlen = sizeof(int); + if (usrsctp_getsockopt(psock, SOL_SOCKET, SO_RCVBUF, &myrcvbufsize, (socklen_t *)&intlen) < 0) { + perror("getsockopt: rcvbuf"); + } else { + fprintf(stdout,"Receive buffer size: %d.\n", myrcvbufsize); + } + } + + if (usrsctp_listen(psock, 1) < 0) { + perror("usrsctp_listen"); + exit(1); + } + + while (1) { + memset(&remote_addr, 0, sizeof(struct sockaddr_in)); + addr_len = sizeof(struct sockaddr_in); + if (use_cb) { + struct socket *conn_sock; + + if ((conn_sock = usrsctp_accept(psock, (struct sockaddr *) &remote_addr, &addr_len)) == NULL) { + perror("usrsctp_accept"); + continue; + } + } else { + struct socket **conn_sock; + + conn_sock = (struct socket **) malloc(sizeof(struct socket *)); + if ((*conn_sock = usrsctp_accept(psock, (struct sockaddr *) &remote_addr, &addr_len)) == NULL) { + perror("usrsctp_accept"); + continue; + } +#ifdef _WIN32 + if ((tid = CreateThread(NULL, 0, &handle_connection, (void *)conn_sock, 0, NULL)) == NULL) { + fprintf(stderr, "CreateThread() failed with error: %d\n", GetLastError()); +#else + if ((rc = pthread_create(&tid, NULL, &handle_connection, (void *)conn_sock)) != 0) { + fprintf(stderr, "pthread_create: %s\n", strerror(rc)); +#endif + usrsctp_close(*conn_sock); + continue; + } + } + if (verbose) { + /* const char *inet_ntop(int af, const void *src, char *dst, socklen_t size) + inet_ntoa(remote_addr.sin_addr) */ + char addrbuf[INET_ADDRSTRLEN]; + printf("Connection accepted from %s:%d\n", inet_ntop(AF_INET, &(remote_addr.sin_addr), addrbuf, INET_ADDRSTRLEN), ntohs(remote_addr.sin_port)); + } + } + /* usrsctp_close(psock); unreachable */ + } else { + memset(&encaps, 0, sizeof(struct sctp_udpencaps)); + encaps.sue_address.ss_family = AF_INET; + encaps.sue_port = htons(remote_udp_port); + if (usrsctp_setsockopt(psock, IPPROTO_SCTP, SCTP_REMOTE_UDP_ENCAPS_PORT, (const void*)&encaps, (socklen_t)sizeof(struct sctp_udpencaps)) < 0) { + perror("setsockopt"); + } + + remote_addr.sin_family = AF_INET; +#ifdef HAVE_SIN_LEN + remote_addr.sin_len = sizeof(struct sockaddr_in); +#endif + if (!inet_pton(AF_INET, argv[optind], &remote_addr.sin_addr.s_addr)){ + printf("error: invalid destination address\n"); + exit(1); + } + remote_addr.sin_port = htons(remote_port); + + /* TODO fragpoint stuff */ + if (nodelay == 1) { + optval = 1; + } else { + optval = 0; + } + usrsctp_setsockopt(psock, IPPROTO_SCTP, SCTP_NODELAY, &optval, sizeof(int)); + + if (fragpoint) { + av.assoc_id = 0; + av.assoc_value = fragpoint; + if (usrsctp_setsockopt(psock, IPPROTO_SCTP, SCTP_MAXSEG, &av, sizeof(struct sctp_assoc_value)) < 0) { + perror("setsockopt: SCTP_MAXSEG"); + } + } + + if (sndbufsize) { + if (usrsctp_setsockopt(psock, SOL_SOCKET, SO_SNDBUF, &sndbufsize, sizeof(int)) < 0) { + perror("setsockopt: sndbuf"); + } + } + if (verbose) { + intlen = sizeof(int); + if (usrsctp_getsockopt(psock, SOL_SOCKET, SO_SNDBUF, &mysndbufsize, (socklen_t *)&intlen) < 0) { + perror("setsockopt: SO_SNDBUF"); + } else { + fprintf(stdout,"Send buffer size: %d.\n", mysndbufsize); + } + } + + buffer = malloc(length); + memset(buffer, 'b', length); + + if (usrsctp_connect(psock, (struct sockaddr *) &remote_addr, sizeof(struct sockaddr_in)) == -1 ) { + perror("usrsctp_connect"); + exit(1); + } + + gettimeofday(&time_start, NULL); + + done = 0; + + if (runtime > 0) { +#ifndef _WIN32 + signal(SIGALRM, stop_sender); + alarm(runtime); +#else + fprintf(stderr, "You cannot set the runtime in Windows yet\n"); + exit(-1); +#endif + } + + if (use_cb) { + while (done < 2 && (cb_messages < (number_of_messages - 1))) { +#ifdef _WIN32 + Sleep(1000); +#else + sleep(1); +#endif + } + } else { + sndinfo.snd_sid = 0; + sndinfo.snd_flags = 0; + if (unordered != 0) { + sndinfo.snd_flags |= SCTP_UNORDERED; + } + sndinfo.snd_ppid = 0; + sndinfo.snd_context = 0; + sndinfo.snd_assoc_id = 0; + if (verbose) { + printf("Start sending "); + if (number_of_messages > 0) { + printf("%ld messages ", (long)number_of_messages); + } + if (runtime > 0) { + printf("for %u seconds ...", runtime); + } + printf("\n"); + fflush(stdout); + } + while (!done && ((number_of_messages == 0) || (messages < (number_of_messages - 1)))) { + if (very_verbose) { + printf("Sending message number %lu.\n", messages + 1); + } + + if (usrsctp_sendv(psock, buffer, length, (struct sockaddr *) &remote_addr, 1, + (void *)&sndinfo, (socklen_t)sizeof(struct sctp_sndinfo), SCTP_SENDV_SNDINFO, + 0) < 0) { + perror("usrsctp_sendv"); + exit(1); + } + messages++; + } + if (very_verbose) { + printf("Sending message number %lu.\n", messages + 1); + } + + sndinfo.snd_flags |= SCTP_EOF; + if (usrsctp_sendv(psock, buffer, length, (struct sockaddr *) &remote_addr, 1, + (void *)&sndinfo, (socklen_t)sizeof(struct sctp_sndinfo), SCTP_SENDV_SNDINFO, + 0) < 0) { + perror("usrsctp_sendv"); + exit(1); + } + messages++; + } + free (buffer); + + if (verbose) { + printf("Closing socket.\n"); + } + + usrsctp_close(psock); + gettimeofday(&time_now, NULL); + timersub(&time_now, &time_start, &time_diff); + seconds = time_diff.tv_sec + (double)time_diff.tv_usec/1000000; + printf("%s of %lu messages of length %d took %f seconds.\n", + "Sending", messages, length, seconds); + throughput = (double)messages * (double)length / seconds; + printf("Throughput was %f Byte/sec.\n", throughput); + } + + while (usrsctp_finish() != 0) { +#ifdef _WIN32 + Sleep(1000); +#else + sleep(1); +#endif + } + return 0; +} |