OnixS C++ SGX Titan OUCH Trading Handler  1.2.0
API documentation
HandlerImpl.cpp
Go to the documentation of this file.
1 /*
2 * Copyright Onix Solutions Limited [OnixS]. All rights reserved.
3 *
4 * This software owned by Onix Solutions Limited [OnixS] and is protected by copyright law
5 * and international copyright treaties.
6 *
7 * Access to and use of the software is governed by the terms of the applicable ONIXS Software
8 * Services Agreement (the Agreement) and Customer end user license agreements granting
9 * a non-assignable, non-transferable and non-exclusive license to use the software
10 * for it's own data processing purposes under the terms defined in the Agreement.
11 *
12 * Except as otherwise granted within the terms of the Agreement, copying or reproduction of any part
13 * of this source code or associated reference material to any other location for further reproduction
14 * or redistribution, and any amendments to this copyright notice, are expressly prohibited.
15 *
16 * Any reproduction or redistribution for sale or hiring of the Software not in accordance with
17 * the terms of the Agreement is a violation of copyright law.
18 */
19 #include <boost/bind.hpp>
20 #include <boost/current_function.hpp>
21 #include <boost/format.hpp>
22 
23 #include <system/Directory.h>
24 #include <util/Base64Encoding.h>
25 #include <util/HexEncoding.h>
26 #include <licensing/LicenseManager.h>
27 
28 #include <OnixS/HandlerCore/HandlerLogger.h>
29 #include <OnixS/HandlerCore/Utils.h>
30 #include <OnixS/HandlerCore/Compiler.h>
31 
33 
34 #include "ListenerHolder.h"
35 #include "Version.h"
36 #include "ProtocolFormatting.h"
37 #include "AuditTrailDumper.h"
38 
39 #include "HandlerImpl.h"
40 
41 using namespace OnixS::System;
42 using namespace OnixS::SgxTitan::Trading::Ouch;
44 
45 
46 const OnixS::Licensing::ProductId productId = 153;
47 
48 HandlerImpl::HandlerImpl(const HandlerSettings& settings)
49  : Licensing::LicenseChecker(settings.licenseDirectory, productId)
50  , base("Handler", nullptr, static_cast<Logging::LogLevel>(settings.logLevel))
51  , settings_(settings)
52  , logger_(new OnixS::HandlerCore::Common::HandlerLogger(OnixS::HandlerCore::Common::convertLogSettings(settings)))
53  , listenerHolder_(new ListenerHolder(this, *logger_))
54  , externalState_(HandlerState::Disconnected)
55  , session_(nullptr)
56 {
57  LogFacility facility("Handler", nullptr, Logging::LOG_LEVEL_DEBUG);
58 
59  forceLog(ONIXS_LOG_INFO[&facility]
60  << "OnixS C++ SGX TITAN OUCH Trading Handler, version "
62  << ", "
63  << os()
64  );
65 
66  forceLog(ONIXS_LOG_INFO[&facility] << settings_);
67 
68  runAuditTrail();
69 }
70 
71 void HandlerImpl::onError(OnixS::ItchCore::SoupBinTCP::ReconnectableSession&, const std::string& what)
72 {
73  BOOST_ASSERT(listenerHolder_);
74  listenerHolder_->invokeError(ErrorCode::General, what);
75 }
76 
77 void HandlerImpl::onWarning(OnixS::ItchCore::SoupBinTCP::ReconnectableSession&, const std::string& what)
78 {
79  BOOST_ASSERT(listenerHolder_);
80  listenerHolder_->invokeWarning(what);
81 }
82 
83 void HandlerImpl::onStateChange(
84  OnixS::ItchCore::SoupBinTCP::ReconnectableSession&,
85  OnixS::ItchCore::SoupBinTCP::ReconnectableSessionState::Enum /*oldState*/,
86  OnixS::ItchCore::SoupBinTCP::ReconnectableSessionState::Enum newState)
87 {
88  externalState_.change(static_cast<HandlerState::Enum>(newState));
89 
90  BOOST_ASSERT(listenerHolder_);
91  listenerHolder_->invokeStateChanged(externalState_.read());
92 }
93 
94 void HandlerImpl::onData(OnixS::ItchCore::SoupBinTCP::ReconnectableSession&, const void* data, UInt16 size)
95 {
96  BOOST_ASSERT(listenerHolder_);
97  listenerHolder_->invokeReceivedBytes(static_cast<const char*>(data), size);
98 
99  processData(data, size);
100 }
101 
103 {
104  checkState(HandlerState::Connected);
105 
106  Guard guard (sessionLock_);
107 
108  BOOST_ASSERT(session_);
109  return session_->receivingSeqNo();
110 }
111 
112 std::string HandlerImpl::sessionId() const
113 {
114  checkState(HandlerState::Connected);
115 
116  Guard guard (sessionLock_);
117 
118  BOOST_ASSERT(session_);
119  return session_->sessionId();
120 }
121 
122 void HandlerImpl::runAuditTrail()
123 {
124  if (!settings_.auditTrailFile.empty())
125  {
126  std::string auditTrailDir = settings_.auditTrailDirectory;
127 
128  if (auditTrailDir.find_last_of("\\/") != auditTrailDir.length() - 1)
129  auditTrailDir.append("/");
130 
131  if (!OnixS::System::Directory::exists(auditTrailDir))
132  OnixS::System::Directory::create(auditTrailDir);
133 
134  try
135  {
136  auditTrailDumper_.reset(
137  new AuditTrailDumper(
138  auditTrailDir + settings_.auditTrailFile + ".txt",
139  this,
140  *logger_,
141  settings_.auditTrailThreadAffinity,
142  settings_.auditTrailFileMaxSize));
143  }
144  catch (const std::exception& ex)
145  {
146  throw OperationException(BOOST_CURRENT_FUNCTION, OnixS::Util::format("Can't create Audit Trail file: %s", ex.what()).c_str());
147  }
148  catch (...)
149  {
150  throw OperationException(BOOST_CURRENT_FUNCTION, "Can't create Audit Trail file.");
151  }
152  }
153 }
154 
156 {
157  try
158  {
159  if(externalState_.read() == HandlerState::Connected)
160  disconnect();
161  }
162  catch (...) {}
163 
164  try
165  {
166  if (auditTrailDumper_)
167  auditTrailDumper_->stop();
168  }
169  catch (...) {}
170 }
171 
173 {
174  return externalState_.read();
175 }
176 
177 void HandlerImpl::commonLog(int logLevel, const char * msg, size_t length)
178 {
179  BOOST_ASSERT(msg != nullptr);
180  BOOST_ASSERT(length != 0);
181 
182  if (logLevel < OnixS::Logging::MIN_LOG_LEVEL || logLevel > OnixS::Logging::MAX_LOG_LEVEL)
183  throw OperationException (
184  BOOST_CURRENT_FUNCTION,
185  (boost::format("An error occurred during log operation. Invalid log level (logLevel=%d).")
186  % logLevel).str().c_str()
187  );
188 
189  static const std::string userLogFacilityName = "USER";
190 
191  log (
192  OnixS::Logging::LogMsg(
193  OnixS::Logging::LogLevel(logLevel))[userLogFacilityName] << OnixS::Util::ValuePtr(msg, length)
194  );
195 }
196 
197 void HandlerImpl::connect(const LogonSettings& logonSettings,
198  const std::string& hostName,
199  const UInt16 port,
200  const std::string& localNetworkInterface)
201 {
202  ItchCore::SoupBinTCP::ReconnectableSessionSettings settings;
203  settings.receiveTimeoutMs = settings_.receiveTimeoutMs;
204  settings.sendTimeoutMs = settings_.sendTimeoutMs;
205  settings.reconnectIntervalMs = settings_.connectionRetries.intervalSec * 1000;
206  settings.reconnectAttempts = settings_.connectionRetries.number;
207 
208  ItchCore::SoupBinTCP::ConnectivitySettings connectivitySettings;
209  connectivitySettings.connectionA = ItchCore::SoupBinTCP::ValidatedNetFeedConnection(hostName, port, localNetworkInterface);
210  connectivitySettings.authenticationSettings.userName = logonSettings.userName;
211  connectivitySettings.authenticationSettings.password = logonSettings.password;
212  connectivitySettings.authenticationSettings.session = logonSettings.session;
213  connectivitySettings.initialSequenceNumber = logonSettings.sequenceNumber;
214 
215  {
216  Guard guard (sessionLock_);
217 
218  session_.reset(
219  new ItchCore::SoupBinTCP::ReconnectableSession(settings, connectivitySettings, this, this)
220  );
221 
222  session_->setLogger(logger_.get());
223 
224  session_->connect();
225  }
226 
227  checkState(HandlerState::Connected);
228 }
229 
231 {
232  checkState(HandlerState::Connected);
233 
234  Guard guard (sessionLock_);
235 
236  if (session_)
237  {
238  session_->disconnect(false);
239  session_.reset();
240  }
241 }
242 
244 {
245  checkState(HandlerState::Connected);
246 
247  Guard guard (sessionLock_);
248 
249  if (session_)
250  {
251  session_->disconnect(true);
252  }
253 }
254 
255 void HandlerImpl::send(const OutgoingMessage& msg, bool warmupMode)
256 {
257  checkState(HandlerState::Connected);
258 
259  if (auditTrailDumper_)
260  auditTrailDumper_->onOutboundMessage(msg, warmupMode);
261 
262  if (warmupMode)
263  return;
264 
265  log(ONIXS_LOG_DEBUG[this] << "Sending " << msg);
266 
267  Guard guard (sessionLock_);
268 
269  BOOST_ASSERT(session_);
270  session_->sendData(msg.binary(), msg.binarySize());
271 }
272 
273 void HandlerImpl::checkState(HandlerState::Enum expectedState) const
274 {
275  const HandlerState::Enum state = externalState_.read();
276  if (state!= expectedState)
277  throw OnixS::DomainException(
278  (boost::format("Wrong state = %s, expected = %s.") % toStr(state) % toStr(expectedState)).str()
279  );
280 }
281 
282 std::string HandlerImpl::os()
283 {
284 #if BOOST_OS_WINDOWS
285  return "Windows";
286 #elif BOOST_OS_UNIX
287  std::string res = "Linux";
288  res += ", ";
289  res += __VERSION__;
290  return res;
291 #else
292 # error "Unknown OS"
293 #endif
294 }
void connect(const LogonSettings &logonSettings, const std::string &hostName, UInt16 port, const std::string &localNetworkInterface)
const OnixS::Licensing::ProductId productId
Definition: HandlerImpl.cpp:46
void send(const OutgoingMessage &message, bool warmupMode=false)
Identifies errors of generic nature.
Definition: ErrorListener.h:35
Enum
Defines the state that the handler is in.
MessageSize binarySize() const
Size of message.
std::string session
Requested Session.
void commonLog(int logLevel, const char *msg, size_t length)
ONIXS_SGXTITAN_OUCH_API void toStr(std::string &, OutboundMessageTypes::Enum)
Appends string presentation of object.
Defines the state that the handler is in.