Index  Source Files  Annotated Class List  Alphabetical Class List  Class Hierarchy  Graphical Class Hierarchy   
 

/home/orenmnero/autobuild/quickfix/src/C++/Session.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 ** Copyright (c) quickfixengine.org  All rights reserved.
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 #include "CallStack.h"
00026 
00027 #include "Session.h"
00028 #include "Values.h"
00029 #include <algorithm>
00030 #include <iostream>
00031 
00032 namespace FIX
00033 {
00034 Session::Sessions Session::s_sessions;
00035 Session::Sessions Session::s_registered;
00036 Mutex Session::s_mutex;
00037 
00038 #define LOGEX( method ) try { method; } catch( std::exception& e ) \
00039   { m_state.onEvent( e.what() ); }
00040 
00041 Session::Session( Application& application,
00042                   MessageStoreFactory& messageStoreFactory,
00043                   const SessionID& sessionID,
00044                   const DataDictionary& dataDictionary,
00045                   const SessionTime& sessionTime,
00046                   int heartBtInt, LogFactory* pLogFactory )
00047 : m_application( application ),
00048   m_sessionID( sessionID ),
00049   m_sessionTime( sessionTime ),
00050   m_checkCompId( true ),
00051   m_checkLatency( true ), 
00052   m_maxLatency( 120 ),
00053   m_resetOnLogon( false ),
00054   m_resetOnLogout( false ), 
00055   m_resetOnDisconnect( false ),
00056   m_millisecondsInTimeStamp( true ),
00057   m_dataDictionary( dataDictionary ),
00058   m_messageStoreFactory( messageStoreFactory ),
00059   m_pLogFactory( pLogFactory ),
00060   m_pResponder( 0 )
00061 {
00062   m_state.heartBtInt( heartBtInt );
00063   m_state.initiate( heartBtInt != 0 );
00064   m_state.store( m_messageStoreFactory.create( m_sessionID ) );
00065   if ( m_pLogFactory )
00066     m_state.log( m_pLogFactory->create( m_sessionID ) );
00067 
00068   if( !checkSessionTime( UtcTimeStamp() ) )
00069     reset();
00070 
00071   addSession( *this );
00072   m_application.onCreate( m_sessionID );
00073   m_state.onEvent( "Created session" );
00074 }
00075 
00076 Session::~Session()
00077 { QF_STACK_IGNORE_BEGIN
00078   removeSession( *this );
00079   m_messageStoreFactory.destroy( m_state.store() );
00080   if ( m_pLogFactory && m_state.log() )
00081     m_pLogFactory->destroy( m_state.log() );
00082   QF_STACK_IGNORE_END
00083 }
00084 
00085 void Session::insertSendingTime( Header& header )
00086 { QF_STACK_PUSH(Session::insertSendingTime)
00087 
00088   UtcTimeStamp now;
00089   bool showMilliseconds = m_sessionID.getBeginString() >= BeginString_FIX42;
00090   header.setField( SendingTime(now, showMilliseconds && m_millisecondsInTimeStamp) );
00091 
00092   QF_STACK_POP
00093 }
00094 
00095 void Session::insertOrigSendingTime( Header& header, const UtcTimeStamp& when )
00096 { QF_STACK_PUSH(Session::insertSendingTime)
00097 
00098   bool showMilliseconds = m_sessionID.getBeginString() >= BeginString_FIX42;
00099   header.setField( OrigSendingTime(when, showMilliseconds && m_millisecondsInTimeStamp) );
00100 
00101   QF_STACK_POP
00102 }
00103 
00104 void Session::fill( Header& header )
00105 { QF_STACK_PUSH(Session::fill)
00106 
00107   UtcTimeStamp now;
00108   m_state.lastSentTime( now );
00109   header.setField( m_sessionID.getBeginString() );
00110   header.setField( m_sessionID.getSenderCompID() );
00111   header.setField( m_sessionID.getTargetCompID() );
00112   header.setField( MsgSeqNum( getExpectedSenderNum() ) );
00113   insertSendingTime( header );
00114 
00115   QF_STACK_POP
00116 }
00117 
00118 void Session::next()
00119 { QF_STACK_PUSH(Session::next)
00120 
00121   try
00122   {
00123     if( !isEnabled() )
00124     {
00125       if( isLoggedOn() )
00126       {
00127         if( !m_state.sentLogout() )
00128         {
00129           m_state.onEvent( "Initiated logout request" );
00130           generateLogout( m_state.logoutReason() );
00131         }
00132       }
00133       else
00134         return;
00135     }
00136 
00137     UtcTimeStamp now;
00138     if ( !checkSessionTime( now ) )
00139       { reset(); return; }
00140 
00141     if ( !m_state.receivedLogon() )
00142     {
00143       if ( m_state.shouldSendLogon() )
00144       {
00145         generateLogon();
00146         m_state.onEvent( "Initiated logon request" );
00147       }
00148       else if ( m_state.alreadySentLogon() && m_state.logonTimedOut() )
00149       {
00150         m_state.onEvent( "Timed out waiting for logon response" );
00151         disconnect();
00152       }
00153       return ;
00154     }
00155 
00156     if ( m_state.heartBtInt() == 0 ) return ;
00157 
00158     if ( m_state.logoutTimedOut() )
00159     {
00160       m_state.onEvent( "Timed out waiting for logout response" );
00161       disconnect();
00162     }
00163 
00164     if ( m_state.withinHeartBeat() ) return ;
00165 
00166     if ( m_state.timedOut() )
00167     {
00168       m_state.onEvent( "Timed out waiting for heartbeat" );
00169       disconnect();
00170     }
00171     else
00172     {
00173       if ( m_state.needTestRequest() )
00174       {
00175         generateTestRequest( "TEST" );
00176         m_state.testRequest( m_state.testRequest() + 1 );
00177         m_state.onEvent( "Sent test request TEST" );
00178       }
00179       else if ( m_state.needHeartbeat() )
00180       {
00181         generateHeartbeat();
00182       }
00183     }
00184   }
00185   catch ( FIX::IOException& e )
00186   {
00187     m_state.onEvent( e.what() );
00188     disconnect();
00189   }
00190 
00191   QF_STACK_POP
00192 }
00193 
00194 void Session::nextLogon( const Message& logon )
00195 { QF_STACK_PUSH(Session::nextLogon)
00196 
00197   SenderCompID senderCompID;
00198   TargetCompID targetCompID;
00199   logon.getHeader().getField( senderCompID );
00200   logon.getHeader().getField( targetCompID );
00201 
00202   if( m_refreshOnLogon )
00203     refresh();
00204 
00205   ResetSeqNumFlag resetSeqNumFlag(false);
00206   if( logon.isSetField(resetSeqNumFlag) )
00207     logon.getField( resetSeqNumFlag );
00208   m_state.receivedReset( resetSeqNumFlag );
00209 
00210   if( m_state.receivedReset() )
00211   {
00212     m_state.onEvent( "Logon contains ResetSeqNumFlag=Y, reseting sequence numbers to 1" );
00213     if( !m_state.sentReset() ) m_state.reset();
00214   }
00215 
00216   if( m_state.shouldSendLogon() && !m_state.receivedReset() )
00217   {
00218     m_state.onEvent( "Received logon response before sending request" );
00219     disconnect();
00220     return ;
00221   }
00222 
00223   if( !m_state.shouldSendLogon() && m_resetOnLogon )
00224     m_state.reset();
00225 
00226   if( !verify( logon, false, true ) )
00227     return;
00228   m_state.receivedLogon( true );
00229 
00230   if ( !m_state.initiate() 
00231        || (m_state.sentReset() && !m_state.receivedReset()) )
00232   {
00233     if( logon.isSetField(m_state.heartBtInt()) )
00234       logon.getField( m_state.heartBtInt() );
00235     m_state.onEvent( "Received logon request" );
00236     generateLogon( logon );
00237     m_state.onEvent( "Responding to logon request" );
00238   }
00239   else
00240     m_state.onEvent( "Received logon response" );
00241 
00242   m_state.sentReset( false );
00243   m_state.receivedReset( false );
00244 
00245   MsgSeqNum msgSeqNum;
00246   logon.getHeader().getField( msgSeqNum );
00247   if ( isTargetTooHigh( msgSeqNum ) && !resetSeqNumFlag )
00248   {
00249     doTargetTooHigh( logon );
00250   }
00251   else
00252   {
00253     m_state.incrNextTargetMsgSeqNum();
00254     nextQueued();
00255   }
00256 
00257   if ( isLoggedOn() )
00258     m_application.onLogon( m_sessionID );
00259 
00260   QF_STACK_POP
00261 }
00262 
00263 void Session::nextHeartbeat( const Message& heartbeat )
00264 { QF_STACK_PUSH(Session::nextHeartbeat)
00265 
00266   if ( !verify( heartbeat ) ) return ;
00267   m_state.incrNextTargetMsgSeqNum();
00268   nextQueued();
00269 
00270   QF_STACK_POP
00271 }
00272 
00273 void Session::nextTestRequest( const Message& testRequest )
00274 { QF_STACK_PUSH(Session::nextTestRequest)
00275 
00276   if ( !verify( testRequest ) ) return ;
00277   generateHeartbeat( testRequest );
00278   m_state.incrNextTargetMsgSeqNum();
00279   nextQueued();
00280 
00281   QF_STACK_POP
00282 }
00283 
00284 void Session::nextLogout( const Message& logout )
00285 { QF_STACK_PUSH(Session::nextLogout)
00286 
00287   if ( !verify( logout, false, false ) ) return ;
00288   if ( !m_state.sentLogout() )
00289   {
00290     m_state.onEvent( "Received logout request" );
00291     generateLogout();
00292     m_state.onEvent( "Sending logout response" );
00293   }
00294   else
00295     m_state.onEvent( "Received logout response" );
00296 
00297   m_state.incrNextTargetMsgSeqNum();
00298   if ( m_resetOnLogout ) m_state.reset();
00299   disconnect();
00300 
00301   QF_STACK_POP
00302 }
00303 
00304 void Session::nextReject( const Message& reject )
00305 { QF_STACK_PUSH(Session::nextReject)
00306 
00307   if ( !verify( reject ) ) return ;
00308   m_state.incrNextTargetMsgSeqNum();
00309   nextQueued();
00310 
00311   QF_STACK_POP
00312 }
00313 
00314 void Session::nextSequenceReset( const Message& sequenceReset )
00315 { QF_STACK_PUSH(Session::nextSequenceReset)
00316 
00317   bool isGapFill = false;
00318   GapFillFlag gapFillFlag;
00319   if ( sequenceReset.isSetField( gapFillFlag ) )
00320   {
00321     sequenceReset.getField( gapFillFlag );
00322     isGapFill = gapFillFlag;
00323   }
00324 
00325   if ( !verify( sequenceReset, isGapFill, isGapFill ) ) return ;
00326 
00327   NewSeqNo newSeqNo;
00328   if ( sequenceReset.isSetField( newSeqNo ) )
00329   {
00330     sequenceReset.getField( newSeqNo );
00331 
00332     m_state.onEvent( "Received SequenceReset FROM: "
00333                      + IntConvertor::convert( getExpectedTargetNum() ) +
00334                      " TO: " + IntConvertor::convert( newSeqNo ) );
00335 
00336     if ( newSeqNo > getExpectedTargetNum() )
00337       m_state.setNextTargetMsgSeqNum( MsgSeqNum( newSeqNo ) );
00338     else if ( newSeqNo < getExpectedTargetNum() )
00339       generateReject( sequenceReset, SessionRejectReason_VALUE_IS_INCORRECT );
00340   }
00341 
00342   QF_STACK_POP
00343 }
00344 
00345 void Session::nextResendRequest( const Message& resendRequest )
00346 { QF_STACK_PUSH(Session::nextResendRequest)
00347 
00348   if ( !verify( resendRequest, false, false ) ) return ;
00349 
00350   Locker l( m_mutex );
00351 
00352   BeginSeqNo beginSeqNo;
00353   EndSeqNo endSeqNo;
00354   resendRequest.getField( beginSeqNo );
00355   resendRequest.getField( endSeqNo );
00356 
00357   m_state.onEvent( "Received ResendRequest FROM: "
00358        + IntConvertor::convert( beginSeqNo ) +
00359                    " TO: " + IntConvertor::convert( endSeqNo ) );
00360 
00361   std::string beginString = m_sessionID.getBeginString();
00362   if ( beginString >= FIX::BeginString_FIX42 && endSeqNo == 0 ||
00363        beginString <= FIX::BeginString_FIX42 && endSeqNo == 999999 ||
00364        endSeqNo >= getExpectedSenderNum() )
00365   { endSeqNo = getExpectedSenderNum() - 1; }
00366 
00367   std::vector < std::string > messages;
00368   m_state.get( beginSeqNo, endSeqNo, messages );
00369 
00370   std::vector < std::string > ::iterator i;
00371   MsgSeqNum msgSeqNum(0);
00372   MsgType msgType;
00373   int begin = 0;
00374   int current = beginSeqNo;
00375   std::string messageString;
00376 
00377   for ( i = messages.begin(); i != messages.end(); ++i )
00378   {
00379     Message msg( *i, m_dataDictionary );
00380     msg.getHeader().getField( msgSeqNum );
00381     msg.getHeader().getField( msgType );
00382 
00383     if( (current != msgSeqNum) && !begin )
00384       begin = current;
00385 
00386     if ( Message::isAdminMsgType( msgType ) )
00387     {
00388       if ( !begin ) begin = msgSeqNum;
00389     }
00390     else
00391     {
00392       if ( resend( msg ) )
00393       {
00394         if ( begin ) generateSequenceReset( begin, msgSeqNum );
00395         send( msg.toString(messageString) );
00396         m_state.onEvent( "Resending Message: "
00397                          + IntConvertor::convert( msgSeqNum ) );
00398         begin = 0;
00399       }
00400       else
00401       { if ( !begin ) begin = msgSeqNum; }
00402     }
00403     current = msgSeqNum + 1;
00404   }
00405   if ( begin )
00406   {
00407     generateSequenceReset( begin, msgSeqNum + 1 );
00408   }
00409 
00410   if ( endSeqNo > msgSeqNum )
00411   {
00412     endSeqNo = EndSeqNo(endSeqNo + 1);
00413     int next = m_state.getNextSenderMsgSeqNum();
00414     if( endSeqNo > next )
00415       endSeqNo = EndSeqNo(next);
00416     generateSequenceReset( beginSeqNo, endSeqNo );
00417   }
00418 
00419   resendRequest.getHeader().getField( msgSeqNum );
00420   if( !isTargetTooHigh(msgSeqNum) && !isTargetTooLow(msgSeqNum) )
00421     m_state.incrNextTargetMsgSeqNum();
00422 
00423   QF_STACK_POP
00424 }
00425 
00426 bool Session::send( Message& message )
00427 { QF_STACK_PUSH(Session::send)
00428 
00429   message.getHeader().removeField( FIELD::PossDupFlag );
00430   message.getHeader().removeField( FIELD::OrigSendingTime );
00431   return sendRaw( message );
00432 
00433   QF_STACK_POP
00434 }
00435 
00436 bool Session::sendRaw( Message& message, int num )
00437 { QF_STACK_PUSH(Session::sendRaw)
00438 
00439   Locker l( m_mutex );
00440 
00441   try
00442   {
00443     bool result = false;
00444     Header& header = message.getHeader();
00445     MsgType msgType;
00446     header.getField( msgType );
00447 
00448     fill( header );
00449     std::string messageString;
00450 
00451     if ( num )
00452       header.setField( MsgSeqNum( num ) );
00453 
00454     if ( Message::isAdminMsgType( msgType ) )
00455     {
00456       m_application.toAdmin( message, m_sessionID );
00457 
00458       if( msgType == "A" && !m_state.receivedReset() )
00459       {
00460         ResetSeqNumFlag resetSeqNumFlag( false );
00461         if( message.isSetField(resetSeqNumFlag) )
00462           message.getField( resetSeqNumFlag );
00463         if( resetSeqNumFlag )
00464         {
00465           m_state.reset();
00466           message.getHeader().setField( MsgSeqNum(getExpectedSenderNum()) );
00467         }
00468         m_state.sentReset( resetSeqNumFlag );
00469       }
00470 
00471       message.toString( messageString );
00472       if (
00473         msgType == "A" || msgType == "5"
00474         || msgType == "2" || msgType == "4"
00475         || isLoggedOn() )
00476       {
00477         result = send( messageString );
00478       }
00479     }
00480     else
00481     {
00482       // do not send application messages if they will just be cleared
00483       if( !isLoggedOn() && shouldSendReset() )
00484         return false;
00485 
00486       try
00487       {
00488         m_application.toApp( message, m_sessionID );
00489         message.toString( messageString );
00490         if ( isLoggedOn() )
00491           result = send( messageString );
00492       }
00493       catch ( DoNotSend& ) { return false; }
00494     }
00495 
00496     if ( !num )
00497     {
00498       MsgSeqNum msgSeqNum;
00499       header.getField( msgSeqNum );
00500       m_state.set( msgSeqNum, messageString );
00501       m_state.incrNextSenderMsgSeqNum();
00502     }
00503     return result;
00504   }
00505   catch ( IOException& e )
00506   {
00507     m_state.onEvent( e.what() );
00508     return false;
00509   }
00510 
00511   QF_STACK_POP
00512 }
00513 
00514 bool Session::send( const std::string& string )
00515 { QF_STACK_PUSH(Session::send)
00516 
00517   if ( !m_pResponder ) return false;
00518   m_state.onOutgoing( string );
00519   return m_pResponder->send( string );
00520 
00521   QF_STACK_POP
00522 }
00523 
00524 void Session::disconnect()
00525 { QF_STACK_PUSH(Session::disconnect)
00526 
00527   Locker l(m_mutex);
00528 
00529   if ( m_pResponder )
00530   {
00531     m_state.onEvent( "Disconnecting" );
00532 
00533     m_pResponder->disconnect();
00534     m_pResponder = 0;
00535   }
00536 
00537   if ( m_state.receivedLogon() || m_state.sentLogon() )
00538   {
00539     m_state.receivedLogon( false );
00540     m_state.sentLogon( false );
00541     m_application.onLogout( m_sessionID );
00542   }
00543 
00544   m_state.sentLogout( false );
00545   m_state.receivedReset( false );
00546   m_state.sentReset( false );
00547   m_state.clearQueue();
00548   m_state.logoutReason();
00549   if ( m_resetOnDisconnect )
00550     m_state.reset();
00551 
00552   m_state.resendRange( 0, 0 );
00553 
00554   QF_STACK_POP
00555 }
00556 
00557 bool Session::resend( Message& message )
00558 { QF_STACK_PUSH(Session::resend)
00559 
00560   SendingTime sendingTime;
00561   MsgSeqNum msgSeqNum;
00562   Header& header = message.getHeader();
00563   header.getField( sendingTime );
00564   header.getField( msgSeqNum );
00565   insertOrigSendingTime( header, sendingTime );
00566   header.setField( PossDupFlag( true ) );
00567   insertSendingTime( header );
00568 
00569   try
00570   {
00571     m_application.toApp( message, m_sessionID );
00572     return true;
00573   }
00574   catch ( DoNotSend& )
00575   { return false; }
00576 
00577   QF_STACK_POP
00578 }
00579 
00580 void Session::generateLogon()
00581 { QF_STACK_PUSH(Session::generateLogon)
00582 
00583   Message logon;
00584   logon.getHeader().setField( MsgType( "A" ) );
00585   logon.setField( EncryptMethod( 0 ) );
00586   logon.setField( m_state.heartBtInt() );
00587 
00588   if( m_refreshOnLogon )
00589     refresh();
00590 
00591   if( shouldSendReset() )
00592   {
00593     if( m_resetOnLogon ) m_state.reset();
00594     logon.setField( ResetSeqNumFlag(true) );
00595   }
00596 
00597   fill( logon.getHeader() );
00598   UtcTimeStamp now;
00599   m_state.lastReceivedTime( now );
00600   m_state.testRequest( 0 );
00601   m_state.sentLogon( true );
00602   sendRaw( logon );
00603 
00604   QF_STACK_POP
00605 }
00606 
00607 void Session::generateLogon( const Message& aLogon )
00608 { QF_STACK_PUSH(Session::generateLogon)
00609 
00610   Message logon;
00611   EncryptMethod encryptMethod;
00612   HeartBtInt heartBtInt;
00613   logon.setField( EncryptMethod( 0 ) );
00614   if( m_state.receivedReset() )
00615     logon.setField( ResetSeqNumFlag(true) );
00616   aLogon.getField( heartBtInt );
00617   logon.getHeader().setField( MsgType( "A" ) );
00618   logon.setField( heartBtInt );
00619   fill( logon.getHeader() );
00620   sendRaw( logon );
00621   m_state.sentLogon( true );
00622 
00623   QF_STACK_POP
00624 }
00625 
00626 void Session::generateResendRequest( const BeginString& beginString, const MsgSeqNum& msgSeqNum )
00627 { QF_STACK_PUSH(Session::generateResendRequest)
00628 
00629   Message resendRequest;
00630   BeginSeqNo beginSeqNo( ( int ) getExpectedTargetNum() );
00631   EndSeqNo endSeqNo( msgSeqNum - 1 );
00632   if ( beginString >= FIX::BeginString_FIX42 )
00633     endSeqNo = 0;
00634   else if( beginString <= FIX::BeginString_FIX41 )
00635     endSeqNo = 999999;
00636   resendRequest.getHeader().setField( MsgType( "2" ) );
00637   resendRequest.setField( beginSeqNo );
00638   resendRequest.setField( endSeqNo );
00639   fill( resendRequest.getHeader() );
00640   sendRaw( resendRequest );
00641 
00642   m_state.onEvent( "Sent ResendRequest FROM: "
00643                    + IntConvertor::convert( beginSeqNo ) +
00644                    " TO: " + IntConvertor::convert( endSeqNo ) );
00645 
00646   m_state.resendRange( beginSeqNo, msgSeqNum - 1 );
00647 
00648   QF_STACK_POP
00649 }
00650 
00651 void Session::generateSequenceReset
00652 ( int beginSeqNo, int endSeqNo )
00653 { QF_STACK_PUSH(Session::generateSequenceReset)
00654 
00655   Message sequenceReset;
00656   NewSeqNo newSeqNo( endSeqNo );
00657   sequenceReset.getHeader().setField( MsgType( "4" ) );
00658   sequenceReset.getHeader().setField( PossDupFlag( true ) );
00659   sequenceReset.setField( newSeqNo );
00660   fill( sequenceReset.getHeader() );
00661 
00662   SendingTime sendingTime;
00663   sequenceReset.getHeader().getField( sendingTime );
00664   insertOrigSendingTime( sequenceReset.getHeader(), sendingTime );
00665   sequenceReset.getHeader().setField( MsgSeqNum( beginSeqNo ) );
00666   sequenceReset.setField( GapFillFlag( true ) );
00667   sendRaw( sequenceReset, beginSeqNo );
00668   m_state.onEvent( "Sent SequenceReset TO: "
00669                    + IntConvertor::convert( newSeqNo ) );
00670 
00671   QF_STACK_POP
00672 }
00673 
00674 void Session::generateHeartbeat()
00675 { QF_STACK_PUSH(Session::generateHeartbeat)
00676 
00677   Message heartbeat;
00678   heartbeat.getHeader().setField( MsgType( "0" ) );
00679   fill( heartbeat.getHeader() );
00680   sendRaw( heartbeat );
00681 
00682   QF_STACK_POP
00683 }
00684 
00685 void Session::generateHeartbeat( const Message& testRequest )
00686 { QF_STACK_PUSH(Session::generateHeartbeat)
00687 
00688   Message heartbeat;
00689   heartbeat.getHeader().setField( MsgType( "0" ) );
00690   fill( heartbeat.getHeader() );
00691   try
00692   {
00693     TestReqID testReqID;
00694     testRequest.getField( testReqID );
00695     heartbeat.setField( testReqID );
00696   }
00697   catch ( FieldNotFound& ) {}
00698 
00699   sendRaw( heartbeat );
00700 
00701   QF_STACK_POP
00702 }
00703 
00704 void Session::generateTestRequest( const std::string& id )
00705 { QF_STACK_PUSH(Session::generateTestRequest)
00706 
00707   Message testRequest;
00708   testRequest.getHeader().setField( MsgType( "1" ) );
00709   fill( testRequest.getHeader() );
00710   TestReqID testReqID( id );
00711   testRequest.setField( testReqID );
00712 
00713   sendRaw( testRequest );
00714 
00715   QF_STACK_POP
00716 }
00717 
00718 void Session::generateReject( const Message& message, int err, int field )
00719 { QF_STACK_PUSH(Session::generateReject)
00720 
00721   std::string beginString = m_sessionID.getBeginString();
00722 
00723   Message reject;
00724   reject.getHeader().setField( MsgType( "3" ) );
00725   reject.reverseRoute( message.getHeader() );
00726   fill( reject.getHeader() );
00727 
00728   MsgSeqNum msgSeqNum;
00729   MsgType msgType;
00730 
00731   message.getHeader().getField( msgType );
00732   if( message.getHeader().isSetField( msgSeqNum ) )
00733   {
00734     message.getHeader().getField( msgSeqNum );
00735     if( msgSeqNum.getString() != "" )
00736       reject.setField( RefSeqNum( msgSeqNum ) );
00737   }
00738 
00739   if ( beginString >= FIX::BeginString_FIX42 )
00740   {
00741     if( msgType.getString() != "" )
00742       reject.setField( RefMsgType( msgType ) );
00743     if ( (beginString == FIX::BeginString_FIX42
00744           && err <= SessionRejectReason_INVALID_MSGTYPE)
00745           || beginString > FIX::BeginString_FIX42 )
00746     {
00747       reject.setField( SessionRejectReason( err ) );
00748     }
00749   }
00750   if ( msgType != MsgType_Logon && msgType != MsgType_SequenceReset
00751        && msgSeqNum == getExpectedTargetNum() )
00752   { m_state.incrNextTargetMsgSeqNum(); }
00753 
00754   const char* reason = 0;
00755   switch ( err )
00756   {
00757     case SessionRejectReason_INVALID_TAG_NUMBER:
00758     reason = SessionRejectReason_INVALID_TAG_NUMBER_TEXT;
00759     break;
00760     case SessionRejectReason_REQUIRED_TAG_MISSING:
00761     reason = SessionRejectReason_REQUIRED_TAG_MISSING_TEXT;
00762     break;
00763     case SessionRejectReason_TAG_NOT_DEFINED_FOR_THIS_MESSAGE_TYPE:
00764     reason = SessionRejectReason_TAG_NOT_DEFINED_FOR_THIS_MESSAGE_TYPE_TEXT;
00765     break;
00766     case SessionRejectReason_TAG_SPECIFIED_WITHOUT_A_VALUE:
00767     reason = SessionRejectReason_TAG_SPECIFIED_WITHOUT_A_VALUE_TEXT;
00768     break;
00769     case SessionRejectReason_VALUE_IS_INCORRECT:
00770     reason = SessionRejectReason_VALUE_IS_INCORRECT_TEXT;
00771     break;
00772     case SessionRejectReason_INCORRECT_DATA_FORMAT_FOR_VALUE:
00773     reason = SessionRejectReason_INCORRECT_DATA_FORMAT_FOR_VALUE_TEXT;
00774     break;
00775     case SessionRejectReason_COMPID_PROBLEM:
00776     reason = SessionRejectReason_COMPID_PROBLEM_TEXT;
00777     break;
00778     case SessionRejectReason_SENDINGTIME_ACCURACY_PROBLEM:
00779     reason = SessionRejectReason_SENDINGTIME_ACCURACY_PROBLEM_TEXT;
00780     break;
00781     case SessionRejectReason_INVALID_MSGTYPE:
00782     reason = SessionRejectReason_INVALID_MSGTYPE_TEXT;
00783     break;
00784     case SessionRejectReason_TAG_APPEARS_MORE_THAN_ONCE:
00785     reason = SessionRejectReason_TAG_APPEARS_MORE_THAN_ONCE_TEXT;
00786     break;
00787     case SessionRejectReason_TAG_SPECIFIED_OUT_OF_REQUIRED_ORDER:
00788     reason = SessionRejectReason_TAG_SPECIFIED_OUT_OF_REQUIRED_ORDER_TEXT;
00789     break;
00790     case SessionRejectReason_INCORRECT_NUMINGROUP_COUNT_FOR_REPEATING_GROUP:
00791     reason = SessionRejectReason_INCORRECT_NUMINGROUP_COUNT_FOR_REPEATING_GROUP_TEXT;
00792   };
00793 
00794   if ( reason && ( field || err == SessionRejectReason_INVALID_TAG_NUMBER ) )
00795   {
00796     populateRejectReason( reject, field, reason );
00797     m_state.onEvent( "Message " + msgSeqNum.getString() + " Rejected: "
00798                      + reason + ":" + IntConvertor::convert( field ) );
00799   }
00800   else if ( reason )
00801   {
00802     populateRejectReason( reject, reason );
00803     m_state.onEvent( "Message " + msgSeqNum.getString()
00804          + " Rejected: " + reason );
00805   }
00806   else
00807     m_state.onEvent( "Message " + msgSeqNum.getString() + " Rejected" );
00808 
00809   if ( !m_state.receivedLogon() )
00810     throw std::runtime_error( "Tried to send a reject while not logged on" );
00811 
00812   sendRaw( reject );
00813 
00814   QF_STACK_POP
00815 }
00816 
00817 void Session::generateReject( const Message& message, const std::string& str )
00818 { QF_STACK_PUSH(Session::generateReject)
00819 
00820   std::string beginString = m_sessionID.getBeginString();
00821 
00822   Message reject;
00823   reject.getHeader().setField( MsgType( "3" ) );
00824   reject.reverseRoute( message.getHeader() );
00825   fill( reject.getHeader() );
00826 
00827   MsgType msgType;
00828   MsgSeqNum msgSeqNum;
00829 
00830   message.getHeader().getField( msgType );
00831   message.getHeader().getField( msgSeqNum );
00832   if ( beginString >= FIX::BeginString_FIX42 )
00833     reject.setField( RefMsgType( msgType ) );
00834   reject.setField( RefSeqNum( msgSeqNum ) );
00835 
00836   if ( msgType != MsgType_Logon && msgType != MsgType_SequenceReset )
00837     m_state.incrNextTargetMsgSeqNum();
00838 
00839   reject.setField( Text( str ) );
00840   sendRaw( reject );
00841   m_state.onEvent( "Message " + msgSeqNum.getString()
00842                    + " Rejected: " + str );
00843 
00844   QF_STACK_POP
00845 }
00846 
00847 void Session::generateBusinessReject( const Message& message, int err )
00848 { QF_STACK_PUSH(Session::generateBusinessReject)
00849 
00850   Message reject;
00851   reject.getHeader().setField( MsgType( MsgType_BusinessMessageReject ) );
00852   fill( reject.getHeader() );
00853   MsgType msgType;
00854   MsgSeqNum msgSeqNum;
00855   message.getHeader().getField( msgType );
00856   message.getHeader().getField( msgSeqNum );
00857   reject.setField( RefMsgType( msgType ) );
00858   reject.setField( RefSeqNum( msgSeqNum ) );
00859   reject.setField( BusinessRejectReason( err ) );
00860   m_state.incrNextTargetMsgSeqNum();
00861 
00862   const char* reason = 0;
00863   switch ( err )
00864   {
00865     case BusinessRejectReason_OTHER:
00866     reason = BusinessRejectReason_OTHER_TEXT;
00867     break;
00868     case BusinessRejectReason_UNKOWN_ID:
00869     reason = BusinessRejectReason_UNKNOWN_ID_TEXT;
00870     break;
00871     case BusinessRejectReason_UNKNOWN_SECURITY:
00872     reason = BusinessRejectReason_UNKNOWN_SECURITY_TEXT;
00873     break;
00874     case BusinessRejectReason_UNSUPPORTED_MESSAGE_TYPE:
00875     reason = BusinessRejectReason_UNSUPPORTED_MESSAGE_TYPE_TEXT;
00876     break;
00877     case BusinessRejectReason_APPLICATION_NOT_AVAILABLE:
00878     reason = BusinessRejectReason_APPLICATION_NOT_AVAILABLE_TEXT;
00879     break;
00880     case BusinessRejectReason_CONDITIONALLY_REQUIRED_FIELD_MISSING:
00881     reason = BusinessRejectReason_CONDITIONALLY_REQUIRED_FIELD_MISSING_TEXT;
00882     break;
00883     case BusinessRejectReason_NOT_AUTHORIZED:
00884     reason = BusinessRejectReason_NOT_AUTHORIZED_TEXT;
00885     break;
00886     case BusinessRejectReason_DELIVERTO_FIRM_NOT_AVAILABLE_AT_THIS_TIME:
00887     reason = BusinessRejectReason_DELIVERTO_FIRM_NOT_AVAILABLE_AT_THIS_TIME_TEXT;
00888     break;
00889   };
00890 
00891   populateRejectReason( reject, reason );
00892   sendRaw( reject );
00893   m_state.onEvent( "Message " + msgSeqNum.getString()
00894                    + " Rejected: " + reason );
00895 
00896   QF_STACK_POP
00897 }
00898 
00899 void Session::generateLogout( const std::string& text )
00900 { QF_STACK_PUSH(Session::generateLogout)
00901 
00902   Message logout;
00903   logout.getHeader().setField( MsgType( MsgType_Logout ) );
00904   fill( logout.getHeader() );
00905   if ( text.length() )
00906     logout.setField( Text( text ) );
00907   sendRaw( logout );
00908   m_state.sentLogout( true );
00909 
00910   QF_STACK_POP
00911 }
00912 
00913 void Session::populateRejectReason( Message& reject, int field,
00914                                     const std::string& text )
00915 { QF_STACK_PUSH(Session::populateRejectReason)
00916 
00917   if ( m_sessionID.getBeginString() >= FIX::BeginString_FIX42 )
00918   {
00919     reject.setField( RefTagID( field ) );
00920     reject.setField( Text( text ) );
00921   }
00922   else
00923   {
00924     std::stringstream stream;
00925     stream << text << " (" << field << ")";
00926     reject.setField( Text( stream.str() ) );
00927   }
00928 
00929   QF_STACK_POP
00930 }
00931 
00932 void Session::populateRejectReason( Message& reject, const std::string& text )
00933 { QF_STACK_PUSH(Session::populateRejectReason)
00934   reject.setField( Text( text ) );
00935   QF_STACK_POP
00936 }
00937 
00938 bool Session::verify( const Message& msg, bool checkTooHigh,
00939                       bool checkTooLow )
00940 { QF_STACK_PUSH(Session::verify)
00941 
00942   SenderCompID senderCompID;
00943   TargetCompID targetCompID;
00944   SendingTime sendingTime;
00945   MsgType msgType;
00946   MsgSeqNum msgSeqNum;
00947 
00948   try
00949   {
00950     const Header& header = msg.getHeader();
00951     header.getField( senderCompID );
00952     header.getField( targetCompID );
00953     header.getField( sendingTime );
00954     header.getField( msgType );
00955     if( checkTooHigh || checkTooLow )
00956       header.getField( msgSeqNum );
00957 
00958     if ( !validLogonState( msgType ) )
00959       throw std::logic_error( "Logon state is not valid for message" );
00960 
00961     if ( !isGoodTime( sendingTime ) )
00962     {
00963       doBadTime( msg );
00964       return false;
00965     }
00966     if ( !isCorrectCompID( senderCompID, targetCompID ) )
00967     {
00968       doBadCompID( msg );
00969       return false;
00970     }
00971 
00972     if ( checkTooHigh && isTargetTooHigh( msgSeqNum ) )
00973     {
00974       doTargetTooHigh( msg );
00975       return false;
00976     }
00977     else if ( checkTooLow && isTargetTooLow( msgSeqNum ) )
00978     {
00979       doTargetTooLow( msg );
00980       return false;
00981     }
00982 
00983     if ( (checkTooHigh || checkTooLow) && m_state.resendRequested() )
00984     {
00985       SessionState::ResendRange range = m_state.resendRange();
00986  
00987       if ( msgSeqNum >= range.second )
00988       {
00989         m_state.onEvent ("ResendRequest for messages FROM: " +
00990                          IntConvertor::convert (range.first) + " TO: " +
00991                          IntConvertor::convert (range.second) +
00992                          " has been satisfied.");
00993         m_state.resendRange (0, 0);
00994       }
00995     }
00996   }
00997   catch ( std::exception& e )
00998   {
00999     m_state.onEvent( e.what() );
01000     disconnect();
01001     return false;
01002   }
01003 
01004   UtcTimeStamp now;
01005   m_state.lastReceivedTime( now );
01006   m_state.testRequest( 0 );
01007 
01008   fromCallback( msgType, msg, m_sessionID );
01009   return true;
01010 
01011   QF_STACK_POP
01012 }
01013 
01014 bool Session::shouldSendReset()
01015 { QF_STACK_PUSH(Session::shouldSendReset)
01016 
01017   std::string beginString = m_sessionID.getBeginString();
01018   return beginString >= FIX::BeginString_FIX41
01019     && ( m_resetOnLogon || 
01020          m_resetOnLogout || 
01021          m_resetOnDisconnect )
01022     && ( getExpectedSenderNum() == 1 )
01023     && ( getExpectedTargetNum() == 1 );
01024 
01025   QF_STACK_POP
01026 }
01027 
01028 bool Session::validLogonState( const MsgType& msgType )
01029 { QF_STACK_PUSH(Session::validLogonState)
01030 
01031   if ( msgType == MsgType_Logon && m_state.sentReset() || m_state.receivedReset() )
01032     return true;
01033   if ( msgType == MsgType_Logon && !m_state.receivedLogon()
01034        || msgType != MsgType_Logon && m_state.receivedLogon() )
01035     return true;
01036   if ( msgType == MsgType_Logout && m_state.sentLogon() )
01037     return true;
01038   if ( msgType != MsgType_Logout && m_state.sentLogout() )
01039     return true;
01040   if ( msgType == MsgType_SequenceReset ) 
01041     return true;
01042   if ( msgType == MsgType_Reject )
01043     return true;
01044 
01045   return false;
01046 
01047   QF_STACK_POP
01048 }
01049 
01050 void Session::fromCallback( const MsgType& msgType, const Message& msg,
01051                             const SessionID& sessionID )
01052 { QF_STACK_PUSH(Session::fromCallback)
01053 
01054   if ( Message::isAdminMsgType( msgType ) )
01055     m_application.fromAdmin( msg, m_sessionID );
01056   else
01057     m_application.fromApp( msg, m_sessionID );
01058 
01059   QF_STACK_POP
01060 }
01061 
01062 void Session::doBadTime( const Message& msg )
01063 { QF_STACK_PUSH(Session::doBadTime)
01064 
01065   generateReject( msg, SessionRejectReason_SENDINGTIME_ACCURACY_PROBLEM );
01066   generateLogout();
01067 
01068   QF_STACK_POP
01069 }
01070 
01071 void Session::doBadCompID( const Message& msg )
01072 { QF_STACK_PUSH(Session::doBadCompID)
01073 
01074   generateReject( msg, SessionRejectReason_COMPID_PROBLEM );
01075   generateLogout();
01076 
01077   QF_STACK_POP
01078 }
01079 
01080 bool Session::doPossDup( const Message& msg )
01081 { QF_STACK_PUSH(Session::doPossDup)
01082 
01083   const Header & header = msg.getHeader();
01084   OrigSendingTime origSendingTime;
01085   SendingTime sendingTime;
01086   MsgType msgType;
01087 
01088   header.getField( msgType );
01089   header.getField( sendingTime );
01090 
01091   if ( msgType != MsgType_SequenceReset )
01092   {
01093     if ( !header.isSetField( origSendingTime ) )
01094     {
01095       generateReject( msg, SessionRejectReason_REQUIRED_TAG_MISSING, origSendingTime.getField() );
01096       return false;
01097     }
01098     header.getField( origSendingTime );
01099 
01100     if ( origSendingTime > sendingTime )
01101     {
01102       generateReject( msg, SessionRejectReason_SENDINGTIME_ACCURACY_PROBLEM );
01103       generateLogout();
01104       return false;
01105     }
01106   }
01107   return true;
01108 
01109   QF_STACK_POP
01110 }
01111 
01112 bool Session::doTargetTooLow( const Message& msg )
01113 { QF_STACK_PUSH(Session::doTargetTooLow)
01114 
01115   const Header & header = msg.getHeader();
01116   PossDupFlag possDupFlag(false);
01117   MsgSeqNum msgSeqNum;
01118   if( header.isSetField(possDupFlag) )
01119     header.getField( possDupFlag );
01120   header.getField( msgSeqNum );
01121 
01122   if ( !possDupFlag )
01123   {
01124     std::stringstream stream;
01125     stream << "MsgSeqNum too low, expecting " << getExpectedTargetNum()
01126            << " but received " << msgSeqNum;
01127     generateLogout( stream.str() );
01128     throw std::logic_error( stream.str() );
01129   }
01130 
01131   return doPossDup( msg );
01132 
01133   QF_STACK_POP
01134 }
01135 
01136 void Session::doTargetTooHigh( const Message& msg )
01137 { QF_STACK_PUSH(Session::doTargetTooHigh)
01138 
01139   const Header & header = msg.getHeader();
01140   BeginString beginString;
01141   MsgSeqNum msgSeqNum;
01142   header.getField( beginString );
01143   header.getField( msgSeqNum );
01144 
01145   m_state.onEvent( "MsgSeqNum too high, expecting "
01146                    + IntConvertor::convert( getExpectedTargetNum() )
01147                    + " but received "
01148                    + IntConvertor::convert( msgSeqNum ) );
01149 
01150   m_state.queue( msgSeqNum, msg );
01151 
01152   if( m_state.resendRequested() )
01153   {
01154     SessionState::ResendRange range = m_state.resendRange();
01155 
01156     if( msgSeqNum >= range.first )
01157     {
01158           m_state.onEvent ("Already sent ResendRequest FROM: " +
01159                            IntConvertor::convert (range.first) + " TO: " +
01160                            IntConvertor::convert (range.second) +
01161                            ".  Not sending another.");
01162           return;
01163     }
01164   }
01165 
01166   generateResendRequest( beginString, msgSeqNum );
01167 
01168   QF_STACK_POP
01169 }
01170 
01171 void Session::nextQueued()
01172 { QF_STACK_PUSH(Session::nextQueued)
01173   while ( nextQueued( getExpectedTargetNum() ) ) {}
01174   QF_STACK_POP
01175 }
01176 
01177 bool Session::nextQueued( int num )
01178 { QF_STACK_PUSH(Session::nextQueued)
01179 
01180   Message msg;
01181   MsgType msgType;
01182 
01183   if( m_state.retreive( num, msg ) )
01184   {
01185     m_state.onEvent( "Processing QUEUED message: "
01186                      + IntConvertor::convert( num ) );
01187     msg.getHeader().getField( msgType );
01188     if( msgType == MsgType_Logon
01189         || msgType == MsgType_ResendRequest )
01190     {
01191       m_state.incrNextTargetMsgSeqNum();
01192     }
01193     else
01194     {
01195       std::string msgString;
01196       next( msg.toString(msgString), true );
01197     }
01198     return true;
01199   }
01200   return false;
01201 
01202   QF_STACK_POP
01203 }
01204 
01205 void Session::next( const std::string& msg, bool queued )
01206 { QF_STACK_PUSH(Session::next)
01207 
01208   try
01209   {
01210     m_state.onIncoming( msg );
01211     next( Message( msg, m_dataDictionary ), queued );
01212   }
01213   catch( InvalidMessage& e )
01214   {
01215     m_state.onEvent( e.what() );
01216 
01217     try
01218     {
01219       if( identifyType(msg) == MsgType_Logon )
01220       {
01221         m_state.onEvent( "Logon message is not valid" );
01222         disconnect();
01223       }
01224     } catch( MessageParseError& ) {}
01225     throw e;
01226   }
01227 
01228   QF_STACK_POP
01229 }
01230 
01231 void Session::next( const Message& message, bool queued )
01232 { QF_STACK_PUSH(Session::next)
01233 
01234   MsgType msgType;
01235   BeginString beginString;
01236   SenderCompID senderCompID;
01237   TargetCompID targetCompID;
01238 
01239   try
01240   {
01241     UtcTimeStamp now;
01242     if ( !checkSessionTime(now) )
01243       { reset(); return; }
01244 
01245     message.getHeader().getField( msgType );
01246     message.getHeader().getField( beginString );
01247     message.getHeader().getField( senderCompID );
01248     message.getHeader().getField( targetCompID );
01249 
01250     if ( beginString != m_sessionID.getBeginString() )
01251       throw UnsupportedVersion();
01252 
01253     m_dataDictionary.validate( message );
01254 
01255     if ( msgType == MsgType_Logon )
01256       nextLogon( message );
01257     else if ( msgType == MsgType_Heartbeat )
01258       nextHeartbeat( message );
01259     else if ( msgType == MsgType_TestRequest )
01260       nextTestRequest( message );
01261     else if ( msgType == MsgType_SequenceReset )
01262       nextSequenceReset( message );
01263     else if ( msgType == MsgType_Logout )
01264       nextLogout( message );
01265     else if ( msgType == MsgType_ResendRequest )
01266       nextResendRequest( message );
01267     else if ( msgType == MsgType_Reject )
01268       nextReject( message );
01269     else
01270     {
01271       if ( !verify( message ) ) return ;
01272       m_state.incrNextTargetMsgSeqNum();
01273     }
01274   }
01275   catch ( MessageParseError& e )
01276   { m_state.onEvent( e.what() ); }
01277   catch ( RequiredTagMissing & e )
01278   { LOGEX( generateReject( message, SessionRejectReason_REQUIRED_TAG_MISSING, e.field ) ); }
01279   catch ( FieldNotFound & e )
01280   {
01281     if( beginString >= FIX::BeginString_FIX42 && message.isApp() )
01282     {
01283       LOGEX( generateBusinessReject( message, BusinessRejectReason_CONDITIONALLY_REQUIRED_FIELD_MISSING ) );
01284     }
01285     else
01286     {
01287       LOGEX( generateReject( message, SessionRejectReason_REQUIRED_TAG_MISSING, e.field ) );
01288       if ( msgType == MsgType_Logon )
01289       {
01290         m_state.onEvent( "Required field missing from logon" );
01291         disconnect();
01292       }
01293     }
01294   }
01295   catch ( InvalidTagNumber & e )
01296   { LOGEX( generateReject( message, SessionRejectReason_INVALID_TAG_NUMBER, e.field ) ); }
01297   catch ( NoTagValue & e )
01298   { LOGEX( generateReject( message, SessionRejectReason_TAG_SPECIFIED_WITHOUT_A_VALUE, e.field ) ); }
01299   catch ( TagNotDefinedForMessage & e )
01300   { LOGEX( generateReject( message, SessionRejectReason_TAG_NOT_DEFINED_FOR_THIS_MESSAGE_TYPE, e.field ) ); }
01301   catch ( InvalidMessageType& )
01302   { LOGEX( generateReject( message, SessionRejectReason_INVALID_MSGTYPE ) ); }
01303   catch ( UnsupportedMessageType& )
01304   {
01305     if ( beginString >= FIX::BeginString_FIX42 )
01306       { LOGEX( generateBusinessReject( message, BusinessRejectReason_UNSUPPORTED_MESSAGE_TYPE ) ); }
01307     else
01308       { LOGEX( generateReject( message, "Unsupported message type" ) ); }
01309   }
01310   catch ( TagOutOfOrder & e )
01311   { LOGEX( generateReject( message, SessionRejectReason_TAG_SPECIFIED_OUT_OF_REQUIRED_ORDER, e.field ) ); }
01312   catch ( IncorrectDataFormat & e )
01313   { LOGEX( generateReject( message, SessionRejectReason_INCORRECT_DATA_FORMAT_FOR_VALUE, e.field ) ); }
01314   catch ( IncorrectTagValue & e )
01315   { LOGEX( generateReject( message, SessionRejectReason_VALUE_IS_INCORRECT, e.field ) ); }
01316   catch ( RepeatedTag & e )
01317   { LOGEX( generateReject( message, SessionRejectReason_TAG_APPEARS_MORE_THAN_ONCE, e.field ) ); }
01318   catch ( RepeatingGroupCountMismatch & e )
01319   { LOGEX( generateReject( message, SessionRejectReason_INCORRECT_NUMINGROUP_COUNT_FOR_REPEATING_GROUP, e.field ) ); }
01320   catch ( InvalidMessage& e )
01321   { m_state.onEvent( e.what() ); }
01322   catch ( RejectLogon& e )
01323   {
01324     m_state.onEvent( e.what() );
01325     generateLogout( e.what() );
01326     disconnect();
01327   }
01328   catch ( UnsupportedVersion& )
01329   {
01330     if ( msgType == MsgType_Logout )
01331       nextLogout( message );
01332     else
01333     {
01334       generateLogout( "Incorrect BeginString" );
01335       m_state.incrNextTargetMsgSeqNum();
01336     }
01337   }
01338   catch ( IOException& e )
01339   {
01340     m_state.onEvent( e.what() );
01341     disconnect();
01342   }
01343 
01344   if( !queued )
01345     nextQueued();
01346 
01347   if( isLoggedOn() )
01348     next();
01349 
01350   QF_STACK_POP
01351 }
01352 
01353 bool Session::sendToTarget( Message& message, const std::string& qualifier )
01354 throw( SessionNotFound )
01355 { QF_STACK_PUSH(Session::sendToTarget)
01356 
01357   try
01358   {
01359     SessionID sessionID = message.getSessionID( qualifier );
01360     return sendToTarget( message, sessionID );
01361   }
01362   catch ( FieldNotFound& ) { throw SessionNotFound(); }
01363 
01364   QF_STACK_POP
01365 }
01366 
01367 bool Session::sendToTarget( Message& message, const SessionID& sessionID )
01368 throw( SessionNotFound )
01369 { QF_STACK_PUSH(Session::sendToTarget)
01370 
01371   message.setSessionID( sessionID );
01372   Session* pSession = lookupSession( sessionID );
01373   if ( !pSession ) throw SessionNotFound();
01374   return pSession->send( message );
01375 
01376   QF_STACK_POP
01377 }
01378 
01379 bool Session::sendToTarget
01380 ( Message& message,
01381   const SenderCompID& senderCompID,
01382   const TargetCompID& targetCompID,
01383   const std::string& qualifier )
01384 throw( SessionNotFound )
01385 { QF_STACK_PUSH(Session::sendToTarget)
01386 
01387   message.getHeader().setField( senderCompID );
01388   message.getHeader().setField( targetCompID );
01389   return sendToTarget( message, qualifier );
01390 
01391   QF_STACK_POP
01392 }
01393 
01394 bool Session::sendToTarget
01395 ( Message& message, const std::string& sender, const std::string& target,
01396   const std::string& qualifier )
01397 throw( SessionNotFound )
01398 { QF_STACK_PUSH(Session::sendToTarget)
01399 
01400   return sendToTarget( message, SenderCompID( sender ),
01401                        TargetCompID( target ), qualifier );
01402 
01403   QF_STACK_POP
01404 }
01405 
01406 bool Session::doesSessionExist( const SessionID& sessionID )
01407 { QF_STACK_PUSH(Session::doesSessionExist)
01408 
01409   Locker locker( s_mutex );
01410   return s_sessions.end() != s_sessions.find( sessionID );
01411 
01412   QF_STACK_POP
01413 }
01414 
01415 Session* Session::lookupSession( const SessionID& sessionID )
01416 { QF_STACK_PUSH(Session::lookupSession)
01417 
01418   Locker locker( s_mutex );
01419   Sessions::iterator find = s_sessions.find( sessionID );
01420   if ( find != s_sessions.end() )
01421     return find->second;
01422   else
01423     return 0;
01424 
01425   QF_STACK_POP
01426 }
01427 
01428 Session* Session::lookupSession( const std::string& string, bo