OpenClonk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
C4NetIOTCP Class Referenceabstract

#include <C4NetIO.h>

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

Classes

struct  ConnectWait
 
class  Peer
 

Public Types

typedef EndpointAddress addr_t
 

Public Member Functions

 C4NetIOTCP ()
 
virtual ~C4NetIOTCP ()
 
virtual bool Init (uint16_t iPort=addr_t::IPPORT_NONE)
 
virtual bool InitBroadcast (addr_t *pBroadcastAddr)
 
virtual bool Close ()
 
virtual bool CloseBroadcast ()
 
virtual bool Execute (int iMaxTime=TO_INF, pollfd *readyfds=0)
 
virtual bool Connect (const addr_t &addr)
 
virtual bool Close (const addr_t &addr)
 
virtual bool Send (const C4NetIOPacket &rPacket)
 
virtual bool Broadcast (const C4NetIOPacket &rPacket)
 
virtual bool SetBroadcast (const addr_t &addr, bool fSet=true)
 
virtual void UnBlock ()
 
virtual void GetFDs (std::vector< struct pollfd > &FDs)
 
virtual bool GetStatistic (int *pBroadcastRate)
 
virtual bool GetConnStatistic (const addr_t &addr, int *pIRate, int *pORate, int *pLoss)
 
virtual void ClearStatistic ()
 
virtual void SetCallback (CBClass *pnCallback)
 
virtual bool IsNotify ()
 
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

virtual void PackPacket (const C4NetIOPacket &rPacket, StdBuf &rOutBuf)
 
virtual size_t UnpackPacket (const StdBuf &rInBuf, const C4NetIO::addr_t &Addr)
 
bool Listen (uint16_t inListenPort)
 
PeerAccept (SOCKET nsock=INVALID_SOCKET, const addr_t &ConnectAddr=addr_t())
 
PeerGetPeer (const addr_t &addr)
 
void OnShareFree (CStdCSecEx *pCSec)
 
void AddConnectWait (SOCKET sock, const addr_t &addr)
 
ConnectWaitGetConnectWait (const addr_t &addr)
 
void ClearConnectWaits ()
 
bool InitIPv6Socket (SOCKET socket)
 
void SetError (const char *strnError, bool fSockErr=false)
 
void Changed ()
 

Protected Attributes

PeerpPeerList
 
struct C4NetIOTCP::ConnectWaitpConnectWaits
 
CStdCSecEx PeerListCSec
 
CStdCSec PeerListAddCSec
 
bool fInit
 
uint16_t iListenPort
 
SOCKET lsock
 
int Pipe [2]
 
StdCopyStrBuf Error
 

Friends

class Peer
 

Detailed Description

Definition at line 335 of file C4NetIO.h.


Class Documentation

struct C4NetIOTCP::ConnectWait

Definition at line 446 of file C4NetIO.h.

Collaboration diagram for C4NetIOTCP::ConnectWait:
[legend]
Class Members
addr_t addr
ConnectWait * Next
SOCKET sock

Member Typedef Documentation

typedef EndpointAddress C4NetIO::addr_t
inherited

Definition at line 212 of file C4NetIO.h.

Constructor & Destructor Documentation

C4NetIOTCP::C4NetIOTCP ( )

Definition at line 805 of file C4NetIO.cpp.

806  : pPeerList(nullptr),
807  pConnectWaits(nullptr),
808  PeerListCSec(this),
809  fInit(false),
811 #ifdef STDSCHEDULER_USE_EVENTS
812  Event(nullptr),
813 #endif
814  pCB(nullptr)
815 {
816 
817 }
#define INVALID_SOCKET
Definition: C4NetIO.h:37
Peer * pPeerList
Definition: C4NetIO.h:443
CStdCSecEx PeerListCSec
Definition: C4NetIO.h:455
struct C4NetIOTCP::ConnectWait * pConnectWaits
bool fInit
Definition: C4NetIO.h:459
SOCKET lsock
Definition: C4NetIO.h:463
uint16_t iListenPort
Definition: C4NetIO.h:462
C4NetIOTCP::~C4NetIOTCP ( )
virtual

Definition at line 819 of file C4NetIO.cpp.

References Close().

820 {
821  Close();
822 }
virtual bool Close()
Definition: C4NetIO.cpp:870

Here is the call graph for this function:

Member Function Documentation

C4NetIOTCP::Peer * C4NetIOTCP::Accept ( SOCKET  nsock = INVALID_SOCKET,
const addr_t ConnectAddr = addr_t() 
)
protected

Definition at line 1383 of file C4NetIO.cpp.

References StdSchedulerProc::Changed(), C4NetIO::EndpointAddress::Clear(), CStdLock::Clear(), C4NetIOTCP::Peer::Close(), closesocket, C4NetIO::HostAddress::GetFamily(), INVALID_SOCKET, ioctlsocket, lsock, C4NetIOTCP::Peer::Next, C4NetIO::CBClass::OnConn(), Peer, PeerListAddCSec, PeerListCSec, pPeerList, C4NetIO::SetError(), SOCK_CLOEXEC, SOCKET_ERROR, and C4NetIO::HostAddress::UnknownFamily.

Referenced by Execute().

1384 {
1385 
1386  addr_t caddr = ConnectAddr;
1387 
1388  // accept incoming connection?
1389  C4NetIO::addr_t addr; socklen_t iAddrSize = sizeof addr;
1390  if (nsock == INVALID_SOCKET)
1391  {
1392  // accept from listener
1393 #ifdef __linux__
1394  if ((nsock = ::accept4(lsock, &addr, &iAddrSize, SOCK_CLOEXEC)) == INVALID_SOCKET)
1395 #else
1396  if ((nsock = ::accept(lsock, &addr, &iAddrSize)) == INVALID_SOCKET)
1397 #endif
1398  {
1399  // set error
1400  SetError("socket accept failed", true);
1401  return nullptr;
1402  }
1403  // connect address unknown, so zero it
1404  caddr.Clear();
1405  }
1406  else
1407  {
1408  // get peer address
1409  if (::getpeername(nsock, &addr, &iAddrSize) == SOCKET_ERROR)
1410  {
1411 #ifndef HAVE_WINSOCK
1412  // getpeername behaves strangely on exotic platforms. Just ignore it.
1413  if (errno != ENOTCONN)
1414  {
1415 #endif
1416  // set error
1417  SetError("could not get peer address for connected socket", true);
1418  return nullptr;
1419 #ifndef HAVE_WINSOCK
1420  }
1421 #endif
1422  }
1423  }
1424 
1425  // check address
1426  if (addr.GetFamily() == addr_t::UnknownFamily)
1427  {
1428  // set error
1429  SetError("socket accept failed: invalid address returned");
1430  closesocket(nsock);
1431  return nullptr;
1432  }
1433 
1434  // disable nagle (yep, we know what we are doing here - I think)
1435  int iNoDelay = 1;
1436  ::setsockopt(nsock, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<const char *>(&iNoDelay), sizeof(iNoDelay));
1437 
1438 #ifdef STDSCHEDULER_USE_EVENTS
1439  // set event
1440  if (::WSAEventSelect(nsock, Event, FD_READ | FD_WRITE | FD_CLOSE) == SOCKET_ERROR)
1441  {
1442  // set error
1443  SetError("connection accept failed: could not set event", true);
1444  closesocket(nsock);
1445  return nullptr;
1446  }
1447 #elif defined(HAVE_WINSOCK)
1448  // disable blocking
1449  unsigned long iBlock = 1;
1450  if (::ioctlsocket(nsock, FIONBIO, &iBlock) == SOCKET_ERROR)
1451  {
1452  // set error
1453  SetError("connect failed: could not disable blocking", true);
1454  close(nsock);
1455  return false;
1456  }
1457 #else
1458  // disable blocking
1459  if (::fcntl(nsock, F_SETFL, fcntl(nsock, F_GETFL) | O_NONBLOCK) == SOCKET_ERROR)
1460  {
1461  // set error
1462  SetError("connection accept failed: could not disable blocking", true);
1463  close(nsock);
1464  return nullptr;
1465  }
1466 #endif
1467 
1468 
1469  // create new peer
1470  Peer *pnPeer = new Peer(addr, nsock, this);
1471 
1472  // get required locks to add item to list
1473  CStdShareLock PeerListLock(&PeerListCSec);
1474  CStdLock PeerListAddLock(&PeerListAddCSec);
1475 
1476  // add to list
1477  pnPeer->Next = pPeerList;
1478  pPeerList = pnPeer;
1479 
1480  // clear add-lock
1481  PeerListAddLock.Clear();
1482 
1483  Changed();
1484 
1485  // ask callback if connection should be permitted
1486  if (pCB && !pCB->OnConn(addr, caddr, nullptr, this))
1487  // close socket immediately (will be deleted later)
1488  pnPeer->Close();
1489 
1490  // ok
1491  return pnPeer;
1492 }
#define INVALID_SOCKET
Definition: C4NetIO.h:37
void SetError(const char *strnError, bool fSockErr=false)
Definition: C4NetIO.cpp:754
virtual bool OnConn(const addr_t &AddrPeer, const addr_t &AddrConnect, const addr_t *pOwnAddr, C4NetIO *pNetIO)
Definition: C4NetIO.h:220
#define ioctlsocket
Definition: C4NetIO.cpp:51
Peer * pPeerList
Definition: C4NetIO.h:443
CStdCSecEx PeerListCSec
Definition: C4NetIO.h:455
friend class Peer
Definition: C4NetIO.h:441
AddressFamily GetFamily() const
Definition: C4NetIO.cpp:526
EndpointAddress addr_t
Definition: C4NetIO.h:212
CStdCSec PeerListAddCSec
Definition: C4NetIO.h:456
#define SOCK_CLOEXEC
Definition: C4NetIO.h:51
#define closesocket
Definition: C4NetIO.cpp:52
SOCKET lsock
Definition: C4NetIO.h:463
#define SOCKET_ERROR
Definition: C4NetIO.cpp:53

Here is the call graph for this function:

Here is the caller graph for this function:

void C4NetIOTCP::AddConnectWait ( SOCKET  sock,
const addr_t addr 
)
protected

Definition at line 1607 of file C4NetIO.cpp.

References C4NetIOTCP::ConnectWait::addr, StdSchedulerProc::Changed(), C4NetIOTCP::ConnectWait::Next, pConnectWaits, PeerListAddCSec, PeerListCSec, C4NetIOTCP::ConnectWait::sock, and UnBlock().

Referenced by Connect().

1608 {
1609  CStdShareLock PeerListLock(&PeerListCSec);
1610  CStdLock PeerListAddLock(&PeerListAddCSec);
1611  // create new entry, add to list
1612  ConnectWait *pnWait = new ConnectWait;
1613  pnWait->sock = sock; pnWait->addr = addr;
1614  pnWait->Next = pConnectWaits;
1615  pConnectWaits = pnWait;
1616 #ifndef STDSCHEDULER_USE_EVENTS
1617  // unblock, so new FD can be realized
1618  UnBlock();
1619 #endif
1620  Changed();
1621 }
virtual void UnBlock()
Definition: C4NetIO.cpp:1299
CStdCSecEx PeerListCSec
Definition: C4NetIO.h:455
CStdCSec PeerListAddCSec
Definition: C4NetIO.h:456
struct C4NetIOTCP::ConnectWait * pConnectWaits

Here is the call graph for this function:

Here is the caller graph for this function:

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

Definition at line 1288 of file C4NetIO.cpp.

References C4NetIOPacket::getRef(), C4NetIOTCP::Peer::Next, PeerListCSec, pPeerList, and Send().

1289 {
1290  CStdShareLock PeerListLock(&PeerListCSec);
1291  // just send to all clients
1292  bool fSuccess = true;
1293  for (Peer *pPeer = pPeerList; pPeer; pPeer = pPeer->Next)
1294  if (pPeer->Open() && pPeer->doBroadcast())
1295  fSuccess &= Send(C4NetIOPacket(rPacket.getRef(), pPeer->GetAddr()));
1296  return fSuccess;
1297 }
C4NetIOPacket getRef() const
Definition: C4NetIO.h:324
Peer * pPeerList
Definition: C4NetIO.h:443
CStdCSecEx PeerListCSec
Definition: C4NetIO.h:455
friend class Peer
Definition: C4NetIO.h:441
virtual bool Send(const C4NetIOPacket &rPacket)
Definition: C4NetIO.cpp:1266

Here is the call graph for this function:

void StdSchedulerProc::Changed ( )
protectedinherited

Definition at line 121 of file StdScheduler.cpp.

References s.

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

122 {
123  auto s = scheduler;
124  if (s)
125  s->Changed(this);
126 }
#define s

Here is the caller graph for this function:

void C4NetIOTCP::ClearConnectWaits ( )
protected

Definition at line 1633 of file C4NetIO.cpp.

References closesocket, C4NetIOTCP::ConnectWait::Next, pConnectWaits, and PeerListCSec.

Referenced by Close().

1634 {
1635  CStdShareLock PeerListLock(&PeerListCSec);
1636  for (ConnectWait *pWait = pConnectWaits; pWait; pWait = pWait->Next)
1637  if (pWait->sock)
1638  {
1639  closesocket(pWait->sock);
1640  pWait->sock = 0;
1641  }
1642 }
CStdCSecEx PeerListCSec
Definition: C4NetIO.h:455
ConnectWait * Next
Definition: C4NetIO.h:451
struct C4NetIOTCP::ConnectWait * pConnectWaits
#define closesocket
Definition: C4NetIO.cpp:52

Here is the caller graph for this function:

void C4NetIOTCP::ClearStatistic ( )
virtual

Implements C4NetIO.

Definition at line 1375 of file C4NetIO.cpp.

References C4NetIOTCP::Peer::Next, PeerListCSec, and pPeerList.

1376 {
1377  CStdShareLock PeerListLock(&PeerListCSec);
1378  // clear all peer statistics
1379  for (Peer *pPeer = pPeerList; pPeer; pPeer = pPeer->Next)
1380  pPeer->ClearStatistics();
1381 }
Peer * pPeerList
Definition: C4NetIO.h:443
CStdCSecEx PeerListCSec
Definition: C4NetIO.h:455
friend class Peer
Definition: C4NetIO.h:441
bool C4NetIOTCP::Close ( )
virtual

Implements C4NetIO.

Reimplemented in C4Network2IRCClient, and C4AulDebug.

Definition at line 870 of file C4NetIO.cpp.

References ClearConnectWaits(), closesocket, fInit, INVALID_SOCKET, lsock, C4NetIOTCP::Peer::Next, C4NetIO::CBClass::OnDisconn(), PeerListCSec, Pipe, pPeerList, and C4NetIO::ResetError().

Referenced by C4Network2HTTPClient::Cancel(), C4Network2RefServer::Clear(), C4AulDebug::Close(), C4Network2IRCClient::Close(), Init(), main(), C4Network2HTTPClient::UnpackPacket(), ~C4NetIOTCP(), and C4NetIOTCP::Peer::~Peer().

871 {
872  ResetError();
873 
874  // not init?
875  if (!fInit) return false;
876 
877  // terminate connections
878  CStdShareLock PeerListLock(&PeerListCSec);
879  for (Peer *pPeer = pPeerList; pPeer; pPeer = pPeer->Next)
880  if (pPeer->Open())
881  {
882  pPeer->Close();
883  if (pCB) pCB->OnDisconn(pPeer->GetAddr(), this, "owner class closed");
884  }
885 
887 
888  // close listen socket
889  if (lsock != INVALID_SOCKET)
890  {
893  }
894 
895 #ifdef STDSCHEDULER_USE_EVENTS
896  // close event
897  if (Event != nullptr)
898  {
899  WSACloseEvent(Event);
900  Event = nullptr;
901  }
902 #else
903  // close pipe
904  close(Pipe[0]);
905  close(Pipe[1]);
906 #endif
907 
908 #ifdef HAVE_WINSOCK
909  // release winsock
910  ReleaseWinSock();
911 #endif
912 
913  // ok
914  fInit = false;
915  return true;
916 }
void ResetError()
Definition: C4NetIO.h:286
void ClearConnectWaits()
Definition: C4NetIO.cpp:1633
#define INVALID_SOCKET
Definition: C4NetIO.h:37
Peer * pPeerList
Definition: C4NetIO.h:443
int Pipe[2]
Definition: C4NetIO.h:470
CStdCSecEx PeerListCSec
Definition: C4NetIO.h:455
friend class Peer
Definition: C4NetIO.h:441
#define closesocket
Definition: C4NetIO.cpp:52
bool fInit
Definition: C4NetIO.h:459
SOCKET lsock
Definition: C4NetIO.h:463
virtual void OnDisconn(const addr_t &AddrPeer, C4NetIO *pNetIO, const char *szReason)
Definition: C4NetIO.h:221

Here is the call graph for this function:

Here is the caller graph for this function:

bool C4NetIOTCP::Close ( const addr_t addr)
virtual

Implements C4NetIO.

Reimplemented in C4AulDebug.

Definition at line 1235 of file C4NetIO.cpp.

References C4NetIOTCP::ConnectWait::addr, C4NetIOTCP::Peer::Close(), closesocket, C4NetIOTCP::Peer::GetAddr(), GetConnectWait(), GetPeer(), C4NetIO::CBClass::OnDisconn(), PeerListCSec, and C4NetIOTCP::ConnectWait::sock.

1236 {
1237  CStdShareLock PeerListLock(&PeerListCSec);
1238  // find connect wait
1239  ConnectWait *pWait = GetConnectWait(addr);
1240  if (pWait)
1241  {
1242  // close socket, do callback
1243  closesocket(pWait->sock); pWait->sock = 0;
1244  if (pCB) pCB->OnDisconn(pWait->addr, this, "closed");
1245  }
1246  else
1247  {
1248  // find peer
1249  Peer *pPeer = GetPeer(addr);
1250  if (pPeer)
1251  {
1252  C4NetIO::addr_t addr = pPeer->GetAddr();
1253  // close peer
1254  pPeer->Close();
1255  // do callback
1256  if (pCB) pCB->OnDisconn(addr, this, "closed");
1257  }
1258  // not found
1259  else
1260  return false;
1261  }
1262  // ok
1263  return true;
1264 }
CStdCSecEx PeerListCSec
Definition: C4NetIO.h:455
Peer * GetPeer(const addr_t &addr)
Definition: C4NetIO.cpp:1549
friend class Peer
Definition: C4NetIO.h:441
#define closesocket
Definition: C4NetIO.cpp:52
virtual void OnDisconn(const addr_t &AddrPeer, C4NetIO *pNetIO, const char *szReason)
Definition: C4NetIO.h:221
ConnectWait * GetConnectWait(const addr_t &addr)
Definition: C4NetIO.cpp:1623

Here is the call graph for this function:

bool C4NetIOTCP::CloseBroadcast ( )
virtual

Definition at line 918 of file C4NetIO.cpp.

919 {
920  return true;
921 }
bool C4NetIOTCP::Connect ( const addr_t addr)
virtual

Implements C4NetIO.

Definition at line 1167 of file C4NetIO.cpp.

References AddConnectWait(), closesocket, C4NetIO::HostAddress::GetFamily(), HaveWouldBlockError(), C4NetIO::InitIPv6Socket(), INVALID_SOCKET, ioctlsocket, C4NetIO::HostAddress::IPv6, C4NetIO::SetError(), SOCK_CLOEXEC, SOCKET, and SOCKET_ERROR.

Referenced by C4Network2IRCClient::Connect(), C4Network2HTTPClient::Execute(), main(), and C4Network2HTTPClient::Query().

1168 {
1169  // create new socket
1170  SOCKET nsock = ::socket(addr.GetFamily() == HostAddress::IPv6 ? AF_INET6 : AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP);
1171  if (nsock == INVALID_SOCKET)
1172  {
1173  SetError("socket creation failed", true);
1174  return false;
1175  }
1176 
1177  if (addr.GetFamily() == HostAddress::IPv6)
1178  if (!InitIPv6Socket(nsock))
1179  return false;
1180 
1181 #ifdef STDSCHEDULER_USE_EVENTS
1182  // set event
1183  if (::WSAEventSelect(nsock, Event, FD_CONNECT) == SOCKET_ERROR)
1184  {
1185  // set error
1186  SetError("connect failed: could not set event", true);
1187  closesocket(nsock);
1188  return false;
1189  }
1190 
1191  // add to list
1192  AddConnectWait(nsock, addr);
1193 
1194 #elif defined(HAVE_WINSOCK)
1195  // disable blocking
1196  unsigned long iBlock = 1;
1197  if (::ioctlsocket(nsock, FIONBIO, &iBlock) == SOCKET_ERROR)
1198  {
1199  // set error
1200  SetError("connect failed: could not disable blocking", true);
1201  close(nsock);
1202  return false;
1203  }
1204 #else
1205  // disable blocking
1206  if (::fcntl(nsock, F_SETFL, fcntl(nsock, F_GETFL) | O_NONBLOCK) == SOCKET_ERROR)
1207  {
1208  // set error
1209  SetError("connect failed: could not disable blocking", true);
1210  close(nsock);
1211  return false;
1212  }
1213 #endif
1214 
1215  // connect (async)
1216  if (::connect(nsock, &addr, sizeof addr) == SOCKET_ERROR)
1217  {
1218  if (!HaveWouldBlockError()) // expected
1219  {
1220  SetError("socket connection failed", true);
1221  closesocket(nsock);
1222  return false;
1223  }
1224  }
1225 
1226 #ifndef STDSCHEDULER_USE_EVENTS
1227  // add to list
1228  AddConnectWait(nsock, addr);
1229 #endif
1230 
1231  // ok
1232  return true;
1233 }
#define INVALID_SOCKET
Definition: C4NetIO.h:37
void SetError(const char *strnError, bool fSockErr=false)
Definition: C4NetIO.cpp:754
#define ioctlsocket
Definition: C4NetIO.cpp:51
bool InitIPv6Socket(SOCKET socket)
Definition: C4NetIO.cpp:734
void AddConnectWait(SOCKET sock, const addr_t &addr)
Definition: C4NetIO.cpp:1607
#define SOCKET
Definition: C4NetIO.h:36
bool HaveWouldBlockError()
Definition: C4NetIO.cpp:209
#define SOCK_CLOEXEC
Definition: C4NetIO.h:51
#define closesocket
Definition: C4NetIO.cpp:52
#define SOCKET_ERROR
Definition: C4NetIO.cpp:53

Here is the call graph for this function:

Here is the caller graph for this function:

bool C4NetIOTCP::Execute ( int  iMaxTime = TO_INF,
pollfd *  readyfds = 0 
)
virtual

Implements C4NetIO.

Reimplemented in C4Network2HTTPClient.

Definition at line 932 of file C4NetIO.cpp.

References Accept(), fInit, GetFDs(), GetSocketErrorMsg(), HaveWouldBlockError(), iListenPort, INFINITE, INVALID_SOCKET, ioctlsocket, Listen(), lsock, C4NetIOTCP::Peer::Next, C4NetIO::CBClass::OnDisconn(), pConnectWaits, PeerListCSec, Pipe, pPeerList, ResetSocketError(), C4NetIO::SetError(), SOCKET, SOCKET_ERROR, and C4NetIO::TO_INF.

Referenced by C4AulDebug::DebugStep(), and C4Network2HTTPClient::Execute().

933 {
934  // security
935  if (!fInit) return false;
936 
937 #ifdef STDSCHEDULER_USE_EVENTS
938  // wait for something to happen
939  if (WaitForSingleObject(Event, iMaxTime == C4NetIO::TO_INF ? INFINITE : iMaxTime) == WAIT_TIMEOUT)
940  // timeout -> nothing happened
941  return true;
942  WSAResetEvent(Event);
943 
944  WSANETWORKEVENTS wsaEvents;
945 #else
946 
947 #ifdef __APPLE__
948  iMaxTime = fix_poll_timeout(iMaxTime);
949 #endif
950 
951  std::vector<pollfd> fdvec;
952  std::map<SOCKET, const pollfd*> fdmap;
953  if (!fds)
954  {
955  // build socket sets
956  GetFDs(fdvec);
957  fds = &fdvec[0];
958  // wait for something to happen
959  int ret = poll(fds, fdvec.size(), iMaxTime);
960  // error
961  if (ret < 0)
962  {
963  SetError("poll failed");
964  return false;
965  }
966  // nothing happened
967  if (ret == 0)
968  return true;
969  }
970  else
971  {
972  // We need to know the size of fdvec, so construct the vector
973  GetFDs(fdvec);
974  // Now overwrite with the poll result
975  std::copy(fds, fds + fdvec.size(), fdvec.begin());
976  }
977 
978  // flush pipe
979  assert(fdvec[0].fd == Pipe[0]);
980  if (fdvec[0].events & fdvec[0].revents)
981  {
982  char c;
983  if (::read(Pipe[0], &c, 1) == -1)
984  SetError("read failed");
985  }
986 
987  for (std::vector<pollfd>::const_iterator i = fdvec.begin(); i != fdvec.end(); ++i)
988  fdmap[i->fd] = &*i;
989  std::map<SOCKET, const pollfd*>::const_iterator cur_fd;
990 #endif
991 
992  // check sockets for events
993 
994  // first: the listen socket
995  if (lsock != INVALID_SOCKET)
996  {
997 
998 #ifdef STDSCHEDULER_USE_EVENTS
999  // get event list
1000  if (::WSAEnumNetworkEvents(lsock, nullptr, &wsaEvents) == SOCKET_ERROR)
1001  return false;
1002 
1003  // a connection waiting for accept?
1004  if (wsaEvents.lNetworkEvents & FD_ACCEPT)
1005 #else
1006  cur_fd = fdmap.find(lsock);
1007  // a connection waiting for accept?
1008  if (cur_fd != fdmap.end() && (cur_fd->second->events & cur_fd->second->revents))
1009 #endif
1010  if (!Accept())
1011  return false;
1012  // (note: what happens if there are more connections waiting?)
1013 
1014 #ifdef STDSCHEDULER_USE_EVENTS
1015  // closed?
1016  if (wsaEvents.lNetworkEvents & FD_CLOSE)
1017  // try to recreate the listen socket
1019 #endif
1020  }
1021 
1022  // second: waited-for connection
1023  CStdShareLock PeerListLock(&PeerListCSec);
1024  for (ConnectWait *pWait = pConnectWaits, *pNext; pWait; pWait = pNext)
1025  {
1026  pNext = pWait->Next;
1027 
1028  // not closed?
1029  if (pWait->sock)
1030  {
1031 #ifdef STDSCHEDULER_USE_EVENTS
1032  // get event list
1033  if (::WSAEnumNetworkEvents(pWait->sock, nullptr, &wsaEvents) == SOCKET_ERROR)
1034  return false;
1035 
1036  if (wsaEvents.lNetworkEvents & FD_CONNECT)
1037 #else
1038  // got connection?
1039  cur_fd = fdmap.find(pWait->sock);
1040  if (cur_fd != fdmap.end() && (cur_fd->second->events & cur_fd->second->revents))
1041 #endif
1042  {
1043  // remove from list
1044  SOCKET sock = pWait->sock; pWait->sock = 0;
1045 
1046 #ifdef STDSCHEDULER_USE_EVENTS
1047  // error?
1048  if (wsaEvents.iErrorCode[FD_CONNECT_BIT])
1049  {
1050  // disconnect-callback
1051  if (pCB) pCB->OnDisconn(pWait->addr, this, GetSocketErrorMsg(wsaEvents.iErrorCode[FD_CONNECT_BIT]));
1052  }
1053  else
1054 #else
1055  // get error code
1056  int iErrCode; socklen_t iErrCodeLen = sizeof(iErrCode);
1057  if (getsockopt(sock, SOL_SOCKET, SO_ERROR, reinterpret_cast<char *>(&iErrCode), &iErrCodeLen) != 0)
1058  {
1059  close(sock);
1060  if (pCB) pCB->OnDisconn(pWait->addr, this, GetSocketErrorMsg());
1061  }
1062  // error?
1063  else if (iErrCode)
1064  {
1065  close(sock);
1066  if (pCB) pCB->OnDisconn(pWait->addr, this, GetSocketErrorMsg(iErrCode));
1067  }
1068  else
1069 #endif
1070  // accept connection, do callback
1071  if (!Accept(sock, pWait->addr))
1072  return false;
1073  }
1074  }
1075 
1076  }
1077 
1078  // last: all connected sockets
1079  for (Peer *pPeer = pPeerList; pPeer; pPeer = pPeer->Next)
1080  if (pPeer->Open())
1081  {
1082  SOCKET sock = pPeer->GetSocket();
1083 
1084 #ifdef STDSCHEDULER_USE_EVENTS
1085  // get event list
1086  if (::WSAEnumNetworkEvents(sock, nullptr, &wsaEvents) == SOCKET_ERROR)
1087  return false;
1088 
1089  // something to read from socket?
1090  if (wsaEvents.lNetworkEvents & FD_READ)
1091 #else
1092  // something to read from socket?
1093  cur_fd = fdmap.find(sock);
1094  if (cur_fd != fdmap.end() && (POLLIN & cur_fd->second->revents))
1095 #endif
1096  for (;;)
1097  {
1098  // how much?
1099 #ifdef _WIN32
1100  DWORD iBytesToRead;
1101 #else
1102  int iBytesToRead;
1103 #endif
1104  if (::ioctlsocket(pPeer->GetSocket(), FIONREAD, &iBytesToRead) == SOCKET_ERROR)
1105  {
1106  pPeer->Close();
1107  if (pCB) pCB->OnDisconn(pPeer->GetAddr(), this, GetSocketErrorMsg());
1108  break;
1109  }
1110  // The following two lines of code will make sure that if the variable
1111  // "iBytesToRead" is zero, it will be increased by one.
1112  // In this case, it will hold the value 1 after the operation.
1113  // Note it doesn't do anything for negative values.
1114  // (This comment has been sponsored by Sven2)
1115  if (!iBytesToRead)
1116  ++iBytesToRead;
1117  // get buffer
1118  void *pBuf = pPeer->GetRecvBuf(iBytesToRead);
1119  // read a buffer full of data from socket
1120  int iBytesRead;
1121  if ((iBytesRead = ::recv(sock, reinterpret_cast<char *>(pBuf), iBytesToRead, 0)) == SOCKET_ERROR)
1122  {
1123  // Would block? Ok, let's try this again later
1124  if (HaveWouldBlockError()) { ResetSocketError(); break; }
1125  // So he's serious after all...
1126  pPeer->Close ();
1127  if (pCB) pCB->OnDisconn(pPeer->GetAddr(), this, GetSocketErrorMsg());
1128  break;
1129  }
1130  // nothing? this means the conection was closed, if you trust in linux manpages.
1131  if (!iBytesRead)
1132  {
1133  pPeer->Close();
1134  if (pCB) pCB->OnDisconn(pPeer->GetAddr(), this, "connection closed");
1135  break;
1136  }
1137  // pass to Peer::OnRecv
1138  pPeer->OnRecv(iBytesRead);
1139  }
1140 
1141  // socket has become writeable?
1142 #ifdef STDSCHEDULER_USE_EVENTS
1143  if (wsaEvents.lNetworkEvents & FD_WRITE)
1144 #else
1145  if (cur_fd != fdmap.end() && (POLLOUT & cur_fd->second->revents))
1146 #endif
1147  // send remaining data
1148  pPeer->Send();
1149 
1150 #ifdef STDSCHEDULER_USE_EVENTS
1151  // socket was closed?
1152  if (wsaEvents.lNetworkEvents & FD_CLOSE)
1153  {
1154  const char *szReason = wsaEvents.iErrorCode[FD_CLOSE_BIT] ? GetSocketErrorMsg(wsaEvents.iErrorCode[FD_CLOSE_BIT]) : "closed by peer";
1155  // close socket
1156  pPeer->Close();
1157  // do callback
1158  if (pCB) pCB->OnDisconn(pPeer->GetAddr(), this, szReason);
1159  }
1160 #endif
1161  }
1162 
1163  // done
1164  return true;
1165 }
#define INVALID_SOCKET
Definition: C4NetIO.h:37
const char * GetSocketErrorMsg(int iError)
Definition: C4NetIO.cpp:196
void SetError(const char *strnError, bool fSockErr=false)
Definition: C4NetIO.cpp:754
#define ioctlsocket
Definition: C4NetIO.cpp:51
virtual void GetFDs(std::vector< struct pollfd > &FDs)
Definition: C4NetIO.cpp:1320
bool Listen(uint16_t inListenPort)
Definition: C4NetIO.cpp:1494
Peer * pPeerList
Definition: C4NetIO.h:443
Peer * Accept(SOCKET nsock=INVALID_SOCKET, const addr_t &ConnectAddr=addr_t())
Definition: C4NetIO.cpp:1383
int Pipe[2]
Definition: C4NetIO.h:470
CStdCSecEx PeerListCSec
Definition: C4NetIO.h:455
void ResetSocketError()
Definition: C4NetIO.cpp:217
friend class Peer
Definition: C4NetIO.h:441
#define SOCKET
Definition: C4NetIO.h:36
bool HaveWouldBlockError()
Definition: C4NetIO.cpp:209
static const int TO_INF
Definition: C4NetIO.h:67
struct C4NetIOTCP::ConnectWait * pConnectWaits
bool fInit
Definition: C4NetIO.h:459
SOCKET lsock
Definition: C4NetIO.h:463
virtual void OnDisconn(const addr_t &AddrPeer, C4NetIO *pNetIO, const char *szReason)
Definition: C4NetIO.h:221
#define INFINITE
Definition: StdSync.h:58
uint32_t DWORD
uint16_t iListenPort
Definition: C4NetIO.h:462
#define SOCKET_ERROR
Definition: C4NetIO.cpp:53

Here is the call graph for this function:

Here is the caller graph for this function:

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

Definition at line 46 of file StdScheduler.cpp.

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

Referenced by main().

47 {
48  // Infinite?
49  if (iTimeout < 0)
50  for (;;)
51  if (!Execute())
52  return false;
53  // Calculate endpoint
54  C4TimeMilliseconds tStopTime = C4TimeMilliseconds::Now() + iTimeout;
55  for (;;)
56  {
57  // Call execute with given timeout
58  if (!Execute(std::max(iTimeout, 0)))
59  return false;
60  // Calculate timeout
62  if (tTime >= tStopTime)
63  break;
64  iTimeout = tStopTime - tTime;
65  }
66  // All ok.
67  return true;
68 }
virtual bool Execute(int iTimeout=-1, pollfd *readyfds=0)=0
static C4TimeMilliseconds Now()

Here is the call graph for this function:

Here is the caller graph for this function:

C4NetIOTCP::ConnectWait * C4NetIOTCP::GetConnectWait ( const addr_t addr)
protected

Definition at line 1623 of file C4NetIO.cpp.

References C4NetIOTCP::ConnectWait::Next, pConnectWaits, and PeerListCSec.

Referenced by Close().

1624 {
1625  CStdShareLock PeerListLock(&PeerListCSec);
1626  // search
1627  for (ConnectWait *pWait = pConnectWaits; pWait; pWait = pWait->Next)
1628  if (pWait->addr == addr)
1629  return pWait;
1630  return nullptr;
1631 }
CStdCSecEx PeerListCSec
Definition: C4NetIO.h:455
ConnectWait * Next
Definition: C4NetIO.h:451
struct C4NetIOTCP::ConnectWait * pConnectWaits

Here is the caller graph for this function:

bool C4NetIOTCP::GetConnStatistic ( const addr_t addr,
int *  pIRate,
int *  pORate,
int *  pLoss 
)
virtual

Implements C4NetIO.

Definition at line 1362 of file C4NetIO.cpp.

References C4NetIOTCP::Peer::GetIRate(), C4NetIOTCP::Peer::GetORate(), GetPeer(), C4NetIOTCP::Peer::Open(), and PeerListCSec.

1363 {
1364  CStdShareLock PeerListLock(&PeerListCSec);
1365  // find peer
1366  Peer *pPeer = GetPeer(addr);
1367  if (!pPeer || !pPeer->Open()) return false;
1368  // return statistics
1369  if (pIRate) *pIRate = pPeer->GetIRate();
1370  if (pORate) *pORate = pPeer->GetORate();
1371  if (pLoss) *pLoss = 0;
1372  return true;
1373 }
CStdCSecEx PeerListCSec
Definition: C4NetIO.h:455
Peer * GetPeer(const addr_t &addr)
Definition: C4NetIO.cpp:1549
friend class Peer
Definition: C4NetIO.h:441

Here is the call graph for this function:

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

Definition at line 285 of file C4NetIO.h.

References StdStrBuf::getData().

Referenced by C4Network2IO::Connect(), 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(); }
const char * getData() const
Definition: StdBuf.h:450
StdCopyStrBuf Error
Definition: C4NetIO.h:282

Here is the call graph for this function:

Here is the caller graph for this function:

void C4NetIOTCP::GetFDs ( std::vector< struct pollfd > &  FDs)
virtual

Reimplemented from StdSchedulerProc.

Definition at line 1320 of file C4NetIO.cpp.

References INVALID_SOCKET, lsock, C4NetIOTCP::Peer::Next, C4NetIOTCP::ConnectWait::Next, pConnectWaits, PeerListCSec, Pipe, and pPeerList.

Referenced by Execute().

1321 {
1322  pollfd pfd; pfd.revents = 0;
1323  // add pipe
1324  pfd.fd = Pipe[0]; pfd.events = POLLIN;
1325  fds.push_back(pfd);
1326  // add listener
1327  if (lsock != INVALID_SOCKET)
1328  {
1329  pfd.fd = lsock; pfd.events = POLLIN;
1330  fds.push_back(pfd);
1331  }
1332  // add connect waits (wait for them to become writeable)
1333  CStdShareLock PeerListLock(&PeerListCSec);
1334  for (ConnectWait *pWait = pConnectWaits; pWait; pWait = pWait->Next)
1335  {
1336  pfd.fd = pWait->sock; pfd.events = POLLOUT;
1337  fds.push_back(pfd);
1338  }
1339  // add sockets
1340  for (Peer *pPeer = pPeerList; pPeer; pPeer = pPeer->Next)
1341  if (pPeer->GetSocket())
1342  {
1343  // Wait for socket to become readable
1344  pfd.fd = pPeer->GetSocket(); pfd.events = POLLIN;
1345  // Wait for socket to become writeable, if there is data waiting
1346  if (pPeer->hasWaitingData())
1347  {
1348  pfd.events |= POLLOUT;
1349  }
1350  fds.push_back(pfd);
1351  }
1352 }
#define INVALID_SOCKET
Definition: C4NetIO.h:37
Peer * pPeerList
Definition: C4NetIO.h:443
int Pipe[2]
Definition: C4NetIO.h:470
CStdCSecEx PeerListCSec
Definition: C4NetIO.h:455
friend class Peer
Definition: C4NetIO.h:441
ConnectWait * Next
Definition: C4NetIO.h:451
struct C4NetIOTCP::ConnectWait * pConnectWaits
SOCKET lsock
Definition: C4NetIO.h:463

Here is the caller graph for this function:

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

Definition at line 632 of file C4NetIO.cpp.

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

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

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

Here is the call graph for this function:

Here is the caller graph for this function:

C4TimeMilliseconds StdSchedulerProc::GetNextTick ( C4TimeMilliseconds  tNow)
virtualinherited

Reimplemented in C4NetIOUDP, C4Network2HTTPClient, C4Network2IO, and CStdTimerProc.

Definition at line 128 of file StdScheduler.cpp.

References C4TimeMilliseconds::PositiveInfinity.

Referenced by C4Network2HTTPClient::GetNextTick().

Here is the caller graph for this function:

C4NetIOTCP::Peer * C4NetIOTCP::GetPeer ( const addr_t addr)
protected

Definition at line 1549 of file C4NetIO.cpp.

References C4NetIOTCP::Peer::Next, PeerListCSec, and pPeerList.

Referenced by Close(), GetConnStatistic(), Send(), and SetBroadcast().

1550 {
1551  CStdShareLock PeerListLock(&PeerListCSec);
1552  for (Peer *pPeer = pPeerList; pPeer; pPeer = pPeer->Next)
1553  if (pPeer->Open())
1554  if (pPeer->GetAddr() == addr)
1555  return pPeer;
1556  return nullptr;
1557 }
Peer * pPeerList
Definition: C4NetIO.h:443
CStdCSecEx PeerListCSec
Definition: C4NetIO.h:455
friend class Peer
Definition: C4NetIO.h:441

Here is the caller graph for this function:

bool C4NetIOTCP::GetStatistic ( int *  pBroadcastRate)
virtual

Implements C4NetIO.

Definition at line 1355 of file C4NetIO.cpp.

1356 {
1357  // no broadcast
1358  if (pBroadcastRate) *pBroadcastRate = 0;
1359  return true;
1360 }
bool C4NetIOTCP::Init ( uint16_t  iPort = addr_t::IPPORT_NONE)
virtual

Implements C4NetIO.

Reimplemented in C4AulDebug.

Definition at line 824 of file C4NetIO.cpp.

References Close(), fInit, C4NetIO::EndpointAddress::IPPORT_NONE, Listen(), Pipe, and C4NetIO::SetError().

Referenced by C4StartupNetDlg::CheckVersionUpdate(), C4Network2IRCClient::Connect(), C4AulDebug::Init(), C4Network2IO::Init(), C4Network2::InitLeague(), C4Game::InitNetworkFromAddress(), main(), C4StartupNetListEntry::SetRefQuery(), C4DownloadDlg::ShowModal(), and C4Network2::StartStreaming().

825 {
826  // already init? close first
827  if (fInit) Close();
828 
829 #ifdef HAVE_WINSOCK
830  // init winsock
831  if (!AcquireWinSock())
832  {
833  SetError("could not start winsock");
834  return false;
835  }
836 #endif
837 
838 #ifdef STDSCHEDULER_USE_EVENTS
839  // create event
840  if ((Event = WSACreateEvent()) == WSA_INVALID_EVENT)
841  {
842  SetError("could not create socket event", true); // to do: more error information
843  return false;
844  }
845 #else
846  // create pipe
847  if (pipe(Pipe) != 0)
848  {
849  SetError("could not create pipe", true);
850  return false;
851  }
852 #endif
853 
854  // create listen socket (if necessary)
855  if (iPort != addr_t::IPPORT_NONE)
856  if (!Listen(iPort))
857  return false;
858 
859  // ok
860  fInit = true;
861  return true;
862 }
void SetError(const char *strnError, bool fSockErr=false)
Definition: C4NetIO.cpp:754
bool Listen(uint16_t inListenPort)
Definition: C4NetIO.cpp:1494
int Pipe[2]
Definition: C4NetIO.h:470
virtual bool Close()
Definition: C4NetIO.cpp:870
bool fInit
Definition: C4NetIO.h:459
static const uint16_t IPPORT_NONE
Definition: C4NetIO.h:137

Here is the call graph for this function:

Here is the caller graph for this function:

bool C4NetIOTCP::InitBroadcast ( addr_t pBroadcastAddr)
virtual

Definition at line 864 of file C4NetIO.cpp.

Referenced by main().

865 {
866  // ignore
867  return true;
868 }

Here is the caller graph for this function:

bool C4NetIO::InitIPv6Socket ( SOCKET  socket)
protectedinherited

Definition at line 734 of file C4NetIO.cpp.

References C4NetIO::SetError(), and SOCKET_ERROR.

Referenced by Connect(), C4NetIOSimpleUDP::Init(), and Listen().

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

Here is the call graph for this function:

Here is the caller graph for this function:

virtual bool StdSchedulerProc::IsLowPriority ( )
inlinevirtualinherited

Definition at line 86 of file StdScheduler.h.

86 { return false; }
virtual bool C4NetIO::IsNotify ( )
inlinevirtualinherited

Reimplemented from StdSchedulerProc.

Definition at line 259 of file C4NetIO.h.

259 { return true; }
bool StdSchedulerProc::IsSignaled ( )
inherited
bool C4NetIOTCP::Listen ( uint16_t  inListenPort)
protected

Definition at line 1494 of file C4NetIO.cpp.

References C4NetIO::HostAddress::Any, StdSchedulerProc::Changed(), closesocket, iListenPort, C4NetIO::InitIPv6Socket(), INVALID_SOCKET, C4NetIO::EndpointAddress::IPPORT_NONE, lsock, C4NetIO::SetError(), C4NetIO::EndpointAddress::SetPort(), SOCK_CLOEXEC, and SOCKET_ERROR.

Referenced by Execute(), and Init().

1495 {
1496  // already listening?
1497  if (lsock != INVALID_SOCKET)
1498  // close existing socket
1499  closesocket(lsock);
1501 
1502  // create socket
1503  if ((lsock = ::socket(AF_INET6, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP)) == INVALID_SOCKET)
1504  {
1505  SetError("socket creation failed", true);
1506  return false;
1507  }
1508  if (!InitIPv6Socket(lsock))
1509  return false;
1510  // To be able to reuse the port after close
1511 #if !defined(_DEBUG) && !defined(_WIN32)
1512  int reuseaddr = 1;
1513  setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<const char *>(&reuseaddr), sizeof(reuseaddr));
1514 #endif
1515  // bind listen socket
1516  addr_t addr = addr_t::Any;
1517  addr.SetPort(inListenPort);
1518  if (::bind(lsock, &addr, sizeof(addr)) == SOCKET_ERROR)
1519  {
1520  SetError("socket bind failed", true);
1522  return false;
1523  }
1524 
1525 #ifdef STDSCHEDULER_USE_EVENTS
1526  // set event callback
1527  if (::WSAEventSelect(lsock, Event, FD_ACCEPT | FD_CLOSE) == SOCKET_ERROR)
1528  {
1529  SetError("could not set event for listen socket", true);
1531  return false;
1532  }
1533 #endif
1534 
1535  // start listening
1536  if (::listen(lsock, SOMAXCONN) == SOCKET_ERROR)
1537  {
1538  SetError("socket listen failed", true);
1540  return false;
1541  }
1542 
1543  // ok
1544  iListenPort = inListenPort;
1545  Changed();
1546  return true;
1547 }
#define INVALID_SOCKET
Definition: C4NetIO.h:37
void SetError(const char *strnError, bool fSockErr=false)
Definition: C4NetIO.cpp:754
bool InitIPv6Socket(SOCKET socket)
Definition: C4NetIO.cpp:734
EndpointAddress addr_t
Definition: C4NetIO.h:212
#define SOCK_CLOEXEC
Definition: C4NetIO.h:51
#define closesocket
Definition: C4NetIO.cpp:52
static const uint16_t IPPORT_NONE
Definition: C4NetIO.h:137
SOCKET lsock
Definition: C4NetIO.h:463
uint16_t iListenPort
Definition: C4NetIO.h:462
#define SOCKET_ERROR
Definition: C4NetIO.cpp:53

Here is the call graph for this function:

Here is the caller graph for this function:

void C4NetIOTCP::OnShareFree ( CStdCSecEx pCSec)
protectedvirtual

Implements CStdCSecExCallback.

Definition at line 1559 of file C4NetIO.cpp.

References C4NetIOTCP::Peer::Next, C4NetIOTCP::ConnectWait::Next, C4NetIOTCP::Peer::Open(), pConnectWaits, PeerListCSec, pPeerList, and C4NetIOTCP::ConnectWait::sock.

1560 {
1561  if (pCSec == &PeerListCSec)
1562  {
1563  // clear up
1564  Peer *pPeer = pPeerList, *pLast = nullptr;
1565  while (pPeer)
1566  {
1567  // delete?
1568  if (!pPeer->Open())
1569  {
1570  // unlink
1571  Peer *pDelete = pPeer;
1572  pPeer = pPeer->Next;
1573  (pLast ? pLast->Next : pPeerList) = pPeer;
1574  // delete
1575  delete pDelete;
1576  }
1577  else
1578  {
1579  // next peer
1580  pLast = pPeer;
1581  pPeer = pPeer->Next;
1582  }
1583  }
1584  ConnectWait *pWait = pConnectWaits, *pWLast = nullptr;
1585  while (pWait)
1586  {
1587  // delete?
1588  if (!pWait->sock)
1589  {
1590  // unlink
1591  ConnectWait *pDelete = pWait;
1592  pWait = pWait->Next;
1593  (pWLast ? pWLast->Next : pConnectWaits) = pWait;
1594  // delete
1595  delete pDelete;
1596  }
1597  else
1598  {
1599  // next peer
1600  pWLast = pWait;
1601  pWait = pWait->Next;
1602  }
1603  }
1604  }
1605 }
Peer * pPeerList
Definition: C4NetIO.h:443
CStdCSecEx PeerListCSec
Definition: C4NetIO.h:455
friend class Peer
Definition: C4NetIO.h:441
ConnectWait * Next
Definition: C4NetIO.h:451
struct C4NetIOTCP::ConnectWait * pConnectWaits

Here is the call graph for this function:

void C4NetIOTCP::PackPacket ( const C4NetIOPacket rPacket,
StdBuf rOutBuf 
)
protectedvirtual

Reimplemented in C4Network2HTTPClient, and C4Network2RefServer.

Definition at line 1644 of file C4NetIO.cpp.

References StdBuf::getSize(), StdBuf::Grow(), and iSize.

1645 {
1646  // packet data
1647  uint8_t cFirstByte = 0xff;
1648  uint32_t iSize = rPacket.getSize();
1649  uint32_t iOASize = sizeof(cFirstByte) + sizeof(iSize) + iSize;
1650 
1651  // enlarge buffer
1652  int iPos = rOutBuf.getSize();
1653  rOutBuf.Grow(iOASize);
1654 
1655  // write packet at end of outgoing buffer
1656  *getMBufPtr<uint8_t>(rOutBuf, iPos) = cFirstByte; iPos += sizeof(uint8_t);
1657  *getMBufPtr<uint32_t>(rOutBuf, iPos) = iSize; iPos += sizeof(uint32_t);
1658  rOutBuf.Write(rPacket, iPos);
1659 }
void Grow(size_t iGrow)
Definition: StdBuf.h:179
size_t getSize() const
Definition: StdBuf.h:109
int iSize
Definition: TstC4NetIO.cpp:35

Here is the call graph for this function:

void C4NetIO::ResetError ( )
inlineinherited

Definition at line 286 of file C4NetIO.h.

References StdStrBuf::Clear().

Referenced by C4NetIO::C4NetIO(), Close(), C4NetIOSimpleUDP::Close(), C4NetIOUDP::CloseBroadcast(), C4Network2IO::Connect(), C4NetIOSimpleUDP::Execute(), C4NetIOUDP::Execute(), C4Network2RefClient::GetReferences(), C4NetIOSimpleUDP::Init(), C4NetIOSimpleUDP::InitBroadcast(), C4NetIOUDP::InitBroadcast(), C4Network2HTTPClient::Query(), C4Network2IOConnection::Send(), C4NetIOSimpleUDP::Send(), and C4Network2HTTPClient::SetServer().

286 { Error.Clear(); }
void Clear()
Definition: StdBuf.h:474
StdCopyStrBuf Error
Definition: C4NetIO.h:282

Here is the call graph for this function:

Here is the caller graph for this function:

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

Referenced by main(), MyCBClass::OnConn(), MyCBClass::OnPacket(), C4Network2IOConnection::Send(), and C4Network2IO::SendPuncherPacket().

Here is the caller graph for this function:

bool C4NetIOTCP::Send ( const C4NetIOPacket rPacket)
virtual

Definition at line 1266 of file C4NetIO.cpp.

References C4NetIOPacket::getAddr(), GetPeer(), PeerListCSec, and C4NetIOTCP::Peer::Send().

Referenced by Broadcast(), C4Network2HTTPClient::OnConn(), C4Network2IRCClient::Send(), and C4NetIOTCP::Peer::Send().

1267 {
1268  CStdShareLock PeerListLock(&PeerListCSec);
1269  // find peer
1270  Peer *pPeer = GetPeer(rPacket.getAddr());
1271  // not found?
1272  if (!pPeer) return false;
1273  // send
1274  return pPeer->Send(rPacket);
1275 }
const C4NetIO::addr_t & getAddr() const
Definition: C4NetIO.h:316
CStdCSecEx PeerListCSec
Definition: C4NetIO.h:455
Peer * GetPeer(const addr_t &addr)
Definition: C4NetIO.cpp:1549
friend class Peer
Definition: C4NetIO.h:441
bool Send(const C4NetIOPacket &rPacket)
Definition: C4NetIO.cpp:1707

Here is the call graph for this function:

Here is the caller graph for this function:

bool C4NetIOTCP::SetBroadcast ( const addr_t addr,
bool  fSet = true 
)
virtual

Implements C4NetIO.

Definition at line 1277 of file C4NetIO.cpp.

References GetPeer(), PeerListCSec, and C4NetIOTCP::Peer::SetBroadcast().

1278 {
1279  CStdShareLock PeerListLock(&PeerListCSec);
1280  // find peer
1281  Peer *pPeer = GetPeer(addr);
1282  if (!pPeer) return false;
1283  // set flag
1284  pPeer->SetBroadcast(fSet);
1285  return true;
1286 }
CStdCSecEx PeerListCSec
Definition: C4NetIO.h:455
Peer * GetPeer(const addr_t &addr)
Definition: C4NetIO.cpp:1549
friend class Peer
Definition: C4NetIO.h:441

Here is the call graph for this function:

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

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

Here is the caller graph for this function:

virtual void C4NetIOTCP::SetCallback ( CBClass *  pnCallback)
inlinevirtual

Definition at line 487 of file C4NetIO.h.

Referenced by C4Network2HTTPClient::C4Network2HTTPClient(), C4Network2IRCClient::Connect(), and C4AulDebug::Init().

487 { pCB = pnCallback; };

Here is the caller graph for this function:

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

Definition at line 754 of file C4NetIO.cpp.

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

Referenced by Accept(), C4NetIOSimpleUDP::CloseBroadcast(), C4Network2IRCClient::Connect(), Connect(), C4NetIOUDP::DoLoopbackTest(), Execute(), C4NetIOSimpleUDP::Execute(), C4NetIOUDP::Execute(), C4Network2RefClient::GetReferences(), C4Network2UpdateClient::GetUpdateURL(), C4Network2UpdateClient::GetVersion(), Init(), C4NetIOSimpleUDP::Init(), C4NetIOSimpleUDP::InitBroadcast(), C4NetIOUDP::InitBroadcast(), C4NetIO::InitIPv6Socket(), C4Network2IRCClient::Join(), Listen(), C4Network2IRCClient::Send(), C4NetIOSimpleUDP::Send(), C4Network2HTTPClient::SetServer(), UnBlock(), and C4NetIOSimpleUDP::UnBlock().

755 {
756  fSockErr &= HaveSocketError();
757  if (fSockErr)
758  Error.Format("%s (%s)", strnError, GetSocketErrorMsg());
759  else
760  Error.Copy(strnError);
761 }
const char * GetSocketErrorMsg(int iError)
Definition: C4NetIO.cpp:196
StdCopyStrBuf Error
Definition: C4NetIO.h:282
void Format(const char *szFmt,...) GNUC_FORMAT_ATTRIBUTE_O
Definition: StdBuf.cpp:181
bool HaveSocketError()
Definition: C4NetIO.cpp:205
void Copy()
Definition: StdBuf.h:475

Here is the call graph for this function:

Here is the caller graph for this function:

virtual uint32_t StdSchedulerProc::TimerInterval ( )
inlinevirtualinherited

Reimplemented in CStdTimerProc.

Definition at line 88 of file StdScheduler.h.

Referenced by SCHAdditions::assignAdditionForProc:.

88 { return 0; }

Here is the caller graph for this function:

void C4NetIOTCP::UnBlock ( )
virtual

Definition at line 1299 of file C4NetIO.cpp.

References Pipe, and C4NetIO::SetError().

Referenced by AddConnectWait().

1300 {
1301 #ifdef STDSCHEDULER_USE_EVENTS
1302  // unblock WaitForSingleObject in C4NetIOTCP::Execute manually
1303  // by setting the Event
1304  WSASetEvent(Event);
1305 #else
1306  // write one character to the pipe, this will unblock everything that
1307  // waits for the FD set returned by GetFDs.
1308  char c = 1;
1309  if (write(Pipe[1], &c, 1) == -1)
1310  SetError("write failed");
1311 #endif
1312 }
void SetError(const char *strnError, bool fSockErr=false)
Definition: C4NetIO.cpp:754
int Pipe[2]
Definition: C4NetIO.h:470

Here is the call graph for this function:

Here is the caller graph for this function:

size_t C4NetIOTCP::UnpackPacket ( const StdBuf rInBuf,
const C4NetIO::addr_t Addr 
)
protectedvirtual

Reimplemented in C4Network2HTTPClient, and C4Network2RefServer.

Definition at line 1661 of file C4NetIO.cpp.

References StdBuf::getSize(), and C4NetIO::CBClass::OnPacket().

1662 {
1663  size_t iPos = 0;
1664  // check first byte (should be 0xff)
1665  if (*getBufPtr<uint8_t>(IBuf, iPos) != (uint8_t) 0xff)
1666  // clear buffer
1667  return IBuf.getSize();
1668  iPos += sizeof(char);
1669  // read packet size
1670  uint32_t iPacketSize;
1671  if (iPos + sizeof(uint32_t) > IBuf.getSize())
1672  return 0;
1673  iPacketSize = *getBufPtr<uint32_t>(IBuf, iPos);
1674  iPos += sizeof(uint32_t);
1675  // packet incomplete?
1676  if (iPos + iPacketSize > IBuf.getSize())
1677  return 0;
1678  // ok, call back
1679  if (pCB) pCB->OnPacket(C4NetIOPacket(IBuf.getPart(iPos, iPacketSize), addr), this);
1680  // absorbed
1681  return iPos + iPacketSize;
1682 }
virtual void OnPacket(const class C4NetIOPacket &rPacket, C4NetIO *pNetIO)=0

Here is the call graph for this function:

Friends And Related Function Documentation

friend class Peer
friend

Definition at line 441 of file C4NetIO.h.

Referenced by Accept().

Member Data Documentation

bool C4NetIOTCP::fInit
protected

Definition at line 459 of file C4NetIO.h.

Referenced by Close(), Execute(), and Init().

uint16_t C4NetIOTCP::iListenPort
protected

Definition at line 462 of file C4NetIO.h.

Referenced by Execute(), and Listen().

SOCKET C4NetIOTCP::lsock
protected

Definition at line 463 of file C4NetIO.h.

Referenced by Accept(), Close(), Execute(), GetFDs(), and Listen().

struct C4NetIOTCP::ConnectWait * C4NetIOTCP::pConnectWaits
protected
CStdCSec C4NetIOTCP::PeerListAddCSec
protected

Definition at line 456 of file C4NetIO.h.

Referenced by Accept(), and AddConnectWait().

int C4NetIOTCP::Pipe[2]
protected

Definition at line 470 of file C4NetIO.h.

Referenced by Close(), Execute(), GetFDs(), Init(), and UnBlock().

Peer* C4NetIOTCP::pPeerList
protected

Definition at line 443 of file C4NetIO.h.

Referenced by Accept(), Broadcast(), ClearStatistic(), Close(), Execute(), GetFDs(), GetPeer(), and OnShareFree().

const int C4NetIO::TO_INF = -1
staticinherited

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