OpenClonk
C4NetIO.h
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
5  * Copyright (c) 2009-2016, The OpenClonk Team and contributors
6  *
7  * Distributed under the terms of the ISC license; see accompanying file
8  * "COPYING" for details.
9  *
10  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
11  * See accompanying file "TRADEMARK" for details.
12  *
13  * To redistribute this file separately, substitute the full license texts
14  * for the above references.
15  */
16 /* network i/o, featuring tcp, udp and multicast */
17 
18 #ifndef C4NETIO_H
19 #define C4NETIO_H
20 
21 #include "lib/StdCompiler.h"
22 #include "platform/StdScheduler.h"
23 #include "platform/StdSync.h"
24 
25 #ifdef _WIN32
27 #include <winsock2.h>
28 #include <ws2tcpip.h>
29 #ifndef WINSOCK_VERSION
30 #define WINSOCK_VERSION MAKEWORD(2,2)
31 #endif
32 // Events are Windows-specific
33 #define HAVE_WINSOCK
34 #else
35 #define SOCKET int
36 #define INVALID_SOCKET (-1)
37 #include <arpa/inet.h>
38 // for htons
39 #include <netinet/in.h>
40 #endif
41 
42 #ifdef HAVE_SYS_TYPES_H
43 #include <sys/types.h>
44 #endif
45 #ifdef HAVE_SYS_SOCKET_H
46 #include <sys/socket.h>
47 #endif
48 
49 #ifndef SOCK_CLOEXEC
50 #define SOCK_CLOEXEC 0
51 #endif
52 
53 #ifndef HAVE_CONFIG_H
54 // #define C4NETIO_DEBUG
55 #endif
56 
57 
58 // net i/o base class
59 class C4NetIO : public StdSchedulerProc
60 {
61 public:
62  C4NetIO();
63  ~C4NetIO() override;
64 
65  // *** constants / types
66  static const int TO_INF; // = -1;
67 
68  struct HostAddress
69  {
71  {
72  IPv6 = AF_INET6,
73  IPv4 = AF_INET,
75  };
77  {
78  Loopback, // IPv6 localhost (::1)
79  Any, // IPv6 any-address (::)
80  AnyIPv4 // IPv4 any-address (0.0.0.0)
81  };
82 
84  {
87  };
88 
89  HostAddress() { Clear(); }
90  HostAddress(const HostAddress &other) { SetHost(other); }
92  explicit HostAddress(uint32_t addr) { SetHost(addr); }
93  HostAddress(const StdStrBuf &addr) { SetHost(addr); }
94  HostAddress(const sockaddr *addr) { SetHost(addr); }
95 
96  AddressFamily GetFamily() const;
97  size_t GetAddrLen() const;
98 
99  void SetScopeId(int scopeId);
100  int GetScopeId() const;
101 
102  void Clear();
103  void SetHost(const sockaddr *addr);
104  void SetHost(const HostAddress &host);
105  void SetHost(SpecialAddress host);
106  void SetHost(const StdStrBuf &host, AddressFamily family = UnknownFamily);
107  void SetHost(uint32_t host);
108 
109  C4NetIO::HostAddress AsIPv6() const; // convert an IPv4 address to an IPv6-mapped IPv4 address
110  C4NetIO::HostAddress AsIPv4() const; // try to convert an IPv6-mapped IPv4 address to an IPv4 address (returns unchanged address if not possible)
111 
112  // General categories
113  bool IsNull() const;
114  bool IsMulticast() const;
115  bool IsLoopback() const;
116  bool IsLocal() const; // IPv6 link-local address
117  bool IsPrivate() const; // IPv6 ULA or IPv4 private address range
118 // bool IsBroadcast() const;
119 
120  StdStrBuf ToString(int flags = 0) const;
121 
122  bool operator ==(const HostAddress &rhs) const;
123  bool operator !=(const HostAddress &rhs) const { return !(*this == rhs); }
124 
125  protected:
126  // data
127  union
128  {
129  sockaddr gen;
130  sockaddr_in v4;
131  sockaddr_in6 v6;
132  };
133  };
134 
135  struct EndpointAddress : public HostAddress // Host and port
136  {
137  static const uint16_t IPPORT_NONE = 0;
138 
140  EndpointAddress(const EndpointAddress &other) : HostAddress() { SetAddress(other); }
141  EndpointAddress(const HostAddress &host, uint16_t port = IPPORT_NONE) : HostAddress(host) { SetPort(port); }
142  EndpointAddress(HostAddress::SpecialAddress addr, uint16_t port = IPPORT_NONE) : HostAddress(addr) { SetPort(port); }
143  explicit EndpointAddress(const StdStrBuf &addr) { SetAddress(addr); }
144 
145  StdStrBuf ToString(int flags = 0) const;
146 
147  void Clear();
148 
149  void SetAddress(const sockaddr *addr);
150  void SetAddress(const EndpointAddress &other);
151  void SetAddress(HostAddress::SpecialAddress addr, uint16_t port = IPPORT_NONE);
152  void SetAddress(const HostAddress &host, uint16_t port = IPPORT_NONE);
153  void SetAddress(const StdStrBuf &addr, AddressFamily family = UnknownFamily);
154 
155  HostAddress GetHost() const { return *this; } // HostAddress copy ctor slices off port information
156  EndpointAddress AsIPv6() const; // convert an IPv4 address to an IPv6-mapped IPv4 address
157  EndpointAddress AsIPv4() const; // try to convert an IPv6-mapped IPv4 address to an IPv4 address (returns unchanged address if not possible)
158 
159  void SetPort(uint16_t port);
160  void SetDefaultPort(uint16_t port); // set a port only if there is none
161  uint16_t GetPort() const;
162 
163  bool IsNull() const;
164  bool IsNullHost() const { return HostAddress::IsNull(); }
165 
166  // Pointer wrapper to be able to implicitly convert to sockaddr*
167  class EndpointAddressPtr;
168  const EndpointAddressPtr operator &() const;
169  EndpointAddressPtr operator &();
171  {
172  EndpointAddress * const p;
174  friend const EndpointAddressPtr EndpointAddress::operator &() const;
175  EndpointAddressPtr(EndpointAddress *p) : p(p) {}
176  public:
177  const EndpointAddress &operator *() const { return *p; }
178  EndpointAddress &operator *() { return *p; }
179 
180  const EndpointAddress &operator ->() const { return *p; }
181  EndpointAddress &operator ->() { return *p; }
182 
183  operator const EndpointAddress*() const { return p; }
184  operator EndpointAddress*() { return p; }
185 
186  operator const sockaddr*() const { return &p->gen; }
187  operator sockaddr*() { return &p->gen; }
188 
189  operator const sockaddr_in*() const { return &p->v4; }
190  operator sockaddr_in*() { return &p->v4; }
191 
192  operator const sockaddr_in6*() const { return &p->v6; }
193  operator sockaddr_in6*() { return &p->v6; }
194  };
195 
196  bool operator ==(const EndpointAddress &rhs) const;
197  bool operator !=(const EndpointAddress &rhs) const { return !(*this == rhs); }
198 
199  // conversions
200  operator sockaddr() const { return gen; }
201  operator sockaddr_in() const { assert(gen.sa_family == AF_INET); return v4; }
202  operator sockaddr_in6() const { assert(gen.sa_family == AF_INET6); return v6; }
203 
204  // StdCompiler
205  void CompileFunc(StdCompiler *comp);
206 
207  private:
208  bool SetAddressByString(const StdStrBuf &address, short family);
209 
210  friend class EndpointAddressPtr;
211  };
213 
214  static std::vector<HostAddress> GetLocalAddresses();
215 
216  // callback class
217  class CBClass
218  {
219  public:
220  virtual bool OnConn(const addr_t &AddrPeer, const addr_t &AddrConnect, const addr_t *pOwnAddr, C4NetIO *pNetIO) { return true; }
221  virtual void OnDisconn(const addr_t &AddrPeer, C4NetIO *pNetIO, const char *szReason) { }
222  virtual void OnPacket(const class C4NetIOPacket &rPacket, C4NetIO *pNetIO) = 0;
223  virtual ~CBClass() = default;
224  };
225 
226  // used to explicitly callback to a specific class
227  template <class T>
228  class CBProxy : public CBClass
229  {
230  T *pTarget;
231  public:
232  CBProxy *operator () (T *pnTarget) { pTarget = pnTarget; return this; }
233  bool OnConn(const addr_t &AddrPeer, const addr_t &AddrConnect, const addr_t *pOwnAddr, C4NetIO *pNetIO) override
234  { return pTarget->T::OnConn(AddrPeer, AddrConnect, pOwnAddr, pNetIO); }
235  void OnDisconn(const addr_t &AddrPeer, C4NetIO *pNetIO, const char *szReason) override
236  { pTarget->T::OnDisconn(AddrPeer, pNetIO, szReason); }
237  void OnPacket(const class C4NetIOPacket &rPacket, C4NetIO *pNetIO) override
238  { pTarget->T::OnPacket(rPacket, pNetIO); }
239  };
240 
241 #ifdef _MSC_VER
242 #define NETIO_CREATE_CALLBACK_PROXY(ForClass, ProxyName) \
243  typedef class C4NetIO::CBProxy<ForClass> CBProxyT; \
244  friend CBProxyT; \
245  CBProxyT ProxyName;
246 #else
247 #define NETIO_CREATE_CALLBACK_PROXY(ForClass, ProxyName) \
248  friend class C4NetIO::CBProxy<ForClass>; \
249  C4NetIO::CBProxy<ForClass> ProxyName;
250 #endif
251 
252  // *** interface
253 
254  // * not multithreading safe
255  virtual bool Init(uint16_t iPort = addr_t::IPPORT_NONE) = 0;
256  virtual bool Close() = 0;
257 
258  bool Execute(int iTimeout = -1, pollfd * = nullptr) override = 0; // (for StdSchedulerProc)
259  bool IsNotify() override { return true; }
260 
261  // * multithreading safe
262  virtual bool Connect(const addr_t &addr) = 0; // async!
263  virtual bool Close(const addr_t &addr) = 0;
264 
265  virtual bool Send(const class C4NetIOPacket &rPacket) = 0;
266  virtual bool SetBroadcast(const addr_t &addr, bool fSet = true) = 0;
267  virtual bool Broadcast(const class C4NetIOPacket &rPacket) = 0;
268 
269  // statistics
270  virtual bool GetStatistic(int *pBroadcastRate) = 0;
271  virtual bool GetConnStatistic(const addr_t &addr, int *pIRate, int *pORate, int *pLoss) = 0;
272  virtual void ClearStatistic() = 0;
273 
274 protected:
275 // virtual SOCKET CreateSocket() = 0;
276 
277  // Makes IPv4 connections from an IPv6 socket work.
278  bool InitIPv6Socket(SOCKET socket);
279 
280  // *** errors
281 protected:
283  void SetError(const char *strnError, bool fSockErr = false);
284 public:
285  virtual const char *GetError() const { return Error.getData(); }
286  void ResetError() { Error.Clear(); }
287 
288  // *** callbacks
289  virtual void SetCallback(CBClass *pnCallback) = 0;
290 
291 };
292 
293 // packet class
294 class C4NetIOPacket : public StdCopyBuf
295 {
296 public:
297 
298  C4NetIOPacket();
299 
300  // construct from memory (copies / references data)
301  C4NetIOPacket(const void *pnData, size_t inSize, bool fCopy = false, const C4NetIO::addr_t &naddr = C4NetIO::addr_t());
302  // construct from buffer (copies data)
303  explicit C4NetIOPacket(const StdBuf &Buf, const C4NetIO::addr_t &naddr);
304  // construct from status byte + buffer (copies data)
305  C4NetIOPacket(uint8_t cStatusByte, const char *pnData, size_t inSize, const C4NetIO::addr_t &naddr = C4NetIO::addr_t());
306 
307  ~C4NetIOPacket();
308 
309 protected:
310 
311  // address
313 
314 public:
315 
316  const C4NetIO::addr_t &getAddr() const { return addr; }
317 
318  uint8_t getStatus()const { return getSize() ? *getBufPtr<char>(*this) : 0; }
319  const char *getPData() const { return getSize() ? getBufPtr<char>(*this, 1) : nullptr; }
320  size_t getPSize() const { return getSize() ? getSize() - 1 : 0; }
321  StdBuf getPBuf() const { return getSize() ? getPart(1, getSize() - 1) : getRef(); }
322 
323  // Some overloads
324  C4NetIOPacket getRef() const { return C4NetIOPacket(StdBuf::getRef(), addr); }
326  // change addr
327  void SetAddr(const C4NetIO::addr_t &naddr) { addr = naddr; }
328 
329  // delete contents
330  void Clear();
331 };
332 
333 
334 // tcp network i/o
335 class C4NetIOTCP : public C4NetIO, protected CStdCSecExCallback
336 {
337 public:
338  C4NetIOTCP();
339  ~C4NetIOTCP() override;
340 
341  // Socket is an unconnected, but bound socket.
342  class Socket
343  {
344  SOCKET sock;
345  Socket(SOCKET s) : sock(s) { }
346  friend class C4NetIOTCP;
347  public:
348  ~Socket();
349  // GetAddress returns the address the socket is bound to.
350  C4NetIO::addr_t GetAddress();
351  };
352 
353  // *** interface
354 
355  // * not multithreading safe
356  bool Init(uint16_t iPort = addr_t::IPPORT_NONE) override;
357  virtual bool InitBroadcast(addr_t *pBroadcastAddr);
358  bool Close() override;
359  virtual bool CloseBroadcast();
360 
361  bool Execute(int iMaxTime = TO_INF, pollfd * readyfds = nullptr) override;
362 
363  // * multithreading safe
364  std::unique_ptr<Socket> Bind(const addr_t &addr);
365  bool Connect(const addr_t &addr, std::unique_ptr<Socket> socket);
366  bool Connect(const addr_t &addr) override;
367  bool Close(const addr_t &addr) override;
368 
369  bool Send(const C4NetIOPacket &rPacket) override;
370  bool Broadcast(const C4NetIOPacket &rPacket) override;
371  bool SetBroadcast(const addr_t &addr, bool fSet = true) override;
372 
373  virtual void UnBlock();
374 #ifdef STDSCHEDULER_USE_EVENTS
375  HANDLE GetEvent() override;
376 #else
377  void GetFDs(std::vector<struct pollfd> & FDs) override;
378 #endif
379 
380  // statistics
381  bool GetStatistic(int *pBroadcastRate) override;
382  bool GetConnStatistic(const addr_t &addr, int *pIRate, int *pORate, int *pLoss) override;
383  void ClearStatistic() override;
384 
385 protected:
386 
387  // * overridables (packet format)
388 
389  // Append packet data to output buffer
390  virtual void PackPacket(const C4NetIOPacket &rPacket, StdBuf &rOutBuf);
391 
392  // Extract a packet from the start of the input buffer (if possible) and call OnPacket.
393  // Should return the numer of bytes used.
394  virtual size_t UnpackPacket(const StdBuf &rInBuf, const C4NetIO::addr_t &Addr);
395 
396  // *** data
397 
398  // peer class
399  class Peer
400  {
401  public:
402  Peer(const C4NetIO::addr_t &naddr, SOCKET nsock, C4NetIOTCP *pnParent);
403  ~Peer();
404  protected:
405  // constants
406  static const unsigned int iTCPHeaderSize; // = 28 + 24; // (bytes)
407  static const unsigned int iMinIBufSize; // = 8192; // (bytes)
408  // parent
410  // addr
412  // socket connected
414  // incoming & outgoing buffer
415  StdBuf IBuf, OBuf;
417  // statistics
418  int iIRate, iORate;
419  // status (1 = open, 0 = closed)
420  bool fOpen;
421  // selected for broadcast?
423  // IO critical sections
425  public:
426  // data access
427  const C4NetIO::addr_t &GetAddr() const { return addr; }
428  SOCKET GetSocket() const { return sock; }
429  int GetIRate() const { return iIRate; }
430  int GetORate() const { return iORate; }
431  // send a packet to this peer
432  bool Send(const C4NetIOPacket &rPacket);
433  // send as much data of the interal outgoing buffer as possible
434  bool Send();
435  // request buffer space for new input. Must call OnRecv or NoRecv afterwards!
436  void *GetRecvBuf(int iSize);
437  // called after the buffer returned by GetRecvBuf has been filled with fresh data
438  void OnRecv(int iSize);
439  // close socket
440  void Close();
441  // test: open?
442  bool Open() const { return fOpen; }
443  // selected for broadcast?
444  bool doBroadcast() const { return fDoBroadcast; }
445  // outgoing data waiting?
446  bool hasWaitingData() const { return !OBuf.isNull(); }
447  // select/unselect peer
448  void SetBroadcast(bool fSet) { fDoBroadcast = fSet; }
449  // statistics
450  void ClearStatistics();
451  public:
452  // next peer
454  };
455  friend class Peer;
456  // peer list
457  Peer *pPeerList{nullptr};
458 
459  // small list for waited-for connections
460  struct ConnectWait
461  {
464 
466  }
467  *pConnectWaits{nullptr};
468 
471 
472  // initialized?
473  bool fInit{false};
474 
475  // listen socket
476  uint16_t iListenPort;
478 
479 #ifdef STDSCHEDULER_USE_EVENTS
480  // event indicating network activity
481  HANDLE Event{nullptr};
482 #else
483  // Pipe used for cancelling select
484  int Pipe[2];
485 #endif
486 
487  // *** implementation
488 
489  bool Listen(uint16_t inListenPort);
490 
491  SOCKET CreateSocket(addr_t::AddressFamily family);
492  bool Connect(const addr_t &addr, SOCKET nsock);
493 
494  Peer *Accept(SOCKET nsock = INVALID_SOCKET, const addr_t &ConnectAddr = addr_t());
495  Peer *GetPeer(const addr_t &addr);
496  void OnShareFree(CStdCSecEx *pCSec) override;
497 
498  void AddConnectWait(SOCKET sock, const addr_t &addr);
499  ConnectWait *GetConnectWait(const addr_t &addr);
500  void ClearConnectWaits();
501 
502  // *** callbacks
503 public:
504  void SetCallback(CBClass *pnCallback) override { pCB = pnCallback; };
505 private:
506  CBClass *pCB{nullptr};
507 
508 };
509 
510 // simple udp network i/o
511 // - No connections
512 // - Delivery not garantueed
513 // - Broadcast will multicast the packet to all clients with the same broadcast address.
514 class C4NetIOSimpleUDP : public C4NetIO
515 {
516 public:
518  ~C4NetIOSimpleUDP() override;
519 
520  bool Init(uint16_t iPort = addr_t::IPPORT_NONE) override;
521  virtual bool InitBroadcast(addr_t *pBroadcastAddr);
522  bool Close() override;
523  virtual bool CloseBroadcast();
524 
525  bool Execute(int iMaxTime = TO_INF, pollfd * = nullptr) override;
526 
527  bool Send(const C4NetIOPacket &rPacket) override;
528  bool Broadcast(const C4NetIOPacket &rPacket) override;
529 
530  virtual void UnBlock();
531 #ifdef STDSCHEDULER_USE_EVENTS
532  HANDLE GetEvent() override;
533 #else
534  void GetFDs(std::vector<struct pollfd> & FDs) override;
535 #endif
536 
537  // not implemented
538  bool Connect(const addr_t &addr) override { assert(false); return false; }
539  bool Close(const addr_t &addr) override { assert(false); return false; }
540 
541  bool SetBroadcast(const addr_t &addr, bool fSet = true) override { assert(false); return false; }
542 
543  bool GetStatistic(int *pBroadcastRate) override { assert(false); return false; }
544  bool GetConnStatistic(const addr_t &addr, int *pIRate, int *pORate, int *pLoss) override
545  { assert(false); return false; }
546  void ClearStatistic() override { assert(false); }
547 
548 private:
549  // status
550  bool fInit{false};
551  bool fMultiCast{false};
552  uint16_t iPort;
553 
554  // the socket and the associated event
555  SOCKET sock;
556 #ifdef STDSCHEDULER_USE_EVENTS
557  HANDLE hEvent{nullptr};
558 #else
559  int Pipe[2];
560 #endif
561 
562  // multicast
563  addr_t MCAddr; ipv6_mreq MCGrpInfo;
564  bool fMCLoopback;
565 
566  // multibind
567  int fAllowReUse{false};
568 
569 protected:
570 
571  // multicast address
572  const addr_t &getMCAddr() const { return MCAddr; }
573 
574  // (try to) control loopback
575  bool SetMCLoopback(int fLoopback);
576  bool getMCLoopback() const { return fMCLoopback; }
577 
578  // enable multi-bind (call before Init!)
579  void SetReUseAddress(bool fAllow);
580 
581 private:
582 
583  // socket wait (check for readability)
584  enum WaitResult { WR_Timeout, WR_Readable, WR_Cancelled, WR_Error = -1 };
585  WaitResult WaitForSocket(int iTimeout);
586 
587  // *** callbacks
588 public:
589  void SetCallback(CBClass *pnCallback) override { pCB = pnCallback; };
590 private:
591  CBClass *pCB;
592 
593 };
594 
595 // udp network i/o
596 // - Connection are emulated
597 // - Delivery garantueed
598 // - Broadcast will automatically be activated on one side if it's active on the other side.
599 // If the peer can't be reached through broadcasting, packets will be sent directly.
601 {
602 public:
603  C4NetIOUDP();
604  ~C4NetIOUDP() override;
605 
606  // *** interface
607 
608  bool Init(uint16_t iPort = addr_t::IPPORT_NONE) override;
609  bool InitBroadcast(addr_t *pBroadcastAddr) override;
610  bool Close() override;
611  bool CloseBroadcast() override;
612 
613  bool Execute(int iMaxTime = TO_INF, pollfd * = nullptr) override;
614 
615  bool Connect(const addr_t &addr) override;
616  bool Close(const addr_t &addr) override;
617 
618  bool Send(const C4NetIOPacket &rPacket) override;
619  bool SendDirect(C4NetIOPacket &&rPacket); // (mt-safe)
620  bool Broadcast(const C4NetIOPacket &rPacket) override;
621  bool SetBroadcast(const addr_t &addr, bool fSet = true) override;
622 
624 
625  bool GetStatistic(int *pBroadcastRate) override;
626  bool GetConnStatistic(const addr_t &addr, int *pIRate, int *pORate, int *pLoss) override;
627  void ClearStatistic() override;
628 
629 protected:
630 
631  // *** data
632 
633  // internal packet type ids
634  enum IPTypeID
635  {
636  IPID_Ping = 0,
637  IPID_Test = 1,
638  IPID_Conn = 2,
639  IPID_ConnOK = 3,
640  IPID_AddAddr = 7,
641  IPID_Data = 4,
642  IPID_Check = 5,
643  IPID_Close = 6
644  };
645 
646  // packet structures
647  struct BinAddr;
648  struct PacketHdr; struct TestPacket; struct ConnPacket; struct ConnOKPacket; struct AddAddrPacket;
649  struct DataPacketHdr; struct CheckPacketHdr; struct ClosePacket;
650 
651  // constants
652  static const unsigned int iVersion; // = 2;
653 
654  static const unsigned int iStdTimeout, // = 1000, // (ms)
655  iCheckInterval; // = 1000 // (ms)
656 
657  static const unsigned int iMaxOPacketBacklog; // = 100;
658 
659  static const unsigned int iUDPHeaderSize; // = 8 + 24; // (bytes)
660 
661  // packet class
662  class PacketList;
663  class Packet
664  {
665  friend class PacketList;
666  public:
667 
668  // constants / structures
669  static const size_t MaxSize; // = 1024;
670  static const size_t MaxDataSize; // = MaxSize - sizeof(Header);
671 
672  // types used for packing
673  typedef uint32_t nr_t;
674 
675  // construction / destruction
676  Packet();
677  Packet(C4NetIOPacket &&rnData, nr_t inNr);
678  ~Packet();
679 
680  protected:
681  // data
682  nr_t iNr;
684  bool *pFragmentGot{nullptr};
685 
686  public:
687  // data access
688  C4NetIOPacket &GetData() { return Data; }
689  const C4NetIOPacket &GetData() const { return Data; }
690  nr_t GetNr() const { return iNr; }
691  bool Empty() const { return Data.isNull(); }
692  bool Multicast() const { return !!(Data.getStatus() & 0x80); }
693 
694  // fragmention
695  nr_t FragmentCnt() const;
696  C4NetIOPacket GetFragment(nr_t iFNr, bool fBroadcastFlag = false) const;
697  bool Complete() const;
698  bool FragmentPresent(nr_t iFNr) const;
699  bool AddFragment(const C4NetIOPacket &Packet, const C4NetIO::addr_t &addr);
700  protected:
701  ::size_t FragmentSize(nr_t iFNr) const;
702  // list
703  Packet *Next, *Prev;
704  };
705  friend class Packet;
706 
708  {
709  public:
710  PacketList(unsigned int iMaxPacketCnt = ~0);
711  ~PacketList();
712 
713  protected:
714  // packet list
715  Packet *pFront{nullptr}, *pBack{nullptr};
716  // packet counts
717  unsigned int iPacketCnt{0}, iMaxPacketCnt;
718  // critical section
720 
721  public:
722  Packet *GetPacket(unsigned int iNr);
723  Packet *GetPacketFrgm(unsigned int iNr);
724  Packet *GetFirstPacketComplete();
725  bool FragmentPresent(unsigned int iNr);
726 
727  bool AddPacket(Packet *pPacket);
728  bool DeletePacket(Packet *pPacket);
729  void ClearPackets(unsigned int iUntil);
730  void Clear();
731  };
732  friend class PacketList;
733 
734  // peer class
735  class Peer
736  {
737  public:
738 
739  // construction / destruction
740  Peer(const C4NetIO::addr_t &naddr, C4NetIOUDP *pnParent);
741  ~Peer();
742 
743  protected:
744 
745  // constants
746  static const unsigned int iConnectRetries; // = 5
747  static const unsigned int iReCheckInterval; // = 1000 (ms)
748 
749  // parent class
751 
752  // peer address
754  // alternate peer address
756  // the address used by the peer
758  // connection status
760  {
761  CS_None, CS_Conn, CS_Works, CS_Closed
762  }
763  eStatus;
764  // does multicast work?
766  // selected for broadcast?
768  // do callback on connection timeout?
770 
771  // packet lists (outgoing, incoming, incoming multicast)
773  PacketList IPackets, IMCPackets;
774 
775  // packet counters
776  unsigned int iOPacketCounter;
777  unsigned int iIPacketCounter, iRIPacketCounter;
778  unsigned int iIMCPacketCounter, iRIMCPacketCounter;
779 
780  unsigned int iMCAckPacketCounter;
781 
782  // output critical section
784 
785  // connection check time limit.
787  unsigned int iLastPacketAsked, iLastMCPacketAsked;
788 
789  // timeout time.
791  unsigned int iRetries;
792 
793  // statistics
794  int iIRate, iORate, iLoss;
796 
797  public:
798  // data access
799  const C4NetIO::addr_t &GetAddr() const { return addr; }
800  const C4NetIO::addr_t &GetAltAddr() const { return addr2; }
801 
802  // initiate connection
803  bool Connect(bool fFailCallback);
804 
805  // send something to this computer
806  bool Send(const C4NetIOPacket &rPacket);
807  // check for lost packets
808  bool Check(bool fForceCheck = true);
809 
810  // called if something from this peer was received
811  void OnRecv(const C4NetIOPacket &Packet);
812 
813  // close connection
814  void Close(const char *szReason);
815  // open?
816  bool Open() const { return eStatus == CS_Works; }
817  // closed?
818  bool Closed() const { return eStatus == CS_Closed; }
819  // multicast support?
820  bool MultiCast() const { return fMultiCast; }
821 
822  // acknowledgment check
823  unsigned int GetMCAckPacketCounter() const { return iMCAckPacketCounter; }
824 
825  // timeout checking
826  C4TimeMilliseconds GetTimeout() { return tTimeout; }
827  void CheckTimeout();
828 
829  // selected for broadcast?
830  bool doBroadcast() const { return fDoBroadcast; }
831  // select/unselect peer
832  void SetBroadcast(bool fSet) { fDoBroadcast = fSet; }
833 
834  // alternate address
835  void SetAltAddr(const C4NetIO::addr_t &naddr2) { addr2 = naddr2; }
836 
837  // statistics
838  int GetIRate() const { return iIRate; }
839  int GetORate() const { return iORate; }
840  int GetLoss() const { return iLoss; }
841  void ClearStatistics();
842 
843  protected:
844 
845  // helpers
846  bool DoConn(bool fMC);
847  bool DoCheck(int iAskCnt = 0, int iMCAskCnt = 0, unsigned int *pAskList = nullptr);
848 
849  // sending
850  bool SendDirect(const Packet &rPacket, unsigned int iNr = ~0);
851  bool SendDirect(C4NetIOPacket &&rPacket);
852 
853  // events
854  void OnConn();
855  void OnClose(const char *szReason);
856 
857  // incoming packet list
858  void CheckCompleteIPackets();
859 
860  // timeout
861  void SetTimeout(int iLength = iStdTimeout, int iRetryCnt = 0);
862  void OnTimeout();
863 
864  public:
865  // next peer
867  };
868  friend class Peer;
869 
870  // critical sections
874 
875  // status
876  bool fInit{false};
877  bool fMultiCast{false};
878  uint16_t iPort;
879 
880  // peer list
881  Peer *pPeerList{nullptr};
882 
883  // currently initializing - do not process packets, save them back instead
884  bool fSavePacket{false};
886 
887  // multicast support data
889  bool fDelayedLoopbackTest{false};
890 
891  // check timing.
893 
894  // outgoing packet list (for multicast)
896  unsigned int iOPacketCounter{0};
897 
898  // statistics
899  int iBroadcastRate{0};
901 
902  // callback proxy
904 
905  // * helpers
906 
907  // sending
908  bool BroadcastDirect(const Packet &rPacket, unsigned int iNr = ~0u); // (mt-safe)
909 
910  // multicast related
911  bool DoLoopbackTest();
912  void ClearMCPackets();
913 
914  // peer list
915  void AddPeer(Peer *pPeer);
916  Peer *GetPeer(const addr_t &addr);
917  Peer *ConnectPeer(const addr_t &PeerAddr, bool fFailCallback);
918  void OnShareFree(CStdCSecEx *pCSec) override;
919 
920  // connection check
921  void DoCheck();
922 
923  // critical section: only one execute at a time
925 
926  // debug
927 #ifdef C4NETIO_DEBUG
928  int hDebugLog;
929  void OpenDebugLog();
930  void CloseDebugLog();
931  void DebugLogPkt(bool fOut, const C4NetIOPacket &Pkt);
932 #endif
933 
934  // *** callbacks
935 public:
936  void SetCallback(CBClass *pnCallback) override { pCB = pnCallback; };
937 private:
938  CBClass *pCB;
939 
940  // callback interface for C4NetIO
941  virtual bool OnConn(const addr_t &AddrPeer, const addr_t &AddrConnect, const addr_t *pOwnAddr, C4NetIO *pNetIO);
942  virtual void OnDisconn(const addr_t &AddrPeer, C4NetIO *pNetIO, const char *szReason);
943  virtual void OnPacket(const class C4NetIOPacket &rPacket, C4NetIO *pNetIO);
944 
945  void OnAddAddress(const addr_t &FromAddr, const AddAddrPacket &Packet);
946 };
947 
948 // net i/o management (e.g. thread support)
950 {
951 public:
952  C4NetIOMan();
953  ~C4NetIOMan() override;
954 
955  void Clear();
956 
957  void AddIO(C4NetIO *pNetIO, bool fSetCallback = true);
958  void RemoveIO(C4NetIO *pNetIO);
959 
960 protected:
961 
962  // net i/o list
963  int iNetIOCnt{0}, iNetIOCapacity{0};
964  C4NetIO **ppNetIO{nullptr};
965 
966  // overridables
967  virtual void OnError(const char *strError, C4NetIO *pNetIO) { };
968 
969 private:
970  void OnError(StdSchedulerProc *pProc) override;
971 
972  void EnlargeIO(int iBy);
973 };
974 
975 #ifdef HAVE_WINSOCK
976 bool AcquireWinSock();
977 void ReleaseWinSock();
978 #endif
979 
980 // Class that keeps winsock loaded
982 {
983 public:
985  {
986 #ifdef HAVE_WINSOCK
987  AcquireWinSock();
988 #endif
989  }
990 
992  {
993 #ifdef HAVE_WINSOCK
994  ReleaseWinSock();
995 #endif
996  }
997 };
998 
999 
1000 #endif
void OnPacket(const class C4NetIOPacket &rPacket, C4NetIO *pNetIO) override
Definition: C4NetIO.h:237
unsigned int iMCAckPacketCounter
Definition: C4NetIO.h:780
C4NetIO::addr_t addr
Definition: C4NetIO.h:753
void ResetError()
Definition: C4NetIO.h:286
int GetLoss() const
Definition: C4NetIO.h:840
void SetBroadcast(bool fSet)
Definition: C4NetIO.h:832
bool OnConn(const addr_t &AddrPeer, const addr_t &AddrConnect, const addr_t *pOwnAddr, C4NetIO *pNetIO) override
Definition: C4NetIO.h:233
bool IsNull() const
Definition: C4NetIO.cpp:508
C4NetIOPacket Data
Definition: C4NetIO.h:683
Definition: StdBuf.h:29
#define INVALID_SOCKET
Definition: C4NetIO.h:36
const char * getPData() const
Definition: C4NetIO.h:319
bool Open() const
Definition: C4NetIO.h:816
C4TimeMilliseconds GetTimeout()
Definition: C4NetIO.h:826
int GetIRate() const
Definition: C4NetIO.h:838
addr_t PeerAddr
Definition: C4NetIO.h:757
void SetCallback(CBClass *pnCallback) override
Definition: C4NetIO.h:589
bool IsMulticast() const
Definition: C4NetIO.cpp:242
void SetAltAddr(const C4NetIO::addr_t &naddr2)
Definition: C4NetIO.h:835
HostAddress(uint32_t addr)
Definition: C4NetIO.h:92
void Clear()
Definition: StdBuf.h:466
CStdCSecEx PeerListCSec
Definition: C4NetIO.h:871
void SetError(const char *strnError, bool fSockErr=false)
Definition: C4NetIO.cpp:750
virtual C4TimeMilliseconds GetNextTick(C4TimeMilliseconds tNow)
size_t getPSize() const
Definition: C4NetIO.h:320
uint8_t getStatus() const
Definition: C4NetIO.h:318
virtual bool Broadcast(const class C4NetIOPacket &rPacket)=0
bool doBroadcast() const
Definition: C4NetIO.h:830
unsigned int iLastPacketAsked
Definition: C4NetIO.h:787
PacketList OPackets
Definition: C4NetIO.h:895
bool hasWaitingData() const
Definition: C4NetIO.h:446
C4NetIOPacket & GetData()
Definition: C4NetIO.h:688
unsigned int iRetries
Definition: C4NetIO.h:791
unsigned int GetMCAckPacketCounter() const
Definition: C4NetIO.h:823
static const unsigned int iReCheckInterval
Definition: C4NetIO.h:747
void SetCallback(CBClass *pnCallback) override
Definition: C4NetIO.h:504
HostAddress(SpecialAddress addr)
Definition: C4NetIO.h:91
virtual void OnError(const char *strError, C4NetIO *pNetIO)
Definition: C4NetIO.h:967
CStdCSec OutCSec
Definition: C4NetIO.h:873
static const unsigned int iMinIBufSize
Definition: C4NetIO.h:407
StdCopyStrBuf Error
Definition: C4NetIO.h:282
void ClearStatistic() override
Definition: C4NetIO.h:546
void SetHost(const sockaddr *addr)
Definition: C4NetIO.cpp:346
bool Empty() const
Definition: C4NetIO.h:691
static const unsigned int iUDPHeaderSize
Definition: C4NetIO.h:659
bool GetStatistic(int *pBroadcastRate) override
Definition: C4NetIO.h:543
virtual void SetCallback(CBClass *pnCallback)=0
virtual void PackPacket(const C4NetIOPacket &rPacket, StdBuf &rOutBuf)
Definition: C4NetIO.cpp:1688
static const unsigned int iMaxOPacketBacklog
Definition: C4NetIO.h:657
virtual bool OnConn(const addr_t &AddrPeer, const addr_t &AddrConnect, const addr_t *pOwnAddr, C4NetIO *pNetIO)
Definition: C4NetIO.h:220
const C4NetIOPacket & GetData() const
Definition: C4NetIO.h:689
bool operator!=(const HostAddress &rhs) const
Definition: C4NetIO.h:123
int GetORate() const
Definition: C4NetIO.h:430
int GetORate() const
Definition: C4NetIO.h:839
bool Close(const addr_t &addr) override
Definition: C4NetIO.h:539
bool InitIPv6Socket(SOCKET socket)
Definition: C4NetIO.cpp:730
unsigned int iRIPacketCounter
Definition: C4NetIO.h:777
C4NetIOPacket LastPacket
Definition: C4NetIO.h:885
bool IsNullHost() const
Definition: C4NetIO.h:164
virtual bool InitBroadcast(addr_t *pBroadcastAddr)
Definition: C4NetIO.cpp:851
StdBuf Duplicate() const
Definition: StdBuf.h:248
void SetBroadcast(bool fSet)
Definition: C4NetIO.h:448
~WinSockHolder()
Definition: C4NetIO.h:991
void SetCallback(CBClass *pnCallback) override
Definition: C4NetIO.h:936
virtual void UnBlock()
Definition: C4NetIO.cpp:1343
void OnDisconn(const addr_t &AddrPeer, C4NetIO *pNetIO, const char *szReason) override
Definition: C4NetIO.h:235
static const size_t MaxDataSize
Definition: C4NetIO.h:670
PacketList IPackets
Definition: C4NetIO.h:773
static const unsigned int iVersion
Definition: C4NetIO.h:649
EndpointAddress(const EndpointAddress &other)
Definition: C4NetIO.h:140
bool IsLocal() const
Definition: C4NetIO.cpp:260
bool Open() const
Definition: C4NetIO.h:442
SOCKET GetSocket() const
Definition: C4NetIO.h:428
static std::vector< HostAddress > GetLocalAddresses()
Definition: C4NetIO.cpp:631
static const unsigned int iTCPHeaderSize
Definition: C4NetIO.h:406
CStdCSecEx PeerListCSec
Definition: C4NetIO.h:469
const C4NetIO::addr_t & GetAddr() const
Definition: C4NetIO.h:799
const EndpointAddressPtr operator&() const
C4NetIO::HostAddress AsIPv4() const
Definition: C4NetIO.cpp:325
EndpointAddress(const StdStrBuf &addr)
Definition: C4NetIO.h:143
C4NetIO::addr_t addr
Definition: C4NetIO.h:312
HostAddress GetHost() const
Definition: C4NetIO.h:155
std::unique_ptr< Socket > Bind(const addr_t &addr)
Definition: C4NetIO.cpp:1192
virtual bool GetConnStatistic(const addr_t &addr, int *pIRate, int *pORate, int *pLoss)=0
uint16_t iPort
Definition: C4NetIO.h:878
HostAddress(const HostAddress &other)
Definition: C4NetIO.h:90
C4NetIOUDP *const pParent
Definition: C4NetIO.h:750
bool Connect(const addr_t &addr) override
Definition: C4NetIO.h:538
bool isNull() const
Definition: StdBuf.h:98
const addr_t & getMCAddr() const
Definition: C4NetIO.h:572
bool fConnFailCallback
Definition: C4NetIO.h:769
C4TimeMilliseconds tTimeout
Definition: C4NetIO.h:790
StdMeshMatrix operator*(const StdMeshMatrix &lhs, const StdMeshMatrix &rhs)
addr_t MCLoopbackAddr
Definition: C4NetIO.h:888
bool operator==(const HostAddress &rhs) const
Definition: C4NetIO.cpp:558
virtual void ClearStatistic()=0
C4NetIO::HostAddress AsIPv6() const
Definition: C4NetIO.cpp:303
void SetScopeId(int scopeId)
Definition: C4NetIO.cpp:289
ConnectWait * Next
Definition: C4NetIO.h:465
#define SOCKET
Definition: C4NetIO.h:35
CStdCSecEx ListCSec
Definition: C4NetIO.h:719
bool fDoBroadcast
Definition: C4NetIO.h:422
bool GetConnStatistic(const addr_t &addr, int *pIRate, int *pORate, int *pLoss) override
Definition: C4NetIO.h:544
EndpointAddress addr_t
Definition: C4NetIO.h:212
nr_t GetNr() const
Definition: C4NetIO.h:690
CStdCSec PeerListAddCSec
Definition: C4NetIO.h:470
StdBuf getRef() const
Definition: StdBuf.h:271
StdBuf getPBuf() const
Definition: C4NetIO.h:321
const char * getData() const
Definition: StdBuf.h:442
static const int TO_INF
Definition: C4NetIO.h:66
EndpointAddress(const HostAddress &host, uint16_t port=IPPORT_NONE)
Definition: C4NetIO.h:141
#define NETIO_CREATE_CALLBACK_PROXY(ForClass, ProxyName)
Definition: C4NetIO.h:247
HostAddress(const StdStrBuf &addr)
Definition: C4NetIO.h:93
virtual bool Close()=0
uint32_t nr_t
Definition: C4NetIO.h:673
static const size_t MaxSize
Definition: C4NetIO.h:669
virtual bool Send(const class C4NetIOPacket &rPacket)=0
bool IsPrivate() const
Definition: C4NetIO.cpp:270
int GetScopeId() const
Definition: C4NetIO.cpp:296
bool Multicast() const
Definition: C4NetIO.h:692
virtual size_t UnpackPacket(const StdBuf &rInBuf, const C4NetIO::addr_t &Addr)
Definition: C4NetIO.cpp:1705
const C4NetIO::addr_t & GetAltAddr() const
Definition: C4NetIO.h:800
unsigned int iOPacketCounter
Definition: C4NetIO.h:776
bool MultiCast() const
Definition: C4NetIO.h:820
virtual void GetFDs(std::vector< struct pollfd > &)
Definition: StdScheduler.h:72
static const uint16_t IPPORT_NONE
Definition: C4NetIO.h:137
bool Execute(int iTimeout=-1, pollfd *=nullptr) override=0
int GetIRate() const
Definition: C4NetIO.h:429
SOCKET lsock
Definition: C4NetIO.h:477
virtual bool CloseBroadcast()
Definition: C4NetIO.cpp:905
virtual void OnDisconn(const addr_t &AddrPeer, C4NetIO *pNetIO, const char *szReason)
Definition: C4NetIO.h:221
StdStrBuf ToString(int flags=0) const
Definition: C4NetIO.cpp:588
C4NetIOTCP *const pParent
Definition: C4NetIO.h:409
virtual const char * GetError() const
Definition: C4NetIO.h:285
C4NetIOPacket Duplicate() const
Definition: C4NetIO.h:325
bool IsNotify() override
Definition: C4NetIO.h:259
bool fDoBroadcast
Definition: C4NetIO.h:767
CStdCSec StatCSec
Definition: C4NetIO.h:795
CStdCSec OutCSec
Definition: C4NetIO.h:783
virtual bool Init(uint16_t iPort=addr_t::IPPORT_NONE)=0
C4TimeMilliseconds tNextCheck
Definition: C4NetIO.h:892
C4NetIO::addr_t addr
Definition: C4NetIO.h:411
virtual bool GetStatistic(int *pBroadcastRate)=0
C4NetIOPacket getRef() const
Definition: C4NetIO.h:324
C4NetIO()
Definition: C4NetIO.cpp:723
PacketList OPackets
Definition: C4NetIO.h:772
unsigned int iRIMCPacketCounter
Definition: C4NetIO.h:778
CStdCSec PeerListAddCSec
Definition: C4NetIO.h:872
EndpointAddress(HostAddress::SpecialAddress addr, uint16_t port=IPPORT_NONE)
Definition: C4NetIO.h:142
C4NetIO::addr_t addr2
Definition: C4NetIO.h:755
static const unsigned int iStdTimeout
Definition: C4NetIO.h:654
const C4NetIO::addr_t & GetAddr() const
Definition: C4NetIO.h:427
CStdCSec ExecuteCSec
Definition: C4NetIO.h:924
Packet * Prev
Definition: C4NetIO.h:703
C4TimeMilliseconds tNextReCheck
Definition: C4NetIO.h:786
void SetAddr(const C4NetIO::addr_t &naddr)
Definition: C4NetIO.h:327
CStdCSec OCSec
Definition: C4NetIO.h:424
bool getMCLoopback() const
Definition: C4NetIO.h:576
#define s
size_t GetAddrLen() const
Definition: C4NetIO.cpp:526
bool Closed() const
Definition: C4NetIO.h:818
bool SetBroadcast(const addr_t &addr, bool fSet=true) override
Definition: C4NetIO.h:541
virtual bool SetBroadcast(const addr_t &addr, bool fSet=true)=0
AddressFamily GetFamily() const
Definition: C4NetIO.cpp:520
void CompileFunc(C4Real &rValue, StdCompiler *pComp)
Definition: C4Real.cpp:9033
bool doBroadcast() const
Definition: C4NetIO.h:444
const C4NetIO::addr_t & getAddr() const
Definition: C4NetIO.h:316
HostAddress(const sockaddr *addr)
Definition: C4NetIO.h:94
bool IsLoopback() const
Definition: C4NetIO.cpp:251
int iSize
Definition: TstC4NetIO.cpp:32
static const unsigned int iConnectRetries
Definition: C4NetIO.h:746
virtual bool Connect(const addr_t &addr)=0
CStdCSec StatCSec
Definition: C4NetIO.h:900
uint16_t iListenPort
Definition: C4NetIO.h:476
~C4NetIO() override