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