OpenClonk
C4NetIOSimpleUDP Class Referenceabstract

#include <C4NetIO.h>

Inheritance diagram for C4NetIOSimpleUDP:
[legend]
Collaboration diagram for C4NetIOSimpleUDP:
[legend]

Public Types

typedef EndpointAddress addr_t
 

Public Member Functions

 C4NetIOSimpleUDP ()
 
 ~C4NetIOSimpleUDP () override
 
bool Init (uint16_t iPort=addr_t::IPPORT_NONE) override
 
virtual bool InitBroadcast (addr_t *pBroadcastAddr)
 
bool Close () override
 
virtual bool CloseBroadcast ()
 
bool Execute (int iMaxTime=TO_INF, pollfd *=nullptr) override
 
bool Send (const C4NetIOPacket &rPacket) override
 
bool Broadcast (const C4NetIOPacket &rPacket) override
 
virtual void UnBlock ()
 
void GetFDs (std::vector< struct pollfd > &FDs) override
 
bool Connect (const addr_t &addr) override
 
bool Close (const addr_t &addr) override
 
bool SetBroadcast (const addr_t &addr, bool fSet=true) override
 
bool GetStatistic (int *pBroadcastRate) override
 
bool GetConnStatistic (const addr_t &addr, int *pIRate, int *pORate, int *pLoss) override
 
void ClearStatistic () override
 
void SetCallback (CBClass *pnCallback) override
 
bool IsNotify () override
 
virtual bool Send (const class C4NetIOPacket &rPacket)=0
 
virtual bool Broadcast (const class C4NetIOPacket &rPacket)=0
 
virtual const char * GetError () const
 
void ResetError ()
 
virtual void SetCallback (CBClass *pnCallback)=0
 
bool ExecuteUntil (int iTimeout=-1)
 
virtual C4TimeMilliseconds GetNextTick (C4TimeMilliseconds tNow)
 
bool IsSignaled ()
 
virtual bool IsLowPriority ()
 
virtual uint32_t TimerInterval ()
 

Static Public Member Functions

static std::vector< HostAddressGetLocalAddresses ()
 

Static Public Attributes

static const int TO_INF = -1
 

Protected Member Functions

const addr_tgetMCAddr () const
 
bool SetMCLoopback (int fLoopback)
 
bool getMCLoopback () const
 
void SetReUseAddress (bool fAllow)
 
bool InitIPv6Socket (SOCKET socket)
 
void SetError (const char *strnError, bool fSockErr=false)
 
void Changed ()
 

Protected Attributes

StdCopyStrBuf Error
 

Detailed Description

Definition at line 514 of file C4NetIO.h.

Member Typedef Documentation

◆ addr_t

typedef EndpointAddress C4NetIO::addr_t
inherited

Definition at line 212 of file C4NetIO.h.

Constructor & Destructor Documentation

◆ C4NetIOSimpleUDP()

C4NetIOSimpleUDP::C4NetIOSimpleUDP ( )

Definition at line 1887 of file C4NetIO.cpp.

1888  : iPort(~0), sock(INVALID_SOCKET)
1889 {
1890 
1891 }
#define INVALID_SOCKET
Definition: C4NetIO.h:36

◆ ~C4NetIOSimpleUDP()

C4NetIOSimpleUDP::~C4NetIOSimpleUDP ( )
override

Definition at line 1893 of file C4NetIO.cpp.

References Close().

1894 {
1895  Close();
1896 }
bool Close() override
Definition: C4NetIO.cpp:2041
Here is the call graph for this function:

Member Function Documentation

◆ Broadcast() [1/2]

virtual bool C4NetIO::Broadcast ( const class C4NetIOPacket rPacket)
pure virtualinherited

Referenced by C4NetIO::IsNotify().

Here is the caller graph for this function:

◆ Broadcast() [2/2]

bool C4NetIOSimpleUDP::Broadcast ( const C4NetIOPacket rPacket)
override

Definition at line 2200 of file C4NetIO.cpp.

References C4NetIOPacket::getRef(), INFINITE, Send(), C4NetIO::SetError(), SOCKET_ERROR, C4NetIO::TO_INF, and UnBlock().

Referenced by C4NetIOUDP::DoLoopbackTest(), and C4NetIOUDP::InitBroadcast().

2201 {
2202  // just set broadcast address and send
2203  return C4NetIOSimpleUDP::Send(C4NetIOPacket(rPacket.getRef(), MCAddr));
2204 }
bool Send(const C4NetIOPacket &rPacket) override
Definition: C4NetIO.cpp:2180
C4NetIOPacket getRef() const
Definition: C4NetIO.h:324
Here is the call graph for this function:
Here is the caller graph for this function:

◆ Changed()

void StdSchedulerProc::Changed ( )
protectedinherited

Definition at line 108 of file StdScheduler.cpp.

References s.

Referenced by C4NetIOTCP::Accept(), C4NetIOTCP::AddConnectWait(), C4NetIOUDP::AddPeer(), StdScheduler::IsInManualLoop(), C4NetIOTCP::Listen(), and CStdTimerProc::SetDelay().

109 {
110  auto s = scheduler;
111  if (s)
112  s->Changed(this);
113 }
#define s
Here is the caller graph for this function:

◆ ClearStatistic()

void C4NetIOSimpleUDP::ClearStatistic ( )
inlineoverridevirtual

Implements C4NetIO.

Reimplemented in C4NetIOUDP.

Definition at line 546 of file C4NetIO.h.

References SOCKET.

546 { assert(false); }

◆ Close() [1/2]

bool C4NetIOSimpleUDP::Close ( )
overridevirtual

Implements C4NetIO.

Reimplemented in C4NetIOUDP.

Definition at line 2041 of file C4NetIO.cpp.

References CloseBroadcast(), closesocket, INVALID_SOCKET, and C4NetIO::ResetError().

Referenced by C4NetIOUDP::Close(), Init(), ~C4NetIOSimpleUDP(), and C4StartupNetDlg::~C4StartupNetDlg().

2042 {
2043  // should be initialized
2044  if (!fInit) return true;
2045 
2046  ResetError();
2047 
2048  // deactivate multicast
2049  if (fMultiCast)
2050  CloseBroadcast();
2051 
2052  // close sockets
2053  if (sock != INVALID_SOCKET)
2054  {
2055  closesocket(sock);
2056  sock = INVALID_SOCKET;
2057  }
2058 
2059 #ifdef STDSCHEDULER_USE_EVENTS
2060  // close event
2061  if (hEvent != nullptr)
2062  {
2063  WSACloseEvent(hEvent);
2064  hEvent = nullptr;
2065  }
2066 #else
2067  // close pipes
2068  close(Pipe[0]);
2069  close(Pipe[1]);
2070 #endif
2071 
2072 #ifdef HAVE_WINSOCK
2073  // release winsock
2074  ReleaseWinSock();
2075 #endif
2076 
2077  // ok
2078  fInit = false;
2079  return false;
2080 }
void ResetError()
Definition: C4NetIO.h:286
#define INVALID_SOCKET
Definition: C4NetIO.h:36
virtual bool CloseBroadcast()
Definition: C4NetIO.cpp:2082
#define closesocket
Definition: C4NetIO.cpp:46
Here is the call graph for this function:
Here is the caller graph for this function:

◆ Close() [2/2]

bool C4NetIOSimpleUDP::Close ( const addr_t addr)
inlineoverridevirtual

Implements C4NetIO.

Reimplemented in C4NetIOUDP.

Definition at line 539 of file C4NetIO.h.

539 { assert(false); return false; }

◆ CloseBroadcast()

bool C4NetIOSimpleUDP::CloseBroadcast ( )
virtual

Reimplemented in C4NetIOUDP.

Definition at line 2082 of file C4NetIO.cpp.

References C4NetIO::SetError(), and SOCKET_ERROR.

Referenced by Close(), C4NetIOUDP::CloseBroadcast(), InitBroadcast(), and C4NetIOUDP::InitBroadcast().

2083 {
2084  // multicast not active?
2085  if (!fMultiCast) return true;
2086 
2087  // leave multicast group
2088  if (setsockopt(sock, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP,
2089  reinterpret_cast<const char *>(&MCGrpInfo), sizeof(MCGrpInfo)) == SOCKET_ERROR)
2090  {
2091  SetError("could not leave multicast group"); // to do: more error information
2092  return false;
2093  }
2094 
2095  // ok
2096  fMultiCast = false;
2097  return true;
2098 }
void SetError(const char *strnError, bool fSockErr=false)
Definition: C4NetIO.cpp:750
#define SOCKET_ERROR
Definition: C4NetIO.cpp:47
Here is the call graph for this function:
Here is the caller graph for this function:

◆ Connect()

bool C4NetIOSimpleUDP::Connect ( const addr_t addr)
inlineoverridevirtual

Implements C4NetIO.

Reimplemented in C4NetIOUDP.

Definition at line 538 of file C4NetIO.h.

538 { assert(false); return false; }

◆ Execute()

bool C4NetIOSimpleUDP::Execute ( int  iMaxTime = TO_INF,
pollfd *  = nullptr 
)
overridevirtual

Implements C4NetIO.

Reimplemented in C4NetIOUDP.

Definition at line 2100 of file C4NetIO.cpp.

References C4NetIO::HostAddress::GetFamily(), GetSocketErrorMsg(), HaveConnResetError(), ioctlsocket, StdBuf::New(), C4NetIO::CBClass::OnDisconn(), C4NetIO::CBClass::OnPacket(), C4NetIO::ResetError(), C4NetIOPacket::SetAddr(), C4NetIO::SetError(), StdBuf::SetSize(), SOCKET_ERROR, and C4NetIO::HostAddress::UnknownFamily.

Referenced by C4NetIOUDP::DoLoopbackTest(), C4NetIOUDP::Execute(), C4NetIOUDP::InitBroadcast(), and C4StartupNetDlg::OnSec1Timer().

2101 {
2102  if (!fInit) { SetError("not yet initialized"); return false; }
2103  ResetError();
2104 
2105 #ifdef __APPLE__
2106  iMaxTime = fix_poll_timeout(iMaxTime);
2107 #endif
2108 
2109  // wait for socket / timeout
2110  WaitResult eWR = WaitForSocket(iMaxTime);
2111  if (eWR == WR_Error) return false;
2112 
2113  // cancelled / timeout?
2114  if (eWR == WR_Cancelled || eWR == WR_Timeout) return true;
2115  assert(eWR == WR_Readable);
2116 
2117  // read packets from socket
2118  for (;;)
2119  {
2120  // how much can be read?
2121 #ifdef _WIN32
2122  u_long iMaxMsgSize;
2123 #else
2124  // The FIONREAD ioctl call takes an int on unix
2125  int iMaxMsgSize;
2126 #endif
2127  if (::ioctlsocket(sock, FIONREAD, &iMaxMsgSize) == SOCKET_ERROR)
2128  {
2129  SetError("Could not determine the amount of data that can be read from socket", true);
2130  return false;
2131  }
2132 
2133  // nothing?
2134  if (!iMaxMsgSize)
2135  break;
2136  // alloc buffer
2137  C4NetIOPacket Pkt; Pkt.New(iMaxMsgSize);
2138  // read data (note: it is _not_ garantueed that iMaxMsgSize bytes are available)
2139  addr_t SrcAddr; socklen_t iSrcAddrLen = sizeof(sockaddr_in6);
2140  int iMsgSize = ::recvfrom(sock, getMBufPtr<char>(Pkt), iMaxMsgSize, 0, &SrcAddr, &iSrcAddrLen);
2141  // error?
2142  if (iMsgSize == SOCKET_ERROR)
2143  {
2144  if (HaveConnResetError())
2145  {
2146  // this is actually some kind of notification: an ICMP msg (unreachable)
2147  // came back, so callback and continue reading
2148  if (pCB) pCB->OnDisconn(SrcAddr, this, GetSocketErrorMsg());
2149  continue;
2150  }
2151  else
2152  {
2153  // this is the real thing, though
2154  SetError("could not receive data from socket", true);
2155  return false;
2156  }
2157  }
2158  // invalid address?
2159  if ((iSrcAddrLen != sizeof(sockaddr_in) && iSrcAddrLen != sizeof(sockaddr_in6)) || SrcAddr.GetFamily() == addr_t::UnknownFamily)
2160  {
2161  SetError("recvfrom returned an invalid address");
2162  return false;
2163  }
2164  // again: nothing?
2165  if (!iMsgSize)
2166  // docs say that the connection has been closed (whatever that means for a connectionless socket...)
2167  // let's just pretend it didn't happen, but stop reading.
2168  break;
2169  // fill in packet information
2170  Pkt.SetSize(iMsgSize);
2171  Pkt.SetAddr(SrcAddr);
2172  // callback
2173  if (pCB) pCB->OnPacket(Pkt, this);
2174  }
2175 
2176  // ok
2177  return true;
2178 }
void ResetError()
Definition: C4NetIO.h:286
const char * GetSocketErrorMsg(int iError)
Definition: C4NetIO.cpp:190
void SetError(const char *strnError, bool fSockErr=false)
Definition: C4NetIO.cpp:750
#define ioctlsocket
Definition: C4NetIO.cpp:45
bool HaveConnResetError()
Definition: C4NetIO.cpp:207
void SetSize(size_t inSize)
Definition: StdBuf.h:204
EndpointAddress addr_t
Definition: C4NetIO.h:212
void New(size_t inSize)
Definition: StdBuf.h:146
virtual void OnDisconn(const addr_t &AddrPeer, C4NetIO *pNetIO, const char *szReason)
Definition: C4NetIO.h:221
virtual void OnPacket(const class C4NetIOPacket &rPacket, C4NetIO *pNetIO)=0
void SetAddr(const C4NetIO::addr_t &naddr)
Definition: C4NetIO.h:327
#define SOCKET_ERROR
Definition: C4NetIO.cpp:47
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ExecuteUntil()

bool StdSchedulerProc::ExecuteUntil ( int  iTimeout = -1)
inherited

Definition at line 33 of file StdScheduler.cpp.

References StdSchedulerProc::Execute(), and C4TimeMilliseconds::Now().

Referenced by main().

34 {
35  // Infinite?
36  if (iTimeout < 0)
37  for (;;)
38  if (!Execute())
39  return false;
40  // Calculate endpoint
41  C4TimeMilliseconds tStopTime = C4TimeMilliseconds::Now() + iTimeout;
42  for (;;)
43  {
44  // Call execute with given timeout
45  if (!Execute(std::max(iTimeout, 0)))
46  return false;
47  // Calculate timeout
49  if (tTime >= tStopTime)
50  break;
51  iTimeout = tStopTime - tTime;
52  }
53  // All ok.
54  return true;
55 }
virtual bool Execute(int iTimeout=-1, pollfd *readyfds=nullptr)=0
static C4TimeMilliseconds Now()
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetConnStatistic()

bool C4NetIOSimpleUDP::GetConnStatistic ( const addr_t addr,
int *  pIRate,
int *  pORate,
int *  pLoss 
)
inlineoverridevirtual

Implements C4NetIO.

Reimplemented in C4NetIOUDP.

Definition at line 544 of file C4NetIO.h.

545  { assert(false); return false; }

◆ GetError()

virtual const char* C4NetIO::GetError ( ) const
inlinevirtualinherited

Definition at line 285 of file C4NetIO.h.

References StdStrBuf::getData().

Referenced by C4Network2IO::ConnectWithSocket(), C4NetIOUDP::DoLoopbackTest(), C4StartupNetDlg::DoRefresh(), C4DownloadDlg::GetError(), C4Network2IO::Init(), C4NetIOUDP::InitBroadcast(), C4Network2::InitLeague(), C4Game::InitNetworkFromAddress(), C4Network2::LeagueEnd(), C4Network2::LeaguePlrAuthCheck(), C4Network2::LeagueStart(), C4Network2::LeagueUpdate(), C4Network2::LeagueUpdateProcessReply(), main(), MyCBClass::OnConn(), C4ChatControl::OnConnectBtn(), MyCBClass::OnPacket(), C4StartupNetListEntry::OnReference(), C4ChatControl::ProcessInput(), C4Network2IOConnection::Send(), and C4StartupNetListEntry::SetRefQuery().

285 { return Error.getData(); }
StdCopyStrBuf Error
Definition: C4NetIO.h:282
const char * getData() const
Definition: StdBuf.h:442
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetFDs()

void C4NetIOSimpleUDP::GetFDs ( std::vector< struct pollfd > &  FDs)
overridevirtual

Reimplemented from StdSchedulerProc.

Definition at line 2252 of file C4NetIO.cpp.

References INVALID_SOCKET, and C4NetIO::SetError().

2253 {
2254  // add pipe
2255  pollfd pfd = { Pipe[0], POLLIN, 0 };
2256  fds.push_back(pfd);
2257  // add socket
2258  if (sock != INVALID_SOCKET)
2259  {
2260  pollfd pfd = { sock, POLLIN, 0 };
2261  fds.push_back(pfd);
2262  }
2263 }
#define INVALID_SOCKET
Definition: C4NetIO.h:36
Here is the call graph for this function:

◆ GetLocalAddresses()

std::vector< C4NetIO::HostAddress > C4NetIO::GetLocalAddresses ( )
staticinherited

Definition at line 631 of file C4NetIO.cpp.

References C4NetIO::HostAddress::IsLoopback(), and C4NetIO::HostAddress::SetHost().

Referenced by C4Network2Client::AddLocalAddrs(), and C4NetIOUDP::InitBroadcast().

632 {
633  std::vector<HostAddress> result;
634 
635 #ifdef HAVE_WINSOCK
636  HostAddress addr;
637  const size_t BUFFER_SIZE = 16000;
638  PIP_ADAPTER_ADDRESSES addresses = nullptr;
639  for (int i = 0; i < 3; ++i)
640  {
641  addresses = (PIP_ADAPTER_ADDRESSES) realloc(addresses, BUFFER_SIZE * (i+1));
642  if (!addresses)
643  // allocation failed
644  return result;
645  ULONG bufsz = BUFFER_SIZE * (i+1);
646  DWORD rv = GetAdaptersAddresses(AF_UNSPEC,
647  GAA_FLAG_SKIP_ANYCAST|GAA_FLAG_SKIP_MULTICAST|GAA_FLAG_SKIP_DNS_SERVER|GAA_FLAG_SKIP_FRIENDLY_NAME,
648  nullptr, addresses, &bufsz);
649  if (rv == ERROR_BUFFER_OVERFLOW)
650  // too little space, try again
651  continue;
652  if (rv != NO_ERROR)
653  {
654  // Something else happened
655  free(addresses);
656  return result;
657  }
658  // All okay, add addresses
659  for (PIP_ADAPTER_ADDRESSES address = addresses; address; address = address->Next)
660  {
661  for (PIP_ADAPTER_UNICAST_ADDRESS unicast = address->FirstUnicastAddress; unicast; unicast = unicast->Next)
662  {
663  addr.SetHost(unicast->Address.lpSockaddr);
664  if (addr.IsLoopback())
665  continue;
666  result.push_back(addr);
667  }
668  }
669  }
670  free(addresses);
671 #else
672  bool have_ipv6 = false;
673 
674 #ifdef __linux__
675  // Get IPv6 addresses on Linux from procfs which allows filtering deprecated privacy addresses.
676  FILE *f = fopen("/proc/net/if_inet6", "r");
677  if (f)
678  {
679  sockaddr_in6 sa6 = sockaddr_in6();
680  sa6.sin6_family = AF_INET6;
681  auto a6 = sa6.sin6_addr.s6_addr;
682  uint8_t if_idx, plen, scope, flags;
683  char devname[20];
684  while (fscanf(f, "%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx %02hhx %02hhx %02hhx %02hhx %20s\n",
685  &a6[0], &a6[1], &a6[2], &a6[3], &a6[4], &a6[5], &a6[6], &a6[7],
686  &a6[8], &a6[9], &a6[10], &a6[11], &a6[12], &a6[13], &a6[14], &a6[15],
687  &if_idx, &plen, &scope, &flags, devname) != EOF)
688  {
689  // Skip loopback and deprecated addresses.
690  if (scope == IPV6_ADDR_LOOPBACK || flags & IFA_F_DEPRECATED)
691  continue;
692  sa6.sin6_scope_id = scope == IPV6_ADDR_LINKLOCAL ? if_idx : 0;
693  result.emplace_back((sockaddr*) &sa6);
694  }
695  have_ipv6 = result.size() > 0;
696  fclose(f);
697  }
698 #endif
699 
700  struct ifaddrs* addrs;
701  if (getifaddrs(&addrs) < 0)
702  return result;
703  for (struct ifaddrs* ifaddr = addrs; ifaddr != nullptr; ifaddr = ifaddr->ifa_next)
704  {
705  struct sockaddr* ad = ifaddr->ifa_addr;
706  if (ad == nullptr) continue;
707 
708  if ((ad->sa_family == AF_INET || (!have_ipv6 && ad->sa_family == AF_INET6)) && (~ifaddr->ifa_flags & IFF_LOOPBACK)) // Choose only non-loopback IPv4/6 devices
709  {
710  result.emplace_back(ad);
711  }
712  }
713  freeifaddrs(addrs);
714 #endif
715 
716  return result;
717 }
uint32_t DWORD
Here is the call graph for this function:
Here is the caller graph for this function:

◆ getMCAddr()

const addr_t& C4NetIOSimpleUDP::getMCAddr ( ) const
inlineprotected

Definition at line 572 of file C4NetIO.h.

Referenced by C4NetIOUDP::SendDirect().

572 { return MCAddr; }
Here is the caller graph for this function:

◆ getMCLoopback()

bool C4NetIOSimpleUDP::getMCLoopback ( ) const
inlineprotected

Definition at line 576 of file C4NetIO.h.

Referenced by C4NetIOUDP::DoLoopbackTest(), and C4NetIOUDP::InitBroadcast().

576 { return fMCLoopback; }
Here is the caller graph for this function:

◆ GetNextTick()

C4TimeMilliseconds StdSchedulerProc::GetNextTick ( C4TimeMilliseconds  tNow)
virtualinherited

Reimplemented in C4NetIOUDP, C4Network2HTTPClient, C4Network2IO, and CStdTimerProc.

Definition at line 115 of file StdScheduler.cpp.

References C4TimeMilliseconds::PositiveInfinity.

Referenced by StdSchedulerProc::GetFDs(), C4Network2HTTPClient::GetNextTick(), StdScheduler::IsInManualLoop(), and StdScheduler::ScheduleProcs().

Here is the caller graph for this function:

◆ GetStatistic()

bool C4NetIOSimpleUDP::GetStatistic ( int *  pBroadcastRate)
inlineoverridevirtual

Implements C4NetIO.

Reimplemented in C4NetIOUDP.

Definition at line 543 of file C4NetIO.h.

543 { assert(false); return false; }

◆ Init()

bool C4NetIOSimpleUDP::Init ( uint16_t  iPort = addr_t::IPPORT_NONE)
overridevirtual

Implements C4NetIO.

Reimplemented in C4NetIOUDP, C4Network2IODiscoverClient, and C4Network2IODiscover.

Definition at line 1898 of file C4NetIO.cpp.

References C4NetIO::HostAddress::Any, Close(), C4NetIO::InitIPv6Socket(), INVALID_SOCKET, C4NetIO::ResetError(), C4NetIO::SetError(), C4NetIO::EndpointAddress::SetPort(), SOCK_CLOEXEC, and SOCKET_ERROR.

Referenced by C4Network2IODiscover::Init(), C4Network2IODiscoverClient::Init(), and C4NetIOUDP::Init().

1899 {
1900  // reset error
1901  ResetError();
1902 
1903  // already initialized? close first
1904  if (fInit) Close();
1905 
1906 #ifdef HAVE_WINSOCK
1907  // init winsock
1908  if (!AcquireWinSock())
1909  {
1910  SetError("could not start winsock");
1911  return false;
1912  }
1913 #endif
1914 
1915  // create sockets
1916  if ((sock = ::socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP)) == INVALID_SOCKET)
1917  {
1918  SetError("could not create socket", true);
1919  return false;
1920  }
1921 
1922  if (!InitIPv6Socket(sock))
1923  return false;
1924 
1925  // set reuse socket option
1926  if (::setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char *>(&fAllowReUse), sizeof fAllowReUse) == SOCKET_ERROR)
1927  {
1928  SetError("could not set reuse options", true);
1929  return false;
1930  }
1931 
1932  // bind socket
1933  iPort = inPort;
1934  addr_t naddr = addr_t::Any;
1935  naddr.SetPort(iPort);
1936  if (::bind(sock, &naddr, sizeof(naddr)) == SOCKET_ERROR)
1937  {
1938  SetError("could not bind socket", true);
1939  return false;
1940  }
1941 
1942 #ifdef STDSCHEDULER_USE_EVENTS
1943 
1944  // create event
1945  if ((hEvent = WSACreateEvent()) == WSA_INVALID_EVENT)
1946  {
1947  SetError("could not create event", true);
1948  return false;
1949  }
1950 
1951  // set event for socket
1952  if (WSAEventSelect(sock, hEvent, FD_READ | FD_CLOSE) == SOCKET_ERROR)
1953  {
1954  SetError("could not select event", true);
1955  return false;
1956  }
1957 
1958 #else
1959 
1960  // disable blocking
1961  if (::fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK) == SOCKET_ERROR)
1962  {
1963  // set error
1964  SetError("could not disable blocking", true);
1965  return false;
1966  }
1967 
1968  // create pipe
1969  if (pipe(Pipe) != 0)
1970  {
1971  SetError("could not create pipe", true);
1972  return false;
1973  }
1974 
1975 #endif
1976 
1977  // set flags
1978  fInit = true;
1979  fMultiCast = false;
1980 
1981  // ok, that's all for know.
1982  // call InitBroadcast for more initialization fun
1983  return true;
1984 }
void ResetError()
Definition: C4NetIO.h:286
#define INVALID_SOCKET
Definition: C4NetIO.h:36
void SetError(const char *strnError, bool fSockErr=false)
Definition: C4NetIO.cpp:750
bool Close() override
Definition: C4NetIO.cpp:2041
bool InitIPv6Socket(SOCKET socket)
Definition: C4NetIO.cpp:730
EndpointAddress addr_t
Definition: C4NetIO.h:212
#define SOCK_CLOEXEC
Definition: C4NetIO.h:50
#define SOCKET_ERROR
Definition: C4NetIO.cpp:47
Here is the call graph for this function:
Here is the caller graph for this function:

◆ InitBroadcast()

bool C4NetIOSimpleUDP::InitBroadcast ( addr_t pBroadcastAddr)
virtual

Reimplemented in C4NetIOUDP.

Definition at line 1986 of file C4NetIO.cpp.

References CloseBroadcast(), C4NetIO::HostAddress::GetFamily(), C4NetIO::EndpointAddress::GetPort(), C4NetIO::HostAddress::IPv6, C4NetIO::HostAddress::IsMulticast(), C4NetIO::ResetError(), C4NetIO::SetError(), SetMCLoopback(), and SOCKET_ERROR.

Referenced by C4Network2IODiscover::Init(), C4Network2IODiscoverClient::Init(), and C4NetIOUDP::InitBroadcast().

1987 {
1988  // no error... yet
1989  ResetError();
1990 
1991  // security
1992  if (!pBroadcastAddr) return false;
1993 
1994  // Init() has to be called first
1995  if (!fInit) return false;
1996  // already activated?
1997  if (fMultiCast) CloseBroadcast();
1998 
1999  // broadcast addr valid?
2000  if (!pBroadcastAddr->IsMulticast() || pBroadcastAddr->GetFamily() != HostAddress::IPv6)
2001  {
2002  SetError("invalid broadcast address (only IPv6 multicast addresses are supported)");
2003  return false;
2004  }
2005  if (pBroadcastAddr->GetPort() != iPort)
2006  {
2007  SetError("invalid broadcast address (different port)");
2008  return false;
2009  }
2010 
2011  // set mc ttl to somewhat about "same net"
2012  int TTL = 16;
2013  if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, reinterpret_cast<char*>(&TTL), sizeof(TTL)) == SOCKET_ERROR)
2014  {
2015  SetError("could not set mc ttl", true);
2016  return false;
2017  }
2018 
2019  // set up multicast group information
2020  this->MCAddr = *pBroadcastAddr;
2021  MCGrpInfo.ipv6mr_multiaddr = static_cast<sockaddr_in6>(MCAddr).sin6_addr;
2022  // TODO: do multicast on all interfaces?
2023  MCGrpInfo.ipv6mr_interface = 0; // default interface
2024 
2025  // join multicast group
2026  if (setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
2027  reinterpret_cast<const char *>(&MCGrpInfo), sizeof(MCGrpInfo)) == SOCKET_ERROR)
2028  {
2029  SetError("could not join multicast group"); // to do: more error information
2030  return false;
2031  }
2032 
2033  // (try to) disable loopback (will set fLoopback accordingly)
2034  SetMCLoopback(false);
2035 
2036  // ok
2037  fMultiCast = true;
2038  return true;
2039 }
void ResetError()
Definition: C4NetIO.h:286
bool SetMCLoopback(int fLoopback)
Definition: C4NetIO.cpp:2290
void SetError(const char *strnError, bool fSockErr=false)
Definition: C4NetIO.cpp:750
virtual bool CloseBroadcast()
Definition: C4NetIO.cpp:2082
#define SOCKET_ERROR
Definition: C4NetIO.cpp:47
Here is the call graph for this function:
Here is the caller graph for this function:

◆ InitIPv6Socket()

bool C4NetIO::InitIPv6Socket ( SOCKET  socket)
protectedinherited

Definition at line 730 of file C4NetIO.cpp.

References C4NetIO::SetError(), and SOCKET_ERROR.

Referenced by C4NetIOTCP::CreateSocket(), Init(), C4NetIO::IsNotify(), and C4NetIOTCP::Listen().

731 {
732  int opt = 0;
733  if (setsockopt(socket, IPPROTO_IPV6, IPV6_V6ONLY, reinterpret_cast<char*>(&opt), sizeof(opt)) == SOCKET_ERROR)
734  {
735  SetError("could not enable dual-stack socket", true);
736  return false;
737  }
738 
739 #ifdef IPV6_ADDR_PREFERENCES
740  // Prefer stable addresses. This should prevent issues with address
741  // deprecation while a match is running. No error handling - if the call
742  // fails, we just take any address.
743  opt = IPV6_PREFER_SRC_PUBLIC;
744  setsockopt(socket, IPPROTO_IPV6, IPV6_ADDR_PREFERENCES, reinterpret_cast<char*>(&opt), sizeof(opt));
745 #endif
746 
747  return true;
748 }
void SetError(const char *strnError, bool fSockErr=false)
Definition: C4NetIO.cpp:750
#define SOCKET_ERROR
Definition: C4NetIO.cpp:47
Here is the call graph for this function:
Here is the caller graph for this function:

◆ IsLowPriority()

virtual bool StdSchedulerProc::IsLowPriority ( )
inlinevirtualinherited

Definition at line 82 of file StdScheduler.h.

82 { return false; }

◆ IsNotify()

bool C4NetIO::IsNotify ( )
inlineoverridevirtualinherited

Reimplemented from StdSchedulerProc.

Definition at line 259 of file C4NetIO.h.

References C4NetIO::Broadcast(), C4NetIO::ClearStatistic(), C4NetIO::Close(), C4NetIO::Connect(), C4NetIO::GetConnStatistic(), C4NetIO::GetStatistic(), C4NetIO::InitIPv6Socket(), C4NetIO::Send(), C4NetIO::SetBroadcast(), and SOCKET.

259 { return true; }
Here is the call graph for this function:

◆ IsSignaled()

bool StdSchedulerProc::IsSignaled ( )
inherited

Referenced by StdSchedulerProc::GetFDs().

Here is the caller graph for this function:

◆ ResetError()

void C4NetIO::ResetError ( )
inlineinherited

Definition at line 286 of file C4NetIO.h.

References StdStrBuf::Clear(), and C4NetIO::SetCallback().

Referenced by C4NetIO::C4NetIO(), C4NetIOTCP::Close(), Close(), C4NetIOUDP::CloseBroadcast(), C4Network2IO::ConnectWithSocket(), Execute(), C4NetIOUDP::Execute(), Init(), InitBroadcast(), C4NetIOUDP::InitBroadcast(), C4Network2IOConnection::Send(), and Send().

286 { Error.Clear(); }
void Clear()
Definition: StdBuf.h:466
StdCopyStrBuf Error
Definition: C4NetIO.h:282
Here is the call graph for this function:
Here is the caller graph for this function:

◆ Send() [1/2]

virtual bool C4NetIO::Send ( const class C4NetIOPacket rPacket)
pure virtualinherited

Referenced by C4NetIOUDP::Peer::GetAltAddr(), C4NetIOTCP::Peer::GetORate(), C4NetIO::IsNotify(), main(), MyCBClass::OnConn(), MyCBClass::OnPacket(), C4Network2IOConnection::Send(), and C4Network2IO::SendPuncherPacket().

Here is the caller graph for this function:

◆ Send() [2/2]

bool C4NetIOSimpleUDP::Send ( const C4NetIOPacket rPacket)
override

Definition at line 2180 of file C4NetIO.cpp.

References C4NetIOPacket::getAddr(), C4NetIO::HostAddress::GetAddrLen(), StdBuf::getSize(), HaveWouldBlockError(), C4NetIO::ResetError(), and C4NetIO::SetError().

Referenced by Broadcast(), and C4NetIOUDP::SendDirect().

2181 {
2182  if (!fInit) { SetError("not yet initialized"); return false; }
2183 
2184  // send it
2185  C4NetIO::addr_t addr = rPacket.getAddr();
2186  if (::sendto(sock, getBufPtr<char>(rPacket), rPacket.getSize(), 0,
2187  &addr, addr.GetAddrLen())
2188  != int(rPacket.getSize()) &&
2190  {
2191  SetError("socket sendto failed", true);
2192  return false;
2193  }
2194 
2195  // ok
2196  ResetError();
2197  return true;
2198 }
void ResetError()
Definition: C4NetIO.h:286
void SetError(const char *strnError, bool fSockErr=false)
Definition: C4NetIO.cpp:750
size_t getSize() const
Definition: StdBuf.h:101
bool HaveWouldBlockError()
Definition: C4NetIO.cpp:203
size_t GetAddrLen() const
Definition: C4NetIO.cpp:526
const C4NetIO::addr_t & getAddr() const
Definition: C4NetIO.h:316
Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetBroadcast()

bool C4NetIOSimpleUDP::SetBroadcast ( const addr_t addr,
bool  fSet = true 
)
inlineoverridevirtual

Implements C4NetIO.

Reimplemented in C4NetIOUDP.

Definition at line 541 of file C4NetIO.h.

541 { assert(false); return false; }

◆ SetCallback() [1/2]

virtual void C4NetIO::SetCallback ( CBClass pnCallback)
pure virtualinherited

Referenced by C4NetIOMan::AddIO(), C4Network2IO::Init(), and C4NetIO::ResetError().

Here is the caller graph for this function:

◆ SetCallback() [2/2]

void C4NetIOSimpleUDP::SetCallback ( CBClass *  pnCallback)
inlineoverride

Definition at line 589 of file C4NetIO.h.

Referenced by C4Network2IODiscover::C4Network2IODiscover(), C4Network2IODiscoverClient::C4Network2IODiscoverClient(), C4Network2IODiscover::Init(), C4Network2IODiscoverClient::Init(), and C4NetIOUDP::Init().

589 { pCB = pnCallback; };
Here is the caller graph for this function:

◆ SetError()

void C4NetIO::SetError ( const char *  strnError,
bool  fSockErr = false 
)
protectedinherited

Definition at line 750 of file C4NetIO.cpp.

References C4NetIOPacket::C4NetIOPacket(), StdStrBuf::Copy(), C4NetIO::Error, StdStrBuf::Format(), GetSocketErrorMsg(), and HaveSocketError().

Referenced by C4NetIOTCP::Accept(), C4NetIOTCP::Bind(), Broadcast(), CloseBroadcast(), C4NetIOTCP::Connect(), C4NetIOTCP::CreateSocket(), C4NetIOUDP::DoLoopbackTest(), C4NetIOTCP::Execute(), Execute(), C4NetIOUDP::Execute(), GetFDs(), C4NetIOTCP::Init(), Init(), InitBroadcast(), C4NetIOUDP::InitBroadcast(), C4NetIO::InitIPv6Socket(), C4NetIOTCP::Listen(), C4NetIOTCP::Peer::Send(), Send(), C4NetIOTCP::UnBlock(), and UnBlock().

751 {
752  fSockErr &= HaveSocketError();
753  if (fSockErr)
754  Error.Format("%s (%s)", strnError, GetSocketErrorMsg());
755  else
756  Error.Copy(strnError);
757 }
const char * GetSocketErrorMsg(int iError)
Definition: C4NetIO.cpp:190
StdCopyStrBuf Error
Definition: C4NetIO.h:282
void Format(const char *szFmt,...) GNUC_FORMAT_ATTRIBUTE_O
Definition: StdBuf.cpp:174
bool HaveSocketError()
Definition: C4NetIO.cpp:199
void Copy()
Definition: StdBuf.h:467
Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetMCLoopback()

bool C4NetIOSimpleUDP::SetMCLoopback ( int  fLoopback)
protected

Definition at line 2290 of file C4NetIO.cpp.

References iSize, and SOCKET_ERROR.

Referenced by C4NetIOUDP::DoLoopbackTest(), C4Network2IODiscover::Init(), C4Network2IODiscoverClient::Init(), InitBroadcast(), and C4NetIOUDP::InitBroadcast().

2291 {
2292  // enable/disable MC loopback
2293  setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, reinterpret_cast<char *>(&fLoopback), sizeof fLoopback);
2294  // read result
2295  socklen_t iSize = sizeof(fLoopback);
2296  if (getsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, reinterpret_cast<char *>(&fLoopback), &iSize) == SOCKET_ERROR)
2297  return false;
2298  fMCLoopback = !! fLoopback;
2299  return true;
2300 }
int iSize
Definition: TstC4NetIO.cpp:32
#define SOCKET_ERROR
Definition: C4NetIO.cpp:47
Here is the caller graph for this function:

◆ SetReUseAddress()

void C4NetIOSimpleUDP::SetReUseAddress ( bool  fAllow)
protected

Definition at line 2302 of file C4NetIO.cpp.

Referenced by C4Network2IODiscover::Init(), and C4Network2IODiscoverClient::Init().

2303 {
2304  fAllowReUse = fAllow;
2305 }
Here is the caller graph for this function:

◆ TimerInterval()

virtual uint32_t StdSchedulerProc::TimerInterval ( )
inlinevirtualinherited

Reimplemented in CStdTimerProc.

Definition at line 84 of file StdScheduler.h.

Referenced by SCHAdditions::assignAdditionForProc:.

84 { return 0; }
Here is the caller graph for this function:

◆ UnBlock()

void C4NetIOSimpleUDP::UnBlock ( )
virtual

Definition at line 2243 of file C4NetIO.cpp.

References C4NetIO::SetError().

Referenced by Broadcast().

2244 {
2245  // write one character to the pipe, this will unblock everything that
2246  // waits for the FD set returned by GetFDs.
2247  char c = 42;
2248  if (write(Pipe[1], &c, 1) == -1)
2249  SetError("write failed");
2250 }
void SetError(const char *strnError, bool fSockErr=false)
Definition: C4NetIO.cpp:750
Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ Error

StdCopyStrBuf C4NetIO::Error
protectedinherited

Definition at line 282 of file C4NetIO.h.

Referenced by C4NetIO::SetError().

◆ TO_INF

const int C4NetIO::TO_INF = -1
staticinherited

The documentation for this class was generated from the following files: