Exemple #1
0
/*
 * Report the client or listener Settings in default style
 */
void reporter_reportsettings( ReporterData *data ) {
    int win, win_requested;

    win = getsock_tcp_windowsize( data->info.transferID,
                  (data->mThreadMode == kMode_Listener ? 0 : 1) );
    win_requested = data->mTCPWin;

    printf( seperator_line );
    if ( data->mThreadMode == kMode_Listener ) {
        printf( server_port,
                (isUDP( data ) ? "UDP" : "TCP"), 
                data->mPort );
    } else {
        printf( client_port,
                data->mHost,
                (isUDP( data ) ? "UDP" : "TCP"),
                data->mPort );
    }
    if ( data->mLocalhost != NULL ) {
        printf( bind_address, data->mLocalhost );
        if ( SockAddr_isMulticast( &data->connection.local ) ) {
            printf( join_multicast, data->mLocalhost );
        }
    }

    if ( isUDP( data ) ) {
        printf( (data->mThreadMode == kMode_Listener ? 
                                   server_datagram_size : client_datagram_size),
                data->mBufLen );
        if ( SockAddr_isMulticast( &data->connection.peer ) ) {
            printf( multicast_ttl, data->info.mTTL);
        }
    }
    byte_snprintf( buffer, sizeof(buffer), win,
                   toupper( data->info.mFormat));
    printf( "%s: %s", (isUDP( data ) ? 
                                udp_buffer_size : tcp_window_size), buffer );

    if ( win_requested == 0 ) {
        printf( " %s", window_default );
    } else if ( win != win_requested ) {
        byte_snprintf( buffer, sizeof(buffer), win_requested,
                       toupper( data->info.mFormat));
        printf( warn_window_requested, buffer );
    }
    printf( "\n" );
    printf( seperator_line );
}
Exemple #2
0
bool OutPacket::fill(unsigned char *buf, int *len) 
{
	int headerLen = 0, bodyLen=0, encryptedLen = 0;
	unsigned char *bodyBuf;
	unsigned char *encrypted;
	bodyBuf   = (unsigned char *)malloc(MAX_PACKET_SIZE* sizeof(unsigned char));
	encrypted = (unsigned char *)malloc(MAX_PACKET_SIZE * sizeof(unsigned char));
	
	headerLen = putHead(buf);	
	bodyLen   = putBody(bodyBuf);
	encryptedLen = bodyLen;
	encryptBody(bodyBuf, bodyLen, encrypted, &encryptedLen);
	
	memcpy(buf+headerLen, encrypted, encryptedLen);
	
	buf[ headerLen + encryptedLen ] = QQ_PACKET_TAIL;
	(*len) = headerLen + encryptedLen + 1;
	
	if(!isUDP()) { 
		short tmp2 = htons(*len);
		memcpy(buf, &tmp2, 2);
	}
	free(bodyBuf);
	free(encrypted);
	return true;
}
Exemple #3
0
int OutPacket::putHead(unsigned char *buf) 
{
	int pos=0;
	if(!isUDP()){
		buf[0]=buf[1]=0;
		pos+=2;
	}
	buf[pos++]=(unsigned char)QQ_PACKET_TAG;
	
	short tmp = htons(version);
	memcpy(buf+pos, &tmp, 2);
	pos+=2; 
	
	tmp = htons(command);
	memcpy(buf+pos, &tmp, 2);
	pos+=2; 

	tmp = htons(sequence);
	memcpy(buf+pos, &tmp, 2);
	pos+=2; 
	
	int id = htonl(getQQ());
	memcpy(buf+pos, &id, 4);
	pos+=4;
		
	return pos;
}
Exemple #4
0
/* -------------------------------------------------------------------
 * Listens for connections and starts Servers to handle data.
 * For TCP, each accepted connection spawns a Server thread.
 * For UDP, handle all data in this thread for Win32 Only, otherwise
 *          spawn a new Server thread.
 * ------------------------------------------------------------------- */
void Listener::Run( void ) {
#ifdef WIN32
    if ( isUDP( mSettings ) && !isSingleUDP( mSettings ) ) {
        UDPSingleServer();
    } else
#else
#ifdef sun
    if ( ( isUDP( mSettings ) &&
            isMulticast( mSettings ) &&
            !isSingleUDP( mSettings ) ) ||
            isSingleUDP( mSettings ) ) {
        UDPSingleServer();
    } else
#else if ( isSingleUDP( mSettings ) ) {
    UDPSingleServer();
} else
Exemple #5
0
/*
 * 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;
    }
    if ( isUDP( client ) ) {
        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);
    }
}
Exemple #6
0
/*
 * This function handles multiple format printing by sending to the
 * appropriate dispatch function
 */
int reporter_print( ReporterData *stats, int type, int end ) {
    switch ( type ) {
        case TRANSFER_REPORT:
            statistics_reports[stats->mode]( &stats->info );
            if ( end != 0 && isPrintMSS( stats ) && !isUDP( stats ) ) {
                PrintMSS( stats );
            }
            break;
        case SERVER_RELAY_REPORT:
            serverstatistics_reports[stats->mode]( &stats->connection, &stats->info );
            break;
        case SETTINGS_REPORT:
            settings_reports[stats->mode]( stats );
            break;
        case CONNECTION_REPORT:
            stats->info.reserved_delay = connection_reports[stats->mode]( 
                                               &stats->connection,
                                               stats->info.transferID );
            break;
        case MULTIPLE_REPORT:
            multiple_reports[stats->mode]( &stats->info );
            break;
        default:
            fprintf( stderr, "Printing type not implemented! No Output\n" );
    }
    fflush( stdout );
    return end;
}
Exemple #7
0
/*
 * Prints reports conditionally
 */
int reporter_condprintstats( ReporterData *stats, MultiHeader *multireport, int force ) {
    if ( force != 0 ) {
        stats->info.cntOutofOrder = stats->cntOutofOrder;
        // assume most of the time out-of-order packets are not
        // duplicate packets, so conditionally subtract them from the lost packets.
        stats->info.cntError = stats->cntError;
        if ( stats->info.cntError > stats->info.cntOutofOrder ) {
            stats->info.cntError -= stats->info.cntOutofOrder;
        }
        stats->info.cntDatagrams = (isUDP(stats) ? stats->PacketID : stats->cntDatagrams);
        stats->info.TotalLen = stats->TotalLen;
        stats->info.startTime = 0;
        stats->info.endTime = TimeDifference( stats->packetTime, stats->startTime );
        stats->info.free = 1;
        reporter_print( stats, TRANSFER_REPORT, force );
        if ( isMultipleReport(stats) ) {
            reporter_handle_multiple_reports( multireport, &stats->info, force );
        }
    } else while ((stats->intervalTime.tv_sec != 0 ||
                   stats->intervalTime.tv_usec != 0) &&
                  TimeDifference( stats->nextTime,
                                  stats->packetTime ) < 0 ) {
        stats->info.cntOutofOrder = stats->cntOutofOrder - stats->lastOutofOrder;
        stats->lastOutofOrder = stats->cntOutofOrder;
        // assume most of the time out-of-order packets are not
        // duplicate packets, so conditionally subtract them from the lost packets.
        stats->info.cntError = stats->cntError - stats->lastError;
        if ( stats->info.cntError > stats->info.cntOutofOrder ) {
            stats->info.cntError -= stats->info.cntOutofOrder;
        }
        stats->lastError = stats->cntError;
        stats->info.cntDatagrams = (isUDP( stats ) ? stats->PacketID - stats->lastDatagrams :
                                                     stats->cntDatagrams - stats->lastDatagrams);
        stats->lastDatagrams = (isUDP( stats ) ? stats->PacketID : stats->cntDatagrams);
        stats->info.TotalLen = stats->TotalLen - stats->lastTotal;
        stats->lastTotal = stats->TotalLen;
        stats->info.startTime = stats->info.endTime;
        stats->info.endTime = TimeDifference( stats->nextTime, stats->startTime );
        TimeAdd( stats->nextTime, stats->intervalTime );
        stats->info.free = 0;
        reporter_print( stats, TRANSFER_REPORT, force );
        if ( isMultipleReport(stats) ) {
            reporter_handle_multiple_reports( multireport, &stats->info, force );
        }
    }
    return force;
}
Exemple #8
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;
    }
}
Exemple #9
0
void Client::InitiateServer() {
    if ( !isCompat( mSettings ) ) {
        int currLen;
        client_hdr* temp_hdr;
        if ( isUDP( mSettings ) ) {
            UDP_datagram *UDPhdr = (UDP_datagram *)mBuf;
            temp_hdr = (client_hdr*)(UDPhdr + 1);
        } else {
            temp_hdr = (client_hdr*)mBuf;
        }
        Settings_GenerateClientHdr( mSettings, temp_hdr );
        if ( !isUDP( mSettings ) ) {
            currLen = send( mSettings->mSock, mBuf, sizeof(client_hdr), 0 );
            if ( currLen < 0 ) {
                WARN_errno( currLen < 0, "write1" );
            }
        }
    }
}
Exemple #10
0
void Client::Connect( ) {
    int rc;
    SockAddr_remoteAddr( mSettings );

    assert( mSettings->inHostname != NULL );

    // create an internet socket
    int type = ( isUDP( mSettings )  ?  SOCK_DGRAM : SOCK_STREAM);

    int domain = (SockAddr_isIPv6( &mSettings->peer ) ? 
#ifdef HAVE_IPV6
                  AF_INET6
#else
                  AF_INET
#endif
                  : AF_INET);

    mSettings->mSock = socket( domain, type, 0 );
    WARN_errno( mSettings->mSock == INVALID_SOCKET, "socket" );

    SetSocketOptions( mSettings );


    SockAddr_localAddr( mSettings );
    if ( mSettings->mLocalhost != NULL ) {
        // bind socket to local address
        char temp[100] = "cbind:";
        SockAddr_getHostAddress(&mSettings->local, &temp[6], 94);
        rc = bind( mSettings->mSock, (sockaddr*) &mSettings->local, 
                   SockAddr_get_sizeof_sockaddr( &mSettings->local ) );
        WARN_errno( rc == SOCKET_ERROR, temp );
    }

    // connect socket
    rc = connect( mSettings->mSock, (sockaddr*) &mSettings->peer, 
                  SockAddr_get_sizeof_sockaddr( &mSettings->peer ));
    FAIL_errno( rc == SOCKET_ERROR, "connect", mSettings );

    getsockname( mSettings->mSock, (sockaddr*) &mSettings->local, 
                 &mSettings->size_local );
    getpeername( mSettings->mSock, (sockaddr*) &mSettings->peer,
                 &mSettings->size_peer );
} // end Connect
Exemple #11
0
/*
 * 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 ) {
#ifdef SAME_TCP
    if ( (client->mMode == kTest_DualTest) || (client->mMode == kTest_TradeOff) || (client->mMode == kTest_SameTCP_TradeOff_ClientSide)) {
#else
    if ( client->mMode != kTest_Normal ) {
#endif
        hdr->flags  = htonl(HEADER_VERSION1);
    } else {
        hdr->flags  = 0;
    }
    if ( isBuflenSet( client ) ) {
        hdr->bufferlen = htonl(client->mBufLen);
    } else {
        hdr->bufferlen = 0;
    }
    if ( isUDP( client ) ) {
        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);
    }
#ifdef SAME_TCP
    if ( client->mMode == kTest_SameTCP_TradeOff_ClientSide ) {
        hdr->flags |= htonl(RUN_ON_SAME_TCP);
    }
#endif
}
Exemple #12
0
void Client::Run( void ) {
    struct UDP_datagram* mBuf_UDP = (struct UDP_datagram*) mBuf; 
    unsigned long currLen = 0; 

    int delay_target = 0; 
    int delay = 0; 
    int adjust = 0; 

    char* readAt = mBuf;

#if HAVE_THREAD
    if ( !isUDP( mSettings ) ) {
	RunTCP();
	return;
    }
#endif
    
    // Indicates if the stream is readable 
    bool canRead = true, mMode_Time = isModeTime( mSettings ); 

    // setup termination variables
    if ( mMode_Time ) {
        mEndTime.setnow();
        mEndTime.add( mSettings->mAmount / 100.0 );
    }

    if ( isUDP( mSettings ) ) {
        // Due to the UDP timestamps etc, included 
        // reduce the read size by an amount 
        // equal to the header size
    
        // compute delay for bandwidth restriction, constrained to [0,1] seconds 
        delay_target = (int) ( mSettings->mBufLen * ((kSecs_to_usecs * kBytes_to_Bits) 
                                                     / mSettings->mUDPRate) ); 
        if ( delay_target < 0  || 
             delay_target > (int) 1 * kSecs_to_usecs ) {
            fprintf( stderr, warn_delay_large, delay_target / kSecs_to_usecs ); 
            delay_target = (int) kSecs_to_usecs * 1; 
        }
        if ( isFileInput( mSettings ) ) {
            if ( isCompat( mSettings ) ) {
                Extractor_reduceReadSize( sizeof(struct UDP_datagram), mSettings );
                readAt += sizeof(struct UDP_datagram);
            } else {
                Extractor_reduceReadSize( sizeof(struct UDP_datagram) +
                                          sizeof(struct client_hdr), mSettings );
                readAt += sizeof(struct UDP_datagram) +
                          sizeof(struct client_hdr);
            }
        }
    }

    ReportStruct *reportstruct = NULL;

    // InitReport handles Barrier for multiple Streams
    mSettings->reporthdr = InitReport( mSettings );
    reportstruct = new ReportStruct;
    reportstruct->packetID = 0;

    lastPacketTime.setnow();
    
    do {

        // Test case: drop 17 packets and send 2 out-of-order: 
        // sequence 51, 52, 70, 53, 54, 71, 72 
        //switch( datagramID ) { 
        //  case 53: datagramID = 70; break; 
        //  case 71: datagramID = 53; break; 
        //  case 55: datagramID = 71; break; 
        //  default: break; 
        //} 
        gettimeofday( &(reportstruct->packetTime), NULL );

        if ( isUDP( mSettings ) ) {
            // store datagram ID into buffer 
            mBuf_UDP->id      = htonl( (reportstruct->packetID)++ ); 
            mBuf_UDP->tv_sec  = htonl( reportstruct->packetTime.tv_sec ); 
            mBuf_UDP->tv_usec = htonl( reportstruct->packetTime.tv_usec );

            // delay between writes 
            // make an adjustment for how long the last loop iteration took 
            // TODO this doesn't work well in certain cases, like 2 parallel streams 
            adjust = delay_target + lastPacketTime.subUsec( reportstruct->packetTime ); 
            lastPacketTime.set( reportstruct->packetTime.tv_sec, 
                                reportstruct->packetTime.tv_usec ); 

            if ( adjust > 0  ||  delay > 0 ) {
                delay += adjust; 
            }
        }

        // Read the next data block from 
        // the file if it's file input 
        if ( isFileInput( mSettings ) ) {
            Extractor_getNextDataBlock( readAt, mSettings ); 
            canRead = Extractor_canRead( mSettings ) != 0; 
        } else
            canRead = true; 

        // perform write 
        currLen = write( mSettings->mSock, mBuf, mSettings->mBufLen ); 
        if ( currLen < 0 && errno != ENOBUFS ) {
            WARN_errno( currLen < 0, "write2" ); 
            break; 
        }

        // report packets 
        reportstruct->packetLen = currLen;
        ReportPacket( mSettings->reporthdr, reportstruct );
        
        if ( delay > 0 ) {
            delay_loop( delay ); 
        }
        if ( !mMode_Time ) {
            /* mAmount may be unsigned, so don't let it underflow! */
            if( mSettings->mAmount >= currLen ) {
                mSettings->mAmount -= currLen;
            } else {
                mSettings->mAmount = 0;
            }
        }

    } while ( ! (sInterupted  || 
                 (mMode_Time   &&  mEndTime.before( reportstruct->packetTime ))  || 
                 (!mMode_Time  &&  0 >= mSettings->mAmount)) && canRead ); 

    // stop timing
    gettimeofday( &(reportstruct->packetTime), NULL );
    CloseReport( mSettings->reporthdr, reportstruct );

    if ( isUDP( mSettings ) ) {
        // send a final terminating datagram 
        // Don't count in the mTotalLen. The server counts this one, 
        // but didn't count our first datagram, so we're even now. 
        // The negative datagram ID signifies termination to the server. 
    
        // store datagram ID into buffer 
        mBuf_UDP->id      = htonl( -(reportstruct->packetID)  ); 
        mBuf_UDP->tv_sec  = htonl( reportstruct->packetTime.tv_sec ); 
        mBuf_UDP->tv_usec = htonl( reportstruct->packetTime.tv_usec ); 

        if ( isMulticast( mSettings ) ) {
            write( mSettings->mSock, mBuf, mSettings->mBufLen ); 
        } else {
            write_UDP_FIN( ); 
        }
    }
    DELETE_PTR( reportstruct );
    EndReport( mSettings->reporthdr );
} 
Exemple #13
0
/* -------------------------------------------------------------------
 * Set socket options before the listen() or connect() calls.
 * These are optional performance tuning factors.
 * ------------------------------------------------------------------- */
void SetSocketOptions( thread_Settings *inSettings ) {
    // set the TCP window size (socket buffer sizes)
    // also the UDP buffer size
    // must occur before call to accept() for large window sizes
    setsock_tcp_windowsize( inSettings->mSock, inSettings->mTCPWin,
                            (inSettings->mThreadMode == kMode_Client ? 1 : 0) );

    if ( isCongestionControl( inSettings ) ) {
#ifdef TCP_CONGESTION
	Socklen_t len = strlen( inSettings->mCongestion ) + 1;
	int rc = setsockopt( inSettings->mSock, IPPROTO_TCP, TCP_CONGESTION,
			     inSettings->mCongestion, len);
	FAIL( rc == SOCKET_ERROR, ( "Attempt to set '%s' congestion control failed: %s\r\n", inSettings->mCongestion, strerror(errno) ), NULL );
#else
	fprintf( stderr, "The -Z option is not available on this operating system\r\n");
#endif /* TCP_CONGESTION */
    }

    // check if we're sending multicast, and set TTL
    if ( isMulticast( inSettings ) && ( inSettings->mTTL > 0 ) ) {
#ifdef HAVE_MULTICAST
    int val = inSettings->mTTL;
	if ( !SockAddr_isIPv6( &inSettings->local ) ) {
	    int rc = setsockopt( inSettings->mSock, IPPROTO_IP, IP_MULTICAST_TTL,
		    (const char*) &val, (Socklen_t) sizeof(val));

	    WARN_errno( rc == SOCKET_ERROR, ( "Failed to set multicast TTL.\r\n" ) );
	}
#ifdef HAVE_IPV6_MULTICAST
	else {
	    int rc = setsockopt( inSettings->mSock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
		    (const char*) &val, (Socklen_t) sizeof(val));
	    WARN_errno( rc == SOCKET_ERROR, ( "Failed to set multicast TTL.\r\n" ) );
	}
#endif /* HAVE_IPV6_MULTICAST */
#endif /* HAVE_MULTICAST */
    }

#ifdef IP_TOS
    // set IP TOS (type-of-service) field
//    if ( inSettings->mTOS > 0 ) {
        int  tos, rc;

        tos = inSettings->mTOS;
        Socklen_t len = sizeof(tos);
        rc = setsockopt( inSettings->mSock, IPPROTO_IP, IP_TOS,(char*) &tos, len );
        WARN_errno( rc == SOCKET_ERROR, ( "Failed to set IP_TOS.\r\n" ) );
//    }
#endif /* IP_TOS */

    if ( !isUDP( inSettings ) ) {
        // set the TCP maximum segment size
        setsock_tcp_mss( inSettings->mSock, inSettings->mMSS );

#ifdef TCP_NODELAY
        // set TCP nodelay option
        if ( isNoDelay( inSettings ) ) {
            int nodelay = 1;
            Socklen_t len = sizeof(nodelay);
            int rc = setsockopt( inSettings->mSock, IPPROTO_TCP, TCP_NODELAY,
                                 (char*) &nodelay, len );
            WARN_errno( rc == SOCKET_ERROR, ( "Failed to set TCP_NODELAY.\r\n" ) );
        }
#endif /* TCP_NODELAY */
    }
} // end SetSocketOptions
Exemple #14
0
/*
 * Updates connection stats
 */
int reporter_handle_packet( ReportHeader *reporthdr ) {
    ReportStruct *packet = &reporthdr->data[reporthdr->reporterindex];
    ReporterData *data = &reporthdr->report;
    Transfer_Info *stats = &reporthdr->report.info;
    int finished = 0;
    double usec_transit;

    data->packetTime = packet->packetTime;
    stats->socket = packet->socket;
    if ( packet->packetID < 0 ) {
        finished = 1;
        if ( reporthdr->report.mThreadMode != kMode_Client ) {
            data->TotalLen += packet->packetLen;
        }
    } else {
	if (!packet->emptyreport) {
	    // update fields common to TCP and UDP, client and server
	    data->TotalLen += packet->packetLen;
	    // update fields common to UDP client and server
            if ( isUDP( data ) ) {
		data->cntDatagrams++;
		stats->IPGsum += TimeDifference(data->packetTime, data->IPGstart );
		stats->IPGcnt++;
		data->IPGstart = data->packetTime;
		// Finally, update UDP server fields
		if (stats->mUDP == kMode_Server) {
		    //subsequent packets
		    double transit;
		    double deltaTransit;            
		    transit = TimeDifference( packet->packetTime, packet->sentTime );
		    // packet loss occured if the datagram numbers aren't sequential 
		    if ( packet->packetID != data->PacketID + 1 ) {
			if (packet->packetID < data->PacketID + 1 ) {
			    data->cntOutofOrder++;
			} else {
			    data->cntError += packet->packetID - data->PacketID - 1;
			}
		    }
		    // never decrease datagramID (e.g. if we get an out-of-order packet)
		    if ( packet->packetID > data->PacketID ) {
			data->PacketID = packet->packetID;
		    }
		    if (stats->transit.totcntTransit == 0) {
			// Very first packet
			stats->transit.minTransit = transit;
			stats->transit.maxTransit = transit;
			stats->transit.sumTransit = transit;
			stats->transit.cntTransit = 1;
			stats->transit.totminTransit = transit;
			stats->transit.totmaxTransit = transit;
			stats->transit.totsumTransit = transit;
			stats->transit.totcntTransit = 1;
			// For variance, working units is microseconds
			usec_transit = transit * 1e6;
			stats->transit.vdTransit = usec_transit;
			stats->transit.meanTransit = usec_transit;
			stats->transit.m2Transit = usec_transit * usec_transit;
			stats->transit.totvdTransit = usec_transit;
			stats->transit.totmeanTransit = usec_transit;
			stats->transit.totm2Transit = usec_transit * usec_transit;
		    } else {
			// from RFC 1889, Real Time Protocol (RTP) 
			// J = J + ( | D(i-1,i) | - J ) / 
			// Compute jitter
			deltaTransit = transit - stats->transit.lastTransit;
			if ( deltaTransit < 0.0 ) {
			    deltaTransit = -deltaTransit;
			}
			stats->jitter += (deltaTransit - stats->jitter) / (16.0);
			// Compute end/end delay stats
			stats->transit.sumTransit += transit;
			stats->transit.cntTransit++;
			stats->transit.totsumTransit += transit;
			stats->transit.totcntTransit++;
			// mean min max tests
			if (transit < stats->transit.minTransit) {
			    stats->transit.minTransit=transit;
			}
			if (transit < stats->transit.totminTransit) {
			    stats->transit.totminTransit=transit;
			}
			if (transit > stats->transit.maxTransit) {
			    stats->transit.maxTransit=transit;
			}
			if (transit > stats->transit.totmaxTransit) {
			    stats->transit.totmaxTransit=transit;
			}
			// For variance, working units is microseconds
			// variance interval
			usec_transit = transit * 1e6;
			stats->transit.vdTransit = usec_transit - stats->transit.meanTransit;
			stats->transit.meanTransit = stats->transit.meanTransit + (stats->transit.vdTransit / stats->transit.cntTransit);
			stats->transit.m2Transit = stats->transit.m2Transit + (stats->transit.vdTransit * (usec_transit - stats->transit.meanTransit));
			// variance total
			stats->transit.totvdTransit = usec_transit - stats->transit.totmeanTransit;
			stats->transit.totmeanTransit = stats->transit.totmeanTransit + (stats->transit.totvdTransit / stats->transit.totcntTransit);
			stats->transit.totm2Transit = stats->transit.totm2Transit + (stats->transit.totvdTransit * (usec_transit - stats->transit.totmeanTransit));
		    }
		    stats->transit.lastTransit = transit;
		}
	    } else if (reporthdr->report.mThreadMode == kMode_Server && (packet->packetLen > 0)) {
		int bin;
		// mean min max tests
		stats->tcp.read.cntRead++;
		stats->tcp.read.totcntRead++;
		bin = (int)floor((packet->packetLen -1)/stats->tcp.read.binsize);
		stats->tcp.read.bins[bin]++;
		stats->tcp.read.totbins[bin]++;
	    } else if (reporthdr->report.mThreadMode == kMode_Client) {
		if (packet->errwrite) { 
		    stats->tcp.write.WriteErr++;
		    stats->tcp.write.totWriteErr++;
		}
		else { 
		    stats->tcp.write.WriteCnt++;
		    stats->tcp.write.totWriteCnt++;
		}
	    }
	} else if ((stats->mUDP == kMode_Server) &&	\
		   (stats->transit.cntTransit == 0)) {
	    // This is the case when empty reports
	    // cross the report interval boundary
	    // Hence, set the per interval min to infinity
	    // and the per interval max and sum to zero
	    stats->transit.minTransit = FLT_MAX;
	    stats->transit.maxTransit = FLT_MIN;
	    stats->transit.sumTransit = 0;
	    stats->transit.vdTransit = 0;
	    stats->transit.meanTransit = 0;
	    stats->transit.m2Transit = 0;
	}
    }
    // Print a report if appropriate
    return reporter_condprintstats( &reporthdr->report, reporthdr->multireport, finished );
}
Exemple #15
0
/*
 * InitReport is called by a transfer agent (client or
 * server) to setup the needed structures to communicate
 * traffic.
 */
ReportHeader* InitReport( thread_Settings *agent ) {
    ReportHeader *reporthdr = NULL;
    ReporterData *data = NULL;
    if ( isDataReport( agent ) ) {
        /*
         * Create in one big chunk
         */
        reporthdr = malloc( sizeof(ReportHeader) +
                            NUM_REPORT_STRUCTS * sizeof(ReportStruct) );
        if ( reporthdr != NULL ) {
            // Only need to make sure the headers are clean
            memset( reporthdr, 0, sizeof(ReportHeader));
            reporthdr->data = (ReportStruct*)(reporthdr+1);
            reporthdr->multireport = agent->multihdr;
            data = &reporthdr->report;
            reporthdr->reporterindex = NUM_REPORT_STRUCTS - 1;
            data->info.transferID = agent->mSock;
            data->info.groupID = (agent->multihdr != NULL ? agent->multihdr->groupID : 128);
            data->type = TRANSFER_REPORT;
            if ( agent->mInterval != 0.0 ) {
                struct timeval *interval = &data->intervalTime;
                interval->tv_sec = (long) agent->mInterval;
                interval->tv_usec = (long) ((agent->mInterval - interval->tv_sec) * rMillion);
            }
            data->mHost = agent->mHost;
            data->mLocalhost = agent->mLocalhost;
            data->mBufLen = agent->mBufLen;
            data->mMSS = agent->mMSS;
            data->mTCPWin = agent->mTCPWin;
            data->flags = agent->flags;
            data->mThreadMode = agent->mThreadMode;
            data->mode = agent->mReportMode;
            data->info.mFormat = agent->mFormat;
            data->info.mTTL = agent->mTTL;
	    if (data->mThreadMode == kMode_Server) 
		data->info.tcp.read.binsize = data->mBufLen / 8;
            if ( isUDP( agent ) ) {
		gettimeofday(&data->IPGstart, NULL);
                reporthdr->report.info.mUDP = (char)agent->mThreadMode;
            } else {
                reporthdr->report.info.mTCP = (char)agent->mThreadMode;
	    }
	    if ( isEnhanced( agent ) ) {
		data->info.mEnhanced = 1;
	    } else {
		data->info.mEnhanced = 0;
	    }
        } else {
            FAIL(1, "Out of Memory!!\n", agent);
        }
    }
    if ( isConnectionReport( agent ) ) {
        if ( reporthdr == NULL ) {
            /*
             * Create in one big chunk
             */
            reporthdr = malloc( sizeof(ReportHeader) );
            if ( reporthdr != NULL ) {
                // Only need to make sure the headers are clean
                memset( reporthdr, 0, sizeof(ReportHeader));
                data = &reporthdr->report;
                data->info.transferID = agent->mSock;
                data->info.groupID = 128;
            } else {
                FAIL(1, "Out of Memory!!\n", agent);
            }
        }
        if ( reporthdr != NULL ) {
            data->type |= CONNECTION_REPORT;
            data->connection.peer = agent->peer;
            data->connection.size_peer = agent->size_peer;
            data->connection.local = agent->local;
            data->connection.size_local = agent->size_local;
        } else {
            FAIL(1, "Out of Memory!!\n", agent);
        }
    }
    if ( isConnectionReport( agent ) || isDataReport( agent ) ) {

#ifdef HAVE_THREAD
        /*
         * Update the ReportRoot to include this report.
         */
        if ( reporthdr->report.mThreadMode == kMode_Client &&
             reporthdr->multireport != NULL ) {
            // syncronize watches on my mark......
            BarrierClient( reporthdr );
        } else {
            if ( reporthdr->multireport != NULL && isMultipleReport( agent )) {
                reporthdr->multireport->threads++;
                if ( reporthdr->multireport->report->startTime.tv_sec == 0 ) {
                    gettimeofday( &(reporthdr->multireport->report->startTime), NULL );
                }
                reporthdr->report.startTime = reporthdr->multireport->report->startTime;
            } else {
                // set start time
                gettimeofday( &(reporthdr->report.startTime), NULL );
            }
            reporthdr->report.nextTime = reporthdr->report.startTime;
            TimeAdd( reporthdr->report.nextTime, reporthdr->report.intervalTime );
        }
        Condition_Lock( ReportCond );
        reporthdr->next = ReportRoot;
        ReportRoot = reporthdr;
        Condition_Signal( &ReportCond );
        Condition_Unlock( ReportCond );
#else
        // set start time
        gettimeofday( &(reporthdr->report.startTime), NULL );
        /*
         * Process the report in this thread
         */
        reporthdr->next = NULL;
        process_report ( reporthdr );
#endif 
    }
    if ( !isDataReport( agent ) ) {
        reporthdr = NULL;
    }
    return reporthdr;
}
Exemple #16
0
MultiHeader* InitMulti( thread_Settings *agent, int inID ) {
    MultiHeader *multihdr = NULL;
    if ( agent->mThreads > 1 || agent->mThreadMode == kMode_Server ) {
        if ( isMultipleReport( agent ) ) {
            multihdr = malloc(sizeof(MultiHeader) +  sizeof(ReporterData) +
                              NUM_MULTI_SLOTS * sizeof(Transfer_Info));
        } else {
            multihdr = malloc(sizeof(MultiHeader));
        }
        if ( multihdr != NULL ) {
            memset( multihdr, 0, sizeof(MultiHeader) );
            Condition_Initialize( &multihdr->barrier );
            multihdr->groupID = inID;
            multihdr->threads = agent->mThreads;
            if ( isMultipleReport( agent ) ) {
                int i;
                ReporterData *data = NULL;
                multihdr->report = (ReporterData*)(multihdr + 1);
                memset(multihdr->report, 0, sizeof(ReporterData));
                multihdr->data = (Transfer_Info*)(multihdr->report + 1);
                data = multihdr->report;
                for ( i = 0; i < NUM_MULTI_SLOTS; i++ ) {
                    multihdr->data[i].startTime = -1;
                    multihdr->data[i].transferID = inID;
                    multihdr->data[i].groupID = -2;
                }
                data->type = TRANSFER_REPORT;
                if ( agent->mInterval != 0.0 ) {
                    struct timeval *interval = &data->intervalTime;
                    interval->tv_sec = (long) agent->mInterval;
                    interval->tv_usec = (long) ((agent->mInterval - interval->tv_sec) 
                                                * rMillion);
                }
                data->mHost = agent->mHost;
                data->mLocalhost = agent->mLocalhost;
                data->mBufLen = agent->mBufLen;
                data->mMSS = agent->mMSS;
                data->mTCPWin = agent->mTCPWin;
                data->flags = agent->flags;
                data->mThreadMode = agent->mThreadMode;
                data->mode = agent->mReportMode;
                data->info.mFormat = agent->mFormat;
                data->info.mTTL = agent->mTTL;
		if (data->mThreadMode == kMode_Server) 
		    data->info.tcp.read.binsize = data->mBufLen / 8;
                if ( isEnhanced( agent ) ) {
		    data->info.mEnhanced = 1;
		} else {
		    data->info.mEnhanced = 0;
		}
                if ( isUDP( agent ) ) {
                    multihdr->report->info.mUDP = (char)agent->mThreadMode;
                    multihdr->report->info.mUDP = 0;
                } else {
                    multihdr->report->info.mTCP = (char)agent->mThreadMode;
		}
                if ( isConnectionReport( agent ) ) {
                    data->type |= CONNECTION_REPORT;
                    data->connection.peer = agent->peer;
                    data->connection.size_peer = agent->size_peer;
                    SockAddr_setPortAny( &data->connection.peer );
                    data->connection.local = agent->local;
                    data->connection.size_local = agent->size_local;
                    SockAddr_setPortAny( &data->connection.local );
                }
            }
        } else {
            FAIL(1, "Out of Memory!!\n", agent);
        }
    }
    return multihdr;
}
Exemple #17
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);
    }
}
Exemple #18
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
            if ( !isUDP( mExtSettings ) ) {
                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);
            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
            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 );
            if ( !isUDP( mExtSettings ) ) {
                 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
            if ( mExtSettings->mThreadMode != kMode_Unknown ) {
                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 );
                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
        case 'E': // specify the local port on this PC to connect with (only for client mode)
            mExtSettings->mLocalPort = atoi( optarg );
            break;
        
        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