OnixS C++ CME iLink 3 Binary Order Entry Handler  1.17.0
API Documentation
Gateway.h
Go to the documentation of this file.
1 // Copyright Onix Solutions Limited [OnixS]. All rights reserved.
2 //
3 // This software owned by Onix Solutions Limited [OnixS] and is
4 // protected by copyright law and international copyright treaties.
5 //
6 // Access to and use of the software is governed by the terms of the applicable
7 // OnixS Software Services Agreement (the Agreement) and Customer end user license
8 // agreements granting a non-assignable, non-transferable and non-exclusive license
9 // to use the software for it's own data processing purposes under the terms defined
10 // in the Agreement.
11 //
12 // Except as otherwise granted within the terms of the Agreement, copying or
13 // reproduction of any part of this source code or associated reference material
14 // to any other location for further reproduction or redistribution, and any
15 // amendments to this copyright notice, are expressly prohibited.
16 //
17 // Any reproduction or redistribution for sale or hiring of the Software not in
18 // accordance with the terms of the Agreement is a violation of copyright law.
19 
20 #pragma once
21 
24 
25 #if defined(ONIXS_ILINK3_HAS_GATEWAY_EMULATOR)
26 
31 
32 #include <chrono>
33 #include <atomic>
34 
35 namespace OnixS {
36 namespace CME {
37 namespace iLink3 {
38 namespace Testing {
39 
40 // Assume NegotiationResponse501::credentials is empty
41 constexpr
43 {
44  using Message = NegotiationResponse501;
45 
46  return
47  Message::blockLength(Message::Schema::Version)
49  + Message::getMinimalVariableFieldsSize(Message::Schema::Version);
50 }
51 
52 // Type aliases
59 
65 
66 /// CME iLink 3 Gateway Emulator.
68 {
69 public:
70  /// Timeout alias.
71  using Timeout = std::chrono::milliseconds;
72 
73  Gateway(const SessionSettings::LicenseStores& licenseStores, int port, const char* host = "127.0.0.1",
74  const Timeout& acceptTimeout = defaultTimeout(),
75  const Timeout& sendReceiveTimeout = defaultTimeout());
76 
77  ///
78  virtual ~Gateway();
79 
80  /// Deleted.
81  Gateway(const Gateway&) = delete;
82  Gateway& operator=(const Gateway&) = delete;
83 
84  /// Move semantic.
85  Gateway(Gateway&&) noexcept;
86  Gateway& operator=(Gateway&&) noexcept;
87 
88  /// Swap with other.
89  void swap(Gateway&) noexcept;
90 
91  /// Accepts an incoming connection.
92  /// If the `acceptTimeout` is zero, the `acceptTimeout` provided in the constructor is used.
93  Gateway& acceptConnection(const Timeout& acceptTimeout = defaultTimeout());
94 
95  /// Accepts an incoming connection.
96  /// If the operation is timed out, `false` is returned.
97  bool tryAcceptConnection(const Timeout& acceptTimeout = defaultTimeout());
98 
99  /// Accepts an incoming iLink 3 session.
100  Gateway& acceptSession(SeqNumber outgoingSequenceNumber = 1, UInt64 previousUuid = 0, UInt32 previousSeqNo = 0);
101 
102  /// Waits until the Terminate507 message is received.
103  ///
104  /// If the listener is provided, then receives and reports application-level messages via the corresponding callback.
105  /// Responds to the Sequence506 message if received.
106  /// \note actual `outSeqNum` must be provided before invocation
107  Terminate507Ptr waitUntilTerminate(
108  ClientMessageListener* listener = nullptr, ClientSessionMessageListener* sessionMessageListener = nullptr,
109  std::atomic<bool>* stopRequested = nullptr);
110 
111  /// Sends the Sequence506 message.
112  Gateway& sendSequence(UInt32 nextSeqNo, KeepAliveLapsed::Enum keepAliveLapsed = KeepAliveLapsed::NotLapsed, UInt64 uuid = 0);
113 
114  /// Closes the accepted connection.
115  Gateway& disconnect();
116 
117  /// @return listen host.
118  const char * host() const noexcept;
119 
120  /// \return the listen port.
122  int port() const noexcept;
123 
124  /// Enables logging.
125  Gateway& enableLogger(const std::string& logFileName, unsigned int logLevel = 3);
126 
127  /// Sends the given message.
128  /// \note does not update `outSeqNum`.
129  template <typename SbeMessageType, size_t MaxMessageSize, typename MessageInitializer>
130  Gateway& send(iLink3::Messaging::MessageHolder<SbeMessageType, MaxMessageSize, MessageInitializer>& msg);
131 
132  /// Sends the given message.
133  /// \note does not update `outSeqNum`.
134  template <typename SbeMessageType, size_t MaxMessageSize, typename MessageInitializer>
135  Gateway& send(iLink3::Messaging::MessageHolder<SbeMessageType, MaxMessageSize, MessageInitializer>&& msg);
136 
137  /// Sets the given sequence number and sends the message.
138  /// \note does not update `outSeqNum`.
139  template <typename SbeMessageType, size_t MaxMessageSize, typename MessageInitializer>
140  Gateway& send(iLink3::Messaging::MessageHolder<SbeMessageType, MaxMessageSize, MessageInitializer>& msg, SeqNumber num);
141 
142  /// Sets the given sequence number and sends the message.
143  /// \note does not update `outSeqNum`.
144  template <typename SbeMessageType, size_t MaxMessageSize, typename MessageInitializer>
145  Gateway& send(iLink3::Messaging::MessageHolder<SbeMessageType, MaxMessageSize, MessageInitializer>&& msg, SeqNumber num);
146 
147  /// Sets the given sequence numbers and sends the messages.
148  /// \note does not update `outSeqNum`.
149  template <typename SbeMessageType, size_t MaxMessageSize, typename MessageInitializer>
150  Gateway& send(iLink3::Messaging::MessageHolder<SbeMessageType, MaxMessageSize, MessageInitializer>& msg, std::initializer_list<SeqNumber> numbers);
151 
152  /// Sets the given sequence numbers and sends the messages.
153  /// \note does not update `outSeqNum`.
154  template <typename SbeMessageType, size_t MaxMessageSize, typename MessageInitializer>
155  Gateway& send(iLink3::Messaging::MessageHolder<SbeMessageType, MaxMessageSize, MessageInitializer>&& msg, std::initializer_list<SeqNumber> numbers);
156 
157 
158  /// Receives the message of the particular type.
159  ///
160  /// \throw std::logic_error if an unexpected type is received.
161  template <typename TMsg>
162  MessagePtr<TMsg> receiveTypedMessage();
163 
164  /// Accepts an incoming connection and establishes the session.
165  ///
166  /// - Receives and reports application-level messages via the corresponding callback.
167  /// - Sends Sequence messages in response to the received ones.
168  Gateway& run(ClientMessageListener& listener);
169 
170  /// Accepts an incoming connection and establishes the session.
171  ///
172  /// - Receives and reports application-level messages via the corresponding callback.
173  /// - Receives and reports session-level messages via the corresponding callback.
174  /// - Sends Sequence messages.
175  Gateway& run(ClientMessageListener& appMsgListener, ClientSessionMessageListener& sessionMsgListener);
176 
177  /// \return the sequence number of the next outgoing message.
179  SeqNumber outSeqNum() const noexcept;
180 
181  /// Sets the sequence number of the next outgoing message.
182  Gateway& outSeqNum(SeqNumber nextOutSeqNum) noexcept;
183 
184  /// \return UUID.
186  UInt64 uuid() const noexcept
187  {
188  return uId_;
189  }
190 
191  /// \return the Fault Tolerance Indicator.
194  {
195  return faultToleranceIndicator_;
196  }
197 
198  /// Sets the Fault Tolerance Indicator.
200  {
201  faultToleranceIndicator_ = value;
202 
203  return *this;
204  }
205 
206  /// Sets the value of the option to improve latency at the expense of message throughput (the `TCP_NODELAY` socket option).
207  Gateway& tcpNoDelayOption(bool noDelay);
208 
209  /// \return the value of the option to improve latency at the expense of message throughput (the `TCP_NODELAY` socket option).
210  ///
211  /// The default value is SessionSettings::Default::TcpNoDelayOption.
213  bool tcpNoDelayOption() const noexcept ;
214 
215  /// \return the socket receive buffer size.
216  ///
217  /// The default value is SessionSettings::Default::SocketReceiveBufferSize.
219  int socketReceiveBufferSize() const;
220 
221  /// Sets the socket receive buffer size.
222  ///
223  /// \param bufferSize the size of the socket receive buffer size.
224  /// If SessionSettings::UseOsDefaultSocketBufferSize then the default operating system value is used.
225  Gateway& socketReceiveBufferSize(int bufferSize);
226 
227  /// \return the size of the socket send buffer size.
228  ///
229  /// The default value is SessionSettings::Default::SocketSedndBufferSize.
231  int socketSendBufferSize() const noexcept;
232 
233  /// Sets the size of the socket send buffer size.
234  ///
235  /// \param bufferSize the size of the socket send buffer size.
236  /// If SessionSettings::UseOsDefaultSocketBufferSize then the default operating system value is used.
237  Gateway& socketSendBufferSize(int bufferSize);
238 
239 protected:
240  /// Checks whether the connection is closed by the counterparty.
242  bool isConnectionClosed(const Timeout& timeout) const;
243 
244  /// Checks whether the connection is closed by the counterparty
245  /// using the default timeout (provided in the constructor).
247  bool isConnectionClosed() const;
248 
249  /// Receives a message.
250  MessageBasePtr receive() const;
251 
252  /// Receives a message using the provided timeout.
253  /// If the operation is timed out, an empty message is returned.
254  MessageBasePtr tryReceive(const Timeout& timeout = defaultTimeout()) const;
255 
256  /// Receives the Negotiate500 message.
257  ///
258  /// \throw std::logic_error if an unexpected type is received.
259  Negotiate500Ptr receiveNegotiate();
260 
261  /// Receives the Negotiate500 and responds with the NegotiationResponse501 message.
262  ///
263  /// \throw std::logic_error if an unexpected type is received.
264  Negotiate500Ptr acceptNegotiate(UInt32 previousSeqNo = 0);
265 
266  /// Receives the Negotiate500 message and responds with the NegotiationReject502 message.
267  ///
268  /// \throw std::logic_error if an unexpected type is received.
270  const std::string & reason = std::string());
271 
272  /// Receives the Establish503 message.
273  ///
274  /// \throw std::logic_error if an unexpected type is received.
275  Establish503Ptr receiveEstablish();
276 
277  /// Receive the Establish503 message and respond with the EstablishmentAck504 message.
278  ///
279  /// \throw std::logic_error if an unexpected type is received.
280  Establish503Ptr acceptEstablish(UInt32 outgoingSequenceNumber = 1, UInt64 previousUuid = 0, UInt32 previousSeqNo = 0);
281 
282  /// Receives the Establish503 message and responds with the EstablishmentReject505 message.
283  ///
284  /// \throw std::logic_error if an unexpected type is received.
285  Establish503Ptr rejectEstablish(UInt32 outgoingSequenceNumber = 1, EstablishmentRejectErrorCode::Enum errorCodes = EstablishmentRejectErrorCode::Enum(), const std::string & reason = std::string());
286 
287  /// Receive the Terminate507 message.
288  ///
289  /// \throw std::logic_error if an unexpected type is received.
290  Terminate507Ptr receiveTerminate();
291 
292  /// Receive the Terminate507 message and responds with the Terminate507 message.
293  ///
294  /// \throw std::logic_error if an unexpected type is received.
295  Terminate507Ptr acceptTerminate();
296 
297  /// Sends the Terminate507 message.
298  Gateway& sendTerminate(const std::string& reason = {}, UInt16 errCode = TerminateErrorCode::Other);
299 
300  /// Sends the Terminate507 message and waits until the response is received.
301  Terminate507Ptr terminate(const std::string& reason = {}, UInt16 errCode = TerminateErrorCode::Other);
302 
303  /// Creates a NegotiationResponse501 message
304  NegotiationResponse501Container createNegotiationResponse(const Negotiate500Ptr& request, UInt32 previousSeqNo);
305 
306  /// Creates a NegotiationReject502 message.
307  NegotiationReject502Container createNegotiationReject(const Negotiate500Ptr& request, NegotiationRejectErrorCode::Enum errorCodes,
308  const std::string & reason);
309 
310  /// Creates a EstablishmentAck504 message.
311  EstablishmentAck504Container createEstablishmentAck(const Establish503Ptr& request, UInt32 outgoingSequenceNumber);
312 
313  /// Creates a EstablishmentReject505 message.
314  EstablishmentReject505Container createEstablishmentReject(const Establish503Ptr& request, UInt32 outgoingSequenceNumber,
315  EstablishmentRejectErrorCode::Enum errorCodes, const std::string & reason);
316 
317  /// Creates a Terminate507 message.
318  Terminate507Container createTerminate(const Terminate507Ptr& request);
319 
320  /// Creates a Terminate507 message.
321  Terminate507Container createTerminate(const std::string& reason, UInt16 errCode);
322 
323  /// Creates a Sequence506 message.
324  Sequence506Container createSequence(UInt32 nextSeqNo, KeepAliveLapsed::Enum keepAliveLapsed = KeepAliveLapsed::NotLapsed, UInt64 uuid = 0);
325 
326  /// Sends the given message.
328 
329  /// Sends the given data
330  Gateway& sendData(const void* data, size_t size);
331 
332  /// Close the listening socket
333  Gateway& close();
334 
335  /// Default timeout
337  {
338  return Timeout(30000);
339  }
340 
341  /// UUID.
342  UInt64 uId_{0};
343 
344 private:
345  Messaging::FTI::Enum faultToleranceIndicator_{Messaging::FTI::Enum::Primary};
346 
347  class Impl;
348  Impl* impl_;
349 };
350 
351 
352 template <typename TMsg>
354 {
355  return cast<TMsg>(receive());
356 }
357 
358 template <typename SbeMessageType, size_t MaxMessageSize, typename MessageInitializer>
360 {
361  const auto messageSize = msg.setHeader();
362  auto* const header = msg.header();
363  assert(header);
364 
365  return send(Messaging::SbeMessage(header + 1, messageSize), *header);
366 }
367 
368 template <typename SbeMessageType, size_t MaxMessageSize, typename MessageInitializer>
370 {
371  return send(msg);
372 }
373 
374 template <typename Holder>
375 typename std::enable_if<std::is_base_of<TagBased::Message, typename Holder::MessageType>::value>::type
376  setSeqNum(Holder& msg, SeqNumber num)
377 {
378  msg->set(TagBased::Tags::SeqNum, num);
379 }
380 
381 template <typename Holder>
382 typename std::enable_if<!std::is_base_of<TagBased::Message, typename Holder::MessageType>::value>::type
383  setSeqNum(Holder& msg, SeqNumber num)
384 {
385  msg->setSeqNum(num);
386 }
387 
388 template <typename SbeMessageType, size_t MaxMessageSize, typename MessageInitializer>
390 {
391  setSeqNum(msg, num);
392  return send(msg);
393 }
394 
395 template <typename SbeMessageType, size_t MaxMessageSize, typename MessageInitializer>
397 {
398  setSeqNum(msg, num);
399  return send(msg);
400 }
401 
402 template <typename SbeMessageType, size_t MaxMessageSize, typename MessageInitializer>
405 {
406  for(auto seqNum : numbers)
407  {
408  send(msg, seqNum);
409  }
410 
411  return *this;
412 }
413 
414 template <typename SbeMessageType, size_t MaxMessageSize, typename MessageInitializer>
416  iLink3::Messaging::MessageHolder<SbeMessageType, MaxMessageSize, MessageInitializer>&& msg, std::initializer_list<SeqNumber> numbers)
417 {
418  for(auto seqNum : numbers)
419  {
420  send(msg, seqNum);
421  }
422 
423  return *this;
424 }
425 
426 
427 }}}}
428 
429 
430 #endif
Gateway & send(iLink3::Messaging::MessageHolder< SbeMessageType, MaxMessageSize, MessageInitializer > &msg)
Sends the given message.
Definition: Gateway.h:359
Contains the SimpleOpenFramingHeader, the SBE message, and the data buffer.
std::vector< std::string > LicenseStores
Folders that contain license file(s).
Messaging::UInt32 SeqNumber
Definition: Messaging.h:60
STL namespace.
constexpr UInt16 calculateNegotiationResponse501MaxSize()
Definition: Gateway.h:42
UInt16 UInt16
uInt16.
Definition: Fields.h:296
std::chrono::milliseconds Timeout
Timeout alias.
Definition: Gateway.h:71
Definition: Defines.h:40
std::enable_if< std::is_base_of< TagBased::Message, typename Holder::MessageType >::value >::type setSeqNum(Holder &msg, SeqNumber num)
Definition: Gateway.h:376
CME iLink 3 Gateway Emulator.
Definition: Gateway.h:67
any other error condition not mentioned above
Definition: ValuesEnums.h:212
MessageSize setHeader() noexcept
Calculates the binary size of the message and updates the Simple Open Framing Header accordingly...
FTI::Enum faultToleranceIndicator() const noexcept
Definition: Gateway.h:193
#define ONIXS_ILINK3_EXPORTED
Definition: Compiler.h:167
UInt64 UInt64
uInt64.
Definition: Fields.h:308
UInt32 UInt32
uInt32.
Definition: Fields.h:302
const SimpleOpenFramingHeader * header() const noexcept
Gateway & faultToleranceIndicator(FTI::Enum value)
Sets the Fault Tolerance Indicator.
Definition: Gateway.h:199
static Timeout defaultTimeout()
Default timeout.
Definition: Gateway.h:336
#define ONIXS_ILINK3_NODISCARD
Definition: Compiler.h:177
MessagePtr< TMsg > receiveTypedMessage()
Receives the message of the particular type.
Definition: Gateway.h:353