quickfix_ruby 1.14.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (149) hide show
  1. checksums.yaml +7 -0
  2. data/ext/quickfix/Acceptor.cpp +248 -0
  3. data/ext/quickfix/Acceptor.h +127 -0
  4. data/ext/quickfix/Allocator.h +9 -0
  5. data/ext/quickfix/Application.h +127 -0
  6. data/ext/quickfix/AtomicCount.h +109 -0
  7. data/ext/quickfix/DOMDocument.h +74 -0
  8. data/ext/quickfix/DataDictionary.cpp +618 -0
  9. data/ext/quickfix/DataDictionary.h +539 -0
  10. data/ext/quickfix/DataDictionaryProvider.cpp +71 -0
  11. data/ext/quickfix/DataDictionaryProvider.h +70 -0
  12. data/ext/quickfix/DatabaseConnectionID.h +105 -0
  13. data/ext/quickfix/DatabaseConnectionPool.h +91 -0
  14. data/ext/quickfix/Dictionary.cpp +162 -0
  15. data/ext/quickfix/Dictionary.h +94 -0
  16. data/ext/quickfix/Event.h +95 -0
  17. data/ext/quickfix/Exceptions.h +299 -0
  18. data/ext/quickfix/Field.h +672 -0
  19. data/ext/quickfix/FieldConvertors.h +863 -0
  20. data/ext/quickfix/FieldMap.cpp +238 -0
  21. data/ext/quickfix/FieldMap.h +244 -0
  22. data/ext/quickfix/FieldNumbers.h +46 -0
  23. data/ext/quickfix/FieldTypes.cpp +64 -0
  24. data/ext/quickfix/FieldTypes.h +698 -0
  25. data/ext/quickfix/Fields.h +31 -0
  26. data/ext/quickfix/FileLog.cpp +200 -0
  27. data/ext/quickfix/FileLog.h +112 -0
  28. data/ext/quickfix/FileStore.cpp +332 -0
  29. data/ext/quickfix/FileStore.h +129 -0
  30. data/ext/quickfix/FixFieldNumbers.h +1537 -0
  31. data/ext/quickfix/FixFields.h +1538 -0
  32. data/ext/quickfix/FixValues.h +3281 -0
  33. data/ext/quickfix/FlexLexer.h +188 -0
  34. data/ext/quickfix/Group.cpp +64 -0
  35. data/ext/quickfix/Group.h +73 -0
  36. data/ext/quickfix/HtmlBuilder.h +186 -0
  37. data/ext/quickfix/HttpConnection.cpp +739 -0
  38. data/ext/quickfix/HttpConnection.h +78 -0
  39. data/ext/quickfix/HttpMessage.cpp +149 -0
  40. data/ext/quickfix/HttpMessage.h +133 -0
  41. data/ext/quickfix/HttpParser.cpp +49 -0
  42. data/ext/quickfix/HttpParser.h +54 -0
  43. data/ext/quickfix/HttpServer.cpp +169 -0
  44. data/ext/quickfix/HttpServer.h +78 -0
  45. data/ext/quickfix/Initiator.cpp +289 -0
  46. data/ext/quickfix/Initiator.h +149 -0
  47. data/ext/quickfix/Log.cpp +77 -0
  48. data/ext/quickfix/Log.h +179 -0
  49. data/ext/quickfix/Message.cpp +580 -0
  50. data/ext/quickfix/Message.h +370 -0
  51. data/ext/quickfix/MessageCracker.h +188 -0
  52. data/ext/quickfix/MessageSorters.cpp +105 -0
  53. data/ext/quickfix/MessageSorters.h +156 -0
  54. data/ext/quickfix/MessageStore.cpp +146 -0
  55. data/ext/quickfix/MessageStore.h +174 -0
  56. data/ext/quickfix/Mutex.h +131 -0
  57. data/ext/quickfix/MySQLConnection.h +194 -0
  58. data/ext/quickfix/MySQLLog.cpp +275 -0
  59. data/ext/quickfix/MySQLLog.h +145 -0
  60. data/ext/quickfix/MySQLStore.cpp +331 -0
  61. data/ext/quickfix/MySQLStore.h +142 -0
  62. data/ext/quickfix/NullStore.cpp +54 -0
  63. data/ext/quickfix/NullStore.h +99 -0
  64. data/ext/quickfix/OdbcConnection.h +266 -0
  65. data/ext/quickfix/OdbcLog.cpp +252 -0
  66. data/ext/quickfix/OdbcLog.h +117 -0
  67. data/ext/quickfix/OdbcStore.cpp +338 -0
  68. data/ext/quickfix/OdbcStore.h +113 -0
  69. data/ext/quickfix/PUGIXML_DOMDocument.cpp +112 -0
  70. data/ext/quickfix/PUGIXML_DOMDocument.h +81 -0
  71. data/ext/quickfix/Parser.cpp +103 -0
  72. data/ext/quickfix/Parser.h +57 -0
  73. data/ext/quickfix/PostgreSQLConnection.h +176 -0
  74. data/ext/quickfix/PostgreSQLLog.cpp +276 -0
  75. data/ext/quickfix/PostgreSQLLog.h +144 -0
  76. data/ext/quickfix/PostgreSQLStore.cpp +334 -0
  77. data/ext/quickfix/PostgreSQLStore.h +141 -0
  78. data/ext/quickfix/Queue.h +75 -0
  79. data/ext/quickfix/QuickfixRuby.cpp +252066 -0
  80. data/ext/quickfix/QuickfixRuby.h +34 -0
  81. data/ext/quickfix/Responder.h +43 -0
  82. data/ext/quickfix/Session.cpp +1487 -0
  83. data/ext/quickfix/Session.h +335 -0
  84. data/ext/quickfix/SessionFactory.cpp +274 -0
  85. data/ext/quickfix/SessionFactory.h +86 -0
  86. data/ext/quickfix/SessionID.h +170 -0
  87. data/ext/quickfix/SessionSettings.cpp +189 -0
  88. data/ext/quickfix/SessionSettings.h +171 -0
  89. data/ext/quickfix/SessionState.h +231 -0
  90. data/ext/quickfix/Settings.cpp +100 -0
  91. data/ext/quickfix/Settings.h +53 -0
  92. data/ext/quickfix/SharedArray.h +150 -0
  93. data/ext/quickfix/SocketAcceptor.cpp +222 -0
  94. data/ext/quickfix/SocketAcceptor.h +75 -0
  95. data/ext/quickfix/SocketConnection.cpp +238 -0
  96. data/ext/quickfix/SocketConnection.h +103 -0
  97. data/ext/quickfix/SocketConnector.cpp +116 -0
  98. data/ext/quickfix/SocketConnector.h +67 -0
  99. data/ext/quickfix/SocketInitiator.cpp +260 -0
  100. data/ext/quickfix/SocketInitiator.h +81 -0
  101. data/ext/quickfix/SocketMonitor.cpp +335 -0
  102. data/ext/quickfix/SocketMonitor.h +111 -0
  103. data/ext/quickfix/SocketServer.cpp +177 -0
  104. data/ext/quickfix/SocketServer.h +100 -0
  105. data/ext/quickfix/ThreadedSocketAcceptor.cpp +258 -0
  106. data/ext/quickfix/ThreadedSocketAcceptor.h +98 -0
  107. data/ext/quickfix/ThreadedSocketConnection.cpp +209 -0
  108. data/ext/quickfix/ThreadedSocketConnection.h +82 -0
  109. data/ext/quickfix/ThreadedSocketInitiator.cpp +268 -0
  110. data/ext/quickfix/ThreadedSocketInitiator.h +84 -0
  111. data/ext/quickfix/TimeRange.cpp +173 -0
  112. data/ext/quickfix/TimeRange.h +258 -0
  113. data/ext/quickfix/Utility.cpp +537 -0
  114. data/ext/quickfix/Utility.h +219 -0
  115. data/ext/quickfix/Values.h +62 -0
  116. data/ext/quickfix/config.h +0 -0
  117. data/ext/quickfix/config_windows.h +0 -0
  118. data/ext/quickfix/extconf.rb +12 -0
  119. data/ext/quickfix/index.h +37 -0
  120. data/ext/quickfix/pugiconfig.hpp +72 -0
  121. data/ext/quickfix/pugixml.cpp +10765 -0
  122. data/ext/quickfix/pugixml.hpp +1341 -0
  123. data/ext/quickfix/strptime.h +7 -0
  124. data/lib/quickfix40.rb +274 -0
  125. data/lib/quickfix41.rb +351 -0
  126. data/lib/quickfix42.rb +1184 -0
  127. data/lib/quickfix43.rb +3504 -0
  128. data/lib/quickfix44.rb +10721 -0
  129. data/lib/quickfix50.rb +13426 -0
  130. data/lib/quickfix50sp1.rb +15629 -0
  131. data/lib/quickfix50sp2.rb +17068 -0
  132. data/lib/quickfix_fields.rb +19853 -0
  133. data/lib/quickfix_ruby.rb +82 -0
  134. data/lib/quickfixt11.rb +70 -0
  135. data/spec/FIX40.xml +862 -0
  136. data/spec/FIX41.xml +1285 -0
  137. data/spec/FIX42.xml +2746 -0
  138. data/spec/FIX43.xml +4229 -0
  139. data/spec/FIX44.xml +6596 -0
  140. data/spec/FIX50.xml +8137 -0
  141. data/spec/FIX50SP1.xml +9496 -0
  142. data/spec/FIX50SP2.xml +10011 -0
  143. data/spec/FIXT11.xml +313 -0
  144. data/test/test_DataDictionaryTestCase.rb +268 -0
  145. data/test/test_DictionaryTestCase.rb +112 -0
  146. data/test/test_FieldBaseTestCase.rb +24 -0
  147. data/test/test_MessageTestCase.rb +368 -0
  148. data/test/test_SessionSettingsTestCase.rb +41 -0
  149. metadata +193 -0
@@ -0,0 +1,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