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

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