1 /*---------------------------------------------------------------
2 * Copyright (c) 1999,2000,2001,2002,2003
3 * The Board of Trustees of the University of Illinois
5 *---------------------------------------------------------------
6 * Permission is hereby granted, free of charge, to any person
7 * obtaining a copy of this software (Iperf) and associated
8 * documentation files (the "Software"), to deal in the Software
9 * without restriction, including without limitation the
10 * rights to use, copy, modify, merge, publish, distribute,
11 * sublicense, and/or sell copies of the Software, and to permit
12 * persons to whom the Software is furnished to do
13 * so, subject to the following conditions:
16 * Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and
18 * the following disclaimers.
21 * Redistributions in binary form must reproduce the above
22 * copyright notice, this list of conditions and the following
23 * disclaimers in the documentation and/or other materials
24 * provided with the distribution.
27 * Neither the names of the University of Illinois, NCSA,
28 * nor the names of its contributors may be used to endorse
29 * or promote products derived from this Software without
30 * specific prior written permission.
32 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
33 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
34 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
35 * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT
36 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
37 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
38 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE
39 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
40 * ________________________________________________________________
41 * National Laboratory for Applied Network Research
42 * National Center for Supercomputing Applications
43 * University of Illinois at Urbana-Champaign
44 * http://www.ncsa.uiuc.edu
45 * ________________________________________________________________
48 * by Mark Gates <mgates@nlanr.net>
49 * & Ajay Tirumala <tirumala@ncsa.uiuc.edu>
50 * -------------------------------------------------------------------
51 * Stores and parses the initial values for all the global variables.
52 * -------------------------------------------------------------------
60 * ------------------------------------------------------------------- */
66 #include "Settings.hpp"
68 #include "SocketAddr.h"
72 #include "gnu_getopt.h"
74 void Settings_Interpret( char option, const char *optarg, thread_Settings *mExtSettings );
76 /* -------------------------------------------------------------------
77 * command line options
79 * The option struct essentially maps a long option name (--foobar)
80 * or environment variable ($FOOBAR) to its short option char (f).
81 * ------------------------------------------------------------------- */
82 #define LONG_OPTIONS()
84 const struct option long_options[] =
86 {"singleclient", no_argument, NULL, '1'},
87 {"bandwidth", required_argument, NULL, 'b'},
88 {"client", required_argument, NULL, 'c'},
89 {"dualtest", no_argument, NULL, 'd'},
90 {"format", required_argument, NULL, 'f'},
91 {"help", no_argument, NULL, 'h'},
92 {"interval", required_argument, NULL, 'i'},
93 {"len", required_argument, NULL, 'l'},
94 {"print_mss", no_argument, NULL, 'm'},
95 {"num", required_argument, NULL, 'n'},
96 {"output", required_argument, NULL, 'o'},
97 {"port", required_argument, NULL, 'p'},
98 {"tradeoff", no_argument, NULL, 'r'},
99 {"server", no_argument, NULL, 's'},
100 {"time", required_argument, NULL, 't'},
101 {"udp", no_argument, NULL, 'u'},
102 {"version", no_argument, NULL, 'v'},
103 {"window", required_argument, NULL, 'w'},
104 {"reportexclude", required_argument, NULL, 'x'},
105 {"reportstyle",required_argument, NULL, 'y'},
107 // more esoteric options
108 {"bind", required_argument, NULL, 'B'},
109 {"compatibility", no_argument, NULL, 'C'},
110 {"daemon", no_argument, NULL, 'D'},
111 {"file_input", required_argument, NULL, 'F'},
112 {"stdin_input", no_argument, NULL, 'I'},
113 {"mss", required_argument, NULL, 'M'},
114 {"nodelay", no_argument, NULL, 'N'},
115 {"listenport", required_argument, NULL, 'L'},
116 {"parallel", required_argument, NULL, 'P'},
117 {"remove", no_argument, NULL, 'R'},
118 {"tos", required_argument, NULL, 'S'},
119 {"ttl", required_argument, NULL, 'T'},
120 {"single_udp", no_argument, NULL, 'U'},
121 {"ipv6_domian", no_argument, NULL, 'V'},
122 {"suggest_win_size", no_argument, NULL, 'W'},
126 #define ENV_OPTIONS()
128 const struct option env_options[] =
130 {"IPERF_SINGLECLIENT", no_argument, NULL, '1'},
131 {"IPERF_BANDWIDTH", required_argument, NULL, 'b'},
132 {"IPERF_CLIENT", required_argument, NULL, 'c'},
133 {"IPERF_DUALTEST", no_argument, NULL, 'd'},
134 {"IPERF_FORMAT", required_argument, NULL, 'f'},
136 {"IPERF_INTERVAL", required_argument, NULL, 'i'},
137 {"IPERF_LEN", required_argument, NULL, 'l'},
138 {"IPERF_PRINT_MSS", no_argument, NULL, 'm'},
139 {"IPERF_NUM", required_argument, NULL, 'n'},
140 {"IPERF_PORT", required_argument, NULL, 'p'},
141 {"IPERF_TRADEOFF", no_argument, NULL, 'r'},
142 {"IPERF_SERVER", no_argument, NULL, 's'},
143 {"IPERF_TIME", required_argument, NULL, 't'},
144 {"IPERF_UDP", no_argument, NULL, 'u'},
146 {"TCP_WINDOW_SIZE", required_argument, NULL, 'w'},
147 {"IPERF_REPORTEXCLUDE", required_argument, NULL, 'x'},
148 {"IPERF_REPORTSTYLE",required_argument, NULL, 'y'},
150 // more esoteric options
151 {"IPERF_BIND", required_argument, NULL, 'B'},
152 {"IPERF_COMPAT", no_argument, NULL, 'C'},
153 {"IPERF_DAEMON", no_argument, NULL, 'D'},
154 {"IPERF_FILE_INPUT", required_argument, NULL, 'F'},
155 {"IPERF_STDIN_INPUT", no_argument, NULL, 'I'},
156 {"IPERF_MSS", required_argument, NULL, 'M'},
157 {"IPERF_NODELAY", no_argument, NULL, 'N'},
158 {"IPERF_LISTENPORT", required_argument, NULL, 'L'},
159 {"IPERF_PARALLEL", required_argument, NULL, 'P'},
160 {"IPERF_TOS", required_argument, NULL, 'S'},
161 {"IPERF_TTL", required_argument, NULL, 'T'},
162 {"IPERF_SINGLE_UDP", no_argument, NULL, 'U'},
163 {"IPERF_IPV6_DOMAIN", no_argument, NULL, 'V'},
164 {"IPERF_SUGGEST_WIN_SIZE", required_argument, NULL, 'W'},
168 #define SHORT_OPTIONS()
170 const char short_options[] = "1b:c:df:hi:l:mn:o:p:rst:uvw:x:y:B:CDF:IL:M:NP:RS:T:UVW";
172 /* -------------------------------------------------------------------
174 * ------------------------------------------------------------------- */
177 const long kDefault_UDPRate = 1024 * 1024; // -u if set, 1 Mbit/sec
178 const int kDefault_UDPBufLen = 1470; // -u if set, read/write 1470 bytes
179 // 1470 bytes is small enough to be sending one packet per datagram on ethernet
181 // 1450 bytes is small enough to be sending one packet per datagram on ethernet
182 // **** with IPv6 ****
184 /* -------------------------------------------------------------------
185 * Initialize all settings to defaults.
186 * ------------------------------------------------------------------- */
188 void Settings_Initialize( thread_Settings *main ) {
189 // Everything defaults to zero or NULL with
190 // this memset. Only need to set non-zero values
192 memset( main, 0, sizeof(thread_Settings) );
193 main->mSock = INVALID_SOCKET;
194 main->mReportMode = kReport_Default;
196 main->flags = FLAG_MODETIME | FLAG_STDOUT; // Default time and stdout
197 //main->mUDPRate = 0; // -b, ie. TCP mode
198 //main->mHost = NULL; // -c, none, required for client
199 main->mMode = kTest_Normal; // -d, mMode == kTest_DualTest
200 main->mFormat = 'a'; // -f, adaptive bits
202 //main->mBufLenSet = false; // -l,
203 main->mBufLen = 8 * 1024; // -l, 8 Kbyte
204 //main->mInterval = 0; // -i, ie. no periodic bw reports
205 //main->mPrintMSS = false; // -m, don't print MSS
206 // mAmount is time also // -n, N/A
207 //main->mOutputFileName = NULL; // -o, filename
208 main->mPort = 5001; // -p, ttcp port
209 // mMode = kTest_Normal; // -r, mMode == kTest_TradeOff
210 main->mThreadMode = kMode_Unknown; // -s, or -c, none
211 main->mAmount = 1000; // -t, 10 seconds
212 // mUDPRate > 0 means UDP // -u, N/A, see kDefault_UDPRate
213 // skip version // -v,
214 //main->mTCPWin = 0; // -w, ie. don't set window
216 // more esoteric options
217 //main->mLocalhost = NULL; // -B, none
218 //main->mCompat = false; // -C, run in Compatibility mode
219 //main->mDaemon = false; // -D, run as a daemon
220 //main->mFileInput = false; // -F,
221 //main->mFileName = NULL; // -F, filename
222 //main->mStdin = false; // -I, default not stdin
223 //main->mListenPort = 0; // -L, listen port
224 //main->mMSS = 0; // -M, ie. don't set MSS
225 //main->mNodelay = false; // -N, don't set nodelay
226 //main->mThreads = 0; // -P,
227 //main->mRemoveService = false; // -R,
228 //main->mTOS = 0; // -S, ie. don't set type of service
229 main->mTTL = 1; // -T, link-local TTL
230 //main->mDomain = kMode_IPv4; // -V,
231 //main->mSuggestWin = false; // -W, Suggest the window size.
235 void Settings_Copy( thread_Settings *from, thread_Settings **into ) {
236 *into = new thread_Settings;
237 memcpy( *into, from, sizeof(thread_Settings) );
238 if ( from->mHost != NULL ) {
239 (*into)->mHost = new char[ strlen(from->mHost) + 1];
240 strcpy( (*into)->mHost, from->mHost );
242 if ( from->mOutputFileName != NULL ) {
243 (*into)->mOutputFileName = new char[ strlen(from->mOutputFileName) + 1];
244 strcpy( (*into)->mOutputFileName, from->mOutputFileName );
246 if ( from->mLocalhost != NULL ) {
247 (*into)->mLocalhost = new char[ strlen(from->mLocalhost) + 1];
248 strcpy( (*into)->mLocalhost, from->mLocalhost );
250 if ( from->mFileName != NULL ) {
251 (*into)->mFileName = new char[ strlen(from->mFileName) + 1];
252 strcpy( (*into)->mFileName, from->mFileName );
254 // Zero out certain entries
255 (*into)->mTID = thread_zeroid();
256 (*into)->runNext = NULL;
257 (*into)->runNow = NULL;
260 /* -------------------------------------------------------------------
261 * Delete memory: Does not clean up open file pointers or ptr_parents
262 * ------------------------------------------------------------------- */
264 void Settings_Destroy( thread_Settings *mSettings) {
265 DELETE_ARRAY( mSettings->mHost );
266 DELETE_ARRAY( mSettings->mLocalhost );
267 DELETE_ARRAY( mSettings->mFileName );
268 DELETE_ARRAY( mSettings->mOutputFileName );
269 DELETE_PTR( mSettings );
272 /* -------------------------------------------------------------------
273 * Parses settings from user's environment variables.
274 * ------------------------------------------------------------------- */
275 void Settings_ParseEnvironment( thread_Settings *mSettings ) {
279 while ( env_options[i].name != NULL ) {
280 theVariable = getenv( env_options[i].name );
281 if ( theVariable != NULL ) {
282 Settings_Interpret( env_options[i].val, theVariable, mSettings );
286 } // end ParseEnvironment
288 /* -------------------------------------------------------------------
289 * Parse settings from app's command line.
290 * ------------------------------------------------------------------- */
292 void Settings_ParseCommandLine( int argc, char **argv, thread_Settings *mSettings ) {
295 gnu_getopt_long( argc, argv, short_options,
296 long_options, NULL )) != EOF ) {
297 Settings_Interpret( option, gnu_optarg, mSettings );
300 for ( int i = gnu_optind; i < argc; i++ ) {
301 fprintf( stderr, "%s: ignoring extra argument -- %s\n", argv[0], argv[i] );
303 } // end ParseCommandLine
305 /* -------------------------------------------------------------------
306 * Interpret individual options, either from the command line
307 * or from environment variables.
308 * ------------------------------------------------------------------- */
310 void Settings_Interpret( char option, const char *optarg, thread_Settings *mExtSettings ) {
314 case '1': // Single Client
315 setSingleClient( mExtSettings );
317 case 'b': // UDP bandwidth
318 if ( !isUDP( mExtSettings ) ) {
319 fprintf( stderr, warn_implied_udp, option );
322 if ( mExtSettings->mThreadMode != kMode_Client ) {
323 fprintf( stderr, warn_invalid_server_option, option );
327 Settings_GetLowerCaseArg(optarg,outarg);
328 mExtSettings->mUDPRate = byte_atoi(outarg);
329 setUDP( mExtSettings );
331 // if -l has already been processed, mBufLenSet is true
332 // so don't overwrite that value.
333 if ( !isBuflenSet( mExtSettings ) ) {
334 mExtSettings->mBufLen = kDefault_UDPBufLen;
338 case 'c': // client mode w/ server host to connect to
339 mExtSettings->mHost = new char[ strlen( optarg ) + 1 ];
340 strcpy( mExtSettings->mHost, optarg );
342 if ( mExtSettings->mThreadMode == kMode_Unknown ) {
343 // Test for Multicast
345 SockAddr_setHostname( mExtSettings->mHost, &temp,
346 (isIPV6( mExtSettings ) ? 1 : 0 ));
347 if ( SockAddr_isMulticast( &temp ) ) {
348 setMulticast( mExtSettings );
350 mExtSettings->mThreadMode = kMode_Client;
351 mExtSettings->mThreads = 1;
355 case 'd': // Dual-test Mode
356 if ( mExtSettings->mThreadMode != kMode_Client ) {
357 fprintf( stderr, warn_invalid_server_option, option );
360 if ( isCompat( mExtSettings ) ) {
361 fprintf( stderr, warn_invalid_compatibility_option, option );
364 mExtSettings->mMode = kTest_DualTest;
366 fprintf( stderr, warn_invalid_single_threaded, option );
367 mExtSettings->mMode = kTest_TradeOff;
371 case 'f': // format to print in
372 mExtSettings->mFormat = (*optarg);
375 case 'h': // print help and exit
377 fprintf( stderr, usage_long );
379 fprintf(stderr, usage_long1);
380 fprintf(stderr, usage_long2);
385 case 'i': // specify interval between periodic bw reports
386 mExtSettings->mInterval = atof( optarg );
387 if ( mExtSettings->mInterval < 0.5 ) {
388 fprintf (stderr, report_interval_small, mExtSettings->mInterval);
389 mExtSettings->mInterval = 0.5;
393 case 'l': // length of each buffer
394 Settings_GetUpperCaseArg(optarg,outarg);
395 mExtSettings->mBufLen = byte_atoi( outarg );
396 setBuflenSet( mExtSettings );
397 if ( !isUDP( mExtSettings ) ) {
398 if ( mExtSettings->mBufLen < (int) sizeof( client_hdr ) &&
399 !isCompat( mExtSettings ) ) {
400 setCompat( mExtSettings );
401 fprintf( stderr, warn_implied_compatibility, option );
404 if ( mExtSettings->mBufLen < (int) sizeof( UDP_datagram ) ) {
405 mExtSettings->mBufLen = sizeof( UDP_datagram );
406 fprintf( stderr, warn_buffer_too_small, mExtSettings->mBufLen );
408 if ( !isCompat( mExtSettings ) &&
409 mExtSettings->mBufLen < (int) ( sizeof( UDP_datagram )
410 + sizeof( client_hdr ) ) ) {
411 setCompat( mExtSettings );
412 fprintf( stderr, warn_implied_compatibility, option );
418 case 'm': // print TCP MSS
419 setPrintMSS( mExtSettings );
422 case 'n': // bytes of data
423 // amount mode (instead of time mode)
424 unsetModeTime( mExtSettings );
425 Settings_GetUpperCaseArg(optarg,outarg);
426 mExtSettings->mAmount = byte_atoi( outarg );
429 case 'o' : // output the report and other messages into the file
430 unsetSTDOUT( mExtSettings );
431 mExtSettings->mOutputFileName = new char[strlen(optarg)+1];
432 strcpy( mExtSettings->mOutputFileName, optarg);
435 case 'p': // server port
436 mExtSettings->mPort = atoi( optarg );
439 case 'r': // test mode tradeoff
440 if ( mExtSettings->mThreadMode != kMode_Client ) {
441 fprintf( stderr, warn_invalid_server_option, option );
444 if ( isCompat( mExtSettings ) ) {
445 fprintf( stderr, warn_invalid_compatibility_option, option );
448 mExtSettings->mMode = kTest_TradeOff;
451 case 's': // server mode
452 if ( mExtSettings->mThreadMode != kMode_Unknown ) {
453 fprintf( stderr, warn_invalid_client_option, option );
457 mExtSettings->mThreadMode = kMode_Listener;
460 case 't': // seconds to write for
461 // time mode (instead of amount mode)
462 setModeTime( mExtSettings );
463 mExtSettings->mAmount = (int) (atof( optarg ) * 100.0);
466 case 'u': // UDP instead of TCP
467 // if -b has already been processed, UDP rate will
468 // already be non-zero, so don't overwrite that value
469 if ( !isUDP( mExtSettings ) ) {
470 setUDP( mExtSettings );
471 mExtSettings->mUDPRate = kDefault_UDPRate;
474 // if -l has already been processed, mBufLenSet is true
475 // so don't overwrite that value.
476 if ( !isBuflenSet( mExtSettings ) ) {
477 mExtSettings->mBufLen = kDefault_UDPBufLen;
478 } else if ( mExtSettings->mBufLen < (int) ( sizeof( UDP_datagram )
479 + sizeof( client_hdr ) ) &&
480 !isCompat( mExtSettings ) ) {
481 setCompat( mExtSettings );
482 fprintf( stderr, warn_implied_compatibility, option );
486 case 'v': // print version and exit
487 fprintf( stderr, version );
491 case 'w': // TCP window size (socket buffer size)
492 Settings_GetUpperCaseArg(optarg,outarg);
493 mExtSettings->mTCPWin = byte_atoi(outarg);
495 if ( mExtSettings->mTCPWin < 2048 ) {
496 fprintf( stderr, warn_window_small, mExtSettings->mTCPWin );
500 case 'x': // Limit Reports
501 while ( *optarg != '\0' ) {
505 setNoSettReport( mExtSettings );
509 setNoConnReport( mExtSettings );
513 setNoDataReport( mExtSettings );
517 setNoServReport( mExtSettings );
521 setNoMultReport( mExtSettings );
524 fprintf(stderr, warn_invalid_report, *optarg);
530 case 'y': // Reporting Style
534 mExtSettings->mReportMode = kReport_CSV;
537 fprintf( stderr, warn_invalid_report_style, optarg );
542 // more esoteric options
543 case 'B': // specify bind address
544 mExtSettings->mLocalhost = new char[ strlen( optarg ) + 1 ];
545 strcpy( mExtSettings->mLocalhost, optarg );
546 // Test for Multicast
548 SockAddr_setHostname( mExtSettings->mLocalhost, &temp,
549 (isIPV6( mExtSettings ) ? 1 : 0 ));
550 if ( SockAddr_isMulticast( &temp ) ) {
551 setMulticast( mExtSettings );
555 case 'C': // Run in Compatibility Mode
556 setCompat( mExtSettings );
557 if ( mExtSettings->mMode != kTest_Normal ) {
558 fprintf( stderr, warn_invalid_compatibility_option,
559 ( mExtSettings->mMode == kTest_DualTest ?
561 mExtSettings->mMode = kTest_Normal;
565 case 'D': // Run as a daemon
566 setDaemon( mExtSettings );
569 case 'F' : // Get the input for the data stream from a file
570 if ( mExtSettings->mThreadMode != kMode_Client ) {
571 fprintf( stderr, warn_invalid_server_option, option );
575 setFileInput( mExtSettings );
576 mExtSettings->mFileName = new char[strlen(optarg)+1];
577 strcpy( mExtSettings->mFileName, optarg);
580 case 'I' : // Set the stdin as the input source
581 if ( mExtSettings->mThreadMode != kMode_Client ) {
582 fprintf( stderr, warn_invalid_server_option, option );
586 setFileInput( mExtSettings );
587 setSTDIN( mExtSettings );
588 mExtSettings->mFileName = new char[strlen("<stdin>")+1];
589 strcpy( mExtSettings->mFileName,"<stdin>");
592 case 'L': // Listen Port (bidirectional testing client-side)
593 if ( mExtSettings->mThreadMode != kMode_Client ) {
594 fprintf( stderr, warn_invalid_server_option, option );
598 mExtSettings->mListenPort = atoi( optarg );
601 case 'M': // specify TCP MSS (maximum segment size)
602 Settings_GetUpperCaseArg(optarg,outarg);
604 mExtSettings->mMSS = byte_atoi( outarg );
607 case 'N': // specify TCP nodelay option (disable Jacobson's Algorithm)
608 setNoDelay( mExtSettings );
611 case 'P': // number of client threads
613 mExtSettings->mThreads = atoi( optarg );
615 if ( mExtSettings->mThreadMode != kMode_Server ) {
616 fprintf( stderr, warn_invalid_single_threaded, option );
618 mExtSettings->mThreads = atoi( optarg );
624 setRemoveService( mExtSettings );
627 case 'S': // IP type-of-service
628 // TODO use a function that understands base-2
629 // the zero base here allows the user to specify
630 // "0x#" hex, "0#" octal, and "#" decimal numbers
631 mExtSettings->mTOS = strtol( optarg, NULL, 0 );
634 case 'T': // time-to-live for multicast
635 mExtSettings->mTTL = atoi( optarg );
638 case 'U': // single threaded UDP server
639 setSingleUDP( mExtSettings );
642 case 'V': // IPv6 Domain
643 setIPV6( mExtSettings );
644 if ( mExtSettings->mThreadMode == kMode_Server
645 && mExtSettings->mLocalhost != NULL ) {
646 // Test for Multicast
648 SockAddr_setHostname( mExtSettings->mLocalhost, &temp, 1);
649 if ( SockAddr_isMulticast( &temp ) ) {
650 setMulticast( mExtSettings );
652 } else if ( mExtSettings->mThreadMode == kMode_Client ) {
653 // Test for Multicast
655 SockAddr_setHostname( mExtSettings->mHost, &temp, 1 );
656 if ( SockAddr_isMulticast( &temp ) ) {
657 setMulticast( mExtSettings );
663 setSuggestWin( mExtSettings );
664 fprintf( stderr, "The -W option is not available in this release\n");
667 default: // ignore unknown
672 void Settings_GetUpperCaseArg(const char *inarg, char *outarg) {
674 int len = strlen(inarg);
675 strcpy(outarg,inarg);
677 if ( (len > 0) && (inarg[len-1] >='a')
678 && (inarg[len-1] <= 'z') )
679 outarg[len-1]= outarg[len-1]+'A'-'a';
682 void Settings_GetLowerCaseArg(const char *inarg, char *outarg) {
684 int len = strlen(inarg);
685 strcpy(outarg,inarg);
687 if ( (len > 0) && (inarg[len-1] >='A')
688 && (inarg[len-1] <= 'Z') )
689 outarg[len-1]= outarg[len-1]-'A'+'a';
693 * Settings_GenerateListenerSettings
694 * Called to generate the settings to be passed to the Listener
695 * instance that will handle dual testings from the client side
696 * this should only return an instance if it was called on
697 * the thread_Settings instance generated from the command line
698 * for client side execution
700 void Settings_GenerateListenerSettings( thread_Settings *client, thread_Settings **listener ) {
701 if ( !isCompat( client ) &&
702 (client->mMode == kTest_DualTest || client->mMode == kTest_TradeOff) ) {
703 *listener = new thread_Settings;
704 memcpy(*listener, client, sizeof( thread_Settings ));
705 setCompat( (*listener) );
706 unsetDaemon( (*listener) );
707 if ( client->mListenPort != 0 ) {
708 (*listener)->mPort = client->mListenPort;
710 (*listener)->mPort = client->mPort;
712 (*listener)->mFileName = NULL;
713 (*listener)->mHost = NULL;
714 (*listener)->mLocalhost = NULL;
715 (*listener)->mOutputFileName = NULL;
716 (*listener)->mMode = kTest_Normal;
717 (*listener)->mThreadMode = kMode_Listener;
718 if ( client->mHost != NULL ) {
719 (*listener)->mHost = new char[strlen( client->mHost ) + 1];
720 strcpy( (*listener)->mHost, client->mHost );
722 if ( client->mLocalhost != NULL ) {
723 (*listener)->mLocalhost = new char[strlen( client->mLocalhost ) + 1];
724 strcpy( (*listener)->mLocalhost, client->mLocalhost );
732 * Settings_GenerateSpeakerSettings
733 * Called to generate the settings to be passed to the Speaker
734 * instance that will handle dual testings from the server side
735 * this should only return an instance if it was called on
736 * the thread_Settings instance generated from the command line
737 * for server side execution. This should be an inverse operation
738 * of GenerateClientHdr.
740 void Settings_GenerateClientSettings( thread_Settings *server,
741 thread_Settings **client,
743 int flags = ntohl(hdr->flags);
744 if ( (flags & HEADER_VERSION1) != 0 ) {
745 *client = new thread_Settings;
746 memcpy(*client, server, sizeof( thread_Settings ));
747 setCompat( (*client) );
748 (*client)->mTID = thread_zeroid();
749 (*client)->mPort = (unsigned short) ntohl(hdr->mPort);
750 (*client)->mThreads = ntohl(hdr->numThreads);
751 if ( hdr->bufferlen != 0 ) {
752 (*client)->mBufLen = ntohl(hdr->bufferlen);
754 if ( hdr->mWinBand != 0 ) {
755 if ( isUDP( server ) ) {
756 (*client)->mUDPRate = ntohl(hdr->mWinBand);
758 (*client)->mTCPWin = ntohl(hdr->mWinBand);
761 (*client)->mAmount = ntohl(hdr->mAmount);
762 if ( ((*client)->mAmount & 0x80000000) > 0 ) {
763 setModeTime( (*client) );
765 (*client)->mAmount |= 0xFFFFFFFF00000000LL;
767 (*client)->mAmount |= 0xFFFFFFFF00000000;
769 (*client)->mAmount = -(*client)->mAmount;
771 (*client)->mFileName = NULL;
772 (*client)->mHost = NULL;
773 (*client)->mLocalhost = NULL;
774 (*client)->mOutputFileName = NULL;
775 (*client)->mMode = ((flags & RUN_NOW) == 0 ?
776 kTest_TradeOff : kTest_DualTest);
777 (*client)->mThreadMode = kMode_Client;
778 if ( server->mLocalhost != NULL ) {
779 (*client)->mLocalhost = new char[strlen( server->mLocalhost ) + 1];
780 strcpy( (*client)->mLocalhost, server->mLocalhost );
782 (*client)->mHost = new char[REPORT_ADDRLEN];
783 if ( ((sockaddr*)&server->peer)->sa_family == AF_INET ) {
784 inet_ntop( AF_INET, &((sockaddr_in*)&server->peer)->sin_addr,
785 (*client)->mHost, REPORT_ADDRLEN);
789 inet_ntop( AF_INET6, &((sockaddr_in6*)&server->peer)->sin6_addr,
790 (*client)->mHost, REPORT_ADDRLEN);
799 * Settings_GenerateClientHdr
800 * Called to generate the client header to be passed to the
801 * server that will handle dual testings from the server side
802 * This should be an inverse operation of GenerateSpeakerSettings
804 void Settings_GenerateClientHdr( thread_Settings *client, client_hdr *hdr ) {
805 if ( client->mMode != kTest_Normal ) {
806 hdr->flags = htonl(HEADER_VERSION1);
810 if ( isBuflenSet( client ) ) {
811 hdr->bufferlen = htonl(client->mBufLen);
815 if ( isUDP( client ) ) {
816 hdr->mWinBand = htonl(client->mUDPRate);
818 hdr->mWinBand = htonl(client->mTCPWin);
820 if ( client->mListenPort != 0 ) {
821 hdr->mPort = htonl(client->mListenPort);
823 hdr->mPort = htonl(client->mPort);
825 hdr->numThreads = htonl(client->mThreads);
826 if ( isModeTime( client ) ) {
827 hdr->mAmount = htonl(-(long)client->mAmount);
829 hdr->mAmount = htonl((long)client->mAmount);
830 hdr->mAmount &= htonl( 0x7FFFFFFF );
832 if ( client->mMode == kTest_DualTest ) {
833 hdr->flags |= htonl(RUN_NOW);