Session.cpp
Go to the documentation of this file.
1/****************************************************************************
2** Copyright (c) 2001-2014
3**
4** This file is part of the QuickFIX FIX Engine
5**
6** This file may be distributed under the terms of the quickfixengine.org
7** license as defined by quickfixengine.org and appearing in the file
8** LICENSE included in the packaging of this file.
9**
10** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
11** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
12**
13** See http://www.quickfixengine.org/LICENSE for licensing information.
14**
15** Contact ask@quickfixengine.org if any conditions of this licensing are
16** not clear to you.
17**
18****************************************************************************/
19
20#ifdef _MSC_VER
21#include "stdafx.h"
22#else
23#include "config.h"
24#endif
25
26#include "Session.h"
27#include "Values.h"
28#include <algorithm>
29#include <iostream>
30
31namespace FIX
32{
37
38#define LOGEX( method ) try { method; } catch( std::exception& e ) \
39 { m_state.onEvent( e.what() ); }
40
42 MessageStoreFactory& messageStoreFactory,
43 const SessionID& sessionID,
44 const DataDictionaryProvider& dataDictionaryProvider,
45 const TimeRange& sessionTime,
46 int heartBtInt, LogFactory* pLogFactory )
47: m_application( application ),
48 m_sessionID( sessionID ),
49 m_sessionTime( sessionTime ),
50 m_logonTime( sessionTime ),
51 m_senderDefaultApplVerID(ApplVerID_FIX50),
52 m_targetDefaultApplVerID(ApplVerID_FIX50),
54 m_checkCompId( true ),
55 m_checkLatency( true ),
56 m_maxLatency( 120 ),
57 m_resetOnLogon( false ),
58 m_resetOnLogout( false ),
59 m_resetOnDisconnect( false ),
60 m_refreshOnLogon( false ),
62 m_persistMessages( true ),
64 m_dataDictionaryProvider( dataDictionaryProvider ),
65 m_messageStoreFactory( messageStoreFactory ),
66 m_pLogFactory( pLogFactory ),
67 m_pResponder( 0 )
68{
69 m_state.heartBtInt( heartBtInt );
70 m_state.initiate( heartBtInt != 0 );
71 m_state.store( m_messageStoreFactory.create( m_sessionID ) );
72 if ( m_pLogFactory )
73 m_state.log( m_pLogFactory->create( m_sessionID ) );
74
76 reset();
77
78 addSession( *this );
79 m_application.onCreate( m_sessionID );
80 m_state.onEvent( "Created session" );
81}
82
84{
85 removeSession( *this );
86 m_messageStoreFactory.destroy( m_state.store() );
87 if ( m_pLogFactory && m_state.log() )
88 m_pLogFactory->destroy( m_state.log() );
89}
90
92{
93 UtcTimeStamp now;
94 bool showMilliseconds = false;
95 if( m_sessionID.getBeginString() == BeginString_FIXT11 )
96 showMilliseconds = true;
97 else
98 showMilliseconds = m_sessionID.getBeginString() >= BeginString_FIX42;
99
100 header.setField( SendingTime(now, showMilliseconds ? m_timestampPrecision : 0) );
101}
102
104{
105 bool showMilliseconds = false;
106 if( m_sessionID.getBeginString() == BeginString_FIXT11 )
107 showMilliseconds = true;
108 else
109 showMilliseconds = m_sessionID.getBeginString() >= BeginString_FIX42;
110
111 header.setField( OrigSendingTime(when, showMilliseconds ? m_timestampPrecision : 0) );
112}
113
114void Session::fill( Header& header )
115{
116 UtcTimeStamp now;
117 m_state.lastSentTime( now );
118 header.setField( m_sessionID.getBeginString() );
119 header.setField( m_sessionID.getSenderCompID() );
120 header.setField( m_sessionID.getTargetCompID() );
121 header.setField( MsgSeqNum( getExpectedSenderNum() ) );
122 insertSendingTime( header );
123}
124
126{
127 next( UtcTimeStamp() );
128}
129
130void Session::next( const UtcTimeStamp& timeStamp )
131{
132 try
133 {
134 if ( !checkSessionTime(timeStamp) )
135 { reset(); return; }
136
137 if( !isEnabled() || !isLogonTime(timeStamp) )
138 {
139 if( isLoggedOn() )
140 {
141 if( !m_state.sentLogout() )
142 {
143 m_state.onEvent( "Initiated logout request" );
144 generateLogout( m_state.logoutReason() );
145 }
146 }
147 else
148 return;
149 }
150
151 if ( !m_state.receivedLogon() )
152 {
153 if ( m_state.shouldSendLogon() && isLogonTime(timeStamp) )
154 {
156 m_state.onEvent( "Initiated logon request" );
157 }
158 else if ( m_state.alreadySentLogon() && m_state.logonTimedOut() )
159 {
160 m_state.onEvent( "Timed out waiting for logon response" );
161 disconnect();
162 }
163 return ;
164 }
165
166 if ( m_state.heartBtInt() == 0 ) return ;
167
168 if ( m_state.logoutTimedOut() )
169 {
170 m_state.onEvent( "Timed out waiting for logout response" );
171 disconnect();
172 }
173
174 if ( m_state.withinHeartBeat() ) return ;
175
176 if ( m_state.timedOut() )
177 {
178 m_state.onEvent( "Timed out waiting for heartbeat" );
179 disconnect();
180 }
181 else
182 {
183 if ( m_state.needTestRequest() )
184 {
185 generateTestRequest( "TEST" );
186 m_state.testRequest( m_state.testRequest() + 1 );
187 m_state.onEvent( "Sent test request TEST" );
188 }
189 else if ( m_state.needHeartbeat() )
190 {
192 }
193 }
194 }
195 catch ( FIX::IOException& e )
196 {
197 m_state.onEvent( e.what() );
198 disconnect();
199 }
200}
201
202void Session::nextLogon( const Message& logon, const UtcTimeStamp& timeStamp )
203{
204 SenderCompID senderCompID;
205 TargetCompID targetCompID;
206 logon.getHeader().getField( senderCompID );
207 logon.getHeader().getField( targetCompID );
208
209 if( m_refreshOnLogon )
210 refresh();
211
212 if( !isEnabled() )
213 {
214 m_state.onEvent( "Session is not enabled for logon" );
215 disconnect();
216 return;
217 }
218
219 if( !isLogonTime(timeStamp) )
220 {
221 m_state.onEvent( "Received logon outside of valid logon time" );
222 disconnect();
223 return;
224 }
225
226 ResetSeqNumFlag resetSeqNumFlag(false);
227 logon.getFieldIfSet(resetSeqNumFlag);
228 m_state.receivedReset( resetSeqNumFlag );
229
230 if( m_state.receivedReset() )
231 {
232 m_state.onEvent( "Logon contains ResetSeqNumFlag=Y, reseting sequence numbers to 1" );
233 if( !m_state.sentReset() ) m_state.reset();
234 }
235
236 if( m_state.shouldSendLogon() && !m_state.receivedReset() )
237 {
238 m_state.onEvent( "Received logon response before sending request" );
239 disconnect();
240 return;
241 }
242
243 if( !m_state.initiate() && m_resetOnLogon )
244 m_state.reset();
245
246 if( !verify( logon, false, true ) )
247 return;
248 m_state.receivedLogon( true );
249
250 if ( !m_state.initiate()
251 || (m_state.receivedReset() && !m_state.sentReset()) )
252 {
253 logon.getFieldIfSet(m_state.heartBtInt());
254 m_state.onEvent( "Received logon request" );
256 m_state.onEvent( "Responding to logon request" );
257 }
258 else
259 m_state.onEvent( "Received logon response" );
260
261 m_state.sentReset( false );
262 m_state.receivedReset( false );
263
264 MsgSeqNum msgSeqNum;
265 logon.getHeader().getField( msgSeqNum );
266 if ( isTargetTooHigh( msgSeqNum ) && !resetSeqNumFlag )
267 {
269 }
270 else
271 {
272 m_state.incrNextTargetMsgSeqNum();
273 nextQueued( timeStamp );
274 }
275
276 if ( isLoggedOn() )
277 m_application.onLogon( m_sessionID );
278}
279
280void Session::nextHeartbeat( const Message& heartbeat, const UtcTimeStamp& timeStamp )
281{
282 if ( !verify( heartbeat ) ) return ;
283 m_state.incrNextTargetMsgSeqNum();
284 nextQueued( timeStamp );
285}
286
287void Session::nextTestRequest( const Message& testRequest, const UtcTimeStamp& timeStamp )
288{
289 if ( !verify( testRequest ) ) return ;
290 generateHeartbeat( testRequest );
291 m_state.incrNextTargetMsgSeqNum();
292 nextQueued( timeStamp );
293}
294
295void Session::nextLogout( const Message& logout, const UtcTimeStamp& timeStamp )
296{
297 if ( !verify( logout, false, false ) ) return ;
298 if ( !m_state.sentLogout() )
299 {
300 m_state.onEvent( "Received logout request" );
302 m_state.onEvent( "Sending logout response" );
303 }
304 else
305 m_state.onEvent( "Received logout response" );
306
307 m_state.incrNextTargetMsgSeqNum();
308 if ( m_resetOnLogout ) m_state.reset();
309 disconnect();
310}
311
312void Session::nextReject( const Message& reject, const UtcTimeStamp& timeStamp )
313{
314 if ( !verify( reject, false, true ) ) return ;
315 m_state.incrNextTargetMsgSeqNum();
316 nextQueued( timeStamp );
317}
318
319void Session::nextSequenceReset( const Message& sequenceReset, const UtcTimeStamp& timeStamp )
320{
321 bool isGapFill = false;
322 GapFillFlag gapFillFlag;
323 if ( sequenceReset.getFieldIfSet( gapFillFlag ) )
324 {
325 isGapFill = gapFillFlag;
326 }
327
328 if ( !verify( sequenceReset, isGapFill, isGapFill ) ) return ;
329
330 NewSeqNo newSeqNo;
331 if ( sequenceReset.getFieldIfSet( newSeqNo ) )
332 {
333 m_state.onEvent( "Received SequenceReset FROM: "
335 " TO: " + IntConvertor::convert( newSeqNo ) );
336
337 if ( newSeqNo > getExpectedTargetNum() )
338 m_state.setNextTargetMsgSeqNum( MsgSeqNum( newSeqNo ) );
339 else if ( newSeqNo < getExpectedTargetNum() )
340 generateReject( sequenceReset, SessionRejectReason_VALUE_IS_INCORRECT );
341 }
342}
343
344void Session::nextResendRequest( const Message& resendRequest, const UtcTimeStamp& timeStamp )
345{
346 if ( !verify( resendRequest, false, false ) ) return ;
347
348 Locker l( m_mutex );
349
350 BeginSeqNo beginSeqNo;
351 EndSeqNo endSeqNo;
352 resendRequest.getField( beginSeqNo );
353 resendRequest.getField( endSeqNo );
354
355 m_state.onEvent( "Received ResendRequest FROM: "
356 + IntConvertor::convert( beginSeqNo ) +
357 " TO: " + IntConvertor::convert( endSeqNo ) );
358
359 std::string beginString = m_sessionID.getBeginString();
360 if ( (beginString >= FIX::BeginString_FIX42 && endSeqNo == 0) ||
361 (beginString <= FIX::BeginString_FIX42 && endSeqNo == 999999) ||
362 (endSeqNo >= getExpectedSenderNum()) )
363 { endSeqNo = getExpectedSenderNum() - 1; }
364
365 if ( !m_persistMessages )
366 {
367 endSeqNo = EndSeqNo(endSeqNo + 1);
368 int next = m_state.getNextSenderMsgSeqNum();
369 if( endSeqNo > next )
370 endSeqNo = EndSeqNo(next);
371 generateSequenceReset( beginSeqNo, endSeqNo );
372 return;
373 }
374
375 std::vector < std::string > messages;
376 m_state.get( beginSeqNo, endSeqNo, messages );
377
378 std::vector < std::string > ::iterator i;
379 MsgSeqNum msgSeqNum(0);
380 MsgType msgType;
381 int begin = 0;
382 int current = beginSeqNo;
383 std::string messageString;
384
385 for ( i = messages.begin(); i != messages.end(); ++i )
386 {
388 std::string strMsgType;
389 const DataDictionary& sessionDD =
390 m_dataDictionaryProvider.getSessionDataDictionary(m_sessionID.getBeginString());
391 if (sessionDD.isMessageFieldsOrderPreserved())
392 {
393 std::string::size_type equalSign = (*i).find("\00135=");
394 equalSign += 4;
395 std::string::size_type soh = (*i).find_first_of('\001', equalSign);
396 strMsgType = (*i).substr(equalSign, soh - equalSign);
397#ifdef HAVE_EMX
398 if (FIX::Message::isAdminMsgType(strMsgType) == false)
399 {
400 equalSign = (*i).find("\0019426=", soh);
401 if (equalSign == std::string::npos)
402 throw FIX::IOException("EMX message type (9426) not found");
403
404 equalSign += 6;
405 soh = (*i).find_first_of('\001', equalSign);
406 if (soh == std::string::npos)
407 throw FIX::IOException("EMX message type (9426) soh char not found");
408 strMsgType.assign((*i).substr(equalSign, soh - equalSign));
409 }
410#endif
411 }
412
413 if( m_sessionID.isFIXT() )
414 {
415 Message msg;
416 msg.setStringHeader(*i);
417 ApplVerID applVerID;
418 if( !msg.getHeader().getFieldIfSet(applVerID) )
419 applVerID = m_senderDefaultApplVerID;
420
421 const DataDictionary& applicationDD =
422 m_dataDictionaryProvider.getApplicationDataDictionary(applVerID);
423 if (strMsgType.empty())
424 pMsg.reset( new Message( *i, sessionDD, applicationDD, m_validateLengthAndChecksum ));
425 else
426 {
427 const message_order & hdrOrder = sessionDD.getHeaderOrderedFields();
428 const message_order & trlOrder = sessionDD.getTrailerOrderedFields();
429 const message_order & msgOrder = applicationDD.getMessageOrderedFields(strMsgType);
430 pMsg.reset( new Message( hdrOrder, trlOrder, msgOrder, *i, sessionDD, applicationDD, m_validateLengthAndChecksum ));
431 }
432 }
433 else
434 {
435 if (strMsgType.empty())
436 pMsg.reset( new Message( *i, sessionDD, m_validateLengthAndChecksum ));
437 else
438 {
439 const message_order & hdrOrder = sessionDD.getHeaderOrderedFields();
440 const message_order & trlOrder = sessionDD.getTrailerOrderedFields();
441 const message_order & msgOrder = sessionDD.getMessageOrderedFields(strMsgType);
442 pMsg.reset(new Message(hdrOrder, trlOrder, msgOrder, *i, sessionDD, m_validateLengthAndChecksum ));
443 }
444 }
445
446 Message & msg = *pMsg;
447
448 msg.getHeader().getField( msgSeqNum );
449 msg.getHeader().getField( msgType );
450
451 if( (current != msgSeqNum) && !begin )
452 begin = current;
453
454 if ( Message::isAdminMsgType( msgType ) )
455 {
456 if ( !begin ) begin = msgSeqNum;
457 }
458 else
459 {
460 if ( resend( msg ) )
461 {
462 if ( begin ) generateSequenceReset( begin, msgSeqNum );
463 send( msg.toString(messageString) );
464 m_state.onEvent( "Resending Message: "
465 + IntConvertor::convert( msgSeqNum ) );
466 begin = 0;
467 }
468 else
469 { if ( !begin ) begin = msgSeqNum; }
470 }
471 current = msgSeqNum + 1;
472 }
473 if ( begin )
474 {
475 generateSequenceReset( begin, msgSeqNum + 1 );
476 }
477
478 if ( endSeqNo > msgSeqNum )
479 {
480 endSeqNo = EndSeqNo(endSeqNo + 1);
481 int next = m_state.getNextSenderMsgSeqNum();
482 if( endSeqNo > next )
483 endSeqNo = EndSeqNo(next);
484 generateSequenceReset( beginSeqNo, endSeqNo );
485 }
486
487 resendRequest.getHeader().getField( msgSeqNum );
488 if( !isTargetTooHigh(msgSeqNum) && !isTargetTooLow(msgSeqNum) )
489 m_state.incrNextTargetMsgSeqNum();
490}
491
492Message * Session::newMessage(const std::string & msgType) const
493{
494 Message * msg = 0;
495
496 const DataDictionary& sessionDD =
497 m_dataDictionaryProvider.getSessionDataDictionary(m_sessionID.getBeginString());
498 if (!sessionDD.isMessageFieldsOrderPreserved())
499 {
500 msg = new Message();
501 }
502 else
503 {
504 const message_order & hdrOrder = sessionDD.getHeaderOrderedFields();
505 const message_order & trlOrder = sessionDD.getTrailerOrderedFields();
506 if (!m_sessionID.isFIXT() || Message::isAdminMsgType(msgType) )
507 {
508 const message_order & msgOrder = sessionDD.getMessageOrderedFields(msgType);
509 msg = new Message(hdrOrder, trlOrder, msgOrder);
510 }
511 else
512 {
513 const DataDictionary& applicationDD =
514 m_dataDictionaryProvider.getApplicationDataDictionary(m_senderDefaultApplVerID);
515 const message_order & msgOrder = applicationDD.getMessageOrderedFields(msgType);
516 msg = new Message(hdrOrder, trlOrder, msgOrder);
517 }
518 }
519
520 return msg;
521}
522
523bool Session::send( Message& message )
524{
525 message.getHeader().removeField( FIELD::PossDupFlag );
526 message.getHeader().removeField( FIELD::OrigSendingTime );
527 return sendRaw( message );
528}
529
530bool Session::sendRaw( Message& message, int num )
531{
532 Locker l( m_mutex );
533
534 try
535 {
536 Header& header = message.getHeader();
537
538 MsgType msgType;
539 header.getFieldIfSet(msgType);
540
541 fill( header );
542 std::string messageString;
543
544 if ( num )
545 header.setField( MsgSeqNum( num ) );
546
547 if ( Message::isAdminMsgType( msgType ) )
548 {
549 m_application.toAdmin( message, m_sessionID );
550
551 if( msgType == "A" && !m_state.receivedReset() )
552 {
553 ResetSeqNumFlag resetSeqNumFlag( false );
554 message.getFieldIfSet(resetSeqNumFlag);
555
556 if( resetSeqNumFlag )
557 {
558 m_state.reset();
559 message.getHeader().setField( MsgSeqNum(getExpectedSenderNum()) );
560 }
561 m_state.sentReset( resetSeqNumFlag );
562 }
563
564 message.toString( messageString );
565
566 if( !num )
567 persist( message, messageString );
568
569 if (
570 msgType == "A" || msgType == "5"
571 || msgType == "2" || msgType == "4"
572 || isLoggedOn() )
573 {
574 send( messageString );
575 }
576 }
577 else
578 {
579 // do not send application messages if they will just be cleared
580 if( !isLoggedOn() && shouldSendReset() )
581 return false;
582
583 try
584 {
585 m_application.toApp( message, m_sessionID );
586 message.toString( messageString );
587
588 if( !num )
589 persist( message, messageString );
590
591 if ( isLoggedOn() )
592 send( messageString );
593 }
594 catch ( DoNotSend& ) { return false; }
595 }
596
597 return true;
598 }
599 catch ( IOException& e )
600 {
601 m_state.onEvent( e.what() );
602 return false;
603 }
604}
605
606bool Session::send( const std::string& string )
607{
608 if ( !m_pResponder ) return false;
609 m_state.onOutgoing( string );
610 return m_pResponder->send( string );
611}
612
614{
615 Locker l(m_mutex);
616
617 if ( m_pResponder )
618 {
619 m_state.onEvent( "Disconnecting" );
620
621 m_pResponder->disconnect();
622 m_pResponder = 0;
623 }
624
625 if ( m_state.receivedLogon() || m_state.sentLogon() )
626 {
627 m_state.receivedLogon( false );
628 m_state.sentLogon( false );
629 m_application.onLogout( m_sessionID );
630 }
631
632 m_state.sentLogout( false );
633 m_state.receivedReset( false );
634 m_state.sentReset( false );
635 m_state.clearQueue();
636 m_state.logoutReason();
638 m_state.reset();
639
640 m_state.resendRange( 0, 0 );
641}
642
643bool Session::resend( Message& message )
644{
645 SendingTime sendingTime;
646 MsgSeqNum msgSeqNum;
647 Header& header = message.getHeader();
648 header.getField( sendingTime );
649 header.getField( msgSeqNum );
650 insertOrigSendingTime( header, sendingTime );
651 header.setField( PossDupFlag( true ) );
652 insertSendingTime( header );
653
654 try
655 {
656 m_application.toApp( message, m_sessionID );
657 return true;
658 }
659 catch ( DoNotSend& )
660 { return false; }
661}
662
663void Session::persist( const Message& message, const std::string& messageString )
664throw ( IOException )
665{
666 MsgSeqNum msgSeqNum;
667 message.getHeader().getField( msgSeqNum );
669 m_state.set( msgSeqNum, messageString );
670 m_state.incrNextSenderMsgSeqNum();
671}
672
674{
675 SmartPtr<Message> pMsg(newMessage("A"));
676 Message & logon = *pMsg;
677
678 logon.getHeader().setField( MsgType( "A" ) );
679 logon.setField( EncryptMethod( 0 ) );
680 logon.setField( m_state.heartBtInt() );
681 if( m_sessionID.isFIXT() )
682 logon.setField( DefaultApplVerID(m_senderDefaultApplVerID) );
683 if( m_refreshOnLogon )
684 refresh();
685 if( m_resetOnLogon )
686 m_state.reset();
687 if( shouldSendReset() )
688 logon.setField( ResetSeqNumFlag(true) );
689
690 fill( logon.getHeader() );
691 UtcTimeStamp now;
692 m_state.lastReceivedTime( now );
693 m_state.testRequest( 0 );
694 m_state.sentLogon( true );
695 sendRaw( logon );
696}
697
698void Session::generateLogon( const Message& aLogon )
699{
700 SmartPtr<Message> pMsg(newMessage("A"));
701 Message & logon = *pMsg;
702
703 EncryptMethod encryptMethod;
704 HeartBtInt heartBtInt;
705 logon.setField( EncryptMethod( 0 ) );
706 if( m_sessionID.isFIXT() )
707 logon.setField( DefaultApplVerID(m_senderDefaultApplVerID) );
708 if( m_state.receivedReset() )
709 logon.setField( ResetSeqNumFlag(true) );
710 aLogon.getField( heartBtInt );
711 logon.getHeader().setField( MsgType( "A" ) );
712 logon.setField( heartBtInt );
713 fill( logon.getHeader() );
714 sendRaw( logon );
715 m_state.sentLogon( true );
716}
717
718void Session::generateResendRequest( const BeginString& beginString, const MsgSeqNum& msgSeqNum )
719{
720 SmartPtr<Message> pMsg(newMessage("2"));
721 Message & resendRequest = *pMsg;
722
723 BeginSeqNo beginSeqNo( ( int ) getExpectedTargetNum() );
724 EndSeqNo endSeqNo( msgSeqNum - 1 );
725 if ( beginString >= FIX::BeginString_FIX42 )
726 endSeqNo = 0;
727 else if( beginString <= FIX::BeginString_FIX41 )
728 endSeqNo = 999999;
729 resendRequest.getHeader().setField( MsgType( "2" ) );
730 resendRequest.setField( beginSeqNo );
731 resendRequest.setField( endSeqNo );
732 fill( resendRequest.getHeader() );
733 sendRaw( resendRequest );
734
735 m_state.onEvent( "Sent ResendRequest FROM: "
736 + IntConvertor::convert( beginSeqNo ) +
737 " TO: " + IntConvertor::convert( endSeqNo ) );
738
739 m_state.resendRange( beginSeqNo, msgSeqNum - 1 );
740}
741
743( int beginSeqNo, int endSeqNo )
744{
745 SmartPtr<Message> pMsg(newMessage("4"));
746 Message & sequenceReset = *pMsg;
747
748 NewSeqNo newSeqNo( endSeqNo );
749 sequenceReset.getHeader().setField( MsgType( "4" ) );
750 sequenceReset.getHeader().setField( PossDupFlag( true ) );
751 sequenceReset.setField( newSeqNo );
752 fill( sequenceReset.getHeader() );
753
754 SendingTime sendingTime;
755 sequenceReset.getHeader().getField( sendingTime );
756 insertOrigSendingTime( sequenceReset.getHeader(), sendingTime );
757 sequenceReset.getHeader().setField( MsgSeqNum( beginSeqNo ) );
758 sequenceReset.setField( GapFillFlag( true ) );
759 sendRaw( sequenceReset, beginSeqNo );
760 m_state.onEvent( "Sent SequenceReset TO: "
761 + IntConvertor::convert( newSeqNo ) );
762}
763
765{
766 SmartPtr<Message> pMsg(newMessage("0"));
767 Message & heartbeat = *pMsg;
768
769 heartbeat.getHeader().setField( MsgType( "0" ) );
770 fill( heartbeat.getHeader() );
771 sendRaw( heartbeat );
772}
773
774void Session::generateHeartbeat( const Message& testRequest )
775{
776 SmartPtr<Message> pMsg(newMessage("0"));
777 Message & heartbeat = *pMsg;
778
779 heartbeat.getHeader().setField( MsgType( "0" ) );
780 fill( heartbeat.getHeader() );
781 try
782 {
783 TestReqID testReqID;
784 testRequest.getField( testReqID );
785 heartbeat.setField( testReqID );
786 }
787 catch ( FieldNotFound& ) {}
788
789 sendRaw( heartbeat );
790}
791
792void Session::generateTestRequest( const std::string& id )
793{
794 SmartPtr<Message> pMsg(newMessage("1"));
795 Message & testRequest = *pMsg;
796
797 testRequest.getHeader().setField( MsgType( "1" ) );
798 fill( testRequest.getHeader() );
799 TestReqID testReqID( id );
800 testRequest.setField( testReqID );
801
802 sendRaw( testRequest );
803}
804
805void Session::generateReject( const Message& message, int err, int field )
806{
807 std::string beginString = m_sessionID.getBeginString();
808
809 SmartPtr<Message> pMsg(newMessage("3"));
810 Message & reject = *pMsg;
811
812 reject.getHeader().setField( MsgType( "3" ) );
813 reject.reverseRoute( message.getHeader() );
814 fill( reject.getHeader() );
815
816 MsgSeqNum msgSeqNum;
817 MsgType msgType;
818
819 message.getHeader().getField( msgType );
820 if( message.getHeader().getFieldIfSet( msgSeqNum ) )
821 {
822 if( msgSeqNum.getString() != "" )
823 reject.setField( RefSeqNum( msgSeqNum ) );
824 }
825
826 if ( beginString >= FIX::BeginString_FIX42 )
827 {
828 if( msgType.getString() != "" )
829 reject.setField( RefMsgType( msgType ) );
830 if ( (beginString == FIX::BeginString_FIX42
831 && err <= SessionRejectReason_INVALID_MSGTYPE)
832 || beginString > FIX::BeginString_FIX42 )
833 {
834 reject.setField( SessionRejectReason( err ) );
835 }
836 }
837 if ( msgType != MsgType_Logon && msgType != MsgType_SequenceReset
838 && msgSeqNum == getExpectedTargetNum() )
839 { m_state.incrNextTargetMsgSeqNum(); }
840
841 const char* reason = 0;
842 switch ( err )
843 {
844 case SessionRejectReason_INVALID_TAG_NUMBER:
846 break;
847 case SessionRejectReason_REQUIRED_TAG_MISSING:
849 break;
850 case SessionRejectReason_TAG_NOT_DEFINED_FOR_THIS_MESSAGE_TYPE:
852 break;
853 case SessionRejectReason_TAG_SPECIFIED_WITHOUT_A_VALUE:
855 break;
856 case SessionRejectReason_VALUE_IS_INCORRECT:
858 break;
859 case SessionRejectReason_INCORRECT_DATA_FORMAT_FOR_VALUE:
861 break;
862 case SessionRejectReason_COMPID_PROBLEM:
864 break;
865 case SessionRejectReason_SENDINGTIME_ACCURACY_PROBLEM:
867 break;
868 case SessionRejectReason_INVALID_MSGTYPE:
870 break;
871 case SessionRejectReason_TAG_APPEARS_MORE_THAN_ONCE:
873 break;
874 case SessionRejectReason_TAG_SPECIFIED_OUT_OF_REQUIRED_ORDER:
876 break;
877 case SessionRejectReason_INCORRECT_NUMINGROUP_COUNT_FOR_REPEATING_GROUP:
879 };
880
881 if ( reason && ( field || err == SessionRejectReason_INVALID_TAG_NUMBER ) )
882 {
883 populateRejectReason( reject, field, reason );
884 m_state.onEvent( "Message " + msgSeqNum.getString() + " Rejected: "
885 + reason + ":" + IntConvertor::convert( field ) );
886 }
887 else if ( reason )
888 {
889 populateRejectReason( reject, reason );
890 m_state.onEvent( "Message " + msgSeqNum.getString()
891 + " Rejected: " + reason );
892 }
893 else
894 m_state.onEvent( "Message " + msgSeqNum.getString() + " Rejected" );
895
896 if ( !m_state.receivedLogon() )
897 throw std::runtime_error( "Tried to send a reject while not logged on" );
898
899 sendRaw( reject );
900}
901
902void Session::generateReject( const Message& message, const std::string& str )
903{
904 std::string beginString = m_sessionID.getBeginString();
905
906 SmartPtr<Message> pMsg(newMessage("3"));
907 Message & reject = *pMsg;
908
909 reject.getHeader().setField( MsgType( "3" ) );
910 reject.reverseRoute( message.getHeader() );
911 fill( reject.getHeader() );
912
913 MsgType msgType;
914 MsgSeqNum msgSeqNum;
915
916 message.getHeader().getField( msgType );
917 message.getHeader().getField( msgSeqNum );
918 if ( beginString >= FIX::BeginString_FIX42 )
919 reject.setField( RefMsgType( msgType ) );
920 reject.setField( RefSeqNum( msgSeqNum ) );
921
922 if ( msgType != MsgType_Logon && msgType != MsgType_SequenceReset )
923 m_state.incrNextTargetMsgSeqNum();
924
925 reject.setField( Text( str ) );
926 sendRaw( reject );
927 m_state.onEvent( "Message " + msgSeqNum.getString()
928 + " Rejected: " + str );
929}
930
931void Session::generateBusinessReject( const Message& message, int err, int field )
932{
933 SmartPtr<Message> pMsg(newMessage("j"));
934 Message & reject = *pMsg;
935
936 reject.getHeader().setField( MsgType( MsgType_BusinessMessageReject ) );
937 if( m_sessionID.isFIXT() )
938 reject.setField( DefaultApplVerID(m_senderDefaultApplVerID) );
939 fill( reject.getHeader() );
940 MsgType msgType;
941 MsgSeqNum msgSeqNum;
942 message.getHeader().getField( msgType );
943 message.getHeader().getField( msgSeqNum );
944 reject.setField( RefMsgType( msgType ) );
945 reject.setField( RefSeqNum( msgSeqNum ) );
946 reject.setField( BusinessRejectReason( err ) );
947 m_state.incrNextTargetMsgSeqNum();
948
949 const char* reason = 0;
950 switch ( err )
951 {
952 case BusinessRejectReason_OTHER:
954 break;
955 case BusinessRejectReason_UNKNOWN_ID:
957 break;
958 case BusinessRejectReason_UNKNOWN_SECURITY:
960 break;
961 case BusinessRejectReason_UNKNOWN_MESSAGE_TYPE:
963 break;
964 case BusinessRejectReason_APPLICATION_NOT_AVAILABLE:
966 break;
967 case BusinessRejectReason_CONDITIONALLY_REQUIRED_FIELD_MISSING:
969 break;
970 case BusinessRejectReason_NOT_AUTHORIZED:
972 break;
973 case BusinessRejectReason_DELIVERTO_FIRM_NOT_AVAILABLE_AT_THIS_TIME:
975 break;
976 };
977
978 if ( reason && field )
979 {
980 populateRejectReason( reject, field, reason );
981 m_state.onEvent( "Message " + msgSeqNum.getString() + " Rejected: "
982 + reason + ":" + IntConvertor::convert( field ) );
983 }
984 else if ( reason )
985 {
986 populateRejectReason( reject, reason );
987 m_state.onEvent( "Message " + msgSeqNum.getString()
988 + " Rejected: " + reason );
989 }
990 else
991 m_state.onEvent( "Message " + msgSeqNum.getString() + " Rejected" );
992
993 sendRaw( reject );
994}
995
996void Session::generateLogout( const std::string& text )
997{
998 SmartPtr<Message> pMsg(newMessage("5"));
999 Message & logout = *pMsg;
1000
1001 logout.getHeader().setField( MsgType( MsgType_Logout ) );
1002 fill( logout.getHeader() );
1003 if ( text.length() )
1004 logout.setField( Text( text ) );
1005 sendRaw( logout );
1006 m_state.sentLogout( true );
1007}
1008
1010 const std::string& text )
1011{
1012 MsgType msgType;
1013 reject.getHeader().getField( msgType );
1014
1015 if ( msgType == MsgType_Reject
1016 && m_sessionID.getBeginString() >= FIX::BeginString_FIX42 )
1017 {
1018 reject.setField( RefTagID( field ) );
1019 reject.setField( Text( text ) );
1020 }
1021 else
1022 {
1023 std::stringstream stream;
1024 stream << text << " (" << field << ")";
1025 reject.setField( Text( stream.str() ) );
1026 }
1027}
1028
1029void Session::populateRejectReason( Message& reject, const std::string& text )
1030{
1031 reject.setField( Text( text ) );
1032}
1033
1034bool Session::verify( const Message& msg, bool checkTooHigh,
1035 bool checkTooLow )
1036{
1037 const MsgType* pMsgType = 0;
1038 const MsgSeqNum* pMsgSeqNum = 0;
1039
1040 try
1041 {
1042 const Header& header = msg.getHeader();
1043
1044 pMsgType = FIELD_GET_PTR( header, MsgType );
1045 const SenderCompID& senderCompID = FIELD_GET_REF( header, SenderCompID );
1046 const TargetCompID& targetCompID = FIELD_GET_REF( header, TargetCompID );
1047 const SendingTime& sendingTime = FIELD_GET_REF( header, SendingTime );
1048
1049 if( checkTooHigh || checkTooLow )
1050 pMsgSeqNum = FIELD_GET_PTR( header, MsgSeqNum );
1051
1052 if ( !validLogonState( *pMsgType ) )
1053 throw std::logic_error( "Logon state is not valid for message" );
1054
1055 if ( !isGoodTime( sendingTime ) )
1056 {
1057 doBadTime( msg );
1058 return false;
1059 }
1060 if ( !isCorrectCompID( senderCompID, targetCompID ) )
1061 {
1062 doBadCompID( msg );
1063 return false;
1064 }
1065
1066 if ( checkTooHigh && isTargetTooHigh( *pMsgSeqNum ) )
1067 {
1068 doTargetTooHigh( msg );
1069 return false;
1070 }
1071 else if ( checkTooLow && isTargetTooLow( *pMsgSeqNum ) )
1072 {
1073 doTargetTooLow( msg );
1074 return false;
1075 }
1076
1077 if ( (checkTooHigh || checkTooLow) && m_state.resendRequested() )
1078 {
1079 SessionState::ResendRange range = m_state.resendRange();
1080
1081 if ( *pMsgSeqNum >= range.second )
1082 {
1083 m_state.onEvent ("ResendRequest for messages FROM: " +
1084 IntConvertor::convert (range.first) + " TO: " +
1085 IntConvertor::convert (range.second) +
1086 " has been satisfied.");
1087 m_state.resendRange (0, 0);
1088 }
1089 }
1090 }
1091 catch ( std::exception& e )
1092 {
1093 m_state.onEvent( e.what() );
1094 disconnect();
1095 return false;
1096 }
1097
1098 UtcTimeStamp now;
1099 m_state.lastReceivedTime( now );
1100 m_state.testRequest( 0 );
1101
1102 fromCallback( pMsgType ? *pMsgType : MsgType(), msg, m_sessionID );
1103 return true;
1104}
1105
1107{
1108 std::string beginString = m_sessionID.getBeginString();
1109 return beginString >= FIX::BeginString_FIX41
1110 && ( m_resetOnLogon ||
1111 m_resetOnLogout ||
1113 && ( getExpectedSenderNum() == 1 )
1114 && ( getExpectedTargetNum() == 1 );
1115}
1116
1117bool Session::validLogonState( const MsgType& msgType )
1118{
1119 if ( (msgType == MsgType_Logon && m_state.sentReset())
1120 || (m_state.receivedReset()) )
1121 return true;
1122 if ( (msgType == MsgType_Logon && !m_state.receivedLogon())
1123 || (msgType != MsgType_Logon && m_state.receivedLogon()) )
1124 return true;
1125 if ( msgType == MsgType_Logout && m_state.sentLogon() )
1126 return true;
1127 if ( msgType != MsgType_Logout && m_state.sentLogout() )
1128 return true;
1129 if ( msgType == MsgType_SequenceReset )
1130 return true;
1131 if ( msgType == MsgType_Reject )
1132 return true;
1133
1134 return false;
1135}
1136
1137void Session::fromCallback( const MsgType& msgType, const Message& msg,
1138 const SessionID& sessionID )
1139{
1140 if ( Message::isAdminMsgType( msgType ) )
1141 m_application.fromAdmin( msg, m_sessionID );
1142 else
1143 m_application.fromApp( msg, m_sessionID );
1144}
1145
1146void Session::doBadTime( const Message& msg )
1147{
1148 generateReject( msg, SessionRejectReason_SENDINGTIME_ACCURACY_PROBLEM );
1150}
1151
1153{
1154 generateReject( msg, SessionRejectReason_COMPID_PROBLEM );
1156}
1157
1158bool Session::doPossDup( const Message& msg )
1159{
1160 const Header & header = msg.getHeader();
1161 OrigSendingTime origSendingTime;
1162 SendingTime sendingTime;
1163 MsgType msgType;
1164
1165 header.getField( msgType );
1166 header.getField( sendingTime );
1167
1168 if ( msgType != MsgType_SequenceReset )
1169 {
1170 if ( !header.getFieldIfSet( origSendingTime ) )
1171 {
1172 generateReject( msg, SessionRejectReason_REQUIRED_TAG_MISSING, origSendingTime.getTag() );
1173 return false;
1174 }
1175
1176 if ( origSendingTime > sendingTime )
1177 {
1178 generateReject( msg, SessionRejectReason_SENDINGTIME_ACCURACY_PROBLEM );
1180 return false;
1181 }
1182 }
1183 return true;
1184}
1185
1187{
1188 const Header & header = msg.getHeader();
1189 PossDupFlag possDupFlag(false);
1190 MsgSeqNum msgSeqNum;
1191 header.getFieldIfSet(possDupFlag);
1192 header.getField( msgSeqNum );
1193
1194 if ( !possDupFlag )
1195 {
1196 std::stringstream stream;
1197 stream << "MsgSeqNum too low, expecting " << getExpectedTargetNum()
1198 << " but received " << msgSeqNum;
1199 generateLogout( stream.str() );
1200 throw std::logic_error( stream.str() );
1201 }
1202
1203 return doPossDup( msg );
1204}
1205
1207{
1208 const Header & header = msg.getHeader();
1209 BeginString beginString;
1210 MsgSeqNum msgSeqNum;
1211 header.getField( beginString );
1212 header.getField( msgSeqNum );
1213
1214 m_state.onEvent( "MsgSeqNum too high, expecting "
1216 + " but received "
1217 + IntConvertor::convert( msgSeqNum ) );
1218
1219 m_state.queue( msgSeqNum, msg );
1220
1221 if( m_state.resendRequested() )
1222 {
1223 SessionState::ResendRange range = m_state.resendRange();
1224
1225 if( !m_sendRedundantResendRequests && msgSeqNum >= range.first )
1226 {
1227 m_state.onEvent ("Already sent ResendRequest FROM: " +
1228 IntConvertor::convert (range.first) + " TO: " +
1229 IntConvertor::convert (range.second) +
1230 ". Not sending another.");
1231 return;
1232 }
1233 }
1234
1235 generateResendRequest( beginString, msgSeqNum );
1236}
1237
1238void Session::nextQueued( const UtcTimeStamp& timeStamp )
1239{
1240 while ( nextQueued( getExpectedTargetNum(), timeStamp ) ) {}
1241}
1242
1243bool Session::nextQueued( int num, const UtcTimeStamp& timeStamp )
1244{
1245 Message msg;
1246 MsgType msgType;
1247
1248 if( m_state.retrieve( num, msg ) )
1249 {
1250 m_state.onEvent( "Processing QUEUED message: "
1251 + IntConvertor::convert( num ) );
1252 msg.getHeader().getField( msgType );
1253 if( msgType == MsgType_Logon
1254 || msgType == MsgType_ResendRequest )
1255 {
1256 m_state.incrNextTargetMsgSeqNum();
1257 }
1258 else
1259 {
1260 next( msg, timeStamp, true );
1261 }
1262 return true;
1263 }
1264 return false;
1265}
1266
1267void Session::next( const std::string& msg, const UtcTimeStamp& timeStamp, bool queued )
1268{
1269 try
1270 {
1271 m_state.onIncoming( msg );
1272 const DataDictionary& sessionDD =
1273 m_dataDictionaryProvider.getSessionDataDictionary(m_sessionID.getBeginString());
1274 if( m_sessionID.isFIXT() )
1275 {
1276 const DataDictionary& applicationDD =
1277 m_dataDictionaryProvider.getApplicationDataDictionary(m_senderDefaultApplVerID);
1278 next( Message( msg, sessionDD, applicationDD, m_validateLengthAndChecksum ), timeStamp, queued );
1279 }
1280 else
1281 {
1282 next( Message( msg, sessionDD, m_validateLengthAndChecksum ), timeStamp, queued );
1283 }
1284 }
1285 catch( InvalidMessage& e )
1286 {
1287 m_state.onEvent( e.what() );
1288
1289 try
1290 {
1291 if( identifyType(msg) == MsgType_Logon )
1292 {
1293 m_state.onEvent( "Logon message is not valid" );
1294 disconnect();
1295 }
1296 } catch( MessageParseError& ) {}
1297 throw e;
1298 }
1299}
1300
1301void Session::next( const Message& message, const UtcTimeStamp& timeStamp, bool queued )
1302{
1303 const Header& header = message.getHeader();
1304
1305 try
1306 {
1307 if ( !checkSessionTime(timeStamp) )
1308 { reset(); return; }
1309
1310 const MsgType& msgType = FIELD_GET_REF( header, MsgType );
1311 const BeginString& beginString = FIELD_GET_REF( header, BeginString );
1312 // make sure these fields are present
1313 FIELD_THROW_IF_NOT_FOUND( header, SenderCompID );
1314 FIELD_THROW_IF_NOT_FOUND( header, TargetCompID );
1315
1316 if ( beginString != m_sessionID.getBeginString() )
1317 throw UnsupportedVersion();
1318
1319 if( msgType == MsgType_Logon )
1320 {
1321 if( m_sessionID.isFIXT() )
1322 {
1323 const DefaultApplVerID& applVerID = FIELD_GET_REF( message, DefaultApplVerID );
1324 setTargetDefaultApplVerID(applVerID);
1325 }
1326 else
1327 {
1329 }
1330 }
1331
1332 const DataDictionary& sessionDataDictionary =
1333 m_dataDictionaryProvider.getSessionDataDictionary(m_sessionID.getBeginString());
1334
1335 if( m_sessionID.isFIXT() && message.isApp() )
1336 {
1337 ApplVerID applVerID = m_targetDefaultApplVerID;
1338 header.getFieldIfSet(applVerID);
1339 const DataDictionary& applicationDataDictionary =
1340 m_dataDictionaryProvider.getApplicationDataDictionary(applVerID);
1341 DataDictionary::validate( message, &sessionDataDictionary, &applicationDataDictionary );
1342 }
1343 else
1344 {
1345 sessionDataDictionary.validate( message );
1346 }
1347
1348 if ( msgType == MsgType_Logon )
1349 nextLogon( message, timeStamp );
1350 else if ( msgType == MsgType_Heartbeat )
1351 nextHeartbeat( message, timeStamp );
1352 else if ( msgType == MsgType_TestRequest )
1353 nextTestRequest( message, timeStamp );
1354 else if ( msgType == MsgType_SequenceReset )
1355 nextSequenceReset( message, timeStamp );
1356 else if ( msgType == MsgType_Logout )
1357 nextLogout( message, timeStamp );
1358 else if ( msgType == MsgType_ResendRequest )
1359 nextResendRequest( message,timeStamp );
1360 else if ( msgType == MsgType_Reject )
1361 nextReject( message, timeStamp );
1362 else
1363 {
1364 if ( !verify( message ) ) return ;
1365 m_state.incrNextTargetMsgSeqNum();
1366 }
1367 }
1368 catch ( MessageParseError& e )
1369 { m_state.onEvent( e.what() ); }
1370 catch ( RequiredTagMissing & e )
1371 { LOGEX( generateReject( message, SessionRejectReason_REQUIRED_TAG_MISSING, e.field ) ); }
1372 catch ( FieldNotFound & e )
1373 {
1374 if( header.getField(FIELD::BeginString) >= FIX::BeginString_FIX42 && message.isApp() )
1375 {
1376 LOGEX( generateBusinessReject( message, BusinessRejectReason_CONDITIONALLY_REQUIRED_FIELD_MISSING, e.field ) );
1377 }
1378 else
1379 {
1380 LOGEX( generateReject( message, SessionRejectReason_REQUIRED_TAG_MISSING, e.field ) );
1381 if ( header.getField(FIELD::MsgType) == MsgType_Logon )
1382 {
1383 m_state.onEvent( "Required field missing from logon" );
1384 disconnect();
1385 }
1386 }
1387 }
1388 catch ( InvalidTagNumber & e )
1389 { LOGEX( generateReject( message, SessionRejectReason_INVALID_TAG_NUMBER, e.field ) ); }
1390 catch ( NoTagValue & e )
1391 { LOGEX( generateReject( message, SessionRejectReason_TAG_SPECIFIED_WITHOUT_A_VALUE, e.field ) ); }
1392 catch ( TagNotDefinedForMessage & e )
1393 { LOGEX( generateReject( message, SessionRejectReason_TAG_NOT_DEFINED_FOR_THIS_MESSAGE_TYPE, e.field ) ); }
1394 catch ( InvalidMessageType& )
1395 { LOGEX( generateReject( message, SessionRejectReason_INVALID_MSGTYPE ) ); }
1396 catch ( UnsupportedMessageType& )
1397 {
1398 if ( header.getField(FIELD::BeginString) >= FIX::BeginString_FIX42 )
1399 { LOGEX( generateBusinessReject( message, BusinessRejectReason_UNKNOWN_MESSAGE_TYPE ) ); }
1400 else
1401 { LOGEX( generateReject( message, "Unsupported message type" ) ); }
1402 }
1403 catch ( TagOutOfOrder & e )
1404 { LOGEX( generateReject( message, SessionRejectReason_TAG_SPECIFIED_OUT_OF_REQUIRED_ORDER, e.field ) ); }
1405 catch ( IncorrectDataFormat & e )
1406 { LOGEX( generateReject( message, SessionRejectReason_INCORRECT_DATA_FORMAT_FOR_VALUE, e.field ) ); }
1407 catch ( IncorrectTagValue & e )
1408 { LOGEX( generateReject( message, SessionRejectReason_VALUE_IS_INCORRECT, e.field ) ); }
1409 catch ( RepeatedTag & e )
1410 { LOGEX( generateReject( message, SessionRejectReason_TAG_APPEARS_MORE_THAN_ONCE, e.field ) ); }
1411 catch ( RepeatingGroupCountMismatch & e )
1412 { LOGEX( generateReject( message, SessionRejectReason_INCORRECT_NUMINGROUP_COUNT_FOR_REPEATING_GROUP, e.field ) ); }
1413 catch ( InvalidMessage& e )
1414 { m_state.onEvent( e.what() ); }
1415 catch ( RejectLogon& e )
1416 {
1417 m_state.onEvent( e.what() );
1418 generateLogout( e.what() );
1419 disconnect();
1420 }
1421 catch ( UnsupportedVersion& )
1422 {
1423 if ( header.getField(FIELD::MsgType) == MsgType_Logout )
1424 nextLogout( message, timeStamp );
1425 else
1426 {
1427 generateLogout( "Incorrect BeginString" );
1428 m_state.incrNextTargetMsgSeqNum();
1429 }
1430 }
1431 catch ( IOException& e )
1432 {
1433 m_state.onEvent( e.what() );
1434 disconnect();
1435 }
1436
1437 if( !queued )
1438 nextQueued( timeStamp );
1439
1440 if( isLoggedOn() )
1441 next();
1442}
1443
1444bool Session::sendToTarget( Message& message, const std::string& qualifier )
1445throw( SessionNotFound )
1446{
1447 try
1448 {
1449 SessionID sessionID = message.getSessionID( qualifier );
1450 return sendToTarget( message, sessionID );
1451 }
1452 catch ( FieldNotFound& ) { throw SessionNotFound(); }
1453}
1454
1455bool Session::sendToTarget( Message& message, const SessionID& sessionID )
1456throw( SessionNotFound )
1457{
1458 message.setSessionID( sessionID );
1459 Session* pSession = lookupSession( sessionID );
1460 if ( !pSession ) throw SessionNotFound();
1461 return pSession->send( message );
1462}
1463
1465( Message& message,
1466 const SenderCompID& senderCompID,
1467 const TargetCompID& targetCompID,
1468 const std::string& qualifier )
1469throw( SessionNotFound )
1470{
1471 message.getHeader().setField( senderCompID );
1472 message.getHeader().setField( targetCompID );
1473 return sendToTarget( message, qualifier );
1474}
1475
1477( Message& message, const std::string& sender, const std::string& target,
1478 const std::string& qualifier )
1479throw( SessionNotFound )
1480{
1481 return sendToTarget( message, SenderCompID( sender ),
1482 TargetCompID( target ), qualifier );
1483}
1484
1485std::set<SessionID> Session::getSessions()
1486{
1487 return s_sessionIDs;
1488}
1489
1490bool Session::doesSessionExist( const SessionID& sessionID )
1491{
1492 Locker locker( s_mutex );
1493 return s_sessions.end() != s_sessions.find( sessionID );
1494}
1495
1497{
1498 Locker locker( s_mutex );
1499 Sessions::iterator find = s_sessions.find( sessionID );
1500 if ( find != s_sessions.end() )
1501 return find->second;
1502 else
1503 return 0;
1504}
1505
1506Session* Session::lookupSession( const std::string& string, bool reverse )
1507{
1508 Message message;
1509 if ( !message.setStringHeader( string ) )
1510 return 0;
1511
1512 try
1513 {
1514 const Header& header = message.getHeader();
1515 const BeginString& beginString = FIELD_GET_REF( header, BeginString );
1516 const SenderCompID& senderCompID = FIELD_GET_REF( header, SenderCompID );
1517 const TargetCompID& targetCompID = FIELD_GET_REF( header, TargetCompID );
1518
1519 if ( reverse )
1520 {
1521 return lookupSession( SessionID( beginString, SenderCompID( targetCompID ),
1522 TargetCompID( senderCompID ) ) );
1523 }
1524
1525 return lookupSession( SessionID( beginString, senderCompID,
1526 targetCompID ) );
1527 }
1528 catch ( FieldNotFound& ) { return 0; }
1529}
1530
1532{
1533 Locker locker( s_mutex );
1534 return s_registered.end() != s_registered.find( sessionID );
1535}
1536
1538{
1539 Locker locker( s_mutex );
1540 Session* pSession = lookupSession( sessionID );
1541 if ( pSession == 0 ) return 0;
1542 if ( isSessionRegistered( sessionID ) ) return 0;
1543 s_registered[ sessionID ] = pSession;
1544 return pSession;
1545}
1546
1548{
1549 Locker locker( s_mutex );
1550 s_registered.erase( sessionID );
1551}
1552
1554{
1555 Locker locker( s_mutex );
1556 return s_sessions.size();
1557}
1558
1560{
1561 Locker locker( s_mutex );
1562 Sessions::iterator it = s_sessions.find( s.m_sessionID );
1563 if ( it == s_sessions.end() )
1564 {
1565 s_sessions[ s.m_sessionID ] = &s;
1566 s_sessionIDs.insert( s.m_sessionID );
1567 return true;
1568 }
1569 else
1570 return false;
1571}
1572
1574{
1575 Locker locker( s_mutex );
1576 s_sessions.erase( s.m_sessionID );
1577 s_sessionIDs.erase( s.m_sessionID );
1578 s_registered.erase( s.m_sessionID );
1579}
1580}
#define SmartPtr
#define FIELD_GET_REF(MAP, FLD)
Definition FieldMap.h:376
#define FIELD_GET_PTR(MAP, FLD)
Definition FieldMap.h:374
#define FIELD_THROW_IF_NOT_FOUND(MAP, FLD)
Definition FieldMap.h:378
#define LOGEX(method)
Definition Session.cpp:38
This interface must be implemented to define what your FIX application does.
Definition Application.h:44
Represents a data dictionary for a version of FIX.
message_order const & getTrailerOrderedFields() const
bool isMessageFieldsOrderPreserved() const
static void validate(const Message &message, const DataDictionary *const pSessionDD, const DataDictionary *const pAppID)
Validate a message.
message_order const & getHeaderOrderedFields() const
message_order const & getMessageOrderedFields(const std::string &msgType) const
Queries for DataDictionary based on appropriate version of FIX.
void setField(const FieldBase &field, bool overwrite=true)
Set a field without type checking.
Definition FieldMap.h:116
void removeField(int tag)
Remove a field. If field is not present, this is a no-op.
Definition FieldMap.cpp:156
FieldBase & getField(FieldBase &field) const
Get a field without type checking.
Definition FieldMap.h:156
bool getFieldIfSet(FieldBase &field) const
Get a field if set.
Definition FieldMap.h:146
Locks/Unlocks a mutex using RAII.
Definition Mutex.h:96
This interface must be implemented to create a Log.
Definition Log.h:43
Base class for all FIX messages.
Definition Message.h:118
bool setStringHeader(const std::string &string)
Set a messages header from a string This is an optimization that can be used to get useful informatio...
Definition Message.cpp:475
static ApplVerID toApplVerID(const BeginString &value)
Definition Message.h:307
bool isApp() const
Definition Message.h:280
static bool isAdminMsgType(const MsgType &msgType)
Definition Message.h:300
std::string toString(int beginStringField=FIELD::BeginString, int bodyLengthField=FIELD::BodyLength, int checkSumField=FIELD::CheckSum) const
Get a string representation of the message.
Definition Message.cpp:236
void reverseRoute(const Header &)
Add header informations depending on a source message.
Definition Message.cpp:150
const Header & getHeader() const
Getter for the message header.
Definition Message.h:245
This interface must be implemented to create a MessageStore.
Portable implementation of a mutex.
Definition Mutex.h:31
MessageStoreFactory & m_messageStoreFactory
Definition Session.h:339
void fromCallback(const MsgType &msgType, const Message &msg, const SessionID &sessionID)
Definition Session.cpp:1137
bool m_resetOnLogout
Definition Session.h:330
int m_maxLatency
Definition Session.h:328
static Session * registerSession(const SessionID &)
Definition Session.cpp:1537
void nextQueued(const UtcTimeStamp &timeStamp)
Definition Session.cpp:1238
LogFactory * m_pLogFactory
Definition Session.h:340
bool isTargetTooHigh(const MsgSeqNum &msgSeqNum)
Definition Session.h:260
bool isGoodTime(const SendingTime &sendingTime)
Definition Session.h:249
bool m_checkLatency
Definition Session.h:327
void nextHeartbeat(const Message &, const UtcTimeStamp &timeStamp)
Definition Session.cpp:280
void insertSendingTime(Header &)
Definition Session.cpp:91
static Mutex s_mutex
Definition Session.h:347
void nextSequenceReset(const Message &, const UtcTimeStamp &timeStamp)
Definition Session.cpp:319
Application & m_application
Definition Session.h:318
void nextLogout(const Message &, const UtcTimeStamp &timeStamp)
Definition Session.cpp:295
void populateRejectReason(Message &, int field, const std::string &)
Definition Session.cpp:1009
bool isTargetTooLow(const MsgSeqNum &msgSeqNum)
Definition Session.h:262
SessionState m_state
Definition Session.h:337
bool m_refreshOnLogon
Definition Session.h:332
static void unregisterSession(const SessionID &)
Definition Session.cpp:1547
bool m_persistMessages
Definition Session.h:334
void fill(Header &)
Definition Session.cpp:114
bool send(Message &)
Definition Session.cpp:523
bool resend(Message &message)
Definition Session.cpp:643
void insertOrigSendingTime(Header &, const UtcTimeStamp &when=UtcTimeStamp())
Definition Session.cpp:103
bool isCorrectCompID(const SenderCompID &senderCompID, const TargetCompID &targetCompID)
Definition Session.h:264
void logout(const std::string &reason="")
Definition Session.h:57
void generateHeartbeat()
Definition Session.cpp:764
Responder * m_pResponder
Definition Session.h:341
DataDictionaryProvider m_dataDictionaryProvider
Definition Session.h:338
bool checkSessionTime(const UtcTimeStamp &timeStamp)
Definition Session.h:255
static bool doesSessionExist(const SessionID &)
Definition Session.cpp:1490
bool m_sendRedundantResendRequests
Definition Session.h:325
void setTargetDefaultApplVerID(const std::string &targetDefaultApplVerID)
Definition Session.h:129
bool validLogonState(const MsgType &msgType)
Definition Session.cpp:1117
static void removeSession(Session &)
Definition Session.cpp:1573
SessionID m_sessionID
Definition Session.h:319
bool doTargetTooLow(const Message &msg)
Definition Session.cpp:1186
void reset()
Definition Session.h:66
void generateLogon()
Definition Session.cpp:673
Mutex m_mutex
Definition Session.h:342
bool isEnabled()
Definition Session.h:59
void generateResendRequest(const BeginString &, const MsgSeqNum &)
Definition Session.cpp:718
int getExpectedTargetNum()
Definition Session.h:225
bool verify(const Message &msg, bool checkTooHigh=true, bool checkTooLow=true)
Definition Session.cpp:1034
void nextReject(const Message &, const UtcTimeStamp &timeStamp)
Definition Session.cpp:312
static Session * lookupSession(const SessionID &)
Definition Session.cpp:1496
void generateBusinessReject(const Message &, int err, int field=0)
Definition Session.cpp:931
void nextTestRequest(const Message &, const UtcTimeStamp &timeStamp)
Definition Session.cpp:287
bool shouldSendReset()
Definition Session.cpp:1106
void nextLogon(const Message &, const UtcTimeStamp &timeStamp)
Definition Session.cpp:202
std::string m_targetDefaultApplVerID
Definition Session.h:324
void refresh()
Definition Session.h:68
void nextResendRequest(const Message &, const UtcTimeStamp &timeStamp)
Definition Session.cpp:344
void generateTestRequest(const std::string &)
Definition Session.cpp:792
std::string m_senderDefaultApplVerID
Definition Session.h:323
void next()
Definition Session.cpp:125
bool doPossDup(const Message &msg)
Definition Session.cpp:1158
int m_timestampPrecision
Definition Session.h:333
std::set< SessionID > SessionIDs
Definition Session.h:234
void disconnect()
Definition Session.cpp:613
static Sessions s_registered
Definition Session.h:346
void doBadTime(const Message &msg)
Definition Session.cpp:1146
static SessionIDs s_sessionIDs
Definition Session.h:345
void doTargetTooHigh(const Message &msg)
Definition Session.cpp:1206
void logon()
Definition Session.h:55
static bool addSession(Session &)
Definition Session.cpp:1559
void generateLogout(const std::string &text="")
Definition Session.cpp:996
bool isLogonTime(const UtcTimeStamp &time)
Definition Session.h:110
void generateReject(const Message &, int err, int field=0)
Definition Session.cpp:805
bool m_resetOnDisconnect
Definition Session.h:331
int getExpectedSenderNum()
Definition Session.h:224
bool sendRaw(Message &, int msgSeqNum=0)
Definition Session.cpp:530
void doBadCompID(const Message &msg)
Definition Session.cpp:1152
bool m_validateLengthAndChecksum
Definition Session.h:335
std::map< SessionID, Session * > Sessions
Definition Session.h:233
bool m_resetOnLogon
Definition Session.h:329
virtual ~Session()
Definition Session.cpp:83
TimeRange m_sessionTime
Definition Session.h:320
bool m_checkCompId
Definition Session.h:326
static std::set< SessionID > getSessions()
Definition Session.cpp:1485
static Sessions s_sessions
Definition Session.h:344
static bool isSessionRegistered(const SessionID &)
Definition Session.cpp:1531
Message * newMessage(const std::string &msgType) const
Definition Session.cpp:492
void generateSequenceReset(int, int)
Definition Session.cpp:743
static bool sendToTarget(Message &message, const std::string &qualifier="")
Definition Session.cpp:1444
Session(Application &, MessageStoreFactory &, const SessionID &, const DataDictionaryProvider &, const TimeRange &, int heartBtInt, LogFactory *pLogFactory)
Definition Session.cpp:41
bool isLoggedOn()
Definition Session.h:65
static size_t numSessions()
Definition Session.cpp:1553
TimeRange m_logonTime
Definition Session.h:321
void persist(const Message &, const std::string &)
Definition Session.cpp:663
Unique session id consists of BeginString, SenderCompID and TargetCompID.
Definition SessionID.h:31
std::pair< int, int > ResendRange
Keeps track of when session is active.
Definition TimeRange.h:35
Date and Time represented in UTC.
Definition FieldTypes.h:583
const char SessionRejectReason_INCORRECT_DATA_FORMAT_FOR_VALUE_TEXT[]
Definition Values.h:44
const char BeginString_FIX41[]
Definition Values.h:35
const char BusinessRejectReason_CONDITIONALLY_REQUIRED_FIELD_MISSING_TEXT[]
Definition Values.h:58
const char BusinessRejectReason_NOT_AUTHORIZED_TEXT[]
Definition Values.h:59
const char BusinessRejectReason_APPLICATION_NOT_AVAILABLE_TEXT[]
Definition Values.h:57
const char SessionRejectReason_COMPID_PROBLEM_TEXT[]
Definition Values.h:47
const char BusinessRejectReason_UNSUPPORTED_MESSAGE_TYPE_TEXT[]
Definition Values.h:56
const char SessionRejectReason_INCORRECT_NUMINGROUP_COUNT_FOR_REPEATING_GROUP_TEXT[]
Definition Values.h:52
const char BeginString_FIX42[]
Definition Values.h:34
const char SessionRejectReason_TAG_SPECIFIED_WITHOUT_A_VALUE_TEXT[]
Definition Values.h:42
const char BusinessRejectReason_DELIVERTO_FIRM_NOT_AVAILABLE_AT_THIS_TIME_TEXT[]
Definition Values.h:60
const char BusinessRejectReason_UNKNOWN_ID_TEXT[]
Definition Values.h:54
const char SessionRejectReason_REQUIRED_TAG_MISSING_TEXT[]
Definition Values.h:39
const char SessionRejectReason_INVALID_TAG_NUMBER_TEXT[]
Definition Values.h:38
const char BeginString_FIXT11[]
Definition Values.h:30
const char SessionRejectReason_TAG_SPECIFIED_OUT_OF_REQUIRED_ORDER_TEXT[]
Definition Values.h:51
const char BusinessRejectReason_OTHER_TEXT[]
Definition Values.h:53
const char BusinessRejectReason_UNKNOWN_SECURITY_TEXT[]
Definition Values.h:55
const char SessionRejectReason_INVALID_MSGTYPE_TEXT[]
Definition Values.h:49
const char SessionRejectReason_VALUE_IS_INCORRECT_TEXT[]
Definition Values.h:43
const char SessionRejectReason_TAG_APPEARS_MORE_THAN_ONCE_TEXT[]
Definition Values.h:50
const char SessionRejectReason_TAG_NOT_DEFINED_FOR_THIS_MESSAGE_TYPE_TEXT[]
Definition Values.h:40
const char SessionRejectReason_SENDINGTIME_ACCURACY_PROBLEM_TEXT[]
Definition Values.h:48
MsgType identifyType(const std::string &message)
Parse the type of a message from a string.
Definition Message.h:417
void reverse(I begin, I end)
Definition pugixml.cpp:6009
Indicates user does not want to send a message.
Definition Exceptions.h:218
Field not found inside a message.
Definition Exceptions.h:58
Field has a badly formatted value.
Definition Exceptions.h:147
Field has a value that is out of range.
Definition Exceptions.h:138
static std::string convert(signed_int value)
Not a recognizable message.
Definition Exceptions.h:81
Not a known message type.
Definition Exceptions.h:170
Tag number does not exist in specification.
Definition Exceptions.h:102
Unable to parse message.
Definition Exceptions.h:74
Field exists in message without a value.
Definition Exceptions.h:129
User wants to reject permission to logon.
Definition Exceptions.h:225
Repeated tag not part of repeating group.
Definition Exceptions.h:200
Repeated group count not equal to actual count.
Definition Exceptions.h:209
Required field is not in message.
Definition Exceptions.h:111
Session cannot be found for specified action.
Definition Exceptions.h:232
Field does not belong to message.
Definition Exceptions.h:120
Tag is not in the correct order.
Definition Exceptions.h:191
Message type not supported by application.
Definition Exceptions.h:177
Version of FIX is not supported.
Definition Exceptions.h:184
Sorts fields in header, normal, or trailer order.

Generated on for QuickFIX by doxygen 1.15.0 written by Dimitri van Heesch, © 1997-2001