Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   Related Pages  

QuorumBuilderAct.cc

00001 /*
00002  * Copyright 2003 Michael A. Marsh, Cornell University. All rights reserved.
00003  * This software is released under the modified BSD license.
00004  * See the file LICENSE in the top-level directory for details.
00005  */
00006 //
00007 // $Id: QuorumBuilderAct.cc,v 1.3 2004/05/19 15:56:58 mmarsh Exp $
00008 //
00009 // $Log: QuorumBuilderAct.cc,v $
00010 // Revision 1.3  2004/05/19 15:56:58  mmarsh
00011 // *** empty log message ***
00012 //
00013 // Revision 1.2  2003/11/04 22:31:51  mmarsh
00014 // *** empty log message ***
00015 //
00016 //
00017 
00018 #include "QuorumBuilderAct.h"
00019 #include "QuorumBuilderEvent.h"
00020 #include "QuorumBuilderExpectNonceEvent.h"
00021 
00022 #include "CODEX_ASN1/Integer.h"
00023 #include "CODEX_Exceptions/BignumExceptions.h"
00024 #include "ServerExceptions.h"
00025 
00026 using namespace CODEX_Server;
00027 
00028 QuorumBuilderAct::QuorumBuilderAct( CODEX_Events::DeadPileType& deadPile,
00029                                     CODEX_Events::QType& eventQueue ) :
00030    CODEX_Events::Activity( deadPile, eventQueue )
00031 {
00032    sendEvent( new QuorumBuilderEvent(this), 0 );
00033    for ( unsigned int i = 0 ; i < ServerState::nServers ; ++i )
00034    {
00035       m_pending[i] = NULL;
00036    }
00037 }
00038 
00039 QuorumBuilderAct::~QuorumBuilderAct()
00040 {
00041    for ( unsigned int i = 0 ; i < ServerState::nServers ; ++i )
00042    {
00043       if ( NULL != m_pending[i] )
00044       {
00045          delete m_pending[i];
00046       }
00047    }
00048 }
00049 
00050 bool
00051 QuorumBuilderAct::handler( QuorumBuilderEvent& event )
00052 {
00053    ServerState* serverState = ServerState::instance();
00054    if ( NULL == serverState )
00055    {
00056       // something's seriously wrong
00057       return true;
00058    }
00059 
00060    // Only attempt to connect to one missing server, which will keep
00061    // this somewhat lighter-weight.  Attempts are only made to
00062    // higher-numbered servers.
00063    for ( unsigned int i = 0 ; i < ServerState::nServers ; ++i )
00064    {
00065       // We want to start one host *after* the last one we tried.  This
00066       // will place the last attempt at the end of the list, so it will
00067       // only be tried if none of the others is missing.
00068       unsigned int hostNum =
00069          ( i + event.lastAttempt() + 1 ) % ServerState::nServers;
00070       if ( ( hostNum > serverState->hostNum() ) &&
00071            ( ! serverState->haveQuorumServer( hostNum ) ) &&
00072            ( NULL == m_pending[ hostNum ] ) )
00073       {
00074          // try to connect
00075          RSType* ars = NULL;
00076          try
00077          {
00078             ars = new RSType( serverState->hostName(hostNum),
00079                               serverState->serverPort(hostNum),
00080                               serverState->serverOutSocketBuilder() );
00081 //            fd_set bogus;
00082 //            ars->set_fd( &bogus, CODEX_Quorum::SocketBase::kRead );
00083 //            ars->socket();
00084             m_pending[ hostNum ] = ars;
00085             sendEvent( new QuorumBuilderExpectNonceEvent(this,hostNum),
00086                        0 );
00087          }
00088          catch ( ... )
00089          {
00090             if ( NULL != ars ) delete ars;
00091          }
00092          event.setLastAttempt( hostNum );
00093          return false;
00094       }
00095    }
00096    // No attempts were made this time through.
00097    return false;
00098 }
00099 
00101 bool
00102 QuorumBuilderAct::handler( QuorumBuilderExpectNonceEvent& event )
00103 {
00104    ServerState* serverState = ServerState::instance();
00105    if ( NULL == serverState )
00106    {
00107       // something's seriously wrong
00108       return true;
00109    }
00110 
00111    // Wait until there's a nonce to read.
00112    RSType* ars = m_pending[ event.hostNum() ];
00113    if ( NULL == ars )
00114    {
00115       return true;
00116    }
00117    try
00118    {
00119       fd_set read_set;
00120       FD_ZERO(&read_set);
00121       int s = ars->set_fd(&read_set,CODEX_Quorum::SocketBase::kRead);
00122       struct timeval tv;
00123       tv.tv_sec = 0;
00124       tv.tv_usec = 0;
00125       if ( ( 0 <= select( s+1, &read_set, NULL, NULL, &tv ) ) && 
00126            ( ars->isset_fd( &read_set, CODEX_Quorum::SocketBase::kRead ) ) )
00127       {
00128          if ( event.read( ars ) )
00129          {
00130             // Get the data
00131             unsigned char* buffer = (unsigned char*)event.buffer().buffer();
00132             unsigned char* pBuffer = buffer;
00133             int length = event.buffer().length();
00134 
00135             // Unmarshal the nonce
00136             CODEX_ASN1::BigNumber bn;
00137             if ( NULL == bn.unmarshal(NULL,&pBuffer,length) )
00138             {
00139                throw 0;
00140             }
00141 
00142             // Construct the response, which is the local host number and nonce
00143             CODEX_ASN1::Integer iHost( serverState->hostNum() );
00144             length = iHost.marshal(0);
00145             length += bn.marshal(0);
00146             buffer = new unsigned char[ length ];
00147             pBuffer = buffer;
00148             iHost.marshal(&pBuffer);
00149             bn.marshal(&pBuffer);
00150             CODEX_Quorum::Message msg(buffer,length);
00151 
00152             // Now prepare to sign the response
00153             CODEX_ASN1::ustring* str = NULL;
00154             try
00155             {
00156                str =
00157                   serverState->hashFunc()(CODEX_ASN1::ustring(buffer,length));
00158             }
00159             catch ( ... )
00160             {
00161                if ( NULL != str ) delete str;
00162                delete [] buffer;
00163                throw;
00164             }
00165             delete [] buffer;
00166             BIGNUM * digest = NULL;
00167             digest = BN_new();
00168             if ( NULL == digest )
00169             {
00170                delete str;
00171                throw CODEX_Exceptions::BignumNullException( __FILE__ ,
00172                                                             __LINE__ );
00173             }
00174             if ( ! BN_bin2bn( str->data(), str->length(), digest ) )
00175             {
00176                delete str;
00177                BN_free( digest );
00178                throw CODEX_Exceptions::BignumBin2BNException( __FILE__ ,
00179                                                               __LINE__ );
00180             }
00181             delete str;
00182 
00183             // Sign the message
00184             const CODEX_Ciphers::RSAPrivateKey& key =
00185                serverState->privateKey();
00186             if ( ! key.initialized() )
00187             {
00188                BN_free( digest );
00189                throw PublicKeyNotFoundException( __FILE__ , __LINE__ );
00190             }
00191             CODEX_Ciphers::RSASignature* signature = NULL;
00192             try
00193             {
00194                signature = key.sign(digest);
00195             }
00196             catch ( ... )
00197             {
00198                BN_free( digest );
00199                throw;
00200             }
00201             BN_free( digest );
00202 
00203             // Append the signature
00204             length = signature->marshal(0);
00205             buffer = new unsigned char[ length ];
00206             pBuffer = buffer;
00207             signature->marshal(&pBuffer);
00208             msg.fill(buffer,length);
00209             delete [] buffer;
00210             delete signature;
00211 
00212             // Now send and register the remote server with the quorum system
00213             CODEX_Quorum::RemoteServerReturn r;
00214             ars->sendTo(msg,r);
00215             m_pending[ event.hostNum() ] = NULL;
00216             serverState->addQuorumServer( event.hostNum(), ars );
00217             cout << "Connected to server " << event.hostNum() << endl;
00218             return true;
00219          }
00220       }
00221    }
00222    catch ( ... )
00223    {
00224       if ( NULL != ars ) delete ars;
00225       m_pending[ event.hostNum() ] = NULL;
00226       return true;
00227    }
00228    return false;
00229 }

Generated on Wed Jun 2 16:32:55 2004 for COrnell Data EXchange (CODEX) by doxygen1.2.18