aboutsummaryrefslogtreecommitdiff
path: root/benchmarks
diff options
context:
space:
mode:
Diffstat (limited to 'benchmarks')
-rw-r--r--benchmarks/netio/Makefile6
-rw-r--r--benchmarks/netio/distinfo4
-rw-r--r--benchmarks/netio/files/patch-netio.c3408
3 files changed, 3131 insertions, 287 deletions
diff --git a/benchmarks/netio/Makefile b/benchmarks/netio/Makefile
index 82ed98d8109c..bacb7b860a80 100644
--- a/benchmarks/netio/Makefile
+++ b/benchmarks/netio/Makefile
@@ -2,11 +2,11 @@
# $FreeBSD$
PORTNAME= netio
-PORTVERSION= 1.26
+PORTVERSION= 1.32
CATEGORIES= benchmarks net ipv6
MASTER_SITES= ${MASTER_SITE_LOCAL}
MASTER_SITE_SUBDIR= arved
-DISTNAME= netio126
+DISTNAME= netio132
MAINTAINER= arved@FreeBSD.org
COMMENT= Network benchmark
@@ -15,7 +15,7 @@ WRKSRC= ${WRKDIR}
USES= gmake zip
PLIST_FILES= bin/netio
-CFLAGS+= -DUNIX
+CFLAGS+= -DUNIX -DSOCKLEN_T
LIBS+= -pthread
MAKE_ENV+= OUT=-o
diff --git a/benchmarks/netio/distinfo b/benchmarks/netio/distinfo
index f2ed91c7614d..14a95aeffdff 100644
--- a/benchmarks/netio/distinfo
+++ b/benchmarks/netio/distinfo
@@ -1,2 +1,2 @@
-SHA256 (netio126.zip) = 86c0bdee3224477b43c0cb6161ce1a20b2a2b6d59ef37f67864227096d9e8d5c
-SIZE (netio126.zip) = 140402
+SHA256 (netio132.zip) = c21550dfac6634558a7a79957eed28c46c62e0543017ef9d5c97c49f3cd41ddd
+SIZE (netio132.zip) = 162484
diff --git a/benchmarks/netio/files/patch-netio.c b/benchmarks/netio/files/patch-netio.c
index 121b1fedaa92..173b68446847 100644
--- a/benchmarks/netio/files/patch-netio.c
+++ b/benchmarks/netio/files/patch-netio.c
@@ -1,282 +1,3126 @@
---- netio.c.orig Tue Aug 30 16:47:18 2005
-+++ netio.c Sat Sep 2 13:46:50 2006
-@@ -782,8 +782,13 @@
- const int sobufsize = 131072;
- int nPort = DEFAULTPORT;
- int nAuxPort = DEFAULTPORT + 1;
-+#ifdef USE_IPV6
-+struct in6_addr addr_server;
-+struct in6_addr addr_local;
-+#else
- struct in_addr addr_server;
- struct in_addr addr_local;
-+#endif
-
- int udpsocket, udpd;
- unsigned long nUDPCount;
-@@ -794,7 +799,11 @@
- char *cBuffer;
- CONTROL ctl;
- long long nData;
-+#ifdef USE_IPV6
-+ struct sockaddr_in6 sa_server, sa_client;
-+#else
- struct sockaddr_in sa_server, sa_client;
-+#endif
- int server, client;
- size_t length;
- struct timeval tv;
-@@ -808,7 +817,11 @@
- return THREADRESULT;
- }
-
-+#ifdef USE_IPV6
-+ if ((server = socket(PF_INET6, SOCK_STREAM, 0)) < 0)
-+#else
- if ((server = socket(PF_INET, SOCK_STREAM, 0)) < 0)
-+#endif
- {
- psock_errno("socket()");
- free(cBuffer);
-@@ -818,10 +831,15 @@
- setsockopt(server, SOL_SOCKET, SO_RCVBUF, (char *) &sobufsize, sizeof(sobufsize));
- setsockopt(server, SOL_SOCKET, SO_SNDBUF, (char *) &sobufsize, sizeof(sobufsize));
-
-+#ifdef USE_IPV6
-+ sa_server.sin6_family = AF_INET6;
-+ sa_server.sin6_port = htons(nPort);
-+ sa_server.sin6_addr = addr_local;
-+#else
- sa_server.sin_family = AF_INET;
- sa_server.sin_port = htons(nPort);
- sa_server.sin_addr = addr_local;
--
-+#endif
- if (bind(server, (struct sockaddr *) &sa_server, sizeof(sa_server)) < 0)
- {
- psock_errno("bind()");
-@@ -958,7 +976,11 @@
- long nTime, nResult;
- long long nData;
- int i;
-+#ifdef USE_IPV6
-+ struct sockaddr_in6 sa_server;
-+#else
- struct sockaddr_in sa_server;
-+#endif
- int server;
- int rc;
- int nByte;
-@@ -969,7 +991,11 @@
- return;
- }
-
-+#ifdef USE_IPV6
-+ if ((server = socket(PF_INET6, SOCK_STREAM, 0)) < 0)
-+#else
- if ((server = socket(PF_INET, SOCK_STREAM, 0)) < 0)
-+#endif
- {
- psock_errno("socket()");
- free(cBuffer);
-@@ -979,9 +1005,16 @@
- setsockopt(server, SOL_SOCKET, SO_RCVBUF, (char *) &sobufsize, sizeof(sobufsize));
- setsockopt(server, SOL_SOCKET, SO_SNDBUF, (char *) &sobufsize, sizeof(sobufsize));
-
-+#ifdef USE_IPV6
-+ sa_server.sin6_family = AF_INET6;
-+ sa_server.sin6_port = htons(nPort);
-+ sa_server.sin6_addr = addr_server;
-+
-+#else
- sa_server.sin_family = AF_INET;
- sa_server.sin_port = htons(nPort);
- sa_server.sin_addr = addr_server;
-+#endif
-
- if (connect(server, (struct sockaddr *) &sa_server, sizeof(sa_server)) < 0)
- {
-@@ -1121,7 +1154,11 @@
- THREAD UDP_Receiver(void *arg)
- {
- char *cBuffer;
-+#ifdef USE_IPV6
-+ struct sockaddr_in6 sa_server, sa_client;
-+#else
- struct sockaddr_in sa_server, sa_client;
-+#endif
- int rc;
- size_t nBytes;
-
-@@ -1131,7 +1168,11 @@
- return THREADRESULT;
- }
-
-+#ifdef USE_IPV6
-+ if ((udpsocket = socket(PF_INET6, SOCK_DGRAM, 0)) < 0)
-+#else
- if ((udpsocket = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
-+#endif
- {
- psock_errno("socket(DGRAM)");
- free(cBuffer);
-@@ -1141,9 +1182,15 @@
- setsockopt(udpsocket, SOL_SOCKET, SO_RCVBUF, (char *) &sobufsize, sizeof(sobufsize));
- setsockopt(udpsocket, SOL_SOCKET, SO_SNDBUF, (char *) &sobufsize, sizeof(sobufsize));
-
-+#ifdef USE_IPV6
-+ sa_server.sin6_family = AF_INET6;
-+ sa_server.sin6_port = htons(nAuxPort);
-+ sa_server.sin6_addr = addr_local;
-+#else
- sa_server.sin_family = AF_INET;
- sa_server.sin_port = htons(nAuxPort);
- sa_server.sin_addr = addr_local;
-+#endif
-
- if (bind(udpsocket, (struct sockaddr *) &sa_server, sizeof(sa_server)) < 0)
- {
-@@ -1181,7 +1228,11 @@
- char *cBuffer;
- CONTROL ctl;
- long long nData;
-+#ifdef USE_IPV6
-+ struct sockaddr_in6 sa_server, sa_client;
-+#else
- struct sockaddr_in sa_server, sa_client;
-+#endif
- int server, client;
- struct timeval tv;
- fd_set fds;
-@@ -1194,7 +1245,11 @@
- return THREADRESULT;
- }
-
-+#ifdef USE_IPV6
-+ if ((server = socket(PF_INET6, SOCK_STREAM, 0)) < 0)
-+#else
- if ((server = socket(PF_INET, SOCK_STREAM, 0)) < 0)
-+#endif
- {
- psock_errno("socket(STREAM)");
- free(cBuffer);
-@@ -1204,9 +1259,15 @@
- setsockopt(server, SOL_SOCKET, SO_RCVBUF, (char *) &sobufsize, sizeof(sobufsize));
- setsockopt(server, SOL_SOCKET, SO_SNDBUF, (char *) &sobufsize, sizeof(sobufsize));
-
-+#ifdef USE_IPV6
-+ sa_server.sin6_family = AF_INET6;
-+ sa_server.sin6_port = htons(nAuxPort);
-+ sa_server.sin6_addr = addr_local;
-+#else
- sa_server.sin_family = AF_INET;
- sa_server.sin_port = htons(nAuxPort);
- sa_server.sin_addr = addr_local;
-+#endif
-
- if (bind(server, (struct sockaddr *) &sa_server, sizeof(sa_server)) < 0)
- {
-@@ -1252,7 +1313,11 @@
- printf("UDP connection established ... ");
- fflush(stdout);
-
-+#ifdef USE_IPV6
-+ sa_client.sin6_port = htons(nAuxPort);
-+#else
- sa_client.sin_port = htons(nAuxPort);
-+#endif
-
- for (;;)
- {
-@@ -1345,7 +1410,11 @@
- long nTime, nResult, nCount;
- long long nData;
- int i;
-+#ifdef USE_IPV6
-+ struct sockaddr_in6 sa_server;
-+#else
- struct sockaddr_in sa_server;
-+#endif
- int server;
- int rc, nByte;
-
-@@ -1355,7 +1424,11 @@
- return;
- }
-
-+#ifdef USE_IPV6
-+ if ((server = socket(PF_INET6, SOCK_STREAM, 0)) < 0)
-+#else
- if ((server = socket(PF_INET, SOCK_STREAM, 0)) < 0)
-+#endif
- {
- psock_errno("socket()");
- free(cBuffer);
-@@ -1365,9 +1438,15 @@
- setsockopt(server, SOL_SOCKET, SO_RCVBUF, (char *) &sobufsize, sizeof(sobufsize));
- setsockopt(server, SOL_SOCKET, SO_SNDBUF, (char *) &sobufsize, sizeof(sobufsize));
-
-+#ifdef USE_IPV6
-+ sa_server.sin6_family = AF_INET6;
-+ sa_server.sin6_port = htons(nAuxPort);
-+ sa_server.sin6_addr = addr_server;
-+#else
- sa_server.sin_family = AF_INET;
- sa_server.sin_port = htons(nAuxPort);
- sa_server.sin_addr = addr_server;
-+#endif
-
- if (connect(server, (struct sockaddr *) &sa_server, sizeof(sa_server)) < 0)
- {
-@@ -1669,17 +1748,29 @@
- return psock_errno("sock_init()"), 1;
-
- if (szLocal == 0)
-+#ifdef USE_IPV6
-+ addr_local = in6addr_any;
-+#else
- addr_local.s_addr = INADDR_ANY;
-+#endif
- else
- {
- if (isdigit(*szLocal))
-+#ifdef USE_IPV6
-+ inet_pton(AF_INET6, szLocal, &addr_local);
-+#else
- addr_local.s_addr = inet_addr(szLocal);
-+#endif
- else
- {
- if ((host = gethostbyname(szLocal)) == NULL)
- return psock_errno("gethostbyname()"), 1;
-
-+#ifdef USE_IPV6
-+ addr_local = * (struct in6_addr *) (host->h_addr);
-+#else
- addr_local = * (struct in_addr *) (host->h_addr);
-+#endif
- }
- }
-
-@@ -1689,13 +1780,21 @@
- usage();
-
- if (isdigit(*argv[optind]))
-+#ifdef USE_IPV6
-+ inet_pton(AF_INET6, argv[optind], &addr_server);
-+#else
- addr_server.s_addr = inet_addr(argv[optind]);
-+#endif
- else
- {
- if ((host = gethostbyname(argv[optind])) == NULL)
- return psock_errno("gethostbyname()"), 1;
-
-+#ifdef USE_IPV6
-+ addr_server = * (struct in6_addr *) (host->h_addr);
-+#else
- addr_server = * (struct in_addr *) (host->h_addr);
-+#endif
- }
- }
- }
+--- netio.c.orig 2015-03-22 18:03:25.739744000 +0100
++++ netio.c 2015-03-22 18:03:36.459543000 +0100
+@@ -1,1505 +1,1618 @@
+-/* netio.c
+- *
+- * Author: Kai-Uwe Rommel <rommel@ars.de>
+- * Created: Wed Sep 25 1996
+- */
+-
+-static char *rcsid =
+-"$Id: netio.c,v 1.32 2012/11/22 16:47:24 Rommel Exp Rommel $";
+-static char *rcsrev = "$Revision: 1.32 $";
+-
+-/*
+- * $Log: netio.c,v $
+- * Revision 1.32 2012/11/22 16:47:24 Rommel
+- * added binding to client sockets, too
+- *
+- * Revision 1.31 2010/10/14 16:44:38 Rommel
+- * fixed sleep calls
+- *
+- * Revision 1.30 2010/10/14 14:32:41 Rommel
+- * removed NetBIOS code
+- * added server side result printing
+- * fixed packet loss calculation (data type bug)
+- *
+- * Revision 1.29 2010/10/14 11:28:19 Rommel
+- * central printing routine
+- *
+- * Revision 1.28 2009/09/07 14:09:39 Rommel
+- * changed number output from bytes/KB to bytes/KB/MB
+- *
+- * Revision 1.27 2008/02/11 09:00:22 Rommel
+- * re-randomize buffer data for each loop run
+- *
+- * Revision 1.26 2005/08/30 14:45:51 Rommel
+- * minor fixes
+- *
+- * Revision 1.25 2004/05/26 07:23:04 Rommel
+- * some more corrections from Oliver Lau and Frank Schnell
+- *
+- * Revision 1.24 2004/05/17 16:01:03 Rommel
+- * fix for _send/_recv from Thomas Jahns
+- *
+- * Revision 1.23 2003/09/30 09:32:22 Rommel
+- * corrections from Matthias Scheler for error handling
+- * added socket buffer size setting
+- * added htonl/ntohl code (hint from Oliver Lau)
+- * restructured send/recv error/result checking
+- * more verbose server side messages
+- * other minor changes
+- *
+- * Revision 1.22 2003/09/22 14:58:33 Rommel
+- * added server side progress messages
+- *
+- * Revision 1.21 2003/08/28 12:44:11 Rommel
+- * fixed display of non-k-multiple packet sizes
+- *
+- * Revision 1.20 2003/08/27 11:05:48 Rommel
+- * allow block size specifikation in bytes or k bytes
+- *
+- * Revision 1.19 2003/08/17 16:53:45 Rommel
+- * added Unix/Linux pthreads support (required for UDP)
+- *
+- * Revision 1.18 2003/08/17 14:46:17 Rommel
+- * added UDP benchmark
+- * several minor changes (cleanup)
+- * configurable binding address
+- *
+- * Revision 1.17 2003/07/12 17:25:00 Rommel
+- * made block size selectable
+- *
+- * Revision 1.16 2003/02/10 09:06:59 Rommel
+- * fixed sender algorithm
+- *
+- * Revision 1.15 2001/09/17 13:56:40 Rommel
+- * changed to perform bidirectional benchmarks
+- *
+- * Revision 1.14 2001/04/19 12:20:55 Rommel
+- * added fixes for Unix systems
+- *
+- * Revision 1.13 2001/03/26 11:37:41 Rommel
+- * avoid integer overflows during throughput calculation
+- *
+- * Revision 1.12 2000/12/01 15:57:57 Rommel
+- * *** empty log message ***
+- *
+- * Revision 1.11 2000/03/01 12:21:47 rommel
+- * fixed _INTEGRAL_MAX_BITS problem for WIN32
+- *
+- * Revision 1.10 1999/10/28 17:36:57 rommel
+- * fixed OS/2 timer code
+- *
+- * Revision 1.9 1999/10/28 17:04:12 rommel
+- * fixed timer code
+- *
+- * Revision 1.8 1999/10/24 19:08:20 rommel
+- * imported DOS support from G. Vanem <giva@bgnett.no>
+- *
+- *
+- * Revision 1.8 1999/10/12 11:02:00 giva
+- * added Watt-32 with djgpp support. Added debug mode.
+- * G. Vanem <giva@bgnett.no>
+- *
+- * Revision 1.7 1999/06/13 18:42:25 rommel
+- * added Linux port with patches from Detlef Plotzky <plo@bvu.de>
+- *
+- * Revision 1.6 1998/10/12 11:14:58 rommel
+- * change to malloc'ed (and tiled) memory for transfer buffers
+- * (hint from Guenter Kukkukk <kukuk@berlin.snafu.de>)
+- * for increased performance
+- *
+- * Revision 1.5 1998/07/31 14:15:03 rommel
+- * added random buffer data
+- * fixed bugs
+- *
+- * Revision 1.4 1997/09/12 17:35:04 rommel
+- * termination bug fixes
+- *
+- * Revision 1.3 1997/09/12 12:00:15 rommel
+- * added Win32 port
+- * (tested for Windows NT only)
+- *
+- * Revision 1.2 1997/09/12 10:44:22 rommel
+- * added TCP/IP and a command line interface
+- *
+- * Revision 1.1 1996/09/25 08:42:29 rommel
+- * Initial revision
+- *
+- */
+-
+-#ifdef WIN32
+-#define _INTEGRAL_MAX_BITS 64
+-#endif
+-
+-#include <stdio.h>
+-#include <stdlib.h>
+-#include <string.h>
+-#include <ctype.h>
+-#include <signal.h>
+-#if defined(UNIX) || defined(DJGPP)
+-#include <sys/time.h>
+-#include <unistd.h>
+-#include <errno.h>
+-#else
+-#include <process.h>
+-#include "getopt.h"
+-#endif
+-
+-#define DEFAULTPORT 0x494F /* "IO" */
+-#define DEFAULTNBSRV "NETIOSRV"
+-#define DEFAULTNBCLT "NETIOCLT"
+-#define THREADSTACK 65536
+-
+-/* TCP/IP system specific details */
+-
+-#ifdef OS2
+-
+-#define BSD_SELECT
+-#include <types.h>
+-#include <netinet/in.h>
+-#include <sys/select.h>
+-#include <sys/socket.h>
+-#include <sys/time.h>
+-#include <netdb.h>
+-
+-#ifdef __IBMC__
+-#define newthread(entry) (_beginthread(entry, 0, THREADSTACK, 0) == -1)
+-#else
+-#define newthread(entry) (_beginthread(entry, THREADSTACK, 0) == -1)
+-#endif
+-#define THREAD void
+-#define THREADRESULT
+-
+-#endif /* OS2 */
+-
+-#ifdef WATT32
+-
+-#include <tcp.h> /* sock_init() etc. */
+-#include <netinet/in.h>
+-#include <sys/socket.h>
+-#include <netdb.h>
+-#define soclose close_s
+-#define select select_s
+-#define psock_errno perror
+-
+-#endif /* WATT32 */
+-
+-#ifdef WIN32
+-
+-#include <windows.h>
+-#include <winsock.h>
+-#define soclose closesocket
+-
+-int sock_init(void)
+-{
+- WSADATA wsaData;
+- return WSAStartup(MAKEWORD(1, 1), &wsaData);
+-}
+-
+-void psock_errno(char *text)
+-{
+- int rc = WSAGetLastError();
+- printf("%s: error code %d\n", text, rc);
+-}
+-
+-#ifdef __IBMC__
+-#define newthread(entry) (_beginthread(entry, 0, THREADSTACK, 0) == -1)
+-#else
+-#define newthread(entry) (_beginthread(entry, THREADSTACK, 0) == -1)
+-#endif
+-#define THREAD void
+-#define THREADRESULT
+-
+-#endif /* WIN32 */
+-
+-#ifdef UNIX
+-
+-#include <sys/types.h>
+-#include <sys/socket.h>
+-#include <sys/time.h>
+-#include <time.h>
+-#include <netinet/in.h>
+-#include <netdb.h>
+-
+-#define psock_errno(x) perror(x)
+-#define soclose(x) close(x)
+-
+-int sock_init(void)
+-{
+- return 0;
+-}
+-
+-#include <pthread.h>
+-pthread_t thread;
+-#define newthread(entry) (pthread_create(&thread, 0, entry, 0) != 0)
+-#define THREAD void*
+-#define THREADRESULT ((void*)0)
+-
+-#endif /* UNIX */
+-
+-#ifdef SOCKLEN_T
+-typedef socklen_t socklen_type;
+-#else
+-typedef size_t socklen_type;
+-#endif
+-
+-/* global data */
+-
+-#ifndef max
+-#define max(x, y) ((x) > (y) ? (x) : (y))
+-#endif
+-
+-#ifndef min
+-#define min(x, y) ((x) < (y) ? (x) : (y))
+-#endif
+-
+-#ifndef EINTR
+-#define EINTR 0
+-#endif
+-
+-int nSizes[] = {1024, 2048, 4096, 8192, 16384, 32768};
+-size_t nnSizes = sizeof(nSizes) / sizeof(int);
+-#define NMAXSIZE 65536
+-
+-int tSizes[] = {1024, 2048, 4096, 8192, 16384, 32767};
+-size_t ntSizes = sizeof(tSizes) / sizeof(int);
+-#define TMAXSIZE 65536
+-
+-#define INTERVAL 6
+-
+-/* you may need to adapt this to your platform/compiler */
+-typedef unsigned int uint32;
+-
+-typedef struct
+-{
+- uint32 cmd;
+- uint32 data;
+-}
+-CONTROL;
+-
+-#define CMD_QUIT 0
+-#define CMD_C2S 1
+-#define CMD_S2C 2
+-#define CMD_RES 3
+-
+-#define CTLSIZE sizeof(CONTROL)
+-
+-/* timer code */
+-
+-int bTimeOver;
+-
+-#ifdef OS2
+-
+-#define INCL_DOS
+-#define INCL_NOPM
+-#include <os2.h>
+-
+-typedef QWORD TIMER;
+-
+-void APIENTRY TimerThread(ULONG nSeconds)
+-{
+- HEV hSem;
+- HTIMER hTimer;
+-
+- DosCreateEventSem(0, &hSem, DC_SEM_SHARED, 0);
+-
+- DosAsyncTimer(nSeconds * 1000, (HSEM) hSem, &hTimer);
+- DosWaitEventSem(hSem, SEM_INDEFINITE_WAIT);
+- DosStopTimer(hTimer);
+-
+- DosCloseEventSem(hSem);
+-
+- bTimeOver = 1;
+-
+- DosExit(EXIT_THREAD, 0);
+-}
+-
+-int StartAlarm(long nSeconds)
+-{
+- TID ttid;
+-
+- bTimeOver = 0;
+-
+- if (DosCreateThread(&ttid, TimerThread, nSeconds, 0, THREADSTACK))
+- return printf("Cannot create timer thread.\n"), -1;
+-
+- return 0;
+-}
+-
+-int StartTimer(TIMER *nStart)
+-{
+- if (DosTmrQueryTime(nStart))
+- return printf("Timer error.\n"), -1;
+-
+- return 0;
+-}
+-
+-long StopTimer(TIMER *nStart, int nAccuracy)
+-{
+- TIMER nStop;
+- ULONG nFreq;
+-
+- if (DosTmrQueryTime(&nStop))
+- return printf("Timer error.\n"), -1;
+- if (DosTmrQueryFreq(&nFreq))
+- return printf("Timer error.\n"), -1;
+-
+- nFreq = (nFreq + nAccuracy / 2) / nAccuracy;
+-
+- return (* (long long *) &nStop - * (long long *) nStart) / nFreq;
+-}
+-
+-#endif /* OS2 */
+-
+-#ifdef WIN32
+-
+-typedef LARGE_INTEGER TIMER;
+-
+-#define sleep(x) Sleep((x) * 1000);
+-
+-DWORD CALLBACK TimerThread(void *pArg)
+-{
+- long nSeconds = * (long *) pArg;
+-
+- Sleep(nSeconds * 1000);
+- bTimeOver = 1;
+-
+- return 0;
+-}
+-
+-int StartAlarm(long nSeconds)
+-{
+- static long sSeconds;
+- DWORD ttid;
+-
+- sSeconds = nSeconds;
+-
+- bTimeOver = 0;
+-
+- if (CreateThread(0, THREADSTACK, TimerThread, (void *) &sSeconds, 0, &ttid) == NULL)
+- return printf("Cannot create timer thread.\n"), -1;
+-
+- return 0;
+-}
+-
+-int StartTimer(TIMER *nStart)
+-{
+- if (!QueryPerformanceCounter(nStart))
+- return printf("Timer error.\n"), -1;
+-
+- return 0;
+-}
+-
+-long StopTimer(TIMER *nStart, int nAccuracy)
+-{
+- TIMER nStop, nFreq;
+-
+- if (!QueryPerformanceCounter(&nStop))
+- return printf("Timer error.\n"), -1;
+- if (!QueryPerformanceFrequency(&nFreq))
+- return printf("Timer error.\n"), -1;
+-
+- nFreq.QuadPart = (nFreq.QuadPart + nAccuracy / 2) / nAccuracy;
+-
+- return (nStop.QuadPart - nStart->QuadPart) / nFreq.QuadPart;
+-}
+-
+-#endif /* WIN32 */
+-
+-#if defined(UNIX) || defined(DJGPP)
+-
+-typedef struct timeval TIMER;
+-
+-void on_alarm(int signum)
+-{
+- alarm(0);
+- bTimeOver = 1;
+-}
+-
+-int StartAlarm(long nSeconds)
+-{
+- bTimeOver = 0;
+- signal(SIGALRM, on_alarm);
+- alarm(nSeconds);
+- return 0;
+-}
+-
+-int StartTimer(TIMER *nStart)
+-{
+- struct timezone tz = {0, 0};
+-
+- gettimeofday(nStart, &tz);
+-
+- return 0;
+-}
+-
+-long StopTimer(TIMER *nStart, int nAccuracy)
+-{
+- struct timezone tz = {0, 0};
+- TIMER nStop;
+-
+- gettimeofday(&nStop, &tz);
+-
+- return (nStop.tv_sec - nStart->tv_sec) * nAccuracy
+- + (nStop.tv_usec - nStart->tv_usec) * nAccuracy / 1000000;
+-}
+-
+-#endif /* UNIX || DJGPP */
+-
+-/* initialize data to transfer */
+-
+-void GenerateRandomData(char *cBuffer, size_t nSize)
+-{
+- if (cBuffer != NULL)
+- {
+- size_t i;
+-
+- cBuffer[0] = 0;
+- srand(time(NULL));
+-
+- for (i = 1; i < nSize; i++)
+- cBuffer[i] = (char) rand();
+- }
+-}
+-
+-char *InitBuffer(size_t nSize)
+-{
+- char *cBuffer = malloc(nSize);
+- GenerateRandomData(cBuffer, nSize);
+- return cBuffer;
+-}
+-
+-char *PacketSize(int nSize)
+-{
+- static char szBuffer[64];
+-
+- if ((nSize % 1024) == 0 || (nSize % 1024) == 1023)
+- sprintf(szBuffer, "%2dk", (nSize + 512) / 1024);
+- else
+- sprintf(szBuffer, "%d", nSize);
+-
+- return szBuffer;
+-}
+-
+-/* print results */
+-
+-typedef enum {nf_auto, nf_bytes, nf_kbytes, nf_mbytes, nf_gbytes} numberformat;
+-numberformat nFormat = nf_auto;
+-
+-void print_result(long long nData, long nTime)
+-{
+- numberformat nThisFormat = nFormat;
+- double nResult;
+-
+- if (nThisFormat == nf_auto)
+- {
+- if (nData < 10 * 1024 * INTERVAL)
+- nThisFormat = nf_bytes;
+- else if (nData < 10 * 1024 * 1024 * INTERVAL)
+- nThisFormat = nf_kbytes;
+- else if (nData < (long long) 1024 * 1024 * 1024 * INTERVAL)
+- nThisFormat = nf_mbytes;
+- else
+- nThisFormat = nf_gbytes;
+- }
+-
+- switch(nThisFormat)
+- {
+- case nf_bytes:
+- nResult = (double) nData * 1024 / nTime;
+- printf(" %0.0f Byte/s", nResult);
+- break;
+-
+- case nf_kbytes:
+- nResult = (double) nData / nTime;
+- printf(" %0.2f KByte/s", nResult);
+- break;
+-
+- case nf_mbytes:
+- nResult = (double) nData / nTime / 1024;
+- printf(" %0.2f MByte/s", nResult);
+- break;
+-
+- case nf_gbytes:
+- nResult = (double) nData / nTime / 1024 / 1024;
+- printf(" %0.3f GByte/s", nResult);
+- break;
+- }
+-}
+-
+-/* TCP/IP code */
+-
+-int send_data(int socket, void *buffer, size_t size, int flags)
+-{
+- int rc = send(socket, buffer, size, flags);
+-
+- if (rc < 0)
+- {
+- psock_errno("send()");
+- return -1;
+- }
+-
+- if (rc != size)
+- return 1;
+-
+- return 0;
+-}
+-
+-int recv_data(int socket, void *buffer, size_t size, int flags)
+-{
+- size_t rc = recv(socket, buffer, size, flags);
+-
+- if (rc < 0)
+- {
+- psock_errno("recv()");
+- return -1;
+- }
+-
+- if (rc != size)
+- return 1;
+-
+- return 0;
+-}
+-
+-const int sobufsize = 131072;
+-int nPort = DEFAULTPORT;
+-int nAuxPort = DEFAULTPORT + 1;
+-struct in_addr addr_server;
+-struct in_addr addr_local;
+-
+-int udpsocket, udpd;
+-unsigned long nUDPCount;
+-long long nUDPData;
+-
+-THREAD TCP_Server(void *arg)
+-{
+- char *cBuffer;
+- CONTROL ctl;
+- TIMER nTimer;
+- long nTime;
+- long long nData;
+- struct sockaddr_in sa_server, sa_client;
+- int server, client;
+- socklen_type length;
+- struct timeval tv;
+- fd_set fds;
+- int rc;
+- int nByte;
+-
+- if ((cBuffer = InitBuffer(TMAXSIZE)) == NULL)
+- {
+- perror("malloc()");
+- return THREADRESULT;
+- }
+-
+- if ((server = socket(PF_INET, SOCK_STREAM, 0)) < 0)
+- {
+- psock_errno("socket()");
+- free(cBuffer);
+- return THREADRESULT;
+- }
+-
+- setsockopt(server, SOL_SOCKET, SO_RCVBUF, (char *) &sobufsize, sizeof(sobufsize));
+- setsockopt(server, SOL_SOCKET, SO_SNDBUF, (char *) &sobufsize, sizeof(sobufsize));
+-
+- sa_server.sin_family = AF_INET;
+- sa_server.sin_port = htons(nPort);
+- sa_server.sin_addr = addr_local;
+-
+- if (bind(server, (struct sockaddr *) &sa_server, sizeof(sa_server)) < 0)
+- {
+- psock_errno("bind()");
+- soclose(server);
+- free(cBuffer);
+- return THREADRESULT;
+- }
+-
+- if (listen(server, 2) != 0)
+- {
+- psock_errno("listen()");
+- soclose(server);
+- free(cBuffer);
+- return THREADRESULT;
+- }
+-
+- for (;;)
+- {
+- printf("TCP server listening.\n");
+-
+- FD_ZERO(&fds);
+- FD_SET(server, &fds);
+- tv.tv_sec = 3600;
+- tv.tv_usec = 0;
+-
+- if ((rc = select(FD_SETSIZE, &fds, 0, 0, &tv)) < 0)
+- {
+- psock_errno("select()");
+- break;
+- }
+-
+- if (rc == 0 || FD_ISSET(server, &fds) == 0)
+- continue;
+-
+- length = sizeof(sa_client);
+- if ((client = accept(server, (struct sockaddr *) &sa_client, &length)) == -1)
+- continue;
+-
+- setsockopt(client, SOL_SOCKET, SO_RCVBUF, (char *) &sobufsize, sizeof(sobufsize));
+- setsockopt(client, SOL_SOCKET, SO_SNDBUF, (char *) &sobufsize, sizeof(sobufsize));
+-
+- printf("TCP connection established ... ");
+- fflush(stdout);
+-
+- for (;;)
+- {
+- if (recv_data(client, (void *) &ctl, CTLSIZE, 0))
+- break;
+-
+- ctl.cmd = ntohl(ctl.cmd);
+- ctl.data = ntohl(ctl.data);
+-
+- if (ctl.cmd == CMD_C2S)
+- {
+- StartTimer(&nTimer);
+-
+- printf("\nReceiving from client, packet size %s ... ", PacketSize(ctl.data));
+- nData = 0;
+-
+- do
+- {
+- for (nByte = 0; nByte < ctl.data; )
+- {
+- rc = recv(client, cBuffer + nByte, ctl.data - nByte, 0);
+-
+- if (rc < 0 && errno != EINTR)
+- {
+- psock_errno("recv()");
+- break;
+- }
+-
+- if (rc > 0)
+- nByte += rc;
+- }
+-
+- nData += ctl.data;
+- }
+- while (cBuffer[0] == 0 && rc > 0);
+-
+- if ((nTime = StopTimer(&nTimer, 1024)) != -1)
+- print_result(nData, nTime);
+- }
+- else if (ctl.cmd == CMD_S2C)
+- {
+- if (StartAlarm(INTERVAL) == 0)
+- {
+- StartTimer(&nTimer);
+-
+- printf("\nSending to client, packet size %s ... ", PacketSize(ctl.data));
+- cBuffer[0] = 0;
+- nData = 0;
+-
+- while (!bTimeOver)
+- {
+- //GenerateRandomData(cBuffer, ctl.data);
+-
+- for (nByte = 0; nByte < ctl.data; )
+- {
+- rc = send(client, cBuffer + nByte, ctl.data - nByte, 0);
+-
+- if (rc < 0 && errno != EINTR)
+- {
+- psock_errno("send()");
+- break;
+- }
+-
+- if (rc > 0)
+- nByte += rc;
+- }
+-
+- nData += ctl.data;
+- }
+-
+- cBuffer[0] = 1;
+-
+- if (send_data(client, cBuffer, ctl.data, 0))
+- break;
+-
+- if ((nTime = StopTimer(&nTimer, 1024)) != -1)
+- print_result(nData, nTime);
+- }
+- }
+- else /* quit */
+- break;
+- }
+-
+- printf("\nDone.\n");
+-
+- soclose(client);
+-
+- if (rc < 0)
+- break;
+- }
+-
+- soclose(server);
+- free(cBuffer);
+-
+- return THREADRESULT;
+-}
+-
+-void TCP_Bench(void *arg)
+-{
+- char *cBuffer;
+- CONTROL ctl;
+- TIMER nTimer;
+- long nTime;
+- long long nData;
+- int i;
+- struct sockaddr_in sa_server, sa_client;
+- int server;
+- int rc;
+- int nByte;
+-
+- if ((cBuffer = InitBuffer(TMAXSIZE)) == NULL)
+- {
+- perror("malloc()");
+- return;
+- }
+-
+- if ((server = socket(PF_INET, SOCK_STREAM, 0)) < 0)
+- {
+- psock_errno("socket()");
+- free(cBuffer);
+- return;
+- }
+-
+- setsockopt(server, SOL_SOCKET, SO_RCVBUF, (char *) &sobufsize, sizeof(sobufsize));
+- setsockopt(server, SOL_SOCKET, SO_SNDBUF, (char *) &sobufsize, sizeof(sobufsize));
+-
+- sa_client.sin_family = AF_INET;
+- sa_client.sin_port = htons(0);
+- sa_client.sin_addr = addr_local;
+-
+- if (bind(server, (struct sockaddr *) &sa_client, sizeof(sa_client)) < 0)
+- {
+- psock_errno("bind()");
+- soclose(server);
+- free(cBuffer);
+- return THREADRESULT;
+- }
+-
+- sa_server.sin_family = AF_INET;
+- sa_server.sin_port = htons(nPort);
+- sa_server.sin_addr = addr_server;
+-
+- if (connect(server, (struct sockaddr *) &sa_server, sizeof(sa_server)) < 0)
+- {
+- psock_errno("connect()");
+- soclose(server);
+- free(cBuffer);
+- return;
+- }
+-
+- printf("\nTCP connection established.\n");
+-
+- for (i = 0; i < ntSizes; i++)
+- {
+- printf("Packet size %s bytes: ", PacketSize(tSizes[i]));
+- fflush(stdout);
+-
+- /* tell the server we will send it data now */
+-
+- ctl.cmd = htonl(CMD_C2S);
+- ctl.data = htonl(tSizes[i]);
+-
+- if (send_data(server, (void *) &ctl, CTLSIZE, 0))
+- break;
+-
+- /* 1 - Tx test */
+-
+- if (StartAlarm(INTERVAL) == 0)
+- {
+- StartTimer(&nTimer);
+- nData = 0;
+- cBuffer[0] = 0;
+-
+- while (!bTimeOver)
+- {
+- //GenerateRandomData(cBuffer, tSizes[i]);
+-
+- for (nByte = 0; nByte < tSizes[i]; )
+- {
+- rc = send(server, cBuffer + nByte, tSizes[i] - nByte, 0);
+-
+- if (rc < 0 && errno != EINTR)
+- {
+- psock_errno("send()");
+- break;
+- }
+-
+- if (rc > 0)
+- nByte += rc;
+- }
+-
+- nData += tSizes[i];
+- }
+-
+- if ((nTime = StopTimer(&nTimer, 1024)) == -1)
+- printf(" (failed)");
+- else
+- print_result(nData, nTime);
+-
+- printf(" Tx, ");
+- fflush(stdout);
+-
+- cBuffer[0] = 1;
+-
+- if (send_data(server, cBuffer, tSizes[i], 0))
+- break;
+- }
+-
+- /* tell the server we expect him to send us data now */
+-
+- ctl.cmd = htonl(CMD_S2C);
+- ctl.data = htonl(tSizes[i]);
+-
+- if (send_data(server, (void *) &ctl, CTLSIZE, 0))
+- break;
+-
+- /* 2 - Rx test */
+-
+- StartTimer(&nTimer);
+- nData = 0;
+-
+- do
+- {
+- for (nByte = 0; nByte < tSizes[i]; )
+- {
+- rc = recv(server, cBuffer + nByte, tSizes[i] - nByte, 0);
+-
+- if (rc < 0 && errno != EINTR)
+- {
+- psock_errno("recv()");
+- break;
+- }
+-
+- if (rc > 0)
+- nByte += rc;
+- }
+-
+- nData += tSizes[i];
+- }
+- while (cBuffer[0] == 0 && rc > 0);
+-
+- if ((nTime = StopTimer(&nTimer, 1024)) == -1)
+- printf(" (failed)");
+- else
+- print_result(nData, nTime);
+-
+- printf(" Rx.\n");
+- }
+-
+- ctl.cmd = htonl(CMD_QUIT);
+- ctl.data = 0;
+-
+- send_data(server, (void *) &ctl, CTLSIZE, 0);
+-
+- printf("Done.\n");
+-
+- soclose(server);
+- free(cBuffer);
+-}
+-
+-THREAD UDP_Receiver(void *arg)
+-{
+- char *cBuffer;
+- struct sockaddr_in sa_server, sa_client;
+- int rc;
+- socklen_type nBytes;
+-
+- if ((cBuffer = InitBuffer(TMAXSIZE)) == NULL)
+- {
+- perror("malloc()");
+- return THREADRESULT;
+- }
+-
+- if ((udpsocket = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
+- {
+- psock_errno("socket(DGRAM)");
+- free(cBuffer);
+- return THREADRESULT;
+- }
+-
+- setsockopt(udpsocket, SOL_SOCKET, SO_RCVBUF, (char *) &sobufsize, sizeof(sobufsize));
+- setsockopt(udpsocket, SOL_SOCKET, SO_SNDBUF, (char *) &sobufsize, sizeof(sobufsize));
+-
+- sa_server.sin_family = AF_INET;
+- sa_server.sin_port = htons(nAuxPort);
+- sa_server.sin_addr = addr_local;
+-
+- if (bind(udpsocket, (struct sockaddr *) &sa_server, sizeof(sa_server)) < 0)
+- {
+- psock_errno("bind(DGRAM)");
+- soclose(udpsocket);
+- free(cBuffer);
+- return THREADRESULT;
+- }
+-
+- udpd = 1;
+-
+- for (;;)
+- {
+- nBytes = sizeof(sa_client);
+- rc = recvfrom(udpsocket, cBuffer, TMAXSIZE, 0, (struct sockaddr *) &sa_client, &nBytes);
+-
+- if (rc < 0 && errno != EINTR)
+- psock_errno("recvfrom()");
+-
+- if (rc > 0)
+- {
+- nUDPCount++;
+- nUDPData += rc;
+- }
+- }
+-
+- soclose(udpsocket);
+- free(cBuffer);
+-
+- return THREADRESULT;
+-}
+-
+-THREAD UDP_Server(void *arg)
+-{
+- char *cBuffer;
+- CONTROL ctl;
+- TIMER nTimer;
+- long nTime;
+- long long nData;
+- struct sockaddr_in sa_server, sa_client;
+- int server, client;
+- struct timeval tv;
+- fd_set fds;
+- int rc, nByte;
+- socklen_type nLength;
+-
+- if ((cBuffer = InitBuffer(TMAXSIZE)) == NULL)
+- {
+- perror("malloc()");
+- return THREADRESULT;
+- }
+-
+- if ((server = socket(PF_INET, SOCK_STREAM, 0)) < 0)
+- {
+- psock_errno("socket(STREAM)");
+- free(cBuffer);
+- return THREADRESULT;
+- }
+-
+- setsockopt(server, SOL_SOCKET, SO_RCVBUF, (char *) &sobufsize, sizeof(sobufsize));
+- setsockopt(server, SOL_SOCKET, SO_SNDBUF, (char *) &sobufsize, sizeof(sobufsize));
+-
+- sa_server.sin_family = AF_INET;
+- sa_server.sin_port = htons(nAuxPort);
+- sa_server.sin_addr = addr_local;
+-
+- if (bind(server, (struct sockaddr *) &sa_server, sizeof(sa_server)) < 0)
+- {
+- psock_errno("bind(STREAM)");
+- soclose(server);
+- free(cBuffer);
+- return THREADRESULT;
+- }
+-
+- if (listen(server, 2) != 0)
+- {
+- psock_errno("listen()");
+- soclose(server);
+- free(cBuffer);
+- return THREADRESULT;
+- }
+-
+- for (;;)
+- {
+- printf("UDP server listening.\n");
+-
+- FD_ZERO(&fds);
+- FD_SET(server, &fds);
+- tv.tv_sec = 3600;
+- tv.tv_usec = 0;
+-
+- if ((rc = select(FD_SETSIZE, &fds, 0, 0, &tv)) < 0)
+- {
+- psock_errno("select()");
+- break;
+- }
+-
+- if (rc == 0 || FD_ISSET(server, &fds) == 0)
+- continue;
+-
+- nLength = sizeof(sa_client);
+- if ((client = accept(server, (struct sockaddr *) &sa_client, &nLength)) == -1)
+- continue;
+-
+- setsockopt(client, SOL_SOCKET, SO_RCVBUF, (char *) &sobufsize, sizeof(sobufsize));
+- setsockopt(client, SOL_SOCKET, SO_SNDBUF, (char *) &sobufsize, sizeof(sobufsize));
+-
+- printf("UDP connection established ... ");
+- fflush(stdout);
+-
+- sa_client.sin_port = htons(nAuxPort);
+-
+- for (;;)
+- {
+- if (recv_data(client, (void *) &ctl, CTLSIZE, 0))
+- break;
+-
+- ctl.cmd = ntohl(ctl.cmd);
+- ctl.data = ntohl(ctl.data);
+-
+- if (ctl.cmd == CMD_C2S)
+- {
+- StartTimer(&nTimer);
+- nUDPCount = 0;
+- nUDPData = 0;
+-
+- printf("\nReceiving from client, packet size %s ... ", PacketSize(ctl.data));
+-
+- ctl.cmd = htonl(ctl.cmd);
+- ctl.data = htonl(ctl.data);
+-
+- if (send_data(client, (void *) &ctl, CTLSIZE, 0))
+- break;
+- }
+- else if (ctl.cmd == CMD_RES)
+- {
+- ctl.cmd = htonl(ctl.cmd);
+- ctl.data = htonl(nUDPCount);
+-
+- if (send_data(client, (void *) &ctl, CTLSIZE, 0))
+- break;
+-
+- if ((nTime = StopTimer(&nTimer, 1024)) != -1)
+- print_result(nUDPData, nTime);
+- }
+- else if (ctl.cmd == CMD_S2C)
+- {
+- if (StartAlarm(INTERVAL) == 0)
+- {
+- StartTimer(&nTimer);
+- nData = 0;
+-
+- printf("\nSending to client, packet size %s ... ", PacketSize(ctl.data));
+- cBuffer[0] = 0;
+- nLength = ctl.data;
+-
+- ctl.cmd = htonl(CMD_RES);
+- ctl.data = 0;
+-
+- while (!bTimeOver)
+- {
+- //GenerateRandomData(cBuffer, nLength);
+-
+- for (nByte = 0; nByte < nLength; )
+- {
+- do
+- {
+- rc = sendto(udpsocket, cBuffer + nByte, nLength - nByte, 0,
+- (struct sockaddr *) &sa_client, sizeof(sa_client));
+- }
+-#ifdef ENOBUFS
+- while (rc < 0 && errno == ENOBUFS);
+-#else
+- while (0);
+-#endif
+-
+- if (rc < 0 && errno != EINTR)
+- {
+- psock_errno("sendto()");
+- break;
+- }
+-
+- if (rc > 0)
+- nByte += rc;
+- }
+-
+- ctl.data++;
+- nData += nLength;
+- }
+-
+- ctl.data = htonl(ctl.data);
+-
+- if (send_data(client, (void *) &ctl, CTLSIZE, 0))
+- break;
+-
+- if ((nTime = StopTimer(&nTimer, 1024)) != -1)
+- print_result(nData, nTime);
+- }
+- }
+- else /* quit */
+- break;
+- }
+-
+- printf("\nDone.\n");
+-
+- soclose(client);
+-
+- if (rc < 0)
+- break;
+- }
+-
+- soclose(server);
+- free(cBuffer);
+-
+- return THREADRESULT;
+-}
+-
+-void UDP_Bench(void *arg)
+-{
+- char *cBuffer;
+- CONTROL ctl;
+- TIMER nTimer;
+- long nTime, nCount;
+- long nResult;
+- long long nData;
+- int i;
+- struct sockaddr_in sa_server, sa_client;
+- int server;
+- int rc, nByte;
+-
+- if ((cBuffer = InitBuffer(TMAXSIZE)) == NULL)
+- {
+- perror("malloc()");
+- return;
+- }
+-
+- if ((server = socket(PF_INET, SOCK_STREAM, 0)) < 0)
+- {
+- psock_errno("socket()");
+- free(cBuffer);
+- return;
+- }
+-
+- setsockopt(server, SOL_SOCKET, SO_RCVBUF, (char *) &sobufsize, sizeof(sobufsize));
+- setsockopt(server, SOL_SOCKET, SO_SNDBUF, (char *) &sobufsize, sizeof(sobufsize));
+-
+- sa_client.sin_family = AF_INET;
+- sa_client.sin_port = htons(0);
+- sa_client.sin_addr = addr_local;
+-
+- if (bind(server, (struct sockaddr *) &sa_client, sizeof(sa_client)) < 0)
+- {
+- psock_errno("bind(STREAM)");
+- soclose(server);
+- free(cBuffer);
+- return THREADRESULT;
+- }
+-
+- sa_server.sin_family = AF_INET;
+- sa_server.sin_port = htons(nAuxPort);
+- sa_server.sin_addr = addr_server;
+-
+- if (connect(server, (struct sockaddr *) &sa_server, sizeof(sa_server)) < 0)
+- {
+- psock_errno("connect()");
+- soclose(server);
+- free(cBuffer);
+- return;
+- }
+-
+- printf("\nUDP connection established.\n");
+-
+- for (i = 0; i < ntSizes; i++)
+- {
+- printf("Packet size %s bytes: ", PacketSize(tSizes[i]));
+- fflush(stdout);
+-
+- /* tell the server we will send it data now */
+-
+- ctl.cmd = htonl(CMD_C2S);
+- ctl.data = htonl(tSizes[i]);
+-
+- if (send_data(server, (void *) &ctl, CTLSIZE, 0))
+- break;
+-
+- if (recv_data(server, (void *) &ctl, CTLSIZE, 0))
+- break;
+-
+- /* 1 - Tx test */
+-
+- if (StartAlarm(INTERVAL) == 0)
+- {
+- StartTimer(&nTimer);
+- nData = 0;
+- nCount = 0;
+- cBuffer[0] = 0;
+-
+- while (!bTimeOver)
+- {
+- //GenerateRandomData(cBuffer, tSizes[i]);
+-
+- for (nByte = 0; nByte < tSizes[i]; )
+- {
+- rc = sendto(udpsocket, cBuffer + nByte, tSizes[i] - nByte, 0,
+- (struct sockaddr *) &sa_server, sizeof(sa_server));
+-
+- if (rc < 0)
+- {
+- if (errno != EINTR)
+- {
+- psock_errno("sendto()");
+- break;
+- }
+- }
+- else
+- nByte += rc;
+- }
+-
+- nData += tSizes[i];
+- nCount++;
+- }
+-
+- if ((nTime = StopTimer(&nTimer, 1024)) == -1)
+- printf(" (failed)");
+-
+- ctl.cmd = htonl(CMD_RES);
+-
+- if (send_data(server, (void *) &ctl, CTLSIZE, 0))
+- break;
+-
+- if (recv_data(server, (void *) &ctl, CTLSIZE, 0))
+- break;
+-
+- ctl.data = ntohl(ctl.data);
+- nData = (long long) tSizes[i] * ctl.data;
+-
+- print_result(nData, nTime);
+- nResult = (nCount - ctl.data) * 100 / nCount;
+- printf(" (%ld%%) Tx, ", nResult);
+- fflush(stdout);
+- }
+-
+- /* tell the server we expect him to send us data now */
+-
+- ctl.cmd = htonl(CMD_S2C);
+- ctl.data = htonl(tSizes[i]);
+-
+- if (send_data(server, (void *) &ctl, CTLSIZE, 0))
+- break;
+-
+- /* 2 - Rx test */
+-
+- StartTimer(&nTimer);
+- nUDPCount = 0;
+- nUDPData = 0;
+-
+- if (recv_data(server, (void *) &ctl, CTLSIZE, 0))
+- break;
+-
+- if ((nTime = StopTimer(&nTimer, 1024)) == -1)
+- printf(" (failed)");
+-
+- ctl.data = ntohl(ctl.data);
+-
+- print_result(nUDPData, nTime);
+- nResult = (ctl.data - nUDPCount) * 100 / ctl.data;
+- printf(" (%ld%%) Rx.\n", nResult);
+- }
+-
+- ctl.cmd = htonl(CMD_QUIT);
+- ctl.data = 0;
+-
+- send_data(server, (void *) &ctl, CTLSIZE, 0);
+-
+- printf("Done.\n");
+-
+- soclose(server);
+- free(cBuffer);
+-}
+-
+-/* main / user interface */
+-
+-int bSRV, bTCP, bUDP;
+-
+-void handler(int sig)
+-{
+- _exit(0);
+-}
+-
+-void usage(void)
+-{
+- printf(
+- "\nUsage: netio [options] [<server>]\n"
+- "\n -s run server side of benchmark (otherwise run client)"
+- "\n -b <size>[k] use this block size (otherwise run with 1,2,4,8,16 and 32k)"
+- "\n -B -K -M -G force number formatting to Bytes, K, M or G Bytes\n"
+-
+- "\n -t use TCP protocol for benchmark"
+- "\n -u use UDP protocol for benchmark"
+- "\n -h <addr/name> bind TCP and UDP sockets to this local host address/name"
+- "\n defaults to all (server) or unspecified (client)"
+- "\n -p <port> bind TCP and UDP servers to this port (default is %d)\n"
+-
+- "\n <server> If the client side of the benchmark is running,"
+- "\n a server name or address is required.\n"
+-
+- "\nThe server side can run either TCP (-t) or UDP (-u) protocol or both"
+- "\n(default, if neither -t or -u is specified). The client runs one of"
+- "\nthese protocols only (must specify -t or -u).\n"
+- "\n", nPort);
+- exit(1);
+-}
+-
+-int main(int argc, char **argv)
+-{
+- char szVersion[32], *szName = 0, *szLocal = 0, *szEnd;
+- int option;
+- struct hostent *host;
+- long nSize;
+-
+- strcpy(szVersion, rcsrev + sizeof("$Revision: ") - 1);
+- *strchr(szVersion, ' ') = 0;
+-
+- printf("\nNETIO - Network Throughput Benchmark, Version %s"
+- "\n(C) 1997-2012 Kai Uwe Rommel\n", szVersion);
+-
+- if (argc == 1)
+- usage();
+-
+- /* check arguments */
+-
+- while ((option = getopt(argc, argv, "?stup:h:b:dBKMG")) != -1)
+- switch (option)
+- {
+- case 's':
+- bSRV = 1;
+- break;
+- case 't':
+- bTCP = 1;
+- break;
+- case 'u':
+- bUDP = 1;
+- break;
+- case 'p':
+- nPort = atoi(optarg);
+- nAuxPort = nPort + 1;
+- break;
+- case 'h':
+- szLocal = optarg;
+- break;
+- case 'b':
+- nSize = strtol(optarg, &szEnd, 10);
+- if (*szEnd == 'k')
+- nSize *= 1024;
+- nSizes[0] = min(max(nSize, 1), NMAXSIZE);
+- tSizes[0] = min(max(nSize, 1), TMAXSIZE);
+- nnSizes = ntSizes = 1;
+- break;
+-#ifdef WATT32
+- case 'd':
+- dbug_init();
+- break;
+-#endif
+- case 'B':
+- nFormat = nf_bytes;
+- break;
+- case 'K':
+- nFormat = nf_kbytes;
+- break;
+- case 'M':
+- nFormat = nf_mbytes;
+- break;
+- case 'G':
+- nFormat = nf_gbytes;
+- break;
+- default:
+- usage();
+- break;
+- }
+-
+- if (bSRV == 1 && bTCP == 0 && bUDP == 0)
+- bTCP = bUDP = 1;
+-
+- /* initialize TCP/IP */
+-
+- if (bTCP || bUDP)
+- {
+- if (sock_init())
+- return psock_errno("sock_init()"), 1;
+-
+- if (szLocal == 0)
+- addr_local.s_addr = INADDR_ANY;
+- else
+- {
+- if (isdigit(*szLocal))
+- addr_local.s_addr = inet_addr(szLocal);
+- else
+- {
+- if ((host = gethostbyname(szLocal)) == NULL)
+- return psock_errno("gethostbyname()"), 1;
+-
+- addr_local = * (struct in_addr *) (host->h_addr);
+- }
+- }
+-
+- if (!bSRV)
+- {
+- if (optind == argc)
+- usage();
+-
+- if (isdigit(*argv[optind]))
+- addr_server.s_addr = inet_addr(argv[optind]);
+- else
+- {
+- if ((host = gethostbyname(argv[optind])) == NULL)
+- return psock_errno("gethostbyname()"), 1;
+-
+- addr_server = * (struct in_addr *) (host->h_addr);
+- }
+- }
+- }
+-
+- /* do work */
+-
+- signal(SIGINT, handler);
+-
+- if (bSRV)
+- {
+- printf("\n");
+-
+- if (bTCP)
+- {
+- if (newthread(TCP_Server))
+- return printf("Cannot create additional thread.\n"), 2;
+- }
+- if (bUDP)
+- {
+- if (newthread(UDP_Receiver))
+- return printf("Cannot create additional thread.\n"), 2;
+- if (newthread(UDP_Server))
+- return printf("Cannot create additional thread.\n"), 2;
+- }
+-
+- for (;;) sleep(86400);
+- }
+- else
+- {
+- if (bTCP + bUDP > 1) /* exactly one only */
+- usage();
+-
+- if (bTCP)
+- TCP_Bench(0);
+- else if (bUDP)
+- {
+- if (newthread(UDP_Receiver))
+- return printf("Cannot create additional thread.\n"), 2;
+- while (udpd == 0) sleep(1);
+- UDP_Bench(0);
+- }
+- }
+-
+- /* terminate */
+-
+- printf("\n");
+-
+- return 0;
+-}
+-
+-/* end of netio.c */
++/* netio.c
++ *
++ * Author: Kai-Uwe Rommel <rommel@ars.de>
++ * Created: Wed Sep 25 1996
++ */
++
++static char *rcsid =
++"$Id: netio.c,v 1.32 2012/11/22 16:47:24 Rommel Exp Rommel $";
++static char *rcsrev = "$Revision: 1.32 $";
++
++/*
++ * $Log: netio.c,v $
++ * Revision 1.32 2012/11/22 16:47:24 Rommel
++ * added binding to client sockets, too
++ *
++ * Revision 1.31 2010/10/14 16:44:38 Rommel
++ * fixed sleep calls
++ *
++ * Revision 1.30 2010/10/14 14:32:41 Rommel
++ * removed NetBIOS code
++ * added server side result printing
++ * fixed packet loss calculation (data type bug)
++ *
++ * Revision 1.29 2010/10/14 11:28:19 Rommel
++ * central printing routine
++ *
++ * Revision 1.28 2009/09/07 14:09:39 Rommel
++ * changed number output from bytes/KB to bytes/KB/MB
++ *
++ * Revision 1.27 2008/02/11 09:00:22 Rommel
++ * re-randomize buffer data for each loop run
++ *
++ * Revision 1.26 2005/08/30 14:45:51 Rommel
++ * minor fixes
++ *
++ * Revision 1.25 2004/05/26 07:23:04 Rommel
++ * some more corrections from Oliver Lau and Frank Schnell
++ *
++ * Revision 1.24 2004/05/17 16:01:03 Rommel
++ * fix for _send/_recv from Thomas Jahns
++ *
++ * Revision 1.23 2003/09/30 09:32:22 Rommel
++ * corrections from Matthias Scheler for error handling
++ * added socket buffer size setting
++ * added htonl/ntohl code (hint from Oliver Lau)
++ * restructured send/recv error/result checking
++ * more verbose server side messages
++ * other minor changes
++ *
++ * Revision 1.22 2003/09/22 14:58:33 Rommel
++ * added server side progress messages
++ *
++ * Revision 1.21 2003/08/28 12:44:11 Rommel
++ * fixed display of non-k-multiple packet sizes
++ *
++ * Revision 1.20 2003/08/27 11:05:48 Rommel
++ * allow block size specifikation in bytes or k bytes
++ *
++ * Revision 1.19 2003/08/17 16:53:45 Rommel
++ * added Unix/Linux pthreads support (required for UDP)
++ *
++ * Revision 1.18 2003/08/17 14:46:17 Rommel
++ * added UDP benchmark
++ * several minor changes (cleanup)
++ * configurable binding address
++ *
++ * Revision 1.17 2003/07/12 17:25:00 Rommel
++ * made block size selectable
++ *
++ * Revision 1.16 2003/02/10 09:06:59 Rommel
++ * fixed sender algorithm
++ *
++ * Revision 1.15 2001/09/17 13:56:40 Rommel
++ * changed to perform bidirectional benchmarks
++ *
++ * Revision 1.14 2001/04/19 12:20:55 Rommel
++ * added fixes for Unix systems
++ *
++ * Revision 1.13 2001/03/26 11:37:41 Rommel
++ * avoid integer overflows during throughput calculation
++ *
++ * Revision 1.12 2000/12/01 15:57:57 Rommel
++ * *** empty log message ***
++ *
++ * Revision 1.11 2000/03/01 12:21:47 rommel
++ * fixed _INTEGRAL_MAX_BITS problem for WIN32
++ *
++ * Revision 1.10 1999/10/28 17:36:57 rommel
++ * fixed OS/2 timer code
++ *
++ * Revision 1.9 1999/10/28 17:04:12 rommel
++ * fixed timer code
++ *
++ * Revision 1.8 1999/10/24 19:08:20 rommel
++ * imported DOS support from G. Vanem <giva@bgnett.no>
++ *
++ *
++ * Revision 1.8 1999/10/12 11:02:00 giva
++ * added Watt-32 with djgpp support. Added debug mode.
++ * G. Vanem <giva@bgnett.no>
++ *
++ * Revision 1.7 1999/06/13 18:42:25 rommel
++ * added Linux port with patches from Detlef Plotzky <plo@bvu.de>
++ *
++ * Revision 1.6 1998/10/12 11:14:58 rommel
++ * change to malloc'ed (and tiled) memory for transfer buffers
++ * (hint from Guenter Kukkukk <kukuk@berlin.snafu.de>)
++ * for increased performance
++ *
++ * Revision 1.5 1998/07/31 14:15:03 rommel
++ * added random buffer data
++ * fixed bugs
++ *
++ * Revision 1.4 1997/09/12 17:35:04 rommel
++ * termination bug fixes
++ *
++ * Revision 1.3 1997/09/12 12:00:15 rommel
++ * added Win32 port
++ * (tested for Windows NT only)
++ *
++ * Revision 1.2 1997/09/12 10:44:22 rommel
++ * added TCP/IP and a command line interface
++ *
++ * Revision 1.1 1996/09/25 08:42:29 rommel
++ * Initial revision
++ *
++ */
++
++#ifdef WIN32
++#define _INTEGRAL_MAX_BITS 64
++#endif
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <ctype.h>
++#include <signal.h>
++#if defined(UNIX) || defined(DJGPP)
++#include <arpa/inet.h>
++#include <sys/time.h>
++#include <unistd.h>
++#include <errno.h>
++#else
++#include <process.h>
++#include "getopt.h"
++#endif
++
++#define DEFAULTPORT 0x494F /* "IO" */
++#define DEFAULTNBSRV "NETIOSRV"
++#define DEFAULTNBCLT "NETIOCLT"
++#define THREADSTACK 65536
++
++/* TCP/IP system specific details */
++
++#ifdef OS2
++
++#define BSD_SELECT
++#include <types.h>
++#include <netinet/in.h>
++#include <sys/select.h>
++#include <sys/socket.h>
++#include <sys/time.h>
++#include <netdb.h>
++
++#ifdef __IBMC__
++#define newthread(entry) (_beginthread(entry, 0, THREADSTACK, 0) == -1)
++#else
++#define newthread(entry) (_beginthread(entry, THREADSTACK, 0) == -1)
++#endif
++#define THREAD void
++#define THREADRESULT
++
++#endif /* OS2 */
++
++#ifdef WATT32
++
++#include <tcp.h> /* sock_init() etc. */
++#include <netinet/in.h>
++#include <sys/socket.h>
++#include <netdb.h>
++#define soclose close_s
++#define select select_s
++#define psock_errno perror
++
++#endif /* WATT32 */
++
++#ifdef WIN32
++
++#include <windows.h>
++#include <winsock.h>
++#define soclose closesocket
++
++int sock_init(void)
++{
++ WSADATA wsaData;
++ return WSAStartup(MAKEWORD(1, 1), &wsaData);
++}
++
++void psock_errno(char *text)
++{
++ int rc = WSAGetLastError();
++ printf("%s: error code %d\n", text, rc);
++}
++
++#ifdef __IBMC__
++#define newthread(entry) (_beginthread(entry, 0, THREADSTACK, 0) == -1)
++#else
++#define newthread(entry) (_beginthread(entry, THREADSTACK, 0) == -1)
++#endif
++#define THREAD void
++#define THREADRESULT
++
++#endif /* WIN32 */
++
++#ifdef UNIX
++
++#include <sys/types.h>
++#include <sys/socket.h>
++#include <sys/time.h>
++#include <time.h>
++#include <netinet/in.h>
++#include <netdb.h>
++
++#define psock_errno(x) perror(x)
++#define soclose(x) close(x)
++
++int sock_init(void)
++{
++ return 0;
++}
++
++#include <pthread.h>
++pthread_t thread;
++#define newthread(entry) (pthread_create(&thread, 0, entry, 0) != 0)
++#define THREAD void*
++#define THREADRESULT ((void*)0)
++
++#endif /* UNIX */
++
++#ifdef SOCKLEN_T
++typedef socklen_t socklen_type;
++#else
++typedef size_t socklen_type;
++#endif
++
++/* global data */
++
++#ifndef max
++#define max(x, y) ((x) > (y) ? (x) : (y))
++#endif
++
++#ifndef min
++#define min(x, y) ((x) < (y) ? (x) : (y))
++#endif
++
++#ifndef EINTR
++#define EINTR 0
++#endif
++
++int nSizes[] = {1024, 2048, 4096, 8192, 16384, 32768};
++size_t nnSizes = sizeof(nSizes) / sizeof(int);
++#define NMAXSIZE 65536
++
++int tSizes[] = {1024, 2048, 4096, 8192, 16384, 32767};
++size_t ntSizes = sizeof(tSizes) / sizeof(int);
++#define TMAXSIZE 65536
++
++#define INTERVAL 6
++
++/* you may need to adapt this to your platform/compiler */
++typedef unsigned int uint32;
++
++typedef struct
++{
++ uint32 cmd;
++ uint32 data;
++}
++CONTROL;
++
++#define CMD_QUIT 0
++#define CMD_C2S 1
++#define CMD_S2C 2
++#define CMD_RES 3
++
++#define CTLSIZE sizeof(CONTROL)
++
++/* timer code */
++
++int bTimeOver;
++
++#ifdef OS2
++
++#define INCL_DOS
++#define INCL_NOPM
++#include <os2.h>
++
++typedef QWORD TIMER;
++
++void APIENTRY TimerThread(ULONG nSeconds)
++{
++ HEV hSem;
++ HTIMER hTimer;
++
++ DosCreateEventSem(0, &hSem, DC_SEM_SHARED, 0);
++
++ DosAsyncTimer(nSeconds * 1000, (HSEM) hSem, &hTimer);
++ DosWaitEventSem(hSem, SEM_INDEFINITE_WAIT);
++ DosStopTimer(hTimer);
++
++ DosCloseEventSem(hSem);
++
++ bTimeOver = 1;
++
++ DosExit(EXIT_THREAD, 0);
++}
++
++int StartAlarm(long nSeconds)
++{
++ TID ttid;
++
++ bTimeOver = 0;
++
++ if (DosCreateThread(&ttid, TimerThread, nSeconds, 0, THREADSTACK))
++ return printf("Cannot create timer thread.\n"), -1;
++
++ return 0;
++}
++
++int StartTimer(TIMER *nStart)
++{
++ if (DosTmrQueryTime(nStart))
++ return printf("Timer error.\n"), -1;
++
++ return 0;
++}
++
++long StopTimer(TIMER *nStart, int nAccuracy)
++{
++ TIMER nStop;
++ ULONG nFreq;
++
++ if (DosTmrQueryTime(&nStop))
++ return printf("Timer error.\n"), -1;
++ if (DosTmrQueryFreq(&nFreq))
++ return printf("Timer error.\n"), -1;
++
++ nFreq = (nFreq + nAccuracy / 2) / nAccuracy;
++
++ return (* (long long *) &nStop - * (long long *) nStart) / nFreq;
++}
++
++#endif /* OS2 */
++
++#ifdef WIN32
++
++typedef LARGE_INTEGER TIMER;
++
++#define sleep(x) Sleep((x) * 1000);
++
++DWORD CALLBACK TimerThread(void *pArg)
++{
++ long nSeconds = * (long *) pArg;
++
++ Sleep(nSeconds * 1000);
++ bTimeOver = 1;
++
++ return 0;
++}
++
++int StartAlarm(long nSeconds)
++{
++ static long sSeconds;
++ DWORD ttid;
++
++ sSeconds = nSeconds;
++
++ bTimeOver = 0;
++
++ if (CreateThread(0, THREADSTACK, TimerThread, (void *) &sSeconds, 0, &ttid) == NULL)
++ return printf("Cannot create timer thread.\n"), -1;
++
++ return 0;
++}
++
++int StartTimer(TIMER *nStart)
++{
++ if (!QueryPerformanceCounter(nStart))
++ return printf("Timer error.\n"), -1;
++
++ return 0;
++}
++
++long StopTimer(TIMER *nStart, int nAccuracy)
++{
++ TIMER nStop, nFreq;
++
++ if (!QueryPerformanceCounter(&nStop))
++ return printf("Timer error.\n"), -1;
++ if (!QueryPerformanceFrequency(&nFreq))
++ return printf("Timer error.\n"), -1;
++
++ nFreq.QuadPart = (nFreq.QuadPart + nAccuracy / 2) / nAccuracy;
++
++ return (nStop.QuadPart - nStart->QuadPart) / nFreq.QuadPart;
++}
++
++#endif /* WIN32 */
++
++#if defined(UNIX) || defined(DJGPP)
++
++typedef struct timeval TIMER;
++
++void on_alarm(int signum)
++{
++ alarm(0);
++ bTimeOver = 1;
++}
++
++int StartAlarm(long nSeconds)
++{
++ bTimeOver = 0;
++ signal(SIGALRM, on_alarm);
++ alarm(nSeconds);
++ return 0;
++}
++
++int StartTimer(TIMER *nStart)
++{
++ struct timezone tz = {0, 0};
++
++ gettimeofday(nStart, &tz);
++
++ return 0;
++}
++
++long StopTimer(TIMER *nStart, int nAccuracy)
++{
++ struct timezone tz = {0, 0};
++ TIMER nStop;
++
++ gettimeofday(&nStop, &tz);
++
++ return (nStop.tv_sec - nStart->tv_sec) * nAccuracy
++ + (nStop.tv_usec - nStart->tv_usec) * nAccuracy / 1000000;
++}
++
++#endif /* UNIX || DJGPP */
++
++/* initialize data to transfer */
++
++void GenerateRandomData(char *cBuffer, size_t nSize)
++{
++ if (cBuffer != NULL)
++ {
++ size_t i;
++
++ cBuffer[0] = 0;
++ srand(time(NULL));
++
++ for (i = 1; i < nSize; i++)
++ cBuffer[i] = (char) rand();
++ }
++}
++
++char *InitBuffer(size_t nSize)
++{
++ char *cBuffer = malloc(nSize);
++ GenerateRandomData(cBuffer, nSize);
++ return cBuffer;
++}
++
++char *PacketSize(int nSize)
++{
++ static char szBuffer[64];
++
++ if ((nSize % 1024) == 0 || (nSize % 1024) == 1023)
++ sprintf(szBuffer, "%2dk", (nSize + 512) / 1024);
++ else
++ sprintf(szBuffer, "%d", nSize);
++
++ return szBuffer;
++}
++
++/* print results */
++
++typedef enum {nf_auto, nf_bytes, nf_kbytes, nf_mbytes, nf_gbytes} numberformat;
++numberformat nFormat = nf_auto;
++
++void print_result(long long nData, long nTime)
++{
++ numberformat nThisFormat = nFormat;
++ double nResult;
++
++ if (nThisFormat == nf_auto)
++ {
++ if (nData < 10 * 1024 * INTERVAL)
++ nThisFormat = nf_bytes;
++ else if (nData < 10 * 1024 * 1024 * INTERVAL)
++ nThisFormat = nf_kbytes;
++ else if (nData < (long long) 1024 * 1024 * 1024 * INTERVAL)
++ nThisFormat = nf_mbytes;
++ else
++ nThisFormat = nf_gbytes;
++ }
++
++ switch(nThisFormat)
++ {
++ case nf_bytes:
++ nResult = (double) nData * 1024 / nTime;
++ printf(" %0.0f Byte/s", nResult);
++ break;
++
++ case nf_kbytes:
++ nResult = (double) nData / nTime;
++ printf(" %0.2f KByte/s", nResult);
++ break;
++
++ case nf_mbytes:
++ nResult = (double) nData / nTime / 1024;
++ printf(" %0.2f MByte/s", nResult);
++ break;
++
++ case nf_gbytes:
++ nResult = (double) nData / nTime / 1024 / 1024;
++ printf(" %0.3f GByte/s", nResult);
++ break;
++ }
++}
++
++/* TCP/IP code */
++
++int send_data(int socket, void *buffer, size_t size, int flags)
++{
++ int rc = send(socket, buffer, size, flags);
++
++ if (rc < 0)
++ {
++ psock_errno("send()");
++ return -1;
++ }
++
++ if (rc != size)
++ return 1;
++
++ return 0;
++}
++
++int recv_data(int socket, void *buffer, size_t size, int flags)
++{
++ ssize_t rc = recv(socket, buffer, size, flags);
++
++ if (rc < 0)
++ {
++ psock_errno("recv()");
++ return -1;
++ }
++
++ if (rc != size)
++ return 1;
++
++ return 0;
++}
++
++const int sobufsize = 131072;
++int nPort = DEFAULTPORT;
++int nAuxPort = DEFAULTPORT + 1;
++#ifdef USE_IPV6
++struct in6_addr addr_server;
++struct in6_addr addr_local;
++#else
++struct in_addr addr_server;
++struct in_addr addr_local;
++#endif
++
++int udpsocket, udpd;
++unsigned long nUDPCount;
++long long nUDPData;
++
++THREAD TCP_Server(void *arg)
++{
++ char *cBuffer;
++ CONTROL ctl;
++ TIMER nTimer;
++ long nTime;
++ long long nData;
++#ifdef USE_IPV6
++ struct sockaddr_in6 sa_server, sa_client;
++#else
++ struct sockaddr_in sa_server, sa_client;
++#endif
++ int server, client;
++ socklen_type length;
++ struct timeval tv;
++ fd_set fds;
++ int rc;
++ int nByte;
++
++ if ((cBuffer = InitBuffer(TMAXSIZE)) == NULL)
++ {
++ perror("malloc()");
++ return THREADRESULT;
++ }
++
++#ifdef USE_IPV6
++ if ((server = socket(PF_INET6, SOCK_STREAM, 0)) < 0)
++#else
++ if ((server = socket(PF_INET, SOCK_STREAM, 0)) < 0)
++#endif
++ {
++ psock_errno("socket()");
++ free(cBuffer);
++ return THREADRESULT;
++ }
++
++ setsockopt(server, SOL_SOCKET, SO_RCVBUF, (char *) &sobufsize, sizeof(sobufsize));
++ setsockopt(server, SOL_SOCKET, SO_SNDBUF, (char *) &sobufsize, sizeof(sobufsize));
++
++#ifdef USE_IPV6
++ sa_server.sin6_family = AF_INET6;
++ sa_server.sin6_port = htons(nPort);
++ sa_server.sin6_addr = addr_local;
++#else
++ sa_server.sin_family = AF_INET;
++ sa_server.sin_port = htons(nPort);
++ sa_server.sin_addr = addr_local;
++#endif
++
++ if (bind(server, (struct sockaddr *) &sa_server, sizeof(sa_server)) < 0)
++ {
++ psock_errno("bind()");
++ soclose(server);
++ free(cBuffer);
++ return THREADRESULT;
++ }
++
++ if (listen(server, 2) != 0)
++ {
++ psock_errno("listen()");
++ soclose(server);
++ free(cBuffer);
++ return THREADRESULT;
++ }
++
++ for (;;)
++ {
++ printf("TCP server listening.\n");
++
++ FD_ZERO(&fds);
++ FD_SET(server, &fds);
++ tv.tv_sec = 3600;
++ tv.tv_usec = 0;
++
++ if ((rc = select(FD_SETSIZE, &fds, 0, 0, &tv)) < 0)
++ {
++ psock_errno("select()");
++ break;
++ }
++
++ if (rc == 0 || FD_ISSET(server, &fds) == 0)
++ continue;
++
++ length = sizeof(sa_client);
++ if ((client = accept(server, (struct sockaddr *) &sa_client, &length)) == -1)
++ continue;
++
++ setsockopt(client, SOL_SOCKET, SO_RCVBUF, (char *) &sobufsize, sizeof(sobufsize));
++ setsockopt(client, SOL_SOCKET, SO_SNDBUF, (char *) &sobufsize, sizeof(sobufsize));
++
++ printf("TCP connection established ... ");
++ fflush(stdout);
++
++ for (;;)
++ {
++ if (recv_data(client, (void *) &ctl, CTLSIZE, 0))
++ break;
++
++ ctl.cmd = ntohl(ctl.cmd);
++ ctl.data = ntohl(ctl.data);
++
++ if (ctl.cmd == CMD_C2S)
++ {
++ StartTimer(&nTimer);
++
++ printf("\nReceiving from client, packet size %s ... ", PacketSize(ctl.data));
++ nData = 0;
++
++ do
++ {
++ for (nByte = 0; nByte < ctl.data; )
++ {
++ rc = recv(client, cBuffer + nByte, ctl.data - nByte, 0);
++
++ if (rc < 0 && errno != EINTR)
++ {
++ psock_errno("recv()");
++ break;
++ }
++
++ if (rc > 0)
++ nByte += rc;
++ }
++
++ nData += ctl.data;
++ }
++ while (cBuffer[0] == 0 && rc > 0);
++
++ if ((nTime = StopTimer(&nTimer, 1024)) != -1)
++ print_result(nData, nTime);
++ }
++ else if (ctl.cmd == CMD_S2C)
++ {
++ if (StartAlarm(INTERVAL) == 0)
++ {
++ StartTimer(&nTimer);
++
++ printf("\nSending to client, packet size %s ... ", PacketSize(ctl.data));
++ cBuffer[0] = 0;
++ nData = 0;
++
++ while (!bTimeOver)
++ {
++ //GenerateRandomData(cBuffer, ctl.data);
++
++ for (nByte = 0; nByte < ctl.data; )
++ {
++ rc = send(client, cBuffer + nByte, ctl.data - nByte, 0);
++
++ if (rc < 0 && errno != EINTR)
++ {
++ psock_errno("send()");
++ break;
++ }
++
++ if (rc > 0)
++ nByte += rc;
++ }
++
++ nData += ctl.data;
++ }
++
++ cBuffer[0] = 1;
++
++ if (send_data(client, cBuffer, ctl.data, 0))
++ break;
++
++ if ((nTime = StopTimer(&nTimer, 1024)) != -1)
++ print_result(nData, nTime);
++ }
++ }
++ else /* quit */
++ break;
++ }
++
++ printf("\nDone.\n");
++
++ soclose(client);
++
++ if (rc < 0)
++ break;
++ }
++
++ soclose(server);
++ free(cBuffer);
++
++ return THREADRESULT;
++}
++
++void TCP_Bench(void *arg)
++{
++ char *cBuffer;
++ CONTROL ctl;
++ TIMER nTimer;
++ long nTime;
++ long long nData;
++ int i;
++#ifdef USE_IPV6
++ struct sockaddr_in6 sa_server, sa_client;
++#else
++ struct sockaddr_in sa_server, sa_client;
++#endif
++ int server;
++ int rc;
++ int nByte;
++
++ if ((cBuffer = InitBuffer(TMAXSIZE)) == NULL)
++ {
++ perror("malloc()");
++ return;
++ }
++
++#ifdef USE_IPV6
++ if ((server = socket(PF_INET6, SOCK_STREAM, 0)) < 0)
++#else
++ if ((server = socket(PF_INET, SOCK_STREAM, 0)) < 0)
++#endif
++ {
++ psock_errno("socket()");
++ free(cBuffer);
++ return;
++ }
++
++ setsockopt(server, SOL_SOCKET, SO_RCVBUF, (char *) &sobufsize, sizeof(sobufsize));
++ setsockopt(server, SOL_SOCKET, SO_SNDBUF, (char *) &sobufsize, sizeof(sobufsize));
++
++#ifdef USE_IPV6
++ sa_client.sin6_family = AF_INET6;
++ sa_client.sin6_port = htons(0);
++ sa_client.sin6_addr = addr_local;
++#else
++ sa_client.sin_family = AF_INET;
++ sa_client.sin_port = htons(0);
++ sa_client.sin_addr = addr_local;
++#endif
++
++ if (bind(server, (struct sockaddr *) &sa_client, sizeof(sa_client)) < 0)
++ {
++ psock_errno("bind()");
++ soclose(server);
++ free(cBuffer);
++ return;
++ }
++
++#ifdef USE_IPV6
++ sa_server.sin6_family = AF_INET6;
++ sa_server.sin6_port = htons(nPort);
++ sa_server.sin6_addr = addr_server;
++#else
++ sa_server.sin_family = AF_INET;
++ sa_server.sin_port = htons(nPort);
++ sa_server.sin_addr = addr_server;
++#endif
++
++ if (connect(server, (struct sockaddr *) &sa_server, sizeof(sa_server)) < 0)
++ {
++ psock_errno("connect()");
++ soclose(server);
++ free(cBuffer);
++ return;
++ }
++
++ printf("\nTCP connection established.\n");
++
++ for (i = 0; i < ntSizes; i++)
++ {
++ printf("Packet size %s bytes: ", PacketSize(tSizes[i]));
++ fflush(stdout);
++
++ /* tell the server we will send it data now */
++
++ ctl.cmd = htonl(CMD_C2S);
++ ctl.data = htonl(tSizes[i]);
++
++ if (send_data(server, (void *) &ctl, CTLSIZE, 0))
++ break;
++
++ /* 1 - Tx test */
++
++ if (StartAlarm(INTERVAL) == 0)
++ {
++ StartTimer(&nTimer);
++ nData = 0;
++ cBuffer[0] = 0;
++
++ while (!bTimeOver)
++ {
++ //GenerateRandomData(cBuffer, tSizes[i]);
++
++ for (nByte = 0; nByte < tSizes[i]; )
++ {
++ rc = send(server, cBuffer + nByte, tSizes[i] - nByte, 0);
++
++ if (rc < 0 && errno != EINTR)
++ {
++ psock_errno("send()");
++ break;
++ }
++
++ if (rc > 0)
++ nByte += rc;
++ }
++
++ nData += tSizes[i];
++ }
++
++ if ((nTime = StopTimer(&nTimer, 1024)) == -1)
++ printf(" (failed)");
++ else
++ print_result(nData, nTime);
++
++ printf(" Tx, ");
++ fflush(stdout);
++
++ cBuffer[0] = 1;
++
++ if (send_data(server, cBuffer, tSizes[i], 0))
++ break;
++ }
++
++ /* tell the server we expect him to send us data now */
++
++ ctl.cmd = htonl(CMD_S2C);
++ ctl.data = htonl(tSizes[i]);
++
++ if (send_data(server, (void *) &ctl, CTLSIZE, 0))
++ break;
++
++ /* 2 - Rx test */
++
++ StartTimer(&nTimer);
++ nData = 0;
++
++ do
++ {
++ for (nByte = 0; nByte < tSizes[i]; )
++ {
++ rc = recv(server, cBuffer + nByte, tSizes[i] - nByte, 0);
++
++ if (rc < 0 && errno != EINTR)
++ {
++ psock_errno("recv()");
++ break;
++ }
++
++ if (rc > 0)
++ nByte += rc;
++ }
++
++ nData += tSizes[i];
++ }
++ while (cBuffer[0] == 0 && rc > 0);
++
++ if ((nTime = StopTimer(&nTimer, 1024)) == -1)
++ printf(" (failed)");
++ else
++ print_result(nData, nTime);
++
++ printf(" Rx.\n");
++ }
++
++ ctl.cmd = htonl(CMD_QUIT);
++ ctl.data = 0;
++
++ send_data(server, (void *) &ctl, CTLSIZE, 0);
++
++ printf("Done.\n");
++
++ soclose(server);
++ free(cBuffer);
++}
++
++THREAD UDP_Receiver(void *arg)
++{
++ char *cBuffer;
++#ifdef USE_IPV6
++ struct sockaddr_in6 sa_server, sa_client;
++#else
++ struct sockaddr_in sa_server, sa_client;
++#endif
++ int rc;
++ socklen_type nBytes;
++
++ if ((cBuffer = InitBuffer(TMAXSIZE)) == NULL)
++ {
++ perror("malloc()");
++ return THREADRESULT;
++ }
++
++#ifdef USE_IPV6
++ if ((udpsocket = socket(PF_INET6, SOCK_DGRAM, 0)) < 0)
++#else
++ if ((udpsocket = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
++#endif
++ {
++ psock_errno("socket(DGRAM)");
++ free(cBuffer);
++ return THREADRESULT;
++ }
++
++ setsockopt(udpsocket, SOL_SOCKET, SO_RCVBUF, (char *) &sobufsize, sizeof(sobufsize));
++ setsockopt(udpsocket, SOL_SOCKET, SO_SNDBUF, (char *) &sobufsize, sizeof(sobufsize));
++
++#ifdef USE_IPV6
++ sa_server.sin6_family = AF_INET6;
++ sa_server.sin6_port = htons(nAuxPort);
++ sa_server.sin6_addr = addr_local;
++#else
++ sa_server.sin_family = AF_INET;
++ sa_server.sin_port = htons(nAuxPort);
++ sa_server.sin_addr = addr_local;
++#endif
++
++ if (bind(udpsocket, (struct sockaddr *) &sa_server, sizeof(sa_server)) < 0)
++ {
++ psock_errno("bind(DGRAM)");
++ soclose(udpsocket);
++ free(cBuffer);
++ return THREADRESULT;
++ }
++
++ udpd = 1;
++
++ for (;;)
++ {
++ nBytes = sizeof(sa_client);
++ rc = recvfrom(udpsocket, cBuffer, TMAXSIZE, 0, (struct sockaddr *) &sa_client, &nBytes);
++
++ if (rc < 0 && errno != EINTR)
++ psock_errno("recvfrom()");
++
++ if (rc > 0)
++ {
++ nUDPCount++;
++ nUDPData += rc;
++ }
++ }
++
++ soclose(udpsocket);
++ free(cBuffer);
++
++ return THREADRESULT;
++}
++
++THREAD UDP_Server(void *arg)
++{
++ char *cBuffer;
++ CONTROL ctl;
++ TIMER nTimer;
++ long nTime;
++ long long nData;
++#ifdef USE_IPV6
++ struct sockaddr_in6 sa_server, sa_client;
++#else
++ struct sockaddr_in sa_server, sa_client;
++#endif
++ int server, client;
++ struct timeval tv;
++ fd_set fds;
++ int rc, nByte;
++ socklen_type nLength;
++
++ if ((cBuffer = InitBuffer(TMAXSIZE)) == NULL)
++ {
++ perror("malloc()");
++ return THREADRESULT;
++ }
++
++#ifdef USE_IPV6
++ if ((server = socket(PF_INET6, SOCK_STREAM, 0)) < 0)
++#else
++ if ((server = socket(PF_INET, SOCK_STREAM, 0)) < 0)
++#endif
++ {
++ psock_errno("socket(STREAM)");
++ free(cBuffer);
++ return THREADRESULT;
++ }
++
++ setsockopt(server, SOL_SOCKET, SO_RCVBUF, (char *) &sobufsize, sizeof(sobufsize));
++ setsockopt(server, SOL_SOCKET, SO_SNDBUF, (char *) &sobufsize, sizeof(sobufsize));
++
++#ifdef USE_IPV6
++ sa_server.sin6_family = AF_INET6;
++ sa_server.sin6_port = htons(nAuxPort);
++ sa_server.sin6_addr = addr_local;
++#else
++ sa_server.sin_family = AF_INET;
++ sa_server.sin_port = htons(nAuxPort);
++ sa_server.sin_addr = addr_local;
++#endif
++
++ if (bind(server, (struct sockaddr *) &sa_server, sizeof(sa_server)) < 0)
++ {
++ psock_errno("bind(STREAM)");
++ soclose(server);
++ free(cBuffer);
++ return THREADRESULT;
++ }
++
++ if (listen(server, 2) != 0)
++ {
++ psock_errno("listen()");
++ soclose(server);
++ free(cBuffer);
++ return THREADRESULT;
++ }
++
++ for (;;)
++ {
++ printf("UDP server listening.\n");
++
++ FD_ZERO(&fds);
++ FD_SET(server, &fds);
++ tv.tv_sec = 3600;
++ tv.tv_usec = 0;
++
++ if ((rc = select(FD_SETSIZE, &fds, 0, 0, &tv)) < 0)
++ {
++ psock_errno("select()");
++ break;
++ }
++
++ if (rc == 0 || FD_ISSET(server, &fds) == 0)
++ continue;
++
++ nLength = sizeof(sa_client);
++ if ((client = accept(server, (struct sockaddr *) &sa_client, &nLength)) == -1)
++ continue;
++
++ setsockopt(client, SOL_SOCKET, SO_RCVBUF, (char *) &sobufsize, sizeof(sobufsize));
++ setsockopt(client, SOL_SOCKET, SO_SNDBUF, (char *) &sobufsize, sizeof(sobufsize));
++
++ printf("UDP connection established ... ");
++ fflush(stdout);
++
++#ifdef USE_IPV6
++ sa_client.sin6_port = htons(nAuxPort);
++#else
++ sa_client.sin_port = htons(nAuxPort);
++#endif
++
++ for (;;)
++ {
++ if (recv_data(client, (void *) &ctl, CTLSIZE, 0))
++ break;
++
++ ctl.cmd = ntohl(ctl.cmd);
++ ctl.data = ntohl(ctl.data);
++
++ if (ctl.cmd == CMD_C2S)
++ {
++ StartTimer(&nTimer);
++ nUDPCount = 0;
++ nUDPData = 0;
++
++ printf("\nReceiving from client, packet size %s ... ", PacketSize(ctl.data));
++
++ ctl.cmd = htonl(ctl.cmd);
++ ctl.data = htonl(ctl.data);
++
++ if (send_data(client, (void *) &ctl, CTLSIZE, 0))
++ break;
++ }
++ else if (ctl.cmd == CMD_RES)
++ {
++ ctl.cmd = htonl(ctl.cmd);
++ ctl.data = htonl(nUDPCount);
++
++ if (send_data(client, (void *) &ctl, CTLSIZE, 0))
++ break;
++
++ if ((nTime = StopTimer(&nTimer, 1024)) != -1)
++ print_result(nUDPData, nTime);
++ }
++ else if (ctl.cmd == CMD_S2C)
++ {
++ if (StartAlarm(INTERVAL) == 0)
++ {
++ StartTimer(&nTimer);
++ nData = 0;
++
++ printf("\nSending to client, packet size %s ... ", PacketSize(ctl.data));
++ cBuffer[0] = 0;
++ nLength = ctl.data;
++
++ ctl.cmd = htonl(CMD_RES);
++ ctl.data = 0;
++
++ while (!bTimeOver)
++ {
++ //GenerateRandomData(cBuffer, nLength);
++
++ for (nByte = 0; nByte < nLength; )
++ {
++ do
++ {
++ rc = sendto(udpsocket, cBuffer + nByte, nLength - nByte, 0,
++ (struct sockaddr *) &sa_client, sizeof(sa_client));
++ }
++#ifdef ENOBUFS
++ while (rc < 0 && errno == ENOBUFS);
++#else
++ while (0);
++#endif
++
++ if (rc < 0 && errno != EINTR)
++ {
++ psock_errno("sendto()");
++ break;
++ }
++
++ if (rc > 0)
++ nByte += rc;
++ }
++
++ ctl.data++;
++ nData += nLength;
++ }
++
++ ctl.data = htonl(ctl.data);
++
++ if (send_data(client, (void *) &ctl, CTLSIZE, 0))
++ break;
++
++ if ((nTime = StopTimer(&nTimer, 1024)) != -1)
++ print_result(nData, nTime);
++ }
++ }
++ else /* quit */
++ break;
++ }
++
++ printf("\nDone.\n");
++
++ soclose(client);
++
++ if (rc < 0)
++ break;
++ }
++
++ soclose(server);
++ free(cBuffer);
++
++ return THREADRESULT;
++}
++
++void UDP_Bench(void *arg)
++{
++ char *cBuffer;
++ CONTROL ctl;
++ TIMER nTimer;
++ long nTime, nCount;
++ long nResult;
++ long long nData;
++ int i;
++#ifdef USE_IPV6
++ struct sockaddr_in6 sa_server, sa_client;
++#else
++ struct sockaddr_in sa_server, sa_client;
++#endif
++ int server;
++ int rc, nByte;
++
++ if ((cBuffer = InitBuffer(TMAXSIZE)) == NULL)
++ {
++ perror("malloc()");
++ return;
++ }
++
++#ifdef USE_IPV6
++ if ((server = socket(PF_INET6, SOCK_STREAM, 0)) < 0)
++#else
++ if ((server = socket(PF_INET, SOCK_STREAM, 0)) < 0)
++#endif
++ {
++ psock_errno("socket()");
++ free(cBuffer);
++ return;
++ }
++
++ setsockopt(server, SOL_SOCKET, SO_RCVBUF, (char *) &sobufsize, sizeof(sobufsize));
++ setsockopt(server, SOL_SOCKET, SO_SNDBUF, (char *) &sobufsize, sizeof(sobufsize));
++
++#ifdef USE_IPV6
++ sa_client.sin6_family = AF_INET6;
++ sa_client.sin6_port = htons(0);
++ sa_client.sin6_addr = addr_local;
++#else
++ sa_client.sin_family = AF_INET;
++ sa_client.sin_port = htons(0);
++ sa_client.sin_addr = addr_local;
++#endif
++
++ if (bind(server, (struct sockaddr *) &sa_client, sizeof(sa_client)) < 0)
++ {
++ psock_errno("bind(STREAM)");
++ soclose(server);
++ free(cBuffer);
++ return;
++ }
++
++#ifdef USE_IPV6
++ sa_server.sin6_family = AF_INET6;
++ sa_server.sin6_port = htons(nAuxPort);
++ sa_server.sin6_addr = addr_server;
++#else
++ sa_server.sin_family = AF_INET;
++ sa_server.sin_port = htons(nAuxPort);
++ sa_server.sin_addr = addr_server;
++#endif
++
++ if (connect(server, (struct sockaddr *) &sa_server, sizeof(sa_server)) < 0)
++ {
++ psock_errno("connect()");
++ soclose(server);
++ free(cBuffer);
++ return;
++ }
++
++ printf("\nUDP connection established.\n");
++
++ for (i = 0; i < ntSizes; i++)
++ {
++ printf("Packet size %s bytes: ", PacketSize(tSizes[i]));
++ fflush(stdout);
++
++ /* tell the server we will send it data now */
++
++ ctl.cmd = htonl(CMD_C2S);
++ ctl.data = htonl(tSizes[i]);
++
++ if (send_data(server, (void *) &ctl, CTLSIZE, 0))
++ break;
++
++ if (recv_data(server, (void *) &ctl, CTLSIZE, 0))
++ break;
++
++ /* 1 - Tx test */
++
++ if (StartAlarm(INTERVAL) == 0)
++ {
++ StartTimer(&nTimer);
++ nData = 0;
++ nCount = 0;
++ cBuffer[0] = 0;
++
++ while (!bTimeOver)
++ {
++ //GenerateRandomData(cBuffer, tSizes[i]);
++
++ for (nByte = 0; nByte < tSizes[i]; )
++ {
++ rc = sendto(udpsocket, cBuffer + nByte, tSizes[i] - nByte, 0,
++ (struct sockaddr *) &sa_server, sizeof(sa_server));
++
++ if (rc < 0)
++ {
++ if (errno != EINTR)
++ {
++ psock_errno("sendto()");
++ break;
++ }
++ }
++ else
++ nByte += rc;
++ }
++
++ nData += tSizes[i];
++ nCount++;
++ }
++
++ if ((nTime = StopTimer(&nTimer, 1024)) == -1)
++ printf(" (failed)");
++
++ ctl.cmd = htonl(CMD_RES);
++
++ if (send_data(server, (void *) &ctl, CTLSIZE, 0))
++ break;
++
++ if (recv_data(server, (void *) &ctl, CTLSIZE, 0))
++ break;
++
++ ctl.data = ntohl(ctl.data);
++ nData = (long long) tSizes[i] * ctl.data;
++
++ print_result(nData, nTime);
++ nResult = (nCount - ctl.data) * 100 / nCount;
++ printf(" (%ld%%) Tx, ", nResult);
++ fflush(stdout);
++ }
++
++ /* tell the server we expect him to send us data now */
++
++ ctl.cmd = htonl(CMD_S2C);
++ ctl.data = htonl(tSizes[i]);
++
++ if (send_data(server, (void *) &ctl, CTLSIZE, 0))
++ break;
++
++ /* 2 - Rx test */
++
++ StartTimer(&nTimer);
++ nUDPCount = 0;
++ nUDPData = 0;
++
++ if (recv_data(server, (void *) &ctl, CTLSIZE, 0))
++ break;
++
++ if ((nTime = StopTimer(&nTimer, 1024)) == -1)
++ printf(" (failed)");
++
++ ctl.data = ntohl(ctl.data);
++
++ print_result(nUDPData, nTime);
++ nResult = (ctl.data - nUDPCount) * 100 / ctl.data;
++ printf(" (%ld%%) Rx.\n", nResult);
++ }
++
++ ctl.cmd = htonl(CMD_QUIT);
++ ctl.data = 0;
++
++ send_data(server, (void *) &ctl, CTLSIZE, 0);
++
++ printf("Done.\n");
++
++ soclose(server);
++ free(cBuffer);
++}
++
++/* main / user interface */
++
++int bSRV, bTCP, bUDP;
++
++void handler(int sig)
++{
++ _exit(0);
++}
++
++void usage(void)
++{
++ printf(
++ "\nUsage: netio [options] [<server>]\n"
++ "\n -s run server side of benchmark (otherwise run client)"
++ "\n -b <size>[k] use this block size (otherwise run with 1,2,4,8,16 and 32k)"
++ "\n -B -K -M -G force number formatting to Bytes, K, M or G Bytes\n"
++
++ "\n -t use TCP protocol for benchmark"
++ "\n -u use UDP protocol for benchmark"
++ "\n -h <addr/name> bind TCP and UDP sockets to this local host address/name"
++ "\n defaults to all (server) or unspecified (client)"
++ "\n -p <port> bind TCP and UDP servers to this port (default is %d)\n"
++
++ "\n <server> If the client side of the benchmark is running,"
++ "\n a server name or address is required.\n"
++
++ "\nThe server side can run either TCP (-t) or UDP (-u) protocol or both"
++ "\n(default, if neither -t or -u is specified). The client runs one of"
++ "\nthese protocols only (must specify -t or -u).\n"
++ "\n", nPort);
++ exit(1);
++}
++
++int main(int argc, char **argv)
++{
++ char szVersion[32], *szName = 0, *szLocal = 0, *szEnd;
++ int option;
++ struct hostent *host;
++ long nSize;
++
++ strcpy(szVersion, rcsrev + sizeof("$Revision: ") - 1);
++ *strchr(szVersion, ' ') = 0;
++
++ printf("\nNETIO - Network Throughput Benchmark, Version %s"
++ "\n(C) 1997-2012 Kai Uwe Rommel\n", szVersion);
++
++ if (argc == 1)
++ usage();
++
++ /* check arguments */
++
++ while ((option = getopt(argc, argv, "?stup:h:b:dBKMG")) != -1)
++ switch (option)
++ {
++ case 's':
++ bSRV = 1;
++ break;
++ case 't':
++ bTCP = 1;
++ break;
++ case 'u':
++ bUDP = 1;
++ break;
++ case 'p':
++ nPort = atoi(optarg);
++ nAuxPort = nPort + 1;
++ break;
++ case 'h':
++ szLocal = optarg;
++ break;
++ case 'b':
++ nSize = strtol(optarg, &szEnd, 10);
++ if (*szEnd == 'k')
++ nSize *= 1024;
++ nSizes[0] = min(max(nSize, 1), NMAXSIZE);
++ tSizes[0] = min(max(nSize, 1), TMAXSIZE);
++ nnSizes = ntSizes = 1;
++ break;
++#ifdef WATT32
++ case 'd':
++ dbug_init();
++ break;
++#endif
++ case 'B':
++ nFormat = nf_bytes;
++ break;
++ case 'K':
++ nFormat = nf_kbytes;
++ break;
++ case 'M':
++ nFormat = nf_mbytes;
++ break;
++ case 'G':
++ nFormat = nf_gbytes;
++ break;
++ default:
++ usage();
++ break;
++ }
++
++ if (bSRV == 1 && bTCP == 0 && bUDP == 0)
++ bTCP = bUDP = 1;
++
++ /* initialize TCP/IP */
++
++ if (bTCP || bUDP)
++ {
++ if (sock_init())
++ return psock_errno("sock_init()"), 1;
++
++ if (szLocal == 0)
++#ifdef USE_IPV6
++ addr_local = in6addr_any;
++#else
++ addr_local.s_addr = INADDR_ANY;
++#endif
++ else
++ {
++ if (isdigit(*szLocal))
++#ifdef USE_IPV6
++ inet_pton(AF_INET6, szLocal, &addr_local);
++#else
++ addr_local.s_addr = inet_addr(szLocal);
++#endif
++ else
++ {
++ if ((host = gethostbyname(szLocal)) == NULL)
++ return psock_errno("gethostbyname()"), 1;
++
++#ifdef USE_IPV6
++ addr_local = * (struct in6_addr *) (host->h_addr);
++#else
++ addr_local = * (struct in_addr *) (host->h_addr);
++#endif
++ }
++ }
++
++ if (!bSRV)
++ {
++ if (optind == argc)
++ usage();
++
++ if (isdigit(*argv[optind]))
++#ifdef USE_IPV6
++ inet_pton(AF_INET6, argv[optind], &addr_server);
++#else
++ addr_server.s_addr = inet_addr(argv[optind]);
++#endif
++ else
++ {
++ if ((host = gethostbyname(argv[optind])) == NULL)
++ return psock_errno("gethostbyname()"), 1;
++
++#ifdef USE_IPV6
++ addr_server = * (struct in6_addr *) (host->h_addr);
++#else
++ addr_server = * (struct in_addr *) (host->h_addr);
++#endif
++ }
++ }
++ }
++
++ /* do work */
++
++ signal(SIGINT, handler);
++
++ if (bSRV)
++ {
++ printf("\n");
++
++ if (bTCP)
++ {
++ if (newthread(TCP_Server))
++ return printf("Cannot create additional thread.\n"), 2;
++ }
++ if (bUDP)
++ {
++ if (newthread(UDP_Receiver))
++ return printf("Cannot create additional thread.\n"), 2;
++ if (newthread(UDP_Server))
++ return printf("Cannot create additional thread.\n"), 2;
++ }
++
++ for (;;) sleep(86400);
++ }
++ else
++ {
++ if (bTCP + bUDP > 1) /* exactly one only */
++ usage();
++
++ if (bTCP)
++ TCP_Bench(0);
++ else if (bUDP)
++ {
++ if (newthread(UDP_Receiver))
++ return printf("Cannot create additional thread.\n"), 2;
++ while (udpd == 0) sleep(1);
++ UDP_Bench(0);
++ }
++ }
++
++ /* terminate */
++
++ printf("\n");
++
++ return 0;
++}
++
++/* end of netio.c */
++