quickfix_ruby_ud 2.0.7-aarch64-linux

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (205) hide show
  1. checksums.yaml +7 -0
  2. data/ext/quickfix/Acceptor.cpp +257 -0
  3. data/ext/quickfix/Acceptor.h +127 -0
  4. data/ext/quickfix/Allocator.h +9 -0
  5. data/ext/quickfix/Application.h +137 -0
  6. data/ext/quickfix/DOMDocument.h +70 -0
  7. data/ext/quickfix/DataDictionary.cpp +679 -0
  8. data/ext/quickfix/DataDictionary.h +607 -0
  9. data/ext/quickfix/DataDictionaryProvider.cpp +66 -0
  10. data/ext/quickfix/DataDictionaryProvider.h +67 -0
  11. data/ext/quickfix/DatabaseConnectionID.h +98 -0
  12. data/ext/quickfix/DatabaseConnectionPool.h +84 -0
  13. data/ext/quickfix/Dictionary.cpp +157 -0
  14. data/ext/quickfix/Dictionary.h +89 -0
  15. data/ext/quickfix/Event.h +89 -0
  16. data/ext/quickfix/Except.h +39 -0
  17. data/ext/quickfix/Exceptions.h +257 -0
  18. data/ext/quickfix/Field.h +654 -0
  19. data/ext/quickfix/FieldConvertors.cpp +86 -0
  20. data/ext/quickfix/FieldConvertors.h +800 -0
  21. data/ext/quickfix/FieldMap.cpp +254 -0
  22. data/ext/quickfix/FieldMap.h +327 -0
  23. data/ext/quickfix/FieldNumbers.h +44 -0
  24. data/ext/quickfix/FieldTypes.cpp +62 -0
  25. data/ext/quickfix/FieldTypes.h +817 -0
  26. data/ext/quickfix/Fields.h +30 -0
  27. data/ext/quickfix/FileLog.cpp +176 -0
  28. data/ext/quickfix/FileLog.h +110 -0
  29. data/ext/quickfix/FileStore.cpp +369 -0
  30. data/ext/quickfix/FileStore.h +131 -0
  31. data/ext/quickfix/FixCommonFields.h +13 -0
  32. data/ext/quickfix/FixFieldNumbers.h +6132 -0
  33. data/ext/quickfix/FixFields.h +6133 -0
  34. data/ext/quickfix/FixValues.h +5790 -0
  35. data/ext/quickfix/Group.cpp +44 -0
  36. data/ext/quickfix/Group.h +78 -0
  37. data/ext/quickfix/HostDetailsProvider.cpp +79 -0
  38. data/ext/quickfix/HostDetailsProvider.h +44 -0
  39. data/ext/quickfix/HtmlBuilder.h +178 -0
  40. data/ext/quickfix/HttpConnection.cpp +914 -0
  41. data/ext/quickfix/HttpConnection.h +74 -0
  42. data/ext/quickfix/HttpMessage.cpp +229 -0
  43. data/ext/quickfix/HttpMessage.h +112 -0
  44. data/ext/quickfix/HttpParser.cpp +49 -0
  45. data/ext/quickfix/HttpParser.h +49 -0
  46. data/ext/quickfix/HttpServer.cpp +152 -0
  47. data/ext/quickfix/HttpServer.h +76 -0
  48. data/ext/quickfix/Initiator.cpp +310 -0
  49. data/ext/quickfix/Initiator.h +151 -0
  50. data/ext/quickfix/Log.cpp +71 -0
  51. data/ext/quickfix/Log.h +254 -0
  52. data/ext/quickfix/Message.cpp +617 -0
  53. data/ext/quickfix/Message.h +419 -0
  54. data/ext/quickfix/MessageCracker.h +171 -0
  55. data/ext/quickfix/MessageSorters.cpp +101 -0
  56. data/ext/quickfix/MessageSorters.h +185 -0
  57. data/ext/quickfix/MessageStore.cpp +182 -0
  58. data/ext/quickfix/MessageStore.h +164 -0
  59. data/ext/quickfix/Mutex.h +120 -0
  60. data/ext/quickfix/MySQLConnection.h +187 -0
  61. data/ext/quickfix/MySQLLog.cpp +262 -0
  62. data/ext/quickfix/MySQLLog.h +158 -0
  63. data/ext/quickfix/MySQLStore.cpp +323 -0
  64. data/ext/quickfix/MySQLStore.h +161 -0
  65. data/ext/quickfix/MySQLStubs.h +203 -0
  66. data/ext/quickfix/NullStore.cpp +40 -0
  67. data/ext/quickfix/NullStore.h +89 -0
  68. data/ext/quickfix/OdbcConnection.h +241 -0
  69. data/ext/quickfix/OdbcLog.cpp +230 -0
  70. data/ext/quickfix/OdbcLog.h +109 -0
  71. data/ext/quickfix/OdbcStore.cpp +313 -0
  72. data/ext/quickfix/OdbcStore.h +124 -0
  73. data/ext/quickfix/PUGIXML_DOMDocument.cpp +112 -0
  74. data/ext/quickfix/PUGIXML_DOMDocument.h +81 -0
  75. data/ext/quickfix/Parser.cpp +111 -0
  76. data/ext/quickfix/Parser.h +50 -0
  77. data/ext/quickfix/PostgreSQLConnection.h +163 -0
  78. data/ext/quickfix/PostgreSQLLog.cpp +263 -0
  79. data/ext/quickfix/PostgreSQLLog.h +157 -0
  80. data/ext/quickfix/PostgreSQLStore.cpp +327 -0
  81. data/ext/quickfix/PostgreSQLStore.h +160 -0
  82. data/ext/quickfix/PostgreSQLStubs.h +203 -0
  83. data/ext/quickfix/Queue.h +66 -0
  84. data/ext/quickfix/QuickfixRuby.cpp +131900 -0
  85. data/ext/quickfix/QuickfixRuby.h +56 -0
  86. data/ext/quickfix/Responder.h +41 -0
  87. data/ext/quickfix/SSLSocketAcceptor.cpp +409 -0
  88. data/ext/quickfix/SSLSocketAcceptor.h +186 -0
  89. data/ext/quickfix/SSLSocketConnection.cpp +434 -0
  90. data/ext/quickfix/SSLSocketConnection.h +221 -0
  91. data/ext/quickfix/SSLSocketInitiator.cpp +558 -0
  92. data/ext/quickfix/SSLSocketInitiator.h +203 -0
  93. data/ext/quickfix/SSLStubs.h +129 -0
  94. data/ext/quickfix/Session.cpp +1437 -0
  95. data/ext/quickfix/Session.h +343 -0
  96. data/ext/quickfix/SessionFactory.cpp +314 -0
  97. data/ext/quickfix/SessionFactory.h +84 -0
  98. data/ext/quickfix/SessionID.h +136 -0
  99. data/ext/quickfix/SessionSettings.cpp +165 -0
  100. data/ext/quickfix/SessionSettings.h +283 -0
  101. data/ext/quickfix/SessionState.h +260 -0
  102. data/ext/quickfix/Settings.cpp +160 -0
  103. data/ext/quickfix/Settings.h +56 -0
  104. data/ext/quickfix/SharedArray.h +274 -0
  105. data/ext/quickfix/SocketAcceptor.cpp +216 -0
  106. data/ext/quickfix/SocketAcceptor.h +77 -0
  107. data/ext/quickfix/SocketConnection.cpp +256 -0
  108. data/ext/quickfix/SocketConnection.h +102 -0
  109. data/ext/quickfix/SocketConnector.cpp +112 -0
  110. data/ext/quickfix/SocketConnector.h +76 -0
  111. data/ext/quickfix/SocketInitiator.cpp +241 -0
  112. data/ext/quickfix/SocketInitiator.h +76 -0
  113. data/ext/quickfix/SocketMonitor.h +26 -0
  114. data/ext/quickfix/SocketMonitor_UNIX.cpp +238 -0
  115. data/ext/quickfix/SocketMonitor_UNIX.h +101 -0
  116. data/ext/quickfix/SocketMonitor_WIN32.cpp +248 -0
  117. data/ext/quickfix/SocketMonitor_WIN32.h +99 -0
  118. data/ext/quickfix/SocketServer.cpp +163 -0
  119. data/ext/quickfix/SocketServer.h +100 -0
  120. data/ext/quickfix/ThreadedSSLSocketAcceptor.cpp +436 -0
  121. data/ext/quickfix/ThreadedSSLSocketAcceptor.h +209 -0
  122. data/ext/quickfix/ThreadedSSLSocketConnection.cpp +364 -0
  123. data/ext/quickfix/ThreadedSSLSocketConnection.h +191 -0
  124. data/ext/quickfix/ThreadedSSLSocketInitiator.cpp +434 -0
  125. data/ext/quickfix/ThreadedSSLSocketInitiator.h +193 -0
  126. data/ext/quickfix/ThreadedSocketAcceptor.cpp +242 -0
  127. data/ext/quickfix/ThreadedSocketAcceptor.h +95 -0
  128. data/ext/quickfix/ThreadedSocketConnection.cpp +227 -0
  129. data/ext/quickfix/ThreadedSocketConnection.h +89 -0
  130. data/ext/quickfix/ThreadedSocketInitiator.cpp +238 -0
  131. data/ext/quickfix/ThreadedSocketInitiator.h +78 -0
  132. data/ext/quickfix/TimeRange.cpp +227 -0
  133. data/ext/quickfix/TimeRange.h +215 -0
  134. data/ext/quickfix/Utility.cpp +639 -0
  135. data/ext/quickfix/Utility.h +255 -0
  136. data/ext/quickfix/UtilitySSL.cpp +1612 -0
  137. data/ext/quickfix/UtilitySSL.h +274 -0
  138. data/ext/quickfix/Values.h +63 -0
  139. data/ext/quickfix/config-all.h +10 -0
  140. data/ext/quickfix/config.h +10 -0
  141. data/ext/quickfix/config_unix.h +178 -0
  142. data/ext/quickfix/config_windows.h +0 -0
  143. data/ext/quickfix/dirent_windows.h +838 -0
  144. data/ext/quickfix/double-conversion/bignum-dtoa.cc +641 -0
  145. data/ext/quickfix/double-conversion/bignum-dtoa.h +84 -0
  146. data/ext/quickfix/double-conversion/bignum.cc +766 -0
  147. data/ext/quickfix/double-conversion/bignum.h +144 -0
  148. data/ext/quickfix/double-conversion/cached-powers.cc +176 -0
  149. data/ext/quickfix/double-conversion/cached-powers.h +64 -0
  150. data/ext/quickfix/double-conversion/diy-fp.cc +57 -0
  151. data/ext/quickfix/double-conversion/diy-fp.h +118 -0
  152. data/ext/quickfix/double-conversion/double-conversion.cc +994 -0
  153. data/ext/quickfix/double-conversion/double-conversion.h +543 -0
  154. data/ext/quickfix/double-conversion/fast-dtoa.cc +665 -0
  155. data/ext/quickfix/double-conversion/fast-dtoa.h +88 -0
  156. data/ext/quickfix/double-conversion/fixed-dtoa.cc +404 -0
  157. data/ext/quickfix/double-conversion/fixed-dtoa.h +56 -0
  158. data/ext/quickfix/double-conversion/ieee.h +402 -0
  159. data/ext/quickfix/double-conversion/strtod.cc +557 -0
  160. data/ext/quickfix/double-conversion/strtod.h +45 -0
  161. data/ext/quickfix/double-conversion/utils.h +374 -0
  162. data/ext/quickfix/extconf.rb +76 -0
  163. data/ext/quickfix/index.h +37 -0
  164. data/ext/quickfix/pugiconfig.hpp +77 -0
  165. data/ext/quickfix/pugixml.cpp +13237 -0
  166. data/ext/quickfix/pugixml.hpp +1516 -0
  167. data/ext/quickfix/scope_guard.hpp +215 -0
  168. data/ext/quickfix/stdint_msvc.h +254 -0
  169. data/ext/quickfix/strptime.h +7 -0
  170. data/lib/2.4/quickfix.so +0 -0
  171. data/lib/2.5/quickfix.so +0 -0
  172. data/lib/2.6/quickfix.so +0 -0
  173. data/lib/2.7/quickfix.so +0 -0
  174. data/lib/3.0/quickfix.so +0 -0
  175. data/lib/3.1/quickfix.so +0 -0
  176. data/lib/3.2/quickfix.so +0 -0
  177. data/lib/3.3/quickfix.so +0 -0
  178. data/lib/3.4/quickfix.so +0 -0
  179. data/lib/quickfix40.rb +274 -0
  180. data/lib/quickfix41.rb +351 -0
  181. data/lib/quickfix42.rb +1184 -0
  182. data/lib/quickfix43.rb +3504 -0
  183. data/lib/quickfix44.rb +14040 -0
  184. data/lib/quickfix50.rb +20051 -0
  185. data/lib/quickfix50sp1.rb +23596 -0
  186. data/lib/quickfix50sp2.rb +412444 -0
  187. data/lib/quickfix_fields.rb +79393 -0
  188. data/lib/quickfix_ruby.rb +82 -0
  189. data/lib/quickfixt11.rb +65 -0
  190. data/spec/FIX40.xml +862 -0
  191. data/spec/FIX41.xml +1282 -0
  192. data/spec/FIX42.xml +2743 -0
  193. data/spec/FIX43.xml +4230 -0
  194. data/spec/FIX44.xml +6600 -0
  195. data/spec/FIX50.xml +8142 -0
  196. data/spec/FIX50SP1.xml +9506 -0
  197. data/spec/FIX50SP2.xml +26069 -0
  198. data/spec/FIXT11.xml +252 -0
  199. data/test/DataDictionaryTestCase.rb +268 -0
  200. data/test/DictionaryTestCase.rb +112 -0
  201. data/test/FieldBaseTestCase.rb +24 -0
  202. data/test/MessageStoreTestCase.rb +19 -0
  203. data/test/MessageTestCase.rb +368 -0
  204. data/test/SessionSettingsTestCase.rb +41 -0
  205. metadata +247 -0
@@ -0,0 +1,1437 @@
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
+ Session::Sessions Session::s_sessions;
33
+ Session::SessionIDs Session::s_sessionIDs;
34
+ Session::Sessions Session::s_registered;
35
+ Mutex Session::s_mutex;
36
+
37
+ #define LOGEX(method) \
38
+ try { \
39
+ method; \
40
+ } catch (std::exception & e) { \
41
+ m_state.onEvent(e.what()); \
42
+ }
43
+
44
+ Session::Session(
45
+ std::function<UtcTimeStamp()> timestamper,
46
+ Application &application,
47
+ MessageStoreFactory &messageStoreFactory,
48
+ const SessionID &sessionID,
49
+ const DataDictionaryProvider &dataDictionaryProvider,
50
+ const TimeRange &sessionTime,
51
+ int heartBtInt,
52
+ LogFactory *pLogFactory)
53
+ : m_timestamper(std::move(timestamper)),
54
+ m_application(application),
55
+ m_sessionID(sessionID),
56
+ m_sessionTime(sessionTime),
57
+ m_logonTime(sessionTime),
58
+ m_senderDefaultApplVerID(ApplVerID_FIX50),
59
+ m_targetDefaultApplVerID(ApplVerID_FIX50),
60
+ m_sendRedundantResendRequests(false),
61
+ m_checkCompId(true),
62
+ m_checkLatency(true),
63
+ m_maxLatency(120),
64
+ m_resetOnLogon(false),
65
+ m_resetOnLogout(false),
66
+ m_resetOnDisconnect(false),
67
+ m_refreshOnLogon(false),
68
+ m_timestampPrecision(3),
69
+ m_persistMessages(true),
70
+ m_validateLengthAndChecksum(true),
71
+ m_sendNextExpectedMsgSeqNum(false),
72
+ m_isNonStopSession(false),
73
+ m_state(m_timestamper()),
74
+ m_dataDictionaryProvider(dataDictionaryProvider),
75
+ m_messageStoreFactory(messageStoreFactory),
76
+ m_pLogFactory(pLogFactory),
77
+ m_pResponder(0) {
78
+ m_state.heartBtInt(heartBtInt);
79
+ m_state.initiate(heartBtInt != 0);
80
+ m_state.store(m_messageStoreFactory.create(m_timestamper(), m_sessionID));
81
+ if (m_pLogFactory) {
82
+ m_state.log(m_pLogFactory->create(m_sessionID));
83
+ }
84
+
85
+ if (!checkSessionTime(m_timestamper())) {
86
+ m_state.reset(m_timestamper());
87
+ }
88
+
89
+ addSession(*this);
90
+ m_application.onCreate(m_sessionID);
91
+ m_state.onEvent("Created session");
92
+ }
93
+
94
+ Session::~Session() {
95
+ removeSession(*this);
96
+ m_messageStoreFactory.destroy(m_state.store());
97
+ if (m_pLogFactory && m_state.log()) {
98
+ m_pLogFactory->destroy(m_state.log());
99
+ }
100
+ }
101
+
102
+ void Session::insertSendingTime(Header &header) {
103
+ header.setField(SendingTime(m_timestamper(), getSupportedTimestampPrecision()));
104
+ }
105
+
106
+ void Session::insertOrigSendingTime(Header &header, const UtcTimeStamp &now) {
107
+ header.setField(OrigSendingTime(now, getSupportedTimestampPrecision()));
108
+ }
109
+
110
+ void Session::fill(Header &header) {
111
+ m_state.lastSentTime(m_timestamper());
112
+ header.setField(m_sessionID.getBeginString());
113
+ header.setField(m_sessionID.getSenderCompID());
114
+ header.setField(m_sessionID.getTargetCompID());
115
+ header.setField(MsgSeqNum(getExpectedSenderNum()));
116
+ insertSendingTime(header);
117
+ }
118
+
119
+ void Session::next(const UtcTimeStamp &now) {
120
+ try {
121
+ if (!checkSessionTime(now)) {
122
+ reset();
123
+ return;
124
+ }
125
+
126
+ if (!isEnabled() || !isLogonTime(now)) {
127
+ if (isLoggedOn()) {
128
+ if (!m_state.sentLogout()) {
129
+ m_state.onEvent("Initiated logout request");
130
+ generateLogout(m_state.logoutReason());
131
+ }
132
+ } else {
133
+ return;
134
+ }
135
+ }
136
+
137
+ if (!m_state.receivedLogon()) {
138
+ if (m_state.shouldSendLogon() && isLogonTime(now)) {
139
+ generateLogon();
140
+ m_state.onEvent("Initiated logon request");
141
+ } else if (m_state.alreadySentLogon() && m_state.logonTimedOut(m_timestamper())) {
142
+ m_state.onEvent("Timed out waiting for logon response");
143
+ disconnect();
144
+ }
145
+ return;
146
+ }
147
+
148
+ if (m_state.heartBtInt() == 0) {
149
+ return;
150
+ }
151
+
152
+ if (m_state.logoutTimedOut(m_timestamper())) {
153
+ m_state.onEvent("Timed out waiting for logout response");
154
+ disconnect();
155
+ }
156
+
157
+ if (m_state.withinHeartBeat(m_timestamper())) {
158
+ return;
159
+ }
160
+
161
+ if (m_state.timedOut(m_timestamper())) {
162
+ m_state.onEvent("Timed out waiting for heartbeat");
163
+ disconnect();
164
+ } else {
165
+ if (m_state.needTestRequest(m_timestamper())) {
166
+ generateTestRequest("TEST");
167
+ m_state.testRequest(m_state.testRequest() + 1);
168
+ m_state.onEvent("Sent test request TEST");
169
+ } else if (m_state.needHeartbeat(m_timestamper())) {
170
+ generateHeartbeat();
171
+ }
172
+ }
173
+ } catch (FIX::IOException &e) {
174
+ m_state.onEvent(e.what());
175
+ disconnect();
176
+ }
177
+ }
178
+
179
+ void Session::nextLogon(const Message &logon, const UtcTimeStamp &now) {
180
+ logon.getHeader().getField<SenderCompID>();
181
+ logon.getHeader().getField<TargetCompID>();
182
+
183
+ if (m_refreshOnLogon) {
184
+ refresh();
185
+ }
186
+
187
+ if (!isEnabled()) {
188
+ m_state.onEvent("Session is not enabled for logon");
189
+ disconnect();
190
+ return;
191
+ }
192
+
193
+ if (!isLogonTime(now)) {
194
+ m_state.onEvent("Received logon outside of valid logon time");
195
+ disconnect();
196
+ return;
197
+ }
198
+
199
+ ResetSeqNumFlag resetSeqNumFlag(false);
200
+ logon.getFieldIfSet(resetSeqNumFlag);
201
+ m_state.receivedReset(resetSeqNumFlag);
202
+
203
+ if (m_state.receivedReset()) {
204
+ m_state.onEvent("Logon contains ResetSeqNumFlag=Y, reseting sequence numbers to 1");
205
+ if (!m_state.sentReset()) {
206
+ m_state.reset(m_timestamper());
207
+ }
208
+ }
209
+
210
+ if (m_state.shouldSendLogon() && !m_state.receivedReset()) {
211
+ m_state.onEvent("Received logon response before sending request");
212
+ disconnect();
213
+ return;
214
+ }
215
+
216
+ if (!m_state.initiate() && m_resetOnLogon) {
217
+ m_state.reset(m_timestamper());
218
+ }
219
+
220
+ if (!verify(logon, false, true)) {
221
+ return;
222
+ }
223
+ m_state.receivedLogon(true);
224
+
225
+ bool sendRetransmitsAfterLogon = false;
226
+ NextExpectedMsgSeqNum nextExpectedMsgSeqNum;
227
+ if (logon.getFieldIfSet(nextExpectedMsgSeqNum)) {
228
+ if (nextExpectedMsgSeqNum.getValue() < getExpectedSenderNum()) {
229
+ sendRetransmitsAfterLogon = true;
230
+ } else if (nextExpectedMsgSeqNum.getValue() > getExpectedSenderNum()) {
231
+ std::stringstream stream;
232
+ stream << "NextExpectedMsgSeqNum too high, expecting " << getExpectedSenderNum() << " but received "
233
+ << nextExpectedMsgSeqNum;
234
+ m_state.onEvent(stream.str());
235
+ generateLogout(stream.str());
236
+ disconnect();
237
+ return;
238
+ }
239
+ }
240
+
241
+ if (!m_state.initiate() || (m_state.receivedReset() && !m_state.sentReset())) {
242
+ logon.getFieldIfSet(m_state.heartBtInt());
243
+ m_state.onEvent("Received logon request");
244
+ generateLogon(logon);
245
+ m_state.onEvent("Responding to logon request");
246
+ } else {
247
+ m_state.onEvent("Received logon response");
248
+ }
249
+
250
+ m_state.sentReset(false);
251
+ m_state.receivedReset(false);
252
+
253
+ auto const &msgSeqNum = logon.getHeader().getField<MsgSeqNum>();
254
+ if (isTargetTooHigh(msgSeqNum) && !resetSeqNumFlag) {
255
+ if (m_sendNextExpectedMsgSeqNum) {
256
+ m_state.onEvent(
257
+ "Expecting retransmits FROM: " + SEQNUM_CONVERTOR::convert(getExpectedTargetNum())
258
+ + " TO: " + SEQNUM_CONVERTOR::convert(msgSeqNum - 1));
259
+ m_state.queue(msgSeqNum, logon);
260
+ m_state.resendRange(getExpectedTargetNum(), msgSeqNum - 1);
261
+ } else {
262
+ doTargetTooHigh(logon);
263
+ }
264
+ } else {
265
+ m_state.incrNextTargetMsgSeqNum();
266
+ nextQueued(now);
267
+ }
268
+
269
+ if (isLoggedOn()) {
270
+ m_application.onLogon(m_sessionID);
271
+ }
272
+
273
+ if (sendRetransmitsAfterLogon) {
274
+ Locker l(m_mutex);
275
+
276
+ auto beginSeqNo = nextExpectedMsgSeqNum.getValue();
277
+ auto endSeqNo = getExpectedSenderNum() - 1;
278
+ m_state.onEvent(
279
+ "Sending retransmits due to received NextExpectedMsgSeqNum is too low. FROM: "
280
+ + SEQNUM_CONVERTOR::convert(beginSeqNo) + " TO: " + SEQNUM_CONVERTOR::convert(endSeqNo));
281
+
282
+ if (!m_persistMessages) {
283
+ endSeqNo = EndSeqNo(endSeqNo + 1);
284
+ auto next = m_state.getNextSenderMsgSeqNum();
285
+ if (endSeqNo > next) {
286
+ endSeqNo = EndSeqNo(next);
287
+ }
288
+ generateSequenceReset(beginSeqNo, endSeqNo);
289
+ } else {
290
+ generateRetransmits(beginSeqNo, endSeqNo);
291
+ }
292
+ }
293
+ }
294
+
295
+ void Session::nextHeartbeat(const Message &heartbeat, const UtcTimeStamp &now) {
296
+ if (!verify(heartbeat)) {
297
+ return;
298
+ }
299
+ m_state.incrNextTargetMsgSeqNum();
300
+ nextQueued(now);
301
+ }
302
+
303
+ void Session::nextTestRequest(const Message &testRequest, const UtcTimeStamp &now) {
304
+ if (!verify(testRequest)) {
305
+ return;
306
+ }
307
+ generateHeartbeat(testRequest);
308
+ m_state.incrNextTargetMsgSeqNum();
309
+ nextQueued(now);
310
+ }
311
+
312
+ void Session::nextLogout(const Message &logout, const UtcTimeStamp &now) {
313
+ if (!verify(logout, false, false)) {
314
+ return;
315
+ }
316
+ if (!m_state.sentLogout()) {
317
+ m_state.onEvent("Received logout request");
318
+ generateLogout();
319
+ m_state.onEvent("Sending logout response");
320
+ } else {
321
+ m_state.onEvent("Received logout response");
322
+ }
323
+
324
+ m_state.incrNextTargetMsgSeqNum();
325
+ if (m_resetOnLogout) {
326
+ m_state.reset(m_timestamper());
327
+ }
328
+ disconnect();
329
+ }
330
+
331
+ void Session::nextReject(const Message &reject, const UtcTimeStamp &now) {
332
+ if (!verify(reject, false, true)) {
333
+ return;
334
+ }
335
+ m_state.incrNextTargetMsgSeqNum();
336
+ nextQueued(now);
337
+ }
338
+
339
+ void Session::nextSequenceReset(const Message &sequenceReset, const UtcTimeStamp &now) {
340
+ bool isGapFill = false;
341
+ GapFillFlag gapFillFlag;
342
+ if (sequenceReset.getFieldIfSet(gapFillFlag)) {
343
+ isGapFill = gapFillFlag;
344
+ }
345
+
346
+ if (!verify(sequenceReset, isGapFill, isGapFill)) {
347
+ return;
348
+ }
349
+
350
+ NewSeqNo newSeqNo;
351
+ if (sequenceReset.getFieldIfSet(newSeqNo)) {
352
+ m_state.onEvent(
353
+ "Received SequenceReset FROM: " + SEQNUM_CONVERTOR::convert(getExpectedTargetNum())
354
+ + " TO: " + SEQNUM_CONVERTOR::convert(newSeqNo));
355
+
356
+ if (newSeqNo > getExpectedTargetNum()) {
357
+ m_state.setNextTargetMsgSeqNum(MsgSeqNum(newSeqNo));
358
+ } else if (newSeqNo < getExpectedTargetNum()) {
359
+ generateReject(sequenceReset, SessionRejectReason_VALUE_IS_INCORRECT);
360
+ }
361
+ }
362
+ }
363
+
364
+ void Session::nextResendRequest(const Message &resendRequest, const UtcTimeStamp &now) {
365
+ if (!verify(resendRequest, false, false)) {
366
+ return;
367
+ }
368
+
369
+ Locker l(m_mutex);
370
+
371
+ auto beginSeqNo = resendRequest.getField<BeginSeqNo>();
372
+ auto endSeqNo = resendRequest.getField<EndSeqNo>();
373
+
374
+ m_state.onEvent(
375
+ "Received ResendRequest FROM: " + SEQNUM_CONVERTOR::convert(beginSeqNo)
376
+ + " TO: " + SEQNUM_CONVERTOR::convert(endSeqNo));
377
+
378
+ std::string beginString = m_sessionID.getBeginString();
379
+ if ((beginString >= FIX::BeginString_FIX42 && endSeqNo == 0)
380
+ || (beginString <= FIX::BeginString_FIX42 && endSeqNo == 999999) || (endSeqNo >= getExpectedSenderNum())) {
381
+ endSeqNo = getExpectedSenderNum() - 1;
382
+ }
383
+
384
+ if (!m_persistMessages) {
385
+ endSeqNo = EndSeqNo(endSeqNo + 1);
386
+ auto next = m_state.getNextSenderMsgSeqNum();
387
+ if (endSeqNo > next) {
388
+ endSeqNo = EndSeqNo(next);
389
+ }
390
+ generateSequenceReset(beginSeqNo, endSeqNo);
391
+ } else {
392
+ generateRetransmits(beginSeqNo.getValue(), endSeqNo.getValue());
393
+ }
394
+
395
+ MsgSeqNum msgSeqNum(0);
396
+ resendRequest.getHeader().getField(msgSeqNum);
397
+ if (!isTargetTooHigh(msgSeqNum) && !isTargetTooLow(msgSeqNum)) {
398
+ m_state.incrNextTargetMsgSeqNum();
399
+ }
400
+ }
401
+
402
+ void Session::generateRetransmits(SEQNUM beginSeqNo, SEQNUM endSeqNo) {
403
+ std::vector<std::string> messages;
404
+ m_state.get(beginSeqNo, endSeqNo, messages);
405
+
406
+ std::vector<std::string>::iterator i;
407
+ MsgSeqNum msgSeqNum(0);
408
+ MsgType msgType;
409
+ SEQNUM begin = 0;
410
+ SEQNUM current = beginSeqNo;
411
+ bool appMessageJustSent = false;
412
+ std::string messageString;
413
+
414
+ for (i = messages.begin(); i != messages.end(); ++i) {
415
+ appMessageJustSent = false;
416
+ std::unique_ptr<FIX::Message> pMsg;
417
+ std::string strMsgType;
418
+ const DataDictionary &sessionDD = m_dataDictionaryProvider.getSessionDataDictionary(m_sessionID.getBeginString());
419
+ if (sessionDD.isMessageFieldsOrderPreserved()) {
420
+ std::string::size_type equalSign = (*i).find("\00135=");
421
+ equalSign += 4;
422
+ std::string::size_type soh = (*i).find_first_of('\001', equalSign);
423
+ strMsgType = (*i).substr(equalSign, soh - equalSign);
424
+ }
425
+
426
+ if (m_sessionID.isFIXT()) {
427
+ Message msg;
428
+ msg.setStringHeader(*i);
429
+ ApplVerID applVerID;
430
+ if (!msg.getHeader().getFieldIfSet(applVerID)) {
431
+ applVerID = m_senderDefaultApplVerID;
432
+ }
433
+
434
+ const DataDictionary &applicationDD = m_dataDictionaryProvider.getApplicationDataDictionary(applVerID);
435
+ if (strMsgType.empty()) {
436
+ pMsg.reset(new Message(*i, sessionDD, applicationDD, m_validateLengthAndChecksum));
437
+ } else {
438
+ const message_order &headerOrder = sessionDD.getHeaderOrderedFields();
439
+ const message_order &trailerOrder = sessionDD.getTrailerOrderedFields();
440
+ const message_order &messageOrder = applicationDD.getMessageOrderedFields(strMsgType);
441
+ pMsg.reset(new Message(
442
+ headerOrder,
443
+ trailerOrder,
444
+ messageOrder,
445
+ *i,
446
+ sessionDD,
447
+ applicationDD,
448
+ m_validateLengthAndChecksum));
449
+ }
450
+ } else {
451
+ if (strMsgType.empty()) {
452
+ pMsg.reset(new Message(*i, sessionDD, m_validateLengthAndChecksum));
453
+ } else {
454
+ const message_order &headerOrder = sessionDD.getHeaderOrderedFields();
455
+ const message_order &trailerOrder = sessionDD.getTrailerOrderedFields();
456
+ const message_order &messageOrder = sessionDD.getMessageOrderedFields(strMsgType);
457
+ pMsg.reset(new Message(headerOrder, trailerOrder, messageOrder, *i, sessionDD, m_validateLengthAndChecksum));
458
+ }
459
+ }
460
+
461
+ Message &msg = *pMsg;
462
+
463
+ msg.getHeader().getField(msgSeqNum);
464
+ msg.getHeader().getField(msgType);
465
+
466
+ if ((current != msgSeqNum) && !begin) {
467
+ begin = current;
468
+ }
469
+
470
+ if (Message::isAdminMsgType(msgType)) {
471
+ if (!begin) {
472
+ begin = msgSeqNum;
473
+ }
474
+ } else {
475
+ if (resend(msg)) {
476
+ if (begin) {
477
+ generateSequenceReset(begin, msgSeqNum);
478
+ }
479
+ send(msg.toString(messageString));
480
+ m_state.onEvent("Resending Message: " + SEQNUM_CONVERTOR::convert(msgSeqNum));
481
+ begin = 0;
482
+ appMessageJustSent = true;
483
+ } else {
484
+ if (!begin) {
485
+ begin = msgSeqNum;
486
+ }
487
+ }
488
+ }
489
+ current = msgSeqNum + 1;
490
+ }
491
+ if (begin) {
492
+ generateSequenceReset(begin, msgSeqNum + 1);
493
+ }
494
+
495
+ if (endSeqNo > msgSeqNum) {
496
+ endSeqNo = EndSeqNo(endSeqNo + 1);
497
+ auto next = m_state.getNextSenderMsgSeqNum();
498
+ if (endSeqNo > next) {
499
+ endSeqNo = EndSeqNo(next);
500
+ }
501
+ if (appMessageJustSent) {
502
+ beginSeqNo = msgSeqNum + 1;
503
+ }
504
+ generateSequenceReset(beginSeqNo, endSeqNo);
505
+ }
506
+ }
507
+
508
+ Message Session::newMessage(const MsgType &msgType) const {
509
+ const DataDictionary &sessionDD = m_dataDictionaryProvider.getSessionDataDictionary(m_sessionID.getBeginString());
510
+
511
+ if (!sessionDD.isMessageFieldsOrderPreserved()) {
512
+ Message message = Message();
513
+ message.getHeader().setField(msgType);
514
+ return message;
515
+ } else {
516
+ const message_order &headerOrder = sessionDD.getHeaderOrderedFields();
517
+ const message_order &trailerOrder = sessionDD.getTrailerOrderedFields();
518
+ if (!m_sessionID.isFIXT() || Message::isAdminMsgType(msgType.getValue())) {
519
+ const message_order &messageOrder = sessionDD.getMessageOrderedFields(msgType.getValue());
520
+ Message message = Message(headerOrder, trailerOrder, messageOrder);
521
+ message.getHeader().setField(msgType);
522
+ return message;
523
+ } else {
524
+ const DataDictionary &applicationDD
525
+ = m_dataDictionaryProvider.getApplicationDataDictionary(m_senderDefaultApplVerID);
526
+ const message_order &messageOrder = applicationDD.getMessageOrderedFields(msgType.getValue());
527
+ Message message = Message(headerOrder, trailerOrder, messageOrder);
528
+ message.getHeader().setField(msgType);
529
+ return message;
530
+ }
531
+ }
532
+ }
533
+
534
+ bool Session::send(Message &message) {
535
+ message.getHeader().removeField(FIELD::PossDupFlag);
536
+ message.getHeader().removeField(FIELD::OrigSendingTime);
537
+ return sendRaw(message);
538
+ }
539
+
540
+ bool Session::sendRaw(Message &message, SEQNUM num) {
541
+ Locker l(m_mutex);
542
+
543
+ try {
544
+ Header &header = message.getHeader();
545
+
546
+ MsgType msgType;
547
+ header.getFieldIfSet(msgType);
548
+
549
+ fill(header);
550
+ std::string messageString;
551
+
552
+ if (num) {
553
+ header.setField(MsgSeqNum(num));
554
+ }
555
+
556
+ if (Message::isAdminMsgType(msgType)) {
557
+ m_application.toAdmin(message, m_sessionID);
558
+
559
+ if (msgType == MsgType_Logon && !m_state.receivedReset()) {
560
+ ResetSeqNumFlag resetSeqNumFlag(false);
561
+ message.getFieldIfSet(resetSeqNumFlag);
562
+
563
+ if (resetSeqNumFlag) {
564
+ m_state.reset(m_timestamper());
565
+ message.getHeader().setField(MsgSeqNum(getExpectedSenderNum()));
566
+ }
567
+ m_state.sentReset(resetSeqNumFlag);
568
+ }
569
+
570
+ message.toString(messageString);
571
+
572
+ if (!num) {
573
+ persist(message, messageString);
574
+ }
575
+
576
+ if (msgType == MsgType_Logon || msgType == MsgType_Logout || msgType == MsgType_ResendRequest
577
+ || msgType == MsgType_SequenceReset || isLoggedOn()) {
578
+ send(messageString);
579
+ }
580
+ } else {
581
+ // do not send application messages if they will just be cleared
582
+ if (!isLoggedOn() && shouldSendReset()) {
583
+ return false;
584
+ }
585
+
586
+ try {
587
+ m_application.toApp(message, m_sessionID);
588
+ message.toString(messageString);
589
+
590
+ if (!num) {
591
+ persist(message, messageString);
592
+ }
593
+
594
+ if (isLoggedOn()) {
595
+ send(messageString);
596
+ }
597
+ } catch (DoNotSend &) {
598
+ return false;
599
+ }
600
+ }
601
+
602
+ return true;
603
+ } catch (IOException &e) {
604
+ m_state.onEvent(e.what());
605
+ return false;
606
+ }
607
+ }
608
+
609
+ bool Session::send(const std::string &string) {
610
+ if (!m_pResponder) {
611
+ return false;
612
+ }
613
+ m_state.onOutgoing(string);
614
+ return m_pResponder->send(string);
615
+ }
616
+
617
+ void Session::disconnect() {
618
+ Locker l(m_mutex);
619
+
620
+ if (m_pResponder) {
621
+ m_state.onEvent("Disconnecting");
622
+
623
+ m_pResponder->disconnect();
624
+ m_pResponder = 0;
625
+ }
626
+
627
+ if (m_state.receivedLogon() || m_state.sentLogon()) {
628
+ m_state.receivedLogon(false);
629
+ m_state.sentLogon(false);
630
+ m_application.onLogout(m_sessionID);
631
+ }
632
+
633
+ m_state.sentLogout(false);
634
+ m_state.receivedReset(false);
635
+ m_state.sentReset(false);
636
+ m_state.clearQueue();
637
+ m_state.logoutReason();
638
+ if (m_resetOnDisconnect) {
639
+ m_state.reset(m_timestamper());
640
+ }
641
+
642
+ m_state.resendRange(0, 0);
643
+ }
644
+
645
+ bool Session::resend(Message &message) {
646
+ Header &header = message.getHeader();
647
+ auto const &sendingTime = header.getField<SendingTime>();
648
+ header.getField<MsgSeqNum>();
649
+ insertOrigSendingTime(header, sendingTime);
650
+ header.setField(PossDupFlag(true));
651
+ insertSendingTime(header);
652
+
653
+ try {
654
+ m_application.toApp(message, m_sessionID);
655
+ return true;
656
+ } catch (DoNotSend &) {
657
+ return false;
658
+ }
659
+ }
660
+
661
+ void Session::persist(const Message &message, const std::string &messageString) EXCEPT(IOException) {
662
+ auto const &msgSeqNum = message.getHeader().getField<MsgSeqNum>();
663
+ if (m_persistMessages) {
664
+ m_state.set(msgSeqNum, messageString);
665
+ }
666
+ m_state.incrNextSenderMsgSeqNum();
667
+ }
668
+
669
+ void Session::generateLogon() {
670
+ Message logon = newMessage(MsgType(MsgType_Logon));
671
+
672
+ logon.setField(EncryptMethod(0));
673
+ logon.setField(m_state.heartBtInt());
674
+ if (m_sessionID.isFIXT()) {
675
+ logon.setField(DefaultApplVerID(m_senderDefaultApplVerID));
676
+ }
677
+ if (m_refreshOnLogon) {
678
+ refresh();
679
+ }
680
+ if (m_resetOnLogon) {
681
+ m_state.reset(m_timestamper());
682
+ }
683
+ if (shouldSendReset()) {
684
+ logon.setField(ResetSeqNumFlag(true));
685
+ }
686
+ if (m_sendNextExpectedMsgSeqNum) {
687
+ logon.setField(NextExpectedMsgSeqNum(getExpectedTargetNum()));
688
+ }
689
+
690
+ fill(logon.getHeader());
691
+ m_state.lastReceivedTime(m_timestamper());
692
+ m_state.testRequest(0);
693
+ m_state.sentLogon(true);
694
+ sendRaw(logon);
695
+ }
696
+
697
+ void Session::generateLogon(const Message &aLogon) {
698
+ Message logon = newMessage(MsgType(MsgType_Logon));
699
+
700
+ logon.setField(EncryptMethod(0));
701
+ if (m_sessionID.isFIXT()) {
702
+ logon.setField(DefaultApplVerID(m_senderDefaultApplVerID));
703
+ }
704
+ if (m_state.receivedReset()) {
705
+ logon.setField(ResetSeqNumFlag(true));
706
+ }
707
+ logon.setField(aLogon.getField<HeartBtInt>());
708
+ if (m_sendNextExpectedMsgSeqNum) {
709
+ logon.setField(NextExpectedMsgSeqNum(
710
+ getExpectedTargetNum() + 1)); // +1 because incoming Logon did not increment the target SeqNum yet
711
+ }
712
+ fill(logon.getHeader());
713
+ sendRaw(logon);
714
+ m_state.sentLogon(true);
715
+ }
716
+
717
+ void Session::generateResendRequest(const BeginString &beginString, const MsgSeqNum &msgSeqNum) {
718
+ Message resendRequest = newMessage(MsgType(MsgType_ResendRequest));
719
+
720
+ BeginSeqNo beginSeqNo((int)getExpectedTargetNum());
721
+ EndSeqNo endSeqNo(msgSeqNum - 1);
722
+ if (beginString >= FIX::BeginString_FIX42) {
723
+ endSeqNo = 0;
724
+ } else if (beginString <= FIX::BeginString_FIX41) {
725
+ endSeqNo = 999999;
726
+ }
727
+ resendRequest.setField(beginSeqNo);
728
+ resendRequest.setField(endSeqNo);
729
+ fill(resendRequest.getHeader());
730
+ sendRaw(resendRequest);
731
+
732
+ m_state.onEvent(
733
+ "Sent ResendRequest FROM: " + SEQNUM_CONVERTOR::convert(beginSeqNo)
734
+ + " TO: " + SEQNUM_CONVERTOR::convert(endSeqNo));
735
+
736
+ m_state.resendRange(beginSeqNo, msgSeqNum - 1);
737
+ }
738
+
739
+ void Session::generateSequenceReset(SEQNUM beginSeqNo, SEQNUM endSeqNo) {
740
+ Message sequenceReset = newMessage(MsgType(MsgType_SequenceReset));
741
+
742
+ NewSeqNo newSeqNo(endSeqNo);
743
+ sequenceReset.getHeader().setField(PossDupFlag(true));
744
+ sequenceReset.setField(newSeqNo);
745
+ fill(sequenceReset.getHeader());
746
+
747
+ insertOrigSendingTime(sequenceReset.getHeader(), sequenceReset.getHeader().getField<SendingTime>());
748
+ sequenceReset.getHeader().setField(MsgSeqNum(beginSeqNo));
749
+ sequenceReset.setField(GapFillFlag(true));
750
+ sendRaw(sequenceReset, beginSeqNo);
751
+ m_state.onEvent("Sent SequenceReset TO: " + SEQNUM_CONVERTOR::convert(newSeqNo));
752
+ }
753
+
754
+ void Session::generateHeartbeat() {
755
+ Message heartbeat = newMessage(MsgType(MsgType_Heartbeat));
756
+
757
+ fill(heartbeat.getHeader());
758
+ sendRaw(heartbeat);
759
+ }
760
+
761
+ void Session::generateHeartbeat(const Message &testRequest) {
762
+ Message heartbeat = newMessage(MsgType(MsgType_Heartbeat));
763
+
764
+ fill(heartbeat.getHeader());
765
+ try {
766
+ heartbeat.setField(testRequest.getField<TestReqID>());
767
+ } catch (FieldNotFound &) {}
768
+
769
+ sendRaw(heartbeat);
770
+ }
771
+
772
+ void Session::generateTestRequest(const std::string &id) {
773
+ Message testRequest = newMessage(MsgType(MsgType_TestRequest));
774
+
775
+ fill(testRequest.getHeader());
776
+ TestReqID testReqID(id);
777
+ testRequest.setField(testReqID);
778
+
779
+ sendRaw(testRequest);
780
+ }
781
+
782
+ void Session::generateReject(const Message &message, int err, int field) {
783
+ std::string beginString = m_sessionID.getBeginString();
784
+
785
+ Message reject = newMessage(MsgType(MsgType_Reject));
786
+
787
+ reject.reverseRoute(message.getHeader());
788
+ fill(reject.getHeader());
789
+
790
+ MsgSeqNum msgSeqNum;
791
+
792
+ auto const &msgType = message.getHeader().getField<MsgType>();
793
+ if (message.getHeader().getFieldIfSet(msgSeqNum)) {
794
+ if (msgSeqNum.getString() != "") {
795
+ reject.setField(RefSeqNum(msgSeqNum));
796
+ }
797
+ }
798
+
799
+ if (beginString >= FIX::BeginString_FIX42) {
800
+ if (msgType.getString() != "") {
801
+ reject.setField(RefMsgType(msgType));
802
+ }
803
+ if ((beginString == FIX::BeginString_FIX42 && err <= SessionRejectReason_INVALID_MSGTYPE)
804
+ || beginString > FIX::BeginString_FIX42) {
805
+ reject.setField(SessionRejectReason(err));
806
+ }
807
+ }
808
+ if (msgType != MsgType_Logon && msgType != MsgType_SequenceReset && msgSeqNum == getExpectedTargetNum()) {
809
+ m_state.incrNextTargetMsgSeqNum();
810
+ }
811
+
812
+ const char *reason = 0;
813
+ switch (err) {
814
+ case SessionRejectReason_INVALID_TAG_NUMBER:
815
+ reason = SessionRejectReason_INVALID_TAG_NUMBER_TEXT;
816
+ break;
817
+ case SessionRejectReason_REQUIRED_TAG_MISSING:
818
+ reason = SessionRejectReason_REQUIRED_TAG_MISSING_TEXT;
819
+ break;
820
+ case SessionRejectReason_TAG_NOT_DEFINED_FOR_THIS_MESSAGE_TYPE:
821
+ reason = SessionRejectReason_TAG_NOT_DEFINED_FOR_THIS_MESSAGE_TYPE_TEXT;
822
+ break;
823
+ case SessionRejectReason_TAG_SPECIFIED_WITHOUT_A_VALUE:
824
+ reason = SessionRejectReason_TAG_SPECIFIED_WITHOUT_A_VALUE_TEXT;
825
+ break;
826
+ case SessionRejectReason_VALUE_IS_INCORRECT:
827
+ reason = SessionRejectReason_VALUE_IS_INCORRECT_TEXT;
828
+ break;
829
+ case SessionRejectReason_INCORRECT_DATA_FORMAT_FOR_VALUE:
830
+ reason = SessionRejectReason_INCORRECT_DATA_FORMAT_FOR_VALUE_TEXT;
831
+ break;
832
+ case SessionRejectReason_COMPID_PROBLEM:
833
+ reason = SessionRejectReason_COMPID_PROBLEM_TEXT;
834
+ break;
835
+ case SessionRejectReason_SENDINGTIME_ACCURACY_PROBLEM:
836
+ reason = SessionRejectReason_SENDINGTIME_ACCURACY_PROBLEM_TEXT;
837
+ break;
838
+ case SessionRejectReason_INVALID_MSGTYPE:
839
+ reason = SessionRejectReason_INVALID_MSGTYPE_TEXT;
840
+ break;
841
+ case SessionRejectReason_TAG_APPEARS_MORE_THAN_ONCE:
842
+ reason = SessionRejectReason_TAG_APPEARS_MORE_THAN_ONCE_TEXT;
843
+ break;
844
+ case SessionRejectReason_TAG_SPECIFIED_OUT_OF_REQUIRED_ORDER:
845
+ reason = SessionRejectReason_TAG_SPECIFIED_OUT_OF_REQUIRED_ORDER_TEXT;
846
+ break;
847
+ case SessionRejectReason_INCORRECT_NUMINGROUP_COUNT_FOR_REPEATING_GROUP:
848
+ reason = SessionRejectReason_INCORRECT_NUMINGROUP_COUNT_FOR_REPEATING_GROUP_TEXT;
849
+ break;
850
+ };
851
+
852
+ if (reason && (field || err == SessionRejectReason_INVALID_TAG_NUMBER)) {
853
+ populateRejectReason(reject, field, reason);
854
+ m_state.onEvent(
855
+ "Message " + msgSeqNum.getString() + " Rejected: " + reason + ":" + SEQNUM_CONVERTOR::convert(field));
856
+ } else if (reason) {
857
+ populateRejectReason(reject, reason);
858
+ m_state.onEvent("Message " + msgSeqNum.getString() + " Rejected: " + reason);
859
+ } else {
860
+ m_state.onEvent("Message " + msgSeqNum.getString() + " Rejected");
861
+ }
862
+
863
+ if (!m_state.receivedLogon()) {
864
+ throw std::runtime_error("Tried to send a reject while not logged on");
865
+ }
866
+
867
+ sendRaw(reject);
868
+ }
869
+
870
+ void Session::generateReject(const Message &message, const std::string &text) {
871
+ std::string beginString = m_sessionID.getBeginString();
872
+
873
+ Message reject = newMessage(MsgType(MsgType_Reject));
874
+
875
+ reject.reverseRoute(message.getHeader());
876
+ fill(reject.getHeader());
877
+
878
+ auto const &msgType = message.getHeader().getField<MsgType>();
879
+ auto const &msgSeqNum = message.getHeader().getField<MsgSeqNum>();
880
+
881
+ if (beginString >= FIX::BeginString_FIX42) {
882
+ reject.setField(RefMsgType(msgType));
883
+ }
884
+ reject.setField(RefSeqNum(msgSeqNum));
885
+
886
+ if (msgType != MsgType_Logon && msgType != MsgType_SequenceReset) {
887
+ m_state.incrNextTargetMsgSeqNum();
888
+ }
889
+
890
+ reject.setField(Text(text));
891
+ sendRaw(reject);
892
+ m_state.onEvent("Message " + msgSeqNum.getString() + " Rejected: " + text);
893
+ }
894
+
895
+ void Session::generateBusinessReject(const Message &message, int err, int field) {
896
+ Message reject = newMessage(MsgType(MsgType_BusinessMessageReject));
897
+ auto const &msgSeqNum = message.getHeader().getField<MsgSeqNum>();
898
+
899
+ if (m_sessionID.isFIXT()) {
900
+ reject.setField(DefaultApplVerID(m_senderDefaultApplVerID));
901
+ }
902
+ fill(reject.getHeader());
903
+ reject.setField(RefMsgType(message.getHeader().getField<MsgType>()));
904
+ reject.setField(RefSeqNum(msgSeqNum));
905
+ reject.setField(BusinessRejectReason(err));
906
+ m_state.incrNextTargetMsgSeqNum();
907
+
908
+ const char *reason = 0;
909
+ switch (err) {
910
+ case BusinessRejectReason_OTHER:
911
+ reason = BusinessRejectReason_OTHER_TEXT;
912
+ break;
913
+ case BusinessRejectReason_UNKNOWN_ID:
914
+ reason = BusinessRejectReason_UNKNOWN_ID_TEXT;
915
+ break;
916
+ case BusinessRejectReason_UNKNOWN_SECURITY:
917
+ reason = BusinessRejectReason_UNKNOWN_SECURITY_TEXT;
918
+ break;
919
+ case BusinessRejectReason_UNSUPPORTED_MESSAGE_TYPE:
920
+ reason = BusinessRejectReason_UNSUPPORTED_MESSAGE_TYPE_TEXT;
921
+ break;
922
+ case BusinessRejectReason_APPLICATION_NOT_AVAILABLE:
923
+ reason = BusinessRejectReason_APPLICATION_NOT_AVAILABLE_TEXT;
924
+ break;
925
+ case BusinessRejectReason_CONDITIONALLY_REQUIRED_FIELD_MISSING:
926
+ reason = BusinessRejectReason_CONDITIONALLY_REQUIRED_FIELD_MISSING_TEXT;
927
+ break;
928
+ case BusinessRejectReason_NOT_AUTHORIZED:
929
+ reason = BusinessRejectReason_NOT_AUTHORIZED_TEXT;
930
+ break;
931
+ case BusinessRejectReason_DELIVER_TO_FIRM_NOT_AVAILABLE_AT_THIS_TIME:
932
+ reason = BusinessRejectReason_DELIVER_TO_FIRM_NOT_AVAILABLE_AT_THIS_TIME_TEXT;
933
+ break;
934
+ };
935
+
936
+ if (reason && field) {
937
+ populateRejectReason(reject, field, reason);
938
+ m_state.onEvent(
939
+ "Message " + msgSeqNum.getString() + " Rejected: " + reason + ":" + SEQNUM_CONVERTOR::convert(field));
940
+ } else if (reason) {
941
+ populateRejectReason(reject, reason);
942
+ m_state.onEvent("Message " + msgSeqNum.getString() + " Rejected: " + reason);
943
+ } else {
944
+ m_state.onEvent("Message " + msgSeqNum.getString() + " Rejected");
945
+ }
946
+
947
+ sendRaw(reject);
948
+ }
949
+
950
+ void Session::generateLogout(const std::string &text) {
951
+ Message logout = newMessage(MsgType(MsgType_Logout));
952
+
953
+ fill(logout.getHeader());
954
+ if (text.length()) {
955
+ logout.setField(Text(text));
956
+ }
957
+ sendRaw(logout);
958
+ m_state.sentLogout(true);
959
+ }
960
+
961
+ void Session::populateRejectReason(Message &reject, int field, const std::string &text) {
962
+ auto const &msgType = reject.getHeader().getField<MsgType>();
963
+
964
+ if (msgType == MsgType_Reject && m_sessionID.getBeginString() >= FIX::BeginString_FIX42) {
965
+ reject.setField(RefTagID(field));
966
+ reject.setField(Text(text));
967
+ } else {
968
+ std::stringstream stream;
969
+ stream << text << " (" << field << ")";
970
+ reject.setField(Text(stream.str()));
971
+ }
972
+ }
973
+
974
+ void Session::populateRejectReason(Message &reject, const std::string &text) { reject.setField(Text(text)); }
975
+
976
+ bool Session::verify(const Message &msg, bool checkTooHigh, bool checkTooLow) {
977
+ const MsgType *pMsgType = 0;
978
+ const MsgSeqNum *pMsgSeqNum = 0;
979
+
980
+ try {
981
+ const Header &header = msg.getHeader();
982
+
983
+ pMsgType = FIELD_GET_PTR(header, MsgType);
984
+ const SenderCompID &senderCompID = FIELD_GET_REF(header, SenderCompID);
985
+ const TargetCompID &targetCompID = FIELD_GET_REF(header, TargetCompID);
986
+ const SendingTime &sendingTime = FIELD_GET_REF(header, SendingTime);
987
+
988
+ if (checkTooHigh || checkTooLow) {
989
+ pMsgSeqNum = FIELD_GET_PTR(header, MsgSeqNum);
990
+ }
991
+
992
+ if (!validLogonState(*pMsgType)) {
993
+ throw std::logic_error("Logon state is not valid for message");
994
+ }
995
+
996
+ if (!isGoodTime(sendingTime)) {
997
+ doBadTime(msg);
998
+ return false;
999
+ }
1000
+ if (!isCorrectCompID(senderCompID, targetCompID)) {
1001
+ doBadCompID(msg);
1002
+ return false;
1003
+ }
1004
+
1005
+ if (checkTooHigh && isTargetTooHigh(*pMsgSeqNum)) {
1006
+ doTargetTooHigh(msg);
1007
+ return false;
1008
+ } else if (checkTooLow && isTargetTooLow(*pMsgSeqNum)) {
1009
+ doTargetTooLow(msg);
1010
+ return false;
1011
+ }
1012
+
1013
+ if ((checkTooHigh || checkTooLow) && m_state.resendRequested()) {
1014
+ SessionState::ResendRange range = m_state.resendRange();
1015
+
1016
+ if (*pMsgSeqNum >= range.second) {
1017
+ m_state.onEvent(
1018
+ "ResendRequest for messages FROM: " + SEQNUM_CONVERTOR::convert(range.first)
1019
+ + " TO: " + SEQNUM_CONVERTOR::convert(range.second) + " has been satisfied.");
1020
+ m_state.resendRange(0, 0);
1021
+ }
1022
+ }
1023
+ } catch (std::exception &e) {
1024
+ m_state.onEvent(e.what());
1025
+ disconnect();
1026
+ return false;
1027
+ }
1028
+
1029
+ m_state.lastReceivedTime(m_timestamper());
1030
+ m_state.testRequest(0);
1031
+
1032
+ fromCallback(pMsgType ? *pMsgType : MsgType(), msg, m_sessionID);
1033
+ return true;
1034
+ }
1035
+
1036
+ bool Session::shouldSendReset() {
1037
+ std::string beginString = m_sessionID.getBeginString();
1038
+ return beginString >= FIX::BeginString_FIX41 && (m_resetOnLogon || m_resetOnLogout || m_resetOnDisconnect)
1039
+ && (getExpectedSenderNum() == 1) && (getExpectedTargetNum() == 1);
1040
+ }
1041
+
1042
+ bool Session::validLogonState(const MsgType &msgType) {
1043
+ if ((msgType == MsgType_Logon && m_state.sentReset()) || (m_state.receivedReset())) {
1044
+ return true;
1045
+ }
1046
+ if ((msgType == MsgType_Logon && !m_state.receivedLogon()) || (msgType != MsgType_Logon && m_state.receivedLogon())) {
1047
+ return true;
1048
+ }
1049
+ if (msgType == MsgType_Logout && m_state.sentLogon()) {
1050
+ return true;
1051
+ }
1052
+ if (msgType != MsgType_Logout && m_state.sentLogout()) {
1053
+ return true;
1054
+ }
1055
+ if (msgType == MsgType_SequenceReset) {
1056
+ return true;
1057
+ }
1058
+ if (msgType == MsgType_Reject) {
1059
+ return true;
1060
+ }
1061
+
1062
+ return false;
1063
+ }
1064
+
1065
+ void Session::fromCallback(const MsgType &msgType, const Message &msg, const SessionID &sessionID) {
1066
+ if (Message::isAdminMsgType(msgType)) {
1067
+ m_application.fromAdmin(msg, m_sessionID);
1068
+ } else {
1069
+ m_application.fromApp(msg, m_sessionID);
1070
+ }
1071
+ }
1072
+
1073
+ void Session::doBadTime(const Message &msg) {
1074
+ generateReject(msg, SessionRejectReason_SENDINGTIME_ACCURACY_PROBLEM);
1075
+ generateLogout();
1076
+ }
1077
+
1078
+ void Session::doBadCompID(const Message &msg) {
1079
+ generateReject(msg, SessionRejectReason_COMPID_PROBLEM);
1080
+ generateLogout();
1081
+ }
1082
+
1083
+ bool Session::doPossDup(const Message &msg) {
1084
+ OrigSendingTime origSendingTime = m_timestamper();
1085
+
1086
+ const Header &header = msg.getHeader();
1087
+ auto const &msgType = header.getField<MsgType>();
1088
+ auto const &sendingTime = header.getField<SendingTime>();
1089
+
1090
+ if (msgType != MsgType_SequenceReset) {
1091
+ if (!header.getFieldIfSet(origSendingTime)) {
1092
+ generateReject(msg, SessionRejectReason_REQUIRED_TAG_MISSING, origSendingTime.getTag());
1093
+ return false;
1094
+ }
1095
+
1096
+ if (origSendingTime > sendingTime) {
1097
+ generateReject(msg, SessionRejectReason_SENDINGTIME_ACCURACY_PROBLEM);
1098
+ generateLogout();
1099
+ return false;
1100
+ }
1101
+ }
1102
+ return true;
1103
+ }
1104
+
1105
+ bool Session::doTargetTooLow(const Message &msg) {
1106
+ const Header &header = msg.getHeader();
1107
+ PossDupFlag possDupFlag(false);
1108
+ header.getFieldIfSet(possDupFlag);
1109
+ auto const &msgSeqNum = header.getField<MsgSeqNum>();
1110
+
1111
+ if (!possDupFlag) {
1112
+ std::stringstream stream;
1113
+ stream << "MsgSeqNum too low, expecting " << getExpectedTargetNum() << " but received " << msgSeqNum;
1114
+ generateLogout(stream.str());
1115
+ throw std::logic_error(stream.str());
1116
+ }
1117
+
1118
+ return doPossDup(msg);
1119
+ }
1120
+
1121
+ void Session::doTargetTooHigh(const Message &msg) {
1122
+ const Header &header = msg.getHeader();
1123
+ auto const &beginString = header.getField<BeginString>();
1124
+ auto const &msgSeqNum = header.getField<MsgSeqNum>();
1125
+
1126
+ m_state.onEvent(
1127
+ "MsgSeqNum too high, expecting " + SEQNUM_CONVERTOR::convert(getExpectedTargetNum()) + " but received "
1128
+ + SEQNUM_CONVERTOR::convert(msgSeqNum));
1129
+
1130
+ m_state.queue(msgSeqNum, msg);
1131
+
1132
+ if (m_state.resendRequested()) {
1133
+ SessionState::ResendRange range = m_state.resendRange();
1134
+
1135
+ if (!m_sendRedundantResendRequests && msgSeqNum >= range.first) {
1136
+ m_state.onEvent(
1137
+ "Already sent ResendRequest FROM: " + SEQNUM_CONVERTOR::convert(range.first)
1138
+ + " TO: " + SEQNUM_CONVERTOR::convert(range.second) + ". Not sending another.");
1139
+ return;
1140
+ }
1141
+ }
1142
+
1143
+ generateResendRequest(beginString, msgSeqNum);
1144
+ }
1145
+
1146
+ void Session::nextQueued(const UtcTimeStamp &now) {
1147
+ while (nextQueued(getExpectedTargetNum(), now)) {}
1148
+ }
1149
+
1150
+ bool Session::nextQueued(SEQNUM num, const UtcTimeStamp &now) {
1151
+ Message msg;
1152
+
1153
+ if (m_state.retrieve(num, msg)) {
1154
+ m_state.onEvent("Processing QUEUED message: " + SEQNUM_CONVERTOR::convert(num));
1155
+ auto const &msgType = msg.getHeader().getField<MsgType>();
1156
+ if (msgType == MsgType_Logon || msgType == MsgType_ResendRequest) {
1157
+ m_state.incrNextTargetMsgSeqNum();
1158
+ } else {
1159
+ next(msg, now, true);
1160
+ }
1161
+ return true;
1162
+ }
1163
+ return false;
1164
+ }
1165
+
1166
+ void Session::next(const std::string &msg, const UtcTimeStamp &now, bool queued) {
1167
+ try {
1168
+ m_state.onIncoming(msg);
1169
+ const DataDictionary &sessionDD = m_dataDictionaryProvider.getSessionDataDictionary(m_sessionID.getBeginString());
1170
+ if (m_sessionID.isFIXT()) {
1171
+ const DataDictionary &applicationDD
1172
+ = m_dataDictionaryProvider.getApplicationDataDictionary(m_senderDefaultApplVerID);
1173
+ next(Message(msg, sessionDD, applicationDD, m_validateLengthAndChecksum), now, queued);
1174
+ } else {
1175
+ next(Message(msg, sessionDD, m_validateLengthAndChecksum), now, queued);
1176
+ }
1177
+ } catch (InvalidMessage &e) {
1178
+ m_state.onEvent(e.what());
1179
+
1180
+ try {
1181
+ if (identifyType(msg) == MsgType_Logon) {
1182
+ m_state.onEvent("Logon message is not valid");
1183
+ disconnect();
1184
+ }
1185
+ } catch (MessageParseError &) {}
1186
+ throw e;
1187
+ }
1188
+ }
1189
+
1190
+ void Session::next(const Message &message, const UtcTimeStamp &now, bool queued) {
1191
+ const Header &header = message.getHeader();
1192
+
1193
+ try {
1194
+ if (!checkSessionTime(now)) {
1195
+ reset();
1196
+ return;
1197
+ }
1198
+
1199
+ const MsgType &msgType = FIELD_GET_REF(header, MsgType);
1200
+ const BeginString &beginString = FIELD_GET_REF(header, BeginString);
1201
+ // make sure these fields are present
1202
+ FIELD_THROW_IF_NOT_FOUND(header, SenderCompID);
1203
+ FIELD_THROW_IF_NOT_FOUND(header, TargetCompID);
1204
+
1205
+ if (beginString != m_sessionID.getBeginString()) {
1206
+ throw UnsupportedVersion();
1207
+ }
1208
+
1209
+ if (msgType == MsgType_Logon) {
1210
+ if (m_sessionID.isFIXT()) {
1211
+ const DefaultApplVerID &applVerID = FIELD_GET_REF(message, DefaultApplVerID);
1212
+ setTargetDefaultApplVerID(applVerID);
1213
+ } else {
1214
+ setTargetDefaultApplVerID(Message::toApplVerID(beginString));
1215
+ }
1216
+ }
1217
+
1218
+ const DataDictionary &sessionDataDictionary
1219
+ = m_dataDictionaryProvider.getSessionDataDictionary(m_sessionID.getBeginString());
1220
+
1221
+ if (m_sessionID.isFIXT() && message.isApp()) {
1222
+ ApplVerID applVerID = m_targetDefaultApplVerID;
1223
+ header.getFieldIfSet(applVerID);
1224
+ const DataDictionary &applicationDataDictionary
1225
+ = m_dataDictionaryProvider.getApplicationDataDictionary(applVerID);
1226
+ DataDictionary::validate(message, &sessionDataDictionary, &applicationDataDictionary);
1227
+ } else {
1228
+ sessionDataDictionary.validate(message);
1229
+ }
1230
+
1231
+ if (msgType == MsgType_Logon) {
1232
+ nextLogon(message, now);
1233
+ } else if (msgType == MsgType_Heartbeat) {
1234
+ nextHeartbeat(message, now);
1235
+ } else if (msgType == MsgType_TestRequest) {
1236
+ nextTestRequest(message, now);
1237
+ } else if (msgType == MsgType_SequenceReset) {
1238
+ nextSequenceReset(message, now);
1239
+ } else if (msgType == MsgType_Logout) {
1240
+ nextLogout(message, now);
1241
+ } else if (msgType == MsgType_ResendRequest) {
1242
+ nextResendRequest(message, now);
1243
+ } else if (msgType == MsgType_Reject) {
1244
+ nextReject(message, now);
1245
+ } else {
1246
+ if (!verify(message)) {
1247
+ return;
1248
+ }
1249
+ m_state.incrNextTargetMsgSeqNum();
1250
+ }
1251
+ } catch (MessageParseError &e) {
1252
+ m_state.onEvent(e.what());
1253
+ } catch (RequiredTagMissing &e) {
1254
+ LOGEX(generateReject(message, SessionRejectReason_REQUIRED_TAG_MISSING, e.field));
1255
+ } catch (FieldNotFound &e) {
1256
+ if (header.getField(FIELD::BeginString) >= FIX::BeginString_FIX42 && message.isApp()) {
1257
+ LOGEX(generateBusinessReject(message, BusinessRejectReason_CONDITIONALLY_REQUIRED_FIELD_MISSING, e.field));
1258
+ } else {
1259
+ LOGEX(generateReject(message, SessionRejectReason_REQUIRED_TAG_MISSING, e.field));
1260
+ if (header.getField(FIELD::MsgType) == MsgType_Logon) {
1261
+ m_state.onEvent("Required field missing from logon");
1262
+ disconnect();
1263
+ }
1264
+ }
1265
+ } catch (InvalidTagNumber &e) {
1266
+ LOGEX(generateReject(message, SessionRejectReason_INVALID_TAG_NUMBER, e.field));
1267
+ } catch (NoTagValue &e) {
1268
+ LOGEX(generateReject(message, SessionRejectReason_TAG_SPECIFIED_WITHOUT_A_VALUE, e.field));
1269
+ } catch (TagNotDefinedForMessage &e) {
1270
+ LOGEX(generateReject(message, SessionRejectReason_TAG_NOT_DEFINED_FOR_THIS_MESSAGE_TYPE, e.field));
1271
+ } catch (InvalidMessageType &) {
1272
+ LOGEX(generateReject(message, SessionRejectReason_INVALID_MSGTYPE));
1273
+ } catch (UnsupportedMessageType &) {
1274
+ if (header.getField(FIELD::BeginString) >= FIX::BeginString_FIX42) {
1275
+ LOGEX(generateBusinessReject(message, BusinessRejectReason_UNSUPPORTED_MESSAGE_TYPE));
1276
+ } else {
1277
+ LOGEX(generateReject(message, "Unsupported message type"));
1278
+ }
1279
+ } catch (TagOutOfOrder &e) {
1280
+ LOGEX(generateReject(message, SessionRejectReason_TAG_SPECIFIED_OUT_OF_REQUIRED_ORDER, e.field));
1281
+ } catch (IncorrectDataFormat &e) {
1282
+ LOGEX(generateReject(message, SessionRejectReason_INCORRECT_DATA_FORMAT_FOR_VALUE, e.field));
1283
+ } catch (IncorrectTagValue &e) {
1284
+ LOGEX(generateReject(message, SessionRejectReason_VALUE_IS_INCORRECT, e.field));
1285
+ } catch (RepeatedTag &e) {
1286
+ LOGEX(generateReject(message, SessionRejectReason_TAG_APPEARS_MORE_THAN_ONCE, e.field));
1287
+ } catch (RepeatingGroupCountMismatch &e) {
1288
+ LOGEX(generateReject(message, SessionRejectReason_INCORRECT_NUMINGROUP_COUNT_FOR_REPEATING_GROUP, e.field));
1289
+ } catch (InvalidMessage &e) {
1290
+ m_state.onEvent(e.what());
1291
+ } catch (RejectLogon &e) {
1292
+ m_state.onEvent(e.what());
1293
+ generateLogout(e.what());
1294
+ disconnect();
1295
+ } catch (UnsupportedVersion &) {
1296
+ if (header.getField(FIELD::MsgType) == MsgType_Logout) {
1297
+ nextLogout(message, now);
1298
+ } else {
1299
+ generateLogout("Incorrect BeginString");
1300
+ m_state.incrNextTargetMsgSeqNum();
1301
+ }
1302
+ } catch (IOException &e) {
1303
+ m_state.onEvent(e.what());
1304
+ disconnect();
1305
+ }
1306
+
1307
+ if (!queued) {
1308
+ nextQueued(now);
1309
+ }
1310
+
1311
+ if (isLoggedOn()) {
1312
+ next(m_timestamper());
1313
+ }
1314
+ }
1315
+
1316
+ bool Session::sendToTarget(Message &message, const std::string &qualifier) EXCEPT(SessionNotFound) {
1317
+ try {
1318
+ SessionID sessionID = message.getSessionID(qualifier);
1319
+ return sendToTarget(message, sessionID);
1320
+ } catch (FieldNotFound &) {
1321
+ throw SessionNotFound();
1322
+ }
1323
+ }
1324
+
1325
+ bool Session::sendToTarget(Message &message, const SessionID &sessionID) EXCEPT(SessionNotFound) {
1326
+ message.setSessionID(sessionID);
1327
+ Session *pSession = lookupSession(sessionID);
1328
+ if (!pSession) {
1329
+ throw SessionNotFound();
1330
+ }
1331
+ return pSession->send(message);
1332
+ }
1333
+
1334
+ bool Session::sendToTarget(
1335
+ Message &message,
1336
+ const SenderCompID &senderCompID,
1337
+ const TargetCompID &targetCompID,
1338
+ const std::string &qualifier) EXCEPT(SessionNotFound) {
1339
+ message.getHeader().setField(senderCompID);
1340
+ message.getHeader().setField(targetCompID);
1341
+ return sendToTarget(message, qualifier);
1342
+ }
1343
+
1344
+ bool Session::sendToTarget(
1345
+ Message &message,
1346
+ const std::string &sender,
1347
+ const std::string &target,
1348
+ const std::string &qualifier) EXCEPT(SessionNotFound) {
1349
+ return sendToTarget(message, SenderCompID(sender), TargetCompID(target), qualifier);
1350
+ }
1351
+
1352
+ std::set<SessionID> Session::getSessions() { return s_sessionIDs; }
1353
+
1354
+ bool Session::doesSessionExist(const SessionID &sessionID) {
1355
+ Locker locker(s_mutex);
1356
+ return s_sessions.end() != s_sessions.find(sessionID);
1357
+ }
1358
+
1359
+ Session *Session::lookupSession(const SessionID &sessionID) {
1360
+ Locker locker(s_mutex);
1361
+ Sessions::iterator find = s_sessions.find(sessionID);
1362
+ if (find != s_sessions.end()) {
1363
+ return find->second;
1364
+ } else {
1365
+ return nullptr;
1366
+ }
1367
+ }
1368
+
1369
+ Session *Session::lookupSession(const std::string &string, bool reverse) {
1370
+ Message message;
1371
+ if (!message.setStringHeader(string)) {
1372
+ return nullptr;
1373
+ }
1374
+
1375
+ try {
1376
+ const Header &header = message.getHeader();
1377
+ const BeginString &beginString = FIELD_GET_REF(header, BeginString);
1378
+ const SenderCompID &senderCompID = FIELD_GET_REF(header, SenderCompID);
1379
+ const TargetCompID &targetCompID = FIELD_GET_REF(header, TargetCompID);
1380
+
1381
+ if (reverse) {
1382
+ return lookupSession(SessionID(beginString, SenderCompID(targetCompID), TargetCompID(senderCompID)));
1383
+ }
1384
+
1385
+ return lookupSession(SessionID(beginString, senderCompID, targetCompID));
1386
+ } catch (FieldNotFound &) {
1387
+ return nullptr;
1388
+ }
1389
+ }
1390
+
1391
+ bool Session::isSessionRegistered(const SessionID &sessionID) {
1392
+ Locker locker(s_mutex);
1393
+ return s_registered.end() != s_registered.find(sessionID);
1394
+ }
1395
+
1396
+ Session *Session::registerSession(const SessionID &sessionID) {
1397
+ Locker locker(s_mutex);
1398
+ Session *pSession = lookupSession(sessionID);
1399
+ if (pSession == nullptr) {
1400
+ return nullptr;
1401
+ }
1402
+ if (isSessionRegistered(sessionID)) {
1403
+ return nullptr;
1404
+ }
1405
+ s_registered[sessionID] = pSession;
1406
+ return pSession;
1407
+ }
1408
+
1409
+ void Session::unregisterSession(const SessionID &sessionID) {
1410
+ Locker locker(s_mutex);
1411
+ s_registered.erase(sessionID);
1412
+ }
1413
+
1414
+ size_t Session::numSessions() {
1415
+ Locker locker(s_mutex);
1416
+ return s_sessions.size();
1417
+ }
1418
+
1419
+ bool Session::addSession(Session &s) {
1420
+ Locker locker(s_mutex);
1421
+ Sessions::iterator it = s_sessions.find(s.m_sessionID);
1422
+ if (it == s_sessions.end()) {
1423
+ s_sessions[s.m_sessionID] = &s;
1424
+ s_sessionIDs.insert(s.m_sessionID);
1425
+ return true;
1426
+ } else {
1427
+ return false;
1428
+ }
1429
+ }
1430
+
1431
+ void Session::removeSession(Session &s) {
1432
+ Locker locker(s_mutex);
1433
+ s_sessions.erase(s.m_sessionID);
1434
+ s_sessionIDs.erase(s.m_sessionID);
1435
+ s_registered.erase(s.m_sessionID);
1436
+ }
1437
+ } // namespace FIX