OpenClonk
C4Network2Client.cpp
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) 2010-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 #include "C4Include.h"
18 
19 #include "editor/C4Console.h"
20 #include "gui/C4GameLobby.h" // fullscreen network lobby
21 #include "network/C4Network2.h"
23 #include "player/C4PlayerList.h"
24 
25 #include <thread>
26 #include <chrono>
27 
28 // *** C4Network2Client
29 
31  : pClient(pClient),
32  iAddrCnt(0),
33  eStatus(NCS_Ready),
34  iLastActivity(0),
35  pMsgConn(nullptr), pDataConn(nullptr),
36  iNextConnAttempt(0),
37  pNext(nullptr), pParent(nullptr), pstatPing(nullptr)
38 {
39 }
40 
42 {
43  ClearGraphs();
44  if (pMsgConn) { pMsgConn->Close(); pMsgConn->DelRef(); } pMsgConn = nullptr;
45  if (pDataConn) { pDataConn->Close(); pDataConn->DelRef(); } pDataConn = nullptr;
47 }
48 
50 {
51  return pMsgConn == pConn || pDataConn == pConn;
52 }
53 
55 {
56  // security
57  if (pConn != pMsgConn)
58  {
59  if (pMsgConn) pMsgConn->DelRef();
60  pMsgConn = pConn;
61  pMsgConn->AddRef();
62  }
63  if (!pDataConn) SetDataConn(pConn);
64 }
65 
67 {
68  // security
69  if (pConn != pDataConn)
70  {
71  if (pDataConn) pDataConn->DelRef();
72  pDataConn = pConn;
73  pDataConn->AddRef();
74  }
75  if (!pMsgConn) SetMsgConn(pConn);
76 }
77 
79 {
80  if (pConn == pMsgConn)
81  { pMsgConn->DelRef(); pMsgConn = nullptr; }
82  if (pConn == pDataConn)
83  { pDataConn->DelRef(); pDataConn = nullptr; }
86 }
87 
88 
89 void C4Network2Client::CloseConns(const char *szMsg)
90 {
91  C4PacketConnRe Pkt(false, false, szMsg);
93  while ((pConn = pMsgConn))
94  {
95  // send packet, close
96  if (pConn->isOpen())
97  {
98  pConn->Send(MkC4NetIOPacket(PID_ConnRe, Pkt));
99  pConn->Close();
100  }
101  // remove
102  RemoveConn(pConn);
103  }
104 }
105 
107 {
108  return getMsgConn() && getMsgConn()->Send(rPkt);
109 }
110 
112 {
113  return getDataConn() && getDataConn()->Send(rPkt);
114 }
115 
117 {
118  // local?
119  if (isLocal()) { iNextConnAttempt = 0; return true; }
120  // msg and data connected? Nothing to do
121  if (getMsgConn() != getDataConn()) { iNextConnAttempt = time(nullptr) + 10; return true; }
122  // too early?
123  if (iNextConnAttempt && iNextConnAttempt > time(nullptr)) return true;
124  // find address to try
125  int32_t iBestAddress = -1;
126  for (int32_t i = 0; i < iAddrCnt; i++)
127  // no connection for this protocol?
128  if ((!pDataConn || Addr[i].getProtocol() != pDataConn->getProtocol()) &&
129  (!pMsgConn || Addr[i].getProtocol() != pMsgConn->getProtocol()))
130  // protocol available?
131  if (pIO->getNetIO(Addr[i].getProtocol()))
132  // new best address?
133  if (iBestAddress < 0 || AddrAttempts[i] < AddrAttempts[iBestAddress])
134  iBestAddress = i;
135  // too many attempts or nothing found?
136  if (iBestAddress < 0 || AddrAttempts[iBestAddress] > C4NetClientConnectAttempts)
137  { iNextConnAttempt = time(nullptr) + 10; return true; }
138  // save attempt
139  AddrAttempts[iBestAddress]++; iNextConnAttempt = time(nullptr) + C4NetClientConnectInterval;
140  auto addr = Addr[iBestAddress].getAddr();
141 
142  // try TCP simultaneous open if the stars align right
143  if (addr.GetFamily() == C4NetIO::addr_t::IPv6 && // address needs to be IPv6...
144  !addr.IsLocal() && !addr.IsPrivate() && // ...global unicast...
145  Addr[iBestAddress].getProtocol() == P_TCP && // ...TCP,
146  !TcpSimOpenSocket && // there is no previous request,
147  pParent->GetLocal()->getID() < getID()) // and make sure that only one client per pair initiates a request.
148  {
150  }
151 
152  std::set<int> interfaceIDs;
153  if (addr.IsLocal())
154  interfaceIDs = Network.Clients.GetLocal()->getInterfaceIDs();
155  else
156  interfaceIDs = {0};
157  for (auto id : interfaceIDs)
158  {
159  addr.SetScopeId(id);
160  // log
161  LogSilentF("Network: connecting client %s on %s...", getName(), addr.ToString().getData());
162  // connect
163  if (pIO->Connect(addr, Addr[iBestAddress].getProtocol(), pClient->getCore()))
164  return true;
165  }
166  return false;
167 }
168 
170 {
171  if (!pIO->getNetIO(P_TCP)) return false;
172 
173  // Did we already bind a socket?
174  if (TcpSimOpenSocket)
175  {
176  LogSilentF("Network: connecting client %s on %s with TCP simultaneous open...", getName(), addr.getAddr().ToString().getData());
177  return pIO->ConnectWithSocket(addr.getAddr(), addr.getProtocol(), pClient->getCore(), std::move(TcpSimOpenSocket));
178  }
179  else
180  {
181  // No - bind one, inform peer, and schedule a connection attempt.
182  auto NetIOTCP = dynamic_cast<C4NetIOTCP*>(pIO->getNetIO(P_TCP));
183  auto bindAddr = pParent->GetLocal()->IPv6AddrFromPuncher;
184  // We need to know an address that works.
185  if (bindAddr.IsNull()) return false;
186  bindAddr.SetPort(0);
187  TcpSimOpenSocket = NetIOTCP->Bind(bindAddr);
188  auto boundAddr = TcpSimOpenSocket->GetAddress();
189  LogSilentF("Network: %s TCP simultaneous open request for client %s from %s...", addr.isIPNull() ? "initiating" : "responding to",
190  getName(), boundAddr.ToString().getData());
191  // Send address we bound to to the client.
193  return false;
194  if (!addr.isIPNull())
195  {
196  // We need to delay the connection attempt a bit. Unfortunately,
197  // waiting for the next tick would usually take way too much time.
198  // Instead, we block the main thread for a very short time and hope
199  // that noone notices...
200  int ping = getMsgConn()->getLag();
201  std::this_thread::sleep_for(std::chrono::milliseconds(std::min(ping / 2, 10)));
202  DoTCPSimultaneousOpen(pIO, addr);
203  }
204  return true;
205  }
206 }
207 
209 {
210  // Note that the host only knows its own address as 0.0.0.0, so if the real address is being added, that can't be sorted out.
211  for (int32_t i = 0; i < iAddrCnt; i++)
212  if (Addr[i] == addr)
213  return true;
214  return false;
215 }
216 
218 {
219  iAddrCnt = 0;
220 }
221 
223 {
224  AddAddr(C4Network2Address(addr, P_UDP), true);
225  // If the outside port matches the inside port, there is no port translation and the
226  // TCP address will probably work as well.
227  if (addr.GetPort() == Config.Network.PortUDP && Config.Network.PortTCP > 0)
228  {
229  auto tcpAddr = addr;
230  tcpAddr.SetPort(Config.Network.PortTCP);
231  AddAddr(C4Network2Address(tcpAddr, P_TCP), true);
232  }
233  // Save IPv6 address for TCP simultaneous connect.
234  if (addr.GetFamily() == C4NetIO::addr_t::IPv6)
235  IPv6AddrFromPuncher = addr;
236 }
237 
238 bool C4Network2Client::AddAddr(const C4Network2Address &addr, bool fAnnounce)
239 {
240  // checks
241  if (iAddrCnt + 1 >= C4ClientMaxAddr) return false;
242  if (hasAddr(addr)) return true;
243  // add
244  Addr[iAddrCnt] = addr; AddrAttempts[iAddrCnt] = 0;
245  iAddrCnt++;
246  // attempt to use this one
247  if (!iNextConnAttempt) iNextConnAttempt = time(nullptr);
248  // announce
249  if (fAnnounce)
251  return false;
252  // done
253  return true;
254 }
255 
256 void C4Network2Client::AddLocalAddrs(int16_t iPortTCP, int16_t iPortUDP)
257 {
258  C4NetIO::addr_t addr;
259 
260  for (auto& ha : C4NetIO::GetLocalAddresses())
261  {
262  addr.SetAddress(ha);
263  if (iPortTCP)
264  {
265  addr.SetPort(iPortTCP);
266  AddAddr(C4Network2Address(addr, P_TCP), false);
267  }
268  if (iPortUDP)
269  {
270  addr.SetPort(iPortUDP);
271  AddAddr(C4Network2Address(addr, P_UDP), false);
272  }
273  if (addr.GetScopeId())
274  InterfaceIDs.insert(addr.GetScopeId());
275  }
276 }
277 
279 {
280  // send all addresses
281  for (int32_t i = 0; i < iAddrCnt; i++)
282  {
283  if (Addr[i].getAddr().GetScopeId() && (!pConn || pConn->getPeerAddr().GetScopeId() != Addr[i].getAddr().GetScopeId()))
284  continue;
285  C4Network2Address addr(Addr[i]);
286  addr.getAddr().SetScopeId(0);
288  if (pConn)
289  pConn->Send(Pkt);
290  else
292  }
293 
294 }
295 
297 {
298  // del prev
299  ClearGraphs();
300  // get client color
301  static const DWORD ClientDefColors[] = {0xff0000, 0x00ff00, 0xffff00, 0x7f7fff, 0xffffff, 0x00ffff, 0xff00ff, 0x7f7f7f, 0xff7f7f, 0x7fff7f, 0x0000ff};
302  int32_t iClientColorNum = sizeof(ClientDefColors)/sizeof(DWORD);
303  DWORD dwClientClr = ClientDefColors[std::max<int32_t>(getID(), 0) % iClientColorNum];
304  // create graphs
306  pstatPing->SetColorDw(dwClientClr);
308  // register into stat module
309  if (Game.pNetworkStatistics) Game.pNetworkStatistics->statPings.AddGraph(pstatPing);
310 }
311 
313 {
314  // del all assigned graphs
315  if (pstatPing)
316  {
317  if (Game.pNetworkStatistics) Game.pNetworkStatistics->statPings.RemoveGraph(pstatPing);
318  delete pstatPing;
319  pstatPing = nullptr;
320  }
321 }
322 
323 // *** C4Network2ClientList
324 
326  : pIO(pIO), pFirst(nullptr), pLocal(nullptr)
327 {
328 
329 }
330 
332 {
333  Clear();
334 }
335 
337 {
338  for (C4Network2Client *pClient = pFirst; pClient; pClient = pClient->pNext)
339  if (pClient->getID() == iID)
340  return pClient;
341  return nullptr;
342 }
343 
345 {
346  // return client with smallest ID > iSmallerClientID
347  C4Network2Client *pBest = nullptr;
348  for (C4Network2Client *pClient = pFirst; pClient; pClient = pClient->pNext)
349  if (pClient->getID() > iSmallerClientID)
350  if (!pBest || pBest->getID() > pClient->getID())
351  pBest = pClient;
352  return pBest;
353 }
354 
356 {
357  for (C4Network2Client *pClient = pFirst; pClient; pClient = pClient->pNext)
358  if (SEqual(pClient->getName(), szName))
359  return pClient;
360  return nullptr;
361 }
362 
364 {
365  for (C4Network2Client *pClient = pFirst; pClient; pClient = pClient->pNext)
366  if (pClient->hasConn(pConn))
367  return pClient;
368  return nullptr;
369 }
370 
371 C4Network2Client *C4Network2ClientList::GetClient(const C4ClientCore &CCore, int32_t iMaxDiffLevel)
372 {
373  for (C4Network2Client *pClient = pFirst; pClient; pClient = pClient->pNext)
374  if (pClient->getCore().getDiffLevel(CCore) <= iMaxDiffLevel)
375  return pClient;
376  return nullptr;
377 }
378 
380 {
381  unsigned int ret(0);
382  for (C4Network2Client *pClient = pFirst; pClient; pClient = pClient->pNext) ret++;
383  return ret;
384 }
385 
387 {
389 }
390 
392 {
393  return pClient ? pClient->pNext : pFirst;
394 }
395 
396 void C4Network2ClientList::Init(C4ClientList *pnClientList, bool fnHost)
397 {
398  // save flag
399  fHost = fnHost;
400  // initialize
401  pClientList = pnClientList;
402  pClientList->InitNetwork(this);
403 }
404 
406 {
407  // security
408  if (pClient->getNetClient())
409  return pClient->getNetClient();
410  // find insert position
411  C4Network2Client *pPos = pFirst, *pLast = nullptr;
412  for (; pPos; pLast = pPos, pPos = pPos->getNext())
413  if (pPos->getID() > pClient->getID())
414  break;
415  assert(!pLast || pLast->getID() != pClient->getID());
416  // create new client
417  C4Network2Client *pNetClient = new C4Network2Client(pClient);
418  // add to list
419  pNetClient->pNext = pPos;
420  (pLast ? pLast->pNext : pFirst) = pNetClient;
421  pNetClient->pParent = this;
422  // local?
423  if (pClient->isLocal())
424  pLocal = pNetClient;
425  else
426  // set auto-accept
427  pIO->AddAutoAccept(pClient->getCore());
428  // add
429  return pNetClient;
430 }
431 
433 {
434  // close connections
435  pClient->CloseConns("removing client");
436  // remove from list
437  if (pClient == pFirst)
438  pFirst = pClient->getNext();
439  else
440  {
441  C4Network2Client *pPrev;
442  for (pPrev = pFirst; pPrev && pPrev->getNext(); pPrev = pPrev->getNext())
443  if (pPrev->getNext() == pClient)
444  break;
445  if (pPrev && pPrev->getNext() == pClient)
446  pPrev->pNext = pClient->getNext();
447  }
448  // remove auto-accept
449  pIO->RemoveAutoAccept(pClient->getCore());
450  // delete
451  delete pClient;
452 }
453 
455 {
456  // remove link to main client list
457  if (pClientList)
458  {
459  C4ClientList *poClientList = pClientList;
460  pClientList = nullptr;
461  poClientList->ClearNetwork();
462  }
463  // delete clients
464  while (pFirst)
465  {
467  }
468  pLocal = nullptr;
469 }
470 
472 {
473  // Send a msg to all clients that are currently directly reachable.
474 
475  // lock
476  pIO->BeginBroadcast(false);
477  // select connections for broadcast
478  for (C4Network2Client *pClient = pFirst; pClient; pClient = pClient->getNext())
479  if (pClient->isConnected())
480  pClient->getMsgConn()->SetBroadcastTarget(true);
481  // broadcast
482  bool fSuccess = pIO->Broadcast(rPkt);
483  // unlock
484  pIO->EndBroadcast();
485  // finished
486  return fSuccess;
487 }
488 
490 {
491  // Send a msg to all clients, including clients that are not connected to
492  // this computer (will get forwarded by host).
493 
494  C4PacketFwd Fwd; Fwd.SetListType(true);
495  // lock
496  pIO->BeginBroadcast(false);
497  // select connections for broadcast
498  for (C4Network2Client *pClient = pFirst; pClient; pClient = pClient->getNext())
499  if (!pClient->isHost())
500  if (pClient->isConnected())
501  {
502  pClient->getMsgConn()->SetBroadcastTarget(true);
503  Fwd.AddClient(pClient->getID());
504  }
505  // broadcast
506  bool fSuccess = pIO->Broadcast(rPkt);
507  // unlock
508  pIO->EndBroadcast();
509  // clients: send forward request to host
510  if (!fHost)
511  {
512  Fwd.SetData(rPkt);
513  fSuccess &= SendMsgToHost(MkC4NetIOPacket(PID_FwdReq, Fwd));
514  }
515  return fSuccess;
516 }
517 
519 {
520  // find host
521  C4Network2Client *pHost = GetHost();
522  if (!pHost) return false;
523  // send message
524  if (!pHost->getMsgConn()) return false;
525  return pHost->SendMsg(rPkt);
526 }
527 
529 {
530  // find client
531  C4Network2Client *pClient = GetClientByID(iClient);
532  if (!pClient) return false;
533  // connected? send directly
534  if (pClient->isConnected())
535  return pClient->SendMsg(rPkt);
536  // forward
537  C4PacketFwd Fwd; Fwd.SetListType(false);
538  Fwd.AddClient(iClient);
539  Fwd.SetData(rPkt);
541 }
542 
543 void C4Network2ClientList::HandlePacket(char cStatus, const C4PacketBase *pBasePkt, C4Network2IOConnection *pConn)
544 {
545  // find associated client
546  C4Network2Client *pClient = GetClient(pConn);
547  if (!pClient) return;
548 
549 #define GETPKT(type, name) \
550  assert(pBasePkt); const type &name = \
551  static_cast<const type &>(*pBasePkt);
552 
553  switch (cStatus)
554  {
555 
556  case PID_Addr: // address propagation
557  {
558  GETPKT(C4PacketAddr, rPkt)
559  // find client
560  pClient = GetClientByID(rPkt.getClientID());
561  if (pClient)
562  {
563  C4Network2Address addr = rPkt.getAddr();
564  // IP zero? Set to IP from where the packet came
565  if (addr.isIPNull())
566  {
567  addr.SetIP(pConn->getPeerAddr());
568  }
569  // add (no announce)
570  if (pClient->AddAddr(addr, true))
571  // new address? Try to connect
572  pClient->DoConnectAttempt(pIO);
573  }
574  }
575  break;
576 
577  case PID_TCPSimOpen:
578  {
580  pClient = GetClientByID(rPkt.getClientID());
581  if (pClient)
582  {
583  C4Network2Address addr = rPkt.getAddr();
584  pClient->DoTCPSimultaneousOpen(pIO, addr);
585  }
586  }
587  break;
588 
589  }
590 
591 #undef GETPKT
592 }
593 
595 {
596  // send all client addresses known
597  for (C4Network2Client *pClient = pFirst; pClient; pClient = pClient->getNext())
598  pClient->SendAddresses(pConn);
599 }
600 
602 {
603  // check interval
604  time_t t; time(&t);
605  for (C4Network2Client *pClient = pFirst; pClient; pClient = pClient->getNext())
606  {
607  if (!pClient->isLocal() && !pClient->isRemoved() && pClient->getNextConnAttempt() && pClient->getNextConnAttempt() <= t)
608  // attempt connect
609  pClient->DoConnectAttempt(pIO);
610  }
611 }
612 
614 {
615  for (C4Network2Client *pClient = pFirst; pClient; pClient = pClient->getNext())
616  if (pClient->isWaitedFor())
617  pClient->SetStatus(NCS_NotReady);
618 }
619 
621 {
622  for (C4Network2Client *pClient = pFirst; pClient; pClient = pClient->getNext())
623  if (!pClient->isLocal() && pClient->isWaitedFor() && !pClient->isReady())
624  return false;
625  return true;
626 }
627 
629 {
630  for (C4Network2Client *pClient = pFirst; pClient; pClient = pClient->getNext())
631  if (pClient->isActivated())
632  if (::Players.GetAtClient(pClient->getID()))
633  pClient->SetLastActivity(Game.FrameCounter);
634 }
635 
636 // *** C4PacketAddr
637 
639 {
641  pComp->Value(mkNamingAdapt(addr, "Addr"));
642 }
643 
644 // *** C4PacketTCPSimOpen
645 
647 {
649  pComp->Value(mkNamingAdapt(addr, "Addr"));
650 }
651 
const int32_t C4ClientIDHost
Definition: C4Client.h:25
const int32_t C4ClientIDUnknown
Definition: C4Client.h:24
C4Config Config
Definition: C4Config.cpp:930
C4Game Game
Definition: C4Globals.cpp:52
C4Network2 Network
Definition: C4Globals.cpp:53
bool LogSilentF(const char *strMessage,...)
Definition: C4Log.cpp:272
#define GETPKT(type, name)
@ NCS_Ready
@ NCS_NotReady
const int32_t C4NetClientConnectAttempts
const int32_t C4NetClientConnectInterval
const int32_t C4ClientMaxAddr
@ P_UDP
Definition: C4Network2IO.h:31
@ P_TCP
Definition: C4Network2IO.h:31
C4NetIOPacket MkC4NetIOPacket(char cStatus, const class C4PacketBase &Pkt, const C4NetIO::addr_t &addr=C4NetIO::addr_t())
Definition: C4PacketBase.h:40
@ PID_TCPSimOpen
Definition: C4PacketBase.h:113
@ PID_FwdReq
Definition: C4PacketBase.h:92
@ PID_ConnRe
Definition: C4PacketBase.h:89
@ PID_Addr
Definition: C4PacketBase.h:107
C4PlayerList Players
uint32_t DWORD
bool SEqual(const char *szStr1, const char *szStr2)
Definition: Standard.h:93
StdIntPackAdapt< T > mkIntPackAdapt(T &rVal)
Definition: StdAdaptors.h:791
StdNamingAdapt< T > mkNamingAdapt(T &&rValue, const char *szName)
Definition: StdAdaptors.h:92
bool isLocal() const
Definition: C4Client.h:116
int32_t getID() const
Definition: C4Client.h:105
void UnlinkNetClient()
Definition: C4Client.h:129
C4Network2Client * getNetClient() const
Definition: C4Client.h:117
const C4ClientCore & getCore() const
Definition: C4Client.h:104
void InitNetwork(class C4Network2ClientList *pNetClients)
Definition: C4Client.cpp:251
void ClearNetwork()
Definition: C4Client.cpp:262
C4ConfigNetwork Network
Definition: C4Config.h:259
int32_t PortUDP
Definition: C4Config.h:153
int32_t PortTCP
Definition: C4Config.h:153
std::unique_ptr< C4Network2Stats > pNetworkStatistics
Definition: C4Game.h:95
int32_t FrameCounter
Definition: C4Game.h:129
void SetTitle(const char *szNewTitle)
void SetColorDw(DWORD dwClr)
static std::vector< HostAddress > GetLocalAddresses()
Definition: C4NetIO.cpp:631
const C4NetIO::addr_t & getAddr() const
void SetIP(C4NetIO::addr_t ip)
C4Network2IOProtocol getProtocol() const
bool isIPNull() const
C4Network2Address Addr[C4ClientMaxAddr]
void CloseConns(const char *szMsg)
bool DoConnectAttempt(class C4Network2IO *pIO)
void AddAddrFromPuncher(const C4NetIO::addr_t &addr)
C4Network2IOConnection * pMsgConn
bool hasAddr(const C4Network2Address &addr) const
bool DoTCPSimultaneousOpen(class C4Network2IO *pIO, const C4Network2Address &addr)
const char * getName() const
int32_t getID() const
C4Network2Client * pNext
const std::set< int > & getInterfaceIDs() const
C4Network2Client(C4Client *pClient)
int32_t AddrAttempts[C4ClientMaxAddr]
bool isConnected() const
void RemoveConn(C4Network2IOConnection *pConn)
class C4TableGraph * pstatPing
C4Network2IOConnection * getDataConn() const
bool isLocal() const
bool SendMsg(C4NetIOPacket rPkt) const
C4Network2IOConnection * getMsgConn() const
C4Network2IOConnection * pDataConn
std::set< int > InterfaceIDs
std::unique_ptr< C4NetIOTCP::Socket > TcpSimOpenSocket
class C4Network2ClientList * pParent
void SetDataConn(C4Network2IOConnection *pConn)
bool SendData(C4NetIOPacket rPkt) const
void SendAddresses(C4Network2IOConnection *pConn)
bool AddAddr(const C4Network2Address &addr, bool fAnnounce)
const C4Network2Address & getAddr(int32_t i) const
C4Network2Client * getNext() const
C4NetIO::addr_t IPv6AddrFromPuncher
bool hasConn(C4Network2IOConnection *pConn)
void SetMsgConn(C4Network2IOConnection *pConn)
void AddLocalAddrs(int16_t iPortTCP, int16_t iPortUDP)
const C4ClientCore & getCore() const
C4ClientList * pClientList
C4Network2Client * GetClient(const char *szName) const
C4Network2Client * GetHost()
bool SendMsgToClient(int32_t iClient, C4NetIOPacket &&rPkt)
C4Network2Client * GetNextClientAfterID(int32_t iSmallerClientID) const
C4Network2Client * GetNextClient(C4Network2Client *pClient)
C4Network2Client * GetClientByID(int32_t iID) const
C4Network2Client * GetLocal() const
bool BroadcastMsgToClients(const C4NetIOPacket &rPkt)
C4Network2Client * pLocal
void Init(C4ClientList *pClientList, bool fHost)
bool BroadcastMsgToConnClients(const C4NetIOPacket &rPkt)
C4Network2Client * pFirst
bool SendMsgToHost(C4NetIOPacket rPkt)
C4Network2ClientList(C4Network2IO *pIO)
C4Network2Client * RegClient(C4Client *pClient)
void DeleteClient(C4Network2Client *pClient)
void SendAddresses(C4Network2IOConnection *pConn)
void HandlePacket(char cStatus, const C4PacketBase *pBasePkt, C4Network2IOConnection *pConn)
C4Network2ClientList Clients
Definition: C4Network2.h:116
const C4NetIO::addr_t & getPeerAddr() const
Definition: C4Network2IO.h:266
bool Send(const C4NetIOPacket &rPkt)
C4Network2IOProtocol getProtocol() const
Definition: C4Network2IO.h:265
void RemoveAutoAccept(const C4ClientCore &CCore)
bool ConnectWithSocket(const C4NetIO::addr_t &addr, C4Network2IOProtocol eProt, const C4ClientCore &nCCore, std::unique_ptr< C4NetIOTCP::Socket > socket, const char *szPassword=nullptr)
void BeginBroadcast(bool fSelectAll=false)
bool Connect(const C4NetIO::addr_t &addr, C4Network2IOProtocol eProt, const C4ClientCore &nCCore, const char *szPassword=nullptr)
bool Broadcast(const C4NetIOPacket &rPkt)
C4NetIO * getNetIO(C4Network2IOProtocol eProt)
void AddAutoAccept(const C4ClientCore &CCore)
void EndBroadcast()
C4Network2Address addr
void CompileFunc(StdCompiler *pComp) override
void SetData(const StdBuf &Pkt)
Definition: C4Packet2.cpp:453
void AddClient(int32_t iClient)
Definition: C4Packet2.cpp:463
void SetListType(bool fnNegativeList)
Definition: C4Packet2.cpp:458
void CompileFunc(StdCompiler *pComp) override
C4Network2Address addr
C4Player * GetAtClient(int iClient, int iIndex=0) const
void Value(const T &rStruct)
Definition: StdCompiler.h:161
const char * getData() const
Definition: StdBuf.h:442
uint16_t GetPort() const
Definition: C4NetIO.cpp:547
void SetAddress(const sockaddr *addr)
Definition: C4NetIO.cpp:364
void SetPort(uint16_t port)
Definition: C4NetIO.cpp:531
StdStrBuf ToString(int flags=0) const
Definition: C4NetIO.cpp:604
void SetScopeId(int scopeId)
Definition: C4NetIO.cpp:289
AddressFamily GetFamily() const
Definition: C4NetIO.cpp:520
int GetScopeId() const
Definition: C4NetIO.cpp:296