ThreadedSSLSocketConnection.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 
126 #include "Session.h"
127 #include "Utility.h"
128 
129 namespace FIX
130 {
131 ThreadedSSLSocketConnection::ThreadedSSLSocketConnection(int s, SSL *ssl,
132  Sessions sessions,
133  Log *pLog)
134  : m_socket(s), m_ssl(ssl), m_pLog(pLog), m_sessions(sessions),
135  m_pSession(0), m_disconnect(false)
136 {
137  FD_ZERO(&m_fds);
138  FD_SET(m_socket, &m_fds);
139 }
140 
141 ThreadedSSLSocketConnection::ThreadedSSLSocketConnection(
142  const SessionID &sessionID, int s, SSL *ssl, const std::string &address,
143  short port, Log *pLog)
144  : m_socket(s), m_ssl(ssl), m_address(address), m_port(port), m_pLog(pLog),
145  m_pSession(Session::lookupSession(sessionID)), m_disconnect(false)
146 {
147  FD_ZERO(&m_fds);
148  FD_SET(m_socket, &m_fds);
149  if (m_pSession)
150  m_pSession->setResponder(this);
151 }
152 
153 ThreadedSSLSocketConnection::~ThreadedSSLSocketConnection()
154 {
155  if (m_pSession)
156  {
157  m_pSession->setResponder(0);
158  Session::unregisterSession(m_pSession->getSessionID());
159  }
160 }
161 
162 bool ThreadedSSLSocketConnection::send(const std::string &msg)
163 {
164  int totalSent = 0;
165 
166  while (totalSent < (int)msg.length())
167  {
168  errno = 0;
169  int errCodeSSL = 0;
170  int sent = 0;
171  ERR_clear_error();
172 
173  // Cannot do concurrent SSL write and read as ssl context has to be
174  // protected.
175  {
176  Locker locker(m_mutex);
177 
178  sent = SSL_write(m_ssl, msg.c_str() + totalSent, msg.length() - totalSent);
179  if (sent <= 0)
180  errCodeSSL = SSL_get_error(m_ssl, sent);
181  }
182 
183  if (sent <= 0)
184  {
185  if ((errCodeSSL == SSL_ERROR_WANT_READ) ||
186  (errCodeSSL == SSL_ERROR_WANT_WRITE))
187  {
188  errno = EINTR;
189  sent = 0;
190  }
191  else
192  {
193  char errbuf[200];
194 
195  socket_error(errbuf, sizeof(errbuf));
196 
197  m_pSession->getLog()->onEvent("SSL send error <" +
198  IntConvertor::convert(errCodeSSL) + "> " +
199  errbuf);
200 
201  return false;
202  }
203  }
204 
205  totalSent += sent;
206  }
207 
208  return true;
209 }
210 
211 bool ThreadedSSLSocketConnection::connect()
212 {
213  return socket_connect(getSocket(), m_address.c_str(), m_port) >= 0;
214 }
215 
216 void ThreadedSSLSocketConnection::disconnect()
217 {
218  m_disconnect = true;
219  ssl_socket_close(m_socket, m_ssl);
220 }
221 
222 bool ThreadedSSLSocketConnection::read()
223 {
224  struct timeval timeout = {1, 0};
225  fd_set readset = m_fds;
226 
227  try
228  {
229  // Wait for input (1 second timeout)
230  int result = select(1 + m_socket, &readset, 0, 0, &timeout);
231 
232  if (result > 0) // Something to read
233  {
234  bool pending = false;
235 
236  do
237  {
238  pending = false;
239  errno = 0;
240  int size = 0;
241  int errCodeSSL = 0;
242  ERR_clear_error();
243 
244  // Cannot do concurrent SSL write and read as ssl context has to be
245  // protected.
246  {
247  Locker locker(m_mutex);
248 
249  size = SSL_read(m_ssl, m_buffer, sizeof(m_buffer));
250  if (size <= 0)
251  errCodeSSL = SSL_get_error(m_ssl, size);
252  else if (SSL_pending(m_ssl) > 0)
253  pending = true;
254  }
255 
256  if (size <= 0)
257  {
258  if ((errCodeSSL == SSL_ERROR_WANT_READ) ||
259  (errCodeSSL == SSL_ERROR_WANT_WRITE))
260  {
261  errno = EINTR;
262  size = 0;
263 
264  return true;
265  }
266  else
267  {
268  char errbuf[200];
269 
270  socket_error(errbuf, sizeof(errbuf));
271 
272  if (m_pSession)
273  m_pSession->getLog()->onEvent("SSL read error <" +
274  IntConvertor::convert(errCodeSSL) +
275  "> " + errbuf);
276  else
277  {
279  << "SSL read error <"
280  << IntConvertor::convert(errCodeSSL) << "> " << errbuf
281  << std::endl;
282  }
283 
284  throw SocketRecvFailed(size);
285  }
286  }
287 
288  m_parser.addToStream(m_buffer, size);
289  } while (pending);
290  }
291  else if (result == 0 && m_pSession) // Timeout
292  {
293  m_pSession->next();
294  }
295  else if (result < 0) // Error
296  {
297  throw SocketRecvFailed(result);
298  }
299 
300  processStream();
301 
302  if (m_disconnect)
303  return false;
304 
305  return true;
306  }
307  catch (SocketRecvFailed &e)
308  {
309  if (m_disconnect)
310  return false;
311 
312  if (m_pSession)
313  {
314  m_pSession->getLog()->onEvent(e.what());
315  m_pSession->disconnect();
316  }
317  else
318  {
319  disconnect();
320  }
321 
322  return false;
323  }
324 }
325 
326 bool ThreadedSSLSocketConnection::readMessage(std::string &msg) throw(
327  SocketRecvFailed)
328 {
329  try
330  {
331  return m_parser.readFixMessage(msg);
332  }
333  catch (MessageParseError &)
334  {
335  }
336  return true;
337 }
338 
339 void ThreadedSSLSocketConnection::processStream()
340 {
341  std::string msg;
342  while (readMessage(msg))
343  {
344  if (!m_pSession)
345  {
346  if (!setSession(msg))
347  {
348  disconnect();
349  continue;
350  }
351  }
352  try
353  {
354  m_pSession->next(msg, UtcTimeStamp());
355  }
356  catch (InvalidMessage &)
357  {
358  if (!m_pSession->isLoggedOn())
359  {
360  disconnect();
361  return;
362  }
363  }
364  }
365 }
366 
367 bool ThreadedSSLSocketConnection::setSession(const std::string &msg)
368 {
369  m_pSession = Session::lookupSession(msg, true);
370  if (!m_pSession)
371  {
372  if (m_pLog)
373  {
374  m_pLog->onEvent("Session not found for incoming message: " + msg);
375  m_pLog->onIncoming(msg);
376  }
377  return false;
378  }
379 
380  SessionID sessionID = m_pSession->getSessionID();
381  m_pSession = 0;
382 
383  // see if the session frees up within 5 seconds
384  for (int i = 1; i <= 5; i++)
385  {
386  if (!Session::isSessionRegistered(sessionID))
387  m_pSession = Session::registerSession(sessionID);
388  if (m_pSession)
389  break;
390  process_sleep(1);
391  }
392 
393  if (!m_pSession)
394  return false;
395  if (m_sessions.find(m_pSession->getSessionID()) == m_sessions.end())
396  return false;
397 
398  m_pSession->setResponder(this);
399  return true;
400 }
401 
402 } // namespace FIX
403 
404 #endif
ThreadedSSLSocketAcceptor.h
FIX::Session::lookupSession
static Session * lookupSession(const SessionID &)
Definition: Session.cpp:1513
FIX::Session::unregisterSession
static void unregisterSession(const SessionID &)
Definition: Session.cpp:1564
ThreadedSSLSocketConnection.h
FIX::socket_connect
int socket_connect(int socket, const char *address, int port)
Definition: Utility.cpp:165
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
FIX::Session::isSessionRegistered
static bool isSessionRegistered(const SessionID &)
Definition: Session.cpp:1548
ThreadedSSLSocketInitiator.h
FIX::UtcTimeStampConvertor::convert
static std::string convert(const UtcTimeStamp &value, int precision=0)
Definition: FieldConvertors.h:451
FIX::process_sleep
void process_sleep(double s)
Definition: Utility.cpp:483
FIX
Definition: Acceptor.cpp:34
Session.h
Utility.h

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