ED247 Library  VA2.3.0
Implementation of ED247-A standard
ed247_cominterface.h
1 /* -*- mode: c++; c-basic-offset: 2 -*- */
2 /******************************************************************************
3  * The MIT Licence
4  *
5  * Copyright (c) 2021 Airbus Operations S.A.S
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11  * and/or sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included
15  * in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23  * OTHER DEALINGS IN THE SOFTWARE.
24  *****************************************************************************/
25 #ifndef _ED247_COMINTERFACE_H_
26 #define _ED247_COMINTERFACE_H_
27 #include "ed247_xml.h"
28 #include "ed247_friend_test.h"
29 #include <functional>
30 
31 // Networking
32 #ifdef __unix__
33 # include <sys/socket.h>
34 # include <netinet/in.h>
35 # include <sys/select.h>
36 using ed247_socket_t = int;
37 # define INVALID_SOCKET (-1)
38 #elif _WIN32
39 # include <winsock2.h>
40 using ed247_socket_t = SOCKET;
41 #endif
42 
43 
44 //
45 // socket_address_t : store a network address (ip/port)
46 //
47 namespace ed247 {
48  namespace udp {
50  {
51  socket_address_t(std::string ip_address, uint16_t ip_port);
52  void set_ip_address(std::string ip_address);
53  void set_ip_port(uint16_t ip_port);
54  bool is_multicast() const;
55  bool is_unicast() const;
56  bool is_any_addr() const;
57  };
58  }
59 }
60 std::ostream& operator<<(std::ostream & os, const ed247::udp::socket_address_t& socket_address);
61 
62 
63 
64 namespace ed247 {
65 
66  class Context;
67 
68  namespace udp {
69 
70  //
71  // Transceiver (aka ECIC UdpSocket)
72  // Hold a system socket and prepare it for transceiving.
73  // base class for emitter and receiver.
74  //
75  class Transceiver {
76  public:
77  Transceiver(Context* context, const socket_address_t& socket_address);
78  ~Transceiver();
79 
80  Transceiver(const Transceiver&) = delete;
81  Transceiver& operator=(const Transceiver&) = delete;
82 
83  const ed247_socket_t& get_socket() const { return _socket; }
84 
85  protected:
86  Context* _context;
87  socket_address_t _socket_address; // Where the packets come from (regardless direction)
88  ed247_socket_t _socket{INVALID_SOCKET}; // Where the packets come from (regardless direction)
89  };
90 
91  class Emitter : public Transceiver
92  {
93  public:
94  Emitter(Context* context, socket_address_t from_address, socket_address_t destination_address, uint16_t multicast_ttl = 1);
95  void send_frame(const void* payload, const uint32_t payload_size);
96 
97  private:
98  socket_address_t _destination_address;
99  };
100 
101  class Receiver : public Transceiver
102  {
103  public:
104  static const uint32_t MAX_FRAME_SIZE{65508};
105  struct frame_t
106  {
107  char payload[MAX_FRAME_SIZE];
108  uint32_t size{MAX_FRAME_SIZE};
109  };
110 
111  using receive_callback_t = std::function<void(const char* payload, uint32_t size)>;
112 
113  Receiver(Context* context,
114  socket_address_t from_address,
115  socket_address_t multicast_interface,
116  receive_callback_t callback);
117  void receive();
118 
119  private:
120  receive_callback_t _receive_callback;
121  frame_t& _receive_frame; // Reference to ReceiverSet::_receive_frame
122 
123  ED247_FRIEND_TEST();
124  };
125 
126  //
127  // ReceiverSet
128  // Store receiver and allows to receive data on all of them.
129  // There is only one of this class per context.
130  //
132  {
133  public:
134  ReceiverSet();
135  ~ReceiverSet();
136 
137  ReceiverSet& operator=(const ReceiverSet &) = delete;
138  ReceiverSet& operator=(ReceiverSet &&) = delete;
139 
140  // Add receiver and take onership
141  void emplace(Receiver* receiver);
142 
143  // Receive frames from all registered receivers.
144  // Call receive_callback(s) set by ComInterface::load()
145  ed247_status_t wait_frame(int32_t timeout_us);
146  ed247_status_t wait_during(int32_t duration_us);
147 
148  // Frame to be used by the receivers.
149  // All receivers of the same set will share the same memory to prevent 65k alloc per receiver
150  Receiver::frame_t& get_receive_frame() { return _receive_frame; }
151 
152  private:
153  std::vector<std::unique_ptr<Receiver>> _receivers;
154  Receiver::frame_t _receive_frame;
155 
156  struct select_options_s {
157  fd_set fd;
158  int nfds;
159  } _select_options;
160 
161  ED247_FRIEND_TEST();
162  };
163 
164 
165  //
166  // ComInterface
167  // The ComInterface will load all its transceivers (aka ECIC UdpSokets) and :
168  // - Store its emitters to allow to send_frame to all of them,
169  // - Store its receivers in context_receiver_set to allow to receive on all context receivers.
170  //
172  {
173  public:
174  // Load configuration and
175  // - store emmiters
176  // - store receivers in context_receiver_set,
177  // - set receive_callback on each of them.
178  void load(const xml::ComInterface& configuration,
179  Receiver::receive_callback_t receive_callback);
180 
181  // Send a frame to all ComInterface emitters
182  void send_frame(const void* payload, const uint32_t payload_size);
183 
184  ComInterface(Context* context);
185  ~ComInterface();
186 
187  private:
188  Context* _context;
189  std::vector<std::unique_ptr<Emitter>> _emitters;
190  };
191 
192 
193  // throw an exception if not all socket are closed (debug purpose)
194  void assert_sockets_closed();
195  }
196 }
197 
198 #endif
Definition: ed247_cominterface.h:131
Definition: ed247_cominterface.h:75
Definition: ed247_cominterface.h:101
Definition: ed247_xml.h:63
Definition: ed247_cominterface.h:105
Definition: ed247_cominterface.h:91
Definition: ed247_context.h:36
Definition: ed247_cominterface.h:49
ed247_status_t
Status codes.
Definition: ed247.h:67
Definition: ed247_channel.cpp:37
Definition: ed247_cominterface.h:171