OpenClonk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
C4Network2Reference.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) 2009-2016, The OpenClonk Team and contributors
6  *
7  * Distributed under the terms of the ISC license; see accompanying file
8  * "COPYING" for details.
9  *
10  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
11  * See accompanying file "TRADEMARK" for details.
12  *
13  * To redistribute this file separately, substitute the full license texts
14  * for the above references.
15  */
16 #include "C4Include.h"
18 
19 #include "game/C4Game.h"
20 #include "control/C4RoundResults.h"
21 #include "C4Version.h"
22 #include "game/C4Application.h"
23 
24 #include <utility>
25 #include <fcntl.h>
26 #include <zlib.h>
27 
28 // *** C4Network2Reference
29 
31  : Icon(0), GameMode(), Time(0), Frame(0), StartTime(0), LeaguePerformance(0),
32  JoinAllowed(true), ObservingAllowed(true), PasswordNeeded(false), OfficialServer(false),
33  IsEditor(false), iAddrCnt(0), NetpuncherGameID(C4NetpuncherID())
34 {
35 
36 }
37 
39 {
40 
41 }
42 
44 {
45  source = ip;
46  if (iAddrCnt < C4ClientMaxAddr)
47  Addrs[++iAddrCnt].SetAddr(ip);
48 }
49 
51 {
52  // Copy all game parameters
54 
55  // Discard player resources (we don't want these infos in the reference)
56  // Add league performance (but only after game end)
57  C4ClientPlayerInfos *pClientInfos; C4PlayerInfo *pPlayerInfo;
58  int32_t i, j;
59  for (i = 0; (pClientInfos = Parameters.PlayerInfos.GetIndexedInfo(i)); i++)
60  for (j = 0; (pPlayerInfo = pClientInfos->GetPlayerInfo(j)); j++)
61  {
62  pPlayerInfo->DiscardResource();
63  if(::Game.GameOver)
64  pPlayerInfo->SetLeaguePerformance(::Game.RoundResults.GetLeaguePerformance(pPlayerInfo->GetID()));
65  }
66 
67  // Special additional information in reference
68  Icon = ::Game.C4S.Head.Icon;
70  GameMode = ::Game.C4S.Game.Mode;
71  GameStatus = ::Network.Status;
72  Time = ::Game.Time;
73  Frame = ::Game.FrameCounter;
74  StartTime = ::Game.StartTime;
75  LeaguePerformance = ::Game.RoundResults.GetLeaguePerformance();
76  Comment = Config.Network.Comment;
77  JoinAllowed = ::Network.isJoinAllowed();
78  ObservingAllowed = ::Network.isObservingAllowed();
79  PasswordNeeded = ::Network.isPassworded();
80  IsEditor = !!::Application.isEditor;
81  NetpuncherGameID = ::Network.getNetpuncherGameID();
82  NetpuncherAddr = ::Network.getNetpuncherAddr();
83  Statistics = ::Game.RoundResults.GetStatistics();
84  Game.Set();
85 
86  // Addresses
87  C4Network2Client *pLocalNetClient = ::Game.Clients.getLocal()->getNetClient();
88  iAddrCnt = pLocalNetClient->getAddrCnt();
89  for (i = 0; i < iAddrCnt; i++)
90  Addrs[i] = pLocalNetClient->getAddr(i);
91 
92 }
93 
95 {
96  // Sort all addresses with zero IP to back of list
97  int iSortAddrCnt = iAddrCnt;
98  for (int i = 0; i < iSortAddrCnt; i++)
99  if (Addrs[i].isIPNull())
100  {
101  C4Network2Address Addr = Addrs[i];
102  for (int j = i + 1; j < iAddrCnt; j++)
103  Addrs[j - 1] = Addrs[j];
104  Addrs[iAddrCnt - 1] = Addr;
105  // Correct position
106  i--; iSortAddrCnt--;
107  }
108 }
109 
111 {
112  pComp->Value(mkNamingAdapt(Icon, "Icon", 0));
113  pComp->Value(mkNamingAdapt(Title, "Title", "No title"));
114  pComp->Value(mkNamingAdapt(mkParAdapt(GameMode, StdCompiler::RCT_IdtfAllowEmpty), "GameMode", ""));
115  pComp->Value(mkParAdapt(GameStatus, true));
116  pComp->Value(mkNamingAdapt(Time, "Time", 0));
117  pComp->Value(mkNamingAdapt(Frame, "Frame", 0));
118  pComp->Value(mkNamingAdapt(StartTime, "StartTime", 0));
119  pComp->Value(mkNamingAdapt(LeaguePerformance, "LeaguePerformance",0));
120  pComp->Value(mkNamingAdapt(Comment, "Comment", ""));
121  pComp->Value(mkNamingAdapt(JoinAllowed, "JoinAllowed", true));
122  pComp->Value(mkNamingAdapt(ObservingAllowed, "ObservingAllowed", true));
123  pComp->Value(mkNamingAdapt(PasswordNeeded, "PasswordNeeded", false));
124  pComp->Value(mkNamingAdapt(IsEditor, "IsEditor", false));
125  pComp->Value(mkNamingAdapt(mkIntPackAdapt(iAddrCnt), "AddressCount", 0));
126  iAddrCnt = std::min<uint8_t>(C4ClientMaxAddr, iAddrCnt);
127  pComp->Value(mkNamingAdapt(mkArrayAdapt(Addrs, iAddrCnt, C4Network2Address()), "Address"));
128  pComp->Value(mkNamingAdapt(Game.sEngineName, "Game", "None"));
129  pComp->Value(mkNamingAdapt(mkArrayAdaptDM(Game.iVer,0),"Version" ));
130  pComp->Value(mkNamingAdapt(OfficialServer, "OfficialServer", false));
131  pComp->Value(mkNamingAdapt(NetpuncherGameID, "NetpuncherID", C4NetpuncherID(), false, false));
132  pComp->Value(mkNamingAdapt(NetpuncherAddr, "NetpuncherAddr", "", false, false));
133  pComp->Value(mkNamingAdapt(mkParAdapt(Statistics, StdCompiler::RCT_All), "Statistics", "", false, false));
134 
135  pComp->Value(Parameters);
136 }
137 
138 int32_t C4Network2Reference::getSortOrder() const // Don't go over 100, because that's for the masterserver...
139 {
140  C4GameVersion verThis;
141  int iOrder = 0;
142  // Official server
143  if (isOfficialServer() && !Config.Network.UseAlternateServer) iOrder += 50;
144  // Joinable
145  if (isJoinAllowed() && (getGameVersion() == verThis)) iOrder += 25;
146  // League game
147  if (Parameters.isLeague()) iOrder += 5;
148  // In lobby
149  if (getGameStatus().isLobbyActive()) iOrder += 3;
150  // No password needed
151  if (!isPasswordNeeded()) iOrder += 1;
152  // Done
153  return iOrder;
154 }
155 
157 {
158  if (GameMode.getLength() > 0)
159  {
160  // Prefer to derive string from game mode
161  return FormatString("%s: %s", LoadResStr("IDS_MENU_CPGOALS"), GameMode.getData());
162  }
163  else
164  {
165  // If not defined, fall back to goal string
166  return Parameters.GetGameGoalString();
167  }
168 }
169 
170 
171 // *** C4Network2RefServer
172 
174  : pReference(nullptr)
175 {
176 }
177 
179 {
180  Clear();
181 }
182 
184 {
186  delete pReference; pReference = nullptr;
187 }
188 
190 {
191  CStdLock RefLock(&RefCSec);
192  delete pReference; pReference = pNewReference;
193 }
194 
196 {
197  // Just append the packet
198  rOutBuf.Append(rPacket);
199 }
200 
201 size_t C4Network2RefServer::UnpackPacket(const StdBuf &rInBuf, const C4NetIO::addr_t &addr)
202 {
203  const char *pData = getBufPtr<char>(rInBuf);
204  // Check for complete header
205  const char *pHeaderEnd = strstr(pData, "\r\n\r\n");
206  if (!pHeaderEnd)
207  return 0;
208  // Check method (only GET is allowed for now)
209  if (!SEqual2(pData, "GET "))
210  {
211  RespondNotImplemented(addr, "Method not implemented");
212  return rInBuf.getSize();
213  }
214  // Check target
215  // TODO
216  RespondReference(addr);
217  return rInBuf.getSize();
218 }
219 
220 void C4Network2RefServer::RespondNotImplemented(const C4NetIO::addr_t &addr, const char *szMessage)
221 {
222  // Send the message
223  StdStrBuf Data = FormatString("HTTP/1.0 501 %s\r\n\r\n", szMessage);
224  Send(C4NetIOPacket(Data.getData(), Data.getLength(), false, addr));
225  // Close the connection
226  Close(addr);
227 }
228 
229 void C4Network2RefServer::RespondReference(const C4NetIO::addr_t &addr)
230 {
231  CStdLock RefLock(&RefCSec);
232  // Pack
233  StdStrBuf PacketData = DecompileToBuf<StdCompilerINIWrite>(mkNamingPtrAdapt(pReference, "Reference"));
234  // Create header
235  StdStrBuf Header = FormatString(
236  "HTTP/1.1 200 Found\r\n"
237  "Content-Length: %lu\r\n"
238  "Content-Type: text/plain; charset=UTF-8\r\n"
239  "Server: " C4ENGINENAME "/" C4VERSION "\r\n"
240  "\r\n",
241  static_cast<unsigned long>(PacketData.getLength()));
242  // Send back
243  Send(C4NetIOPacket(Header, Header.getLength(), false, addr));
244  Send(C4NetIOPacket(PacketData, PacketData.getLength(), false, addr));
245  // Close the connection
246  Close(addr);
247 }
248 
249 // *** C4Network2HTTPClient
250 
252  : fBinary(false), fBusy(false), fSuccess(false), fConnected(false), iDataOffset(0), iDownloadedSize(0), iTotalSize(0),
253  pNotify(nullptr)
254 {
256 }
257 
259 {
260 }
261 
263 {
264  // Just append the packet
265  rOutBuf.Append(rPacket);
266 }
267 
269 {
270  // since new data arrived, increase timeout time
272  // Check for complete header
273  if (!iDataOffset)
274  {
275  // Copy data into string buffer (terminate)
276  StdStrBuf Data; Data.Copy(getBufPtr<char>(rInBuf), rInBuf.getSize());
277  const char *pData = Data.getData();
278  // Header complete?
279  const char *pContent = SSearch(pData, "\r\n\r\n");
280  if (!pContent)
281  return 0;
282  // Read the header
283  if (!ReadHeader(Data))
284  {
285  fBusy = fSuccess = false;
286  Close(addr);
287  return rInBuf.getSize();
288  }
289  }
290  iDownloadedSize = rInBuf.getSize() - iDataOffset;
291  // Check if the packet is complete
292  if (iTotalSize > iDownloadedSize)
293  {
294  return 0;
295  }
296  // Get data, uncompress it if needed
297  StdBuf Data = rInBuf.getPart(iDataOffset, iTotalSize);
298  if (fCompressed)
299  if (!Decompress(&Data))
300  {
301  fBusy = fSuccess = false;
302  Close(addr);
303  return rInBuf.getSize();
304  }
305  // Save the result
306  if (fBinary)
307  ResultBin.Copy(Data);
308  else
309  ResultString.Copy(getBufPtr<char>(Data), Data.getSize());
310  fBusy = false; fSuccess = true;
311  // Callback
312  OnPacket(C4NetIOPacket(Data, addr), this);
313  // Done
314  Close(addr);
315  return rInBuf.getSize();
316 }
317 
318 bool C4Network2HTTPClient::ReadHeader(StdStrBuf Data)
319 {
320  const char *pData = Data.getData();
321  const char *pContent = SSearch(pData, "\r\n\r\n");
322  if (!pContent)
323  return 0;
324  // Parse header line
325  int iHTTPVer1, iHTTPVer2, iResponseCode, iStatusStringPtr;
326  if (sscanf(pData, "HTTP/%d.%d %d %n", &iHTTPVer1, &iHTTPVer2, &iResponseCode, &iStatusStringPtr) != 3)
327  {
328  Error = "Invalid status line!";
329  return false;
330  }
331  // Check HTTP version
332  if (iHTTPVer1 != 1)
333  {
334  Error.Format("Unsupported HTTP version: %d.%d!", iHTTPVer1, iHTTPVer2);
335  return false;
336  }
337  // Check code
338  if (iResponseCode != 200)
339  {
340  // Get status string
341  StdStrBuf StatusString; StatusString.CopyUntil(pData + iStatusStringPtr, '\r');
342  // Create error message
343  Error.Format("HTTP server responded %d: %s", iResponseCode, StatusString.getData());
344  return false;
345  }
346  // Get content length
347  const char *pContentLength = SSearch(pData, "\r\nContent-Length:");
348  int iContentLength;
349  if (!pContentLength || pContentLength > pContent ||
350  sscanf(pContentLength, "%d", &iContentLength) != 1)
351  {
352  Error.Format("Invalid server response: Content-Length is missing!");
353  return false;
354  }
355  iTotalSize = iContentLength;
356  iDataOffset = (pContent - pData);
357  // Get content encoding
358  const char *pContentEncoding = SSearch(pData, "\r\nContent-Encoding:");
359  if (pContentEncoding)
360  {
361  while (*pContentEncoding == ' ') pContentEncoding++;
362  StdStrBuf Encoding; Encoding.CopyUntil(pContentEncoding, '\r');
363  if (Encoding == "gzip")
364  fCompressed = true;
365  else
366  fCompressed = false;
367  }
368  else
369  fCompressed = false;
370  // Okay
371  return true;
372 }
373 
374 bool C4Network2HTTPClient::Decompress(StdBuf *pData)
375 {
376  size_t iSize = pData->getSize();
377  // Create buffer
378  uint32_t iOutSize = *getBufPtr<uint32_t>(*pData, pData->getSize() - sizeof(uint32_t));
379  iOutSize = std::min<uint32_t>(iOutSize, iSize * 1000);
380  StdBuf Out; Out.New(iOutSize);
381  // Prepare stream
382  z_stream zstrm;
383  ZeroMem(&zstrm, sizeof(zstrm));
384  zstrm.next_in = const_cast<Byte *>(getBufPtr<Byte>(*pData));
385  zstrm.avail_in = pData->getSize();
386  zstrm.next_out = getMBufPtr<Byte>(Out);
387  zstrm.avail_out = Out.getSize();
388  // Inflate...
389  if (inflateInit2(&zstrm, 15 + 16) != Z_OK)
390  {
391  Error.Format("Could not decompress data!");
392  return false;
393  }
394  // Inflate!
395  if (inflate(&zstrm, Z_FINISH) != Z_STREAM_END)
396  {
397  inflateEnd(&zstrm);
398  Error.Format("Could not decompress data!");
399  return false;
400  }
401  // Return the buffer
402  Out.SetSize(zstrm.total_out);
403  pData->Take(std::move(Out));
404  // Okay
405  inflateEnd(&zstrm);
406  return true;
407 }
408 
409 bool C4Network2HTTPClient::OnConn(const C4NetIO::addr_t &AddrPeer, const C4NetIO::addr_t &AddrConnect, const C4NetIO::addr_t *pOwnAddr, C4NetIO *pNetIO)
410 {
411  // Make sure we're actually waiting for this connection
412  if (fConnected || (AddrConnect != ServerAddr && AddrConnect != ServerAddrFallback))
413  return false;
414  // Save pack peer address
415  PeerAddr = AddrPeer;
416  // Send the request
417  if (!Send(C4NetIOPacket(Request, AddrPeer)))
418  {
419  Error.Format("Unable to send HTTP request: %s", Error.getData());
420  }
421  Request.Clear();
422  fConnected = true;
423  return true;
424 }
425 
426 void C4Network2HTTPClient::OnDisconn(const C4NetIO::addr_t &AddrPeer, C4NetIO *pNetIO, const char *szReason)
427 {
428  // Got no complete packet? Failure...
429  if (!fSuccess && Error.isNull())
430  {
431  fBusy = false;
432  Error.Format("Unexpected disconnect: %s", szReason);
433  }
434  fConnected = false;
435  // Notify
436  if (pNotify)
437  pNotify->PushEvent(Ev_HTTP_Response, this);
438 }
439 
440 void C4Network2HTTPClient::OnPacket(const class C4NetIOPacket &rPacket, C4NetIO *pNetIO)
441 {
442  // Everything worthwhile was already done in UnpackPacket. Only do notify callback
443  if (pNotify)
444  pNotify->PushEvent(Ev_HTTP_Response, this);
445 }
446 
448 {
449  // Check timeout
450  if (fBusy)
451  {
452  if (C4TimeMilliseconds::Now() > HappyEyeballsTimeout)
453  {
454  HappyEyeballsTimeout = C4TimeMilliseconds::PositiveInfinity;
455  Application.InteractiveThread.ThreadLogS("HTTP: Starting fallback connection to %s (%s)", Server.getData(), ServerAddrFallback.ToString().getData());
456  Connect(ServerAddrFallback);
457  }
458  if (time(nullptr) > iRequestTimeout)
459  {
460  Cancel("Request timeout");
461  return true;
462  }
463  }
464  // Execute normally
465  return C4NetIOTCP::Execute(iMaxTime);
466 }
467 
469 {
470  C4TimeMilliseconds tNetIOTCPTick = C4NetIOTCP::GetNextTick(tNow);
471  if (!fBusy)
472  return tNetIOTCPTick;
473 
474  C4TimeMilliseconds tHTTPClientTick = tNow + 1000 * std::max<time_t>(iRequestTimeout - time(nullptr), 0);
475 
476  C4TimeMilliseconds HappyEyeballsTick = tNow + std::max(HappyEyeballsTimeout - C4TimeMilliseconds::Now(), 0);
477 
478  return std::min({tNetIOTCPTick, tHTTPClientTick, HappyEyeballsTick});
479 }
480 
481 bool C4Network2HTTPClient::Query(const StdBuf &Data, bool fBinary)
482 {
483  if (Server.isNull()) return false;
484  // Cancel previous request
485  if (fBusy)
486  Cancel("Cancelled");
487  // No result known yet
489  // store mode
490  this->fBinary = fBinary;
491  // Create request
492  StdStrBuf Header;
493  if (Data.getSize())
494  Header.Format(
495  "POST %s HTTP/1.0\r\n"
496  "Host: %s\r\n"
497  "Connection: Close\r\n"
498  "Content-Length: %lu\r\n"
499  "Content-Type: text/plain; charset=utf-8\r\n"
500  "Accept-Charset: utf-8\r\n"
501  "Accept-Encoding: gzip\r\n"
502  "Accept-Language: %s\r\n"
503  "User-Agent: " C4ENGINENAME "/" C4VERSION "\r\n"
504  "\r\n",
505  RequestPath.getData(),
506  Server.getData(),
507  static_cast<unsigned long>(Data.getSize()),
509  else
510  Header.Format(
511  "GET %s HTTP/1.0\r\n"
512  "Host: %s\r\n"
513  "Connection: Close\r\n"
514  "Accept-Charset: utf-8\r\n"
515  "Accept-Encoding: gzip\r\n"
516  "Accept-Language: %s\r\n"
517  "User-Agent: " C4ENGINENAME "/" C4VERSION "\r\n"
518  "\r\n",
519  RequestPath.getData(),
520  Server.getData(),
522  // Compose query
523  Request.Take(Header.GrabPointer(), Header.getLength());
524  Request.Append(Data);
525  // Start connecting
526  if (!Connect(ServerAddr))
527  return false;
528  // Also try the fallback address after some time (if there is one)
529  if (!ServerAddrFallback.IsNull())
531  else
532  HappyEyeballsTimeout = C4TimeMilliseconds::PositiveInfinity;
533  // Okay, request will be performed when connection is complete
534  fBusy = true;
535  iDataOffset = 0;
537  ResetError();
538  return true;
539 }
540 
542 {
543  // timeout C4Network2HTTPQueryTimeout seconds from this point
544  iRequestTimeout = time(nullptr) + C4Network2HTTPQueryTimeout;
545 }
546 
547 void C4Network2HTTPClient::Cancel(const char *szReason)
548 {
549  // Close connection - and connection attempt
550  Close(ServerAddr); Close(ServerAddrFallback); Close(PeerAddr);
551  // Reset flags
552  fBusy = fSuccess = fConnected = fBinary = false;
553  iDownloadedSize = iTotalSize = iDataOffset = 0;
554  Error = szReason;
555 }
556 
558 {
559  fBusy = fSuccess = fConnected = fBinary = false;
560  iDownloadedSize = iTotalSize = iDataOffset = 0;
561  ResultBin.Clear();
563  Error.Clear();
564 }
565 
566 bool C4Network2HTTPClient::SetServer(const char *szServerAddress)
567 {
568  // Split address
569  const char *pRequestPath;
570  if ((pRequestPath = strchr(szServerAddress, '/')))
571  {
572  Server.CopyUntil(szServerAddress, '/');
573  RequestPath = pRequestPath;
574  }
575  else
576  {
577  Server = szServerAddress;
578  RequestPath = "/";
579  }
580  // Resolve address
581  ServerAddr.SetAddress(Server);
582  if (ServerAddr.IsNull())
583  {
584  SetError(FormatString("Could not resolve server address %s!", Server.getData()).getData());
585  return false;
586  }
587  ServerAddr.SetDefaultPort(GetDefaultPort());
588  if (ServerAddr.GetFamily() == C4NetIO::HostAddress::IPv6)
589  {
590  // Try to find a fallback IPv4 address for Happy Eyeballs.
591  ServerAddrFallback.SetAddress(Server, C4NetIO::HostAddress::IPv4);
592  ServerAddrFallback.SetDefaultPort(GetDefaultPort());
593  }
594  else
595  ServerAddrFallback.Clear();
596  // Remove port
597  const char *firstColon = strchr(Server.getData(), ':');
598  const char *lastColon = strrchr(Server.getData(), ':');
599  if (firstColon)
600  // hostname/IPv4 address or IPv6 address with port (e.g. [::1]:1234)
601  if (firstColon == lastColon || (Server[0] == '[' && *(lastColon - 1) == ']'))
602  Server.SetLength(lastColon - Server.getData());
603 
604  // Done
605  ResetError();
606  return true;
607 }
608 
609 // *** C4Network2UpdateClient
610 
612 {
613  // Perform an Query query
614  return Query(nullptr, false);
615 }
616 
618 {
619  // Sanity check
620  if (isBusy() || !isSuccess()) return false;
621  // Parse response
622  try
623  {
624  CompileFromBuf<StdCompilerINIRead>(mkNamingAdapt(
625  mkNamingAdapt(mkParAdapt(*pUpdateURL, StdCompiler::RCT_All), "UpdateURL", ""),
626  C4ENGINENAME), ResultString);
627  }
628  catch (StdCompiler::Exception *pExc)
629  {
630  SetError(pExc->Msg.getData());
631  return false;
632  }
633  // done; version OK!
634  return true;
635 }
636 
638 {
639  // Sanity check
640  if (isBusy() || !isSuccess()) return false;
641  // Parse response
642  try
643  {
644  CompileFromBuf<StdCompilerINIRead>(mkNamingAdapt(
645  mkNamingAdapt(mkParAdapt(*pVersion, StdCompiler::RCT_All), "Version", ""),
646  C4ENGINENAME), ResultString);
647  }
648  catch (StdCompiler::Exception *pExc)
649  {
650  SetError(pExc->Msg.getData());
651  return false;
652  }
653  // done; version OK!
654  return true;
655 }
656 
657 // *** C4Network2RefClient
658 
660 {
661  // Perform an Query query
662  return Query(nullptr, false);
663 }
664 
665 bool C4Network2RefClient::GetReferences(C4Network2Reference **&rpReferences, int32_t &rRefCount)
666 {
667  // Sanity check
668  if (isBusy() || !isSuccess()) return false;
669  // local update test
670  try
671  {
672  // Create compiler
673  StdCompilerINIRead Comp;
674  Comp.setInput(ResultString);
675  Comp.Begin();
676  // Read reference count
677  Comp.Value(mkNamingCountAdapt(rRefCount, "Reference"));
678  // Create reference array and initialize
679  rpReferences = new C4Network2Reference *[rRefCount];
680  for (int i = 0; i < rRefCount; i++)
681  rpReferences[i] = nullptr;
682  // Get references
683  Comp.Value(mkNamingAdapt(mkArrayAdaptMap(rpReferences, rRefCount, mkPtrAdaptNoNull<C4Network2Reference>), "Reference"));
684  mkPtrAdaptNoNull<C4Network2Reference>(*rpReferences);
685  // Done
686  Comp.End();
687  }
688  catch (StdCompiler::Exception *pExc)
689  {
690  SetError(pExc->Msg.getData());
691  return false;
692  }
693  // Set source ip
694  for (int i = 0; i < rRefCount; i++)
695  rpReferences[i]->SetSourceAddress(getServerAddress());
696  // Done
697  ResetError();
698  return true;
699 }
700 
const C4Network2Address & getAddr(int32_t i) const
const char * getData() const
Definition: StdBuf.h:450
StdCopyStrBuf Mode
Definition: C4Scenario.h:121
virtual bool Execute(int iMaxTime=TO_INF, pollfd *readyfds=0)
Definition: C4NetIO.cpp:932
C4Client * getLocal() const
Definition: C4Client.h:161
void ResetError()
Definition: C4NetIO.h:286
int32_t Icon
Definition: C4Scenario.h:68
C4Config Config
Definition: C4Config.cpp:831
char * GrabPointer()
Definition: StdBuf.h:467
Definition: StdBuf.h:37
virtual bool Execute(int iMaxTime, pollfd *readyfds)
void Take(void *pnData, size_t inSize)
Definition: StdBuf.h:132
StdNamingCountAdapt< int_t > mkNamingCountAdapt(int_t &iCount, const char *szName)
Definition: StdAdaptors.h:974
C4Game Game
Definition: C4Globals.cpp:52
C4Scenario C4S
Definition: C4Game.h:76
void Clear()
Definition: StdBuf.h:474
C4ConfigGeneral General
Definition: C4Config.h:252
void SetError(const char *strnError, bool fSockErr=false)
Definition: C4NetIO.cpp:754
virtual C4TimeMilliseconds GetNextTick(C4TimeMilliseconds tNow)
C4NetpuncherID::value & getNetpuncherGameID(C4NetIO::HostAddress::AddressFamily family)
bool ThreadLogS(const char *szMessage,...) GNUC_FORMAT_ATTRIBUTE_O
StdCopyStrBuf ScenarioTitle
Definition: C4Game.h:105
const char * SSearch(const char *szString, const char *szIndex)
Definition: Standard.cpp:333
void Clear()
Definition: StdBuf.h:198
virtual int32_t GetDefaultPort()
virtual bool Connect(const addr_t &addr)
Definition: C4NetIO.cpp:1167
const int C4Network2HTTPQueryTimeout
ValidatedStdCopyStrBuf< C4InVal::VAL_Comment > Comment
Definition: C4Config.h:147
StdStrBuf ToString(int flags=0) const
Definition: C4NetIO.cpp:605
C4Network2Status getGameStatus() const
void OnDisconn(const C4NetIO::addr_t &AddrPeer, C4NetIO *pNetIO, const char *szReason)
void setInput(const InT &In)
Definition: StdCompiler.h:638
StdStrBuf getNetpuncherAddr() const
Definition: C4Network2.h:309
StdCopyStrBuf Error
Definition: C4NetIO.h:282
void Format(const char *szFmt,...) GNUC_FORMAT_ATTRIBUTE_O
Definition: StdBuf.cpp:181
bool PushEvent(C4InteractiveEventType eEventType, void *pData=nullptr)
bool isJoinAllowed() const
Definition: C4Network2.h:213
C4Network2Client * getNetClient() const
Definition: C4Client.h:117
void SetAddress(const sockaddr *addr)
Definition: C4NetIO.cpp:370
bool isObservingAllowed() const
Definition: C4Network2.h:214
void DiscardResource()
C4GameParameters & Parameters
Definition: C4Game.h:69
bool GetVersion(StdStrBuf *pVersion)
C4ClientPlayerInfos * GetIndexedInfo(int32_t iIndex) const
Definition: C4PlayerInfo.h:361
size_t getSize() const
Definition: StdBuf.h:109
StdBuf getPart(size_t iStart, size_t inSize) const
Definition: StdBuf.h:115
StdCopyStrBuf GetStatistics() const
const char * LoadResStr(const char *id)
Definition: C4Language.h:83
void Cancel(const char *szReason)
StdNamingAdapt< T > mkNamingAdapt(T &&rValue, const char *szName)
Definition: StdAdaptors.h:93
bool GetUpdateURL(StdStrBuf *pUpdateURL)
void CompileFunc(StdCompiler *pComp)
int32_t FrameCounter
Definition: C4Game.h:130
C4PlayerInfo * GetPlayerInfo(int32_t iIndex) const
C4Network2 Network
Definition: C4Globals.cpp:53
int32_t StartTime
Definition: C4Game.h:134
bool isPasswordNeeded() const
void OnPacket(const class C4NetIOPacket &rPacket, C4NetIO *pNetIO)
bool GameOver
Definition: C4Game.h:116
StdStrBuf GetGameGoalString() const
virtual size_t UnpackPacket(const StdBuf &rInBuf, const C4NetIO::addr_t &addr)
bool GetReferences(C4Network2Reference **&rpReferences, int32_t &rRefCount)
void Copy(size_t inSize)
Definition: StdBuf.h:233
StdArrayAdapt< T > mkArrayAdapt(T *pArray, int iSize)
Definition: StdAdaptors.h:308
virtual void SetCallback(CBClass *pnCallback)
Definition: C4NetIO.h:487
virtual bool Close()
Definition: C4NetIO.cpp:870
int32_t Time
Definition: C4Game.h:133
C4ConfigNetwork Network
Definition: C4Config.h:256
const int32_t C4ClientMaxAddr
int32_t getSortOrder() const
C4Network2Status Status
Definition: C4Network2.h:122
virtual C4TimeMilliseconds GetNextTick(C4TimeMilliseconds tNow)
AddressFamily GetFamily() const
Definition: C4NetIO.cpp:526
void Value(const T &rStruct)
Definition: StdCompiler.h:171
char LanguageEx[CFG_MaxString+1]
Definition: C4Config.h:38
bool OnConn(const C4NetIO::addr_t &AddrPeer, const C4NetIO::addr_t &AddrConnect, const addr_t *pOwnAddr, C4NetIO *pNetIO)
C4RoundResults & RoundResults
Definition: C4Game.h:75
void New(size_t inSize)
Definition: StdBuf.h:154
void CopyUntil(const char *szString, char cUntil)
Definition: StdBuf.h:621
#define mkArrayAdaptDM(A, D)
Definition: StdAdaptors.h:361
bool isJoinAllowed() const
const C4NetIO::addr_t & getServerAddress() const
virtual bool Send(const C4NetIOPacket &rPacket)
Definition: C4NetIO.cpp:1266
void SetAddr(C4NetIO::addr_t naddr)
virtual size_t UnpackPacket(const StdBuf &rInBuf, const C4NetIO::addr_t &addr)
StdIntPackAdapt< T > mkIntPackAdapt(T &rVal)
Definition: StdAdaptors.h:757
void Append(const void *pnData, size_t inSize)
Definition: StdBuf.h:262
void SetSourceAddress(const C4NetIO::EndpointAddress &ip)
virtual void PackPacket(const C4NetIOPacket &rPacket, StdBuf &rOutBuf)
virtual void Begin() override
virtual void PackPacket(const C4NetIOPacket &rPacket, StdBuf &rOutBuf)
const uint32_t C4Network2HTTPHappyEyeballsTimeout
bool isLobbyActive() const
Definition: C4Network2.h:87
void SetLeaguePerformance(int32_t iNewPerf)
Definition: C4PlayerInfo.h:140
bool isNull() const
Definition: StdBuf.h:449
C4PlayerInfoList PlayerInfos
bool isOfficialServer() const
virtual void End() override
C4SGame Game
Definition: C4Scenario.h:232
bool SEqual2(const char *szStr1, const char *szStr2)
Definition: Standard.cpp:168
C4ClientList & Clients
Definition: C4Game.h:71
bool isPassworded() const
Definition: C4Network2.h:218
bool isLeague() const
StdParameterAdapt< T, P > mkParAdapt(T &&rObj, P &&rPar)
Definition: StdAdaptors.h:456
bool IsNull() const
Definition: C4NetIO.cpp:509
size_t getLength() const
Definition: StdBuf.h:453
int32_t GetID() const
Definition: C4PlayerInfo.h:197
void SetLength(size_t iLength)
Definition: StdBuf.h:517
std::enable_if< std::is_pod< T >::value >::type ZeroMem(T *lpMem, size_t dwSize)
Definition: Standard.h:63
C4SHead Head
Definition: C4Scenario.h:230
StdPtrAdapt< T > mkNamingPtrAdapt(T *&rpObj, const char *szNaming)
Definition: StdAdaptors.h:602
bool Query(const StdBuf &Data, bool fBinary)
int32_t UseAlternateServer
Definition: C4Config.h:153
void SetDefaultPort(uint16_t port)
Definition: C4NetIO.cpp:542
const C4GameVersion & getGameVersion() const
StdArrayAdapt< T, M > mkArrayAdaptMap(T *pArray, int iSize, M &&map)
Definition: StdAdaptors.h:311
void Copy()
Definition: StdBuf.h:475
int32_t getAddrCnt() const
void CopyValidated(const char *szFromVal)
bool SetServer(const char *szServerAddress)
int32_t GetLeaguePerformance(int32_t idPlayer=0) const
C4Application Application
Definition: C4Globals.cpp:44
C4InteractiveThread InteractiveThread
Definition: C4Application.h:45
static C4TimeMilliseconds Now()
C4GameParameters Parameters
int iSize
Definition: TstC4NetIO.cpp:35
void SetReference(C4Network2Reference *pReference)
StdStrBuf FormatString(const char *szFmt,...)
Definition: StdBuf.cpp:277
StdStrBuf getGameGoalString() const