#include "common.h"
#include <arpa/inet.h>

// установка параметров клиентов: адрес, порт и число повторений
static void setkey( int argc, char *argv[], char *adr, in_port_t* port, int* num ) {
    int opt, val;
    while ( ( opt = getopt( argc, argv, "a:p:n:") ) != -1 ) {
        switch( opt ) {
            case 'a' :
                strcpy( adr, optarg );
                break;
            case 'p' :
                if( sscanf( optarg, "%i", &val ) != 1 ) errx( "parse command line failed", EINVAL );
                *port = (in_port_t)val;
                break;
            case 'n' :
                if( ( sscanf( optarg, "%i", &val ) != 1 ) || ( val <= 0 ) ) errx( "parse command line failed", EINVAL );
                *num = val;
                break;
            default :
                errx( "parse command line failed", EINVAL );
                break;
        }
    };
};

// клиент - источник потока тестовых пакетов TCP
int main( int argc, char *argv[] ) {
   in_port_t listen_port = SINGLE_PORT;
   int num = 10;
   char data[ MAXLINE ], echo[ MAXLINE ], sadr[ MAXLINE ] = "localhost";
   setkey( argc, argv, &sadr[ 0 ], &listen_port, &num );
   cout << "wait ..." << flush;
   uint64_t cps = proc_hz(); // cycles per sec.
   cout << '\r' << "host: " << sadr << ", TCP port = " << listen_port << ", number of echoes = " 
        << num << endl << "time of reply - Cycles [usec.] :" << endl;
   for( int i = 0; i < num; i++ ) {
      int rc, ls;
      if( ( ls = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 ) errx( "create stream socket failed" );
      struct sockaddr_in addr;
      memset( &addr, 0, sizeof( addr ) );
      addr.sin_family = AF_INET;
      addr.sin_port = htons( listen_port );
      inet_aton( sadr, &addr.sin_addr );
      if( ( rc = connect( ls, (struct sockaddr*)&addr, sizeof( sockaddr ) ) ) < 0 ) errx( "connect failed" );
      sprintf( data, "%d", rand() );
      uint64_t cycle = rdtsc();
      if( ( rc = write( ls, data, strlen( data ) + 1 ) ) <= 0 ) { perror( "write data failed" ); break; };
      rc = read( ls, echo, MAXLINE );
      cycle = rdtsc() - cycle;      
      if( rc < 0 ) { perror( "read data failed" ); break; };
      if( rc == 0 ) { cout << "server closed connection" << endl; break; };
      if( strcmp( data, echo ) != 0 ) { cout << "wrong data" << endl; break; };
      cout << cycle << "[" << cycle * 1000000 / cps << "]";   // sec. / 10E6
      if( i % 5 == 4 ) cout << endl; else cout << '\t'; cout << flush;
      close( ls );
      delay( 100 ); // пауза 100 usec.
   };
   if( num % 5 != 0 ) cout << endl;
   exit( EXIT_SUCCESS );
};
