SocketConnection.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 "SocketConnection.h"
00027 #include "SocketAcceptor.h"
00028 #include "SocketConnector.h"
00029 #include "SocketInitiator.h"
00030 #include "Session.h"
00031 #include "Utility.h"
00032 
00033 namespace FIX
00034 {
00035 SocketConnection::SocketConnection( int s, Sessions sessions,
00036                                     SocketMonitor* pMonitor )
00037 : m_socket( s ), m_sendLength( 0 ),
00038   m_sessions(sessions), m_pSession( 0 ), m_pMonitor( pMonitor )
00039 {
00040   FD_ZERO( &m_fds );
00041   FD_SET( m_socket, &m_fds );
00042 }
00043 
00044 SocketConnection::SocketConnection( SocketInitiator& i,
00045                                     const SessionID& sessionID, int s,
00046                                     SocketMonitor* pMonitor )
00047 : m_socket( s ), m_sendLength( 0 ),
00048   m_pSession( i.getSession( sessionID, *this ) ),
00049   m_pMonitor( pMonitor ) 
00050 {
00051   FD_ZERO( &m_fds );
00052   FD_SET( m_socket, &m_fds );
00053   m_sessions.insert( sessionID );
00054 }
00055 
00056 SocketConnection::~SocketConnection()
00057 {
00058   if ( m_pSession )
00059     Session::unregisterSession( m_pSession->getSessionID() );
00060 }
00061 
00062 bool SocketConnection::send( const std::string& msg )
00063 {
00064   Locker l( m_mutex );
00065 
00066   m_sendQueue.push_back( msg );
00067   processQueue();
00068   signal();
00069   return true;
00070 }
00071 
00072 bool SocketConnection::processQueue()
00073 {
00074   Locker l( m_mutex );
00075 
00076   if( !m_sendQueue.size() ) return true;
00077 
00078   struct timeval timeout = { 0, 0 };
00079   fd_set writeset = m_fds;
00080   if( select( 1 + m_socket, 0, &writeset, 0, &timeout ) <= 0 )
00081     return false;
00082     
00083   const std::string& msg = m_sendQueue.front();
00084 
00085   size_t result = socket_send
00086     ( m_socket, msg.c_str() + m_sendLength, msg.length() - m_sendLength );
00087 
00088   if( result > 0 )
00089     m_sendLength += result;
00090 
00091   if( m_sendLength == msg.length() )
00092   {
00093     m_sendLength = 0;
00094     m_sendQueue.pop_front();
00095   }
00096 
00097   return !m_sendQueue.size();
00098 }
00099 
00100 void SocketConnection::disconnect()
00101 {
00102   if ( m_pMonitor )
00103     m_pMonitor->drop( m_socket );
00104 }
00105 
00106 bool SocketConnection::read( SocketConnector& s )
00107 {
00108   if ( !m_pSession ) return false;
00109 
00110   try
00111   {
00112     readFromSocket();
00113     readMessages( s.getMonitor() );
00114   }
00115   catch( SocketRecvFailed& e )
00116   {
00117     m_pSession->getLog()->onEvent( e.what() );
00118     return false;
00119   }
00120   return true;
00121 }
00122 
00123 bool SocketConnection::read( SocketAcceptor& a, SocketServer& s )
00124 {
00125   std::string msg;
00126   try
00127   {
00128     if ( !m_pSession )
00129     {
00130       struct timeval timeout = { 1, 0 };
00131       fd_set readset = m_fds;
00132 
00133       while( !readMessage( msg ) )
00134       {
00135         int result = select( 1 + m_socket, &readset, 0, 0, &timeout );
00136         if( result > 0 )
00137           readFromSocket();
00138         else if( result == 0 )
00139           return false;
00140         else if( result < 0 )
00141           return false;
00142       }
00143 
00144       m_pSession = Session::lookupSession( msg, true );
00145       if( !isValidSession() )
00146       {
00147         m_pSession = 0;
00148         if( a.getLog() )
00149         {
00150           a.getLog()->onEvent( "Session not found for incoming message: " + msg );
00151           a.getLog()->onIncoming( msg );
00152         }
00153       }
00154       if( m_pSession )
00155         m_pSession = a.getSession( msg, *this );
00156       if( m_pSession )
00157         m_pSession->next( msg, UtcTimeStamp() );
00158       if( !m_pSession )
00159       {
00160         s.getMonitor().drop( m_socket );
00161         return false;
00162       }
00163 
00164       Session::registerSession( m_pSession->getSessionID() );
00165       return true;
00166     }
00167     else
00168     {
00169       readFromSocket();
00170       readMessages( s.getMonitor() );
00171       return true;
00172     }
00173   }
00174   catch ( SocketRecvFailed& e )
00175   {
00176     if( m_pSession )
00177       m_pSession->getLog()->onEvent( e.what() );
00178     s.getMonitor().drop( m_socket );
00179   }
00180   catch ( InvalidMessage& )
00181   {
00182     s.getMonitor().drop( m_socket );
00183   }
00184   return false;
00185 }
00186 
00187 bool SocketConnection::isValidSession()
00188 {
00189   if( m_pSession == 0 )
00190     return false;
00191   SessionID sessionID = m_pSession->getSessionID();
00192   if( Session::isSessionRegistered(sessionID) )
00193     return false;
00194   return !( m_sessions.find(sessionID) == m_sessions.end() );
00195 }
00196 
00197 void SocketConnection::readFromSocket()
00198 throw( SocketRecvFailed )
00199 {
00200   ssize_t size = recv( m_socket, m_buffer, sizeof(m_buffer), 0 );
00201   if( size <= 0 ) throw SocketRecvFailed( size );
00202   m_parser.addToStream( m_buffer, size );
00203 }
00204 
00205 bool SocketConnection::readMessage( std::string& msg )
00206 {
00207   try
00208   {
00209     return m_parser.readFixMessage( msg );
00210   }
00211   catch ( MessageParseError& ) {}
00212   return true;
00213 }
00214 
00215 void SocketConnection::readMessages( SocketMonitor& s )
00216 {
00217   if( !m_pSession ) return;
00218 
00219   std::string msg;
00220   while( readMessage( msg ) )
00221   {
00222     try
00223     {
00224       m_pSession->next( msg, UtcTimeStamp() );
00225     }
00226     catch ( InvalidMessage& )
00227     {
00228       if( !m_pSession->isLoggedOn() )
00229         s.drop( m_socket );
00230     }
00231   }
00232 }
00233 
00234 void SocketConnection::onTimeout()
00235 {
00236   if ( m_pSession ) m_pSession->next();
00237 }
00238 } // namespace FIX

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