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