quickfix_ruby 1.14.3

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 (149) hide show
  1. checksums.yaml +7 -0
  2. data/ext/quickfix/Acceptor.cpp +248 -0
  3. data/ext/quickfix/Acceptor.h +127 -0
  4. data/ext/quickfix/Allocator.h +9 -0
  5. data/ext/quickfix/Application.h +127 -0
  6. data/ext/quickfix/AtomicCount.h +109 -0
  7. data/ext/quickfix/DOMDocument.h +74 -0
  8. data/ext/quickfix/DataDictionary.cpp +618 -0
  9. data/ext/quickfix/DataDictionary.h +539 -0
  10. data/ext/quickfix/DataDictionaryProvider.cpp +71 -0
  11. data/ext/quickfix/DataDictionaryProvider.h +70 -0
  12. data/ext/quickfix/DatabaseConnectionID.h +105 -0
  13. data/ext/quickfix/DatabaseConnectionPool.h +91 -0
  14. data/ext/quickfix/Dictionary.cpp +162 -0
  15. data/ext/quickfix/Dictionary.h +94 -0
  16. data/ext/quickfix/Event.h +95 -0
  17. data/ext/quickfix/Exceptions.h +299 -0
  18. data/ext/quickfix/Field.h +672 -0
  19. data/ext/quickfix/FieldConvertors.h +863 -0
  20. data/ext/quickfix/FieldMap.cpp +238 -0
  21. data/ext/quickfix/FieldMap.h +244 -0
  22. data/ext/quickfix/FieldNumbers.h +46 -0
  23. data/ext/quickfix/FieldTypes.cpp +64 -0
  24. data/ext/quickfix/FieldTypes.h +698 -0
  25. data/ext/quickfix/Fields.h +31 -0
  26. data/ext/quickfix/FileLog.cpp +200 -0
  27. data/ext/quickfix/FileLog.h +112 -0
  28. data/ext/quickfix/FileStore.cpp +332 -0
  29. data/ext/quickfix/FileStore.h +129 -0
  30. data/ext/quickfix/FixFieldNumbers.h +1537 -0
  31. data/ext/quickfix/FixFields.h +1538 -0
  32. data/ext/quickfix/FixValues.h +3281 -0
  33. data/ext/quickfix/FlexLexer.h +188 -0
  34. data/ext/quickfix/Group.cpp +64 -0
  35. data/ext/quickfix/Group.h +73 -0
  36. data/ext/quickfix/HtmlBuilder.h +186 -0
  37. data/ext/quickfix/HttpConnection.cpp +739 -0
  38. data/ext/quickfix/HttpConnection.h +78 -0
  39. data/ext/quickfix/HttpMessage.cpp +149 -0
  40. data/ext/quickfix/HttpMessage.h +133 -0
  41. data/ext/quickfix/HttpParser.cpp +49 -0
  42. data/ext/quickfix/HttpParser.h +54 -0
  43. data/ext/quickfix/HttpServer.cpp +169 -0
  44. data/ext/quickfix/HttpServer.h +78 -0
  45. data/ext/quickfix/Initiator.cpp +289 -0
  46. data/ext/quickfix/Initiator.h +149 -0
  47. data/ext/quickfix/Log.cpp +77 -0
  48. data/ext/quickfix/Log.h +179 -0
  49. data/ext/quickfix/Message.cpp +580 -0
  50. data/ext/quickfix/Message.h +370 -0
  51. data/ext/quickfix/MessageCracker.h +188 -0
  52. data/ext/quickfix/MessageSorters.cpp +105 -0
  53. data/ext/quickfix/MessageSorters.h +156 -0
  54. data/ext/quickfix/MessageStore.cpp +146 -0
  55. data/ext/quickfix/MessageStore.h +174 -0
  56. data/ext/quickfix/Mutex.h +131 -0
  57. data/ext/quickfix/MySQLConnection.h +194 -0
  58. data/ext/quickfix/MySQLLog.cpp +275 -0
  59. data/ext/quickfix/MySQLLog.h +145 -0
  60. data/ext/quickfix/MySQLStore.cpp +331 -0
  61. data/ext/quickfix/MySQLStore.h +142 -0
  62. data/ext/quickfix/NullStore.cpp +54 -0
  63. data/ext/quickfix/NullStore.h +99 -0
  64. data/ext/quickfix/OdbcConnection.h +266 -0
  65. data/ext/quickfix/OdbcLog.cpp +252 -0
  66. data/ext/quickfix/OdbcLog.h +117 -0
  67. data/ext/quickfix/OdbcStore.cpp +338 -0
  68. data/ext/quickfix/OdbcStore.h +113 -0
  69. data/ext/quickfix/PUGIXML_DOMDocument.cpp +112 -0
  70. data/ext/quickfix/PUGIXML_DOMDocument.h +81 -0
  71. data/ext/quickfix/Parser.cpp +103 -0
  72. data/ext/quickfix/Parser.h +57 -0
  73. data/ext/quickfix/PostgreSQLConnection.h +176 -0
  74. data/ext/quickfix/PostgreSQLLog.cpp +276 -0
  75. data/ext/quickfix/PostgreSQLLog.h +144 -0
  76. data/ext/quickfix/PostgreSQLStore.cpp +334 -0
  77. data/ext/quickfix/PostgreSQLStore.h +141 -0
  78. data/ext/quickfix/Queue.h +75 -0
  79. data/ext/quickfix/QuickfixRuby.cpp +252066 -0
  80. data/ext/quickfix/QuickfixRuby.h +34 -0
  81. data/ext/quickfix/Responder.h +43 -0
  82. data/ext/quickfix/Session.cpp +1487 -0
  83. data/ext/quickfix/Session.h +335 -0
  84. data/ext/quickfix/SessionFactory.cpp +274 -0
  85. data/ext/quickfix/SessionFactory.h +86 -0
  86. data/ext/quickfix/SessionID.h +170 -0
  87. data/ext/quickfix/SessionSettings.cpp +189 -0
  88. data/ext/quickfix/SessionSettings.h +171 -0
  89. data/ext/quickfix/SessionState.h +231 -0
  90. data/ext/quickfix/Settings.cpp +100 -0
  91. data/ext/quickfix/Settings.h +53 -0
  92. data/ext/quickfix/SharedArray.h +150 -0
  93. data/ext/quickfix/SocketAcceptor.cpp +222 -0
  94. data/ext/quickfix/SocketAcceptor.h +75 -0
  95. data/ext/quickfix/SocketConnection.cpp +238 -0
  96. data/ext/quickfix/SocketConnection.h +103 -0
  97. data/ext/quickfix/SocketConnector.cpp +116 -0
  98. data/ext/quickfix/SocketConnector.h +67 -0
  99. data/ext/quickfix/SocketInitiator.cpp +260 -0
  100. data/ext/quickfix/SocketInitiator.h +81 -0
  101. data/ext/quickfix/SocketMonitor.cpp +335 -0
  102. data/ext/quickfix/SocketMonitor.h +111 -0
  103. data/ext/quickfix/SocketServer.cpp +177 -0
  104. data/ext/quickfix/SocketServer.h +100 -0
  105. data/ext/quickfix/ThreadedSocketAcceptor.cpp +258 -0
  106. data/ext/quickfix/ThreadedSocketAcceptor.h +98 -0
  107. data/ext/quickfix/ThreadedSocketConnection.cpp +209 -0
  108. data/ext/quickfix/ThreadedSocketConnection.h +82 -0
  109. data/ext/quickfix/ThreadedSocketInitiator.cpp +268 -0
  110. data/ext/quickfix/ThreadedSocketInitiator.h +84 -0
  111. data/ext/quickfix/TimeRange.cpp +173 -0
  112. data/ext/quickfix/TimeRange.h +258 -0
  113. data/ext/quickfix/Utility.cpp +537 -0
  114. data/ext/quickfix/Utility.h +219 -0
  115. data/ext/quickfix/Values.h +62 -0
  116. data/ext/quickfix/config.h +0 -0
  117. data/ext/quickfix/config_windows.h +0 -0
  118. data/ext/quickfix/extconf.rb +12 -0
  119. data/ext/quickfix/index.h +37 -0
  120. data/ext/quickfix/pugiconfig.hpp +72 -0
  121. data/ext/quickfix/pugixml.cpp +10765 -0
  122. data/ext/quickfix/pugixml.hpp +1341 -0
  123. data/ext/quickfix/strptime.h +7 -0
  124. data/lib/quickfix40.rb +274 -0
  125. data/lib/quickfix41.rb +351 -0
  126. data/lib/quickfix42.rb +1184 -0
  127. data/lib/quickfix43.rb +3504 -0
  128. data/lib/quickfix44.rb +10721 -0
  129. data/lib/quickfix50.rb +13426 -0
  130. data/lib/quickfix50sp1.rb +15629 -0
  131. data/lib/quickfix50sp2.rb +17068 -0
  132. data/lib/quickfix_fields.rb +19853 -0
  133. data/lib/quickfix_ruby.rb +82 -0
  134. data/lib/quickfixt11.rb +70 -0
  135. data/spec/FIX40.xml +862 -0
  136. data/spec/FIX41.xml +1285 -0
  137. data/spec/FIX42.xml +2746 -0
  138. data/spec/FIX43.xml +4229 -0
  139. data/spec/FIX44.xml +6596 -0
  140. data/spec/FIX50.xml +8137 -0
  141. data/spec/FIX50SP1.xml +9496 -0
  142. data/spec/FIX50SP2.xml +10011 -0
  143. data/spec/FIXT11.xml +313 -0
  144. data/test/test_DataDictionaryTestCase.rb +268 -0
  145. data/test/test_DictionaryTestCase.rb +112 -0
  146. data/test/test_FieldBaseTestCase.rb +24 -0
  147. data/test/test_MessageTestCase.rb +368 -0
  148. data/test/test_SessionSettingsTestCase.rb +41 -0
  149. metadata +193 -0
@@ -0,0 +1,258 @@
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 "ThreadedSocketAcceptor.h"
27
+ #include "Settings.h"
28
+ #include "Utility.h"
29
+
30
+ namespace FIX
31
+ {
32
+ ThreadedSocketAcceptor::ThreadedSocketAcceptor(
33
+ Application& application,
34
+ MessageStoreFactory& factory,
35
+ const SessionSettings& settings ) throw( ConfigError )
36
+ : Acceptor( application, factory, settings )
37
+ { socket_init(); }
38
+
39
+ ThreadedSocketAcceptor::ThreadedSocketAcceptor(
40
+ Application& application,
41
+ MessageStoreFactory& factory,
42
+ const SessionSettings& settings,
43
+ LogFactory& logFactory ) throw( ConfigError )
44
+ : Acceptor( application, factory, settings, logFactory )
45
+ {
46
+ socket_init();
47
+ }
48
+
49
+ ThreadedSocketAcceptor::~ThreadedSocketAcceptor()
50
+ {
51
+ socket_term();
52
+ }
53
+
54
+ void ThreadedSocketAcceptor::onConfigure( const SessionSettings& s )
55
+ throw ( ConfigError )
56
+ {
57
+ std::set<SessionID> sessions = s.getSessions();
58
+ std::set<SessionID>::iterator i;
59
+ for( i = sessions.begin(); i != sessions.end(); ++i )
60
+ {
61
+ const Dictionary& settings = s.get( *i );
62
+ settings.getInt( SOCKET_ACCEPT_PORT );
63
+ if( settings.has(SOCKET_REUSE_ADDRESS) )
64
+ settings.getBool( SOCKET_REUSE_ADDRESS );
65
+ if( settings.has(SOCKET_NODELAY) )
66
+ settings.getBool( SOCKET_NODELAY );
67
+ }
68
+ }
69
+
70
+ void ThreadedSocketAcceptor::onInitialize( const SessionSettings& s )
71
+ throw ( RuntimeError )
72
+ {
73
+ short port = 0;
74
+ std::set<int> ports;
75
+
76
+ std::set<SessionID> sessions = s.getSessions();
77
+ std::set<SessionID>::iterator i = sessions.begin();
78
+ for( ; i != sessions.end(); ++i )
79
+ {
80
+ const Dictionary& settings = s.get( *i );
81
+ port = (short)settings.getInt( SOCKET_ACCEPT_PORT );
82
+
83
+ m_portToSessions[port].insert( *i );
84
+
85
+ if( ports.find(port) != ports.end() )
86
+ continue;
87
+ ports.insert( port );
88
+
89
+ const bool reuseAddress = settings.has( SOCKET_REUSE_ADDRESS ) ?
90
+ settings.getBool( SOCKET_REUSE_ADDRESS ) : true;
91
+
92
+ const bool noDelay = settings.has( SOCKET_NODELAY ) ?
93
+ settings.getBool( SOCKET_NODELAY ) : false;
94
+
95
+ const int sendBufSize = settings.has( SOCKET_SEND_BUFFER_SIZE ) ?
96
+ settings.getInt( SOCKET_SEND_BUFFER_SIZE ) : 0;
97
+
98
+ const int rcvBufSize = settings.has( SOCKET_RECEIVE_BUFFER_SIZE ) ?
99
+ settings.getInt( SOCKET_RECEIVE_BUFFER_SIZE ) : 0;
100
+
101
+ int socket = socket_createAcceptor( port, reuseAddress );
102
+ if( socket < 0 )
103
+ {
104
+ SocketException e;
105
+ socket_close( socket );
106
+ throw RuntimeError( "Unable to create, bind, or listen to port "
107
+ + IntConvertor::convert( (unsigned short)port ) + " (" + e.what() + ")" );
108
+ }
109
+ if( noDelay )
110
+ socket_setsockopt( socket, TCP_NODELAY );
111
+ if( sendBufSize )
112
+ socket_setsockopt( socket, SO_SNDBUF, sendBufSize );
113
+ if( rcvBufSize )
114
+ socket_setsockopt( socket, SO_RCVBUF, rcvBufSize );
115
+
116
+ m_socketToPort[socket] = port;
117
+ m_sockets.insert( socket );
118
+ }
119
+ }
120
+
121
+ void ThreadedSocketAcceptor::onStart()
122
+ {
123
+ Sockets::iterator i;
124
+ for( i = m_sockets.begin(); i != m_sockets.end(); ++i )
125
+ {
126
+ Locker l( m_mutex );
127
+ int port = m_socketToPort[*i];
128
+ AcceptorThreadInfo* info = new AcceptorThreadInfo( this, *i, port );
129
+ thread_id thread;
130
+ thread_spawn( &socketAcceptorThread, info, thread );
131
+ addThread( *i, thread );
132
+ }
133
+ }
134
+
135
+ bool ThreadedSocketAcceptor::onPoll( double timeout )
136
+ {
137
+ return false;
138
+ }
139
+
140
+ void ThreadedSocketAcceptor::onStop()
141
+ {
142
+ SocketToThread threads;
143
+ SocketToThread::iterator i;
144
+
145
+ {
146
+ Locker l(m_mutex);
147
+
148
+ time_t start = 0;
149
+ time_t now = 0;
150
+
151
+ ::time( &start );
152
+ while ( isLoggedOn() )
153
+ {
154
+ if( ::time(&now) -5 >= start )
155
+ break;
156
+ }
157
+
158
+ threads = m_threads;
159
+ m_threads.clear();
160
+ }
161
+
162
+ for ( i = threads.begin(); i != threads.end(); ++i )
163
+ socket_close( i->first );
164
+ for ( i = threads.begin(); i != threads.end(); ++i )
165
+ thread_join( i->second );
166
+ }
167
+
168
+ void ThreadedSocketAcceptor::addThread( int s, thread_id t )
169
+ {
170
+ Locker l(m_mutex);
171
+
172
+ m_threads[ s ] = t;
173
+ }
174
+
175
+ void ThreadedSocketAcceptor::removeThread( int s )
176
+ {
177
+ Locker l(m_mutex);
178
+ SocketToThread::iterator i = m_threads.find( s );
179
+ if ( i != m_threads.end() )
180
+ {
181
+ thread_detach( i->second );
182
+ m_threads.erase( i );
183
+ }
184
+ }
185
+
186
+ THREAD_PROC ThreadedSocketAcceptor::socketAcceptorThread( void* p )
187
+ {
188
+ AcceptorThreadInfo * info = reinterpret_cast < AcceptorThreadInfo* > ( p );
189
+
190
+ ThreadedSocketAcceptor* pAcceptor = info->m_pAcceptor;
191
+ int s = info->m_socket;
192
+ int port = info->m_port;
193
+ delete info;
194
+
195
+ int noDelay = 0;
196
+ int sendBufSize = 0;
197
+ int rcvBufSize = 0;
198
+ socket_getsockopt( s, TCP_NODELAY, noDelay );
199
+ socket_getsockopt( s, SO_SNDBUF, sendBufSize );
200
+ socket_getsockopt( s, SO_RCVBUF, rcvBufSize );
201
+
202
+ int socket = 0;
203
+ while ( ( !pAcceptor->isStopped() && ( socket = socket_accept( s ) ) >= 0 ) )
204
+ {
205
+ if( noDelay )
206
+ socket_setsockopt( socket, TCP_NODELAY );
207
+ if( sendBufSize )
208
+ socket_setsockopt( socket, SO_SNDBUF, sendBufSize );
209
+ if( rcvBufSize )
210
+ socket_setsockopt( socket, SO_RCVBUF, rcvBufSize );
211
+
212
+ Sessions sessions = pAcceptor->m_portToSessions[port];
213
+
214
+ ThreadedSocketConnection * pConnection =
215
+ new ThreadedSocketConnection
216
+ ( socket, sessions, pAcceptor->getLog() );
217
+
218
+ ConnectionThreadInfo* info = new ConnectionThreadInfo( pAcceptor, pConnection );
219
+
220
+ {
221
+ Locker l( pAcceptor->m_mutex );
222
+
223
+ std::stringstream stream;
224
+ stream << "Accepted connection from " << socket_peername( socket ) << " on port " << port;
225
+
226
+ if( pAcceptor->getLog() )
227
+ pAcceptor->getLog()->onEvent( stream.str() );
228
+
229
+ thread_id thread;
230
+ if ( !thread_spawn( &socketConnectionThread, info, thread ) )
231
+ delete info;
232
+ pAcceptor->addThread( socket, thread );
233
+ }
234
+ }
235
+
236
+ if( !pAcceptor->isStopped() )
237
+ pAcceptor->removeThread( s );
238
+
239
+ return 0;
240
+ }
241
+
242
+ THREAD_PROC ThreadedSocketAcceptor::socketConnectionThread( void* p )
243
+ {
244
+ ConnectionThreadInfo * info = reinterpret_cast < ConnectionThreadInfo* > ( p );
245
+
246
+ ThreadedSocketAcceptor* pAcceptor = info->m_pAcceptor;
247
+ ThreadedSocketConnection* pConnection = info->m_pConnection;
248
+ delete info;
249
+
250
+ int socket = pConnection->getSocket();
251
+
252
+ while ( pConnection->read() ) {}
253
+ delete pConnection;
254
+ if( !pAcceptor->isStopped() )
255
+ pAcceptor->removeThread( socket );
256
+ return 0;
257
+ }
258
+ }
@@ -0,0 +1,98 @@
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 "ThreadedSocketConnection.h"
31
+ #include "Mutex.h"
32
+
33
+ namespace FIX
34
+ {
35
+ /// Threaded Socket implementation of Acceptor.
36
+ class ThreadedSocketAcceptor : public Acceptor
37
+ {
38
+ friend class SocketConnection;
39
+ public:
40
+ ThreadedSocketAcceptor( Application&, MessageStoreFactory&,
41
+ const SessionSettings& ) throw( ConfigError );
42
+ ThreadedSocketAcceptor( Application&, MessageStoreFactory&,
43
+ const SessionSettings&,
44
+ LogFactory& ) throw( ConfigError );
45
+
46
+ virtual ~ThreadedSocketAcceptor();
47
+
48
+ private:
49
+ struct AcceptorThreadInfo
50
+ {
51
+ AcceptorThreadInfo( ThreadedSocketAcceptor* pAcceptor, int socket, int port )
52
+ : m_pAcceptor( pAcceptor ), m_socket( socket ), m_port( port ) {}
53
+
54
+ ThreadedSocketAcceptor* m_pAcceptor;
55
+ int m_socket;
56
+ int m_port;
57
+ };
58
+
59
+ struct ConnectionThreadInfo
60
+ {
61
+ ConnectionThreadInfo( ThreadedSocketAcceptor* pAcceptor,
62
+ ThreadedSocketConnection* pConnection )
63
+ : m_pAcceptor( pAcceptor ), m_pConnection( pConnection ) {}
64
+
65
+ ThreadedSocketAcceptor* m_pAcceptor;
66
+ ThreadedSocketConnection* m_pConnection;
67
+ };
68
+
69
+ bool readSettings( const SessionSettings& );
70
+
71
+ typedef std::set < int > Sockets;
72
+ typedef std::set < SessionID > Sessions;
73
+ typedef std::map < int, Sessions > PortToSessions;
74
+ typedef std::map < int, int > SocketToPort;
75
+ typedef std::map < int, thread_id > SocketToThread;
76
+
77
+ void onConfigure( const SessionSettings& ) throw ( ConfigError );
78
+ void onInitialize( const SessionSettings& ) throw ( RuntimeError );
79
+
80
+ void onStart();
81
+ bool onPoll( double timeout );
82
+ void onStop();
83
+
84
+ void addThread( int s, thread_id t );
85
+ void removeThread( int s );
86
+ static THREAD_PROC socketAcceptorThread( void* p );
87
+ static THREAD_PROC socketConnectionThread( void* p );
88
+
89
+ Sockets m_sockets;
90
+ PortToSessions m_portToSessions;
91
+ SocketToPort m_socketToPort;
92
+ SocketToThread m_threads;
93
+ Mutex m_mutex;
94
+ };
95
+ /*! @} */
96
+ }
97
+
98
+ #endif //FIX_THREADEDSOCKETACCEPTOR_H
@@ -0,0 +1,209 @@
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 "ThreadedSocketConnection.h"
27
+ #include "ThreadedSocketAcceptor.h"
28
+ #include "ThreadedSocketInitiator.h"
29
+ #include "Session.h"
30
+ #include "Utility.h"
31
+
32
+ namespace FIX
33
+ {
34
+ ThreadedSocketConnection::ThreadedSocketConnection
35
+ ( int s, Sessions sessions, Log* pLog )
36
+ : m_socket( s ), m_pLog( pLog ),
37
+ m_sessions( sessions ), m_pSession( 0 ),
38
+ m_disconnect( false )
39
+ {
40
+ FD_ZERO( &m_fds );
41
+ FD_SET( m_socket, &m_fds );
42
+ }
43
+
44
+ ThreadedSocketConnection::ThreadedSocketConnection
45
+ ( const SessionID& sessionID, int s,
46
+ const std::string& address, short port,
47
+ Log* pLog )
48
+ : m_socket( s ), m_address( address ), m_port( port ),
49
+ m_pLog( pLog ),
50
+ m_pSession( Session::lookupSession( sessionID ) ),
51
+ m_disconnect( false )
52
+ {
53
+ FD_ZERO( &m_fds );
54
+ FD_SET( m_socket, &m_fds );
55
+ if ( m_pSession ) m_pSession->setResponder( this );
56
+ }
57
+
58
+ ThreadedSocketConnection::~ThreadedSocketConnection()
59
+ {
60
+ if ( m_pSession )
61
+ {
62
+ m_pSession->setResponder( 0 );
63
+ Session::unregisterSession( m_pSession->getSessionID() );
64
+ }
65
+ }
66
+
67
+ bool ThreadedSocketConnection::send( const std::string& msg )
68
+ {
69
+ int totalSent = 0;
70
+ while(totalSent < (int)msg.length())
71
+ {
72
+ ssize_t sent = socket_send( m_socket, msg.c_str() + totalSent, msg.length() );
73
+ if(sent < 0) return false;
74
+ totalSent += sent;
75
+ }
76
+
77
+ return true;
78
+ }
79
+
80
+ bool ThreadedSocketConnection::connect()
81
+ {
82
+ return socket_connect(getSocket(), m_address.c_str(), m_port) >= 0;
83
+ }
84
+
85
+ void ThreadedSocketConnection::disconnect()
86
+ {
87
+ m_disconnect = true;
88
+ socket_close( m_socket );
89
+ }
90
+
91
+ bool ThreadedSocketConnection::read()
92
+ {
93
+ struct timeval timeout = { 1, 0 };
94
+ fd_set readset = m_fds;
95
+
96
+ try
97
+ {
98
+ // Wait for input (1 second timeout)
99
+ int result = select( 1 + m_socket, &readset, 0, 0, &timeout );
100
+
101
+ if( result > 0 ) // Something to read
102
+ {
103
+ // We can read without blocking
104
+ ssize_t size = recv( m_socket, m_buffer, sizeof(m_buffer), 0 );
105
+ if ( size <= 0 ) { throw SocketRecvFailed( size ); }
106
+ m_parser.addToStream( m_buffer, size );
107
+ }
108
+ else if( result == 0 && m_pSession ) // Timeout
109
+ {
110
+ m_pSession->next();
111
+ }
112
+ else if( result < 0 ) // Error
113
+ {
114
+ throw SocketRecvFailed( result );
115
+ }
116
+
117
+ processStream();
118
+ return true;
119
+ }
120
+ catch ( SocketRecvFailed& e )
121
+ {
122
+ if( m_disconnect )
123
+ return false;
124
+
125
+ if( m_pSession )
126
+ {
127
+ m_pSession->getLog()->onEvent( e.what() );
128
+ m_pSession->disconnect();
129
+ }
130
+ else
131
+ {
132
+ disconnect();
133
+ }
134
+
135
+ return false;
136
+ }
137
+ }
138
+
139
+ bool ThreadedSocketConnection::readMessage( std::string& msg )
140
+ throw( SocketRecvFailed )
141
+ {
142
+ try
143
+ {
144
+ return m_parser.readFixMessage( msg );
145
+ }
146
+ catch ( MessageParseError& ) {}
147
+ return true;
148
+ }
149
+
150
+ void ThreadedSocketConnection::processStream()
151
+ {
152
+ std::string msg;
153
+ while( readMessage(msg) )
154
+ {
155
+ if ( !m_pSession )
156
+ {
157
+ if ( !setSession( msg ) )
158
+ { disconnect(); continue; }
159
+ }
160
+ try
161
+ {
162
+ m_pSession->next( msg, UtcTimeStamp() );
163
+ }
164
+ catch( InvalidMessage& )
165
+ {
166
+ if( !m_pSession->isLoggedOn() )
167
+ {
168
+ disconnect();
169
+ return;
170
+ }
171
+ }
172
+ }
173
+ }
174
+
175
+ bool ThreadedSocketConnection::setSession( const std::string& msg )
176
+ {
177
+ m_pSession = Session::lookupSession( msg, true );
178
+ if ( !m_pSession )
179
+ {
180
+ if( m_pLog )
181
+ {
182
+ m_pLog->onEvent( "Session not found for incoming message: " + msg );
183
+ m_pLog->onIncoming( msg );
184
+ }
185
+ return false;
186
+ }
187
+
188
+ SessionID sessionID = m_pSession->getSessionID();
189
+ m_pSession = 0;
190
+
191
+ // see if the session frees up within 5 seconds
192
+ for( int i = 1; i <= 5; i++ )
193
+ {
194
+ if( !Session::isSessionRegistered( sessionID ) )
195
+ m_pSession = Session::registerSession( sessionID );
196
+ if( m_pSession ) break;
197
+ process_sleep( 1 );
198
+ }
199
+
200
+ if ( !m_pSession )
201
+ return false;
202
+ if ( m_sessions.find(m_pSession->getSessionID()) == m_sessions.end() )
203
+ return false;
204
+
205
+ m_pSession->setResponder( this );
206
+ return true;
207
+ }
208
+
209
+ } // namespace FIX
@@ -0,0 +1,82 @@
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 <set>
33
+ #include <map>
34
+
35
+ namespace FIX
36
+ {
37
+ class ThreadedSocketAcceptor;
38
+ class ThreadedSocketInitiator;
39
+ class Session;
40
+ class Application;
41
+ class Log;
42
+
43
+ /// Encapsulates a socket file descriptor (multi-threaded).
44
+ class ThreadedSocketConnection : Responder
45
+ {
46
+ public:
47
+ typedef std::set<SessionID> Sessions;
48
+
49
+ ThreadedSocketConnection( int s, Sessions sessions, Log* pLog );
50
+ ThreadedSocketConnection( const SessionID&, int s,
51
+ const std::string& address, short port,
52
+ Log* pLog );
53
+ virtual ~ThreadedSocketConnection() ;
54
+
55
+ Session* getSession() const { return m_pSession; }
56
+ int getSocket() const { return m_socket; }
57
+ bool connect();
58
+ void disconnect();
59
+ bool read();
60
+
61
+ private:
62
+ bool readMessage( std::string& msg ) throw( SocketRecvFailed );
63
+ void processStream();
64
+ bool send( const std::string& );
65
+ bool setSession( const std::string& msg );
66
+
67
+ int m_socket;
68
+ char m_buffer[BUFSIZ];
69
+
70
+ std::string m_address;
71
+ int m_port;
72
+
73
+ Log* m_pLog;
74
+ Parser m_parser;
75
+ Sessions m_sessions;
76
+ Session* m_pSession;
77
+ bool m_disconnect;
78
+ fd_set m_fds;
79
+ };
80
+ }
81
+
82
+ #endif //FIX_THREADEDSOCKETCONNECTION_H