quickfix_ruby 1.14.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (149) hide show
  1. checksums.yaml +7 -0
  2. data/ext/quickfix/Acceptor.cpp +248 -0
  3. data/ext/quickfix/Acceptor.h +127 -0
  4. data/ext/quickfix/Allocator.h +9 -0
  5. data/ext/quickfix/Application.h +127 -0
  6. data/ext/quickfix/AtomicCount.h +109 -0
  7. data/ext/quickfix/DOMDocument.h +74 -0
  8. data/ext/quickfix/DataDictionary.cpp +618 -0
  9. data/ext/quickfix/DataDictionary.h +539 -0
  10. data/ext/quickfix/DataDictionaryProvider.cpp +71 -0
  11. data/ext/quickfix/DataDictionaryProvider.h +70 -0
  12. data/ext/quickfix/DatabaseConnectionID.h +105 -0
  13. data/ext/quickfix/DatabaseConnectionPool.h +91 -0
  14. data/ext/quickfix/Dictionary.cpp +162 -0
  15. data/ext/quickfix/Dictionary.h +94 -0
  16. data/ext/quickfix/Event.h +95 -0
  17. data/ext/quickfix/Exceptions.h +299 -0
  18. data/ext/quickfix/Field.h +672 -0
  19. data/ext/quickfix/FieldConvertors.h +863 -0
  20. data/ext/quickfix/FieldMap.cpp +238 -0
  21. data/ext/quickfix/FieldMap.h +244 -0
  22. data/ext/quickfix/FieldNumbers.h +46 -0
  23. data/ext/quickfix/FieldTypes.cpp +64 -0
  24. data/ext/quickfix/FieldTypes.h +698 -0
  25. data/ext/quickfix/Fields.h +31 -0
  26. data/ext/quickfix/FileLog.cpp +200 -0
  27. data/ext/quickfix/FileLog.h +112 -0
  28. data/ext/quickfix/FileStore.cpp +332 -0
  29. data/ext/quickfix/FileStore.h +129 -0
  30. data/ext/quickfix/FixFieldNumbers.h +1537 -0
  31. data/ext/quickfix/FixFields.h +1538 -0
  32. data/ext/quickfix/FixValues.h +3281 -0
  33. data/ext/quickfix/FlexLexer.h +188 -0
  34. data/ext/quickfix/Group.cpp +64 -0
  35. data/ext/quickfix/Group.h +73 -0
  36. data/ext/quickfix/HtmlBuilder.h +186 -0
  37. data/ext/quickfix/HttpConnection.cpp +739 -0
  38. data/ext/quickfix/HttpConnection.h +78 -0
  39. data/ext/quickfix/HttpMessage.cpp +149 -0
  40. data/ext/quickfix/HttpMessage.h +133 -0
  41. data/ext/quickfix/HttpParser.cpp +49 -0
  42. data/ext/quickfix/HttpParser.h +54 -0
  43. data/ext/quickfix/HttpServer.cpp +169 -0
  44. data/ext/quickfix/HttpServer.h +78 -0
  45. data/ext/quickfix/Initiator.cpp +289 -0
  46. data/ext/quickfix/Initiator.h +149 -0
  47. data/ext/quickfix/Log.cpp +77 -0
  48. data/ext/quickfix/Log.h +179 -0
  49. data/ext/quickfix/Message.cpp +580 -0
  50. data/ext/quickfix/Message.h +370 -0
  51. data/ext/quickfix/MessageCracker.h +188 -0
  52. data/ext/quickfix/MessageSorters.cpp +105 -0
  53. data/ext/quickfix/MessageSorters.h +156 -0
  54. data/ext/quickfix/MessageStore.cpp +146 -0
  55. data/ext/quickfix/MessageStore.h +174 -0
  56. data/ext/quickfix/Mutex.h +131 -0
  57. data/ext/quickfix/MySQLConnection.h +194 -0
  58. data/ext/quickfix/MySQLLog.cpp +275 -0
  59. data/ext/quickfix/MySQLLog.h +145 -0
  60. data/ext/quickfix/MySQLStore.cpp +331 -0
  61. data/ext/quickfix/MySQLStore.h +142 -0
  62. data/ext/quickfix/NullStore.cpp +54 -0
  63. data/ext/quickfix/NullStore.h +99 -0
  64. data/ext/quickfix/OdbcConnection.h +266 -0
  65. data/ext/quickfix/OdbcLog.cpp +252 -0
  66. data/ext/quickfix/OdbcLog.h +117 -0
  67. data/ext/quickfix/OdbcStore.cpp +338 -0
  68. data/ext/quickfix/OdbcStore.h +113 -0
  69. data/ext/quickfix/PUGIXML_DOMDocument.cpp +112 -0
  70. data/ext/quickfix/PUGIXML_DOMDocument.h +81 -0
  71. data/ext/quickfix/Parser.cpp +103 -0
  72. data/ext/quickfix/Parser.h +57 -0
  73. data/ext/quickfix/PostgreSQLConnection.h +176 -0
  74. data/ext/quickfix/PostgreSQLLog.cpp +276 -0
  75. data/ext/quickfix/PostgreSQLLog.h +144 -0
  76. data/ext/quickfix/PostgreSQLStore.cpp +334 -0
  77. data/ext/quickfix/PostgreSQLStore.h +141 -0
  78. data/ext/quickfix/Queue.h +75 -0
  79. data/ext/quickfix/QuickfixRuby.cpp +252066 -0
  80. data/ext/quickfix/QuickfixRuby.h +34 -0
  81. data/ext/quickfix/Responder.h +43 -0
  82. data/ext/quickfix/Session.cpp +1487 -0
  83. data/ext/quickfix/Session.h +335 -0
  84. data/ext/quickfix/SessionFactory.cpp +274 -0
  85. data/ext/quickfix/SessionFactory.h +86 -0
  86. data/ext/quickfix/SessionID.h +170 -0
  87. data/ext/quickfix/SessionSettings.cpp +189 -0
  88. data/ext/quickfix/SessionSettings.h +171 -0
  89. data/ext/quickfix/SessionState.h +231 -0
  90. data/ext/quickfix/Settings.cpp +100 -0
  91. data/ext/quickfix/Settings.h +53 -0
  92. data/ext/quickfix/SharedArray.h +150 -0
  93. data/ext/quickfix/SocketAcceptor.cpp +222 -0
  94. data/ext/quickfix/SocketAcceptor.h +75 -0
  95. data/ext/quickfix/SocketConnection.cpp +238 -0
  96. data/ext/quickfix/SocketConnection.h +103 -0
  97. data/ext/quickfix/SocketConnector.cpp +116 -0
  98. data/ext/quickfix/SocketConnector.h +67 -0
  99. data/ext/quickfix/SocketInitiator.cpp +260 -0
  100. data/ext/quickfix/SocketInitiator.h +81 -0
  101. data/ext/quickfix/SocketMonitor.cpp +335 -0
  102. data/ext/quickfix/SocketMonitor.h +111 -0
  103. data/ext/quickfix/SocketServer.cpp +177 -0
  104. data/ext/quickfix/SocketServer.h +100 -0
  105. data/ext/quickfix/ThreadedSocketAcceptor.cpp +258 -0
  106. data/ext/quickfix/ThreadedSocketAcceptor.h +98 -0
  107. data/ext/quickfix/ThreadedSocketConnection.cpp +209 -0
  108. data/ext/quickfix/ThreadedSocketConnection.h +82 -0
  109. data/ext/quickfix/ThreadedSocketInitiator.cpp +268 -0
  110. data/ext/quickfix/ThreadedSocketInitiator.h +84 -0
  111. data/ext/quickfix/TimeRange.cpp +173 -0
  112. data/ext/quickfix/TimeRange.h +258 -0
  113. data/ext/quickfix/Utility.cpp +537 -0
  114. data/ext/quickfix/Utility.h +219 -0
  115. data/ext/quickfix/Values.h +62 -0
  116. data/ext/quickfix/config.h +0 -0
  117. data/ext/quickfix/config_windows.h +0 -0
  118. data/ext/quickfix/extconf.rb +12 -0
  119. data/ext/quickfix/index.h +37 -0
  120. data/ext/quickfix/pugiconfig.hpp +72 -0
  121. data/ext/quickfix/pugixml.cpp +10765 -0
  122. data/ext/quickfix/pugixml.hpp +1341 -0
  123. data/ext/quickfix/strptime.h +7 -0
  124. data/lib/quickfix40.rb +274 -0
  125. data/lib/quickfix41.rb +351 -0
  126. data/lib/quickfix42.rb +1184 -0
  127. data/lib/quickfix43.rb +3504 -0
  128. data/lib/quickfix44.rb +10721 -0
  129. data/lib/quickfix50.rb +13426 -0
  130. data/lib/quickfix50sp1.rb +15629 -0
  131. data/lib/quickfix50sp2.rb +17068 -0
  132. data/lib/quickfix_fields.rb +19853 -0
  133. data/lib/quickfix_ruby.rb +82 -0
  134. data/lib/quickfixt11.rb +70 -0
  135. data/spec/FIX40.xml +862 -0
  136. data/spec/FIX41.xml +1285 -0
  137. data/spec/FIX42.xml +2746 -0
  138. data/spec/FIX43.xml +4229 -0
  139. data/spec/FIX44.xml +6596 -0
  140. data/spec/FIX50.xml +8137 -0
  141. data/spec/FIX50SP1.xml +9496 -0
  142. data/spec/FIX50SP2.xml +10011 -0
  143. data/spec/FIXT11.xml +313 -0
  144. data/test/test_DataDictionaryTestCase.rb +268 -0
  145. data/test/test_DictionaryTestCase.rb +112 -0
  146. data/test/test_FieldBaseTestCase.rb +24 -0
  147. data/test/test_MessageTestCase.rb +368 -0
  148. data/test/test_SessionSettingsTestCase.rb +41 -0
  149. metadata +193 -0
@@ -0,0 +1,1487 @@
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
+
31
+ namespace FIX
32
+ {
33
+ Session::Sessions Session::s_sessions;
34
+ Session::SessionIDs Session::s_sessionIDs;
35
+ Session::Sessions Session::s_registered;
36
+ Mutex Session::s_mutex;
37
+
38
+ #define LOGEX( method ) try { method; } catch( std::exception& e ) \
39
+ { m_state.onEvent( e.what() ); }
40
+
41
+ Session::Session( Application& application,
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),
53
+ m_sendRedundantResendRequests( false ),
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 ),
61
+ m_millisecondsInTimeStamp( true ),
62
+ m_persistMessages( true ),
63
+ m_validateLengthAndChecksum( 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
+
75
+ if( !checkSessionTime(UtcTimeStamp()) )
76
+ reset();
77
+
78
+ addSession( *this );
79
+ m_application.onCreate( m_sessionID );
80
+ m_state.onEvent( "Created session" );
81
+ }
82
+
83
+ Session::~Session()
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
+
91
+ void Session::insertSendingTime( Header& header )
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_millisecondsInTimeStamp) );
101
+ }
102
+
103
+ void Session::insertOrigSendingTime( Header& header, const UtcTimeStamp& when )
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_millisecondsInTimeStamp) );
112
+ }
113
+
114
+ void 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
+
125
+ void Session::next()
126
+ {
127
+ next( UtcTimeStamp() );
128
+ }
129
+
130
+ void 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
+ {
155
+ generateLogon();
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
+ {
191
+ generateHeartbeat();
192
+ }
193
+ }
194
+ }
195
+ catch ( FIX::IOException& e )
196
+ {
197
+ m_state.onEvent( e.what() );
198
+ disconnect();
199
+ }
200
+ }
201
+
202
+ void 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" );
255
+ generateLogon( logon );
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
+ {
268
+ doTargetTooHigh( logon );
269
+ }
270
+ else
271
+ {
272
+ m_state.incrNextTargetMsgSeqNum();
273
+ nextQueued( timeStamp );
274
+ }
275
+
276
+ if ( isLoggedOn() )
277
+ m_application.onLogon( m_sessionID );
278
+ }
279
+
280
+ void Session::nextHeartbeat( const Message& heartbeat, const UtcTimeStamp& timeStamp )
281
+ {
282
+ if ( !verify( heartbeat ) ) return ;
283
+ m_state.incrNextTargetMsgSeqNum();
284
+ nextQueued( timeStamp );
285
+ }
286
+
287
+ void 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
+
295
+ void 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" );
301
+ generateLogout();
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
+
312
+ void 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
+
319
+ void 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: "
334
+ + IntConvertor::convert( getExpectedTargetNum() ) +
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
+
344
+ void 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
+ Message msg;
385
+
386
+ for ( i = messages.begin(); i != messages.end(); ++i )
387
+ {
388
+ const DataDictionary& sessionDD =
389
+ m_dataDictionaryProvider.getSessionDataDictionary(m_sessionID.getBeginString());
390
+
391
+ if( m_sessionID.isFIXT() )
392
+ {
393
+ msg.setStringHeader(*i);
394
+ ApplVerID applVerID;
395
+ if( !msg.getHeader().getFieldIfSet(applVerID) )
396
+ applVerID = m_senderDefaultApplVerID;
397
+
398
+ const DataDictionary& applicationDD =
399
+ m_dataDictionaryProvider.getApplicationDataDictionary(applVerID);
400
+ msg = Message( *i, sessionDD, applicationDD, m_validateLengthAndChecksum );
401
+ }
402
+ else
403
+ {
404
+ msg = Message( *i, sessionDD, m_validateLengthAndChecksum );
405
+ }
406
+
407
+
408
+ msg.getHeader().getField( msgSeqNum );
409
+ msg.getHeader().getField( msgType );
410
+
411
+ if( (current != msgSeqNum) && !begin )
412
+ begin = current;
413
+
414
+ if ( Message::isAdminMsgType( msgType ) )
415
+ {
416
+ if ( !begin ) begin = msgSeqNum;
417
+ }
418
+ else
419
+ {
420
+ if ( resend( msg ) )
421
+ {
422
+ if ( begin ) generateSequenceReset( begin, msgSeqNum );
423
+ send( msg.toString(messageString) );
424
+ m_state.onEvent( "Resending Message: "
425
+ + IntConvertor::convert( msgSeqNum ) );
426
+ begin = 0;
427
+ }
428
+ else
429
+ { if ( !begin ) begin = msgSeqNum; }
430
+ }
431
+ current = msgSeqNum + 1;
432
+ }
433
+ if ( begin )
434
+ {
435
+ generateSequenceReset( begin, msgSeqNum + 1 );
436
+ }
437
+
438
+ if ( endSeqNo > msgSeqNum )
439
+ {
440
+ endSeqNo = EndSeqNo(endSeqNo + 1);
441
+ int next = m_state.getNextSenderMsgSeqNum();
442
+ if( endSeqNo > next )
443
+ endSeqNo = EndSeqNo(next);
444
+ generateSequenceReset( beginSeqNo, endSeqNo );
445
+ }
446
+
447
+ resendRequest.getHeader().getField( msgSeqNum );
448
+ if( !isTargetTooHigh(msgSeqNum) && !isTargetTooLow(msgSeqNum) )
449
+ m_state.incrNextTargetMsgSeqNum();
450
+ }
451
+
452
+ bool Session::send( Message& message )
453
+ {
454
+ message.getHeader().removeField( FIELD::PossDupFlag );
455
+ message.getHeader().removeField( FIELD::OrigSendingTime );
456
+ return sendRaw( message );
457
+ }
458
+
459
+ bool Session::sendRaw( Message& message, int num )
460
+ {
461
+ Locker l( m_mutex );
462
+
463
+ try
464
+ {
465
+ Header& header = message.getHeader();
466
+
467
+ MsgType msgType;
468
+ header.getFieldIfSet(msgType);
469
+
470
+ fill( header );
471
+ std::string messageString;
472
+
473
+ if ( num )
474
+ header.setField( MsgSeqNum( num ) );
475
+
476
+ if ( Message::isAdminMsgType( msgType ) )
477
+ {
478
+ m_application.toAdmin( message, m_sessionID );
479
+
480
+ if( msgType == "A" && !m_state.receivedReset() )
481
+ {
482
+ ResetSeqNumFlag resetSeqNumFlag( false );
483
+ message.getFieldIfSet(resetSeqNumFlag);
484
+
485
+ if( resetSeqNumFlag )
486
+ {
487
+ m_state.reset();
488
+ message.getHeader().setField( MsgSeqNum(getExpectedSenderNum()) );
489
+ }
490
+ m_state.sentReset( resetSeqNumFlag );
491
+ }
492
+
493
+ message.toString( messageString );
494
+
495
+ if( !num )
496
+ persist( message, messageString );
497
+
498
+ if (
499
+ msgType == "A" || msgType == "5"
500
+ || msgType == "2" || msgType == "4"
501
+ || isLoggedOn() )
502
+ {
503
+ send( messageString );
504
+ }
505
+ }
506
+ else
507
+ {
508
+ // do not send application messages if they will just be cleared
509
+ if( !isLoggedOn() && shouldSendReset() )
510
+ return false;
511
+
512
+ try
513
+ {
514
+ m_application.toApp( message, m_sessionID );
515
+ message.toString( messageString );
516
+
517
+ if( !num )
518
+ persist( message, messageString );
519
+
520
+ if ( isLoggedOn() )
521
+ send( messageString );
522
+ }
523
+ catch ( DoNotSend& ) { return false; }
524
+ }
525
+
526
+ return true;
527
+ }
528
+ catch ( IOException& e )
529
+ {
530
+ m_state.onEvent( e.what() );
531
+ return false;
532
+ }
533
+ }
534
+
535
+ bool Session::send( const std::string& string )
536
+ {
537
+ if ( !m_pResponder ) return false;
538
+ m_state.onOutgoing( string );
539
+ return m_pResponder->send( string );
540
+ }
541
+
542
+ void Session::disconnect()
543
+ {
544
+ Locker l(m_mutex);
545
+
546
+ if ( m_pResponder )
547
+ {
548
+ m_state.onEvent( "Disconnecting" );
549
+
550
+ m_pResponder->disconnect();
551
+ m_pResponder = 0;
552
+ }
553
+
554
+ if ( m_state.receivedLogon() || m_state.sentLogon() )
555
+ {
556
+ m_state.receivedLogon( false );
557
+ m_state.sentLogon( false );
558
+ m_application.onLogout( m_sessionID );
559
+ }
560
+
561
+ m_state.sentLogout( false );
562
+ m_state.receivedReset( false );
563
+ m_state.sentReset( false );
564
+ m_state.clearQueue();
565
+ m_state.logoutReason();
566
+ if ( m_resetOnDisconnect )
567
+ m_state.reset();
568
+
569
+ m_state.resendRange( 0, 0 );
570
+ }
571
+
572
+ bool Session::resend( Message& message )
573
+ {
574
+ SendingTime sendingTime;
575
+ MsgSeqNum msgSeqNum;
576
+ Header& header = message.getHeader();
577
+ header.getField( sendingTime );
578
+ header.getField( msgSeqNum );
579
+ insertOrigSendingTime( header, sendingTime );
580
+ header.setField( PossDupFlag( true ) );
581
+ insertSendingTime( header );
582
+
583
+ try
584
+ {
585
+ m_application.toApp( message, m_sessionID );
586
+ return true;
587
+ }
588
+ catch ( DoNotSend& )
589
+ { return false; }
590
+ }
591
+
592
+ void Session::persist( const Message& message, const std::string& messageString )
593
+ throw ( IOException )
594
+ {
595
+ MsgSeqNum msgSeqNum;
596
+ message.getHeader().getField( msgSeqNum );
597
+ if( m_persistMessages )
598
+ m_state.set( msgSeqNum, messageString );
599
+ m_state.incrNextSenderMsgSeqNum();
600
+ }
601
+
602
+ void Session::generateLogon()
603
+ {
604
+ Message logon;
605
+ logon.getHeader().setField( MsgType( "A" ) );
606
+ logon.setField( EncryptMethod( 0 ) );
607
+ logon.setField( m_state.heartBtInt() );
608
+ if( m_sessionID.isFIXT() )
609
+ logon.setField( DefaultApplVerID(m_senderDefaultApplVerID) );
610
+ if( m_refreshOnLogon )
611
+ refresh();
612
+ if( m_resetOnLogon )
613
+ m_state.reset();
614
+ if( shouldSendReset() )
615
+ logon.setField( ResetSeqNumFlag(true) );
616
+
617
+ fill( logon.getHeader() );
618
+ UtcTimeStamp now;
619
+ m_state.lastReceivedTime( now );
620
+ m_state.testRequest( 0 );
621
+ m_state.sentLogon( true );
622
+ sendRaw( logon );
623
+ }
624
+
625
+ void Session::generateLogon( const Message& aLogon )
626
+ {
627
+ Message logon;
628
+ EncryptMethod encryptMethod;
629
+ HeartBtInt heartBtInt;
630
+ logon.setField( EncryptMethod( 0 ) );
631
+ if( m_sessionID.isFIXT() )
632
+ logon.setField( DefaultApplVerID(m_senderDefaultApplVerID) );
633
+ if( m_state.receivedReset() )
634
+ logon.setField( ResetSeqNumFlag(true) );
635
+ aLogon.getField( heartBtInt );
636
+ logon.getHeader().setField( MsgType( "A" ) );
637
+ logon.setField( heartBtInt );
638
+ fill( logon.getHeader() );
639
+ sendRaw( logon );
640
+ m_state.sentLogon( true );
641
+ }
642
+
643
+ void Session::generateResendRequest( const BeginString& beginString, const MsgSeqNum& msgSeqNum )
644
+ {
645
+ Message resendRequest;
646
+ BeginSeqNo beginSeqNo( ( int ) getExpectedTargetNum() );
647
+ EndSeqNo endSeqNo( msgSeqNum - 1 );
648
+ if ( beginString >= FIX::BeginString_FIX42 )
649
+ endSeqNo = 0;
650
+ else if( beginString <= FIX::BeginString_FIX41 )
651
+ endSeqNo = 999999;
652
+ resendRequest.getHeader().setField( MsgType( "2" ) );
653
+ resendRequest.setField( beginSeqNo );
654
+ resendRequest.setField( endSeqNo );
655
+ fill( resendRequest.getHeader() );
656
+ sendRaw( resendRequest );
657
+
658
+ m_state.onEvent( "Sent ResendRequest FROM: "
659
+ + IntConvertor::convert( beginSeqNo ) +
660
+ " TO: " + IntConvertor::convert( endSeqNo ) );
661
+
662
+ m_state.resendRange( beginSeqNo, msgSeqNum - 1 );
663
+ }
664
+
665
+ void Session::generateSequenceReset
666
+ ( int beginSeqNo, int endSeqNo )
667
+ {
668
+ Message sequenceReset;
669
+ NewSeqNo newSeqNo( endSeqNo );
670
+ sequenceReset.getHeader().setField( MsgType( "4" ) );
671
+ sequenceReset.getHeader().setField( PossDupFlag( true ) );
672
+ sequenceReset.setField( newSeqNo );
673
+ fill( sequenceReset.getHeader() );
674
+
675
+ SendingTime sendingTime;
676
+ sequenceReset.getHeader().getField( sendingTime );
677
+ insertOrigSendingTime( sequenceReset.getHeader(), sendingTime );
678
+ sequenceReset.getHeader().setField( MsgSeqNum( beginSeqNo ) );
679
+ sequenceReset.setField( GapFillFlag( true ) );
680
+ sendRaw( sequenceReset, beginSeqNo );
681
+ m_state.onEvent( "Sent SequenceReset TO: "
682
+ + IntConvertor::convert( newSeqNo ) );
683
+ }
684
+
685
+ void Session::generateHeartbeat()
686
+ {
687
+ Message heartbeat;
688
+ heartbeat.getHeader().setField( MsgType( "0" ) );
689
+ fill( heartbeat.getHeader() );
690
+ sendRaw( heartbeat );
691
+ }
692
+
693
+ void Session::generateHeartbeat( const Message& testRequest )
694
+ {
695
+ Message heartbeat;
696
+ heartbeat.getHeader().setField( MsgType( "0" ) );
697
+ fill( heartbeat.getHeader() );
698
+ try
699
+ {
700
+ TestReqID testReqID;
701
+ testRequest.getField( testReqID );
702
+ heartbeat.setField( testReqID );
703
+ }
704
+ catch ( FieldNotFound& ) {}
705
+
706
+ sendRaw( heartbeat );
707
+ }
708
+
709
+ void Session::generateTestRequest( const std::string& id )
710
+ {
711
+ Message testRequest;
712
+ testRequest.getHeader().setField( MsgType( "1" ) );
713
+ fill( testRequest.getHeader() );
714
+ TestReqID testReqID( id );
715
+ testRequest.setField( testReqID );
716
+
717
+ sendRaw( testRequest );
718
+ }
719
+
720
+ void Session::generateReject( const Message& message, int err, int field )
721
+ {
722
+ std::string beginString = m_sessionID.getBeginString();
723
+
724
+ Message reject;
725
+ reject.getHeader().setField( MsgType( "3" ) );
726
+ reject.reverseRoute( message.getHeader() );
727
+ fill( reject.getHeader() );
728
+
729
+ MsgSeqNum msgSeqNum;
730
+ MsgType msgType;
731
+
732
+ message.getHeader().getField( msgType );
733
+ if( message.getHeader().getFieldIfSet( msgSeqNum ) )
734
+ {
735
+ if( msgSeqNum.getString() != "" )
736
+ reject.setField( RefSeqNum( msgSeqNum ) );
737
+ }
738
+
739
+ if ( beginString >= FIX::BeginString_FIX42 )
740
+ {
741
+ if( msgType.getString() != "" )
742
+ reject.setField( RefMsgType( msgType ) );
743
+ if ( (beginString == FIX::BeginString_FIX42
744
+ && err <= SessionRejectReason_INVALID_MSGTYPE)
745
+ || beginString > FIX::BeginString_FIX42 )
746
+ {
747
+ reject.setField( SessionRejectReason( err ) );
748
+ }
749
+ }
750
+ if ( msgType != MsgType_Logon && msgType != MsgType_SequenceReset
751
+ && msgSeqNum == getExpectedTargetNum() )
752
+ { m_state.incrNextTargetMsgSeqNum(); }
753
+
754
+ const char* reason = 0;
755
+ switch ( err )
756
+ {
757
+ case SessionRejectReason_INVALID_TAG_NUMBER:
758
+ reason = SessionRejectReason_INVALID_TAG_NUMBER_TEXT;
759
+ break;
760
+ case SessionRejectReason_REQUIRED_TAG_MISSING:
761
+ reason = SessionRejectReason_REQUIRED_TAG_MISSING_TEXT;
762
+ break;
763
+ case SessionRejectReason_TAG_NOT_DEFINED_FOR_THIS_MESSAGE_TYPE:
764
+ reason = SessionRejectReason_TAG_NOT_DEFINED_FOR_THIS_MESSAGE_TYPE_TEXT;
765
+ break;
766
+ case SessionRejectReason_TAG_SPECIFIED_WITHOUT_A_VALUE:
767
+ reason = SessionRejectReason_TAG_SPECIFIED_WITHOUT_A_VALUE_TEXT;
768
+ break;
769
+ case SessionRejectReason_VALUE_IS_INCORRECT:
770
+ reason = SessionRejectReason_VALUE_IS_INCORRECT_TEXT;
771
+ break;
772
+ case SessionRejectReason_INCORRECT_DATA_FORMAT_FOR_VALUE:
773
+ reason = SessionRejectReason_INCORRECT_DATA_FORMAT_FOR_VALUE_TEXT;
774
+ break;
775
+ case SessionRejectReason_COMPID_PROBLEM:
776
+ reason = SessionRejectReason_COMPID_PROBLEM_TEXT;
777
+ break;
778
+ case SessionRejectReason_SENDINGTIME_ACCURACY_PROBLEM:
779
+ reason = SessionRejectReason_SENDINGTIME_ACCURACY_PROBLEM_TEXT;
780
+ break;
781
+ case SessionRejectReason_INVALID_MSGTYPE:
782
+ reason = SessionRejectReason_INVALID_MSGTYPE_TEXT;
783
+ break;
784
+ case SessionRejectReason_TAG_APPEARS_MORE_THAN_ONCE:
785
+ reason = SessionRejectReason_TAG_APPEARS_MORE_THAN_ONCE_TEXT;
786
+ break;
787
+ case SessionRejectReason_TAG_SPECIFIED_OUT_OF_REQUIRED_ORDER:
788
+ reason = SessionRejectReason_TAG_SPECIFIED_OUT_OF_REQUIRED_ORDER_TEXT;
789
+ break;
790
+ case SessionRejectReason_INCORRECT_NUMINGROUP_COUNT_FOR_REPEATING_GROUP:
791
+ reason = SessionRejectReason_INCORRECT_NUMINGROUP_COUNT_FOR_REPEATING_GROUP_TEXT;
792
+ };
793
+
794
+ if ( reason && ( field || err == SessionRejectReason_INVALID_TAG_NUMBER ) )
795
+ {
796
+ populateRejectReason( reject, field, reason );
797
+ m_state.onEvent( "Message " + msgSeqNum.getString() + " Rejected: "
798
+ + reason + ":" + IntConvertor::convert( field ) );
799
+ }
800
+ else if ( reason )
801
+ {
802
+ populateRejectReason( reject, reason );
803
+ m_state.onEvent( "Message " + msgSeqNum.getString()
804
+ + " Rejected: " + reason );
805
+ }
806
+ else
807
+ m_state.onEvent( "Message " + msgSeqNum.getString() + " Rejected" );
808
+
809
+ if ( !m_state.receivedLogon() )
810
+ throw std::runtime_error( "Tried to send a reject while not logged on" );
811
+
812
+ sendRaw( reject );
813
+ }
814
+
815
+ void Session::generateReject( const Message& message, const std::string& str )
816
+ {
817
+ std::string beginString = m_sessionID.getBeginString();
818
+
819
+ Message reject;
820
+ reject.getHeader().setField( MsgType( "3" ) );
821
+ reject.reverseRoute( message.getHeader() );
822
+ fill( reject.getHeader() );
823
+
824
+ MsgType msgType;
825
+ MsgSeqNum msgSeqNum;
826
+
827
+ message.getHeader().getField( msgType );
828
+ message.getHeader().getField( msgSeqNum );
829
+ if ( beginString >= FIX::BeginString_FIX42 )
830
+ reject.setField( RefMsgType( msgType ) );
831
+ reject.setField( RefSeqNum( msgSeqNum ) );
832
+
833
+ if ( msgType != MsgType_Logon && msgType != MsgType_SequenceReset )
834
+ m_state.incrNextTargetMsgSeqNum();
835
+
836
+ reject.setField( Text( str ) );
837
+ sendRaw( reject );
838
+ m_state.onEvent( "Message " + msgSeqNum.getString()
839
+ + " Rejected: " + str );
840
+ }
841
+
842
+ void Session::generateBusinessReject( const Message& message, int err, int field )
843
+ {
844
+ Message reject;
845
+ reject.getHeader().setField( MsgType( MsgType_BusinessMessageReject ) );
846
+ if( m_sessionID.isFIXT() )
847
+ reject.setField( DefaultApplVerID(m_senderDefaultApplVerID) );
848
+ fill( reject.getHeader() );
849
+ MsgType msgType;
850
+ MsgSeqNum msgSeqNum;
851
+ message.getHeader().getField( msgType );
852
+ message.getHeader().getField( msgSeqNum );
853
+ reject.setField( RefMsgType( msgType ) );
854
+ reject.setField( RefSeqNum( msgSeqNum ) );
855
+ reject.setField( BusinessRejectReason( err ) );
856
+ m_state.incrNextTargetMsgSeqNum();
857
+
858
+ const char* reason = 0;
859
+ switch ( err )
860
+ {
861
+ case BusinessRejectReason_OTHER:
862
+ reason = BusinessRejectReason_OTHER_TEXT;
863
+ break;
864
+ case BusinessRejectReason_UNKNOWN_ID:
865
+ reason = BusinessRejectReason_UNKNOWN_ID_TEXT;
866
+ break;
867
+ case BusinessRejectReason_UNKNOWN_SECURITY:
868
+ reason = BusinessRejectReason_UNKNOWN_SECURITY_TEXT;
869
+ break;
870
+ case BusinessRejectReason_UNKNOWN_MESSAGE_TYPE:
871
+ reason = BusinessRejectReason_UNSUPPORTED_MESSAGE_TYPE_TEXT;
872
+ break;
873
+ case BusinessRejectReason_APPLICATION_NOT_AVAILABLE:
874
+ reason = BusinessRejectReason_APPLICATION_NOT_AVAILABLE_TEXT;
875
+ break;
876
+ case BusinessRejectReason_CONDITIONALLY_REQUIRED_FIELD_MISSING:
877
+ reason = BusinessRejectReason_CONDITIONALLY_REQUIRED_FIELD_MISSING_TEXT;
878
+ break;
879
+ case BusinessRejectReason_NOT_AUTHORIZED:
880
+ reason = BusinessRejectReason_NOT_AUTHORIZED_TEXT;
881
+ break;
882
+ case BusinessRejectReason_DELIVERTO_FIRM_NOT_AVAILABLE_AT_THIS_TIME:
883
+ reason = BusinessRejectReason_DELIVERTO_FIRM_NOT_AVAILABLE_AT_THIS_TIME_TEXT;
884
+ break;
885
+ };
886
+
887
+ if ( reason && field )
888
+ {
889
+ populateRejectReason( reject, field, reason );
890
+ m_state.onEvent( "Message " + msgSeqNum.getString() + " Rejected: "
891
+ + reason + ":" + IntConvertor::convert( field ) );
892
+ }
893
+ else if ( reason )
894
+ {
895
+ populateRejectReason( reject, reason );
896
+ m_state.onEvent( "Message " + msgSeqNum.getString()
897
+ + " Rejected: " + reason );
898
+ }
899
+ else
900
+ m_state.onEvent( "Message " + msgSeqNum.getString() + " Rejected" );
901
+
902
+ sendRaw( reject );
903
+ }
904
+
905
+ void Session::generateLogout( const std::string& text )
906
+ {
907
+ Message logout;
908
+ logout.getHeader().setField( MsgType( MsgType_Logout ) );
909
+ fill( logout.getHeader() );
910
+ if ( text.length() )
911
+ logout.setField( Text( text ) );
912
+ sendRaw( logout );
913
+ m_state.sentLogout( true );
914
+ }
915
+
916
+ void Session::populateRejectReason( Message& reject, int field,
917
+ const std::string& text )
918
+ {
919
+ MsgType msgType;
920
+ reject.getHeader().getField( msgType );
921
+
922
+ if ( msgType == MsgType_Reject
923
+ && m_sessionID.getBeginString() >= FIX::BeginString_FIX42 )
924
+ {
925
+ reject.setField( RefTagID( field ) );
926
+ reject.setField( Text( text ) );
927
+ }
928
+ else
929
+ {
930
+ std::stringstream stream;
931
+ stream << text << " (" << field << ")";
932
+ reject.setField( Text( stream.str() ) );
933
+ }
934
+ }
935
+
936
+ void Session::populateRejectReason( Message& reject, const std::string& text )
937
+ {
938
+ reject.setField( Text( text ) );
939
+ }
940
+
941
+ bool Session::verify( const Message& msg, bool checkTooHigh,
942
+ bool checkTooLow )
943
+ {
944
+ const MsgType* pMsgType = 0;
945
+ const MsgSeqNum* pMsgSeqNum = 0;
946
+
947
+ try
948
+ {
949
+ const Header& header = msg.getHeader();
950
+
951
+ pMsgType = FIELD_GET_PTR( header, MsgType );
952
+ const SenderCompID& senderCompID = FIELD_GET_REF( header, SenderCompID );
953
+ const TargetCompID& targetCompID = FIELD_GET_REF( header, TargetCompID );
954
+ const SendingTime& sendingTime = FIELD_GET_REF( header, SendingTime );
955
+
956
+ if( checkTooHigh || checkTooLow )
957
+ pMsgSeqNum = FIELD_GET_PTR( header, MsgSeqNum );
958
+
959
+ if ( !validLogonState( *pMsgType ) )
960
+ throw std::logic_error( "Logon state is not valid for message" );
961
+
962
+ if ( !isGoodTime( sendingTime ) )
963
+ {
964
+ doBadTime( msg );
965
+ return false;
966
+ }
967
+ if ( !isCorrectCompID( senderCompID, targetCompID ) )
968
+ {
969
+ doBadCompID( msg );
970
+ return false;
971
+ }
972
+
973
+ if ( checkTooHigh && isTargetTooHigh( *pMsgSeqNum ) )
974
+ {
975
+ doTargetTooHigh( msg );
976
+ return false;
977
+ }
978
+ else if ( checkTooLow && isTargetTooLow( *pMsgSeqNum ) )
979
+ {
980
+ doTargetTooLow( msg );
981
+ return false;
982
+ }
983
+
984
+ if ( (checkTooHigh || checkTooLow) && m_state.resendRequested() )
985
+ {
986
+ SessionState::ResendRange range = m_state.resendRange();
987
+
988
+ if ( *pMsgSeqNum >= range.second )
989
+ {
990
+ m_state.onEvent ("ResendRequest for messages FROM: " +
991
+ IntConvertor::convert (range.first) + " TO: " +
992
+ IntConvertor::convert (range.second) +
993
+ " has been satisfied.");
994
+ m_state.resendRange (0, 0);
995
+ }
996
+ }
997
+ }
998
+ catch ( std::exception& e )
999
+ {
1000
+ m_state.onEvent( e.what() );
1001
+ disconnect();
1002
+ return false;
1003
+ }
1004
+
1005
+ UtcTimeStamp now;
1006
+ m_state.lastReceivedTime( now );
1007
+ m_state.testRequest( 0 );
1008
+
1009
+ fromCallback( pMsgType ? *pMsgType : MsgType(), msg, m_sessionID );
1010
+ return true;
1011
+ }
1012
+
1013
+ bool Session::shouldSendReset()
1014
+ {
1015
+ std::string beginString = m_sessionID.getBeginString();
1016
+ return beginString >= FIX::BeginString_FIX41
1017
+ && ( m_resetOnLogon ||
1018
+ m_resetOnLogout ||
1019
+ m_resetOnDisconnect )
1020
+ && ( getExpectedSenderNum() == 1 )
1021
+ && ( getExpectedTargetNum() == 1 );
1022
+ }
1023
+
1024
+ bool Session::validLogonState( const MsgType& msgType )
1025
+ {
1026
+ if ( (msgType == MsgType_Logon && m_state.sentReset())
1027
+ || (m_state.receivedReset()) )
1028
+ return true;
1029
+ if ( (msgType == MsgType_Logon && !m_state.receivedLogon())
1030
+ || (msgType != MsgType_Logon && m_state.receivedLogon()) )
1031
+ return true;
1032
+ if ( msgType == MsgType_Logout && m_state.sentLogon() )
1033
+ return true;
1034
+ if ( msgType != MsgType_Logout && m_state.sentLogout() )
1035
+ return true;
1036
+ if ( msgType == MsgType_SequenceReset )
1037
+ return true;
1038
+ if ( msgType == MsgType_Reject )
1039
+ return true;
1040
+
1041
+ return false;
1042
+ }
1043
+
1044
+ void Session::fromCallback( const MsgType& msgType, const Message& msg,
1045
+ const SessionID& sessionID )
1046
+ {
1047
+ if ( Message::isAdminMsgType( msgType ) )
1048
+ m_application.fromAdmin( msg, m_sessionID );
1049
+ else
1050
+ m_application.fromApp( msg, m_sessionID );
1051
+ }
1052
+
1053
+ void Session::doBadTime( const Message& msg )
1054
+ {
1055
+ generateReject( msg, SessionRejectReason_SENDINGTIME_ACCURACY_PROBLEM );
1056
+ generateLogout();
1057
+ }
1058
+
1059
+ void Session::doBadCompID( const Message& msg )
1060
+ {
1061
+ generateReject( msg, SessionRejectReason_COMPID_PROBLEM );
1062
+ generateLogout();
1063
+ }
1064
+
1065
+ bool Session::doPossDup( const Message& msg )
1066
+ {
1067
+ const Header & header = msg.getHeader();
1068
+ OrigSendingTime origSendingTime;
1069
+ SendingTime sendingTime;
1070
+ MsgType msgType;
1071
+
1072
+ header.getField( msgType );
1073
+ header.getField( sendingTime );
1074
+
1075
+ if ( msgType != MsgType_SequenceReset )
1076
+ {
1077
+ if ( !header.getFieldIfSet( origSendingTime ) )
1078
+ {
1079
+ generateReject( msg, SessionRejectReason_REQUIRED_TAG_MISSING, origSendingTime.getField() );
1080
+ return false;
1081
+ }
1082
+
1083
+ if ( origSendingTime > sendingTime )
1084
+ {
1085
+ generateReject( msg, SessionRejectReason_SENDINGTIME_ACCURACY_PROBLEM );
1086
+ generateLogout();
1087
+ return false;
1088
+ }
1089
+ }
1090
+ return true;
1091
+ }
1092
+
1093
+ bool Session::doTargetTooLow( const Message& msg )
1094
+ {
1095
+ const Header & header = msg.getHeader();
1096
+ PossDupFlag possDupFlag(false);
1097
+ MsgSeqNum msgSeqNum;
1098
+ header.getFieldIfSet(possDupFlag);
1099
+ header.getField( msgSeqNum );
1100
+
1101
+ if ( !possDupFlag )
1102
+ {
1103
+ std::stringstream stream;
1104
+ stream << "MsgSeqNum too low, expecting " << getExpectedTargetNum()
1105
+ << " but received " << msgSeqNum;
1106
+ generateLogout( stream.str() );
1107
+ throw std::logic_error( stream.str() );
1108
+ }
1109
+
1110
+ return doPossDup( msg );
1111
+ }
1112
+
1113
+ void Session::doTargetTooHigh( const Message& msg )
1114
+ {
1115
+ const Header & header = msg.getHeader();
1116
+ BeginString beginString;
1117
+ MsgSeqNum msgSeqNum;
1118
+ header.getField( beginString );
1119
+ header.getField( msgSeqNum );
1120
+
1121
+ m_state.onEvent( "MsgSeqNum too high, expecting "
1122
+ + IntConvertor::convert( getExpectedTargetNum() )
1123
+ + " but received "
1124
+ + IntConvertor::convert( msgSeqNum ) );
1125
+
1126
+ m_state.queue( msgSeqNum, msg );
1127
+
1128
+ if( m_state.resendRequested() )
1129
+ {
1130
+ SessionState::ResendRange range = m_state.resendRange();
1131
+
1132
+ if( !m_sendRedundantResendRequests && msgSeqNum >= range.first )
1133
+ {
1134
+ m_state.onEvent ("Already sent ResendRequest FROM: " +
1135
+ IntConvertor::convert (range.first) + " TO: " +
1136
+ IntConvertor::convert (range.second) +
1137
+ ". Not sending another.");
1138
+ return;
1139
+ }
1140
+ }
1141
+
1142
+ generateResendRequest( beginString, msgSeqNum );
1143
+ }
1144
+
1145
+ void Session::nextQueued( const UtcTimeStamp& timeStamp )
1146
+ {
1147
+ while ( nextQueued( getExpectedTargetNum(), timeStamp ) ) {}
1148
+ }
1149
+
1150
+ bool Session::nextQueued( int num, const UtcTimeStamp& timeStamp )
1151
+ {
1152
+ Message msg;
1153
+ MsgType msgType;
1154
+
1155
+ if( m_state.retrieve( num, msg ) )
1156
+ {
1157
+ m_state.onEvent( "Processing QUEUED message: "
1158
+ + IntConvertor::convert( num ) );
1159
+ msg.getHeader().getField( msgType );
1160
+ if( msgType == MsgType_Logon
1161
+ || msgType == MsgType_ResendRequest )
1162
+ {
1163
+ m_state.incrNextTargetMsgSeqNum();
1164
+ }
1165
+ else
1166
+ {
1167
+ next( msg, timeStamp, true );
1168
+ }
1169
+ return true;
1170
+ }
1171
+ return false;
1172
+ }
1173
+
1174
+ void Session::next( const std::string& msg, const UtcTimeStamp& timeStamp, bool queued )
1175
+ {
1176
+ try
1177
+ {
1178
+ m_state.onIncoming( msg );
1179
+ const DataDictionary& sessionDD =
1180
+ m_dataDictionaryProvider.getSessionDataDictionary(m_sessionID.getBeginString());
1181
+ if( m_sessionID.isFIXT() )
1182
+ {
1183
+ const DataDictionary& applicationDD =
1184
+ m_dataDictionaryProvider.getApplicationDataDictionary(m_senderDefaultApplVerID);
1185
+ next( Message( msg, sessionDD, applicationDD, m_validateLengthAndChecksum ), timeStamp, queued );
1186
+ }
1187
+ else
1188
+ {
1189
+ next( Message( msg, sessionDD, m_validateLengthAndChecksum ), timeStamp, queued );
1190
+ }
1191
+ }
1192
+ catch( InvalidMessage& e )
1193
+ {
1194
+ m_state.onEvent( e.what() );
1195
+
1196
+ try
1197
+ {
1198
+ if( identifyType(msg) == MsgType_Logon )
1199
+ {
1200
+ m_state.onEvent( "Logon message is not valid" );
1201
+ disconnect();
1202
+ }
1203
+ } catch( MessageParseError& ) {}
1204
+ throw e;
1205
+ }
1206
+ }
1207
+
1208
+ void Session::next( const Message& message, const UtcTimeStamp& timeStamp, bool queued )
1209
+ {
1210
+ const Header& header = message.getHeader();
1211
+
1212
+ try
1213
+ {
1214
+ if ( !checkSessionTime(timeStamp) )
1215
+ { reset(); return; }
1216
+
1217
+ const MsgType& msgType = FIELD_GET_REF( header, MsgType );
1218
+ const BeginString& beginString = FIELD_GET_REF( header, BeginString );
1219
+ // make sure these fields are present
1220
+ FIELD_THROW_IF_NOT_FOUND( header, SenderCompID );
1221
+ FIELD_THROW_IF_NOT_FOUND( header, TargetCompID );
1222
+
1223
+ if ( beginString != m_sessionID.getBeginString() )
1224
+ throw UnsupportedVersion();
1225
+
1226
+ if( msgType == MsgType_Logon )
1227
+ {
1228
+ if( m_sessionID.isFIXT() )
1229
+ {
1230
+ const DefaultApplVerID& applVerID = FIELD_GET_REF( message, DefaultApplVerID );
1231
+ setTargetDefaultApplVerID(applVerID);
1232
+ }
1233
+ else
1234
+ {
1235
+ setTargetDefaultApplVerID(Message::toApplVerID(beginString));
1236
+ }
1237
+ }
1238
+
1239
+ const DataDictionary& sessionDataDictionary =
1240
+ m_dataDictionaryProvider.getSessionDataDictionary(m_sessionID.getBeginString());
1241
+
1242
+ if( m_sessionID.isFIXT() && message.isApp() )
1243
+ {
1244
+ ApplVerID applVerID = m_targetDefaultApplVerID;
1245
+ header.getFieldIfSet(applVerID);
1246
+ const DataDictionary& applicationDataDictionary =
1247
+ m_dataDictionaryProvider.getApplicationDataDictionary(applVerID);
1248
+ DataDictionary::validate( message, &sessionDataDictionary, &applicationDataDictionary );
1249
+ }
1250
+ else
1251
+ {
1252
+ sessionDataDictionary.validate( message );
1253
+ }
1254
+
1255
+ if ( msgType == MsgType_Logon )
1256
+ nextLogon( message, timeStamp );
1257
+ else if ( msgType == MsgType_Heartbeat )
1258
+ nextHeartbeat( message, timeStamp );
1259
+ else if ( msgType == MsgType_TestRequest )
1260
+ nextTestRequest( message, timeStamp );
1261
+ else if ( msgType == MsgType_SequenceReset )
1262
+ nextSequenceReset( message, timeStamp );
1263
+ else if ( msgType == MsgType_Logout )
1264
+ nextLogout( message, timeStamp );
1265
+ else if ( msgType == MsgType_ResendRequest )
1266
+ nextResendRequest( message,timeStamp );
1267
+ else if ( msgType == MsgType_Reject )
1268
+ nextReject( message, timeStamp );
1269
+ else
1270
+ {
1271
+ if ( !verify( message ) ) return ;
1272
+ m_state.incrNextTargetMsgSeqNum();
1273
+ }
1274
+ }
1275
+ catch ( MessageParseError& e )
1276
+ { m_state.onEvent( e.what() ); }
1277
+ catch ( RequiredTagMissing & e )
1278
+ { LOGEX( generateReject( message, SessionRejectReason_REQUIRED_TAG_MISSING, e.field ) ); }
1279
+ catch ( FieldNotFound & e )
1280
+ {
1281
+ if( header.getField(FIELD::BeginString) >= FIX::BeginString_FIX42 && message.isApp() )
1282
+ {
1283
+ LOGEX( generateBusinessReject( message, BusinessRejectReason_CONDITIONALLY_REQUIRED_FIELD_MISSING, e.field ) );
1284
+ }
1285
+ else
1286
+ {
1287
+ LOGEX( generateReject( message, SessionRejectReason_REQUIRED_TAG_MISSING, e.field ) );
1288
+ if ( header.getField(FIELD::MsgType) == MsgType_Logon )
1289
+ {
1290
+ m_state.onEvent( "Required field missing from logon" );
1291
+ disconnect();
1292
+ }
1293
+ }
1294
+ }
1295
+ catch ( InvalidTagNumber & e )
1296
+ { LOGEX( generateReject( message, SessionRejectReason_INVALID_TAG_NUMBER, e.field ) ); }
1297
+ catch ( NoTagValue & e )
1298
+ { LOGEX( generateReject( message, SessionRejectReason_TAG_SPECIFIED_WITHOUT_A_VALUE, e.field ) ); }
1299
+ catch ( TagNotDefinedForMessage & e )
1300
+ { LOGEX( generateReject( message, SessionRejectReason_TAG_NOT_DEFINED_FOR_THIS_MESSAGE_TYPE, e.field ) ); }
1301
+ catch ( InvalidMessageType& )
1302
+ { LOGEX( generateReject( message, SessionRejectReason_INVALID_MSGTYPE ) ); }
1303
+ catch ( UnsupportedMessageType& )
1304
+ {
1305
+ if ( header.getField(FIELD::BeginString) >= FIX::BeginString_FIX42 )
1306
+ { LOGEX( generateBusinessReject( message, BusinessRejectReason_UNKNOWN_MESSAGE_TYPE ) ); }
1307
+ else
1308
+ { LOGEX( generateReject( message, "Unsupported message type" ) ); }
1309
+ }
1310
+ catch ( TagOutOfOrder & e )
1311
+ { LOGEX( generateReject( message, SessionRejectReason_TAG_SPECIFIED_OUT_OF_REQUIRED_ORDER, e.field ) ); }
1312
+ catch ( IncorrectDataFormat & e )
1313
+ { LOGEX( generateReject( message, SessionRejectReason_INCORRECT_DATA_FORMAT_FOR_VALUE, e.field ) ); }
1314
+ catch ( IncorrectTagValue & e )
1315
+ { LOGEX( generateReject( message, SessionRejectReason_VALUE_IS_INCORRECT, e.field ) ); }
1316
+ catch ( RepeatedTag & e )
1317
+ { LOGEX( generateReject( message, SessionRejectReason_TAG_APPEARS_MORE_THAN_ONCE, e.field ) ); }
1318
+ catch ( RepeatingGroupCountMismatch & e )
1319
+ { LOGEX( generateReject( message, SessionRejectReason_INCORRECT_NUMINGROUP_COUNT_FOR_REPEATING_GROUP, e.field ) ); }
1320
+ catch ( InvalidMessage& e )
1321
+ { m_state.onEvent( e.what() ); }
1322
+ catch ( RejectLogon& e )
1323
+ {
1324
+ m_state.onEvent( e.what() );
1325
+ generateLogout( e.what() );
1326
+ disconnect();
1327
+ }
1328
+ catch ( UnsupportedVersion& )
1329
+ {
1330
+ if ( header.getField(FIELD::MsgType) == MsgType_Logout )
1331
+ nextLogout( message, timeStamp );
1332
+ else
1333
+ {
1334
+ generateLogout( "Incorrect BeginString" );
1335
+ m_state.incrNextTargetMsgSeqNum();
1336
+ }
1337
+ }
1338
+ catch ( IOException& e )
1339
+ {
1340
+ m_state.onEvent( e.what() );
1341
+ disconnect();
1342
+ }
1343
+
1344
+ if( !queued )
1345
+ nextQueued( timeStamp );
1346
+
1347
+ if( isLoggedOn() )
1348
+ next();
1349
+ }
1350
+
1351
+ bool Session::sendToTarget( Message& message, const std::string& qualifier )
1352
+ throw( SessionNotFound )
1353
+ {
1354
+ try
1355
+ {
1356
+ SessionID sessionID = message.getSessionID( qualifier );
1357
+ return sendToTarget( message, sessionID );
1358
+ }
1359
+ catch ( FieldNotFound& ) { throw SessionNotFound(); }
1360
+ }
1361
+
1362
+ bool Session::sendToTarget( Message& message, const SessionID& sessionID )
1363
+ throw( SessionNotFound )
1364
+ {
1365
+ message.setSessionID( sessionID );
1366
+ Session* pSession = lookupSession( sessionID );
1367
+ if ( !pSession ) throw SessionNotFound();
1368
+ return pSession->send( message );
1369
+ }
1370
+
1371
+ bool Session::sendToTarget
1372
+ ( Message& message,
1373
+ const SenderCompID& senderCompID,
1374
+ const TargetCompID& targetCompID,
1375
+ const std::string& qualifier )
1376
+ throw( SessionNotFound )
1377
+ {
1378
+ message.getHeader().setField( senderCompID );
1379
+ message.getHeader().setField( targetCompID );
1380
+ return sendToTarget( message, qualifier );
1381
+ }
1382
+
1383
+ bool Session::sendToTarget
1384
+ ( Message& message, const std::string& sender, const std::string& target,
1385
+ const std::string& qualifier )
1386
+ throw( SessionNotFound )
1387
+ {
1388
+ return sendToTarget( message, SenderCompID( sender ),
1389
+ TargetCompID( target ), qualifier );
1390
+ }
1391
+
1392
+ std::set<SessionID> Session::getSessions()
1393
+ {
1394
+ return s_sessionIDs;
1395
+ }
1396
+
1397
+ bool Session::doesSessionExist( const SessionID& sessionID )
1398
+ {
1399
+ Locker locker( s_mutex );
1400
+ return s_sessions.end() != s_sessions.find( sessionID );
1401
+ }
1402
+
1403
+ Session* Session::lookupSession( const SessionID& sessionID )
1404
+ {
1405
+ Locker locker( s_mutex );
1406
+ Sessions::iterator find = s_sessions.find( sessionID );
1407
+ if ( find != s_sessions.end() )
1408
+ return find->second;
1409
+ else
1410
+ return 0;
1411
+ }
1412
+
1413
+ Session* Session::lookupSession( const std::string& string, bool reverse )
1414
+ {
1415
+ Message message;
1416
+ if ( !message.setStringHeader( string ) )
1417
+ return 0;
1418
+
1419
+ try
1420
+ {
1421
+ const Header& header = message.getHeader();
1422
+ const BeginString& beginString = FIELD_GET_REF( header, BeginString );
1423
+ const SenderCompID& senderCompID = FIELD_GET_REF( header, SenderCompID );
1424
+ const TargetCompID& targetCompID = FIELD_GET_REF( header, TargetCompID );
1425
+
1426
+ if ( reverse )
1427
+ {
1428
+ return lookupSession( SessionID( beginString, SenderCompID( targetCompID ),
1429
+ TargetCompID( senderCompID ) ) );
1430
+ }
1431
+
1432
+ return lookupSession( SessionID( beginString, senderCompID,
1433
+ targetCompID ) );
1434
+ }
1435
+ catch ( FieldNotFound& ) { return 0; }
1436
+ }
1437
+
1438
+ bool Session::isSessionRegistered( const SessionID& sessionID )
1439
+ {
1440
+ Locker locker( s_mutex );
1441
+ return s_registered.end() != s_registered.find( sessionID );
1442
+ }
1443
+
1444
+ Session* Session::registerSession( const SessionID& sessionID )
1445
+ {
1446
+ Locker locker( s_mutex );
1447
+ Session* pSession = lookupSession( sessionID );
1448
+ if ( pSession == 0 ) return 0;
1449
+ if ( isSessionRegistered( sessionID ) ) return 0;
1450
+ s_registered[ sessionID ] = pSession;
1451
+ return pSession;
1452
+ }
1453
+
1454
+ void Session::unregisterSession( const SessionID& sessionID )
1455
+ {
1456
+ Locker locker( s_mutex );
1457
+ s_registered.erase( sessionID );
1458
+ }
1459
+
1460
+ size_t Session::numSessions()
1461
+ {
1462
+ Locker locker( s_mutex );
1463
+ return s_sessions.size();
1464
+ }
1465
+
1466
+ bool Session::addSession( Session& s )
1467
+ {
1468
+ Locker locker( s_mutex );
1469
+ Sessions::iterator it = s_sessions.find( s.m_sessionID );
1470
+ if ( it == s_sessions.end() )
1471
+ {
1472
+ s_sessions[ s.m_sessionID ] = &s;
1473
+ s_sessionIDs.insert( s.m_sessionID );
1474
+ return true;
1475
+ }
1476
+ else
1477
+ return false;
1478
+ }
1479
+
1480
+ void Session::removeSession( Session& s )
1481
+ {
1482
+ Locker locker( s_mutex );
1483
+ s_sessions.erase( s.m_sessionID );
1484
+ s_sessionIDs.erase( s.m_sessionID );
1485
+ s_registered.erase( s.m_sessionID );
1486
+ }
1487
+ }