quickfix_ruby_ud 2.0.7-x86_64-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.
- checksums.yaml +7 -0
- data/ext/quickfix/Acceptor.cpp +257 -0
- data/ext/quickfix/Acceptor.h +127 -0
- data/ext/quickfix/Allocator.h +9 -0
- data/ext/quickfix/Application.h +137 -0
- data/ext/quickfix/DOMDocument.h +70 -0
- data/ext/quickfix/DataDictionary.cpp +679 -0
- data/ext/quickfix/DataDictionary.h +607 -0
- data/ext/quickfix/DataDictionaryProvider.cpp +66 -0
- data/ext/quickfix/DataDictionaryProvider.h +67 -0
- data/ext/quickfix/DatabaseConnectionID.h +98 -0
- data/ext/quickfix/DatabaseConnectionPool.h +84 -0
- data/ext/quickfix/Dictionary.cpp +157 -0
- data/ext/quickfix/Dictionary.h +89 -0
- data/ext/quickfix/Event.h +89 -0
- data/ext/quickfix/Except.h +39 -0
- data/ext/quickfix/Exceptions.h +257 -0
- data/ext/quickfix/Field.h +654 -0
- data/ext/quickfix/FieldConvertors.cpp +86 -0
- data/ext/quickfix/FieldConvertors.h +800 -0
- data/ext/quickfix/FieldMap.cpp +254 -0
- data/ext/quickfix/FieldMap.h +327 -0
- data/ext/quickfix/FieldNumbers.h +44 -0
- data/ext/quickfix/FieldTypes.cpp +62 -0
- data/ext/quickfix/FieldTypes.h +817 -0
- data/ext/quickfix/Fields.h +30 -0
- data/ext/quickfix/FileLog.cpp +176 -0
- data/ext/quickfix/FileLog.h +110 -0
- data/ext/quickfix/FileStore.cpp +369 -0
- data/ext/quickfix/FileStore.h +131 -0
- data/ext/quickfix/FixCommonFields.h +13 -0
- data/ext/quickfix/FixFieldNumbers.h +6132 -0
- data/ext/quickfix/FixFields.h +6133 -0
- data/ext/quickfix/FixValues.h +5790 -0
- data/ext/quickfix/Group.cpp +44 -0
- data/ext/quickfix/Group.h +78 -0
- data/ext/quickfix/HostDetailsProvider.cpp +79 -0
- data/ext/quickfix/HostDetailsProvider.h +44 -0
- data/ext/quickfix/HtmlBuilder.h +178 -0
- data/ext/quickfix/HttpConnection.cpp +914 -0
- data/ext/quickfix/HttpConnection.h +74 -0
- data/ext/quickfix/HttpMessage.cpp +229 -0
- data/ext/quickfix/HttpMessage.h +112 -0
- data/ext/quickfix/HttpParser.cpp +49 -0
- data/ext/quickfix/HttpParser.h +49 -0
- data/ext/quickfix/HttpServer.cpp +152 -0
- data/ext/quickfix/HttpServer.h +76 -0
- data/ext/quickfix/Initiator.cpp +310 -0
- data/ext/quickfix/Initiator.h +151 -0
- data/ext/quickfix/Log.cpp +71 -0
- data/ext/quickfix/Log.h +254 -0
- data/ext/quickfix/Message.cpp +617 -0
- data/ext/quickfix/Message.h +419 -0
- data/ext/quickfix/MessageCracker.h +171 -0
- data/ext/quickfix/MessageSorters.cpp +101 -0
- data/ext/quickfix/MessageSorters.h +185 -0
- data/ext/quickfix/MessageStore.cpp +182 -0
- data/ext/quickfix/MessageStore.h +164 -0
- data/ext/quickfix/Mutex.h +120 -0
- data/ext/quickfix/MySQLConnection.h +187 -0
- data/ext/quickfix/MySQLLog.cpp +262 -0
- data/ext/quickfix/MySQLLog.h +158 -0
- data/ext/quickfix/MySQLStore.cpp +323 -0
- data/ext/quickfix/MySQLStore.h +161 -0
- data/ext/quickfix/MySQLStubs.h +203 -0
- data/ext/quickfix/NullStore.cpp +40 -0
- data/ext/quickfix/NullStore.h +89 -0
- data/ext/quickfix/OdbcConnection.h +241 -0
- data/ext/quickfix/OdbcLog.cpp +230 -0
- data/ext/quickfix/OdbcLog.h +109 -0
- data/ext/quickfix/OdbcStore.cpp +313 -0
- data/ext/quickfix/OdbcStore.h +124 -0
- data/ext/quickfix/PUGIXML_DOMDocument.cpp +112 -0
- data/ext/quickfix/PUGIXML_DOMDocument.h +81 -0
- data/ext/quickfix/Parser.cpp +111 -0
- data/ext/quickfix/Parser.h +50 -0
- data/ext/quickfix/PostgreSQLConnection.h +163 -0
- data/ext/quickfix/PostgreSQLLog.cpp +263 -0
- data/ext/quickfix/PostgreSQLLog.h +157 -0
- data/ext/quickfix/PostgreSQLStore.cpp +327 -0
- data/ext/quickfix/PostgreSQLStore.h +160 -0
- data/ext/quickfix/PostgreSQLStubs.h +203 -0
- data/ext/quickfix/Queue.h +66 -0
- data/ext/quickfix/QuickfixRuby.cpp +131900 -0
- data/ext/quickfix/QuickfixRuby.h +56 -0
- data/ext/quickfix/Responder.h +41 -0
- data/ext/quickfix/SSLSocketAcceptor.cpp +409 -0
- data/ext/quickfix/SSLSocketAcceptor.h +186 -0
- data/ext/quickfix/SSLSocketConnection.cpp +434 -0
- data/ext/quickfix/SSLSocketConnection.h +221 -0
- data/ext/quickfix/SSLSocketInitiator.cpp +558 -0
- data/ext/quickfix/SSLSocketInitiator.h +203 -0
- data/ext/quickfix/SSLStubs.h +129 -0
- data/ext/quickfix/Session.cpp +1437 -0
- data/ext/quickfix/Session.h +343 -0
- data/ext/quickfix/SessionFactory.cpp +314 -0
- data/ext/quickfix/SessionFactory.h +84 -0
- data/ext/quickfix/SessionID.h +136 -0
- data/ext/quickfix/SessionSettings.cpp +165 -0
- data/ext/quickfix/SessionSettings.h +283 -0
- data/ext/quickfix/SessionState.h +260 -0
- data/ext/quickfix/Settings.cpp +160 -0
- data/ext/quickfix/Settings.h +56 -0
- data/ext/quickfix/SharedArray.h +274 -0
- data/ext/quickfix/SocketAcceptor.cpp +216 -0
- data/ext/quickfix/SocketAcceptor.h +77 -0
- data/ext/quickfix/SocketConnection.cpp +256 -0
- data/ext/quickfix/SocketConnection.h +102 -0
- data/ext/quickfix/SocketConnector.cpp +112 -0
- data/ext/quickfix/SocketConnector.h +76 -0
- data/ext/quickfix/SocketInitiator.cpp +241 -0
- data/ext/quickfix/SocketInitiator.h +76 -0
- data/ext/quickfix/SocketMonitor.h +26 -0
- data/ext/quickfix/SocketMonitor_UNIX.cpp +238 -0
- data/ext/quickfix/SocketMonitor_UNIX.h +101 -0
- data/ext/quickfix/SocketMonitor_WIN32.cpp +248 -0
- data/ext/quickfix/SocketMonitor_WIN32.h +99 -0
- data/ext/quickfix/SocketServer.cpp +163 -0
- data/ext/quickfix/SocketServer.h +100 -0
- data/ext/quickfix/ThreadedSSLSocketAcceptor.cpp +436 -0
- data/ext/quickfix/ThreadedSSLSocketAcceptor.h +209 -0
- data/ext/quickfix/ThreadedSSLSocketConnection.cpp +364 -0
- data/ext/quickfix/ThreadedSSLSocketConnection.h +191 -0
- data/ext/quickfix/ThreadedSSLSocketInitiator.cpp +434 -0
- data/ext/quickfix/ThreadedSSLSocketInitiator.h +193 -0
- data/ext/quickfix/ThreadedSocketAcceptor.cpp +242 -0
- data/ext/quickfix/ThreadedSocketAcceptor.h +95 -0
- data/ext/quickfix/ThreadedSocketConnection.cpp +227 -0
- data/ext/quickfix/ThreadedSocketConnection.h +89 -0
- data/ext/quickfix/ThreadedSocketInitiator.cpp +238 -0
- data/ext/quickfix/ThreadedSocketInitiator.h +78 -0
- data/ext/quickfix/TimeRange.cpp +227 -0
- data/ext/quickfix/TimeRange.h +215 -0
- data/ext/quickfix/Utility.cpp +639 -0
- data/ext/quickfix/Utility.h +255 -0
- data/ext/quickfix/UtilitySSL.cpp +1612 -0
- data/ext/quickfix/UtilitySSL.h +274 -0
- data/ext/quickfix/Values.h +63 -0
- data/ext/quickfix/config-all.h +10 -0
- data/ext/quickfix/config.h +10 -0
- data/ext/quickfix/config_unix.h +178 -0
- data/ext/quickfix/config_windows.h +0 -0
- data/ext/quickfix/dirent_windows.h +838 -0
- data/ext/quickfix/double-conversion/bignum-dtoa.cc +641 -0
- data/ext/quickfix/double-conversion/bignum-dtoa.h +84 -0
- data/ext/quickfix/double-conversion/bignum.cc +766 -0
- data/ext/quickfix/double-conversion/bignum.h +144 -0
- data/ext/quickfix/double-conversion/cached-powers.cc +176 -0
- data/ext/quickfix/double-conversion/cached-powers.h +64 -0
- data/ext/quickfix/double-conversion/diy-fp.cc +57 -0
- data/ext/quickfix/double-conversion/diy-fp.h +118 -0
- data/ext/quickfix/double-conversion/double-conversion.cc +994 -0
- data/ext/quickfix/double-conversion/double-conversion.h +543 -0
- data/ext/quickfix/double-conversion/fast-dtoa.cc +665 -0
- data/ext/quickfix/double-conversion/fast-dtoa.h +88 -0
- data/ext/quickfix/double-conversion/fixed-dtoa.cc +404 -0
- data/ext/quickfix/double-conversion/fixed-dtoa.h +56 -0
- data/ext/quickfix/double-conversion/ieee.h +402 -0
- data/ext/quickfix/double-conversion/strtod.cc +557 -0
- data/ext/quickfix/double-conversion/strtod.h +45 -0
- data/ext/quickfix/double-conversion/utils.h +374 -0
- data/ext/quickfix/extconf.rb +76 -0
- data/ext/quickfix/index.h +37 -0
- data/ext/quickfix/pugiconfig.hpp +77 -0
- data/ext/quickfix/pugixml.cpp +13237 -0
- data/ext/quickfix/pugixml.hpp +1516 -0
- data/ext/quickfix/scope_guard.hpp +215 -0
- data/ext/quickfix/stdint_msvc.h +254 -0
- data/ext/quickfix/strptime.h +7 -0
- data/lib/2.4/quickfix.so +0 -0
- data/lib/2.5/quickfix.so +0 -0
- data/lib/2.6/quickfix.so +0 -0
- data/lib/2.7/quickfix.so +0 -0
- data/lib/3.0/quickfix.so +0 -0
- data/lib/3.1/quickfix.so +0 -0
- data/lib/3.2/quickfix.so +0 -0
- data/lib/3.3/quickfix.so +0 -0
- data/lib/3.4/quickfix.so +0 -0
- data/lib/quickfix40.rb +274 -0
- data/lib/quickfix41.rb +351 -0
- data/lib/quickfix42.rb +1184 -0
- data/lib/quickfix43.rb +3504 -0
- data/lib/quickfix44.rb +14040 -0
- data/lib/quickfix50.rb +20051 -0
- data/lib/quickfix50sp1.rb +23596 -0
- data/lib/quickfix50sp2.rb +412444 -0
- data/lib/quickfix_fields.rb +79393 -0
- data/lib/quickfix_ruby.rb +82 -0
- data/lib/quickfixt11.rb +65 -0
- data/spec/FIX40.xml +862 -0
- data/spec/FIX41.xml +1282 -0
- data/spec/FIX42.xml +2743 -0
- data/spec/FIX43.xml +4230 -0
- data/spec/FIX44.xml +6600 -0
- data/spec/FIX50.xml +8142 -0
- data/spec/FIX50SP1.xml +9506 -0
- data/spec/FIX50SP2.xml +26069 -0
- data/spec/FIXT11.xml +252 -0
- data/test/DataDictionaryTestCase.rb +268 -0
- data/test/DictionaryTestCase.rb +112 -0
- data/test/FieldBaseTestCase.rb +24 -0
- data/test/MessageStoreTestCase.rb +19 -0
- data/test/MessageTestCase.rb +368 -0
- data/test/SessionSettingsTestCase.rb +41 -0
- metadata +247 -0
@@ -0,0 +1,242 @@
|
|
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 "Settings.h"
|
27
|
+
#include "ThreadedSocketAcceptor.h"
|
28
|
+
#include "Utility.h"
|
29
|
+
|
30
|
+
namespace FIX {
|
31
|
+
ThreadedSocketAcceptor::ThreadedSocketAcceptor(
|
32
|
+
Application &application,
|
33
|
+
MessageStoreFactory &factory,
|
34
|
+
const SessionSettings &settings) EXCEPT(ConfigError)
|
35
|
+
: Acceptor(application, factory, settings) {
|
36
|
+
socket_init();
|
37
|
+
}
|
38
|
+
|
39
|
+
ThreadedSocketAcceptor::ThreadedSocketAcceptor(
|
40
|
+
Application &application,
|
41
|
+
MessageStoreFactory &factory,
|
42
|
+
const SessionSettings &settings,
|
43
|
+
LogFactory &logFactory) EXCEPT(ConfigError)
|
44
|
+
: Acceptor(application, factory, settings, logFactory) {
|
45
|
+
socket_init();
|
46
|
+
}
|
47
|
+
|
48
|
+
ThreadedSocketAcceptor::~ThreadedSocketAcceptor() { socket_term(); }
|
49
|
+
|
50
|
+
void ThreadedSocketAcceptor::onConfigure(const SessionSettings &sessionSettings) EXCEPT(ConfigError) {
|
51
|
+
for (const SessionID &sessionID : sessionSettings.getSessions()) {
|
52
|
+
const Dictionary &settings = sessionSettings.get(sessionID);
|
53
|
+
settings.getInt(SOCKET_ACCEPT_PORT);
|
54
|
+
if (settings.has(SOCKET_REUSE_ADDRESS)) {
|
55
|
+
settings.getBool(SOCKET_REUSE_ADDRESS);
|
56
|
+
}
|
57
|
+
if (settings.has(SOCKET_NODELAY)) {
|
58
|
+
settings.getBool(SOCKET_NODELAY);
|
59
|
+
}
|
60
|
+
}
|
61
|
+
}
|
62
|
+
|
63
|
+
void ThreadedSocketAcceptor::onInitialize(const SessionSettings &sessionSettings) EXCEPT(RuntimeError) {
|
64
|
+
short port = 0;
|
65
|
+
std::set<int> ports;
|
66
|
+
|
67
|
+
for (const SessionID &sessionID : sessionSettings.getSessions()) {
|
68
|
+
const Dictionary &settings = sessionSettings.get(sessionID);
|
69
|
+
port = (short)settings.getInt(SOCKET_ACCEPT_PORT);
|
70
|
+
|
71
|
+
m_portToSessions[port].insert(sessionID);
|
72
|
+
|
73
|
+
if (ports.find(port) != ports.end()) {
|
74
|
+
continue;
|
75
|
+
}
|
76
|
+
ports.insert(port);
|
77
|
+
|
78
|
+
const bool reuseAddress = settings.has(SOCKET_REUSE_ADDRESS) ? settings.getBool(SOCKET_REUSE_ADDRESS) : true;
|
79
|
+
|
80
|
+
const bool noDelay = settings.has(SOCKET_NODELAY) ? settings.getBool(SOCKET_NODELAY) : false;
|
81
|
+
|
82
|
+
const int sendBufSize = settings.has(SOCKET_SEND_BUFFER_SIZE) ? settings.getInt(SOCKET_SEND_BUFFER_SIZE) : 0;
|
83
|
+
|
84
|
+
const int rcvBufSize = settings.has(SOCKET_RECEIVE_BUFFER_SIZE) ? settings.getInt(SOCKET_RECEIVE_BUFFER_SIZE) : 0;
|
85
|
+
|
86
|
+
socket_handle socket = socket_createAcceptor(port, reuseAddress);
|
87
|
+
if (socket == INVALID_SOCKET_HANDLE) {
|
88
|
+
SocketException e;
|
89
|
+
socket_close(socket);
|
90
|
+
throw RuntimeError(
|
91
|
+
"Unable to create, bind, or listen to port " + IntConvertor::convert((unsigned short)port) + " (" + e.what()
|
92
|
+
+ ")");
|
93
|
+
}
|
94
|
+
if (noDelay) {
|
95
|
+
socket_setsockopt(socket, TCP_NODELAY);
|
96
|
+
}
|
97
|
+
if (sendBufSize) {
|
98
|
+
socket_setsockopt(socket, SO_SNDBUF, sendBufSize);
|
99
|
+
}
|
100
|
+
if (rcvBufSize) {
|
101
|
+
socket_setsockopt(socket, SO_RCVBUF, rcvBufSize);
|
102
|
+
}
|
103
|
+
|
104
|
+
m_socketToPort[socket] = port;
|
105
|
+
m_sockets.insert(socket);
|
106
|
+
}
|
107
|
+
}
|
108
|
+
|
109
|
+
void ThreadedSocketAcceptor::onStart() {
|
110
|
+
for (const Sockets::value_type &socket : m_sockets) {
|
111
|
+
Locker l(m_mutex);
|
112
|
+
int port = m_socketToPort[socket];
|
113
|
+
AcceptorThreadInfo *info = new AcceptorThreadInfo(this, socket, port);
|
114
|
+
thread_id thread;
|
115
|
+
thread_spawn(&socketAcceptorThread, info, thread);
|
116
|
+
addThread(socket, thread);
|
117
|
+
}
|
118
|
+
}
|
119
|
+
|
120
|
+
bool ThreadedSocketAcceptor::onPoll() { return false; }
|
121
|
+
|
122
|
+
void ThreadedSocketAcceptor::onStop() {
|
123
|
+
SocketToThread threads;
|
124
|
+
SocketToThread::iterator i;
|
125
|
+
|
126
|
+
{
|
127
|
+
Locker l(m_mutex);
|
128
|
+
|
129
|
+
time_t start = 0;
|
130
|
+
time_t now = 0;
|
131
|
+
|
132
|
+
::time(&start);
|
133
|
+
while (isLoggedOn()) {
|
134
|
+
if (::time(&now) - 5 >= start) {
|
135
|
+
break;
|
136
|
+
}
|
137
|
+
}
|
138
|
+
|
139
|
+
threads = m_threads;
|
140
|
+
m_threads.clear();
|
141
|
+
}
|
142
|
+
|
143
|
+
for (i = threads.begin(); i != threads.end(); ++i) {
|
144
|
+
socket_close(i->first);
|
145
|
+
}
|
146
|
+
for (i = threads.begin(); i != threads.end(); ++i) {
|
147
|
+
thread_join(i->second);
|
148
|
+
}
|
149
|
+
}
|
150
|
+
|
151
|
+
void ThreadedSocketAcceptor::addThread(socket_handle s, thread_id t) {
|
152
|
+
Locker l(m_mutex);
|
153
|
+
|
154
|
+
m_threads[s] = t;
|
155
|
+
}
|
156
|
+
|
157
|
+
void ThreadedSocketAcceptor::removeThread(socket_handle s) {
|
158
|
+
Locker l(m_mutex);
|
159
|
+
SocketToThread::iterator i = m_threads.find(s);
|
160
|
+
if (i != m_threads.end()) {
|
161
|
+
thread_detach(i->second);
|
162
|
+
m_threads.erase(i);
|
163
|
+
}
|
164
|
+
}
|
165
|
+
|
166
|
+
THREAD_PROC ThreadedSocketAcceptor::socketAcceptorThread(void *p) {
|
167
|
+
AcceptorThreadInfo *info = reinterpret_cast<AcceptorThreadInfo *>(p);
|
168
|
+
|
169
|
+
ThreadedSocketAcceptor *pAcceptor = info->m_pAcceptor;
|
170
|
+
socket_handle s = info->m_socket;
|
171
|
+
int port = info->m_port;
|
172
|
+
delete info;
|
173
|
+
|
174
|
+
int noDelay = 0;
|
175
|
+
int sendBufSize = 0;
|
176
|
+
int rcvBufSize = 0;
|
177
|
+
socket_getsockopt(s, TCP_NODELAY, noDelay);
|
178
|
+
socket_getsockopt(s, SO_SNDBUF, sendBufSize);
|
179
|
+
socket_getsockopt(s, SO_RCVBUF, rcvBufSize);
|
180
|
+
|
181
|
+
socket_handle socket = 0;
|
182
|
+
while ((!pAcceptor->isStopped() && (socket = socket_accept(s)) != INVALID_SOCKET_HANDLE)) {
|
183
|
+
if (noDelay) {
|
184
|
+
socket_setsockopt(socket, TCP_NODELAY);
|
185
|
+
}
|
186
|
+
if (sendBufSize) {
|
187
|
+
socket_setsockopt(socket, SO_SNDBUF, sendBufSize);
|
188
|
+
}
|
189
|
+
if (rcvBufSize) {
|
190
|
+
socket_setsockopt(socket, SO_RCVBUF, rcvBufSize);
|
191
|
+
}
|
192
|
+
|
193
|
+
Sessions sessions = pAcceptor->m_portToSessions[port];
|
194
|
+
|
195
|
+
ThreadedSocketConnection *pConnection = new ThreadedSocketConnection(socket, sessions, pAcceptor->getLog());
|
196
|
+
|
197
|
+
ConnectionThreadInfo *info = new ConnectionThreadInfo(pAcceptor, pConnection);
|
198
|
+
|
199
|
+
{
|
200
|
+
Locker l(pAcceptor->m_mutex);
|
201
|
+
|
202
|
+
std::stringstream stream;
|
203
|
+
stream << "Accepted connection from " << socket_peername(socket) << " on port " << port;
|
204
|
+
|
205
|
+
if (pAcceptor->getLog()) {
|
206
|
+
pAcceptor->getLog()->onEvent(stream.str());
|
207
|
+
}
|
208
|
+
|
209
|
+
thread_id thread;
|
210
|
+
if (!thread_spawn(&socketConnectionThread, info, thread)) {
|
211
|
+
delete info;
|
212
|
+
delete pConnection;
|
213
|
+
} else {
|
214
|
+
pAcceptor->addThread(socket, thread);
|
215
|
+
}
|
216
|
+
}
|
217
|
+
}
|
218
|
+
|
219
|
+
if (!pAcceptor->isStopped()) {
|
220
|
+
pAcceptor->removeThread(s);
|
221
|
+
}
|
222
|
+
|
223
|
+
return 0;
|
224
|
+
}
|
225
|
+
|
226
|
+
THREAD_PROC ThreadedSocketAcceptor::socketConnectionThread(void *p) {
|
227
|
+
ConnectionThreadInfo *info = reinterpret_cast<ConnectionThreadInfo *>(p);
|
228
|
+
|
229
|
+
ThreadedSocketAcceptor *pAcceptor = info->m_pAcceptor;
|
230
|
+
ThreadedSocketConnection *pConnection = info->m_pConnection;
|
231
|
+
delete info;
|
232
|
+
|
233
|
+
socket_handle socket = pConnection->getSocket();
|
234
|
+
|
235
|
+
while (pConnection->read()) {}
|
236
|
+
delete pConnection;
|
237
|
+
if (!pAcceptor->isStopped()) {
|
238
|
+
pAcceptor->removeThread(socket);
|
239
|
+
}
|
240
|
+
return 0;
|
241
|
+
}
|
242
|
+
} // namespace FIX
|
@@ -0,0 +1,95 @@
|
|
1
|
+
/* -*- C++ -*- */
|
2
|
+
|
3
|
+
/****************************************************************************
|
4
|
+
** Copyright (c) 2001-2014
|
5
|
+
**
|
6
|
+
** This file is part of the QuickFIX FIX Engine
|
7
|
+
**
|
8
|
+
** This file may be distributed under the terms of the quickfixengine.org
|
9
|
+
** license as defined by quickfixengine.org and appearing in the file
|
10
|
+
** LICENSE included in the packaging of this file.
|
11
|
+
**
|
12
|
+
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
13
|
+
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
14
|
+
**
|
15
|
+
** See http://www.quickfixengine.org/LICENSE for licensing information.
|
16
|
+
**
|
17
|
+
** Contact ask@quickfixengine.org if any conditions of this licensing are
|
18
|
+
** not clear to you.
|
19
|
+
**
|
20
|
+
****************************************************************************/
|
21
|
+
|
22
|
+
#ifndef FIX_THREADEDSOCKETACCEPTOR_H
|
23
|
+
#define FIX_THREADEDSOCKETACCEPTOR_H
|
24
|
+
|
25
|
+
#ifdef _MSC_VER
|
26
|
+
#pragma warning(disable : 4503 4355 4786 4290)
|
27
|
+
#endif
|
28
|
+
|
29
|
+
#include "Acceptor.h"
|
30
|
+
#include "Mutex.h"
|
31
|
+
#include "ThreadedSocketConnection.h"
|
32
|
+
|
33
|
+
namespace FIX {
|
34
|
+
/// Threaded Socket implementation of Acceptor.
|
35
|
+
class ThreadedSocketAcceptor : public Acceptor {
|
36
|
+
friend class SocketConnection;
|
37
|
+
|
38
|
+
public:
|
39
|
+
ThreadedSocketAcceptor(Application &, MessageStoreFactory &, const SessionSettings &) EXCEPT(ConfigError);
|
40
|
+
ThreadedSocketAcceptor(Application &, MessageStoreFactory &, const SessionSettings &, LogFactory &)
|
41
|
+
EXCEPT(ConfigError);
|
42
|
+
|
43
|
+
virtual ~ThreadedSocketAcceptor();
|
44
|
+
|
45
|
+
private:
|
46
|
+
struct AcceptorThreadInfo {
|
47
|
+
AcceptorThreadInfo(ThreadedSocketAcceptor *pAcceptor, socket_handle socket, int port)
|
48
|
+
: m_pAcceptor(pAcceptor),
|
49
|
+
m_socket(socket),
|
50
|
+
m_port(port) {}
|
51
|
+
|
52
|
+
ThreadedSocketAcceptor *m_pAcceptor;
|
53
|
+
socket_handle m_socket;
|
54
|
+
int m_port;
|
55
|
+
};
|
56
|
+
|
57
|
+
struct ConnectionThreadInfo {
|
58
|
+
ConnectionThreadInfo(ThreadedSocketAcceptor *pAcceptor, ThreadedSocketConnection *pConnection)
|
59
|
+
: m_pAcceptor(pAcceptor),
|
60
|
+
m_pConnection(pConnection) {}
|
61
|
+
|
62
|
+
ThreadedSocketAcceptor *m_pAcceptor;
|
63
|
+
ThreadedSocketConnection *m_pConnection;
|
64
|
+
};
|
65
|
+
|
66
|
+
bool readSettings(const SessionSettings &);
|
67
|
+
|
68
|
+
typedef std::set<socket_handle> Sockets;
|
69
|
+
typedef std::set<SessionID> Sessions;
|
70
|
+
typedef std::map<int, Sessions> PortToSessions;
|
71
|
+
typedef std::map<socket_handle, int> SocketToPort;
|
72
|
+
typedef std::map<socket_handle, thread_id> SocketToThread;
|
73
|
+
|
74
|
+
void onConfigure(const SessionSettings &) EXCEPT(ConfigError);
|
75
|
+
void onInitialize(const SessionSettings &) EXCEPT(RuntimeError);
|
76
|
+
|
77
|
+
void onStart();
|
78
|
+
bool onPoll();
|
79
|
+
void onStop();
|
80
|
+
|
81
|
+
void addThread(socket_handle s, thread_id t);
|
82
|
+
void removeThread(socket_handle s);
|
83
|
+
static THREAD_PROC socketAcceptorThread(void *p);
|
84
|
+
static THREAD_PROC socketConnectionThread(void *p);
|
85
|
+
|
86
|
+
Sockets m_sockets;
|
87
|
+
PortToSessions m_portToSessions;
|
88
|
+
SocketToPort m_socketToPort;
|
89
|
+
SocketToThread m_threads;
|
90
|
+
Mutex m_mutex;
|
91
|
+
};
|
92
|
+
/*! @} */
|
93
|
+
} // namespace FIX
|
94
|
+
|
95
|
+
#endif // FIX_THREADEDSOCKETACCEPTOR_H
|
@@ -0,0 +1,227 @@
|
|
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
|
+
#include <poll.h>
|
25
|
+
#endif
|
26
|
+
|
27
|
+
#include "Session.h"
|
28
|
+
#include "ThreadedSocketAcceptor.h"
|
29
|
+
#include "ThreadedSocketConnection.h"
|
30
|
+
#include "ThreadedSocketInitiator.h"
|
31
|
+
#include "Utility.h"
|
32
|
+
|
33
|
+
namespace FIX {
|
34
|
+
ThreadedSocketConnection::ThreadedSocketConnection(socket_handle s, Sessions sessions, Log *pLog)
|
35
|
+
: m_socket(s),
|
36
|
+
m_pLog(pLog),
|
37
|
+
m_sessions(sessions),
|
38
|
+
m_pSession(0),
|
39
|
+
m_disconnect(false) {
|
40
|
+
#if _MSC_VER
|
41
|
+
FD_ZERO(&m_fds);
|
42
|
+
FD_SET(m_socket, &m_fds);
|
43
|
+
#endif
|
44
|
+
}
|
45
|
+
|
46
|
+
ThreadedSocketConnection::ThreadedSocketConnection(
|
47
|
+
const SessionID &sessionID,
|
48
|
+
socket_handle s,
|
49
|
+
const std::string &address,
|
50
|
+
short port,
|
51
|
+
Log *pLog,
|
52
|
+
const std::string &sourceAddress,
|
53
|
+
short sourcePort)
|
54
|
+
: m_socket(s),
|
55
|
+
m_address(address),
|
56
|
+
m_port(port),
|
57
|
+
m_sourceAddress(sourceAddress),
|
58
|
+
m_sourcePort(sourcePort),
|
59
|
+
m_pLog(pLog),
|
60
|
+
m_pSession(Session::lookupSession(sessionID)),
|
61
|
+
m_disconnect(false) {
|
62
|
+
#if _MSC_VER
|
63
|
+
FD_ZERO(&m_fds);
|
64
|
+
FD_SET(m_socket, &m_fds);
|
65
|
+
#endif
|
66
|
+
if (m_pSession) {
|
67
|
+
m_pSession->setResponder(this);
|
68
|
+
}
|
69
|
+
}
|
70
|
+
|
71
|
+
ThreadedSocketConnection::~ThreadedSocketConnection() {
|
72
|
+
if (m_pSession) {
|
73
|
+
m_pSession->setResponder(0);
|
74
|
+
Session::unregisterSession(m_pSession->getSessionID());
|
75
|
+
}
|
76
|
+
}
|
77
|
+
|
78
|
+
bool ThreadedSocketConnection::send(const std::string &msg) {
|
79
|
+
ssize_t totalSent = 0;
|
80
|
+
while (totalSent < (int)msg.length()) {
|
81
|
+
ssize_t sent = socket_send(m_socket, msg.c_str() + totalSent, msg.length());
|
82
|
+
if (sent < 0) {
|
83
|
+
return false;
|
84
|
+
}
|
85
|
+
totalSent += sent;
|
86
|
+
}
|
87
|
+
|
88
|
+
return true;
|
89
|
+
}
|
90
|
+
|
91
|
+
bool ThreadedSocketConnection::connect() {
|
92
|
+
// do the bind in the thread as name resolution may block
|
93
|
+
if (!m_sourceAddress.empty() || m_sourcePort) {
|
94
|
+
socket_bind(m_socket, m_sourceAddress.c_str(), m_sourcePort);
|
95
|
+
}
|
96
|
+
|
97
|
+
return socket_connect(getSocket(), m_address.c_str(), m_port) >= 0;
|
98
|
+
}
|
99
|
+
|
100
|
+
void ThreadedSocketConnection::disconnect() {
|
101
|
+
m_disconnect = true;
|
102
|
+
socket_close(m_socket);
|
103
|
+
}
|
104
|
+
|
105
|
+
bool ThreadedSocketConnection::read() {
|
106
|
+
#if _MSC_VER
|
107
|
+
struct timeval timeout = {1, 0};
|
108
|
+
fd_set readset = m_fds;
|
109
|
+
#else
|
110
|
+
int timeout = 1000; // 1000ms = 1 second
|
111
|
+
struct pollfd pfd = {m_socket, POLLIN | POLLPRI, 0};
|
112
|
+
#endif
|
113
|
+
|
114
|
+
try {
|
115
|
+
// Wait for input (1 second timeout)
|
116
|
+
#if _MSC_VER
|
117
|
+
int result = select(0, &readset, 0, 0, &timeout);
|
118
|
+
#else
|
119
|
+
int result = poll(&pfd, 1, timeout);
|
120
|
+
#endif
|
121
|
+
|
122
|
+
if (result > 0) // Something to read
|
123
|
+
{
|
124
|
+
// We can read without blocking
|
125
|
+
ssize_t size = socket_recv(m_socket, m_buffer, sizeof(m_buffer));
|
126
|
+
if (size <= 0) {
|
127
|
+
throw SocketRecvFailed(size);
|
128
|
+
}
|
129
|
+
m_parser.addToStream(m_buffer, size);
|
130
|
+
} else if (result == 0 && m_pSession) // Timeout
|
131
|
+
{
|
132
|
+
m_pSession->next(UtcTimeStamp::now());
|
133
|
+
} else if (result < 0) // Error
|
134
|
+
{
|
135
|
+
throw SocketRecvFailed(result);
|
136
|
+
}
|
137
|
+
|
138
|
+
processStream();
|
139
|
+
return true;
|
140
|
+
} catch (SocketRecvFailed &e) {
|
141
|
+
if (m_disconnect) {
|
142
|
+
return false;
|
143
|
+
}
|
144
|
+
|
145
|
+
if (m_pSession) {
|
146
|
+
m_pSession->getLog()->onEvent(e.what());
|
147
|
+
m_pSession->disconnect();
|
148
|
+
} else {
|
149
|
+
disconnect();
|
150
|
+
}
|
151
|
+
|
152
|
+
return false;
|
153
|
+
}
|
154
|
+
}
|
155
|
+
|
156
|
+
bool ThreadedSocketConnection::readMessage(std::string &msg) EXCEPT(SocketRecvFailed) {
|
157
|
+
try {
|
158
|
+
return m_parser.readFixMessage(msg);
|
159
|
+
} catch (MessageParseError &) {}
|
160
|
+
return true;
|
161
|
+
}
|
162
|
+
|
163
|
+
void ThreadedSocketConnection::processStream() {
|
164
|
+
std::string msg;
|
165
|
+
while (readMessage(msg)) {
|
166
|
+
if (!m_pSession) {
|
167
|
+
if (!setSession(msg)) {
|
168
|
+
disconnect();
|
169
|
+
continue;
|
170
|
+
}
|
171
|
+
}
|
172
|
+
try {
|
173
|
+
m_pSession->next(msg, UtcTimeStamp::now());
|
174
|
+
} catch (InvalidMessage &) {
|
175
|
+
if (!m_pSession->isLoggedOn()) {
|
176
|
+
disconnect();
|
177
|
+
return;
|
178
|
+
}
|
179
|
+
}
|
180
|
+
}
|
181
|
+
}
|
182
|
+
|
183
|
+
bool ThreadedSocketConnection::setSession(const std::string &msg) {
|
184
|
+
m_pSession = Session::lookupSession(msg, true);
|
185
|
+
if (!m_pSession) {
|
186
|
+
if (m_pLog) {
|
187
|
+
m_pLog->onEvent("Session not found for incoming message: " + msg);
|
188
|
+
m_pLog->onIncoming(msg);
|
189
|
+
}
|
190
|
+
return false;
|
191
|
+
}
|
192
|
+
|
193
|
+
SessionID sessionID = m_pSession->getSessionID();
|
194
|
+
m_pSession = 0;
|
195
|
+
|
196
|
+
// see if the session frees up within 5 seconds
|
197
|
+
for (int i = 1; i <= 5; i++) {
|
198
|
+
if (!Session::isSessionRegistered(sessionID)) {
|
199
|
+
m_pSession = Session::registerSession(sessionID);
|
200
|
+
}
|
201
|
+
if (m_pSession) {
|
202
|
+
break;
|
203
|
+
}
|
204
|
+
process_sleep(1);
|
205
|
+
}
|
206
|
+
|
207
|
+
if (!m_pSession) {
|
208
|
+
return false;
|
209
|
+
}
|
210
|
+
if (m_sessions.find(m_pSession->getSessionID()) == m_sessions.end()) {
|
211
|
+
return false;
|
212
|
+
}
|
213
|
+
|
214
|
+
if (m_pSession->isAcceptor()) {
|
215
|
+
std::string remote_address = socket_peername(m_socket);
|
216
|
+
if (!m_pSession->getAllowedRemoteAddresses().empty() && !m_pSession->inAllowedRemoteAddresses(remote_address)) {
|
217
|
+
m_pSession->getLog()->onEvent("Deny connections to the acceptor from " + remote_address);
|
218
|
+
return false;
|
219
|
+
}
|
220
|
+
m_pSession->getLog()->onEvent("Allows connections to the acceptor from " + remote_address);
|
221
|
+
}
|
222
|
+
|
223
|
+
m_pSession->setResponder(this);
|
224
|
+
return true;
|
225
|
+
}
|
226
|
+
|
227
|
+
} // namespace FIX
|
@@ -0,0 +1,89 @@
|
|
1
|
+
/* -*- C++ -*- */
|
2
|
+
|
3
|
+
/****************************************************************************
|
4
|
+
** Copyright (c) 2001-2014
|
5
|
+
**
|
6
|
+
** This file is part of the QuickFIX FIX Engine
|
7
|
+
**
|
8
|
+
** This file may be distributed under the terms of the quickfixengine.org
|
9
|
+
** license as defined by quickfixengine.org and appearing in the file
|
10
|
+
** LICENSE included in the packaging of this file.
|
11
|
+
**
|
12
|
+
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
13
|
+
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
14
|
+
**
|
15
|
+
** See http://www.quickfixengine.org/LICENSE for licensing information.
|
16
|
+
**
|
17
|
+
** Contact ask@quickfixengine.org if any conditions of this licensing are
|
18
|
+
** not clear to you.
|
19
|
+
**
|
20
|
+
****************************************************************************/
|
21
|
+
|
22
|
+
#ifndef FIX_THREADEDSOCKETCONNECTION_H
|
23
|
+
#define FIX_THREADEDSOCKETCONNECTION_H
|
24
|
+
|
25
|
+
#ifdef _MSC_VER
|
26
|
+
#pragma warning(disable : 4503 4355 4786 4290)
|
27
|
+
#endif
|
28
|
+
|
29
|
+
#include "Parser.h"
|
30
|
+
#include "Responder.h"
|
31
|
+
#include "SessionID.h"
|
32
|
+
#include <map>
|
33
|
+
#include <set>
|
34
|
+
|
35
|
+
namespace FIX {
|
36
|
+
class ThreadedSocketAcceptor;
|
37
|
+
class ThreadedSocketInitiator;
|
38
|
+
class Session;
|
39
|
+
class Application;
|
40
|
+
class Log;
|
41
|
+
|
42
|
+
/// Encapsulates a socket file descriptor (multi-threaded).
|
43
|
+
class ThreadedSocketConnection : Responder {
|
44
|
+
public:
|
45
|
+
typedef std::set<SessionID> Sessions;
|
46
|
+
|
47
|
+
ThreadedSocketConnection(socket_handle s, Sessions sessions, Log *pLog);
|
48
|
+
ThreadedSocketConnection(
|
49
|
+
const SessionID &,
|
50
|
+
socket_handle s,
|
51
|
+
const std::string &address,
|
52
|
+
short port,
|
53
|
+
Log *pLog,
|
54
|
+
const std::string &sourceAddress = "",
|
55
|
+
short sourcePort = 0);
|
56
|
+
virtual ~ThreadedSocketConnection();
|
57
|
+
|
58
|
+
Session *getSession() const { return m_pSession; }
|
59
|
+
socket_handle getSocket() const { return m_socket; }
|
60
|
+
bool connect();
|
61
|
+
void disconnect();
|
62
|
+
bool read();
|
63
|
+
|
64
|
+
private:
|
65
|
+
bool readMessage(std::string &msg) EXCEPT(SocketRecvFailed);
|
66
|
+
void processStream();
|
67
|
+
bool send(const std::string &);
|
68
|
+
bool setSession(const std::string &msg);
|
69
|
+
|
70
|
+
socket_handle m_socket;
|
71
|
+
char m_buffer[BUFSIZ];
|
72
|
+
|
73
|
+
std::string m_address;
|
74
|
+
int m_port;
|
75
|
+
std::string m_sourceAddress;
|
76
|
+
int m_sourcePort;
|
77
|
+
|
78
|
+
Log *m_pLog;
|
79
|
+
Parser m_parser;
|
80
|
+
Sessions m_sessions;
|
81
|
+
Session *m_pSession;
|
82
|
+
bool m_disconnect;
|
83
|
+
#if _MSC_VER
|
84
|
+
fd_set m_fds;
|
85
|
+
#endif
|
86
|
+
};
|
87
|
+
} // namespace FIX
|
88
|
+
|
89
|
+
#endif // FIX_THREADEDSOCKETCONNECTION_H
|