SSLSocketConnection.cpp
Go to the documentation of this file.
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 "SSLSocketConnection.h"
124#include "SSLSocketAcceptor.h"
125#include "SocketConnector.h"
126#include "SSLSocketInitiator.h"
127#include "Session.h"
128#include "Utility.h"
129
130namespace FIX
131{
132SSLSocketConnection::SSLSocketConnection(int s, SSL *ssl, Sessions sessions,
133 SocketMonitor* pMonitor )
134: m_socket( s ), m_ssl(ssl), m_sendLength( 0 ),
135 m_sessions(sessions), m_pSession( 0 ), m_pMonitor( pMonitor )
136{
137 FD_ZERO( &m_fds );
138 FD_SET( m_socket, &m_fds );
139}
140
141SSLSocketConnection::SSLSocketConnection(SSLSocketInitiator &i,
142 const SessionID& sessionID, int s, SSL * ssl,
143 SocketMonitor* pMonitor )
144: m_socket( s ), m_ssl(ssl), m_sendLength( 0 ),
145 m_pSession( i.getSession( sessionID, *this ) ),
146 m_pMonitor( pMonitor )
147{
148 FD_ZERO( &m_fds );
149 FD_SET( m_socket, &m_fds );
150 m_sessions.insert( sessionID );
151}
152
153SSLSocketConnection::~SSLSocketConnection()
154{
155 if ( m_pSession )
156 Session::unregisterSession( m_pSession->getSessionID() );
157
158 ssl_socket_close(m_socket, m_ssl);
159
160 SSL_free(m_ssl);
161}
162
163bool SSLSocketConnection::send( const std::string& msg )
164{
165 Locker l( m_mutex );
166
167 m_sendQueue.push_back( msg );
168 processQueue();
169 signal();
170 return true;
171}
172
173bool SSLSocketConnection::processQueue()
174{
175 Locker l( m_mutex );
176
177 if( m_sendQueue.empty() ) return true;
178
179 struct timeval timeout = { 0, 0 };
180 fd_set writeset = m_fds;
181 if( select( 1 + m_socket, 0, &writeset, 0, &timeout ) <= 0 )
182 return false;
183
184 const std::string& msg = m_sendQueue.front();
185 m_sendLength = 0;
186
187 while (m_sendLength < (int)msg.length())
188 {
189 errno = 0;
190 int errCodeSSL = 0;
191 int sent = 0;
192 ERR_clear_error();
193
194 // Cannot do concurrent SSL write and read as ssl context has to be
195 // protected. Done above.
196 {
197 sent = SSL_write(m_ssl, msg.c_str() + m_sendLength, msg.length() - m_sendLength);
198 if (sent <= 0)
199 errCodeSSL = SSL_get_error(m_ssl, sent);
200 }
201
202 if (sent <= 0)
203 {
204 if ((errCodeSSL == SSL_ERROR_WANT_READ) ||
205 (errCodeSSL == SSL_ERROR_WANT_WRITE))
206 {
207 errno = EINTR;
208 sent = 0;
209 }
210 else
211 {
212 char errbuf[200];
213
214 socket_error(errbuf, sizeof(errbuf));
215
216 m_pSession->getLog()->onEvent("SSL send error <" +
217 IntConvertor::convert(errCodeSSL) + "> " +
218 errbuf);
219
220 return m_sendQueue.empty();
221 }
222 }
223
224 m_sendLength += sent;
225 }
226
227 m_sendLength = 0;
228 m_sendQueue.pop_front();
229
230 return m_sendQueue.empty();
231}
232
233void SSLSocketConnection::disconnect()
234{
235 if ( m_pMonitor )
236 m_pMonitor->drop( m_socket );
237}
238
239bool SSLSocketConnection::read( SocketConnector& s )
240{
241 if ( !m_pSession ) return false;
242
243 try
244 {
245 readFromSocket();
246 readMessages( s.getMonitor() );
247 }
248 catch( SocketRecvFailed& e )
249 {
250 m_pSession->getLog()->onEvent( e.what() );
251 return false;
252 }
253 return true;
254}
255
256bool SSLSocketConnection::read(SSLSocketAcceptor &a, SocketServer& s )
257{
258 std::string msg;
259 try
260 {
261 if ( !m_pSession )
262 {
263 struct timeval timeout = { 1, 0 };
264 fd_set readset = m_fds;
265
266 while( !readMessage( msg ) )
267 {
268 int result = select( 1 + m_socket, &readset, 0, 0, &timeout );
269 if( result > 0 )
270 readFromSocket();
271 else if( result == 0 )
272 return false;
273 else if( result < 0 )
274 return false;
275 }
276
277 m_pSession = Session::lookupSession( msg, true );
278 if( !isValidSession() )
279 {
280 m_pSession = 0;
281 if( a.getLog() )
282 {
283 a.getLog()->onEvent( "Session not found for incoming message: " + msg );
284 a.getLog()->onIncoming( msg );
285 }
286 }
287 if( m_pSession )
288 m_pSession = a.getSession( msg, *this );
289 if( m_pSession )
290 m_pSession->next( msg, UtcTimeStamp() );
291 if( !m_pSession )
292 {
293 s.getMonitor().drop( m_socket );
294 return false;
295 }
296
297 Session::registerSession( m_pSession->getSessionID() );
298 return true;
299 }
300 else
301 {
302 readFromSocket();
303 readMessages( s.getMonitor() );
304 return true;
305 }
306 }
307 catch ( SocketRecvFailed& e )
308 {
309 if( m_pSession )
310 m_pSession->getLog()->onEvent( e.what() );
311 s.getMonitor().drop( m_socket );
312 }
313 catch ( InvalidMessage& )
314 {
315 s.getMonitor().drop( m_socket );
316 }
317 return false;
318}
319
320bool SSLSocketConnection::isValidSession()
321{
322 if( m_pSession == 0 )
323 return false;
324 SessionID sessionID = m_pSession->getSessionID();
325 if( Session::isSessionRegistered(sessionID) )
326 return false;
327 return !( m_sessions.find(sessionID) == m_sessions.end() );
328}
329
330void SSLSocketConnection::readFromSocket()
331throw( SocketRecvFailed )
332{
333 bool pending = false;
334
335 do
336 {
337 pending = false;
338 errno = 0;
339 ssize_t size = 0;
340 int errCodeSSL = 0;
341 ERR_clear_error();
342
343 // Cannot do concurrent SSL write and read as ssl context has to be
344 // protected.
345 {
346 Locker locker(m_mutex);
347
348 size = SSL_read(m_ssl, m_buffer, sizeof(m_buffer));
349 if (size <= 0)
350 errCodeSSL = SSL_get_error(m_ssl, size);
351 else if (SSL_pending(m_ssl) > 0)
352 pending = true;
353 }
354
355 if (size <= 0)
356 {
357 if ((errCodeSSL == SSL_ERROR_WANT_READ) ||
358 (errCodeSSL == SSL_ERROR_WANT_WRITE))
359 {
360 errno = EINTR;
361 size = 0;
362
363 return;
364 }
365 else
366 {
367 char errbuf[200];
368
369 socket_error(errbuf, sizeof(errbuf));
370
371 if (m_pSession)
372 m_pSession->getLog()->onEvent("SSL read error <" +
373 IntConvertor::convert(errCodeSSL) +
374 "> " + errbuf);
375 else
376 {
377 std::cerr << UtcTimeStampConvertor::convert(UtcTimeStamp())
378 << "SSL read error <"
379 << IntConvertor::convert(errCodeSSL) << "> " << errbuf
380 << std::endl;
381 }
382
383 throw SocketRecvFailed(size);
384 }
385 }
386
387 m_parser.addToStream(m_buffer, size);
388 } while (pending);
389}
390
391bool SSLSocketConnection::readMessage( std::string& msg )
392{
393 try
394 {
395 return m_parser.readFixMessage( msg );
396 }
397 catch ( MessageParseError& ) {}
398 return true;
399}
400
401void SSLSocketConnection::readMessages( SocketMonitor& s )
402{
403 if( !m_pSession ) return;
404
405 std::string msg;
406 while( readMessage( msg ) )
407 {
408 try
409 {
410 m_pSession->next( msg, UtcTimeStamp() );
411 }
412 catch ( InvalidMessage& )
413 {
414 if( !m_pSession->isLoggedOn() )
415 s.drop( m_socket );
416 }
417 }
418}
419
420void SSLSocketConnection::onTimeout()
421{
422 if ( m_pSession ) m_pSession->next();
423}
424
425} // namespace FIX
426
427#endif

Generated on Mon Oct 14 2024 06:04:44 for QuickFIX by doxygen 1.9.8 written by Dimitri van Heesch, © 1997-2001