OnixS C++ CME iLink 3 Binary Order Entry Handler  1.9.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 
22 #include <OnixS/CME/iLink3/ABI.h>
23 
24 #if defined(ONIXS_ILINK3_HAS_GATEWAY_EMULATOR)
25 
29 #include <OnixS/CME/iLink3/testing/ClientMessageListener.h>
30 
31 #include <chrono>
32 
33 namespace OnixS {
34 namespace CME {
35 namespace iLink3 {
36 namespace Testing {
37 
38 // Assume NegotiationResponse501::credentials is empty
39 constexpr
41 {
42  using Message = NegotiationResponse501;
43 
44  return
45  Message::blockLength(Message::Schema::Version)
47  + Message::getMinimalVariableFieldsSize(Message::Schema::Version);
48 }
49 
50 // Type aliases
57 
63 
64 /// CME iLink 3 Gateway Emulator.
66 {
67 public:
68  explicit
69  Gateway(int port, const char* host = "127.0.0.1", const std::chrono::seconds& timeout = std::chrono::seconds(10));
70 
71  ///
72  virtual ~Gateway();
73 
74  /// Deleted.
75  Gateway(const Gateway&) = delete;
76  Gateway& operator=(const Gateway&) = delete;
77 
78  /// Move semantic.
79  Gateway(Gateway&&) noexcept;
80  Gateway& operator=(Gateway&&) noexcept;
81 
82  /// Swap with other.
83  void swap(Gateway&) noexcept;
84 
85  /// Accepts an incoming connection.
86  Gateway& acceptConnection();
87 
88  /// Accepts an incoming iLink 3 session.
89  Gateway& acceptSession(SeqNumber outgoingSequenceNumber = 1, UInt64 previousUuid = 0, UInt32 previousSeqNo = 0);
90 
91  /// Waits until the Terminate507 message is received.
92  ///
93  /// If the listener is provided, then receives and reports application-level messages via the corresponding callback.
94  /// Responds to the Sequence506 message if received.
95  Terminate507Ptr waitUntilTerminate(ClientMessageListener* listener = nullptr);
96 
97  /// Sends the Sequence506 message.
98  Gateway& sendSequence(UInt32 nextSeqNo, KeepAliveLapsed::Enum keepAliveLapsed = KeepAliveLapsed::NotLapsed);
99 
100  /// Closes the accepted connection.
101  Gateway& disconnect();
102 
103  /// \return the listen port.
105  int port() const noexcept;
106 
107  /// Enables logging.
108  Gateway& enableLogger(const std::string& logFileName);
109 
110  /// Sends the given message.
111  template <typename SbeMessageType, size_t MaxMessageSize, typename MessageInitializer>
113 
114  /// Sends the given message.
115  template <typename SbeMessageType, size_t MaxMessageSize, typename MessageInitializer>
117 
118  /// Sets the given sequence number and send the message.
119  template <typename SbeMessageType, size_t MaxMessageSize, typename MessageInitializer>
121 
122  /// Sets the given sequence number and send the message.
123  template <typename SbeMessageType, size_t MaxMessageSize, typename MessageInitializer>
125 
126  /// Receives the message of the particular type.
127  ///
128  /// \throw std::logic_error if an unexpected type is received.
129  template <typename TMsg>
130  MessagePtr<TMsg> receiveTypedMessage();
131 
132  /// Accepts an incoming connection and establishes the session.
133  ///
134  /// - Receives and reports application-level messages via the corresponding callback.
135  /// - Sends Sequence messages.
136  Gateway& run(ClientMessageListener& listener);
137 
138  /// \return the sequence number of the next outgoing message.
140  SeqNumber outSeqNum() const;
141 
142  /// Sets the sequence number of the next outgoing message.
143  Gateway& outSeqNum(SeqNumber nextOutSeqNum);
144 
145  /// \return UUUD.
147  UInt64 uuid() const noexcept
148  {
149  return uId_;
150  }
151 
152  /// \return the Fault Tolerance Indicator.
155  {
156  return faultToleranceIndicator_;
157  }
158 
159  /// Sets the Fault Tolerance Indicator.
161  {
162  faultToleranceIndicator_ = value;
163 
164  return *this;
165  }
166 
167  /// Sets the value of the option to improve latency at the expense of message throughput (the `TCP_NODELAY` socket option).
168  Gateway& tcpNoDelayOption(bool noDelay);
169 
170  /// \return the value of the option to improve latency at the expense of message throughput (the `TCP_NODELAY` socket option).
171  ///
172  /// The default value is SessionSettings::Default::TcpNoDelayOption.
174  bool tcpNoDelayOption() const;
175 
176  /// \return the socket receive buffer size.
177  ///
178  /// The default value is SessionSettings::Default::SocketReceiveBufferSize.
180  int socketReceiveBufferSize() const;
181 
182  /// Sets the socket receive buffer size.
183  ///
184  /// \param bufferSize the size of the socket receive buffer size.
185  /// If SessionSettings::UseOsDefaultSocketBufferSize then the default operating system value is used.
186  Gateway& socketReceiveBufferSize(int bufferSize);
187 
188  /// \return the size of the socket send buffer size.
189  ///
190  /// The default value is SessionSettings::Default::SocketSedndBufferSize.
192  int socketSendBufferSize() const;
193 
194  /// Sets the size of the socket send buffer size.
195  ///
196  /// \param bufferSize the size of the socket send buffer size.
197  /// If SessionSettings::UseOsDefaultSocketBufferSize then the default operating system value is used.
198  Gateway& socketSendBufferSize(int bufferSize);
199 
200 protected:
201  /// Checks whether the connection is closed by the counterparty.
203  bool isConnectionClosed(const std::chrono::seconds& timeout) const;
204 
205  /// Checks whether the connection is closed by the counterparty
206  /// using the default timeout (provided in the constructor).
208  bool isConnectionClosed() const;
209 
210  /// Receives a message.
211  MessageBasePtr receive() const;
212 
213  /// Receives the Negotiate500 message.
214  ///
215  /// \throw std::logic_error if an unexpected type is received.
216  Negotiate500Ptr receiveNegotiate();
217 
218  /// Receives the Negotiate500 and responds with the NegotiationResponse501 message.
219  ///
220  /// \throw std::logic_error if an unexpected type is received.
221  Negotiate500Ptr acceptNegotiate(UInt32 previousSeqNo = 0);
222 
223  /// Receives the Negotiate500 message and responds with the NegotiationReject502 message.
224  ///
225  /// \throw std::logic_error if an unexpected type is received.
227  const std::string & reason = std::string());
228 
229  /// Receives the Establish503 message.
230  ///
231  /// \throw std::logic_error if an unexpected type is received.
232  Establish503Ptr receiveEstablish();
233 
234  /// Receive the Establish503 message and respond with the EstablishmentAck504 message.
235  ///
236  /// \throw std::logic_error if an unexpected type is received.
237  Establish503Ptr acceptEstablish(UInt32 outgoingSequenceNumber = 1, UInt64 previousUuid = 0, UInt32 previousSeqNo = 0);
238 
239  /// Receives the Establish503 message and responds with the EstablishmentReject505 message.
240  ///
241  /// \throw std::logic_error if an unexpected type is received.
242  Establish503Ptr rejectEstablish(UInt32 outgoingSequenceNumber = 1, EstablishmentRejectErrorCode::Enum errorCodes = EstablishmentRejectErrorCode::Enum(), const std::string & reason = std::string());
243 
244  /// Receive the Terminate507 message.
245  ///
246  /// \throw std::logic_error if an unexpected type is received.
247  Terminate507Ptr receiveTerminate();
248 
249  /// Receive the Terminate507 message and responds with the Terminate507 message.
250  ///
251  /// \throw std::logic_error if an unexpected type is received.
252  Terminate507Ptr acceptTerminate();
253 
254  /// Sends the Terminate507 message.
255  Gateway& sendTerminate(const std::string& reason = {}, UInt16 errCode = TerminateErrorCode::Other);
256 
257  /// Sends the Terminate507 meassage and waist until the response is received.
258  Terminate507Ptr terminate(const std::string& reason = {}, UInt16 errCode = TerminateErrorCode::Other);
259 
260  /// Creates a NegotiationResponse501 message
261  NegotiationResponse501Container createNegotiationResponse(const Negotiate500Ptr& request, UInt32 previousSeqNo);
262 
263  /// Creates a NegotiationReject502 message.
264  NegotiationReject502Container createNegotiationReject(const Negotiate500Ptr& request, NegotiationRejectErrorCode::Enum errorCodes,
265  const std::string & reason);
266 
267  /// Creates a EstablishmentAck504 message.
268  EstablishmentAck504Container createEstablishmentAck(const Establish503Ptr& request, UInt32 outgoingSequenceNumber);
269 
270  /// Creates a EstablishmentReject505 message.
271  EstablishmentReject505Container createEstablishmentReject(const Establish503Ptr& request, UInt32 outgoingSequenceNumber,
272  EstablishmentRejectErrorCode::Enum errorCodes, const std::string & reason);
273 
274  /// Creates a Terminate507 message.
275  Terminate507Container createTerminate(const Terminate507Ptr& request);
276 
277  /// Creates a Terminate507 message.
278  Terminate507Container createTerminate(const std::string& reason, UInt16 errCode);
279 
280  /// Creates a Sequence506 message.
281  Sequence506Container createSequence(UInt32 nextSeqNo, KeepAliveLapsed::Enum keepAliveLapsed = KeepAliveLapsed::NotLapsed);
282 
283  /// Sends the given message.
285 
286  /// Sends the given data
287  Gateway& sendData(const void* data, size_t size);
288 
289  /// UUID.
290  UInt64 uId_{0};
291 
292 private:
293  Messaging::FTI::Enum faultToleranceIndicator_{Messaging::FTI::Enum::Primary};
294 
295  template<typename MessageType>
296  void invokeCallback(void(ClientMessageListener::*Callback)(const MessageType &, Gateway *), ClientMessageListener * listener, const MessageBasePtr & msg)
297  {
298  if(listener)
299  (listener->*Callback)(cast<MessageType>(msg), this);
300  }
301 
302  class Impl;
303  Impl* impl_;
304 };
305 
306 
307 template <typename TMsg>
309 {
310  return cast<TMsg>(receive());
311 }
312 
313 template <typename SbeMessageType, size_t MaxMessageSize, typename MessageInitializer>
315 {
316  const auto messageSize = msg.setHeader();
317  auto* const header = msg.header();
318  assert(header);
319 
320  return send(Messaging::SbeMessage(header + 1, messageSize), *header);
321 }
322 
323 template <typename SbeMessageType, size_t MaxMessageSize, typename MessageInitializer>
325 {
326  return send(msg);
327 }
328 
329 template <typename Holder>
330 typename std::enable_if<std::is_base_of<TagBased::Message, typename Holder::MessageType>::value>::type
331  setSeqNum(Holder& msg, SeqNumber num)
332 {
333  msg->set(TagBased::Tags::SeqNum, num);
334 }
335 
336 template <typename Holder>
337 typename std::enable_if<!std::is_base_of<TagBased::Message, typename Holder::MessageType>::value>::type
338  setSeqNum(Holder& msg, SeqNumber num)
339 {
340  msg->setSeqNum(num);
341 }
342 
343 template <typename SbeMessageType, size_t MaxMessageSize, typename MessageInitializer>
345 {
346  setSeqNum(msg, num);
347  return send(msg);
348 }
349 
350 template <typename SbeMessageType, size_t MaxMessageSize, typename MessageInitializer>
352 {
353  setSeqNum(msg, num);
354  return send(msg);
355 }
356 
357 }}}}
358 
359 #endif
Gateway & send(iLink3::Messaging::MessageHolder< SbeMessageType, MaxMessageSize, MessageInitializer > &msg)
Sends the given message.
Definition: Gateway.h:314
Contains the SimpleOpenFramingHeader, the SBE message, and the data buffer.
FTI::Enum faultToleranceIndicator() const noexcept
Definition: Gateway.h:154
Messaging::UInt32 SeqNumber
Definition: Messaging.h:58
constexpr UInt16 calculateNegotiationResponse501MaxSize()
Definition: Gateway.h:40
UInt16 UInt16
uInt16.
Definition: Fields.h:264
Definition: Defines.h:40
const SimpleOpenFramingHeader * header() const
std::enable_if< std::is_base_of< TagBased::Message, typename Holder::MessageType >::value >::type setSeqNum(Holder &msg, SeqNumber num)
Definition: Gateway.h:331
CME iLink 3 Gateway Emulator.
Definition: Gateway.h:65
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...
#define ONIXS_ILINK3_EXPORTED
Definition: Compiler.h:162
UInt64 UInt64
uInt64.
Definition: Fields.h:276
UInt32 UInt32
uInt32.
Definition: Fields.h:270
UInt64 uuid() const noexcept
Definition: Gateway.h:147
Gateway & faultToleranceIndicator(FTI::Enum value)
Sets the Fault Tolerance Indicator.
Definition: Gateway.h:160
#define ONIXS_ILINK3_NODISCARD
Definition: Compiler.h:173
MessagePtr< TMsg > receiveTypedMessage()
Receives the message of the particular type.
Definition: Gateway.h:308