SocketInitiator.cpp
Go to the documentation of this file.
00001 /****************************************************************************
00002 ** Copyright (c) 2001-2014
00003 **
00004 ** This file is part of the QuickFIX FIX Engine
00005 **
00006 ** This file may be distributed under the terms of the quickfixengine.org
00007 ** license as defined by quickfixengine.org and appearing in the file
00008 ** LICENSE included in the packaging of this file.
00009 **
00010 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00011 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00012 **
00013 ** See http://www.quickfixengine.org/LICENSE for licensing information.
00014 **
00015 ** Contact ask@quickfixengine.org if any conditions of this licensing are
00016 ** not clear to you.
00017 **
00018 ****************************************************************************/
00019 
00020 #ifdef _MSC_VER
00021 #include "stdafx.h"
00022 #else
00023 #include "config.h"
00024 #endif
00025 
00026 #include "SocketInitiator.h"
00027 #include "Session.h"
00028 #include "Settings.h"
00029 
00030 namespace FIX
00031 {
00032 SocketInitiator::SocketInitiator( Application& application,
00033                                   MessageStoreFactory& factory,
00034                                   const SessionSettings& settings )
00035 throw( ConfigError )
00036 : Initiator( application, factory, settings ),
00037   m_connector( 1 ), m_lastConnect( 0 ),
00038   m_reconnectInterval( 30 ), m_noDelay( false ), m_sendBufSize( 0 ),
00039   m_rcvBufSize( 0 ) 
00040 {
00041 }
00042 
00043 SocketInitiator::SocketInitiator( Application& application,
00044                                   MessageStoreFactory& factory,
00045                                   const SessionSettings& settings,
00046                                   LogFactory& logFactory )
00047 throw( ConfigError )
00048 : Initiator( application, factory, settings, logFactory ),
00049   m_connector( 1 ), m_lastConnect( 0 ),
00050   m_reconnectInterval( 30 ), m_noDelay( false ), m_sendBufSize( 0 ),
00051   m_rcvBufSize( 0 )
00052 {
00053 }
00054 
00055 SocketInitiator::~SocketInitiator()
00056 {
00057   SocketConnections::iterator i;
00058   for (i = m_connections.begin();
00059        i != m_connections.end(); ++i)
00060     delete i->second;
00061 
00062   for (i = m_pendingConnections.begin();
00063        i != m_pendingConnections.end(); ++i)
00064     delete i->second;
00065 }
00066 
00067 void SocketInitiator::onConfigure( const SessionSettings& s )
00068 throw ( ConfigError )
00069 {
00070   const Dictionary& dict = s.get();
00071 
00072   if( dict.has( RECONNECT_INTERVAL ) )
00073     m_reconnectInterval = dict.getInt( RECONNECT_INTERVAL );
00074   if( dict.has( SOCKET_NODELAY ) )
00075     m_noDelay = dict.getBool( SOCKET_NODELAY );
00076   if( dict.has( SOCKET_SEND_BUFFER_SIZE ) )
00077     m_sendBufSize = dict.getInt( SOCKET_SEND_BUFFER_SIZE );
00078   if( dict.has( SOCKET_RECEIVE_BUFFER_SIZE ) )
00079     m_rcvBufSize = dict.getInt( SOCKET_RECEIVE_BUFFER_SIZE );
00080 }
00081 
00082 void SocketInitiator::onInitialize( const SessionSettings& s )
00083 throw ( RuntimeError )
00084 {
00085 }
00086 
00087 void SocketInitiator::onStart()
00088 {
00089   connect();
00090 
00091   while ( !isStopped() ) {
00092     m_connector.block( *this, false, 1.0 );
00093     onTimeout( m_connector );
00094   }
00095 
00096   time_t start = 0;
00097   time_t now = 0;
00098 
00099   ::time( &start );
00100   while ( isLoggedOn() )
00101   {
00102     m_connector.block( *this );
00103     if( ::time(&now) -5 >= start )
00104       break;
00105   }
00106 }
00107 
00108 bool SocketInitiator::onPoll( double timeout )
00109 {
00110   time_t start = 0;
00111   time_t now = 0;
00112 
00113   if( isStopped() )
00114   {
00115     if( start == 0 )
00116       ::time( &start );
00117     if( !isLoggedOn() )
00118       return false;
00119     if( ::time(&now) - 5 >= start )
00120       return false;
00121   }
00122 
00123   m_connector.block( *this, true, timeout );
00124   return true;
00125 }
00126 
00127 void SocketInitiator::onStop()
00128 {
00129 }
00130 
00131 void SocketInitiator::doConnect( const SessionID& s, const Dictionary& d )
00132 {
00133   try
00134   {
00135     std::string address;
00136     short port = 0;
00137     Session* session = Session::lookupSession( s );
00138     if( !session->isSessionTime(UtcTimeStamp()) ) return;
00139 
00140     Log* log = session->getLog();
00141 
00142     getHost( s, d, address, port );
00143 
00144     log->onEvent( "Connecting to " + address + " on port " + IntConvertor::convert((unsigned short)port) );
00145     int result = m_connector.connect( address, port, m_noDelay, m_sendBufSize, m_rcvBufSize );
00146     setPending( s );
00147 
00148     m_pendingConnections[ result ] 
00149       = new SocketConnection( *this, s, result, &m_connector.getMonitor() );
00150   }
00151   catch ( std::exception& ) {}
00152 }
00153 
00154 void SocketInitiator::onConnect( SocketConnector&, int s )
00155 {
00156   SocketConnections::iterator i = m_pendingConnections.find( s );
00157   if( i == m_pendingConnections.end() ) return;
00158   SocketConnection* pSocketConnection = i->second;
00159   
00160   m_connections[s] = pSocketConnection;
00161   m_pendingConnections.erase( i );
00162   setConnected( pSocketConnection->getSession()->getSessionID() );
00163   pSocketConnection->onTimeout();
00164 }
00165 
00166 void SocketInitiator::onWrite( SocketConnector& connector, int s )
00167 {
00168   SocketConnections::iterator i = m_connections.find( s );
00169   if ( i == m_connections.end() ) return ;
00170   SocketConnection* pSocketConnection = i->second;
00171   if( pSocketConnection->processQueue() )
00172     pSocketConnection->unsignal();
00173 }
00174 
00175 bool SocketInitiator::onData( SocketConnector& connector, int s )
00176 {
00177   SocketConnections::iterator i = m_connections.find( s );
00178   if ( i == m_connections.end() ) return false;
00179   SocketConnection* pSocketConnection = i->second;
00180   return pSocketConnection->read( connector );
00181 }
00182 
00183 void SocketInitiator::onDisconnect( SocketConnector&, int s )
00184 {
00185   SocketConnections::iterator i = m_connections.find( s );
00186   SocketConnections::iterator j = m_pendingConnections.find( s );
00187 
00188   SocketConnection* pSocketConnection = 0;
00189   if( i != m_connections.end() ) 
00190     pSocketConnection = i->second;
00191   if( j != m_pendingConnections.end() )
00192     pSocketConnection = j->second;
00193   if( !pSocketConnection )
00194     return;
00195 
00196   setDisconnected( pSocketConnection->getSession()->getSessionID() );
00197 
00198   Session* pSession = pSocketConnection->getSession();
00199   if ( pSession )
00200   {
00201     pSession->disconnect();
00202     setDisconnected( pSession->getSessionID() );
00203   }
00204 
00205   delete pSocketConnection;
00206   m_connections.erase( s );
00207   m_pendingConnections.erase( s );
00208 }
00209 
00210 void SocketInitiator::onError( SocketConnector& connector )
00211 {
00212   onTimeout( connector );
00213 }
00214 
00215 void SocketInitiator::onTimeout( SocketConnector& )
00216 {
00217   time_t now;
00218   ::time( &now );
00219 
00220   if ( (now - m_lastConnect) >= m_reconnectInterval )
00221   {
00222     connect();
00223     m_lastConnect = now;
00224   }
00225 
00226   SocketConnections::iterator i;
00227   for ( i = m_connections.begin(); i != m_connections.end(); ++i )
00228     i->second->onTimeout();
00229 }
00230 
00231 void SocketInitiator::getHost( const SessionID& s, const Dictionary& d,
00232                                std::string& address, short& port )
00233 {
00234   int num = 0;
00235   SessionToHostNum::iterator i = m_sessionToHostNum.find( s );
00236   if ( i != m_sessionToHostNum.end() ) num = i->second;
00237 
00238   std::stringstream hostStream;
00239   hostStream << SOCKET_CONNECT_HOST << num;
00240   std::string hostString = hostStream.str();
00241 
00242   std::stringstream portStream;
00243   portStream << SOCKET_CONNECT_PORT << num;
00244   std::string portString = portStream.str();
00245 
00246   if( d.has(hostString) && d.has(portString) )
00247   {
00248     address = d.getString( hostString );
00249     port = ( short ) d.getInt( portString );
00250   }
00251   else
00252   {
00253     num = 0;
00254     address = d.getString( SOCKET_CONNECT_HOST );
00255     port = ( short ) d.getInt( SOCKET_CONNECT_PORT );
00256   }
00257 
00258   m_sessionToHostNum[ s ] = ++num;
00259 }
00260 }

Generated on Mon Sep 15 2014 01:23:55 for QuickFIX by doxygen 1.7.6.1 written by Dimitri van Heesch, © 1997-2001