Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

ComputeCallback.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: ComputeCallback.cc,v 1.3 2004/05/19 15:56:23 mmarsh Exp $
00008 //
00009 // $Log: ComputeCallback.cc,v $
00010 // Revision 1.3  2004/05/19 15:56:23  mmarsh
00011 // Added copyright and license statements.
00012 //
00013 // Revision 1.2  2003/11/04 22:31:45  mmarsh
00014 // *** empty log message ***
00015 //
00016 //
00017 
00018 #include "ComputeCallback.h"
00019 #include "StateInfo.h"
00020 #include "CODEX_Server/ServerState.h"
00021 
00022 #include "CODEX_Exceptions/BignumExceptions.h"
00023 #include "CODEX_Server/ServerExceptions.h"
00024 
00025 #include "timing.h"
00026 
00027 using namespace CODEX_APSS;
00028 
00029 ComputeCallback::ComputeCallback( const LabelType& label ) :
00030    m_label( label ),
00031    m_completed( false )
00032 {
00033 }
00034 
00035 ComputeCallback::~ComputeCallback()
00036 {
00037 }
00038 
00039 bool
00040 ComputeCallback::operator()( unsigned int server, CODEX_Quorum::Message* msg )
00041 {
00042    if ( m_completed )
00043    {
00044       if ( 0 != msg ) delete msg;
00045       return true;
00046    }
00047 
00048    if ( 0 == msg )
00049    {
00050       return false;
00051    }
00052 
00053 #ifdef TIMING
00054    ActiveTimer.start();
00055 #endif
00056    CODEX_Server::ServerState* serverState =
00057       CODEX_Server::ServerState::instance();
00058    if ( 0 == serverState )
00059    {
00060       delete msg;
00061 #ifdef TIMING
00062       ActiveTimer.stop();
00063 #endif
00064       return false;
00065    }
00066 
00067    StateInfo* stateInfo = StateInfo::instance();
00068    if ( 0 == stateInfo )
00069    {
00070       delete msg;
00071 #ifdef TIMING
00072       ActiveTimer.stop();
00073 #endif
00074       return false;
00075    }
00076 
00077    // See if we're already in the next epoch.
00078    const unsigned long epoch = stateInfo->version( m_label.num().value() );
00079    const unsigned long version = m_label.version().value();
00080    if ( epoch >= version )
00081    {
00082       delete msg;
00083       m_completed = true;
00084 #ifdef TIMING
00085       ActiveTimer.stop();
00086 #endif
00087       return true;
00088    }
00089 
00090    // Unmarshal the message.
00091    unsigned char* data = (unsigned char*)msg->buffer();
00092    int length = msg->length();
00093 
00094    if ( length < 2 )
00095    {
00096       delete msg;
00097 #ifdef TIMING
00098       ActiveTimer.stop();
00099 #endif
00100       return false;
00101    }
00102 
00103    if ( stateInfo->domain() != data[0] )
00104    {
00105       delete msg;
00106 #ifdef TIMING
00107       ActiveTimer.stop();
00108 #endif
00109       return false;
00110    }
00111    ++data;
00112    --length;
00113 
00114    if ( ( kComputedMsg | SignatureMask ) != data[0] )
00115    {
00116       delete msg;
00117 #ifdef TIMING
00118       ActiveTimer.stop();
00119 #endif
00120       return false;
00121    }
00122    ++data;
00123    --length;
00124 
00125    SignedComputedMsg* signedResponse = new SignedComputedMsg;
00126    if ( 0 == signedResponse )
00127    {
00128       delete msg;
00129 #ifdef TIMING
00130       ActiveTimer.stop();
00131 #endif
00132       return false;
00133    }
00134    if ( 0 == signedResponse->unmarshal( 0, &data, length ) )
00135    {
00136       delete msg;
00137 #ifdef TIMING
00138       ActiveTimer.stop();
00139 #endif
00140       return false;
00141    }
00142    delete msg;
00143 
00144    // Make sure the response is valid.
00145    const ComputedMsg& response = signedResponse->message();
00146 
00147    unsigned int computor = response.computor().value();
00148    if ( computor != server )
00149    {
00150 #ifdef TIMING
00151       ActiveTimer.stop();
00152 #endif
00153       return false;
00154    }
00155 
00156    if ( response.shareLabel() != m_label )
00157    {
00158 #ifdef TIMING
00159       ActiveTimer.stop();
00160 #endif
00161       return false;
00162    }
00163 
00164    // Check the signature.
00165    BIGNUM * digest = 0;
00166    try
00167    {
00168       digest = response.digest( serverState->hashFunc() );
00169       if ( 0 == digest )
00170       {
00171          throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00172       }
00173       if ( ! serverState->publicKey(server).verifySignature(
00174          signedResponse->signature(),
00175          digest ) )
00176       {
00177          throw CODEX_Server::SignatureVerificationFailedException( __FILE__ ,
00178                                                                    __LINE__ );
00179       }
00180       BN_free(digest);
00181    }
00182    catch ( ... )
00183    {
00184       if ( 0 != digest ) BN_free(digest);
00185 #ifdef TIMING
00186       ActiveTimer.stop();
00187 #endif
00188       return false;
00189    }
00190 
00191    // Add the response to the evidence set.
00192    m_evidence.append( signedResponse );
00193 
00194    CODEX_Quorum::QuorumSystem* qs = serverState->quorumSystem();
00195    if ( 0 == qs )
00196    {
00197 #ifdef TIMING
00198       ActiveTimer.stop();
00199 #endif
00200       throw CODEX_Server::NoQuorumSystemException( __FILE__ , __LINE__ );
00201    }
00202 
00203    if ( m_evidence.size() >= qs->quorumSize() )
00204    {
00205       // Compose the finished message.
00206       FinishedMsg fm( m_label.version(), m_label.id(), m_evidence );
00207 
00208       // Sign the finished message.
00209       BIGNUM * digest = 0;
00210       CODEX_Ciphers::RSASignature* signature = 0;
00211       try
00212       {
00213          const CODEX_Ciphers::HashFunction& hashFunc = serverState->hashFunc();
00214          digest = fm.digest( hashFunc );
00215          const CODEX_Ciphers::RSAPrivateKey& key = serverState->privateKey();
00216          signature = key.sign( digest );
00217          BN_free(digest);
00218          digest = 0;
00219          if ( 0 == signature )
00220          {
00221             throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00222          }
00223       }
00224       catch ( ... )
00225       {
00226          if ( 0 != digest ) BN_free( digest );
00227          if ( 0 != signature ) delete signature;
00228 #ifdef TIMING
00229          ActiveTimer.stop();
00230 #endif
00231          throw;
00232       }
00233       SignedFinishedMsg signedFM( fm, *signature );
00234       delete signature;
00235 
00236       // Create the marshalled message.
00237       CODEX_Quorum::Message m;
00238       m.fill( serverState->hostNum() |
00239               CODEX_Server::ServerState::OutgoingMask );
00240       const unsigned char* seqNum = serverState->newSequenceNumber();
00241       m.fill( seqNum, CODEX_Server::ServerState::nMID );
00242       m.fill( stateInfo->domain() );
00243       m.fill( kFinishedMsg | SignatureMask );
00244       int length = signedFM.marshal(0);
00245       unsigned char* buffer = new unsigned char[length];
00246       unsigned char* pBuffer = buffer;
00247       signedFM.marshal(&pBuffer);
00248       m.fill( buffer, length );
00249       delete [] buffer;
00250 
00251       // Broadcast finished message.  No callback is registered.
00252       stateInfo->broadcast( m, 0 );
00253 
00254       m_completed = true;
00255 
00256 #ifdef TIMING
00257       ComputeTimer[m_label.num().value()].stop();
00258 #endif
00259 
00260    }
00261 
00262 #ifdef TIMING
00263    ActiveTimer.stop();
00264 #endif
00265    return true;
00266 }

Generated on Fri May 6 17:38:58 2005 for COrnell Data EXchange (CODEX) by  doxygen 1.4.1