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

channel.cpp

00001 /*
00002    CABAL - CAched BAlanced LAN
00003    Test for cached channel based server
00004 
00005    (single thread version)
00006 
00007    $Id: channel.cpp,v 1.3 2004/03/26 22:45:11 jonnymind Exp $
00008 ---------------------------------------------
00009    Begin      :
00010    Author     : Giancarlo Niccolai
00011 
00012    Last modified because:
00013 
00014 */
00015 
00016 #include <cabal.h>
00017 
00018 // This is just a test: we are using a rough way to use windows or unix timings.
00019 #include <time.h>
00020 #include <stdlib.h>
00021 
00022 #define DEFAULT_PORT       2051
00023 
00024 using namespace std;
00025 using namespace Cabal;
00026 
00027 /**********************************************************************
00028 * To demonstrate caching abilities, we need a recetption class. Very
00029 * basic here:
00030 ***********************************************************************/
00031 class DflReception: public Reception
00032 {
00033    int m_number;
00034    Line *m_line;
00035 
00036 public:
00037    DflReception( const int number, Line *line ) {
00038       m_number = number;
00039       m_line = line;
00040    }
00041 
00042    virtual void init( Socket *skt ) { 
00043       cout << "Receiver " << m_number << " waiting " << skt->remote_ip() <<":" << skt->remote_port() << endl;
00044    }
00045       
00046    virtual bool receive( Socket *skt );
00047    
00048    virtual void terminate( Socket *skt );
00049    
00050 };
00051 
00052  
00053 void DflReception::terminate( Socket *skt )
00054 {
00055    cout << "Receiver "<< m_number << " is destroyed";
00056    // possibly, this is because of an error on the socket.
00057    if ( skt->osError() != 0 )
00058       cout << " because of socket error " << skt->osError();
00059    // or because the socket has been cleanly closed.
00060    else if ( skt->closed() )
00061       cout << " because of socket closed by other side";
00062    
00063    cout << "." << endl;
00064    
00065    // destroy all the connections with the client;
00066    // notice, if this has been done in receive with the quit command,
00067    // this code does nothing (delete 0 is ansi c++)
00068    delete m_line;
00069    m_line = 0; // overkill but you never know...
00070 }
00071          
00072 bool DflReception::receive( Socket *skt )
00073 {
00074    char buffer[1501];   
00075    int length = skt->recv( buffer, 1500 );
00076 
00077    cout << "R" << m_number <<": received " << length << " bytes from " <<
00078          skt->remote_ip() << endl;
00079 
00080    buffer[length] = '\0';
00081    cout << "Data: " << buffer << endl;
00082 
00083    if ( strncmp( "quit", buffer,4 ) == 0 || length == 0) {
00084       // destroy all the connections with the client
00085       cout << "R" << m_number <<": terminating on request/disconnection " <<endl;
00086       delete m_line;
00087       m_line = 0;
00088       return false;
00089    }
00090       
00091    return true;
00092 }
00093 
00094 
00095 /**********************************************************************
00096 * We also need a transmission class to provide client with some random
00097 * fuzz.... as we were transmitting them...
00098 ***********************************************************************/
00099 
00100 class DflTransmit: public Transmission
00101 {
00102    int m_number;
00103    int m_timeout;
00104    int m_greeting;
00105    Connection *m_con;
00106 public:
00107    DflTransmit( int number, int to ) {
00108       m_number = number;
00109       m_timeout = to;
00110       m_greeting = 0;
00111    }
00112 
00113    virtual void init( Connection *con ) { cout << "Transmission " << m_number << " started" << endl; }
00114    virtual bool transmit( Connection *con );
00115    virtual void terminate( Connection *con ) {
00116       cout << "Transmission " << m_number << " terminated on socket status " << con->socket()->osError() <<endl;
00117    }
00118    
00119 };
00120 
00121 bool DflTransmit::transmit( Connection * con )
00122 {
00123 
00124    char buffer[256];
00125    Socket *skt = con->socket();
00126 
00127    if ( skt->osError() ) {
00128       cout << "Transmitter found error " << skt->osError() << " on socket" << endl;
00129       return false; // self-destruction
00130    }
00131    
00132    // or because the socket has been cleanly closed.
00133    if ( skt->closed() ) 
00134    {
00135       cout << "Transmitter found socket closed." <<endl;
00136       return false;
00137    }
00138 
00139    // ready to send data:
00140    if ( m_greeting == 0 ) {
00141       sprintf( buffer, "Welcome in CABAL demo\r\n" );
00142       m_greeting++;
00143    }
00144    else
00145       sprintf( buffer, "A random string from %d: %d\r\n", m_number, rand() );
00146       
00147    int len = strlen( buffer );
00148    len = skt->send( buffer, len );
00149    
00150    if ( len > 0 ) {
00151       // all fine, rescheduling
00152       con->account( len );
00153       con->schedule( m_timeout * 1000 );
00154       return true;
00155    }
00156    else {
00157       cout << "Transmitter had error in sending: " << skt->osError() << " on socket" << endl;
00158       return false; // self-destruction
00159    }
00160 }
00161 
00162 /*******************************************************************
00163 * Main procedure: create a server that accepts incoming connections
00164 * and produces a cacher for each new socket.
00165 * Cachers are destroyed as remote connections are closed.
00166 ********************************************************************/
00167 
00168 int main ( int argc, char *argv[] )
00169 {
00170    Net::init();
00171    int n_port;
00172    Channel *channel;
00173 
00174    if ( argc > 1 ) {
00175       n_port = atoi( argv[1] );
00176    }
00177    else {
00178       n_port = DEFAULT_PORT;
00179    }
00180 
00181    srand( static_cast<long>(time(0)) );
00182 
00183    // creates a channel for our server socket;
00184    channel = new Channel();
00185 
00186    try {
00187       ServerSocket ss( "0.0.0.0", n_port );
00188       Socket *s;
00189 
00190       cout << "Server waiting on port "<< n_port << endl;
00191       // setting timeout to 0 (don't stop, immediate timeout)
00192       ss.timeout( 0 );
00193       int num = 0;
00194 
00195       while ( true ) {
00196 
00197          s = ss.accept();
00198 
00199          // has a new connection come on board?
00200          while ( s != NULL ) {
00201             cout << "Connection from: " << s->remote_ip() << ":" <<
00202                   s->remote_port() << "\n";
00203 
00204             Line *line = new Line(0);            
00205             
00206             num++;
00207             DflTransmit *trans = new DflTransmit( num, 2 + rand()/(RAND_MAX/5));
00208             DflReception *rec = new DflReception( num, line );
00209 
00210             s->channel( channel, rec );
00211             Connection *con = new Connection( s, trans );
00212             line->set( "default", con );
00213             // immediately prepare to send the first message
00214             con->schedule( 0 );
00215             // releasing MY reference to the socket; now the channel is the owner.
00216             s->decref();
00217             
00218             //s = ss.accept();  // continue accepting.
00219             s = NULL;
00220          }
00221 
00222          // sleep 1/4th of seconds
00223          bool res = channel->process( 250 );
00224          // and continue while there is data to be processed
00225          while( res ) res = channel->process( 0 );
00226       }
00227 
00228    }
00229    catch (Error e ) {
00230       cout << e <<"\n";
00231    }
00232    Net::exit();
00233 
00234    return 0;
00235 }

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