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

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

Generated on Mon Mar 1 13:41:38 2010 for QuickFIX by doxygen 1.5.8 written by Dimitri van Heesch, © 1997-2001