void CloseListenSD( void ) { g_StopListenTh = 1; pthread_join(SDTid, NULL); SDTid = thread_zeroid(); close( hotplug_sock ); }
/* * Settings_GenerateSpeakerSettings * Called to generate the settings to be passed to the Speaker * instance that will handle dual testings from the server side * this should only return an instance if it was called on * the thread_Settings instance generated from the command line * for server side execution. This should be an inverse operation * of GenerateClientHdr. */ void Settings_GenerateClientSettings( thread_Settings *server, thread_Settings **client, client_hdr *hdr ) { int flags = ntohl(hdr->flags); if ( (flags & HEADER_VERSION1) != 0 ) { *client = new thread_Settings; memcpy(*client, server, sizeof( thread_Settings )); setCompat( (*client) ); (*client)->mTID = thread_zeroid(); (*client)->mPort = (unsigned short) ntohl(hdr->mPort); (*client)->mThreads = ntohl(hdr->numThreads); if ( hdr->bufferlen != 0 ) { (*client)->mBufLen = ntohl(hdr->bufferlen); } if ( hdr->mWinBand != 0 ) { if ( isUDP( server ) ) { (*client)->mUDPRate = ntohl(hdr->mWinBand); } else { (*client)->mTCPWin = ntohl(hdr->mWinBand); } } (*client)->mAmount = ntohl(hdr->mAmount); if ( ((*client)->mAmount & 0x80000000) > 0 ) { setModeTime( (*client) ); #ifndef WIN32 (*client)->mAmount |= 0xFFFFFFFF00000000LL; #else (*client)->mAmount |= 0xFFFFFFFF00000000; #endif (*client)->mAmount = -(*client)->mAmount; } (*client)->mFileName = NULL; (*client)->mHost = NULL; (*client)->mLocalhost = NULL; (*client)->mOutputFileName = NULL; (*client)->mMode = ((flags & RUN_NOW) == 0 ? kTest_TradeOff : kTest_DualTest); (*client)->mThreadMode = kMode_Client; if ( server->mLocalhost != NULL ) { (*client)->mLocalhost = new char[strlen( server->mLocalhost ) + 1]; strcpy( (*client)->mLocalhost, server->mLocalhost ); } (*client)->mHost = new char[REPORT_ADDRLEN]; if ( ((sockaddr*)&server->peer)->sa_family == AF_INET ) { inet_ntop( AF_INET, &((sockaddr_in*)&server->peer)->sin_addr, (*client)->mHost, REPORT_ADDRLEN); } #ifdef HAVE_IPV6 else { inet_ntop( AF_INET6, &((sockaddr_in6*)&server->peer)->sin6_addr, (*client)->mHost, REPORT_ADDRLEN); } #endif } else { *client = NULL; } }
/** * @brief stop to get pcm from ad * * @author dengzhou * @date 2013-04-07 * @param[in] * @return T_S32 * @retval if return 0 success, otherwise failed */ int audio_stop(void) { gaudio.bIsStop = AK_TRUE; //wait capture thread return pthread_join(gaudio.TID, NULL); gaudio.TID = thread_zeroid(); audio_process_close(); return 0; }
/* ------------------------------------------------------------------- * Start the specified object's thread execution. Increments thread * count, spawns new thread, and stores thread ID. * ------------------------------------------------------------------- */ void thread_start( struct thread_Settings* thread ) { // Make sure this object has not been started already if ( thread_equalid( thread->mTID, thread_zeroid() ) ) { // Check if we need to start another thread before this one if ( thread->runNow != NULL ) { thread_start( thread->runNow ); } // increment thread count Condition_Lock( thread_sNum_cond ); thread_sNum++; Condition_Unlock( thread_sNum_cond ); #if defined( HAVE_POSIX_THREAD ) // pthreads -- spawn new thread if ( pthread_create( &thread->mTID, NULL, thread_run_wrapper, thread ) != 0 ) { WARN( 1, "pthread_create" ); // decrement thread count Condition_Lock( thread_sNum_cond ); thread_sNum--; Condition_Unlock( thread_sNum_cond ); } #elif defined( HAVE_WIN32_THREAD ) // Win32 threads -- spawn new thread // Win32 has a thread handle in addition to the thread ID thread->mHandle = CreateThread( NULL, 0, thread_run_wrapper, thread, 0, &thread->mTID ); if ( thread->mHandle == NULL ) { WARN( 1, "CreateThread" ); // decrement thread count Condition_Lock( thread_sNum_cond ); thread_sNum--; Condition_Unlock( thread_sNum_cond ); } #else // single-threaded -- call Run_Wrapper in this thread thread_run_wrapper( thread ); #endif } } // end thread_start
/* ------------------------------------------------------------------- * Stop the specified object's thread execution (if any) immediately. * Decrements thread count and resets the thread ID. * ------------------------------------------------------------------- */ void thread_stop( struct thread_Settings* thread ) { #ifdef HAVE_THREAD // Make sure we have been started if ( ! thread_equalid( thread->mTID, thread_zeroid() ) ) { // decrement thread count Condition_Lock( thread_sNum_cond ); IPERF_DEBUGF( THREAD_DEBUG | IPERF_DBG_TRACE, ( "Decrementing thread count from %d to %d.\r\n", thread_sNum, (thread_sNum - 1) ) ); thread_sNum--; IPERF_DEBUGF( CONDITION_DEBUG | IPERF_DBG_TRACE, ( "Signaling thread_sNum_cond condition.\r\n" ) ); Condition_Signal( &thread_sNum_cond ); Condition_Unlock( thread_sNum_cond ); // use exit() if called from within this thread // use cancel() if called from a different thread if ( thread_equalid( thread_getid(), thread->mTID ) ) { // Destroy the object Settings_Destroy( thread ); // Exit #if defined( HAVE_POSIX_THREAD ) IPERF_DEBUGF( THREAD_DEBUG | IPERF_DBG_TRACE, ( "Exiting %s thread.\r\n", thread_names[thread->mThreadMode] ) ); pthread_exit( NULL ); #elif defined( HAVE_WIN32_THREAD ) IPERF_DEBUGF( THREAD_DEBUG | IPERF_DBG_TRACE, ( "Exiting %s thread.\r\n", thread_names[thread->mThreadMode] ) ); CloseHandle( thread->mHandle ); ExitThread( 0 ); #endif /* HAVE_POSIX_THREAD */ } else { // Cancel #if defined( HAVE_POSIX_THREAD ) // Cray J90 doesn't have pthread_cancel; Iperf works okay without #ifdef HAVE_PTHREAD_CANCEL IPERF_DEBUGF( THREAD_DEBUG | IPERF_DBG_TRACE, ( "Canceling %s thread.\r\n", thread_names[thread->mThreadMode] ) ); pthread_cancel( thread->mTID ); #endif /* HAVE_PTHREAD_CANCEL */ #elif defined(HAVE_WIN32_THREAD) // this is a somewhat dangerous function; it's not // suggested to Stop() threads a lot. IPERF_DEBUGF( THREAD_DEBUG | IPERF_DBG_TRACE, ( "Terminating %s thread.\r\n", thread_names[thread->mThreadMode] ) ); TerminateThread( thread->mHandle, 0 ); #endif /* HAVE_POSIX_THREAD */ // Destroy the object only after killing the thread Settings_Destroy( thread ); } } #endif /* HAVE_THREAD */ } // end thread_stop
int mux_exit( void ) { if (hMedia == AK_NULL) return 0; g_mux_exit = 1; printf("mux process close \n"); //wait capture thread return pthread_join(ThredMuxID, NULL); ThredMuxID = thread_zeroid(); mux_close(); CloseRecordManager(); CloseListenSD(); return 0; }
/* ------------------------------------------------------------------- * Stop the specified object's thread execution (if any) immediately. * Decrements thread count and resets the thread ID. * ------------------------------------------------------------------- */ void thread_stop( struct thread_Settings* thread ) { #ifdef HAVE_THREAD // Make sure we have been started if ( ! thread_equalid( thread->mTID, thread_zeroid() ) ) { // decrement thread count Condition_Lock( thread_sNum_cond ); thread_sNum--; Condition_Signal( &thread_sNum_cond ); Condition_Unlock( thread_sNum_cond ); // use exit() if called from within this thread // use cancel() if called from a different thread if ( thread_equalid( thread_getid(), thread->mTID ) ) { // Destroy the object Settings_Destroy( thread ); // Exit #if defined( HAVE_POSIX_THREAD ) pthread_exit( NULL ); #else // Win32 CloseHandle( thread->mHandle ); ExitThread( 0 ); #endif } else { // Cancel #if defined( HAVE_POSIX_THREAD ) // Cray J90 doesn't have pthread_cancel; Iperf works okay without #ifdef HAVE_PTHREAD_CANCEL pthread_cancel( thread->mTID ); #endif #else // Win32 // this is a somewhat dangerous function; it's not // suggested to Stop() threads a lot. TerminateThread( thread->mHandle, 0 ); #endif // Destroy the object only after killing the thread Settings_Destroy( thread ); } } #endif } // end Stop
/* ------------------------------------------------------------------- * Start the specified object's thread execution. Increments thread * count, spawns new thread, and stores thread ID. * ------------------------------------------------------------------- */ void thread_start( struct thread_Settings* thread ) { // Make sure this object has not been started already if ( thread_equalid( thread->mTID, thread_zeroid() ) ) { // Check if we need to start another thread before this one if ( thread->runNow != NULL ) { thread_start( thread->runNow ); } // increment thread count Condition_Lock( thread_sNum_cond ); IPERF_DEBUGF( THREAD_DEBUG | IPERF_DBG_TRACE, ( "Incrementing thread count from %d to %d.\r\n", thread_sNum, (thread_sNum + 1) ) ); thread_sNum++; Condition_Unlock( thread_sNum_cond ); IPERF_DEBUGF( THREAD_DEBUG | IPERF_DBG_TRACE | IPERF_DBG_STATE, ( "Spawning %s thread.\r\n", thread_names[thread->mThreadMode] ) ); #if defined( HAVE_POSIX_THREAD ) // pthreads -- spawn new thread if ( pthread_create( &thread->mTID, NULL, thread_run_wrapper, thread ) != 0 ) { WARN( 1, ( "pthread_create failed!\r\n" ) ); // decrement thread count Condition_Lock( thread_sNum_cond ); IPERF_DEBUGF( THREAD_DEBUG | IPERF_DBG_TRACE, ( "Decrementing thread count from %d to %d.\r\n", thread_sNum, (thread_sNum - 1) ) ); thread_sNum--; Condition_Unlock( thread_sNum_cond ); } #elif defined( HAVE_WIN32_THREAD ) // Win32 threads -- spawn new thread // Win32 has a thread handle in addition to the thread ID thread->mHandle = CreateThread( NULL, 0, thread_run_wrapper, thread, 0, &thread->mTID ); if ( thread->mHandle == NULL ) { WARN( 1, ( "CreateThread failed!\r\n" ) ); // decrement thread count Condition_Lock( thread_sNum_cond ); IPERF_DEBUGF( THREAD_DEBUG | IPERF_DBG_TRACE, ( "Decrementing thread count from %d to %d.\r\n", thread_sNum, (thread_sNum - 1) ) ); thread_sNum--; Condition_Unlock( thread_sNum_cond ); } #else // single-threaded -- call Run_Wrapper in this thread thread_run_wrapper( thread ); #endif /* HAVE_POSIX_THREAD */ } } // end thread_start
/* ------------------------------------------------------------------- * Signal handler sets the sInterupted flag, so the object can * respond appropriately.. [static] * ------------------------------------------------------------------- */ void Sig_Interupt( int inSigno ) { #ifdef HAVE_THREAD // We try to not allow a single interrupt handled by multiple threads // to completely kill the app so we save off the first thread ID // then that is the only thread that can supply the next interrupt if ( thread_equalid( sThread, thread_zeroid() ) ) { sThread = thread_getid(); } else if ( thread_equalid( sThread, thread_getid() ) ) { sig_exit( inSigno ); } // global variable used by threads to see if they were interrupted sInterupted = 1; // with threads, stop waiting for non-terminating threads // (ie Listener Thread) thread_release_nonterm( 1 ); #else // without threads, just exit quietly, same as sig_exit() sig_exit( inSigno ); #endif /* HAVE_THREAD */ } // end Sig_Interupt
void Settings_Copy( thread_Settings *from, thread_Settings **into ) { *into = new thread_Settings; memcpy( *into, from, sizeof(thread_Settings) ); if ( from->mHost != NULL ) { (*into)->mHost = new char[ strlen(from->mHost) + 1]; strcpy( (*into)->mHost, from->mHost ); } if ( from->mOutputFileName != NULL ) { (*into)->mOutputFileName = new char[ strlen(from->mOutputFileName) + 1]; strcpy( (*into)->mOutputFileName, from->mOutputFileName ); } if ( from->mLocalhost != NULL ) { (*into)->mLocalhost = new char[ strlen(from->mLocalhost) + 1]; strcpy( (*into)->mLocalhost, from->mLocalhost ); } if ( from->mFileName != NULL ) { (*into)->mFileName = new char[ strlen(from->mFileName) + 1]; strcpy( (*into)->mFileName, from->mFileName ); } // Zero out certain entries (*into)->mTID = thread_zeroid(); (*into)->runNext = NULL; (*into)->runNow = NULL; }
/* ------------------------------------------------------------------- * main() * Entry point into Iperf * * sets up signal handlers * initialize global locks and conditions * parses settings from environment and command line * starts up server or client thread * waits for all threads to complete * ------------------------------------------------------------------- */ int main( int argc, char **argv ) { #ifdef WIN32 // Start winsock WSADATA wsaData; int rc; #endif // Set SIGTERM and SIGINT to call our user interrupt function my_signal( SIGTERM, Sig_Interupt ); my_signal( SIGINT, Sig_Interupt ); #ifndef WIN32 // SIGALRM=14, _NSIG=3... my_signal( SIGALRM, Sig_Interupt ); #endif #ifndef WIN32 // Ignore broken pipes signal(SIGPIPE,SIG_IGN); #endif #ifdef WIN32 // Start winsock rc = WSAStartup( 0x202, &wsaData ); WARN_errno( rc == SOCKET_ERROR, "WSAStartup" ); if (rc == SOCKET_ERROR) return 0; // Tell windows we want to handle our own signals SetConsoleCtrlHandler( sig_dispatcher, true ); #endif // Initialize global mutexes and conditions Condition_Initialize ( &ReportCond ); Condition_Initialize ( &ReportDoneCond ); Mutex_Initialize( &groupCond ); Mutex_Initialize( &clients_mutex ); // Initialize the thread subsystem thread_init( ); // Initialize the interrupt handling thread to 0 sThread = thread_zeroid(); // perform any cleanup when quitting Iperf atexit( cleanup ); // Allocate the "global" settings thread_Settings* ext_gSettings = new thread_Settings; // Initialize settings to defaults Settings_Initialize( ext_gSettings ); // read settings from environment variables Settings_ParseEnvironment( ext_gSettings ); // read settings from command-line parameters Settings_ParseCommandLine( argc, argv, ext_gSettings ); // Check for either having specified client or server if ( ext_gSettings->mThreadMode == kMode_Client || ext_gSettings->mThreadMode == kMode_Listener ) { #ifdef WIN32 // Start the server as a daemon // Daemon mode for non-windows in handled // in the listener_spawn function if ( isDaemon( ext_gSettings ) ) { CmdInstallService(argc, argv); return 0; } // Remove the Windows service if requested if ( isRemoveService( ext_gSettings ) ) { // remove the service if ( CmdRemoveService() ) { fprintf(stderr, "IPerf Service is removed.\n"); return 0; } } #endif // initialize client(s) if ( ext_gSettings->mThreadMode == kMode_Client ) { client_init( ext_gSettings ); } #ifdef HAVE_THREAD // start up the reporter and client(s) or listener { thread_Settings *into = NULL; // Create the settings structure for the reporter thread Settings_Copy( ext_gSettings, &into ); into->mThreadMode = kMode_Reporter; // Have the reporter launch the client or listener into->runNow = ext_gSettings; // Start all the threads that are ready to go thread_start( into ); } #else // No need to make a reporter thread because we don't have threads thread_start( ext_gSettings ); #endif } else { // neither server nor client mode was specified // print usage and exit #ifdef WIN32 // In Win32 we also attempt to start a previously defined service // Starting in 2.0 to restart a previously defined service // you must call iperf with "iperf -D" or using the environment variable SERVICE_TABLE_ENTRY dispatchTable[] = { { TEXT(SZSERVICENAME), (LPSERVICE_MAIN_FUNCTION)service_main}, { NULL, NULL} }; // Only attempt to start the service if "-D" was specified if ( !isDaemon(ext_gSettings) || // starting the service by SCM, there is no arguments will be passed in. // the arguments will pass into Service_Main entry. !StartServiceCtrlDispatcher(dispatchTable) ) // If the service failed to start then print usage #endif fprintf( stderr, usage_short, argv[0], argv[0] ); return 0; } // wait for other (client, server) threads to complete thread_joinall(); // all done! return 0; } // end main
/* ------------------------------------------------------------------- * main() * Entry point into Iperf * * sets up signal handlers * initialize global locks and conditions * parses settings from environment and command line * starts up server or client thread * waits for all threads to complete * ------------------------------------------------------------------- */ #ifdef __cplusplus extern "C" #endif /* __cplusplus */ int IPERF_MAIN( int argc, char **argv ) { #ifdef NO_EXIT should_exit = 0; #endif /* NO_EXIT */ #ifdef IPERF_DEBUG debug_init(); #endif /* IPERF_DEBUG */ #ifndef NO_INTERRUPTS #ifdef WIN32 setsigalrmfunc(call_sigalrm); #endif /* WIN32 */ // Set SIGTERM and SIGINT to call our user interrupt function my_signal( SIGTERM, Sig_Interupt ); my_signal( SIGINT, Sig_Interupt ); my_signal( SIGALRM, Sig_Interupt ); #ifndef WIN32 // Ignore broken pipes signal(SIGPIPE,SIG_IGN); #else // Start winsock WORD wVersionRequested; WSADATA wsaData; // Using MAKEWORD macro, Winsock version request 2.2 wVersionRequested = MAKEWORD(2, 2); int rc = WSAStartup( wVersionRequested, &wsaData ); WARN_errno( rc == SOCKET_ERROR, ( "WSAStartup failed.\n" ) ); if (rc != 0) { fprintf(stderr, "The Winsock DLL was not found!\n"); return 1; } /* * Confirm that the WinSock DLL supports 2.2. Note that if the DLL supports * versions greater than 2.2 in addition to 2.2, it will still return 2.2 in * wVersion since that is the version we requested. */ if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2 ) { /* Tell the user that we could not find a usable WinSock DLL. */ fprintf(stderr, "The DLL does not support the Winsock version %u.%u!\n", LOBYTE(wsaData.wVersion),HIBYTE(wsaData.wVersion)); WSACleanup(); return 1; } // Tell windows we want to handle our own signals SetConsoleCtrlHandler( sig_dispatcher, true ); #endif /* WIN32 */ #endif /* NO_INTERRUPTS */ // Initialize global mutexes and conditions IPERF_DEBUGF( CONDITION_DEBUG | IPERF_DBG_TRACE, ( "Initializing report condition.\n" ) ); Condition_Initialize ( &ReportCond ); IPERF_DEBUGF( CONDITION_DEBUG | IPERF_DBG_TRACE, ( "Initializing report done condition.\n" ) ); Condition_Initialize ( &ReportDoneCond ); IPERF_DEBUGF( MUTEX_DEBUG | IPERF_DBG_TRACE, ( "Initializing group condition mutex.\n" ) ); Mutex_Initialize( &groupCond ); IPERF_DEBUGF( MUTEX_DEBUG | IPERF_DBG_TRACE, ( "Initializing clients mutex.\n" ) ); Mutex_Initialize( &clients_mutex ); // Initialize the thread subsystem IPERF_DEBUGF( THREAD_DEBUG | IPERF_DBG_TRACE, ( "Initializing the thread subsystem.\n" ) ); thread_init( ); // Initialize the interrupt handling thread to 0 sThread = thread_zeroid(); #ifndef NO_EXIT // perform any cleanup when quitting Iperf atexit( cleanup ); #endif /* NO_EXIT */ // Allocate the "global" settings thread_Settings *ext_gSettings = (thread_Settings*) malloc( sizeof( thread_Settings ) ); FAIL( ext_gSettings == NULL, ( "Unable to allocate memory for thread_Settings ext_gSettings.\n" ), NULL ); IPERF_DEBUGF( MEMALLOC_DEBUG, IPERF_MEMALLOC_MSG( ext_gSettings, sizeof( thread_Settings ) ) ); // Initialize settings to defaults Settings_Initialize( ext_gSettings ); #ifndef NO_ENVIRONMENT // read settings from environment variables Settings_ParseEnvironment( ext_gSettings ); #endif /* NO_ENVIORNMENT */ // read settings from command-line parameters Settings_ParseCommandLine( argc, argv, ext_gSettings ); #ifdef NO_EXIT if (should_exit) { IPERF_DEBUGF( MEMFREE_DEBUG | IPERF_DBG_TRACE, IPERF_MEMFREE_MSG( ext_gSettings ) ); FREE_PTR( ext_gSettings ); IPERF_DEBUGF( CONDITION_DEBUG | IPERF_DBG_TRACE, ( "Destroying report condition.\n" ) ); Condition_Destroy( &ReportCond ); IPERF_DEBUGF( CONDITION_DEBUG | IPERF_DBG_TRACE, ( "Destroying report done condition.\n" ) ); Condition_Destroy( &ReportDoneCond ); IPERF_DEBUGF( MUTEX_DEBUG | IPERF_DBG_TRACE, ( "Destroying group condition mutex.\n" ) ); Mutex_Destroy( &groupCond ); IPERF_DEBUGF( MUTEX_DEBUG | IPERF_DBG_TRACE, ( "Destroying clients mutex.\n" ) ); Mutex_Destroy( &clients_mutex ); return 0; } #endif /* NO_EXIT */ // Check for either having specified client or server if ( ext_gSettings->mThreadMode == kMode_Client || ext_gSettings->mThreadMode == kMode_Listener ) { #ifdef WIN32 #ifndef NO_DAEMON // Start the server as a daemon // Daemon mode for non-windows in handled // in the listener_spawn function if ( isDaemon( ext_gSettings ) ) { CmdInstallService(argc, argv); return 0; } #endif /* NO_DAEMON */ #ifndef NO_SERVICE // Remove the Windows service if requested if ( isRemoveService( ext_gSettings ) ) { // remove the service if ( CmdRemoveService() ) { fprintf(stderr, "IPerf Service is removed.\n"); return 0; } } #endif /* NO_SERVICE */ #endif /* WIN32 */ // initialize client(s) if ( ext_gSettings->mThreadMode == kMode_Client ) { IPERF_DEBUGF( CLIENT_DEBUG | LISTENER_DEBUG | IPERF_DBG_TRACE, ( "Initializing client(s)...\n" ) ); client_init( ext_gSettings ); } #ifdef HAVE_THREAD // start up the reporter and client(s) or listener thread_Settings *into = NULL; // Create the settings structure for the reporter thread IPERF_DEBUGF( CLIENT_DEBUG | LISTENER_DEBUG | REPORTER_DEBUG | IPERF_DBG_TRACE, ( "Creating the settings structure for the reporter thread.\n" ) ); Settings_Copy( ext_gSettings, &into ); into->mThreadMode = kMode_Reporter; // Have the reporter launch the client or listener IPERF_DEBUGF( CLIENT_DEBUG | LISTENER_DEBUG | IPERF_DBG_TRACE, ( "Setting the reporter to launch the client or listener before launching itself.\n" ) ); into->runNow = ext_gSettings; // Start all the threads that are ready to go IPERF_DEBUGF( THREAD_DEBUG | IPERF_DBG_TRACE, ( "Starting all the threads...\n" ) ); thread_start( into ); #else // No need to make a reporter thread because we don't have threads IPERF_DEBUGF( THREAD_DEBUG | IPERF_DBG_TRACE, ( "Starting iperf in a single thread...\n" ) ); thread_start( ext_gSettings ); #endif /* HAVE_THREAD */ } else { // neither server nor client mode was specified // print usage and exit #ifdef WIN32 // In Win32 we also attempt to start a previously defined service // Starting in 2.0 to restart a previously defined service // you must call iperf with "iperf -D" or using the environment variable SERVICE_TABLE_ENTRY dispatchTable[] = { { TEXT((char *) SZSERVICENAME), (LPSERVICE_MAIN_FUNCTION)service_main}, { NULL, NULL} }; #ifndef NO_DAEMON // Only attempt to start the service if "-D" was specified if ( !isDaemon(ext_gSettings) || // starting the service by SCM, there is no arguments will be passed in. // the arguments will pass into Service_Main entry. !StartServiceCtrlDispatcher(dispatchTable) ) // If the service failed to start then print usage #endif /* NO_DAEMON */ #endif /* WIN32 */ fprintf( stderr, usage_short, argv[0], argv[0] ); return 0; } // wait for other (client, server) threads to complete // IPERF_DEBUGF( THREAD_DEBUG | IPERF_DBG_TRACE, ( "Waiting for other (client, server) threads to complete...\n" ) ); // thread_joinall(); #ifdef NO_EXIT /* We can't run the atexit function */ #ifdef WIN32 // Shutdown Winsock WSACleanup(); #endif /* WIN32 */ // clean up the list of clients Iperf_destroy ( &clients ); // shutdown the thread subsystem IPERF_DEBUGF( THREAD_DEBUG | IPERF_DBG_TRACE, ( "Deinitializing the thread subsystem.\n" ) ); IPERF_DEBUGF( CONDITION_DEBUG | IPERF_DBG_TRACE, ( "Destroying report condition.\n" ) ); Condition_Destroy( &ReportCond ); IPERF_DEBUGF( CONDITION_DEBUG | IPERF_DBG_TRACE, ( "Destroying report done condition.\n" ) ); Condition_Destroy( &ReportDoneCond ); IPERF_DEBUGF( MUTEX_DEBUG | IPERF_DBG_TRACE, ( "Destroying group condition mutex.\n" ) ); Mutex_Destroy( &groupCond ); IPERF_DEBUGF( MUTEX_DEBUG | IPERF_DBG_TRACE, ( "Destroying clients mutex.\n" ) ); Mutex_Destroy( &clients_mutex ); #ifdef IPERF_DEBUG debug_init(); #endif /* IPERF_DEBUG */ #endif /* NO_EXIT */ // all done! IPERF_DEBUGF( IPERF_DBG_TRACE | IPERF_DBG_STATE, ( "Done!\n" ) ); return 0; } // end main
void Settings_Interpret( char option, const char *optarg, thread_Settings *mExtSettings ) { char outarg[100]; switch ( option ) { case '1': // Single Client setSingleClient( mExtSettings ); break; case 'b': // UDP bandwidth #ifdef RINA if ( !isUDP( mExtSettings ) && !isRINA( mExtSettings ) ) { #else if ( !isUDP( mExtSettings ) ) { #endif fprintf( stderr, warn_implied_udp, option ); } if ( mExtSettings->mThreadMode != kMode_Client ) { fprintf( stderr, warn_invalid_server_option, option ); break; } Settings_GetLowerCaseArg(optarg,outarg); mExtSettings->mUDPRate = byte_atoi(outarg); #ifdef RINA if ( !isUDP( mExtSettings ) && !isRINA( mExtSettings ) ) #endif setUDP( mExtSettings ); // if -l has already been processed, mBufLenSet is true // so don't overwrite that value. if ( !isBuflenSet( mExtSettings ) ) { mExtSettings->mBufLen = kDefault_UDPBufLen; } break; case 'c': // client mode w/ server host to connect to mExtSettings->mHost = new char[ strlen( optarg ) + 1 ]; strcpy( mExtSettings->mHost, optarg ); if ( mExtSettings->mThreadMode == kMode_Unknown ) { // Test for Multicast iperf_sockaddr temp; SockAddr_setHostname( mExtSettings->mHost, &temp, (isIPV6( mExtSettings ) ? 1 : 0 )); if ( SockAddr_isMulticast( &temp ) ) { setMulticast( mExtSettings ); } mExtSettings->mThreadMode = kMode_Client; mExtSettings->mThreads = 1; } break; case 'd': // Dual-test Mode #ifdef RINA if ( isRINA( mExtSettings ) ) { fprintf( stderr, warn_invalid_rina_option, option ); break; } #endif if ( mExtSettings->mThreadMode != kMode_Client ) { fprintf( stderr, warn_invalid_server_option, option ); break; } if ( isCompat( mExtSettings ) ) { fprintf( stderr, warn_invalid_compatibility_option, option ); } #ifdef HAVE_THREAD mExtSettings->mMode = kTest_DualTest; #else fprintf( stderr, warn_invalid_single_threaded, option ); mExtSettings->mMode = kTest_TradeOff; #endif break; case 'f': // format to print in mExtSettings->mFormat = (*optarg); break; case 'h': // print help and exit fprintf(stderr, usage_long1); fprintf(stderr, usage_long2); exit(1); break; case 'i': // specify interval between periodic bw reports mExtSettings->mInterval = atof( optarg ); if ( mExtSettings->mInterval < 0.5 ) { fprintf (stderr, report_interval_small, mExtSettings->mInterval); mExtSettings->mInterval = 0.5; } break; case 'l': // length of each buffer Settings_GetUpperCaseArg(optarg,outarg); mExtSettings->mBufLen = byte_atoi( outarg ); setBuflenSet( mExtSettings ); #ifdef RINA if ( !isUDP( mExtSettings ) && !isRINA( mExtSettings ) ) { #else if ( !isUDP( mExtSettings ) ) { #endif if ( mExtSettings->mBufLen < (int) sizeof( client_hdr ) && !isCompat( mExtSettings ) ) { setCompat( mExtSettings ); fprintf( stderr, warn_implied_compatibility, option ); } } else { if ( mExtSettings->mBufLen < (int) sizeof( UDP_datagram ) ) { mExtSettings->mBufLen = sizeof( UDP_datagram ); fprintf( stderr, warn_buffer_too_small, mExtSettings->mBufLen ); } if ( !isCompat( mExtSettings ) && mExtSettings->mBufLen < (int) ( sizeof( UDP_datagram ) + sizeof( client_hdr ) ) ) { setCompat( mExtSettings ); fprintf( stderr, warn_implied_compatibility, option ); } } break; case 'm': // print TCP MSS setPrintMSS( mExtSettings ); break; case 'n': // bytes of data // amount mode (instead of time mode) unsetModeTime( mExtSettings ); Settings_GetUpperCaseArg(optarg,outarg); mExtSettings->mAmount = byte_atoi( outarg ); break; case 'o' : // output the report and other messages into the file unsetSTDOUT( mExtSettings ); mExtSettings->mOutputFileName = new char[strlen(optarg)+1]; strcpy( mExtSettings->mOutputFileName, optarg); break; case 'p': // server port mExtSettings->mPort = atoi( optarg ); break; case 'r': // test mode tradeoff if ( mExtSettings->mThreadMode != kMode_Client ) { fprintf( stderr, warn_invalid_server_option, option ); break; } if ( isCompat( mExtSettings ) ) { fprintf( stderr, warn_invalid_compatibility_option, option ); } mExtSettings->mMode = kTest_TradeOff; break; case 's': // server mode #ifdef RINA if ( mExtSettings->mThreadMode != kMode_Unknown && !isRINA( mExtSettings ) ) { #else if ( mExtSettings->mThreadMode != kMode_Unknown ) { #endif fprintf( stderr, warn_invalid_client_option, option ); break; } mExtSettings->mThreadMode = kMode_Listener; break; case 't': // seconds to write for // time mode (instead of amount mode) setModeTime( mExtSettings ); mExtSettings->mAmount = (int) (atof( optarg ) * 100.0); break; case 'u': // UDP instead of TCP // if -b has already been processed, UDP rate will // already be non-zero, so don't overwrite that value if ( !isUDP( mExtSettings ) ) { setUDP( mExtSettings ); #ifdef RINA unsetRINA( mExtSettings ); #endif mExtSettings->mUDPRate = kDefault_UDPRate; } // if -l has already been processed, mBufLenSet is true // so don't overwrite that value. if ( !isBuflenSet( mExtSettings ) ) { mExtSettings->mBufLen = kDefault_UDPBufLen; } else if ( mExtSettings->mBufLen < (int) ( sizeof( UDP_datagram ) + sizeof( client_hdr ) ) && !isCompat( mExtSettings ) ) { setCompat( mExtSettings ); fprintf( stderr, warn_implied_compatibility, option ); } break; case 'v': // print version and exit fprintf( stderr, version ); exit(1); break; case 'w': // TCP window size (socket buffer size) Settings_GetUpperCaseArg(optarg,outarg); mExtSettings->mTCPWin = byte_atoi(outarg); if ( mExtSettings->mTCPWin < 2048 ) { fprintf( stderr, warn_window_small, mExtSettings->mTCPWin ); } break; case 'x': // Limit Reports while ( *optarg != '\0' ) { switch ( *optarg ) { case 's': case 'S': setNoSettReport( mExtSettings ); break; case 'c': case 'C': setNoConnReport( mExtSettings ); break; case 'd': case 'D': setNoDataReport( mExtSettings ); break; case 'v': case 'V': setNoServReport( mExtSettings ); break; case 'm': case 'M': setNoMultReport( mExtSettings ); break; default: fprintf(stderr, warn_invalid_report, *optarg); } optarg++; } break; case 'y': // Reporting Style switch ( *optarg ) { case 'c': case 'C': mExtSettings->mReportMode = kReport_CSV; break; default: fprintf( stderr, warn_invalid_report_style, optarg ); } break; // more esoteric options #ifdef RINA case 'A': // RINA instead of UDP or TCP mExtSettings->mMode = kTest_Normal; // RINA don't work in dual mode setRINA( mExtSettings ); // if -b has already been processed, UDP rate will // already be non-zero, so don't overwrite that value if ( isUDP( mExtSettings ) ) { unsetUDP( mExtSettings ); } else { mExtSettings->mUDPRate = kDefault_UDPRate; } // if -l has already been processed, mBufLenSet is true // so don't overwrite that value. if ( !isBuflenSet( mExtSettings ) ) { mExtSettings->mBufLen = kDefault_UDPBufLen; } else if ( mExtSettings->mBufLen < (int) ( sizeof( UDP_datagram ) + sizeof( client_hdr ) ) && !isCompat( mExtSettings ) ) { setCompat( mExtSettings ); fprintf( stderr, warn_implied_compatibility, option ); } // if -s have not been used yet, consider the use of client mode if ( mExtSettings->mThreadMode == kMode_Unknown ) { mExtSettings->mThreadMode = kMode_Client; } rina::initialize("EMERG", ""); break; #endif case 'B': // specify bind address mExtSettings->mLocalhost = new char[ strlen( optarg ) + 1 ]; strcpy( mExtSettings->mLocalhost, optarg ); // Test for Multicast iperf_sockaddr temp; SockAddr_setHostname( mExtSettings->mLocalhost, &temp, (isIPV6( mExtSettings ) ? 1 : 0 )); if ( SockAddr_isMulticast( &temp ) ) { setMulticast( mExtSettings ); } break; case 'C': // Run in Compatibility Mode setCompat( mExtSettings ); if ( mExtSettings->mMode != kTest_Normal ) { fprintf( stderr, warn_invalid_compatibility_option, ( mExtSettings->mMode == kTest_DualTest ? 'd' : 'r' ) ); mExtSettings->mMode = kTest_Normal; } break; case 'D': // Run as a daemon setDaemon( mExtSettings ); break; case 'F' : // Get the input for the data stream from a file if ( mExtSettings->mThreadMode != kMode_Client ) { fprintf( stderr, warn_invalid_server_option, option ); break; } setFileInput( mExtSettings ); mExtSettings->mFileName = new char[strlen(optarg)+1]; strcpy( mExtSettings->mFileName, optarg); break; case 'I' : // Set the stdin as the input source if ( mExtSettings->mThreadMode != kMode_Client ) { fprintf( stderr, warn_invalid_server_option, option ); break; } setFileInput( mExtSettings ); setSTDIN( mExtSettings ); mExtSettings->mFileName = new char[strlen("<stdin>")+1]; strcpy( mExtSettings->mFileName,"<stdin>"); break; case 'L': // Listen Port (bidirectional testing client-side) if ( mExtSettings->mThreadMode != kMode_Client ) { fprintf( stderr, warn_invalid_server_option, option ); break; } mExtSettings->mListenPort = atoi( optarg ); break; case 'M': // specify TCP MSS (maximum segment size) Settings_GetUpperCaseArg(optarg,outarg); mExtSettings->mMSS = byte_atoi( outarg ); break; case 'N': // specify TCP nodelay option (disable Jacobson's Algorithm) setNoDelay( mExtSettings ); break; case 'P': // number of client threads #ifdef HAVE_THREAD mExtSettings->mThreads = atoi( optarg ); #else if ( mExtSettings->mThreadMode != kMode_Server ) { fprintf( stderr, warn_invalid_single_threaded, option ); } else { mExtSettings->mThreads = atoi( optarg ); } #endif break; case 'R': setRemoveService( mExtSettings ); break; case 'S': // IP type-of-service // TODO use a function that understands base-2 // the zero base here allows the user to specify // "0x#" hex, "0#" octal, and "#" decimal numbers mExtSettings->mTOS = strtol( optarg, NULL, 0 ); break; case 'T': // time-to-live for multicast mExtSettings->mTTL = atoi( optarg ); break; case 'U': // single threaded UDP server setSingleUDP( mExtSettings ); break; case 'V': // IPv6 Domain setIPV6( mExtSettings ); if ( mExtSettings->mThreadMode == kMode_Server && mExtSettings->mLocalhost != NULL ) { // Test for Multicast iperf_sockaddr temp; SockAddr_setHostname( mExtSettings->mLocalhost, &temp, 1); if ( SockAddr_isMulticast( &temp ) ) { setMulticast( mExtSettings ); } } else if ( mExtSettings->mThreadMode == kMode_Client ) { // Test for Multicast iperf_sockaddr temp; SockAddr_setHostname( mExtSettings->mHost, &temp, 1 ); if ( SockAddr_isMulticast( &temp ) ) { setMulticast( mExtSettings ); } } break; case 'W' : setSuggestWin( mExtSettings ); fprintf( stderr, "The -W option is not available in this release\n"); break; case 'Z': #ifdef TCP_CONGESTION setCongestionControl( mExtSettings ); mExtSettings->mCongestion = new char[strlen(optarg)+1]; strcpy( mExtSettings->mCongestion, optarg); #else fprintf( stderr, "The -Z option is not available on this operating system\n"); #endif break; default: // ignore unknown break; } } // end Interpret void Settings_GetUpperCaseArg(const char *inarg, char *outarg) { int len = strlen(inarg); strcpy(outarg,inarg); if ( (len > 0) && (inarg[len-1] >='a') && (inarg[len-1] <= 'z') ) outarg[len-1]= outarg[len-1]+'A'-'a'; } void Settings_GetLowerCaseArg(const char *inarg, char *outarg) { int len = strlen(inarg); strcpy(outarg,inarg); if ( (len > 0) && (inarg[len-1] >='A') && (inarg[len-1] <= 'Z') ) outarg[len-1]= outarg[len-1]-'A'+'a'; } /* * Settings_GenerateListenerSettings * Called to generate the settings to be passed to the Listener * instance that will handle dual testings from the client side * this should only return an instance if it was called on * the thread_Settings instance generated from the command line * for client side execution */ void Settings_GenerateListenerSettings( thread_Settings *client, thread_Settings **listener ) { if ( !isCompat( client ) && (client->mMode == kTest_DualTest || client->mMode == kTest_TradeOff) ) { *listener = new thread_Settings; memcpy(*listener, client, sizeof( thread_Settings )); setCompat( (*listener) ); unsetDaemon( (*listener) ); if ( client->mListenPort != 0 ) { (*listener)->mPort = client->mListenPort; } else { (*listener)->mPort = client->mPort; } (*listener)->mFileName = NULL; (*listener)->mHost = NULL; (*listener)->mLocalhost = NULL; (*listener)->mOutputFileName = NULL; (*listener)->mMode = kTest_Normal; (*listener)->mThreadMode = kMode_Listener; if ( client->mHost != NULL ) { (*listener)->mHost = new char[strlen( client->mHost ) + 1]; strcpy( (*listener)->mHost, client->mHost ); } if ( client->mLocalhost != NULL ) { (*listener)->mLocalhost = new char[strlen( client->mLocalhost ) + 1]; strcpy( (*listener)->mLocalhost, client->mLocalhost ); } } else { *listener = NULL; } } /* * Settings_GenerateSpeakerSettings * Called to generate the settings to be passed to the Speaker * instance that will handle dual testings from the server side * this should only return an instance if it was called on * the thread_Settings instance generated from the command line * for server side execution. This should be an inverse operation * of GenerateClientHdr. */ void Settings_GenerateClientSettings( thread_Settings *server, thread_Settings **client, client_hdr *hdr ) { int flags = ntohl(hdr->flags); if ( (flags & HEADER_VERSION1) != 0 ) { *client = new thread_Settings; memcpy(*client, server, sizeof( thread_Settings )); setCompat( (*client) ); (*client)->mTID = thread_zeroid(); (*client)->mPort = (unsigned short) ntohl(hdr->mPort); (*client)->mThreads = ntohl(hdr->numThreads); if ( hdr->bufferlen != 0 ) { (*client)->mBufLen = ntohl(hdr->bufferlen); } if ( hdr->mWinBand != 0 ) { #ifdef RINA if ( isUDP( server ) || isRINA( server ) ) { #else if ( isUDP( server ) ) { #endif (*client)->mUDPRate = ntohl(hdr->mWinBand); } else { (*client)->mTCPWin = ntohl(hdr->mWinBand); } } (*client)->mAmount = ntohl(hdr->mAmount); if ( ((*client)->mAmount & 0x80000000) > 0 ) { setModeTime( (*client) ); #ifndef WIN32 (*client)->mAmount |= 0xFFFFFFFF00000000LL; #else (*client)->mAmount |= 0xFFFFFFFF00000000; #endif (*client)->mAmount = -(*client)->mAmount; } (*client)->mFileName = NULL; (*client)->mHost = NULL; (*client)->mLocalhost = NULL; (*client)->mOutputFileName = NULL; (*client)->mMode = ((flags & RUN_NOW) == 0 ? kTest_TradeOff : kTest_DualTest); (*client)->mThreadMode = kMode_Client; if ( server->mLocalhost != NULL ) { (*client)->mLocalhost = new char[strlen( server->mLocalhost ) + 1]; strcpy( (*client)->mLocalhost, server->mLocalhost ); } (*client)->mHost = new char[REPORT_ADDRLEN]; if ( ((sockaddr*)&server->peer)->sa_family == AF_INET ) { inet_ntop( AF_INET, &((sockaddr_in*)&server->peer)->sin_addr, (*client)->mHost, REPORT_ADDRLEN); } #ifdef HAVE_IPV6 else { inet_ntop( AF_INET6, &((sockaddr_in6*)&server->peer)->sin6_addr, (*client)->mHost, REPORT_ADDRLEN); } #endif } else { *client = NULL; } } /* * Settings_GenerateClientHdr * Called to generate the client header to be passed to the * server that will handle dual testings from the server side * This should be an inverse operation of GenerateSpeakerSettings */ void Settings_GenerateClientHdr( thread_Settings *client, client_hdr *hdr ) { if ( client->mMode != kTest_Normal ) { hdr->flags = htonl(HEADER_VERSION1); } else { hdr->flags = 0; } if ( isBuflenSet( client ) ) { hdr->bufferlen = htonl(client->mBufLen); } else { hdr->bufferlen = 0; } #ifdef RINA if ( isUDP( client ) || isRINA( client ) ) { #else if ( isUDP( client ) ) { #endif hdr->mWinBand = htonl(client->mUDPRate); } else { hdr->mWinBand = htonl(client->mTCPWin); } if ( client->mListenPort != 0 ) { hdr->mPort = htonl(client->mListenPort); } else { hdr->mPort = htonl(client->mPort); } hdr->numThreads = htonl(client->mThreads); if ( isModeTime( client ) ) { hdr->mAmount = htonl(-(long)client->mAmount); } else { hdr->mAmount = htonl((long)client->mAmount); hdr->mAmount &= htonl( 0x7FFFFFFF ); } if ( client->mMode == kTest_DualTest ) { hdr->flags |= htonl(RUN_NOW); } }