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 * ________________________________________________________________
47 * by Mark Gates <mgates@nlanr.net>
48 * & Ajay Tirumala <tirumala@ncsa.uiuc.edu>
49 * -------------------------------------------------------------------
50 * main does initialization and creates the various objects that will
51 * actually run the iperf program, then waits in the Joinall().
52 * -------------------------------------------------------------------
59 * ------------------------------------------------------------------- */
65 #include "Settings.hpp"
66 #include "PerfSocket.hpp"
68 #include "Condition.h"
69 #include "Timestamp.hpp"
70 #include "Listener.hpp"
74 /* -------------------------------------------------------------------
76 * ------------------------------------------------------------------- */
77 // Function called at exit to clean up as much as possible
80 /* -------------------------------------------------------------------
82 * ------------------------------------------------------------------- */
84 // Global flag to signal a user interrupt
86 // Global ID that we increment to be used
87 // as identifier for SUM reports
89 // Mutex to protect access to the above ID
91 // Condition used to signify advances of the current
92 // records being accessed in a report and also to
93 // serialize modification of the report list
95 Condition ReportDoneCond;
98 // global variables only accessed within this file
100 // Thread that received the SIGTERM or SIGINT signal
101 // Used to ensure that if multiple threads receive the
102 // signal we do not prematurely exit
104 // The main thread uses this function to wait
105 // for all other threads to complete
106 void waitUntilQuit( void );
108 /* -------------------------------------------------------------------
110 * Entry point into Iperf
112 * sets up signal handlers
113 * initialize global locks and conditions
114 * parses settings from environment and command line
115 * starts up server or client thread
116 * waits for all threads to complete
117 * ------------------------------------------------------------------- */
118 int main( int argc, char **argv ) {
120 // Set SIGTERM and SIGINT to call our user interrupt function
121 my_signal( SIGTERM, Sig_Interupt );
122 my_signal( SIGINT, Sig_Interupt );
125 // Initialize global mutexes and conditions
126 Condition_Initialize ( &ReportCond );
127 Condition_Initialize ( &ReportDoneCond );
128 Mutex_Initialize( &groupCond );
129 Mutex_Initialize( &clients_mutex );
131 // Initialize the thread subsystem
134 // Initialize the interrupt handling thread to 0
135 sThread = thread_zeroid();
137 // perform any cleanup when quitting Iperf
140 // Allocate the "global" settings
141 thread_Settings* ext_gSettings = new thread_Settings;
143 // Initialize settings to defaults
144 Settings_Initialize( ext_gSettings );
145 // read settings from environment variables
146 Settings_ParseEnvironment( ext_gSettings );
147 // read settings from command-line parameters
148 Settings_ParseCommandLine( argc, argv, ext_gSettings );
150 if (isPacketOriented(ext_gSettings) &&
151 !(ext_gSettings->mProtocol == kProto_UDP ||
152 ext_gSettings->mProtocol == kProto_UDPLITE ||
153 ext_gSettings->mProtocol == kProto_DCCP ))
154 die("Can't use packet-oriented mode with these settings.");
156 if (isSingleUDP(ext_gSettings) && ext_gSettings->mProtocol != kProto_UDP) {
157 fprintf(stderr, "WARNING: option -U applies to UDP only, ignored!\n");
158 unsetSingleUDP(ext_gSettings);
161 if (!isModeTime(ext_gSettings) &&
162 (isConnectionLess(ext_gSettings) || isPacketOriented(ext_gSettings)))
163 die("Amount-oriented (-n) works only in non-packet-oriented mode.");
165 // Check for either having specified client or server
166 if ( ext_gSettings->mThreadMode == kMode_Client
167 || ext_gSettings->mThreadMode == kMode_Listener ) {
168 // initialize client(s)
169 if ( ext_gSettings->mThreadMode == kMode_Client ) {
170 client_init( ext_gSettings );
174 // start up the reporter and client(s) or listener
176 thread_Settings *into = NULL;
177 // Create the settings structure for the reporter thread
178 Settings_Copy( ext_gSettings, &into );
179 into->mThreadMode = kMode_Reporter;
181 // Have the reporter launch the client or listener
182 into->runNow = ext_gSettings;
184 // Start all the threads that are ready to go
185 thread_start( into );
188 // No need to make a reporter thread because we don't have threads
189 thread_start( ext_gSettings );
192 // neither server nor client mode was specified
193 // print usage and exit
195 fprintf( stderr, usage_short, argv[0], argv[0] );
200 // wait for other (client, server) threads to complete
207 /* -------------------------------------------------------------------
208 * Signal handler sets the sInterupted flag, so the object can
209 * respond appropriately.. [static]
210 * ------------------------------------------------------------------- */
212 void Sig_Interupt( int inSigno ) {
214 // We try to not allow a single interrupt handled by multiple threads
215 // to completely kill the app so we save off the first thread ID
216 // then that is the only thread that can supply the next interrupt
217 if ( thread_equalid( sThread, thread_zeroid() ) ) {
218 sThread = thread_getid();
219 } else if ( thread_equalid( sThread, thread_getid() ) ) {
223 // global variable used by threads to see if they were interrupted
226 // with threads, stop waiting for non-terminating threads
227 // (ie Listener Thread)
228 thread_release_nonterm( 1 );
231 // without threads, just exit quietly, same as sig_exit()
236 /* -------------------------------------------------------------------
237 * Any necesary cleanup before Iperf quits. Called at program exit,
238 * either by exit() or terminating main().
239 * ------------------------------------------------------------------- */
241 void cleanup( void ) {
242 // clean up the list of clients
243 Iperf_destroy ( &clients );
245 // shutdown the thread subsystem