ThreadedSocketConnection.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 "ThreadedSocketConnection.h"
00027 #include "ThreadedSocketAcceptor.h"
00028 #include "ThreadedSocketInitiator.h"
00029 #include "Session.h"
00030 #include "Utility.h"
00031 
00032 namespace FIX
00033 {
00034 ThreadedSocketConnection::ThreadedSocketConnection
00035 ( int s, Sessions sessions, Log* pLog )
00036 : m_socket( s ), m_pLog( pLog ),
00037   m_sessions( sessions ), m_pSession( 0 ),
00038   m_disconnect( false )
00039 {
00040   FD_ZERO( &m_fds );
00041   FD_SET( m_socket, &m_fds );
00042 }
00043 
00044 ThreadedSocketConnection::ThreadedSocketConnection
00045 ( const SessionID& sessionID, int s,
00046   const std::string& address, short port, 
00047   Log* pLog )
00048   : m_socket( s ), m_address( address ), m_port( port ),
00049     m_pLog( pLog ),
00050     m_pSession( Session::lookupSession( sessionID ) ),
00051     m_disconnect( false )
00052 {
00053   FD_ZERO( &m_fds );
00054   FD_SET( m_socket, &m_fds );
00055   if ( m_pSession ) m_pSession->setResponder( this );
00056 }
00057 
00058 ThreadedSocketConnection::~ThreadedSocketConnection()
00059 {
00060   if ( m_pSession )
00061   {
00062     m_pSession->setResponder( 0 );
00063     Session::unregisterSession( m_pSession->getSessionID() );
00064   }
00065 }
00066 
00067 bool ThreadedSocketConnection::send( const std::string& msg )
00068 {
00069   int totalSent = 0;
00070   while(totalSent < (int)msg.length())
00071   {
00072     int sent = socket_send( m_socket, msg.c_str() + totalSent, msg.length() );
00073     if(sent < 0) return false;
00074     totalSent += sent;
00075   }
00076 
00077   return true;
00078 }
00079 
00080 bool ThreadedSocketConnection::connect()
00081 {
00082   return socket_connect(getSocket(), m_address.c_str(), m_port) >= 0;
00083 }
00084 
00085 void ThreadedSocketConnection::disconnect()
00086 {  
00087   m_disconnect = true;
00088   socket_close( m_socket );
00089 }
00090 
00091 bool ThreadedSocketConnection::read()
00092 {
00093   struct timeval timeout = { 1, 0 };
00094   fd_set readset = m_fds;
00095 
00096   try
00097   {
00098     // Wait for input (1 second timeout)
00099     int result = select( 1 + m_socket, &readset, 0, 0, &timeout );
00100 
00101     if( result > 0 ) // Something to read
00102     {
00103       // We can read without blocking
00104       int size = recv( m_socket, m_buffer, sizeof(m_buffer), 0 );
00105       if ( size <= 0 ) { throw SocketRecvFailed( size ); }
00106       m_parser.addToStream( m_buffer, size );
00107     }
00108     else if( result == 0 && m_pSession ) // Timeout
00109     {
00110       m_pSession->next();
00111     }
00112     else if( result < 0 ) // Error
00113     {
00114       throw SocketRecvFailed( result );
00115     }
00116 
00117     processStream();
00118     return true;
00119   }
00120   catch ( SocketRecvFailed& e )
00121   {
00122     if( m_disconnect )
00123       return false;
00124 
00125     if( m_pSession )
00126     {
00127       m_pSession->getLog()->onEvent( e.what() );
00128       m_pSession->disconnect();
00129     }
00130     else
00131     {
00132       disconnect();
00133     }
00134 
00135     return false;
00136   }
00137 }
00138 
00139 bool ThreadedSocketConnection::readMessage( std::string& msg )
00140 throw( SocketRecvFailed )
00141 {
00142   try
00143   {
00144     return m_parser.readFixMessage( msg );
00145   }
00146   catch ( MessageParseError& ) {}
00147   return true;
00148 }
00149 
00150 void ThreadedSocketConnection::processStream()
00151 {
00152   std::string msg;
00153   while( readMessage(msg) )
00154   {
00155     if ( !m_pSession )
00156     {
00157       if ( !setSession( msg ) )
00158       { disconnect(); continue; }
00159     }
00160     try
00161     {
00162       m_pSession->next( msg, UtcTimeStamp() );
00163     }
00164     catch( InvalidMessage& )
00165     {
00166       if( !m_pSession->isLoggedOn() )
00167       {
00168         disconnect();
00169         return;
00170       }
00171     }
00172   }
00173 }
00174 
00175 bool ThreadedSocketConnection::setSession( const std::string& msg )
00176 {
00177   m_pSession = Session::lookupSession( msg, true );
00178   if ( !m_pSession ) 
00179   {
00180     if( m_pLog )
00181     {
00182       m_pLog->onEvent( "Session not found for incoming message: " + msg );
00183       m_pLog->onIncoming( msg );
00184     }
00185     return false;
00186   }
00187 
00188   SessionID sessionID = m_pSession->getSessionID();
00189   m_pSession = 0;
00190 
00191   // see if the session frees up within 5 seconds
00192   for( int i = 1; i <= 5; i++ )
00193   {
00194     if( !Session::isSessionRegistered( sessionID ) )
00195       m_pSession = Session::registerSession( sessionID );
00196     if( m_pSession ) break;
00197     process_sleep( 1 );
00198   }
00199 
00200   if ( !m_pSession ) 
00201     return false;
00202   if ( m_sessions.find(m_pSession->getSessionID()) == m_sessions.end() )
00203     return false;
00204 
00205   m_pSession->setResponder( this );
00206   return true;
00207 }
00208 
00209 } // namespace FIX

Generated on Mon Jun 23 2014 23:49:38 for QuickFIX by doxygen 1.7.6.1 written by Dimitri van Heesch, © 1997-2001