XPMP2
X-Plane multiplayer library 2 - using instancing
Network.h
Go to the documentation of this file.
1 
27 #ifndef Network_h
28 #define Network_h
29 
30 #include <sys/types.h>
31 #if IBM
32 #include <winsock2.h>
33 #include <ws2ipdef.h> // required for sockaddr_in6 (?)
34 #include <iphlpapi.h> // for GetAdaptersAddresses
35 #include <WS2tcpip.h> // for socklen_t
36 #include <MSWSock.h> // for LPFN_WSARECVMSG
37 #else
38 #define __APPLE_USE_RFC_3542 // both required for newer constants like IPV6_RECVPKTINFO
39 #define _GNU_SOURCE
40 #include <sys/socket.h>
41 #include <netdb.h>
42 #include <ifaddrs.h>
43 typedef int SOCKET;
44 constexpr SOCKET INVALID_SOCKET = -1;
45 #endif
46 
47 #include <stdexcept>
48 
49 namespace XPMP2 {
50 
52 struct SockAddrTy
53 {
54  union {
55  sockaddr sa; // unspecific
56  sockaddr_in sa_in; // AF_INET / IPv4
57  sockaddr_in6 sa_in6; // AF_INET6 / IPv6
58  };
59 
61  SockAddrTy() { memset((void*)this, 0, sizeof(SockAddrTy)); }
63  SockAddrTy (const sockaddr* pSa);
64 
66  bool operator< (const SockAddrTy& o) const
67  { return std::memcmp(this, &o, sizeof(*this)) < 0; }
69  bool operator== (const SockAddrTy& o) const
70  { return std::memcmp(this, &o, sizeof(*this)) == 0; }
71 
72  uint8_t family() const { return (uint8_t) sa.sa_family; }
73  bool isIp4() const { return family() == AF_INET; }
74  bool isIp6() const { return family() == AF_INET6; }
75  socklen_t size () const
76  { return
77  sa.sa_family == AF_INET ? sizeof(sa_in) :
78  sa.sa_family == AF_INET6 ? sizeof(sa_in6) : sizeof(sa); }
79 
81  uint16_t port () const {
82  return ntohs(isIp4() ? sa_in.sin_port :
83  isIp6() ? sa_in6.sin6_port : 0);
84  }
86  void setPort (uint16_t port) {
87  if (isIp4()) sa_in.sin_port = htons(port);
88  else if (isIp6()) sa_in6.sin6_port = htons(port);
89  }
90 };
91 
96 class NetRuntimeError : public std::runtime_error
97 {
98 public:
99  std::string errTxt;
100  std::string fullWhat;
101  NetRuntimeError(const std::string& w);
103  const char* what() const noexcept override { return fullWhat.c_str(); }
104 };
105 
109 {
110 protected:
112  int f_port = 0;
113  std::string f_addr;
114 
115  // the data receive buffer
116  char* buf = NULL;
117  size_t bufSize = 512;
118 
119 #if IBM
121  LPFN_WSARECVMSG pWSARecvMsg = nullptr;
122 #endif
123 public:
127  virtual ~SocketNetworking();
128 
130  virtual void Open(const std::string& _addr, int _port, size_t _bufSize = 512,
131  unsigned _timeOut_ms = 0, bool _bBroadcast = false);
133  virtual void Connect(const std::string& _addr, int _port, size_t _bufSize,
134  unsigned _timeOut_ms = 0);
136  virtual void Close();
138  inline bool isOpen() const { return (f_socket != INVALID_SOCKET); }
140  void SetBufSize (size_t _bufSize);
142  static std::string GetLastErr();
143 
144  // attribute access
145  SOCKET getSocket() const { return f_socket; }
146  int getPort() const { return f_port; }
147  std::string getAddr() const { return f_addr; }
148 
150  const char* getBuf () const { return buf ? buf : ""; }
151 
153  void setBlocking (bool bBlock);
154 
159  long recv(std::string* _pFromAddr = nullptr,
160  SockAddrTy* _pFromSockAddr = nullptr);
166  long timedRecv(int max_wait_ms,
167  std::string* _pFromAddr = nullptr,
168  SockAddrTy* _pFromSockAddr = nullptr);
169 
171  virtual bool send(const char* msg);
172 
174  bool broadcast (const char* msg);
175 
177  static std::string GetAddrString (const SockAddrTy& sa, bool withPort = true);
178 
179 protected:
181  virtual void GetAddrHints (struct addrinfo& hints) = 0;
182 #if IBM
186  int WSARecvMsg(
187  LPWSAMSG lpMsg,
188  LPDWORD lpdwNumberOfBytesRecvd,
189  LPWSAOVERLAPPED lpOverlapped,
190  LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);
191 #endif
192 };
193 
194 
197 {
198 public:
201 
202 protected:
204  void GetAddrHints (struct addrinfo& hints) override;
205 };
206 
207 
211 {
212 protected:
213  std::string multicastAddr;
214  struct addrinfo* pMCAddr = nullptr;
215 
216  bool bSendToAll = true;
217  uint32_t oneIntfIdx = 0;
218 
220  std::map<SockAddrTy,std::chrono::time_point<std::chrono::steady_clock> > mapSender;
221 
222 public:
226  UDPMulticast(const std::string& _multicastAddr, int _port,
227  const std::string& _sendIntf,
228  int _ttl=8, size_t _bufSize = 512, unsigned _timeOut_ms = 0);
230  ~UDPMulticast() override;
231 
233  const std::string& GetMCAddr() const { return multicastAddr; }
234 
237  void Join (const std::string& _multicastAddr, int _port,
238  const std::string& _sendIntf,
239  int _ttl=8, size_t _bufSize = 512, unsigned _timeOut_ms = 0);
240 
242  uint8_t GetFamily () const { return pMCAddr ? (uint8_t)pMCAddr->ai_family : AF_UNSPEC; }
243  bool IsIPv4 () const { return GetFamily() == AF_INET; }
244  bool IsIPv6 () const { return GetFamily() == AF_INET6; }
245 
247  void SendToDefault ();
249  void SendToAll ();
251  void SendToIntf (uint32_t idx);
252 
257  size_t SendMC (const void* _bufSend, size_t _bufSendSize);
258 
265  size_t RecvMC (bool bSwitchToRecvIntf,
266  std::string* _pFromAddr = nullptr,
267  SockAddrTy* _pFromSockAddr = nullptr,
268  bool* _pbIntfChanged = nullptr);
269 
270 protected:
271  void Cleanup ();
273  void GetAddrHints (struct addrinfo& hints) override;
275  void SetSendInterface (const in_addr& addr);
277  void SetSendInterface (uint32_t ifIdx);
278 };
279 
280 
283 {
284 protected:
286  struct sockaddr_in f_session_addr = {};
287 #if APL == 1 || LIN == 1
289  SOCKET selfPipe[2] = { INVALID_SOCKET, INVALID_SOCKET };
290 #endif
291 
292 public:
295 
296  void Close() override;
297  void CloseListenerOnly();
298 
299  void listen (int numConnections = 1);
300  bool accept (bool bUnlisten = false);
301  bool listenAccept (int numConnections = 1);
302 
304  bool IsConnected () const { return f_session_socket != INVALID_SOCKET; };
305 
307  bool send(const char* msg) override;
308 
309 protected:
310  void GetAddrHints (struct addrinfo& hints) override;
311 };
312 
313 
315 struct InetAddrTy {
316  union {
317  std::uint32_t addr[4] = {0,0,0,0};
318  struct in_addr in_addr;
319  struct in6_addr in6_addr;
320  };
321 
325  InetAddrTy (const SockAddrTy& sa) { CopyFrom(sa); }
327  InetAddrTy (const sockaddr* pSa) { CopyFrom(SockAddrTy(pSa)); }
328 
330  void CopyFrom (const SockAddrTy& sa);
331 
333  bool operator==(const InetAddrTy& o) const
334  { return std::memcmp(this, &o, sizeof(*this)) == 0; }
335 
337  bool operator<(const InetAddrTy& o) const
338  { return std::memcmp(this, &o, sizeof(*this)) < 0; }
339 
340 };
341 
343 bool NetwIsLocalAddr (const InetAddrTy& addr);
345 inline bool NetwIsLocalAddr (const SockAddrTy& sa)
346 { return NetwIsLocalAddr(InetAddrTy(sa)); }
348 inline bool NetwIsLocalAddr (const sockaddr* pSa)
349 { return NetwIsLocalAddr(InetAddrTy(pSa)); }
350 
356 std::vector<std::string> NetwGetInterfaces (uint8_t family, uint32_t fMust = 0, uint32_t fSkip = 0);
358 std::string NetwGetInterfaceNames (uint8_t family, uint32_t fMust = 0, uint32_t fSkip = 0);
359 
360 } // namespace XPMP2
361 
362 #endif /* Network_h */
constexpr SOCKET INVALID_SOCKET
Definition: Network.h:44
int SOCKET
Windows defines SOCKET, so we define it for non-Windows manually.
Definition: Network.h:43
Exception raised by XPMP2::SocketNetworking objects.
Definition: Network.h:97
std::string errTxt
OS text for what errno says, output of strerror_s()
Definition: Network.h:99
std::string fullWhat
combines w and errTxt
Definition: Network.h:100
NetRuntimeError(const std::string &w)
Definition: Network.cpp:353
const char * what() const noexcept override
Return the full message, ie. fullWhat
Definition: Network.h:103
Base class for any socket-based networking.
Definition: Network.h:109
virtual ~SocketNetworking()
Destructor makes sure the socket is closed.
Definition: Network.cpp:366
SOCKET getSocket() const
the socket
Definition: Network.h:145
bool isOpen() const
Is a socket open?
Definition: Network.h:138
const char * getBuf() const
return the buffer
Definition: Network.h:150
static std::string GetAddrString(const SockAddrTy &sa, bool withPort=true)
Convert addresses to string.
Definition: Network.cpp:758
virtual void Close()
Thread-safely close the connection(s) and frees the buffer.
Definition: Network.cpp:531
SOCKET f_socket
Definition: Network.h:111
size_t bufSize
Definition: Network.h:117
virtual void Open(const std::string &_addr, int _port, size_t _bufSize=512, unsigned _timeOut_ms=0, bool _bBroadcast=false)
Creates a socket and binds it to the given local address.
Definition: Network.cpp:371
virtual bool send(const char *msg)
send messages on session connection
Definition: Network.cpp:706
std::string f_addr
Definition: Network.h:113
SocketNetworking()
Default constructor is not doing anything.
Definition: Network.h:125
int f_port
Definition: Network.h:112
long timedRecv(int max_wait_ms, std::string *_pFromAddr=nullptr, SockAddrTy *_pFromSockAddr=nullptr)
Waits to receive a message with timeout, ensures zero-termination in the buffer.
Definition: Network.cpp:662
virtual void Connect(const std::string &_addr, int _port, size_t _bufSize, unsigned _timeOut_ms=0)
Creates a socket and connects it to the given remote server.
Definition: Network.cpp:464
void SetBufSize(size_t _bufSize)
(Re)Sets the buffer size (or clears it if _bufSize==0)
Definition: Network.cpp:545
static std::string GetLastErr()
Returns a human-readable text for the last error.
Definition: Network.cpp:563
void setBlocking(bool bBlock)
Set blocking mode.
Definition: Network.cpp:582
virtual void GetAddrHints(struct addrinfo &hints)=0
Subclass to tell which addresses to look for.
char * buf
Definition: Network.h:116
long recv(std::string *_pFromAddr=nullptr, SockAddrTy *_pFromSockAddr=nullptr)
Waits to receive a message, ensures zero-termination in the buffer.
Definition: Network.cpp:613
std::string getAddr() const
the interface address
Definition: Network.h:147
bool broadcast(const char *msg)
Sends a broadcast message.
Definition: Network.cpp:729
int getPort() const
the port
Definition: Network.h:146
Listens to TCP connections and opens a session socket upon connect.
Definition: Network.h:283
bool IsConnected() const
Connected to a counterparty?
Definition: Network.h:304
void listen(int numConnections=1)
listen for incoming connections
Definition: Network.cpp:1307
bool accept(bool bUnlisten=false)
accept an incoming connections, optinally stop listening
Definition: Network.cpp:1313
void Close() override
also close session connection
Definition: Network.cpp:1277
void GetAddrHints(struct addrinfo &hints) override
Subclass to tell which addresses to look for.
Definition: Network.cpp:1409
void CloseListenerOnly()
only closes the listening socket, but not a connected session
Definition: Network.cpp:1290
bool send(const char *msg) override
send messages on session connection
Definition: Network.cpp:1385
SOCKET f_session_socket
session socket, ie. the socket opened when a counterparty connects
Definition: Network.h:285
TCPConnection()
Default constructor is not doing anything.
Definition: Network.h:294
struct sockaddr_in f_session_addr
address of the connecting counterparty
Definition: Network.h:286
bool listenAccept(int numConnections=1)
combines listening and accepting
Definition: Network.cpp:1332
UDP Multicast, always binding to INADDR_ANY.
Definition: Network.h:211
const std::string & GetMCAddr() const
Return formatted multicast address, including port.
Definition: Network.h:233
void Join(const std::string &_multicastAddr, int _port, const std::string &_sendIntf, int _ttl=8, size_t _bufSize=512, unsigned _timeOut_ms=0)
Connect to the multicast group.
Definition: Network.cpp:837
void SendToIntf(uint32_t idx)
Send future datagrams on this particular interface only.
Definition: Network.cpp:1009
void SendToAll()
Send future datagrams on all interfaces.
Definition: Network.cpp:998
size_t RecvMC(bool bSwitchToRecvIntf, std::string *_pFromAddr=nullptr, SockAddrTy *_pFromSockAddr=nullptr, bool *_pbIntfChanged=nullptr)
Receive a multicast, received message is in XPMP2::SocketNetworking::GetBuf()
Definition: Network.cpp:1086
~UDPMulticast() override
makes sure pMCAddr is cleared up
Definition: Network.cpp:831
void SendToDefault()
Send future datagrams on default interfaces only (default)
Definition: Network.cpp:975
bool IsIPv6() const
IPv6?
Definition: Network.h:244
void SetSendInterface(const in_addr &addr)
Set multicast send interface (IPv4 only)
Definition: Network.cpp:1240
uint32_t oneIntfIdx
When sending to one interface only, which one?
Definition: Network.h:217
struct addrinfo * pMCAddr
the multicast address
Definition: Network.h:214
size_t SendMC(const void *_bufSend, size_t _bufSendSize)
Send a multicast.
Definition: Network.cpp:1029
std::map< SockAddrTy, std::chrono::time_point< std::chrono::steady_clock > > mapSender
Keep a list of sources we received data from to be able to identify new sources.
Definition: Network.h:220
std::string multicastAddr
the multicast address
Definition: Network.h:213
UDPMulticast()
Default constructor is not doing anything.
Definition: Network.h:224
uint8_t GetFamily() const
Protocol family.
Definition: Network.h:242
bool IsIPv4() const
IPv4?
Definition: Network.h:243
void GetAddrHints(struct addrinfo &hints) override
returns information from *pMCAddr
Definition: Network.cpp:1229
void Cleanup()
Definition: Network.cpp:1218
bool bSendToAll
Send out multicast datagrams to all interfaces.
Definition: Network.h:216
Receives UDP messages.
Definition: Network.h:197
UDPReceiver()
Default constructor is not doing anything.
Definition: Network.h:200
void GetAddrHints(struct addrinfo &hints) override
Sets flags to AI_PASSIVE, AF_INET, SOCK_DGRAM, IPPROTO_UDP.
Definition: Network.cpp:809
Definition: XPMPAircraft.h:70
bool NetwIsLocalAddr(const InetAddrTy &addr)
Is given address a local one?
Definition: Network.cpp:1445
std::vector< std::string > NetwGetInterfaces(uint8_t family, uint32_t fMust, uint32_t fSkip)
Return list of known local interfaces.
Definition: Network.cpp:301
std::string NetwGetInterfaceNames(uint8_t family, uint32_t fMust, uint32_t fSkip)
Return comma-separated string will all known local interfaces, calls NetwGetInterfaces()
Definition: Network.cpp:315
Numerical IP address, used for both ipv4 and ipv6, for ease of handling.
Definition: Network.h:315
InetAddrTy(const sockaddr *pSa)
Take over from structure.
Definition: Network.h:327
void CopyFrom(const SockAddrTy &sa)
Take over address from structure.
Definition: Network.cpp:1422
bool operator<(const InetAddrTy &o) const
Comparison also uses memcmp for defined order.
Definition: Network.h:337
bool operator==(const InetAddrTy &o) const
Equality means: all elements are equal.
Definition: Network.h:333
InetAddrTy()
Default does nothing.
Definition: Network.h:323
InetAddrTy(const SockAddrTy &sa)
Take over from structure.
Definition: Network.h:325
Helper definition for all these IPv4/6 differences.
Definition: Network.h:53
bool operator<(const SockAddrTy &o) const
Comparison bases solely on memory compare, order isn't important, just that there is order.
Definition: Network.h:66
bool isIp4() const
is this an IPv4 address?
Definition: Network.h:73
uint16_t port() const
Get the port number.
Definition: Network.h:81
bool operator==(const SockAddrTy &o) const
Comparison bases solely on memory compare, order isn't important, just that there is order.
Definition: Network.h:69
bool isIp6() const
is this an IPv6 address?
Definition: Network.h:74
socklen_t size() const
< expected structure size as per protocol family
Definition: Network.h:75
uint8_t family() const
return the protocol famaily
Definition: Network.h:72
void setPort(uint16_t port)
Set the port number.
Definition: Network.h:86
SockAddrTy()
Constructor zeroes out everying.
Definition: Network.h:61