quickfix_ruby 1.14.3.1 → 1.15.1
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 +4 -4
- data/ext/quickfix/Acceptor.h +2 -0
- data/ext/quickfix/AtomicCount.h +82 -12
- data/ext/quickfix/DOMDocument.h +9 -7
- data/ext/quickfix/DataDictionary.cpp +77 -14
- data/ext/quickfix/DataDictionary.h +90 -16
- data/ext/quickfix/Dictionary.cpp +1 -2
- data/ext/quickfix/Exceptions.h +3 -5
- data/ext/quickfix/Field.h +83 -32
- data/ext/quickfix/FieldConvertors.cpp +93 -0
- data/ext/quickfix/FieldConvertors.h +129 -275
- data/ext/quickfix/FieldMap.cpp +53 -13
- data/ext/quickfix/FieldMap.h +200 -62
- data/ext/quickfix/FieldTypes.cpp +10 -10
- data/ext/quickfix/FieldTypes.h +293 -44
- data/ext/quickfix/FileLog.cpp +6 -10
- data/ext/quickfix/FileLog.h +4 -10
- data/ext/quickfix/FileStore.cpp +19 -6
- data/ext/quickfix/FileStore.h +4 -0
- data/ext/quickfix/FixFieldNumbers.h +1462 -1461
- data/ext/quickfix/FixFields.h +1462 -1461
- data/ext/quickfix/FixValues.h +3230 -3227
- data/ext/quickfix/HttpConnection.cpp +1 -1
- data/ext/quickfix/Initiator.cpp +7 -1
- data/ext/quickfix/Initiator.h +2 -0
- data/ext/quickfix/Log.h +6 -12
- data/ext/quickfix/Message.cpp +186 -57
- data/ext/quickfix/Message.h +109 -47
- data/ext/quickfix/MySQLConnection.h +1 -1
- data/ext/quickfix/PostgreSQLConnection.h +1 -1
- data/ext/quickfix/QuickfixRuby.cpp +79141 -77959
- data/ext/quickfix/QuickfixRuby.h +1 -1
- data/ext/quickfix/SSLSocketAcceptor.cpp +410 -0
- data/ext/quickfix/SSLSocketAcceptor.h +185 -0
- data/ext/quickfix/SSLSocketConnection.cpp +427 -0
- data/ext/quickfix/SSLSocketConnection.h +206 -0
- data/ext/quickfix/SSLSocketInitiator.cpp +485 -0
- data/ext/quickfix/SSLSocketInitiator.h +196 -0
- data/ext/quickfix/Session.cpp +113 -20
- data/ext/quickfix/Session.h +18 -4
- data/ext/quickfix/SessionFactory.cpp +10 -3
- data/ext/quickfix/SessionSettings.cpp +5 -3
- data/ext/quickfix/SessionSettings.h +97 -5
- data/ext/quickfix/Settings.cpp +72 -2
- data/ext/quickfix/Settings.h +3 -0
- data/ext/quickfix/SharedArray.h +140 -6
- data/ext/quickfix/SocketConnection.cpp +2 -2
- data/ext/quickfix/SocketConnector.cpp +5 -2
- data/ext/quickfix/SocketConnector.h +3 -2
- data/ext/quickfix/SocketInitiator.cpp +28 -4
- data/ext/quickfix/SocketInitiator.h +1 -1
- data/ext/quickfix/SocketMonitor.cpp +5 -5
- data/ext/quickfix/ThreadedSSLSocketAcceptor.cpp +455 -0
- data/ext/quickfix/ThreadedSSLSocketAcceptor.h +217 -0
- data/ext/quickfix/ThreadedSSLSocketConnection.cpp +404 -0
- data/ext/quickfix/ThreadedSSLSocketConnection.h +189 -0
- data/ext/quickfix/ThreadedSSLSocketInitiator.cpp +469 -0
- data/ext/quickfix/ThreadedSSLSocketInitiator.h +201 -0
- data/ext/quickfix/ThreadedSocketAcceptor.cpp +5 -1
- data/ext/quickfix/ThreadedSocketConnection.cpp +8 -2
- data/ext/quickfix/ThreadedSocketConnection.h +4 -1
- data/ext/quickfix/ThreadedSocketInitiator.cpp +24 -4
- data/ext/quickfix/ThreadedSocketInitiator.h +1 -1
- data/ext/quickfix/Utility.cpp +23 -1
- data/ext/quickfix/Utility.h +28 -2
- data/ext/quickfix/UtilitySSL.cpp +1733 -0
- data/ext/quickfix/UtilitySSL.h +277 -0
- data/ext/quickfix/config-all.h +10 -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 +372 -0
- data/ext/quickfix/stdint_msvc.h +254 -0
- data/lib/quickfix44.rb +3329 -10
- data/lib/quickfix50.rb +6649 -81
- data/lib/quickfix50sp1.rb +8054 -142
- data/lib/quickfix50sp2.rb +10900 -234
- data/lib/quickfix_fields.rb +7662 -7649
- data/spec/FIX40.xml +28 -28
- data/spec/FIX41.xml +29 -29
- data/spec/FIX42.xml +47 -47
- data/spec/FIX43.xml +148 -148
- data/spec/FIX44.xml +1078 -1081
- data/spec/FIX50.xml +1292 -1289
- data/spec/FIX50SP1.xml +1811 -1802
- data/spec/FIX50SP2.xml +1948 -1939
- data/spec/FIXT11.xml +5 -8
- data/test/test_FieldBaseTestCase.rb +1 -1
- data/test/test_MessageTestCase.rb +2 -2
- metadata +42 -6
|
@@ -82,7 +82,7 @@ bool SocketConnection::processQueue()
|
|
|
82
82
|
|
|
83
83
|
const std::string& msg = m_sendQueue.front();
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
ssize_t result = socket_send
|
|
86
86
|
( m_socket, msg.c_str() + m_sendLength, msg.length() - m_sendLength );
|
|
87
87
|
|
|
88
88
|
if( result > 0 )
|
|
@@ -197,7 +197,7 @@ bool SocketConnection::isValidSession()
|
|
|
197
197
|
void SocketConnection::readFromSocket()
|
|
198
198
|
throw( SocketRecvFailed )
|
|
199
199
|
{
|
|
200
|
-
ssize_t size =
|
|
200
|
+
ssize_t size = socket_recv( m_socket, m_buffer, sizeof(m_buffer) );
|
|
201
201
|
if( size <= 0 ) throw SocketRecvFailed( size );
|
|
202
202
|
m_parser.addToStream( m_buffer, size );
|
|
203
203
|
}
|
|
@@ -83,7 +83,8 @@ SocketConnector::SocketConnector( int timeout )
|
|
|
83
83
|
: m_monitor( timeout ) {}
|
|
84
84
|
|
|
85
85
|
int SocketConnector::connect( const std::string& address, int port, bool noDelay,
|
|
86
|
-
int sendBufSize, int rcvBufSize
|
|
86
|
+
int sendBufSize, int rcvBufSize,
|
|
87
|
+
const std::string& sourceAddress, int sourcePort)
|
|
87
88
|
{
|
|
88
89
|
int socket = socket_createConnector();
|
|
89
90
|
|
|
@@ -95,6 +96,8 @@ int SocketConnector::connect( const std::string& address, int port, bool noDelay
|
|
|
95
96
|
socket_setsockopt( socket, SO_SNDBUF, sendBufSize );
|
|
96
97
|
if( rcvBufSize )
|
|
97
98
|
socket_setsockopt( socket, SO_RCVBUF, rcvBufSize );
|
|
99
|
+
if ( !sourceAddress.empty() || sourcePort )
|
|
100
|
+
socket_bind( socket, sourceAddress.c_str(), sourcePort );
|
|
98
101
|
m_monitor.addConnect( socket );
|
|
99
102
|
socket_connect( socket, address.c_str(), port );
|
|
100
103
|
}
|
|
@@ -104,7 +107,7 @@ int SocketConnector::connect( const std::string& address, int port, bool noDelay
|
|
|
104
107
|
int SocketConnector::connect( const std::string& address, int port, bool noDelay,
|
|
105
108
|
int sendBufSize, int rcvBufSize, Strategy& strategy )
|
|
106
109
|
{
|
|
107
|
-
int socket = connect( address, port, noDelay, sendBufSize, rcvBufSize );
|
|
110
|
+
int socket = connect( address, port, noDelay, sendBufSize, rcvBufSize, "", 0);
|
|
108
111
|
return socket;
|
|
109
112
|
}
|
|
110
113
|
|
|
@@ -39,8 +39,9 @@ public:
|
|
|
39
39
|
|
|
40
40
|
SocketConnector( int timeout = 0 );
|
|
41
41
|
|
|
42
|
-
int connect( const std::string& address, int port, bool noDelay,
|
|
43
|
-
|
|
42
|
+
int connect( const std::string& address, int port, bool noDelay,
|
|
43
|
+
int sendBufSize, int rcvBufSize,
|
|
44
|
+
const std::string& sourceAddress = "", int sourcePort = 0);
|
|
44
45
|
int connect( const std::string& address, int port, bool noDelay,
|
|
45
46
|
int sendBufSize, int rcvBufSize, Strategy& );
|
|
46
47
|
void block( Strategy& strategy, bool poll = 0, double timeout = 0.0 );
|
|
@@ -134,15 +134,18 @@ void SocketInitiator::doConnect( const SessionID& s, const Dictionary& d )
|
|
|
134
134
|
{
|
|
135
135
|
std::string address;
|
|
136
136
|
short port = 0;
|
|
137
|
+
std::string sourceAddress;
|
|
138
|
+
short sourcePort = 0;
|
|
139
|
+
|
|
137
140
|
Session* session = Session::lookupSession( s );
|
|
138
141
|
if( !session->isSessionTime(UtcTimeStamp()) ) return;
|
|
139
142
|
|
|
140
143
|
Log* log = session->getLog();
|
|
141
144
|
|
|
142
|
-
getHost( s, d, address, port );
|
|
145
|
+
getHost( s, d, address, port, sourceAddress, sourcePort );
|
|
143
146
|
|
|
144
|
-
log->onEvent( "Connecting to " + address + " on port " + IntConvertor::convert((unsigned short)port) );
|
|
145
|
-
int result = m_connector.connect( address, port, m_noDelay, m_sendBufSize, m_rcvBufSize );
|
|
147
|
+
log->onEvent( "Connecting to " + address + " on port " + IntConvertor::convert((unsigned short)port) + " (Source " + sourceAddress + ":" + IntConvertor::convert((unsigned short)sourcePort) + ")");
|
|
148
|
+
int result = m_connector.connect( address, port, m_noDelay, m_sendBufSize, m_rcvBufSize, sourceAddress, sourcePort );
|
|
146
149
|
setPending( s );
|
|
147
150
|
|
|
148
151
|
m_pendingConnections[ result ]
|
|
@@ -229,7 +232,8 @@ void SocketInitiator::onTimeout( SocketConnector& )
|
|
|
229
232
|
}
|
|
230
233
|
|
|
231
234
|
void SocketInitiator::getHost( const SessionID& s, const Dictionary& d,
|
|
232
|
-
std::string& address, short& port
|
|
235
|
+
std::string& address, short& port,
|
|
236
|
+
std::string& sourceAddress, short& sourcePort)
|
|
233
237
|
{
|
|
234
238
|
int num = 0;
|
|
235
239
|
SessionToHostNum::iterator i = m_sessionToHostNum.find( s );
|
|
@@ -243,16 +247,36 @@ void SocketInitiator::getHost( const SessionID& s, const Dictionary& d,
|
|
|
243
247
|
portStream << SOCKET_CONNECT_PORT << num;
|
|
244
248
|
std::string portString = portStream.str();
|
|
245
249
|
|
|
250
|
+
sourcePort = 0;
|
|
251
|
+
sourceAddress.empty();
|
|
252
|
+
|
|
246
253
|
if( d.has(hostString) && d.has(portString) )
|
|
247
254
|
{
|
|
248
255
|
address = d.getString( hostString );
|
|
249
256
|
port = ( short ) d.getInt( portString );
|
|
257
|
+
|
|
258
|
+
std::stringstream sourceHostStream;
|
|
259
|
+
sourceHostStream << SOCKET_CONNECT_SOURCE_HOST << num;
|
|
260
|
+
hostString = sourceHostStream.str();
|
|
261
|
+
if( d.has(hostString) )
|
|
262
|
+
sourceAddress = d.getString( hostString );
|
|
263
|
+
|
|
264
|
+
std::stringstream sourcePortStream;
|
|
265
|
+
sourcePortStream << SOCKET_CONNECT_SOURCE_PORT << num;
|
|
266
|
+
portString = sourcePortStream.str();
|
|
267
|
+
if( d.has(portString) )
|
|
268
|
+
sourcePort = ( short ) d.getInt( portString );
|
|
250
269
|
}
|
|
251
270
|
else
|
|
252
271
|
{
|
|
253
272
|
num = 0;
|
|
254
273
|
address = d.getString( SOCKET_CONNECT_HOST );
|
|
255
274
|
port = ( short ) d.getInt( SOCKET_CONNECT_PORT );
|
|
275
|
+
|
|
276
|
+
if( d.has(SOCKET_CONNECT_SOURCE_HOST) )
|
|
277
|
+
sourceAddress = d.getString( SOCKET_CONNECT_SOURCE_HOST );
|
|
278
|
+
if( d.has(SOCKET_CONNECT_SOURCE_PORT) )
|
|
279
|
+
sourcePort = ( short ) d.getInt( SOCKET_CONNECT_SOURCE_PORT );
|
|
256
280
|
}
|
|
257
281
|
|
|
258
282
|
m_sessionToHostNum[ s ] = ++num;
|
|
@@ -62,7 +62,7 @@ private:
|
|
|
62
62
|
void onError( SocketConnector& );
|
|
63
63
|
void onTimeout( SocketConnector& );
|
|
64
64
|
|
|
65
|
-
void getHost( const SessionID&, const Dictionary&, std::string&, short& );
|
|
65
|
+
void getHost( const SessionID&, const Dictionary&, std::string&, short&, std::string&, short& );
|
|
66
66
|
|
|
67
67
|
SessionSettings m_settings;
|
|
68
68
|
SessionToHostNum m_sessionToHostNum;
|
|
@@ -133,17 +133,17 @@ inline timeval* SocketMonitor::getTimeval( bool poll, double timeout )
|
|
|
133
133
|
m_timeval.tv_sec = timeout;
|
|
134
134
|
return &m_timeval;
|
|
135
135
|
#else
|
|
136
|
-
double elapsed = ( double ) ( clock() - m_ticks ) / ( double ) CLOCKS_PER_SEC;
|
|
136
|
+
double elapsed = ( double ) ( clock() - m_ticks ) / ( double ) CLOCKS_PER_SEC;
|
|
137
137
|
if ( elapsed >= timeout || elapsed == 0.0 )
|
|
138
138
|
{
|
|
139
139
|
m_ticks = clock();
|
|
140
140
|
m_timeval.tv_sec = 0;
|
|
141
|
-
m_timeval.tv_usec = (timeout * 1000000);
|
|
141
|
+
m_timeval.tv_usec = (long)(timeout * 1000000);
|
|
142
142
|
}
|
|
143
143
|
else
|
|
144
144
|
{
|
|
145
145
|
m_timeval.tv_sec = 0;
|
|
146
|
-
m_timeval.tv_usec = ( ( timeout - elapsed ) * 1000000 );
|
|
146
|
+
m_timeval.tv_usec = (long)( ( timeout - elapsed ) * 1000000 );
|
|
147
147
|
}
|
|
148
148
|
return &m_timeval;
|
|
149
149
|
#endif
|
|
@@ -233,7 +233,7 @@ void SocketMonitor::processReadSet( Strategy& strategy, fd_set& readSet )
|
|
|
233
233
|
if( s == m_interrupt )
|
|
234
234
|
{
|
|
235
235
|
int socket = 0;
|
|
236
|
-
|
|
236
|
+
socket_recv( s, (char*)&socket, sizeof(socket) );
|
|
237
237
|
addWrite( socket );
|
|
238
238
|
}
|
|
239
239
|
else
|
|
@@ -252,7 +252,7 @@ void SocketMonitor::processReadSet( Strategy& strategy, fd_set& readSet )
|
|
|
252
252
|
if( s == m_interrupt )
|
|
253
253
|
{
|
|
254
254
|
int socket = 0;
|
|
255
|
-
|
|
255
|
+
socket_recv( s, (char*)&socket, sizeof(socket) );
|
|
256
256
|
addWrite( socket );
|
|
257
257
|
}
|
|
258
258
|
else
|
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
/* ====================================================================
|
|
2
|
+
* Copyright (c) 1998-2006 Ralf S. Engelschall. All rights reserved.
|
|
3
|
+
*
|
|
4
|
+
* Redistribution and use in source and binary forms, with or without
|
|
5
|
+
* modification, are permitted provided that the following conditions
|
|
6
|
+
* are met:
|
|
7
|
+
*
|
|
8
|
+
* 1. Redistributions of source code must retain the above copyright
|
|
9
|
+
* notice, this list of conditions and the following disclaimer.
|
|
10
|
+
*
|
|
11
|
+
* 2. Redistributions in binary form must reproduce the above copyright
|
|
12
|
+
* notice, this list of conditions and the following
|
|
13
|
+
* disclaimer in the documentation and/or other materials
|
|
14
|
+
* provided with the distribution.
|
|
15
|
+
*
|
|
16
|
+
* 3. All advertising materials mentioning features or use of this
|
|
17
|
+
* software must display the following acknowledgment:
|
|
18
|
+
* "This product includes software developed by
|
|
19
|
+
* Ralf S. Engelschall <rse@engelschall.com> for use in the
|
|
20
|
+
* mod_ssl project (http://www.modssl.org/)."
|
|
21
|
+
*
|
|
22
|
+
* 4. The names "mod_ssl" must not be used to endorse or promote
|
|
23
|
+
* products derived from this software without prior written
|
|
24
|
+
* permission. For written permission, please contact
|
|
25
|
+
* rse@engelschall.com.
|
|
26
|
+
*
|
|
27
|
+
* 5. Products derived from this software may not be called "mod_ssl"
|
|
28
|
+
* nor may "mod_ssl" appear in their names without prior
|
|
29
|
+
* written permission of Ralf S. Engelschall.
|
|
30
|
+
*
|
|
31
|
+
* 6. Redistributions of any form whatsoever must retain the following
|
|
32
|
+
* acknowledgment:
|
|
33
|
+
* "This product includes software developed by
|
|
34
|
+
* Ralf S. Engelschall <rse@engelschall.com> for use in the
|
|
35
|
+
* mod_ssl project (http://www.modssl.org/)."
|
|
36
|
+
*
|
|
37
|
+
* THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
|
|
38
|
+
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
39
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
40
|
+
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
|
|
41
|
+
* HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
42
|
+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
43
|
+
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
44
|
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
45
|
+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
46
|
+
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
47
|
+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
|
48
|
+
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
49
|
+
* ====================================================================
|
|
50
|
+
*/
|
|
51
|
+
|
|
52
|
+
/* ====================================================================
|
|
53
|
+
* Copyright (c) 1995-1999 Ben Laurie. All rights reserved.
|
|
54
|
+
*
|
|
55
|
+
* Redistribution and use in source and binary forms, with or without
|
|
56
|
+
* modification, are permitted provided that the following conditions
|
|
57
|
+
* are met:
|
|
58
|
+
*
|
|
59
|
+
* 1. Redistributions of source code must retain the above copyright
|
|
60
|
+
* notice, this list of conditions and the following disclaimer.
|
|
61
|
+
*
|
|
62
|
+
* 2. Redistributions in binary form must reproduce the above copyright
|
|
63
|
+
* notice, this list of conditions and the following disclaimer in
|
|
64
|
+
* the documentation and/or other materials provided with the
|
|
65
|
+
* distribution.
|
|
66
|
+
*
|
|
67
|
+
* 3. All advertising materials mentioning features or use of this
|
|
68
|
+
* software must display the following acknowledgment:
|
|
69
|
+
* "This product includes software developed by Ben Laurie
|
|
70
|
+
* for use in the Apache-SSL HTTP server project."
|
|
71
|
+
*
|
|
72
|
+
* 4. The name "Apache-SSL Server" must not be used to
|
|
73
|
+
* endorse or promote products derived from this software without
|
|
74
|
+
* prior written permission.
|
|
75
|
+
*
|
|
76
|
+
* 5. Redistributions of any form whatsoever must retain the following
|
|
77
|
+
* acknowledgment:
|
|
78
|
+
* "This product includes software developed by Ben Laurie
|
|
79
|
+
* for use in the Apache-SSL HTTP server project."
|
|
80
|
+
*
|
|
81
|
+
* THIS SOFTWARE IS PROVIDED BY BEN LAURIE ``AS IS'' AND ANY
|
|
82
|
+
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
83
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
84
|
+
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BEN LAURIE OR
|
|
85
|
+
* HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
86
|
+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
87
|
+
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
88
|
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
89
|
+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
90
|
+
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
91
|
+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
|
92
|
+
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
93
|
+
* ====================================================================
|
|
94
|
+
*/
|
|
95
|
+
|
|
96
|
+
/****************************************************************************
|
|
97
|
+
** Copyright (c) 2001-2014
|
|
98
|
+
**
|
|
99
|
+
** This file is part of the QuickFIX FIX Engine
|
|
100
|
+
**
|
|
101
|
+
** This file may be distributed under the terms of the quickfixengine.org
|
|
102
|
+
** license as defined by quickfixengine.org and appearing in the file
|
|
103
|
+
** LICENSE included in the packaging of this file.
|
|
104
|
+
**
|
|
105
|
+
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
|
106
|
+
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
107
|
+
**
|
|
108
|
+
** See http://www.quickfixengine.org/LICENSE for licensing information.
|
|
109
|
+
**
|
|
110
|
+
** Contact ask@quickfixengine.org if any conditions of this licensing are
|
|
111
|
+
** not clear to you.
|
|
112
|
+
**
|
|
113
|
+
****************************************************************************/
|
|
114
|
+
|
|
115
|
+
#ifdef _MSC_VER
|
|
116
|
+
#include "stdafx.h"
|
|
117
|
+
#else
|
|
118
|
+
#include "config.h"
|
|
119
|
+
#endif
|
|
120
|
+
|
|
121
|
+
#if (HAVE_SSL > 0)
|
|
122
|
+
|
|
123
|
+
#include "ThreadedSSLSocketAcceptor.h"
|
|
124
|
+
#include "Settings.h"
|
|
125
|
+
#include "Utility.h"
|
|
126
|
+
|
|
127
|
+
namespace FIX
|
|
128
|
+
{
|
|
129
|
+
|
|
130
|
+
FIX::ThreadedSSLSocketAcceptor *acceptObjT = 0;
|
|
131
|
+
|
|
132
|
+
int ThreadedSSLSocketAcceptor::passPhraseHandleCB(char *buf, int bufsize, int verify, void *job)
|
|
133
|
+
{
|
|
134
|
+
return acceptObjT->passwordHandleCallback(buf, bufsize, verify, job);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
ThreadedSSLSocketAcceptor::ThreadedSSLSocketAcceptor(
|
|
138
|
+
Application &application, MessageStoreFactory &factory,
|
|
139
|
+
const SessionSettings &settings) throw(ConfigError)
|
|
140
|
+
: Acceptor(application, factory, settings), m_sslInit(false),
|
|
141
|
+
m_verify(SSL_CLIENT_VERIFY_NOTSET), m_ctx(0), m_revocationStore(0)
|
|
142
|
+
{
|
|
143
|
+
socket_init();
|
|
144
|
+
acceptObjT = this;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
ThreadedSSLSocketAcceptor::ThreadedSSLSocketAcceptor(
|
|
148
|
+
Application &application, MessageStoreFactory &factory,
|
|
149
|
+
const SessionSettings &settings, LogFactory &logFactory) throw(ConfigError)
|
|
150
|
+
: Acceptor(application, factory, settings, logFactory), m_sslInit(false),
|
|
151
|
+
m_verify(SSL_CLIENT_VERIFY_NOTSET), m_ctx(0), m_revocationStore(0)
|
|
152
|
+
{
|
|
153
|
+
socket_init();
|
|
154
|
+
acceptObjT = this;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
ThreadedSSLSocketAcceptor::~ThreadedSSLSocketAcceptor()
|
|
158
|
+
{
|
|
159
|
+
if (m_sslInit)
|
|
160
|
+
{
|
|
161
|
+
SSL_CTX_free(m_ctx);
|
|
162
|
+
m_ctx = 0;
|
|
163
|
+
ssl_term();
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
socket_term();
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
void ThreadedSSLSocketAcceptor::onConfigure(const SessionSettings &s) throw(
|
|
170
|
+
ConfigError)
|
|
171
|
+
{
|
|
172
|
+
std::set< SessionID > sessions = s.getSessions();
|
|
173
|
+
std::set< SessionID >::iterator i;
|
|
174
|
+
for (i = sessions.begin(); i != sessions.end(); ++i)
|
|
175
|
+
{
|
|
176
|
+
const Dictionary &settings = s.get(*i);
|
|
177
|
+
settings.getInt(SOCKET_ACCEPT_PORT);
|
|
178
|
+
if (settings.has(SOCKET_REUSE_ADDRESS))
|
|
179
|
+
settings.getBool(SOCKET_REUSE_ADDRESS);
|
|
180
|
+
if (settings.has(SOCKET_NODELAY))
|
|
181
|
+
settings.getBool(SOCKET_NODELAY);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
void ThreadedSSLSocketAcceptor::onInitialize(const SessionSettings &s) throw(
|
|
186
|
+
RuntimeError)
|
|
187
|
+
{
|
|
188
|
+
if (!m_sslInit)
|
|
189
|
+
{
|
|
190
|
+
|
|
191
|
+
ssl_init();
|
|
192
|
+
|
|
193
|
+
std::string errStr;
|
|
194
|
+
|
|
195
|
+
/* set up the application context */
|
|
196
|
+
if ((m_ctx = createSSLContext(true, m_settings, errStr)) == 0)
|
|
197
|
+
{
|
|
198
|
+
ssl_term();
|
|
199
|
+
throw RuntimeError(errStr);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (!loadSSLCert(m_ctx, true, m_settings, getLog(), ThreadedSSLSocketAcceptor::passPhraseHandleCB, errStr))
|
|
203
|
+
{
|
|
204
|
+
ssl_term();
|
|
205
|
+
throw RuntimeError(errStr);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (!loadCAInfo(m_ctx, true, m_settings, getLog(), errStr, m_verify))
|
|
209
|
+
{
|
|
210
|
+
ssl_term();
|
|
211
|
+
throw RuntimeError(errStr);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
m_revocationStore = loadCRLInfo(m_ctx, m_settings, getLog(), errStr);
|
|
215
|
+
if (!m_revocationStore && !errStr.empty())
|
|
216
|
+
{
|
|
217
|
+
ssl_term();
|
|
218
|
+
throw RuntimeError(errStr);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
m_sslInit = true;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
short port = 0;
|
|
225
|
+
std::set< int > ports;
|
|
226
|
+
|
|
227
|
+
std::set< SessionID > sessions = s.getSessions();
|
|
228
|
+
std::set< SessionID >::iterator i = sessions.begin();
|
|
229
|
+
for (; i != sessions.end(); ++i)
|
|
230
|
+
{
|
|
231
|
+
const Dictionary &settings = s.get(*i);
|
|
232
|
+
port = (short)settings.getInt(SOCKET_ACCEPT_PORT);
|
|
233
|
+
|
|
234
|
+
m_portToSessions[port].insert(*i);
|
|
235
|
+
|
|
236
|
+
if (ports.find(port) != ports.end())
|
|
237
|
+
continue;
|
|
238
|
+
ports.insert(port);
|
|
239
|
+
|
|
240
|
+
const bool reuseAddress = settings.has(SOCKET_REUSE_ADDRESS)
|
|
241
|
+
? settings.getBool(SOCKET_REUSE_ADDRESS)
|
|
242
|
+
: true;
|
|
243
|
+
|
|
244
|
+
const bool noDelay =
|
|
245
|
+
settings.has(SOCKET_NODELAY) ? settings.getBool(SOCKET_NODELAY) : false;
|
|
246
|
+
|
|
247
|
+
const int sendBufSize = settings.has(SOCKET_SEND_BUFFER_SIZE)
|
|
248
|
+
? settings.getInt(SOCKET_SEND_BUFFER_SIZE)
|
|
249
|
+
: 0;
|
|
250
|
+
|
|
251
|
+
const int rcvBufSize = settings.has(SOCKET_RECEIVE_BUFFER_SIZE)
|
|
252
|
+
? settings.getInt(SOCKET_RECEIVE_BUFFER_SIZE)
|
|
253
|
+
: 0;
|
|
254
|
+
|
|
255
|
+
int socket = socket_createAcceptor(port, reuseAddress);
|
|
256
|
+
if (socket < 0)
|
|
257
|
+
{
|
|
258
|
+
SocketException e;
|
|
259
|
+
socket_close(socket);
|
|
260
|
+
throw RuntimeError("Unable to create, bind, or listen to port " +
|
|
261
|
+
IntConvertor::convert((unsigned short)port) + " (" +
|
|
262
|
+
e.what() + ")");
|
|
263
|
+
}
|
|
264
|
+
if (noDelay)
|
|
265
|
+
socket_setsockopt(socket, TCP_NODELAY);
|
|
266
|
+
if (sendBufSize)
|
|
267
|
+
socket_setsockopt(socket, SO_SNDBUF, sendBufSize);
|
|
268
|
+
if (rcvBufSize)
|
|
269
|
+
socket_setsockopt(socket, SO_RCVBUF, rcvBufSize);
|
|
270
|
+
|
|
271
|
+
m_socketToPort[socket] = port;
|
|
272
|
+
m_sockets.insert(socket);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
void ThreadedSSLSocketAcceptor::onStart()
|
|
277
|
+
{
|
|
278
|
+
Sockets::iterator i;
|
|
279
|
+
for (i = m_sockets.begin(); i != m_sockets.end(); ++i)
|
|
280
|
+
{
|
|
281
|
+
Locker l(m_mutex);
|
|
282
|
+
int port = m_socketToPort[*i];
|
|
283
|
+
AcceptorThreadInfo *info = new AcceptorThreadInfo(this, *i, port);
|
|
284
|
+
thread_id thread;
|
|
285
|
+
thread_spawn(&socketAcceptorThread, info, thread);
|
|
286
|
+
addThread(SocketKey(*i, 0), thread);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
bool ThreadedSSLSocketAcceptor::onPoll(double timeout) { return false; }
|
|
291
|
+
|
|
292
|
+
void ThreadedSSLSocketAcceptor::onStop()
|
|
293
|
+
{
|
|
294
|
+
SocketToThread threads;
|
|
295
|
+
SocketToThread::iterator i;
|
|
296
|
+
|
|
297
|
+
{
|
|
298
|
+
Locker l(m_mutex);
|
|
299
|
+
|
|
300
|
+
time_t start = 0;
|
|
301
|
+
time_t now = 0;
|
|
302
|
+
|
|
303
|
+
::time(&start);
|
|
304
|
+
while (isLoggedOn())
|
|
305
|
+
{
|
|
306
|
+
if (::time(&now) - 5 >= start)
|
|
307
|
+
break;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
threads = m_threads;
|
|
311
|
+
m_threads.clear();
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
for (i = threads.begin(); i != threads.end(); ++i)
|
|
315
|
+
ssl_socket_close(i->first.first, i->first.second);
|
|
316
|
+
for (i = threads.begin(); i != threads.end(); ++i)
|
|
317
|
+
{
|
|
318
|
+
thread_join(i->second);
|
|
319
|
+
if (i->first.second != 0)
|
|
320
|
+
SSL_free(i->first.second);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
void ThreadedSSLSocketAcceptor::addThread(SocketKey s, thread_id t)
|
|
325
|
+
{
|
|
326
|
+
Locker l(m_mutex);
|
|
327
|
+
|
|
328
|
+
m_threads[s] = t;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
void ThreadedSSLSocketAcceptor::removeThread(SocketKey s)
|
|
332
|
+
{
|
|
333
|
+
Locker l(m_mutex);
|
|
334
|
+
SocketToThread::iterator i = m_threads.find(s);
|
|
335
|
+
if (i != m_threads.end())
|
|
336
|
+
{
|
|
337
|
+
thread_detach(i->second);
|
|
338
|
+
if (i->first.second != 0)
|
|
339
|
+
SSL_free(i->first.second);
|
|
340
|
+
m_threads.erase(i);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
THREAD_PROC ThreadedSSLSocketAcceptor::socketAcceptorThread(void *p)
|
|
345
|
+
{
|
|
346
|
+
AcceptorThreadInfo *info = reinterpret_cast< AcceptorThreadInfo * >(p);
|
|
347
|
+
|
|
348
|
+
ThreadedSSLSocketAcceptor *pAcceptor = info->m_pAcceptor;
|
|
349
|
+
int s = info->m_socket;
|
|
350
|
+
int port = info->m_port;
|
|
351
|
+
delete info;
|
|
352
|
+
|
|
353
|
+
int noDelay = 0;
|
|
354
|
+
int sendBufSize = 0;
|
|
355
|
+
int rcvBufSize = 0;
|
|
356
|
+
socket_getsockopt(s, TCP_NODELAY, noDelay);
|
|
357
|
+
socket_getsockopt(s, SO_SNDBUF, sendBufSize);
|
|
358
|
+
socket_getsockopt(s, SO_RCVBUF, rcvBufSize);
|
|
359
|
+
|
|
360
|
+
int socket = 0;
|
|
361
|
+
while ((!pAcceptor->isStopped() && (socket = socket_accept(s)) >= 0))
|
|
362
|
+
{
|
|
363
|
+
if (noDelay)
|
|
364
|
+
socket_setsockopt(socket, TCP_NODELAY);
|
|
365
|
+
if (sendBufSize)
|
|
366
|
+
socket_setsockopt(socket, SO_SNDBUF, sendBufSize);
|
|
367
|
+
if (rcvBufSize)
|
|
368
|
+
socket_setsockopt(socket, SO_RCVBUF, rcvBufSize);
|
|
369
|
+
|
|
370
|
+
Sessions sessions = pAcceptor->m_portToSessions[port];
|
|
371
|
+
|
|
372
|
+
SSL *ssl = SSL_new(pAcceptor->sslContext());
|
|
373
|
+
ThreadedSSLSocketConnection *pConnection = new ThreadedSSLSocketConnection(
|
|
374
|
+
socket, ssl, sessions, pAcceptor->getLog());
|
|
375
|
+
SSL_clear(ssl);
|
|
376
|
+
BIO *sBio = BIO_new_socket(socket, BIO_CLOSE);
|
|
377
|
+
SSL_set_bio(ssl, sBio, sBio);
|
|
378
|
+
// TODO - check this
|
|
379
|
+
SSL_set_app_data(ssl, pAcceptor->revocationStore());
|
|
380
|
+
SSL_set_verify_result(ssl, X509_V_OK);
|
|
381
|
+
|
|
382
|
+
ConnectionThreadInfo *info =
|
|
383
|
+
new ConnectionThreadInfo(pAcceptor, pConnection);
|
|
384
|
+
|
|
385
|
+
{
|
|
386
|
+
Locker l(pAcceptor->m_mutex);
|
|
387
|
+
|
|
388
|
+
std::stringstream stream;
|
|
389
|
+
stream << "Accepted connection from " << socket_peername(socket)
|
|
390
|
+
<< " on port " << port;
|
|
391
|
+
|
|
392
|
+
if (pAcceptor->getLog())
|
|
393
|
+
pAcceptor->getLog()->onEvent(stream.str());
|
|
394
|
+
|
|
395
|
+
thread_id thread;
|
|
396
|
+
if (!thread_spawn(&socketConnectionThread, info, thread))
|
|
397
|
+
{
|
|
398
|
+
delete info;
|
|
399
|
+
delete pConnection;
|
|
400
|
+
SSL_free(ssl);
|
|
401
|
+
}
|
|
402
|
+
else
|
|
403
|
+
pAcceptor->addThread(SocketKey(socket, ssl), thread);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
if (!pAcceptor->isStopped())
|
|
408
|
+
pAcceptor->removeThread(SocketKey(s, 0));
|
|
409
|
+
|
|
410
|
+
return 0;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
THREAD_PROC ThreadedSSLSocketAcceptor::socketConnectionThread(void *p)
|
|
414
|
+
{
|
|
415
|
+
ConnectionThreadInfo *info = reinterpret_cast< ConnectionThreadInfo * >(p);
|
|
416
|
+
|
|
417
|
+
ThreadedSSLSocketAcceptor *pAcceptor = info->m_pAcceptor;
|
|
418
|
+
ThreadedSSLSocketConnection *pConnection = info->m_pConnection;
|
|
419
|
+
delete info;
|
|
420
|
+
|
|
421
|
+
int socket = pConnection->getSocket();
|
|
422
|
+
|
|
423
|
+
if (acceptSSLConnection(pConnection->getSocket(), pConnection->sslObject(), pAcceptor->getLog(), pAcceptor->m_verify) != 0)
|
|
424
|
+
{
|
|
425
|
+
if (pAcceptor->getLog())
|
|
426
|
+
pAcceptor->getLog()->onEvent("Failed to accept new SSL connection");
|
|
427
|
+
SSL *ssl = pConnection->sslObject();
|
|
428
|
+
delete pConnection;
|
|
429
|
+
if (!pAcceptor->isStopped())
|
|
430
|
+
pAcceptor->removeThread(SocketKey(socket, ssl));
|
|
431
|
+
return 0;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
while (pConnection->read())
|
|
435
|
+
{
|
|
436
|
+
}
|
|
437
|
+
SSL *ssl = pConnection->sslObject();
|
|
438
|
+
delete pConnection;
|
|
439
|
+
if (!pAcceptor->isStopped())
|
|
440
|
+
pAcceptor->removeThread(SocketKey(socket, ssl));
|
|
441
|
+
return 0;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
int ThreadedSSLSocketAcceptor::passwordHandleCallback(char *buf, size_t bufsize,
|
|
445
|
+
int verify, void *job)
|
|
446
|
+
{
|
|
447
|
+
if (m_password.length() > bufsize)
|
|
448
|
+
return -1;
|
|
449
|
+
|
|
450
|
+
std::strcpy(buf, m_password.c_str());
|
|
451
|
+
return m_password.length();
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
#endif
|