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

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