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 
130 namespace FIX
131 {
132 SSLSocketConnection::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 
141 SSLSocketConnection::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 
153 SSLSocketConnection::~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 
163 bool 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 
173 bool 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 
233 void SSLSocketConnection::disconnect()
234 {
235  if ( m_pMonitor )
236  m_pMonitor->drop( m_socket );
237 }
238 
239 bool 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 
256 bool 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 
320 bool 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 
330 void SSLSocketConnection::readFromSocket()
331 throw( 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  {
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 
391 bool SSLSocketConnection::readMessage( std::string& msg )
392 {
393  try
394  {
395  return m_parser.readFixMessage( msg );
396  }
397  catch ( MessageParseError& ) {}
398  return true;
399 }
400 
401 void 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 
420 void SSLSocketConnection::onTimeout()
421 {
422  if ( m_pSession ) m_pSession->next();
423 }
424 
425 } // namespace FIX
426 
427 #endif
FIX::Session::lookupSession
static Session * lookupSession(const SessionID &)
Definition: Session.cpp:1513
FIX::Session::unregisterSession
static void unregisterSession(const SessionID &)
Definition: Session.cpp:1564
SSLSocketInitiator.h
FIX::Session::registerSession
static Session * registerSession(const SessionID &)
Definition: Session.cpp:1554
FIX::TYPE::UtcTimeStamp
@ UtcTimeStamp
Definition: FieldTypes.h:940
FIX::IntConvertor::convert
static std::string convert(signed_int value)
Definition: FieldConvertors.h:170
SSLSocketAcceptor.h
FIX::Session::isSessionRegistered
static bool isSessionRegistered(const SessionID &)
Definition: Session.cpp:1548
FIX::UtcTimeStampConvertor::convert
static std::string convert(const UtcTimeStamp &value, int precision=0)
Definition: FieldConvertors.h:451
FIX
Definition: Acceptor.cpp:34
Session.h
SocketConnector.h
Utility.h
SSLSocketConnection.h

Generated on Wed Apr 29 2020 19:41:30 for QuickFIX by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2001