Main Page | Modules | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages

balcli.cpp

00001 /*
00002    Cabal - balcli
00003    Short description
00004 
00005    $Id: balcli.cpp,v 1.3 2004/03/29 14:47:55 jonnymind Exp $
00006 ---------------------------------------------
00007    Begin      : lun mar 29 2004 02:17:23
00008    Author     : Giancarlo Niccolai <gc@niccolai.ws>, (C) 2004
00009 
00010    Last modified because:
00011 
00012 */
00013 
00014 /**************************************************************************
00015 *   This program is free software; you can redistribute it and/or modify  *
00016 *   it under the terms of the GNU Library General Public License as       *
00017 *   published by the Free Software Foundation; either version 2.1 of the  *
00018 *   License, or (at your option) any later version.                       *
00019 ***************************************************************************/
00020    
00021 // currently we use a very relaxed modality of direct socket rw;
00022 // clients can use channels/lines as server does, but I am in a hurry...
00023 
00024 #include "balser.h"
00025 #include <list>
00026 
00027 #define DEFAULT_PORT       2051
00028 #define DEFAULT_IP         "127.0.0.1"
00029 
00030 using namespace std;
00031 using namespace Cabal;
00032 
00033 class pkt_account 
00034 {
00035 public:
00036    pkt_account( MSECS t, int l )
00037    {
00038       arr_time = t;
00039       length = l;
00040    }
00041    
00042    MSECS arr_time;
00043    int length;
00044 };
00045 
00046 list< pkt_account> accountList;
00047 
00048 void calcBandwidth( double &immediate, double &mean )
00049 {
00050    double totalSec = 0.0;
00051    double totalTime = 0.0;
00052    double totalData = 0.0;
00053    
00054    list< pkt_account>::iterator iter = accountList.begin();
00055    MSECS now = iter->arr_time;
00056    
00057    int size = 0;
00058    while( iter != accountList.end() )
00059    {   
00060       if ( iter->arr_time > now - 1000 ) {
00061          totalSec += iter->length;
00062       }
00063       totalData += iter->length;
00064       // I should get only the last one, but I am lazy :-)
00065       totalTime = iter->arr_time;
00066       iter++;
00067       size++;
00068    }
00069    
00070    immediate = totalSec;
00071    if ( (now - totalTime) > 0 ) 
00072       mean = totalData / ( now - totalTime ) * (size-1)/(size) *1000.0;
00073    else
00074       mean = 0;
00075 }
00076 
00079 void communicate( UDPSocket &skt, unsigned long userId, Address &remote, PACKET *pkt )
00080 {
00081    MSECS lastTime;
00082    
00083    do { // at first loop, process connection packet
00084       lastTime = Net::timeOfDay();
00085       // finally, we can account a correct packet.
00086       accountList.push_front( pkt_account( lastTime, sizeof( PACKET ) ) ); // we only get this length
00087       // and write the means
00088       double instant, mean;
00089       calcBandwidth( instant, mean );
00090       cout << "\r" << instant << "b/sec " << mean << "b/sec ";
00091       
00092       unsigned char check = static_cast<unsigned char>( pkt->id );
00093       bool correct = true;
00094       for( int pos = 0; pos < sizeof( pkt->data ); pos ++ )
00095       {
00096          if ( static_cast<unsigned char>(pkt->data[pos]) != check ) {
00097             correct = false;
00098             break;
00099          }
00100       }
00101             
00102       // if not correct, ask fro resend.
00103       CLI_REQ *req = reinterpret_cast<CLI_REQ *>(pkt->data);
00104       if ( ! correct )
00105       {
00106          req->type = REQ_TYPE_RESEND;
00107          req->value = pkt->id;
00108          // display bandwidth
00109          cout <<"!" <<flush;
00110       }
00111       else {
00112          req->type = REQ_TYPE_ACK;
00113          req->value = pkt->id;
00114       }
00115       
00116       for ( int i = 0; i < accountList.size(); i ++ )
00117          // display bandwidth
00118          cout <<"#";
00119       
00120       cout << flush;
00121       
00122       //lower timeout to send
00123       skt.timeout( 250 );
00124       int retval = 0;
00125       // insist
00126       // echoes using the pakcet provided timestamp.
00127       retval = skt.sendTo( pkt, CLIENT_REP_SIZE, remote );
00128       if ( retval <= 0 ) {
00129          cout << "Error on socket " << skt.osError() << ": " <<
00130                Net::errorDescription( skt.osError() ) << endl;
00131             return;
00132       }
00133       
00134       skt.timeout( 2500 );
00135       while ( lastTime + 2500 > Net::timeOfDay() ) 
00136       {
00137          retval = skt.recv( pkt, 1500 );
00138          if ( retval > 0 ) {
00139             if ( skt.remote() != remote ) {
00140                cout << "Received unexpected traffic from " << remote.ip() << ":" << remote.port() << endl;
00141             }
00142             else if ( retval != sizeof( PACKET ) || pkt->userId != userId ) {
00143                cout << "Received spurious " << retval << " bytes from " << remote.ip() << ":" << remote.port() << endl;
00144             }
00145             else 
00146                break;
00147          }
00148          else if (retval < 0 )
00149          {
00150             cout << "Error on socket " << skt.osError() << ": " <<
00151                Net::errorDescription( skt.osError() ) << endl;
00152             return;
00153          }
00154       }
00155       
00156       if ( retval == 0 ) {
00157          cout << "Server transmission timed out " << endl;
00158          return;
00159       }      
00160    } while( pkt->id != END_CONNECT );
00161       
00162 }
00163          
00164          
00165       
00166       
00167 int main ( int argc, char *argv[] )
00168 {
00169    int n_port;
00170    char *c_ip;
00171 
00172    if ( argc == 3 ) {
00173       c_ip = argv[1];
00174       n_port = atoi( argv[2] );
00175    }
00176    else if ( argc == 2 ) {
00177       c_ip = DEFAULT_IP;
00178       n_port = atoi( argv[1] );
00179    }
00180    else {
00181       c_ip = DEFAULT_IP;
00182       n_port = DEFAULT_PORT;
00183    }
00184 
00185    
00186    try {
00187       bool connected;
00188       char buffer[1500];
00189       PACKET *pkt = reinterpret_cast< PACKET *>( buffer );
00190       
00191       Net::init();
00192       UDPSocket skt;
00193       Address remote( c_ip, n_port ), incoming;
00194       
00195       skt.timeout( 2500 );
00196       cout << "Sending UDP connection request." << endl;
00197       pkt->userId = START_CONNECT;
00198       
00199       connected = false;
00200       
00201       for ( int tries = 0; tries < 3; tries ++ ) 
00202       {
00203          if ( skt.sendTo( pkt, CLIENT_REP_SIZE, remote ) != CLIENT_REP_SIZE )
00204          {
00205             cout << "Error on first send " << skt.osError() << ": " <<
00206                Net::errorDescription( skt.osError() ) << endl;
00207             break;
00208          }
00209          
00210          int recvd = skt.recvFrom( pkt, 1500, incoming );
00211          if ( recvd < 0 ) {
00212             cout << "Error on first recv " << skt.osError() << ": " <<
00213                Net::errorDescription( skt.osError() ) << endl;
00214             break;
00215          }
00216          else if ( recvd == 0 ) {
00217             cout << "Timedout wihile waiting. Resending." << endl;
00218             continue;
00219          }
00220          else if ( recvd < sizeof( PACKET ) )
00221          {
00222             cout << "Received spurious data." <<endl;
00223          }
00224          else if ( incoming != remote ) {
00225             cout << "Received different traffic source: " << incoming.ip() << endl;
00226          }
00227          else {
00228             cout << "Begin of transmissions." << endl;
00229             connected = true;
00230             break;
00231          }
00232             
00233       }
00234       
00235       if ( connected )
00236       {
00237          communicate( skt, pkt->userId, remote, pkt );
00238       }
00239       
00240       skt.close();
00241       cout << endl << "Done" << endl;
00242       Net::exit();
00243    }
00244    catch (Error e ) {
00245       cout << e <<"\n";
00246    }
00247 
00248    return 0;
00249 }
00250 
00251 /* end of balcli */

Generated on Sat Apr 10 17:41:48 2004 for Cabal by doxygen 1.3.5