Beispiel #1
0
void CloseListenSD( void )
{
	g_StopListenTh = 1;
	pthread_join(SDTid, NULL);
	SDTid = thread_zeroid();
	close( hotplug_sock );
}
Beispiel #2
0
/*
 * 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;
    }
}
Beispiel #3
0
/**
* @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;
}
Beispiel #4
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
Beispiel #6
0
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;
}
Beispiel #7
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
Beispiel #9
0
/* -------------------------------------------------------------------
 * 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
Beispiel #10
0
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;
}
Beispiel #11
0
/* -------------------------------------------------------------------
 * 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
Beispiel #12
0
/* -------------------------------------------------------------------
 * 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
Beispiel #13
0
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);
    }
}