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 {"dualtest", no_argument, NULL, '2'},
88 {"bandwidth", required_argument, NULL, 'b'},
89 {"client", required_argument, NULL, 'c'},
90 {"dccp", no_argument, NULL, 'd'},
91 {"format", required_argument, NULL, 'f'},
92 {"help", no_argument, NULL, 'h'},
93 {"interval", required_argument, NULL, 'i'},
94 {"mcast_iface",required_argument, NULL, 'j'},
95 {"len", required_argument, NULL, 'l'},
96 {"print_mss", no_argument, NULL, 'm'},
97 {"num", required_argument, NULL, 'n'},
98 {"output", required_argument, NULL, 'o'},
99 {"port", required_argument, NULL, 'p'},
100 {"tradeoff", no_argument, NULL, 'r'},
101 {"server", no_argument, NULL, 's'},
102 {"time", required_argument, NULL, 't'},
103 {"udp", no_argument, NULL, 'u'},
104 {"udplite", required_argument, NULL, 'u'},
105 {"version", no_argument, NULL, 'v'},
106 {"window", required_argument, NULL, 'w'},
107 {"reportexclude", required_argument, NULL, 'x'},
108 {"reportstyle",required_argument, NULL, 'y'},
110 // more esoteric options
111 {"algorithm", required_argument, NULL, 'A'},
112 {"bind", required_argument, NULL, 'B'},
113 {"compatibility", no_argument, NULL, 'C'},
114 {"daemon", no_argument, NULL, 'D'},
115 {"file_input", required_argument, NULL, 'F'},
116 {"stdin_input", no_argument, NULL, 'I'},
117 {"mss", required_argument, NULL, 'M'},
118 {"nodelay", no_argument, NULL, 'N'},
119 {"listenport", required_argument, NULL, 'L'},
120 {"parallel", required_argument, NULL, 'P'},
121 {"remove", no_argument, NULL, 'R'},
122 {"dscp", required_argument, NULL, 'S'},
123 {"ttl", required_argument, NULL, 'T'},
124 {"single_udp", no_argument, NULL, 'U'},
125 {"ipv6_domian", no_argument, NULL, 'V'},
126 {"suggest_win_size", no_argument, NULL, 'W'},
127 {"ccid", required_argument, NULL, 'Z'},
128 {"bindport", required_argument, NULL, 'O'},
132 #define ENV_OPTIONS()
134 const struct option env_options[] =
136 {"IPERF_SINGLECLIENT", no_argument, NULL, '1'},
137 {"IPERF_DUALTEST", no_argument, NULL, '2'},
138 {"IPERF_BANDWIDTH", required_argument, NULL, 'b'},
139 {"IPERF_CLIENT", required_argument, NULL, 'c'},
140 {"IPERF_DCCP", no_argument, NULL, 'd'},
141 {"IPERF_FORMAT", required_argument, NULL, 'f'},
143 {"IPERF_INTERVAL", required_argument, NULL, 'i'},
144 {"IPERF_MCASTIFACE", required_argument, NULL, 'j'},
145 {"IPERF_LEN", required_argument, NULL, 'l'},
146 {"IPERF_PRINT_MSS", no_argument, NULL, 'm'},
147 {"IPERF_NUM", required_argument, NULL, 'n'},
148 {"IPERF_PORT", required_argument, NULL, 'p'},
149 {"IPERF_TRADEOFF", no_argument, NULL, 'r'},
150 {"IPERF_SERVER", no_argument, NULL, 's'},
151 {"IPERF_TIME", required_argument, NULL, 't'},
152 {"IPERF_UDP", no_argument, NULL, 'u'},
154 {"TCP_WINDOW_SIZE", required_argument, NULL, 'w'},
155 {"IPERF_REPORTEXCLUDE", required_argument, NULL, 'x'},
156 {"IPERF_REPORTSTYLE",required_argument, NULL, 'y'},
158 // more esoteric options
159 {"IPERF_CC", required_argument, NULL, 'A'},
160 {"IPERF_BIND", required_argument, NULL, 'B'},
161 {"IPERF_COMPAT", no_argument, NULL, 'C'},
162 {"IPERF_DAEMON", no_argument, NULL, 'D'},
163 {"IPERF_FILE_INPUT", required_argument, NULL, 'F'},
164 {"IPERF_STDIN_INPUT", no_argument, NULL, 'I'},
165 {"IPERF_MSS", required_argument, NULL, 'M'},
166 {"IPERF_NODELAY", no_argument, NULL, 'N'},
167 {"IPERF_LISTENPORT", required_argument, NULL, 'L'},
168 {"IPERF_PARALLEL", required_argument, NULL, 'P'},
169 {"IPERF_DSCP", required_argument, NULL, 'S'},
170 {"IPERF_TTL", required_argument, NULL, 'T'},
171 {"IPERF_SINGLE_UDP", no_argument, NULL, 'U'},
172 {"IPERF_IPV6_DOMAIN", no_argument, NULL, 'V'},
173 {"IPERF_SUGGEST_WIN_SIZE", required_argument, NULL, 'W'},
174 {"IPERF_CCID", required_argument, NULL, 'Z'},
175 {"IPERF_BINDPORT", required_argument, NULL, 'O'},
179 #define SHORT_OPTIONS()
181 const char short_options[] =
182 "12b::c:df:hi:j:l:mn:o:p:rst:uvw:x:y:A:B:CDF:IJ:L:M:NP:RS:T:UV:WZ:0:";
184 /* -------------------------------------------------------------------
186 * ------------------------------------------------------------------- */
189 const long kDefault_DgramRate = 1024 * 1024; // -u if set, 1 Mbit/sec
190 const int kDefault_UDPBufLen = 1470; // -u if set, read/write 1470 bytes
191 // 1470 bytes is small enough to be sending one packet per datagram on ethernet
193 // 1450 bytes is small enough to be sending one packet per datagram on ethernet
194 // **** with IPv6 ****
195 const int kDefault_DCCPBufLen = 1420; // -d
196 // old DCCPv4: MPS=1424; new DCCPv4: MPS=1440; new DCCPv6: MPS=1420 (above)
198 /* -------------------------------------------------------------------
199 * Initialize all settings to defaults.
200 * ------------------------------------------------------------------- */
202 void Settings_Initialize( thread_Settings *main ) {
203 // Everything defaults to zero or NULL with
204 // this memset. Only need to set non-zero values
206 memset( main, 0, sizeof(thread_Settings) );
207 main->mSock = INVALID_SOCKET;
208 //main->mSockAF = AF_UNSPEC
209 main->mReportMode = kReport_Default;
211 main->flags = FLAG_MODETIME | FLAG_STDOUT; // Default time and stdout
212 //main->mDgramRate = 0; // -b, ie. TCP mode
213 main->mProtocol = kProto_TCP; // -u / -d
214 //main->mHost = NULL; // -c, none, required for client
215 main->mMode = kTest_Normal; // -2, mMode == kTest_DualTest
216 main->mFormat = 'a'; // -f, adaptive bits
218 //main->mBufLenSet = false; // -l,
219 main->mBufLen = 8 * 1024; // -l, 8 Kbyte
220 //main->mInterval = 0; // -i, ie. no periodic bw reports
221 //main->mPrintMSS = false; // -m, don't print MSS
222 // mAmount is time also // -n, N/A
223 //main->mOutputFileName = NULL; // -o, filename
224 main->mPort = 5001; // -p, ttcp port
225 // mMode = kTest_Normal; // -r, mMode == kTest_TradeOff
226 main->mThreadMode = kMode_Unknown; // -s, or -c, none
227 main->mAmount = 1000; // -t, 10 seconds
228 // mDgramRate // -u, N/A, see kDefault_DgramRate
229 // skip version // -v,
230 //main->mWinSize = 0; // -w, ie. don't set window
232 // more esoteric options
233 //main->mLocalhost = NULL; // -B, bind address - none
234 //main->mCompat = false; // -C, run in Compatibility mode
235 //main->mDaemon = false; // -D, run as a daemon
236 //main->mFileInput = false; // -F,
237 //main->mFileName = NULL; // -F, filename
238 //main->mStdin = false; // -I, default not stdin
239 //main->mMcastIface = 0; // -J, default: host chooses interface
240 //main->mListenPort = 0; // -L, listen port
241 //main->mMSS = 0; // -M, ie. don't set MSS
242 //main->mNodelay = false; // -N, don't set nodelay
243 //main->mThreads = 0; // -P,
244 //main->mRemoveService = false; // -R,
245 //main->mTOS = 0; // -S, ie. don't set type of service
246 main->mTTL = 1; // -T, link-local TTL
247 //main->mDomain = kMode_IPv4; // -V,
248 //main->mSuggestWin = false; // -W, Suggest the window size.
252 void Settings_Copy( thread_Settings *from, thread_Settings **into ) {
253 *into = new thread_Settings;
254 memcpy( *into, from, sizeof(thread_Settings) );
255 if ( from->mHost != NULL ) {
256 (*into)->mHost = new char[ strlen(from->mHost) + 1];
257 strcpy( (*into)->mHost, from->mHost );
259 if ( from->mOutputFileName != NULL ) {
260 (*into)->mOutputFileName = new char[ strlen(from->mOutputFileName) + 1];
261 strcpy( (*into)->mOutputFileName, from->mOutputFileName );
263 if ( from->mLocalhost != NULL ) {
264 (*into)->mLocalhost = new char[ strlen(from->mLocalhost) + 1];
265 strcpy( (*into)->mLocalhost, from->mLocalhost );
267 if ( from->mFileName != NULL ) {
268 (*into)->mFileName = new char[ strlen(from->mFileName) + 1];
269 strcpy( (*into)->mFileName, from->mFileName );
271 // Zero out certain entries
272 (*into)->mTID = thread_zeroid();
273 (*into)->runNext = NULL;
274 (*into)->runNow = NULL;
277 /* -------------------------------------------------------------------
278 * Delete memory: Does not clean up open file pointers or ptr_parents
279 * ------------------------------------------------------------------- */
281 void Settings_Destroy( thread_Settings *mSettings) {
282 DELETE_ARRAY( mSettings->mHost );
283 DELETE_ARRAY( mSettings->mLocalhost );
284 DELETE_ARRAY( mSettings->mFileName );
285 DELETE_ARRAY( mSettings->mOutputFileName );
286 DELETE_PTR( mSettings );
289 /* -------------------------------------------------------------------
290 * Parses settings from user's environment variables.
291 * ------------------------------------------------------------------- */
292 void Settings_ParseEnvironment( thread_Settings *mSettings ) {
296 while ( env_options[i].name != NULL ) {
297 theVariable = getenv( env_options[i].name );
298 if ( theVariable != NULL ) {
299 Settings_Interpret( env_options[i].val, theVariable, mSettings );
303 } // end ParseEnvironment
305 /* -------------------------------------------------------------------
306 * Parse settings from app's command line.
307 * ------------------------------------------------------------------- */
309 void Settings_ParseCommandLine( int argc, char **argv, thread_Settings *mSettings ) {
312 gnu_getopt_long( argc, argv, short_options,
313 long_options, NULL )) != EOF ) {
314 Settings_Interpret( option, gnu_optarg, mSettings );
317 for ( int i = gnu_optind; i < argc; i++ ) {
318 fprintf( stderr, "%s: ignoring extra argument -- %s\n", argv[0], argv[i] );
320 } // end ParseCommandLine
322 /* -------------------------------------------------------------------
323 * Interpret individual options, either from the command line
324 * or from environment variables.
325 * ------------------------------------------------------------------- */
327 void Settings_Interpret( char option, const char *optarg, thread_Settings *mExtSettings ) {
331 case '1': // Single Client
332 setSingleClient( mExtSettings );
335 case '2': // Dual-test Mode
336 if ( mExtSettings->mThreadMode != kMode_Client ) {
337 fprintf( stderr, warn_invalid_server_option, option );
340 if ( isCompat( mExtSettings ) ) {
341 fprintf( stderr, warn_invalid_compatibility_option, option );
344 mExtSettings->mMode = kTest_DualTest;
346 fprintf( stderr, warn_invalid_single_threaded, option );
347 mExtSettings->mMode = kTest_TradeOff;
352 // This sets packet-oriented mode. The optional
353 // argument sets datagram bandwidth (as before).
354 // If not given, a default bandwith is used.
355 setPacketOriented(mExtSettings);
358 Settings_GetLowerCaseArg(optarg, outarg);
359 mExtSettings->mDgramRate = byte_atoi(outarg);
361 mExtSettings->mDgramRate = kDefault_DgramRate;
364 case 'c': // client mode w/ server host to connect to
365 mExtSettings->mHost = new char[ strlen( optarg ) + 1 ];
366 strcpy( mExtSettings->mHost, optarg );
368 if ( mExtSettings->mThreadMode == kMode_Unknown ) {
369 mExtSettings->mThreadMode = kMode_Client;
370 mExtSettings->mThreads = 1;
374 case 'd': // DCCP as transport
375 mExtSettings->mProtocol = kProto_DCCP;
377 // if -l has already been processed, mBufLenSet is true
378 // so don't overwrite that value.
379 if ( !isBuflenSet( mExtSettings ) )
380 mExtSettings->mBufLen = kDefault_DCCPBufLen;
384 case 'f': // format to print in
385 mExtSettings->mFormat = (*optarg);
388 case 'h': // print help and exit
391 case 'i': // specify interval between periodic bw reports
392 mExtSettings->mInterval = atof( optarg );
393 if ( mExtSettings->mInterval < 0.5 ) {
394 fprintf (stderr, report_interval_small, mExtSettings->mInterval);
395 mExtSettings->mInterval = 0.5;
400 case 'J': // multicast interface to join multicast address on
401 mExtSettings->mMcastIface = if_nametoindex(optarg);
402 if (!mExtSettings->mMcastIface)
403 die("Interface \"%s\" does not work for -j/-J.", optarg);
406 case 'l': // length of each buffer
407 Settings_GetUpperCaseArg(optarg,outarg);
408 mExtSettings->mBufLen = byte_atoi( outarg );
409 setBuflenSet( mExtSettings );
411 if ( !isPacketOriented( mExtSettings ) ) {
412 if ( mExtSettings->mBufLen < (int) sizeof( client_hdr ) &&
413 !isCompat( mExtSettings ) ) {
414 setCompat( mExtSettings );
415 fprintf( stderr, warn_implied_compatibility, option );
418 if ( mExtSettings->mBufLen < (int) sizeof( dgram_record ) ) {
419 mExtSettings->mBufLen = sizeof( dgram_record );
420 fprintf( stderr, warn_buffer_too_small, mExtSettings->mBufLen );
422 if ( !isCompat( mExtSettings ) &&
423 mExtSettings->mBufLen < (int) ( sizeof( dgram_record )
424 + sizeof( client_hdr ) ) ) {
425 setCompat( mExtSettings );
426 fprintf( stderr, warn_implied_compatibility, option );
432 case 'm': // print TCP MSS
433 setPrintMSS( mExtSettings );
436 case 'n': // bytes of data
437 // amount mode (instead of time mode)
438 unsetModeTime( mExtSettings );
439 Settings_GetUpperCaseArg(optarg,outarg);
440 mExtSettings->mAmount = byte_atoi( outarg );
443 case 'o' : // output the report and other messages into the file
444 unsetSTDOUT( mExtSettings );
445 mExtSettings->mOutputFileName = new char[strlen(optarg)+1];
446 strcpy( mExtSettings->mOutputFileName, optarg);
449 case 'p': // server port
450 mExtSettings->mPort = atoi( optarg );
453 case 'r': // test mode tradeoff
454 if ( mExtSettings->mThreadMode != kMode_Client ) {
455 fprintf( stderr, warn_invalid_server_option, option );
458 if ( isCompat( mExtSettings ) ) {
459 fprintf( stderr, warn_invalid_compatibility_option, option );
462 mExtSettings->mMode = kTest_TradeOff;
465 case 's': // server mode
466 if ( mExtSettings->mThreadMode != kMode_Unknown ) {
467 fprintf( stderr, warn_invalid_client_option, option );
471 mExtSettings->mThreadMode = kMode_Listener;
474 case 't': // seconds to write for
475 // time mode (instead of amount mode)
476 setModeTime( mExtSettings );
477 mExtSettings->mAmount = (int) (atof( optarg ) * 100.0);
480 case 'u': // UDP(-Lite) instead of TCP
482 mExtSettings->mProtocol = kProto_UDPLITE;
483 // Set partial checksum coverage:
484 // - 0 means entire datagram,
485 // - 1..7 is illegal and will be rounded up to 8;
486 // - 8 and greater mean genuine partial coverage.
487 mExtSettings->cscov = atoi(optarg);
489 mExtSettings->mProtocol = kProto_UDP;
491 setPacketOriented(mExtSettings);
492 // if -b has already been processed, UDP rate will
493 // already be non-zero, so don't overwrite that value
494 if ( mExtSettings->mDgramRate == 0 )
495 mExtSettings->mDgramRate = kDefault_DgramRate;
497 // if -l has already been processed, mBufLenSet is true
498 // so don't overwrite that value.
499 if ( !isBuflenSet( mExtSettings ) ) {
500 mExtSettings->mBufLen = kDefault_UDPBufLen;
501 } else if ( mExtSettings->mBufLen < (int) ( sizeof( dgram_record )
502 + sizeof( client_hdr ) ) &&
503 !isCompat( mExtSettings ) ) {
504 setCompat( mExtSettings );
505 fprintf( stderr, warn_implied_compatibility, option );
509 case 'v': // print version and exit
512 case 'w': // TCP window size or socket send-buffer size (UDP/DCCP)
513 Settings_GetUpperCaseArg(optarg,outarg);
514 mExtSettings->mWinSize = byte_atoi(outarg);
517 case 'x': // Limit Reports
518 while ( *optarg != '\0' ) {
522 setNoSettReport( mExtSettings );
526 setNoConnReport( mExtSettings );
530 setNoDataReport( mExtSettings );
534 setNoServReport( mExtSettings );
538 setNoMultReport( mExtSettings );
541 fprintf(stderr, warn_invalid_report, *optarg);
547 case 'y': // Reporting Style
551 mExtSettings->mReportMode = kReport_CSV;
554 fprintf( stderr, warn_invalid_report_style, optarg );
559 // more esoteric options
560 case 'A': // set TCP congestion control algorithm
561 mExtSettings->congAlgo = new char[ strlen( optarg ) + 1 ];
562 strcpy( mExtSettings->congAlgo, optarg );
565 case 'B': // specify bind address
566 mExtSettings->mLocalhost = new char[ strlen( optarg ) + 1 ];
567 strcpy( mExtSettings->mLocalhost, optarg );
570 case 'C': // Run in Compatibility Mode
571 setCompat( mExtSettings );
572 if ( mExtSettings->mMode != kTest_Normal ) {
573 fprintf( stderr, warn_invalid_compatibility_option,
574 ( mExtSettings->mMode == kTest_DualTest ?
576 mExtSettings->mMode = kTest_Normal;
580 case 'D': // Run as a daemon
581 setDaemon( mExtSettings );
584 case 'F' : // Get the input for the data stream from a file
585 if ( mExtSettings->mThreadMode != kMode_Client ) {
586 fprintf( stderr, warn_invalid_server_option, option );
590 setFileInput( mExtSettings );
591 mExtSettings->mFileName = new char[strlen(optarg)+1];
592 strcpy( mExtSettings->mFileName, optarg);
595 case 'I' : // Set the stdin as the input source
596 if ( mExtSettings->mThreadMode != kMode_Client ) {
597 fprintf( stderr, warn_invalid_server_option, option );
601 setFileInput( mExtSettings );
602 setSTDIN( mExtSettings );
603 mExtSettings->mFileName = new char[strlen("<stdin>")+1];
604 strcpy( mExtSettings->mFileName,"<stdin>");
607 case 'L': // Listen Port (bidirectional testing client-side)
608 if ( mExtSettings->mThreadMode != kMode_Client ) {
609 fprintf( stderr, warn_invalid_server_option, option );
613 mExtSettings->mListenPort = atoi( optarg );
616 case 'M': // specify TCP MSS (maximum segment size)
617 Settings_GetUpperCaseArg(optarg,outarg);
619 mExtSettings->mMSS = byte_atoi( outarg );
622 case 'N': // specify TCP nodelay option (disable Jacobson's Algorithm)
623 setNoDelay( mExtSettings );
626 case 'P': // number of client threads
628 mExtSettings->mThreads = atoi( optarg );
630 if ( mExtSettings->mThreadMode != kMode_Server ) {
631 fprintf( stderr, warn_invalid_single_threaded, option );
633 mExtSettings->mThreads = atoi( optarg );
639 setRemoveService( mExtSettings );
643 // Convert into IPv4/v6 6-bit DiffServ codepoint. If string
644 // - consists of six 0/1 digits, it is seen as binary number;
645 // - is preceded by `0x', it is interpreted as hex number;
646 // - is preceded by `0', it is interpreted as octal number;
647 // - otherwise it is interpreted as decimal number.
648 // The maximum possible 6-bit value is 252 (0xfc).
649 if ( strspn(optarg, "01") == 6 )
650 mExtSettings->mTOS = strtol(optarg, NULL, 2);
652 mExtSettings->mTOS = strtol(optarg, NULL, 0);
653 if ( mExtSettings->mTOS < 0 || mExtSettings->mTOS > 0xfc )
654 die("Invalid DiffServ codepoint %s", optarg);
655 mExtSettings->mTOS <<= 2;
658 case 'T': // time-to-live for multicast
659 mExtSettings->mTTL = atoi( optarg );
662 case 'V': // IP Domain: the optional ar
663 mExtSettings->mSockAF = AF_INET6;
664 if ( optarg && optarg[0] == '4' )
665 mExtSettings->mSockAF = AF_INET;
667 case 'U': // single threaded UDP server
668 setSingleUDP( mExtSettings );
672 setSuggestWin( mExtSettings );
673 fprintf( stderr, "The -W option is not available in this release\n");
676 case 'Z': //DCCP CCID
677 mExtSettings->mCCID=atoi(optarg);
678 if(mExtSettings->mCCID > 255 || mExtSettings->mCCID<=0){
679 fprintf( stderr, "CCID %s is invalid\n", optarg);
683 case 'O': //Bind Port
684 mExtSettings->mBindPort=atoi(optarg);
685 if(mExtSettings->mBindPort <0 || mExtSettings->mBindPort > 65535){
686 fprintf( stderr, "Bind Port %s is invalid\n", optarg);
690 default: // ignore unknown
695 void Settings_GetUpperCaseArg(const char *inarg, char *outarg) {
697 int len = strlen(inarg);
698 strcpy(outarg,inarg);
700 if ( (len > 0) && (inarg[len-1] >='a')
701 && (inarg[len-1] <= 'z') )
702 outarg[len-1]= outarg[len-1]+'A'-'a';
705 void Settings_GetLowerCaseArg(const char *inarg, char *outarg) {
707 int len = strlen(inarg);
708 strcpy(outarg,inarg);
710 if ( (len > 0) && (inarg[len-1] >='A')
711 && (inarg[len-1] <= 'Z') )
712 outarg[len-1]= outarg[len-1]-'A'+'a';
716 * Settings_GenerateListenerSettings
717 * Called to generate the settings to be passed to the Listener
718 * instance that will handle dual testings from the client side
719 * this should only return an instance if it was called on
720 * the thread_Settings instance generated from the command line
721 * for client side execution
723 void Settings_GenerateListenerSettings( thread_Settings *client, thread_Settings **listener ) {
724 if ( !isCompat( client ) &&
725 (client->mMode == kTest_DualTest || client->mMode == kTest_TradeOff) ) {
726 *listener = new thread_Settings;
727 memcpy(*listener, client, sizeof( thread_Settings ));
728 setCompat( (*listener) );
729 unsetDaemon( (*listener) );
730 if ( client->mListenPort != 0 ) {
731 (*listener)->mPort = client->mListenPort;
733 (*listener)->mPort = client->mPort;
735 (*listener)->mFileName = NULL;
736 (*listener)->mHost = NULL;
737 (*listener)->mLocalhost = NULL;
738 (*listener)->mOutputFileName = NULL;
739 (*listener)->mMode = kTest_Normal;
740 (*listener)->mThreadMode = kMode_Listener;
741 if ( client->mHost != NULL ) {
742 (*listener)->mHost = new char[strlen( client->mHost ) + 1];
743 strcpy( (*listener)->mHost, client->mHost );
745 if ( client->mLocalhost != NULL ) {
746 (*listener)->mLocalhost = new char[strlen( client->mLocalhost ) + 1];
747 strcpy( (*listener)->mLocalhost, client->mLocalhost );
755 * Settings_GenerateSpeakerSettings
756 * Called to generate the settings to be passed to the Speaker
757 * instance that will handle dual testings from the server side
758 * this should only return an instance if it was called on
759 * the thread_Settings instance generated from the command line
760 * for server side execution. This should be an inverse operation
761 * of GenerateClientHdr.
763 void Settings_GenerateClientSettings( thread_Settings *server,
764 thread_Settings **client,
766 int flags = ntohl(hdr->flags);
767 if ( (flags & HEADER_VERSION1) != 0 ) {
768 *client = new thread_Settings;
769 memcpy(*client, server, sizeof( thread_Settings ));
770 setCompat( (*client) );
771 (*client)->mTID = thread_zeroid();
772 (*client)->mPort = (unsigned short) ntohl(hdr->mPort);
773 (*client)->mThreads = ntohl(hdr->numThreads);
774 if ( hdr->bufferlen != 0 ) {
775 (*client)->mBufLen = ntohl(hdr->bufferlen);
777 if ( hdr->mWinBand != 0 ) {
778 if ( isPacketOriented( server ) ) {
779 (*client)->mDgramRate = ntohl(hdr->mWinBand);
781 (*client)->mWinSize = ntohl(hdr->mWinBand);
784 (*client)->mAmount = ntohl(hdr->mAmount);
785 if ( ((*client)->mAmount & 0x80000000) > 0 ) {
786 setModeTime( (*client) );
787 (*client)->mAmount |= 0xFFFFFFFF00000000LL;
788 (*client)->mAmount = -(*client)->mAmount;
790 (*client)->mFileName = NULL;
791 (*client)->mHost = NULL;
792 (*client)->mLocalhost = NULL;
793 (*client)->mOutputFileName = NULL;
794 (*client)->mMode = ((flags & RUN_NOW) == 0 ?
795 kTest_TradeOff : kTest_DualTest);
796 (*client)->mThreadMode = kMode_Client;
797 if ( server->mLocalhost != NULL ) {
798 (*client)->mLocalhost = new char[strlen( server->mLocalhost ) + 1];
799 strcpy( (*client)->mLocalhost, server->mLocalhost );
801 (*client)->mHost = new char[REPORT_ADDRLEN];
802 SockAddr_name(&server->peer, (*client)->mHost, REPORT_ADDRLEN);
809 * Settings_GenerateClientHdr
810 * Called to generate the client header to be passed to the
811 * server that will handle dual testings from the server side
812 * This should be an inverse operation of GenerateSpeakerSettings
814 void Settings_GenerateClientHdr( thread_Settings *client, client_hdr *hdr ) {
815 if ( client->mMode != kTest_Normal ) {
816 hdr->flags = htonl(HEADER_VERSION1);
820 if ( isBuflenSet( client ) ) {
821 hdr->bufferlen = htonl(client->mBufLen);
825 if ( isPacketOriented( client ) ) {
826 hdr->mWinBand = htonl(client->mDgramRate);
828 hdr->mWinBand = htonl(client->mWinSize);
830 if ( client->mListenPort != 0 ) {
831 hdr->mPort = htonl(client->mListenPort);
833 hdr->mPort = htonl(client->mPort);
835 hdr->numThreads = htonl(client->mThreads);
836 if ( isModeTime( client ) ) {
837 hdr->mAmount = htonl(-(long)client->mAmount);
839 hdr->mAmount = htonl((long)client->mAmount);
840 hdr->mAmount &= htonl( 0x7FFFFFFF );
842 if ( client->mMode == kTest_DualTest ) {
843 hdr->flags |= htonl(RUN_NOW);