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