Sleipnir
src/server.cpp
00001 /*****************************************************************************
00002 * This file is provided under the Creative Commons Attribution 3.0 license.
00003 *
00004 * You are free to share, copy, distribute, transmit, or adapt this work
00005 * PROVIDED THAT you attribute the work to the authors listed below.
00006 * For more information, please see the following web page:
00007 * http://creativecommons.org/licenses/by/3.0/
00008 *
00009 * This file is a component of the Sleipnir library for functional genomics,
00010 * authored by:
00011 * Curtis Huttenhower (chuttenh@princeton.edu)
00012 * Mark Schroeder
00013 * Maria D. Chikina
00014 * Olga G. Troyanskaya (ogt@princeton.edu, primary contact)
00015 *
00016 * If you use this library, the included executable tools, or any related
00017 * code in your work, please cite the following publication:
00018 * Curtis Huttenhower, Mark Schroeder, Maria D. Chikina, and
00019 * Olga G. Troyanskaya.
00020 * "The Sleipnir library for computational functional genomics"
00021 *****************************************************************************/
00022 #include "stdafx.h"
00023 #include "server.h"
00024 #include "serverclient.h"
00025 
00026 namespace Sleipnir {
00027 
00028 CServer*    CServerImpl::s_pServer      = NULL;
00029 const char* CServerImpl::c_szPort       = "port";
00030 const char* CServerImpl::c_szTimeout    = "timeout";
00031 
00059 bool CServer::Initialize( size_t iPort, size_t iTimeout, IServerClient* pServerClient ) {
00060 #ifndef _MSC_VER
00061     struct sigaction    Sigact;
00062 #endif // _MSC_VER
00063 
00064     m_pClient = pServerClient;
00065     m_iPort = iPort;
00066     m_iTimeout = iTimeout;
00067 #ifndef _MSC_VER
00068     Sigact.sa_handler = Alarm;
00069     memset( &Sigact.sa_mask, 0, sizeof(Sigact.sa_mask) );
00070     Sigact.sa_flags = 0;
00071     sigaction( SIGALRM, &Sigact, NULL );
00072 #endif // _MSC_VER
00073 
00074     return true; }
00075 
00076 #ifndef _MSC_VER
00077 void CServerImpl::Alarm( int iSig ) { }
00078 #endif // _MSC_VER
00079 
00096 bool CServer::Start( ) {
00097     sockaddr_in Addr;
00098     char        cOn;
00099 
00100 #ifdef _MSC_VER
00101     WSADATA     sWSA;
00102     WSAStartup( MAKEWORD(2, 0), &sWSA );
00103 #endif // _MSC_VER
00104 
00105     m_fStop = false;
00106     m_iSocket = socket( PF_INET, SOCK_STREAM, 0 );
00107     cOn = true;
00108     setsockopt( m_iSocket, SOL_SOCKET, SO_REUSEADDR, &cOn, sizeof(cOn) );
00109 
00110     Addr.sin_family = AF_INET;
00111     Addr.sin_port = htons( m_iPort );
00112     Addr.sin_addr.s_addr = INADDR_ANY;
00113     s_pServer = this;
00114     if( bind( m_iSocket, (const sockaddr*)&Addr, sizeof(Addr) ) ||
00115         listen( m_iSocket, INT_MAX ) ) {
00116 #ifdef _MSC_VER
00117         {
00118             char    acError[ 1024 ];
00119 
00120             strerror_s( acError, ARRAYSIZE(acError) - 1, errno );
00121             g_CatSleipnir( ).error( "CServer::Start( ) bind failed: %s", acError );
00122         }
00123 #else // _MSC_VER
00124         g_CatSleipnir( ).error( "CServer::Start( ) bind failed: %s", strerror( errno ) );
00125 #endif // _MSC_VER
00126         return false; }
00127 
00128     g_CatSleipnir( ).notice( "CServer::Start( ) bound to port %d", m_iPort );
00129     Listen( );
00130     g_CatSleipnir( ).info( "CServer::Start( ) preparing to shutdown..." );
00131 
00132 #ifdef _MSC_VER
00133     WSACleanup( );
00134 #endif // _MSC_VER
00135 
00136     return true; }
00137 
00138 void CServerImpl::Listen( ) {
00139     SOCKET              iClient;
00140     socklen_t           iSize;
00141     CServerClientImpl*  pClient;
00142     pthread_t           thrdClient;
00143     sockaddr_in         Addr;
00144 #ifndef _MSC_VER
00145     itimerval           Time;
00146 
00147     memset( &Time, 0, sizeof(Time) );
00148 #endif // _MSC_VER
00149     while( !m_fStop ) {
00150 #ifndef _MSC_VER
00151         Time.it_value.tv_usec = 1000 * m_iTimeout;
00152         setitimer( ITIMER_REAL, &Time, NULL );
00153         Time.it_value.tv_usec = 0;
00154 #endif // _MSC_VER
00155         iSize = sizeof(Addr);
00156         if( ( iClient = accept( m_iSocket, (sockaddr*)&Addr, &iSize ) ) == -1 )
00157             continue;
00158 #ifndef _MSC_VER
00159         setitimer( ITIMER_REAL, &Time, NULL );
00160 #endif // _MSC_VER
00161 
00162         pClient = new CServerClientImpl( iClient, m_pClient->NewInstance( iClient,
00163             iSize = ntohl( Addr.sin_addr.s_addr ), ntohs( Addr.sin_port ) ) );
00164         g_CatSleipnir( ).info( "CServer::Listen( ) client 0x%08x connected from %d.%d.%d.%d",
00165             pClient, ( iSize >> 24 ) & 0xFF, ( iSize >> 16 ) & 0xFF, ( iSize >> 8 ) & 0xFF,
00166             iSize & 0xFF );
00167         pthread_create( &thrdClient, NULL, CServerClientImpl::StartRoutine, pClient );
00168         pthread_detach( thrdClient ); } }
00169 
00170 }