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

codex_server.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: codex_server.cc,v 1.6 2005/01/21 19:44:16 mmarsh Exp $
00008 //
00009 // $Log: codex_server.cc,v $
00010 // Revision 1.6  2005/01/21 19:44:16  mmarsh
00011 // Updated for compatibility with Doxygen 1.4.1
00012 //
00013 // Revision 1.5  2004/05/19 15:56:46  mmarsh
00014 // *** empty log message ***
00015 //
00016 // Revision 1.4  2003/11/06 21:45:35  mmarsh
00017 // Removed ppk parameter, fixed a typo, and added in a couple of missing
00018 // variables.
00019 //
00020 // Revision 1.3  2003/11/06 18:11:51  mmarsh
00021 // Cleaned up doxygen page label and title.
00022 //
00023 // Revision 1.2  2003/11/04 22:07:35  mmarsh
00024 // General code cleanup and reorganization.
00025 //
00026 //
00027 
00133 #include <unistd.h>
00134 #include <signal.h>
00135 #include <openssl/ssl.h>
00136 #include <openssl/rand.h>
00137 
00138 // global state and general information
00139 #include "CODEX_Server/ServerState.h"
00140 #include "CODEX_KeyService/StateInfo.h"
00141 #include "CODEX_APSS/StateInfo.h"
00142 #include "CODEX_Events/DelayedEvent.h"
00143 
00144 // quorum management
00145 #include "CODEX_Server/InternalServer.h"
00146 #include "CODEX_Server/QuorumBuilderAct.h"
00147 #include "CODEX_Server/ServerMessageDispatcher.h"
00148 #include "CODEX_Server/ServerQuorumDispatcher.h"
00149 #include "CODEX_Server/SignRequestHandler.h"
00150 #include "CODEX_Server/ServerResponseHandler.h"
00151 #include "CODEX_Server/BroadcastRequestHandler.h"
00152 #include "CODEX_Server/UnicastRequestHandler.h"
00153 
00154 #include "CODEX_Server/ShareLabelChallengeHandler.h"
00155 #include "CODEX_Server/ShareLabelChallengeEvent.h"
00156 
00157 // client management
00158 #include "CODEX_KeyService/ClientServer.h"
00159 #include "CODEX_KeyService/ClientActivity.h"
00160 #include "CODEX_KeyService/ClientMessageEvent.h"
00161 #include "CODEX_KeyService/ClientMessageVerifier.h"
00162 
00163 // client delegation
00164 #include "CODEX_KeyService/DelegateRequestDistributor.h"
00165 #include "CODEX_KeyService/ClientMessageParser.h"
00166 #include "CODEX_KeyService/ClientResponseParser.h"
00167 #include "CODEX_KeyService/RoutedClientMessageVerifier.h"
00168 #include "CODEX_KeyService/DelegateResponseVerifier.h"
00169 #include "CODEX_KeyService/ClientMessageSigner.h"
00170 #include "CODEX_KeyService/ClientResponseSigner.h"
00171 
00172 // threshold cryptography
00173 
00174 // APSS
00175 #include "CODEX_APSS/MessageDeliverer.h"
00176 #include "CODEX_APSS/MessageProcessor.h"
00177 #include "CODEX_APSS/MessageVerifier.h"
00178 #include "CODEX_APSS/MessageParser.h"
00179 #include "CODEX_APSS/TriggerActivity.h"
00180 
00181 // exceptions
00182 #include "CODEX_Ciphers/CipherExceptions.h"
00183 #include "CODEX_Server/ServerExceptions.h"
00184 #include "CODEX_Server/ConfigurationExceptions.h"
00185 
00186 // This is used for signal handling.
00187 bool running;
00188 
00189 // These are used for simulating a slow processor.
00190 bool SlowServer = false;
00191 long int ServerDelayS = 0;
00192 long int ServerDelayUS = 0;
00193 long int ServerSlowdown = 0;
00194 
00195 // These are used for simulating a slow link.
00196 bool SlowLink = false;
00197 long int LinkDelayS = 0;
00198 long int LinkDelayUS = 0;
00199 long int CODEX_Events::DelayedEvent::sDelay;
00200 long int CODEX_Events::DelayedEvent::usDelay;
00201 
00202 void handle_interrupt(int signal)
00203 {
00204    running = false;
00205 }
00206 
00207 void handle_crash(int signal)
00208 {
00209    cerr << "Fatal error, signal " << signal << endl;
00210    ::exit(1);
00211 }
00212 
00213 void
00214 configure_server(int argc, char** argv)
00215 {
00216    int arg = 0;
00217    string config_file;
00218    string config_section;
00219    string usage_string = "Usage: codex_server -c <config_file> [-s <section>]";
00220    while ( -1 != arg )
00221    {
00222       arg = getopt(argc,argv,"c:s:");
00223       switch(arg)
00224       {
00225          case 'c' :
00226             config_file = optarg;
00227             break;
00228          case 's' :
00229             config_section = optarg;
00230             break;
00231          case ':' :
00232          case '?' :
00233             cerr << usage_string << endl;
00234             ::exit(1);
00235       }
00236    }
00237    if ( 0 == config_file.size() )
00238    {
00239       cerr << usage_string << endl;
00240       ::exit(1);
00241    }
00242 
00243    // Configure the server.
00244    CONF* conf = 0;
00245    try
00246    {
00247       conf = NCONF_new(NCONF_default());
00248       if ( 0 == NCONF_load(conf,config_file.c_str(),0) )
00249       {
00250          throw CODEX_Exceptions::FileCannotOpenException( __FILE__ ,
00251                                                           __LINE__ ,
00252                                                           config_file );
00253       }
00254       const char* sec = config_section.c_str();
00255       CODEX_Server::ServerState::instance()->configure(
00256          conf, sec, config_file );
00257       CODEX_KeyService::StateInfo::instance()->configure(
00258          conf, sec, config_file );
00259       CODEX_APSS::StateInfo::instance()->configure(
00260          conf, sec, config_file );
00261 
00262       // This is testing configuration, and shouldn't be used in general.
00263       // That's why these parameters are not mentioned in the comments
00264       // for the executable.
00265       long dummy;
00266       if ( NCONF_get_number_e(conf,sec,"slow_server",&dummy) )
00267       {
00268          if ( dummy != 0 )
00269          {
00270             SlowServer = true;
00271 
00272             // Get delays
00273             if (NCONF_get_number_e(conf,sec,"server_delay_s",&ServerDelayS))
00274             {
00275                if ( ServerDelayS < 0 )
00276                {
00277                   throw CODEX_Server::BCBadValueException(
00278                      __FILE__ , __LINE__ , config_file, "server_delay_s" );
00279                }
00280             }
00281             if (NCONF_get_number_e(conf,sec,"server_delay_us",&ServerDelayUS))
00282             {
00283                if ( ServerDelayUS < 0 )
00284                {
00285                   throw CODEX_Server::BCBadValueException(
00286                      __FILE__ , __LINE__ , config_file, "server_delay_us" );
00287                }
00288             }
00289             if (NCONF_get_number_e(conf,sec,"server_slowdown",&ServerSlowdown))
00290             {
00291                if ( ServerSlowdown < 0 )
00292                {
00293                   throw CODEX_Server::BCBadValueException(
00294                      __FILE__ , __LINE__ , config_file, "server_slowdown" );
00295                }
00296             }
00297 
00298             cout << "Simulating a slow processor with a delay of "
00299                  << ServerDelayS << "s, "
00300                  << ServerDelayUS << "us "
00301                  << " and slowdown of " << ServerSlowdown << "%"
00302                  << endl;
00303          }
00304       }
00305       if ( NCONF_get_number_e(conf,sec,"slow_link",&dummy) )
00306       {
00307          if ( dummy != 0 )
00308          {
00309             SlowLink = true;
00310 
00311             // Get delays
00312             if (NCONF_get_number_e(conf,sec,"link_delay_s",&LinkDelayS))
00313             {
00314                if ( LinkDelayS < 0 )
00315                {
00316                   throw CODEX_Server::BCBadValueException(
00317                      __FILE__ , __LINE__ , config_file, "link_delay_s" );
00318                }
00319             }
00320             if (NCONF_get_number_e(conf,sec,"link_delay_us",&LinkDelayUS))
00321             {
00322                if ( LinkDelayUS < 0 )
00323                {
00324                   throw CODEX_Server::BCBadValueException(
00325                      __FILE__ , __LINE__ , config_file, "link_delay_us" );
00326                }
00327             }
00328 
00329             cout << "Simulating a slow link with a delay of "
00330                  << LinkDelayS << "s, "
00331                  << LinkDelayUS << "us"
00332                  << endl;
00333             CODEX_Events::DelayedEvent::sDelay = LinkDelayS;
00334             CODEX_Events::DelayedEvent::usDelay = LinkDelayUS;
00335          }
00336       }
00337 
00338       // Clean up the configuration file pointer.
00339       NCONF_free( conf );
00340    }
00341    catch ( CODEX_Exceptions::ExceptionBase& e )
00342    {
00343       if ( 0 != conf ) NCONF_free(conf);
00344       e.report();
00345       throw;
00346    }
00347 }
00348 
00352 void
00353 check_client_servers()
00354 {
00355    fd_set read_set;
00356    fd_set write_set;
00357    FD_ZERO( &read_set );
00358    FD_ZERO( &write_set );
00359    int smax=0;
00360    CODEX_Server::ServerState* serverState =
00361       CODEX_Server::ServerState::instance();
00362 
00363    CODEX_Server::ServerState::ServerList::const_iterator cServItr =
00364       serverState->serverListBegin();
00365    for ( ; cServItr != serverState->serverListEnd() ; ++cServItr )
00366    {
00367       int s = (*cServItr)->set_fd( &read_set,
00368                                    CODEX_Quorum::SocketBase::kRead );
00369       (*cServItr)->set_fd( &write_set, CODEX_Quorum::SocketBase::kWrite );
00370       smax = ( s > smax ) ? s : smax;
00371    }
00372 
00373    struct timeval async_timeout;
00374    async_timeout.tv_sec = 0;
00375    async_timeout.tv_usec = 0;
00376 
00377    // ignore errors from select(2)
00378    if ( 0 < select( smax+1, &read_set, &write_set, 0, &async_timeout ) )
00379    {
00380       for ( cServItr = serverState->serverListBegin() ;
00381             cServItr != serverState->serverListEnd() ;
00382             ++cServItr )
00383       {
00384          CODEX_Quorum::LocalServer* cs = *cServItr;
00385 
00386          // We take a harsh view towards errors involving clients.
00387          // If there's a problem, we kill the connection.
00388          try
00389          {
00390             // Do we need to read?
00391             if ( cs->isset_fd(&read_set,CODEX_Quorum::SocketBase::kRead) )
00392             {
00393                cs->processRequest(CODEX_Quorum::SocketBase::kRead);
00394             }
00395 
00396             // Do we need to write?
00397             if ( cs->isset_fd(&write_set,CODEX_Quorum::SocketBase::kWrite) )
00398             {
00399                cs->processRequest(CODEX_Quorum::SocketBase::kWrite);
00400             }
00401          }
00402          catch ( ... )
00403          {
00404             // Remove this server from serverList and back up.
00405             --cServItr;
00406             serverState->removeServer( cs );
00407          }
00408       }
00409    }
00410 }
00411 
00415 void
00416 process_next_event( CODEX_Events::QType& eventQueue )
00417 {
00418    if ( eventQueue.empty() ) return;
00419    CODEX_Events::EventBase* event = eventQueue.front();
00420    eventQueue.pop();
00421 
00422    if ( SlowServer )
00423    {
00424       struct timeval tv;
00425       tv.tv_sec  = ServerDelayS;
00426       tv.tv_usec = ServerDelayUS;
00427       select(0,0,0,0,&tv);
00428    }
00429    if ( event->handle() )
00430    {
00431       delete event;
00432    }
00433    else
00434    {
00435       // Event wasn't successfully handled yet.
00436       eventQueue.push(event);
00437    }
00438 }
00439 
00443 void
00444 consume_queue( CODEX_Events::QType& eventQueue )
00445 {
00446    while ( ! eventQueue.empty() )
00447    {
00448       delete eventQueue.front();
00449       eventQueue.pop();
00450    }
00451 }
00452 
00453 void
00454 move_delayed_events( CODEX_Events::QType& delayedEventQueue,
00455                      CODEX_Events::QType& eventQueue )
00456 {
00457    while ( ! delayedEventQueue.empty() )
00458    {
00459       eventQueue.push(
00460          new CODEX_Events::DelayedEvent( delayedEventQueue.front() ) );
00461       delayedEventQueue.pop();
00462    }
00463 }
00464 
00468 void
00469 garbage_collect_activities( CODEX_Events::DeadPileType& deadPile )
00470 {
00471    while ( deadPile.size() > 0 )
00472    {
00473       CODEX_Events::Activity* act = deadPile.back();
00474       deadPile.pop_back();
00475       delete act;
00476    }
00477 }
00478 
00482 void
00483 garbage_collect_servers()
00484 {
00485    CODEX_Server::ServerState* serverState =
00486       CODEX_Server::ServerState::instance();
00487    if ( 0 == serverState ) return;
00488    serverState->garbageCollectServers();
00489 }
00490 
00491 
00492 int main( int argc, char** argv )
00493 {
00494    //============================================================
00495    // Grab the server state object.
00496    //============================================================
00497    CODEX_Server::ServerState* serverState =
00498       CODEX_Server::ServerState::instance();
00499    CODEX_KeyService::StateInfo* keyServiceState =
00500       CODEX_KeyService::StateInfo::instance();
00501    CODEX_APSS::StateInfo* apssState = CODEX_APSS::StateInfo::instance();
00502 
00503 
00504    //============================================================
00505    // Seed the random number generator.
00506    //============================================================
00507    unsigned char seed[40] = 
00508    {0x38,0x4F,0x67,0x4C,0xA6,0x02,0x3D,0x9E,
00509     0x69, 0x2c, 0x3f, 0xfd, 0x98, 0x50, 0xcc,
00510     0x76, 0xfa, 0x78, 0x34, 0x12, 0x23, 0xdf,
00511     0x8a, 0xd4, 0x34, 0xcd, 0x98, 0x59, 0x19,
00512     0x35, 0x4f, 0xda, 0xed, 0x4e, 0x99, 0x0f};
00513    RAND_seed(seed,40);
00514 
00515 
00516    //============================================================
00517    // Load SSLeay algorithms
00518    //============================================================
00519    SSL_load_error_strings();
00520    SSLeay_add_ssl_algorithms();
00521 
00522 
00523    //============================================================
00524    // Catch interrupts, which should halt the main loop.
00525    //============================================================
00526    signal(SIGINT,handle_interrupt);
00527    //signal(SIGSEGV,handle_crash);
00528 
00529 
00530    //============================================================
00531    // Process the command line and configure the server.
00532    //============================================================
00533    cout << "Configuring server..." << endl;
00534    configure_server(argc,argv);
00535    cout << "...Server configuration done" << endl;
00536 
00537 
00538    //============================================================
00539    // Set up the bookkeeping objects for the concurrency system.
00540    //============================================================
00541    CODEX_Events::DeadPileType deadPile;
00542    CODEX_Events::QType eventQueue;
00543    CODEX_Events::QType delayedEventQueue;
00544    CODEX_Events::QType* pLinkQueue;
00545    if ( SlowLink )
00546    {
00547       pLinkQueue = &delayedEventQueue;
00548    }
00549    else
00550    {
00551       pLinkQueue = &eventQueue;
00552    }
00553    CODEX_Events::QType& linkQueue = *pLinkQueue;
00554    
00555 
00556    CODEX_Server::InternalServer is( serverState->serverPort(),
00557                                     serverState->serverInSocketBuilder() );
00558    serverState->addServer( &is );
00559    try
00560    {
00561       is.enable();
00562    }
00563    catch ( CODEX_Quorum::QSExceptionBase& e )
00564    {
00565       e.report();
00566       return 1;
00567    }
00568 
00569 
00570    //============================================================
00571    // Create top-level client servers and activities
00572    //============================================================
00573    CODEX_Server::BroadcastRequestHandler broadcastHandler( deadPile,
00574                                                            eventQueue );
00575    CODEX_Server::UnicastRequestHandler unicastHandler( deadPile,
00576                                                        eventQueue );
00577    CODEX_Server::ShareLabelChallengeHandler challengeHandler( deadPile,
00578                                                               eventQueue );
00579    CODEX_Server::SignRequestHandler signHandler( deadPile, eventQueue );
00580    CODEX_KeyService::DelegateRequestDistributor delegateDistributor(
00581       deadPile,
00582       eventQueue,
00583       &broadcastHandler,
00584       &signHandler );
00585    CODEX_KeyService::ClientMessageVerifier* clientMsgVerifier =
00586       new CODEX_KeyService::ClientMessageVerifier( deadPile,
00587                                                    eventQueue,
00588                                                    &delegateDistributor );
00589 
00590 
00591    //============================================================
00592    // Create an activity to connect to other quorum servers
00593    //============================================================
00594    CODEX_Server::QuorumBuilderAct* quorumBuilder =
00595       new CODEX_Server::QuorumBuilderAct( deadPile, eventQueue );
00596 
00597    CODEX_Server::ServerResponseHandler serverResponseHandler( deadPile,
00598                                                               eventQueue );
00599 
00600    //============================================================
00601    // Create a message dispatcher and attach parsers to it.
00602    //============================================================
00603    CODEX_Server::ServerMessageDispatcher messageDispatcher;
00604 
00605    // Read messages from client delegates.
00606    const unsigned char  clientMessageDomain = 1;
00607 
00608    CODEX_KeyService::ClientMessageSigner
00609       delegateMsgSigner( deadPile, eventQueue, &serverResponseHandler );
00610 
00611    CODEX_KeyService::RoutedClientMessageVerifier
00612       delegateVerifier( deadPile, eventQueue, &delegateMsgSigner );
00613 
00614    CODEX_KeyService::ClientMessageParser
00615       clientMessageParser( deadPile, linkQueue, &delegateVerifier );
00616 
00617    keyServiceState->setMessageDomain( clientMessageDomain );
00618    messageDispatcher.addParser( clientMessageDomain, &clientMessageParser );
00619 
00620    // Read supported responses from client delegates.
00621    const unsigned char  clientDelegateDomain = 2;
00622 
00623    CODEX_KeyService::ClientResponseSigner
00624       delegateRespSigner( deadPile, eventQueue, &serverResponseHandler );
00625 
00626    CODEX_KeyService::DelegateResponseVerifier
00627       delegateResponseVerifier( deadPile, eventQueue, &delegateRespSigner );
00628 
00629    CODEX_KeyService::ClientResponseParser
00630       clientResponseParser( deadPile, linkQueue, &delegateResponseVerifier );
00631 
00632    keyServiceState->setDelegationDomain( clientDelegateDomain );
00633    messageDispatcher.addParser( clientDelegateDomain, &clientResponseParser );
00634 
00635    // Read APSS protocol messages.
00636    const unsigned char  apssDomain = 3;
00637 
00638    CODEX_APSS::MessageProcessor
00639       apssProc( deadPile,
00640                 eventQueue,
00641                 &serverResponseHandler,
00642                 &unicastHandler );
00643 
00644    CODEX_APSS::MessageVerifier
00645       apssVerifier( deadPile, eventQueue, &apssProc, &serverResponseHandler );
00646 
00647    CODEX_APSS::MessageParser
00648       apssParser( deadPile, linkQueue, &apssVerifier );
00649 
00650    CODEX_APSS::MessageDeliverer
00651       apssDeliverer( deadPile,
00652                      eventQueue,
00653                      &serverResponseHandler,
00654                      &broadcastHandler );
00655    apssState->setMessageDeliverer( &apssDeliverer );
00656 
00657    apssState->setDomain( apssDomain );
00658    messageDispatcher.addParser( apssDomain, &apssParser );
00659 
00660    CODEX_APSS::TriggerActivity( deadPile, eventQueue );
00661 
00662    //============================================================
00663    // Create a quorum dispatcher.
00664    //============================================================
00665    CODEX_Server::ServerQuorumDispatcher quorumDispatcher;
00666 
00667 
00668    //============================================================
00669    // Set up the server that listens for new client connections.
00670    //============================================================
00671    CODEX_KeyService::ClientServer clientServer(
00672       keyServiceState->clientPort(),
00673       serverState->clientSocketBuilder(),
00674       deadPile,
00675       eventQueue,
00676       clientMsgVerifier );
00677    serverState->addServer( &clientServer );
00678    try
00679    {
00680       clientServer.enable();
00681    }
00682    catch ( CODEX_Quorum::QSExceptionBase& e )
00683    {
00684       e.report();
00685       return 1;
00686    }
00687 
00688 
00689    //============================================================
00690    // Get the configured quorum system.
00691    //============================================================
00692    CODEX_Quorum::QuorumSystem* quorumSystem = serverState->quorumSystem();
00693    if ( 0 == quorumSystem )
00694    {
00695       return 1;
00696    }
00697 
00698 
00699    //============================================================
00700    // main loop
00701    //============================================================
00702    running = true;
00703    while(running)
00704    {
00705       try
00706       {
00707          struct timeval tv;
00708          if ( SlowServer )
00709          {
00710             gettimeofday(&tv,0);
00711          }
00712 
00713          // Check for server-to-server activity.
00714          quorumSystem->poll( messageDispatcher, quorumDispatcher );
00715 
00716          // Check for client-server activity.
00717          check_client_servers();
00718 
00719          // Clean up any terminated Activitys.
00720          garbage_collect_activities( deadPile );
00721 
00722          // Clean up any terminated LocalServers.
00723          garbage_collect_servers();
00724 
00725          // Move delayed events into the normal queue.
00726          move_delayed_events( delayedEventQueue, eventQueue );
00727 
00728          // Process the next event, if any.
00729          process_next_event( eventQueue );
00730 
00731          if ( SlowServer )
00732          {
00733             // Now delay some fraction of the time just taken.
00734             // This is inexact, since select() is based on the wall clock.
00735             struct timeval delay;
00736             gettimeofday(&delay,0);
00737             long int t =
00738                ( delay.tv_sec - tv.tv_sec ) * 1000000 +
00739                ( delay.tv_usec - tv.tv_usec );
00740             t *= ServerSlowdown;
00741             t /= 100; // the slowdown is a percentage
00742             delay.tv_sec = t / 1000000;
00743             delay.tv_usec = t % 1000000;
00744             select(0,0,0,0,&delay);
00745          }
00746       }
00747       catch ( CODEX_Exceptions::ExceptionBase& e )
00748       {
00749          e.report();
00750          //backtrace_symbols_fd(0,0,fileno(stdout));
00751          running = false;
00752       }
00753    }
00754 
00755 
00756    //============================================================
00757    // Clean up.
00758    //============================================================
00759    garbage_collect_activities( deadPile );
00760    garbage_collect_servers();
00761    consume_queue( eventQueue );
00762    delete clientMsgVerifier;
00763    delete quorumBuilder;
00764    CODEX_KeyService::StateInfo::destroy();
00765    CODEX_APSS::StateInfo::destroy();
00766    CODEX_Server::ServerState::destroy();
00767    ERR_free_strings();
00768    ERR_remove_state(0);
00769    EVP_cleanup();
00770    RAND_cleanup();
00771 
00772 
00773    //============================================================
00774    // Now we're done.
00775    //============================================================
00776    return 0;
00777 }

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