refactor: consistently use time_t t... variables for times in network system, scheduler, gui

The network used to cast GetTime() to int, but GetTime() is an unsigned long. This might cause problems if GetTime() returns big integers (see #251). To solve this, the StdSchedulerProc interface had to be extended with another function in order to eliminate the magic return value -1 of GetNextTick for "no scheduled execution".
stable-5.4
Tobias Zwick 2013-11-29 17:28:04 +07:00
parent ecf538cd1f
commit 7b9c1d5a9e
17 changed files with 3804 additions and 3786 deletions

View File

@ -1233,7 +1233,7 @@ namespace C4GUI
int32_t iCursorPos; // cursor position: char, before which the cursor is located
int32_t iSelectionStart, iSelectionEnd; // selection range (start may be larger than end)
int32_t iMaxTextLength; // maximum number of characters to be input here
DWORD dwLastInputTime; // time of last input (for cursor flashing)
time_t tLastInputTime; // time of last input (for cursor flashing)
int32_t iXScroll; // horizontal scrolling
char cPasswordMask; // character to be used for masking the contents. 0 for none.

View File

@ -150,7 +150,7 @@ namespace C4GUI
// reset selection
iSelectionStart = iSelectionEnd = 0;
// cursor might have moved: ensure it is shown
dwLastInputTime=GetTime();
tLastInputTime=GetTime();
}
void Edit::DeleteSelection()
@ -162,7 +162,7 @@ namespace C4GUI
// adjust cursor pos
if (iCursorPos > iSelBegin) iCursorPos = Max(iSelBegin, iCursorPos - iSelEnd + iSelBegin);
// cursor might have moved: ensure it is shown
dwLastInputTime=GetTime();
tLastInputTime=GetTime();
// nothing selected
iSelectionStart = iSelectionEnd = iSelBegin;
}
@ -189,7 +189,7 @@ namespace C4GUI
// advance cursor
iCursorPos += iTextLen;
// cursor moved: ensure it is shown
dwLastInputTime=GetTime();
tLastInputTime=GetTime();
ScrollCursorInView();
}
// done; return whether everything was inserted
@ -452,7 +452,7 @@ namespace C4GUI
iCursorPos += iMoveLength;
}
// show cursor
dwLastInputTime=GetTime();
tLastInputTime=GetTime();
ScrollCursorInView();
// operation recognized
return true;
@ -556,7 +556,7 @@ namespace C4GUI
// select all
iSelectionStart=0; iSelectionEnd=iCursorPos=SLen(Text);
// begin with a flashing cursor
dwLastInputTime=GetTime();
tLastInputTime=GetTime();
}
void Edit::OnLooseFocus()
@ -629,7 +629,7 @@ namespace C4GUI
// draw edit text
pDraw->TextOut(pDrawText, *pFont, 1.0f, cgo.Surface, rcClientRect.x + cgo.TargetX - iXScroll, iY0 + cgo.TargetY - 1, dwFontClr, ALeft, false);
// draw cursor
if (HasDrawFocus() && !(((dwLastInputTime-GetTime())/500)%2))
if (HasDrawFocus() && !(((tLastInputTime-GetTime())/500)%2))
{
char cAtCursor = pDrawText[iCursorPos]; pDrawText[iCursorPos]=0; int32_t w,h,wc;
pFont->GetTextExtent(pDrawText, w, h, false);

View File

@ -33,10 +33,10 @@
C4GameControlNetwork::C4GameControlNetwork(C4GameControl *pnParent)
: fEnabled(false), fRunning(false), iClientID(C4ClientIDUnknown),
fActivated(false), iTargetTick(-1),
iControlPreSend(1), iWaitStart(-1), iAvgControlSendTime(0), iTargetFPS(38),
iControlPreSend(1), tWaitStart(0), iAvgControlSendTime(0), iTargetFPS(38),
iControlSent(0), iControlReady(0),
pCtrlStack(NULL),
iNextControlReqeust(0),
tNextControlRequest(0),
pParent(pnParent)
{
assert(pParent);
@ -62,7 +62,8 @@ bool C4GameControlNetwork::Init(int32_t inClientID, bool fnHost, int32_t iStartT
pNetwork->Clients.BroadcastMsgToConnClients(MkC4NetIOPacket(PID_ControlReq, C4PacketControlReq(iControlReady + 1)));
// ok
fEnabled = true; fRunning = false;
iTargetFPS = 38; iNextControlReqeust = GetTime() + C4ControlRequestInterval;
iTargetFPS = 38;
tNextControlRequest = GetTime() + C4ControlRequestInterval;
return true;
}
@ -88,8 +89,8 @@ void C4GameControlNetwork::Execute() // by main thread
return;
// Save time the control tick was reached
if (iWaitStart == -1)
iWaitStart = GetTime();
if (!tWaitStart)
tWaitStart = GetTime();
// Execute any queued sync control
ExecQueuedSyncCtrl();
@ -116,7 +117,7 @@ bool C4GameControlNetwork::GetControl(C4Control *pCtrl, int32_t iTick) // by mai
pCtrl->Append(pPkt->getControl());
// calc performance
CalcPerformance(iTick);
iWaitStart = -1;
tWaitStart = 0;
// ok
return true;
}
@ -421,7 +422,7 @@ void C4GameControlNetwork::CalcPerformance(int32_t iCtrlTick)
C4GameControlPacket *pCtrl = getCtrl(pClient->getClientID(), iCtrlTick);
if (!pCtrl) continue;
// calc stats
pClient->AddPerf(pCtrl->getTime() - iWaitStart);
pClient->AddPerf(pCtrl->getTime() - tWaitStart);
}
// Now do PreSend-calcs based on ping times
int32_t iControlSendTime;
@ -735,7 +736,7 @@ void C4GameControlNetwork::CheckCompleteCtrl(bool fSetEvent) // by both
// target ctrl tick to reach?
if (iControlReady < iTargetTick &&
(!fActivated || iControlSent > iControlReady) &&
GetTime() >= iNextControlReqeust)
GetTime() >= tNextControlRequest)
{
Application.InteractiveThread.ThreadLogS("Network: Recovering: Requesting control for tick %d...", iControlReady + 1);
// make request
@ -746,7 +747,7 @@ void C4GameControlNetwork::CheckCompleteCtrl(bool fSetEvent) // by both
else
::Network.Clients.BroadcastMsgToConnClients(Pkt);
// set time for next request
iNextControlReqeust = GetTime() + C4ControlRequestInterval;
tNextControlRequest = GetTime() + C4ControlRequestInterval;
}
}
@ -764,7 +765,7 @@ C4GameControlPacket *C4GameControlNetwork::PackCompleteCtrl(int32_t iTick)
{
// async mode: wait n extra frames for slow clients
const int iMaxWait = (Config.Network.AsyncMaxWait * 1000) / iTargetFPS;
if (eMode != CNM_Async || iWaitStart == -1 || GetTime() <= uint32_t(iWaitStart + iMaxWait))
if (eMode != CNM_Async || !tWaitStart || GetTime() <= tWaitStart + iMaxWait)
return NULL;
}
@ -795,7 +796,7 @@ C4GameControlPacket *C4GameControlNetwork::PackCompleteCtrl(int32_t iTick)
::Network.Clients.BroadcastMsgToConnClients(MkC4NetIOPacket(PID_Control, *pComplete));
// advance control request time
iNextControlReqeust = Max<uint32_t>(iNextControlReqeust, GetTime() + C4ControlRequestInterval);
tNextControlRequest = Max(tNextControlRequest, GetTime() + C4ControlRequestInterval);
// return
return pComplete;
@ -851,7 +852,7 @@ void C4GameControlNetwork::ExecQueuedSyncCtrl() // by main thread
C4GameControlPacket::C4GameControlPacket()
: iClientID(C4ClientIDUnknown),
iCtrlTick(-1),
iTime(GetTime()),
tTime(GetTime()),
pNext(NULL)
{
@ -860,7 +861,7 @@ C4GameControlPacket::C4GameControlPacket()
C4GameControlPacket::C4GameControlPacket(const C4GameControlPacket &Pkt2)
: C4PacketBase(Pkt2), iClientID(Pkt2.getClientID()),
iCtrlTick(Pkt2.getCtrlTick()),
iTime(GetTime()),
tTime(GetTime()),
pNext(NULL)
{
Ctrl.Copy(Pkt2.getControl());

View File

@ -64,7 +64,8 @@ protected:
volatile int32_t iControlPreSend;
// statistics
int32_t iWaitStart;
time_t tWaitStart;
int32_t iAvgControlSendTime;
int32_t iTargetFPS; // used for PreSend-colculation
@ -84,7 +85,7 @@ protected:
C4GameControlPacket *pSyncCtrlQueue;
// control request timing
uint32_t iNextControlReqeust;
time_t tNextControlRequest;
// links
C4GameControl *const pParent;
@ -181,7 +182,7 @@ public:
protected:
// header
int32_t iClientID, iCtrlTick;
int32_t iTime;
time_t tTime;
// data
C4Control Ctrl;
@ -192,7 +193,7 @@ protected:
public:
int32_t getClientID() const { return iClientID; }
int32_t getCtrlTick() const { return iCtrlTick; }
int32_t getTime() const { return iTime; }
time_t getTime() const { return tTime; }
const C4Control &getControl() const { return Ctrl; }
void Set(int32_t iClientID, int32_t iCtrlTick);

View File

@ -806,12 +806,6 @@ void C4NetIOTCP::GetFDs(std::vector<struct pollfd> & fds)
}
#endif
int C4NetIOTCP::GetNextTick(int Now) // (mt-safe)
{
return TO_INF;
}
bool C4NetIOTCP::GetStatistic(int *pBroadcastRate) // (mt-safe)
{
// no broadcast
@ -1700,11 +1694,6 @@ enum C4NetIOSimpleUDP::WaitResult C4NetIOSimpleUDP::WaitForSocket(int iTimeout)
#endif // STDSCHEDULER_USE_EVENTS
int C4NetIOSimpleUDP::GetNextTick(int Now)
{
return C4NetIO::TO_INF;
}
bool C4NetIOSimpleUDP::SetMCLoopback(int fLoopback)
{
// enable/disable MC loopback
@ -1806,7 +1795,7 @@ C4NetIOUDP::C4NetIOUDP()
pPeerList(NULL),
fSavePacket(false),
fDelayedLoopbackTest(false),
iNextCheck(0),
tNextCheck(0),
OPackets(iMaxOPacketBacklog),
iOPacketCounter(0),
iBroadcastRate(0)
@ -1840,7 +1829,7 @@ bool C4NetIOUDP::Init(uint16_t inPort)
// set flags
fInit = true;
fMultiCast = false;
iNextCheck = GetTime() + iCheckInterval;
tNextCheck = GetTime() + iCheckInterval;
// ok, that's all for now.
// call InitBroadcast for more initialization fun
@ -2012,8 +2001,8 @@ bool C4NetIOUDP::Execute(int iMaxTime, pollfd *) // (mt-safe)
ResetError();
// adjust maximum block time
int Now = GetTime();
int iMaxBlock = GetNextTick(Now) - Now;
time_t tNow = GetTime();
int iMaxBlock = GetNextTick(tNow) - tNow;
if (iMaxTime == TO_INF || iMaxTime > iMaxBlock) iMaxTime = iMaxBlock;
// execute subclass
@ -2021,7 +2010,7 @@ bool C4NetIOUDP::Execute(int iMaxTime, pollfd *) // (mt-safe)
return false;
// connection check needed?
if (iNextCheck <= GetTime())
if (tNextCheck <= GetTime())
DoCheck();
// client timeout?
for (Peer *pPeer = pPeerList; pPeer; pPeer = pPeer->Next)
@ -2106,18 +2095,18 @@ bool C4NetIOUDP::SetBroadcast(const addr_t &addr, bool fSet) // (mt-safe)
return true;
}
int C4NetIOUDP::GetNextTick(int Now) // (mt-safe)
time_t C4NetIOUDP::GetNextTick(time_t tNow) // (mt-safe)
{
// maximum time: check interval
int iTiming = Max<int>(Now, iNextCheck);
time_t tTiming = Max(tNow, tNextCheck);
// client timeouts (e.g. connection timeout)
CStdShareLock PeerListLock(&PeerListCSec);
for (Peer *pPeer = pPeerList; pPeer; pPeer = pPeer->Next)
if (!pPeer->Closed())
if (pPeer->GetTimeout() > 0)
iTiming = Min(iTiming, Now + pPeer->GetTimeout());
tTiming = Min(tTiming, tNow + pPeer->GetTimeout());
// return timing value
return iTiming;
return tTiming;
}
bool C4NetIOUDP::GetStatistic(int *pBroadcastRate) // (mt-safe)
@ -2496,7 +2485,7 @@ C4NetIOUDP::Peer::Peer(const sockaddr_in &naddr, C4NetIOUDP *pnParent)
iIPacketCounter(0), iRIPacketCounter(0),
iIMCPacketCounter(0), iRIMCPacketCounter(0),
iMCAckPacketCounter(0),
iNextReCheck(0),
tNextReCheck(0),
iIRate(0), iORate(0), iLoss(0)
{
ZeroMem(&addr2, sizeof(addr2));
@ -2544,7 +2533,7 @@ bool C4NetIOUDP::Peer::Check(bool fForceCheck)
if (eStatus != CS_Works) return true;
// prevent re-check (check floods)
// instead, ask for other packets that are missing until recheck is allowed
bool fNoReCheck = !!iNextReCheck && iNextReCheck > GetTime();
bool fNoReCheck = !!tNextReCheck && tNextReCheck > GetTime();
if (!fNoReCheck) iLastPacketAsked = iLastMCPacketAsked = 0;
unsigned int iStartAt = fNoReCheck ? Max(iLastPacketAsked + 1, iIPacketCounter) : iIPacketCounter;
unsigned int iStartAtMC = fNoReCheck ? Max(iLastMCPacketAsked + 1, iIMCPacketCounter) : iIMCPacketCounter;
@ -2562,7 +2551,7 @@ bool C4NetIOUDP::Peer::Check(bool fForceCheck)
int iEAskCnt = iAskCnt + iMCAskCnt;
// no re-check limit? set it
if (!fNoReCheck)
iNextReCheck = iEAskCnt ? GetTime() + iReCheckInterval : 0;
tNextReCheck = iEAskCnt ? GetTime() + iReCheckInterval : 0;
// something to ask for? (or check forced?)
if (iEAskCnt || fForceCheck)
return DoCheck(iAskCnt, iMCAskCnt, iAskList);
@ -2627,7 +2616,7 @@ void C4NetIOUDP::Peer::OnRecv(const C4NetIOPacket &rPacket) // (mt-safe)
else
iRIPacketCounter = iIPacketCounter = pPkt->Nr;
// clear incoming packets
IPackets.Clear(); IMCPackets.Clear(); iNextReCheck = 0;
IPackets.Clear(); IMCPackets.Clear(); tNextReCheck = 0;
iLastPacketAsked = iLastMCPacketAsked = 0;
// Activate Multicast?
if (!pParent->fMultiCast)
@ -2786,9 +2775,9 @@ void C4NetIOUDP::Peer::Close(const char *szReason) // (mt-safe)
void C4NetIOUDP::Peer::CheckTimeout()
{
// timeout set?
if (!iTimeout) return;
if (!tTimeout) return;
// check
if (GetTime() > iTimeout)
if (GetTime() > tTimeout)
OnTimeout();
}
@ -2937,9 +2926,9 @@ void C4NetIOUDP::Peer::CheckCompleteIPackets()
void C4NetIOUDP::Peer::SetTimeout(int iLength, int iRetryCnt) // (mt-safe)
{
if (iLength != TO_INF)
iTimeout = GetTime() + iLength;
tTimeout = GetTime() + iLength;
else
iTimeout = 0;
tTimeout = 0;
iRetries = iRetryCnt;
}
@ -3156,7 +3145,7 @@ void C4NetIOUDP::DoCheck() // (mt-safe)
if (pPeer->Open())
pPeer->Check();
// set time for next check
iNextCheck = GetTime() + iCheckInterval;
tNextCheck = GetTime() + iCheckInterval;
}
// debug
@ -3204,9 +3193,9 @@ void C4NetIOUDP::CloseDebugLog()
void C4NetIOUDP::DebugLogPkt(bool fOut, const C4NetIOPacket &Pkt)
{
StdStrBuf O;
unsigned int iTime = GetTime();
time_t tTime = GetTime();
O.Format("%s %d:%02d:%02d:%03d %s:%d:", fOut ? "out" : "in ",
(iTime / 1000 / 60 / 60), (iTime / 1000 / 60) % 60, (iTime / 1000) % 60, iTime % 1000,
(tTime / 1000 / 60 / 60), (tTime / 1000 / 60) % 60, (tTime / 1000) % 60, tTime % 1000,
inet_ntoa(Pkt.getAddr().sin_addr), htons(Pkt.getAddr().sin_port));
// header?

View File

@ -218,7 +218,6 @@ public:
#else
virtual void GetFDs(std::vector<struct pollfd> & FDs);
#endif
virtual int GetNextTick(int Now);
// statistics
virtual bool GetStatistic(int *pBroadcastRate);
@ -373,7 +372,6 @@ public:
#else
virtual void GetFDs(std::vector<struct pollfd> & FDs);
#endif
virtual int GetNextTick(int Now);
// not implemented
virtual bool Connect(const addr_t &addr) { assert(false); return false; }
@ -460,7 +458,8 @@ public:
virtual bool Broadcast(const C4NetIOPacket &rPacket);
virtual bool SetBroadcast(const addr_t &addr, bool fSet = true);
virtual int GetNextTick(int Now);
virtual time_t GetNextTick(time_t tNow);
virtual bool IsScheduledExecution() { return true; }
virtual bool GetStatistic(int *pBroadcastRate);
virtual bool GetConnStatistic(const addr_t &addr, int *pIRate, int *pORate, int *pLoss);
@ -622,11 +621,11 @@ protected:
CStdCSec OutCSec;
// connection check time limit
unsigned int iNextReCheck;
time_t tNextReCheck;
unsigned int iLastPacketAsked, iLastMCPacketAsked;
// timeout
unsigned int iTimeout;
time_t tTimeout;
unsigned int iRetries;
// statistics
@ -662,7 +661,7 @@ protected:
unsigned int GetMCAckPacketCounter() const { return iMCAckPacketCounter; }
// timeout checking
int GetTimeout() { return iTimeout; }
time_t GetTimeout() { return tTimeout; }
void CheckTimeout();
// selected for broadcast?
@ -728,7 +727,7 @@ protected:
bool fDelayedLoopbackTest;
// check timing
unsigned int iNextCheck;
time_t tNextCheck;
// outgoing packet list (for multicast)
PacketList OPackets;

View File

@ -146,7 +146,7 @@ C4Network2::C4Network2()
pLobby(NULL), fLobbyRunning(false), pLobbyCountdown(NULL),
iNextClientID(0),
iLastChaseTargetUpdate(0),
iLastActivateRequest(0),
tLastActivateRequest(0),
iLastReferenceUpdate(0),
iLastLeagueUpdate(0),
pLeagueClient(NULL),
@ -624,7 +624,7 @@ void C4Network2::Execute()
else
{
// request activate, if neccessary
if (iLastActivateRequest) RequestActivate();
if (tLastActivateRequest) RequestActivate();
}
}
@ -664,7 +664,7 @@ void C4Network2::Clear()
// stuff
fAllowJoin = false;
iDynamicTick = -1; fDynamicNeeded = false;
iLastActivateRequest = iLastChaseTargetUpdate = iLastReferenceUpdate = iLastLeagueUpdate = 0;
tLastActivateRequest = iLastChaseTargetUpdate = iLastReferenceUpdate = iLastLeagueUpdate = 0;
fDelayedActivateReq = false;
delete pVoteDialog; pVoteDialog = NULL;
fPausedForVote = false;
@ -1502,7 +1502,8 @@ C4Network2Res::Ref C4Network2::RetrieveRes(const C4Network2ResCore &Core, int32_
{
C4GUI::ProgressDialog *pDlg = NULL;
bool fLog = false;
int32_t iProcess = -1; uint32_t iTimeout = GetTime() + iTimeoutLen;
int32_t iProcess = -1;
time_t tTimeout = GetTime() + iTimeoutLen;
// wait for resource
while (isEnabled())
{
@ -1534,12 +1535,12 @@ C4Network2Res::Ref C4Network2::RetrieveRes(const C4Network2ResCore &Core, int32_
if (pRes && pRes->getPresentPercent() != iProcess)
{
iProcess = pRes->getPresentPercent();
iTimeout = GetTime() + iTimeoutLen;
tTimeout = GetTime() + iTimeoutLen;
}
else
{
// if not: check timeout
if (GetTime() > iTimeout)
if (GetTime() > tTimeout)
{
LogFatal(FormatString(LoadResStr("IDS_NET_ERR_RESTIMEOUT"), szResName).getData());
if (pDlg) delete pDlg;
@ -1576,7 +1577,7 @@ C4Network2Res::Ref C4Network2::RetrieveRes(const C4Network2ResCore &Core, int32_
}
else
{
if (!Application.ScheduleProcs(iTimeout - GetTime()))
if (!Application.ScheduleProcs(tTimeout - GetTime()))
{ return NULL; }
}
@ -1761,7 +1762,7 @@ void C4Network2::RequestActivate()
// neither observer nor activated?
if (Game.Clients.getLocal()->isObserver() || Game.Clients.getLocal()->isActivated())
{
iLastActivateRequest = 0;
tLastActivateRequest = 0;
return;
}
// host? just do it
@ -1774,7 +1775,7 @@ void C4Network2::RequestActivate()
return;
}
// ensure interval
if (iLastActivateRequest && GetTime() < iLastActivateRequest + C4NetActivationReqInterval)
if (tLastActivateRequest && GetTime() < tLastActivateRequest + C4NetActivationReqInterval)
return;
// status not reached yet? May be chasing, let's delay this.
if (!fStatusReached)
@ -1785,7 +1786,7 @@ void C4Network2::RequestActivate()
// request
Clients.SendMsgToHost(MkC4NetIOPacket(PID_ClientActReq, C4PacketActivateReq(Game.FrameCounter)));
// store time
iLastActivateRequest = GetTime();
tLastActivateRequest = GetTime();
}
void C4Network2::DeactivateInactiveClients()

View File

@ -1,442 +1,442 @@
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 2004-2007 Sven Eberhardt
* Copyright (c) 2004-2008 Peter Wortmann
* Copyright (c) 2006 Günther Brammer
* Copyright (c) 2010 Benjamin Herr
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de
*
* Portions might be copyrighted by other authors who have contributed
* to OpenClonk.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
* See isc_license.txt for full license and disclaimer.
*
* "Clonk" is a registered trademark of Matthes Bender.
* See clonk_trademark_license.txt for full license.
*/
#ifndef INC_C4Network2
#define INC_C4Network2
#include "C4NetIO.h"
#include "C4Network2Players.h"
#include "C4Network2IO.h"
#include "C4Network2Res.h"
#include "C4Network2Client.h"
#include "C4Control.h"
#include "C4Gui.h"
#include "C4GameParameters.h"
// lobby predef - no need to include lobby in header just for the class ptr
namespace C4GameLobby { class MainDlg; class Countdown; }
class C4PacketJoinData;
// standard ports
const int16_t C4NetStdPortTCP = 11112,
C4NetStdPortUDP = 11113,
C4NetStdPortDiscovery = 11114,
C4NetStdPortRefServer = 11111,
C4NetStdPortPuncher = 11115,
C4NetStdPortHTTP = 80;
// resource retrieve wait timeout
const int C4NetResRetrieveTimeout = 100000; // (ms)
// client (de)activation
const int C4NetActivationReqInterval = 5000, // (ms)
C4NetMaxBehind4Activation = 20, // (ticks)
C4NetDeactivationDelay = 500; // (ticks)
// client chase
const unsigned int C4NetChaseTargetUpdateInterval = 5; // (s)
// reference
const unsigned int C4NetReferenceUpdateInterval = 120; // (s)
const unsigned int C4NetMinLeagueUpdateInterval = 10; // (s)
// voting
const unsigned int C4NetVotingTimeout = 10; // (s)
const unsigned int C4NetMinVotingInterval = 120; // (s)
// streaming
const size_t C4NetStreamingMinBlockSize = 10 * 1024;
const size_t C4NetStreamingMaxBlockSize = 20 * 1024;
const int C4NetStreamingInterval = 30; // (s)
enum C4NetGameState
{
GS_None, // network not active
GS_Init, // connecting to host, waiting for join data
GS_Lobby, // lobby mode
GS_Pause, // game paused
GS_Go // game running
};
class C4Network2Status : public C4PacketBase
{
public:
C4Network2Status();
protected:
C4NetGameState eState;
int32_t iCtrlMode;
int32_t iTargetCtrlTick;
public:
C4NetGameState getState() const { return eState; }
int32_t getCtrlMode() const { return iCtrlMode; }
int32_t getTargetCtrlTick() const { return iTargetCtrlTick; }
const char *getStateName() const;
const char *getDescription() const;
bool isEnabled() const { return eState != GS_None; }
bool isLobbyActive() const { return eState == GS_Lobby; }
bool isPastLobby() const { return eState > GS_Lobby; }
bool isPaused() const { return eState == GS_Pause; }
bool isRunning() const { return eState == GS_Go; }
void Set(C4NetGameState eState, int32_t iTargetCtrlTick);
void SetCtrlMode(int32_t iCtrlMode);
void SetTargetTick(int32_t iTargetCtrlTick);
void Clear();
void CompileFunc(StdCompiler *pComp, bool fReference);
virtual void CompileFunc(StdCompiler *pComp);
};
class C4Network2 : private C4ApplicationSec1Timer
{
friend class C4Network2IO;
public:
C4Network2();
virtual ~C4Network2();
public:
// network i/o class
C4Network2IO NetIO;
// resource list
C4Network2ResList ResList;
// client list
C4Network2ClientList Clients;
// player list
C4Network2Players Players;
// game status
C4Network2Status Status;
protected:
// role
bool fHost;
// options
bool fAllowJoin, fAllowObserve;
// join resource
C4Network2ResCore ResDynamic;
// resources
int32_t iDynamicTick;
bool fDynamicNeeded;
// game status flags
bool fStatusAck, fStatusReached;
bool fChasing;
// control
class C4GameControlNetwork *pControl;
// lobby
C4GameLobby::MainDlg *pLobby;
bool fLobbyRunning;
C4GameLobby::Countdown *pLobbyCountdown;
// master server used
StdCopyStrBuf MasterServerAddress;
// clients
int32_t iNextClientID;
// chase
uint32_t iLastChaseTargetUpdate;
// activation
uint32_t iLastActivateRequest;
// reference
uint32_t iLastReferenceUpdate;
uint32_t iLastLeagueUpdate, iLeagueUpdateDelay;
bool fLeagueEndSent;
// league
class C4LeagueClient *pLeagueClient;
// game password
StdStrBuf sPassword;
// connection failed because password needed?
bool fWrongPassword;
// delayed activation request?
bool fDelayedActivateReq;
// voting
C4Control Votes;
class C4VoteDialog *pVoteDialog;
bool fPausedForVote;
time_t iVoteStartTime, iLastOwnVoting;
// streaming
bool fStreaming;
time_t iLastStreamAttempt;
C4Record *pStreamedRecord;
StdBuf StreamingBuf;
z_stream StreamCompressor;
class C4Network2HTTPClient *pStreamer;
unsigned int iCurrentStreamAmount, iCurrentStreamPosition;
public:
// data access
bool isEnabled() const { return Status.isEnabled(); }
bool isLobbyActive()const { return Status.isLobbyActive(); }
bool isPastLobby() const { return Status.isPastLobby(); }
bool isRunning() const { return Status.isRunning() && isStatusAck(); }
bool isPaused() const { return Status.isPaused() && isStatusAck(); }
bool isPausing() const { return Status.isPaused() && !fStatusAck; }
bool isHost() const { return fHost; }
bool isStatusAck() const { return fStatusAck; }
bool isFrozen() const;
bool isJoinAllowed() const { return fAllowJoin; }
bool isObservingAllowed() const { return fAllowObserve; }
class C4GameLobby::MainDlg *GetLobby() const { return pLobby; } // lobby publication
const char *GetPassword() const { return sPassword.getData(); } // Oh noez, now the password is public!
bool isPassworded() const { return !sPassword.isNull(); }
// initialization result type
enum InitResult
{
IR_Success, IR_Error, IR_Fatal
};
// initialization
bool InitHost(bool fLobby);
InitResult InitClient(const class C4Network2Reference &Ref, bool fObserver);
InitResult InitClient(const class C4Network2Address *pAddrs, int iAddrCount, const class C4ClientCore &HostCore, const char *szPassword = NULL);
bool DoLobby();
bool Start();
bool Pause();
bool Sync();
bool FinalInit();
bool RetrieveScenario(char *szScenario);
C4Network2Res::Ref RetrieveRes(const C4Network2ResCore &Core, int32_t iTimeout, const char *szResName, bool fWaitForCore = false);
// idle processes
void OnSec1Timer();
void Execute();
// termination
void Clear();
// some options
bool ToggleAllowJoin();
bool ToggleClientListDlg();
void AllowJoin(bool fAllow);
void SetAllowObserve(bool fAllow);
void SetCtrlMode(int32_t iCtrlMode);
void SetPassword(const char *szToPassword);
StdStrBuf QueryClientPassword(); // ask client for a password; empty if user canceled
// interface for C4Network2IO
void OnConn(C4Network2IOConnection *pConn);
void OnDisconn(C4Network2IOConnection *pConn);
void HandlePacket(char cStatus, const C4PacketBase *pBasePkt, C4Network2IOConnection *pConn);
void HandleLobbyPacket(char cStatus, const C4PacketBase *pBasePkt, C4Network2IOConnection *pConn);
// runtime join stuff
void OnGameSynchronized();
// status
void DrawStatus(C4TargetFacet &cgo);
// client activation
void RequestActivate();
void DeactivateInactiveClients(); // host
// league
void LeagueGameEvaluate(const char *szRecordName = NULL, const BYTE *pRecordSHA = NULL);
void LeagueSignupDisable(); // if "internet game" button is switched off in lobby: Remove from league server
bool LeagueSignupEnable(); // if "internet game" button is switched on in lobby: (re)Add to league server
void InvalidateReference(); // forces a recreation and re-send of the game reference in the next execution cycle
bool LeaguePlrAuth(C4PlayerInfo *pInfo); // client: get authentication for a player from the league server
bool LeaguePlrAuthCheck(C4PlayerInfo *pInfo); // host: check AUID of player info with league server
void LeagueNotifyDisconnect(int32_t iClientID, enum C4LeagueDisconnectReason eReason); //
void LeagueWaitNotBusy(); // block until league serveris no longer busy. Process update reply if last message was an update
void LeagueSurrender(); // forfeit in league - just fake a disconnect
void LeagueShowError(const char *szMsg); // show league error msg box in fullscreen; just log in console
// voting
void Vote(C4ControlVoteType eType, bool fApprove = true, int32_t iData = 0);
void AddVote(const C4ControlVote &Vote);
C4IDPacket *GetVote(int32_t iClientID, C4ControlVoteType eType, int32_t iData);
void EndVote(C4ControlVoteType eType, bool fApprove, int32_t iData);
void OpenVoteDialog();
void OpenSurrenderDialog(C4ControlVoteType eType, int32_t iData);
void OnVoteDialogClosed();
// lobby countdown
void StartLobbyCountdown(int32_t iCountdownTime);
void AbortLobbyCountdown();
bool isLobbyCountDown() { return pLobbyCountdown != 0; }
// streaming
size_t getPendingStreamData() const { return StreamingBuf.getSize() - StreamCompressor.avail_out; }
bool isStreaming() const;
bool StartStreaming(C4Record *pRecord);
bool FinishStreaming();
bool StopStreaming();
protected:
using C4ApplicationSec1Timer::Execute; // to avoid "virtual ... is hidden" warning
// net i/o initialization
bool InitNetIO(bool fNoClientID, bool fHost);
// handling of own packets
void HandleConn(const class C4PacketConn &Pkt, C4Network2IOConnection *pConn, C4Network2Client *pClient);
bool CheckConn(const C4ClientCore &CCore, C4Network2IOConnection *pConn, C4Network2Client *pClient, StdStrBuf * szReply);
bool HostConnect(const C4ClientCore &CCore, C4Network2IOConnection *pConn, StdStrBuf *szReply);
bool Join(C4ClientCore &CCore, C4Network2IOConnection *pConn, StdStrBuf *szReply);
void HandleConnRe(const class C4PacketConnRe &Pkt, C4Network2IOConnection *pConn, C4Network2Client *pClient);
void HandleStatus(const C4Network2Status &nStatus);
void HandleStatusAck(const C4Network2Status &nStatus, C4Network2Client *pClient);
void HandleActivateReq(int32_t iTick, C4Network2Client *pClient);
void HandleJoinData(const class C4PacketJoinData &rPkt);
// events
void OnConnect(C4Network2Client *pClient, C4Network2IOConnection *pConn, const char *szMsg, bool fFirstConnection);
void OnConnectFail(C4Network2IOConnection *pConn);
void OnDisconnect(C4Network2Client *pClient, C4Network2IOConnection *pConn);
void OnClientConnect(C4Network2Client *pClient, C4Network2IOConnection *pConn);
void OnClientDisconnect(C4Network2Client *pClient);
void SendJoinData(C4Network2Client *pClient);
// resource list
bool CreateDynamic(bool fInit);
void RemoveDynamic();
// status changes
bool PauseGame(bool fAutoContinue);
bool ChangeGameStatus(C4NetGameState enState, int32_t iTargetCtrlTick, int32_t iCtrlMode = -1);
void CheckStatusReached(bool fFromFinalInit = false);
void CheckStatusAck();
void OnStatusReached();
void OnStatusAck();
// chase
void UpdateChaseTarget();
// league
bool InitLeague(bool *pCancel);
void DeinitLeague();
bool LeagueStart(bool *pCancel);
bool LeagueUpdate();
bool LeagueUpdateProcessReply();
bool LeagueEnd(const char *szRecordName = NULL, const BYTE *pRecordSHA = NULL);
// streaming
bool StreamIn(bool fFinish);
bool StreamOut();
};
extern C4Network2 Network;
class C4VoteDialog : public C4GUI::MessageDialog
{
public:
C4VoteDialog(const char *szText, C4ControlVoteType eVoteType, int32_t iVoteData, bool fSurrender);
private:
C4ControlVoteType eVoteType;
int32_t iVoteData;
bool fSurrender;
public:
C4ControlVoteType getVoteType() const { return eVoteType; }
int32_t getVoteData() const { return iVoteData; }
private:
virtual bool OnEnter() { UserClose(false); return true; } // the vote dialog defaults to "No" [MarkFra]
virtual void OnClosed(bool fOK);
// true for dialogs that receive full keyboard and mouse input even in shared mode
virtual bool IsExclusiveDialog() { return true; }
};
// * Packets *
class C4PacketJoinData : public C4PacketBase
{
public:
C4PacketJoinData() { }
protected:
// the client ID
int32_t iClientID;
// Dynamic data to boot
C4Network2ResCore Dynamic;
// network status
C4Network2Status GameStatus;
// control tick
int32_t iStartCtrlTick;
public:
// the game parameters
C4GameParameters Parameters;
public:
const int32_t &getClientID() const { return iClientID; }
const C4Network2ResCore&getDynamicCore() const { return Dynamic; }
const C4Network2Status &getStatus() const { return GameStatus; }
int32_t getStartCtrlTick() const { return iStartCtrlTick; }
void SetClientID(int32_t inClientID) { iClientID = inClientID; }
void SetGameStatus(const C4Network2Status &Status) { GameStatus = Status; }
void SetDynamicCore(const C4Network2ResCore &Core) { Dynamic = Core; }
void SetStartCtrlTick(int32_t iTick) { iStartCtrlTick = iTick; }
virtual void CompileFunc(StdCompiler *pComp);
};
class C4PacketActivateReq : public C4PacketBase
{
public:
C4PacketActivateReq(int32_t iTick = -1) : iTick(iTick) { }
protected:
int32_t iTick;
public:
int32_t getTick() const { return iTick; }
virtual void CompileFunc(StdCompiler *pComp);
};
#endif
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 2004-2007 Sven Eberhardt
* Copyright (c) 2004-2008 Peter Wortmann
* Copyright (c) 2006 Günther Brammer
* Copyright (c) 2010 Benjamin Herr
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de
*
* Portions might be copyrighted by other authors who have contributed
* to OpenClonk.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
* See isc_license.txt for full license and disclaimer.
*
* "Clonk" is a registered trademark of Matthes Bender.
* See clonk_trademark_license.txt for full license.
*/
#ifndef INC_C4Network2
#define INC_C4Network2
#include "C4NetIO.h"
#include "C4Network2Players.h"
#include "C4Network2IO.h"
#include "C4Network2Res.h"
#include "C4Network2Client.h"
#include "C4Control.h"
#include "C4Gui.h"
#include "C4GameParameters.h"
// lobby predef - no need to include lobby in header just for the class ptr
namespace C4GameLobby { class MainDlg; class Countdown; }
class C4PacketJoinData;
// standard ports
const int16_t C4NetStdPortTCP = 11112,
C4NetStdPortUDP = 11113,
C4NetStdPortDiscovery = 11114,
C4NetStdPortRefServer = 11111,
C4NetStdPortPuncher = 11115,
C4NetStdPortHTTP = 80;
// resource retrieve wait timeout
const int C4NetResRetrieveTimeout = 100000; // (ms)
// client (de)activation
const int C4NetActivationReqInterval = 5000, // (ms)
C4NetMaxBehind4Activation = 20, // (ticks)
C4NetDeactivationDelay = 500; // (ticks)
// client chase
const unsigned int C4NetChaseTargetUpdateInterval = 5; // (s)
// reference
const unsigned int C4NetReferenceUpdateInterval = 120; // (s)
const unsigned int C4NetMinLeagueUpdateInterval = 10; // (s)
// voting
const unsigned int C4NetVotingTimeout = 10; // (s)
const unsigned int C4NetMinVotingInterval = 120; // (s)
// streaming
const size_t C4NetStreamingMinBlockSize = 10 * 1024;
const size_t C4NetStreamingMaxBlockSize = 20 * 1024;
const int C4NetStreamingInterval = 30; // (s)
enum C4NetGameState
{
GS_None, // network not active
GS_Init, // connecting to host, waiting for join data
GS_Lobby, // lobby mode
GS_Pause, // game paused
GS_Go // game running
};
class C4Network2Status : public C4PacketBase
{
public:
C4Network2Status();
protected:
C4NetGameState eState;
int32_t iCtrlMode;
int32_t iTargetCtrlTick;
public:
C4NetGameState getState() const { return eState; }
int32_t getCtrlMode() const { return iCtrlMode; }
int32_t getTargetCtrlTick() const { return iTargetCtrlTick; }
const char *getStateName() const;
const char *getDescription() const;
bool isEnabled() const { return eState != GS_None; }
bool isLobbyActive() const { return eState == GS_Lobby; }
bool isPastLobby() const { return eState > GS_Lobby; }
bool isPaused() const { return eState == GS_Pause; }
bool isRunning() const { return eState == GS_Go; }
void Set(C4NetGameState eState, int32_t iTargetCtrlTick);
void SetCtrlMode(int32_t iCtrlMode);
void SetTargetTick(int32_t iTargetCtrlTick);
void Clear();
void CompileFunc(StdCompiler *pComp, bool fReference);
virtual void CompileFunc(StdCompiler *pComp);
};
class C4Network2 : private C4ApplicationSec1Timer
{
friend class C4Network2IO;
public:
C4Network2();
virtual ~C4Network2();
public:
// network i/o class
C4Network2IO NetIO;
// resource list
C4Network2ResList ResList;
// client list
C4Network2ClientList Clients;
// player list
C4Network2Players Players;
// game status
C4Network2Status Status;
protected:
// role
bool fHost;
// options
bool fAllowJoin, fAllowObserve;
// join resource
C4Network2ResCore ResDynamic;
// resources
int32_t iDynamicTick;
bool fDynamicNeeded;
// game status flags
bool fStatusAck, fStatusReached;
bool fChasing;
// control
class C4GameControlNetwork *pControl;
// lobby
C4GameLobby::MainDlg *pLobby;
bool fLobbyRunning;
C4GameLobby::Countdown *pLobbyCountdown;
// master server used
StdCopyStrBuf MasterServerAddress;
// clients
int32_t iNextClientID;
// chase
uint32_t iLastChaseTargetUpdate;
// activation
time_t tLastActivateRequest;
// reference
uint32_t iLastReferenceUpdate;
uint32_t iLastLeagueUpdate, iLeagueUpdateDelay;
bool fLeagueEndSent;
// league
class C4LeagueClient *pLeagueClient;
// game password
StdStrBuf sPassword;
// connection failed because password needed?
bool fWrongPassword;
// delayed activation request?
bool fDelayedActivateReq;
// voting
C4Control Votes;
class C4VoteDialog *pVoteDialog;
bool fPausedForVote;
time_t iVoteStartTime, iLastOwnVoting;
// streaming
bool fStreaming;
time_t iLastStreamAttempt;
C4Record *pStreamedRecord;
StdBuf StreamingBuf;
z_stream StreamCompressor;
class C4Network2HTTPClient *pStreamer;
unsigned int iCurrentStreamAmount, iCurrentStreamPosition;
public:
// data access
bool isEnabled() const { return Status.isEnabled(); }
bool isLobbyActive()const { return Status.isLobbyActive(); }
bool isPastLobby() const { return Status.isPastLobby(); }
bool isRunning() const { return Status.isRunning() && isStatusAck(); }
bool isPaused() const { return Status.isPaused() && isStatusAck(); }
bool isPausing() const { return Status.isPaused() && !fStatusAck; }
bool isHost() const { return fHost; }
bool isStatusAck() const { return fStatusAck; }
bool isFrozen() const;
bool isJoinAllowed() const { return fAllowJoin; }
bool isObservingAllowed() const { return fAllowObserve; }
class C4GameLobby::MainDlg *GetLobby() const { return pLobby; } // lobby publication
const char *GetPassword() const { return sPassword.getData(); } // Oh noez, now the password is public!
bool isPassworded() const { return !sPassword.isNull(); }
// initialization result type
enum InitResult
{
IR_Success, IR_Error, IR_Fatal
};
// initialization
bool InitHost(bool fLobby);
InitResult InitClient(const class C4Network2Reference &Ref, bool fObserver);
InitResult InitClient(const class C4Network2Address *pAddrs, int iAddrCount, const class C4ClientCore &HostCore, const char *szPassword = NULL);
bool DoLobby();
bool Start();
bool Pause();
bool Sync();
bool FinalInit();
bool RetrieveScenario(char *szScenario);
C4Network2Res::Ref RetrieveRes(const C4Network2ResCore &Core, int32_t iTimeout, const char *szResName, bool fWaitForCore = false);
// idle processes
void OnSec1Timer();
void Execute();
// termination
void Clear();
// some options
bool ToggleAllowJoin();
bool ToggleClientListDlg();
void AllowJoin(bool fAllow);
void SetAllowObserve(bool fAllow);
void SetCtrlMode(int32_t iCtrlMode);
void SetPassword(const char *szToPassword);
StdStrBuf QueryClientPassword(); // ask client for a password; empty if user canceled
// interface for C4Network2IO
void OnConn(C4Network2IOConnection *pConn);
void OnDisconn(C4Network2IOConnection *pConn);
void HandlePacket(char cStatus, const C4PacketBase *pBasePkt, C4Network2IOConnection *pConn);
void HandleLobbyPacket(char cStatus, const C4PacketBase *pBasePkt, C4Network2IOConnection *pConn);
// runtime join stuff
void OnGameSynchronized();
// status
void DrawStatus(C4TargetFacet &cgo);
// client activation
void RequestActivate();
void DeactivateInactiveClients(); // host
// league
void LeagueGameEvaluate(const char *szRecordName = NULL, const BYTE *pRecordSHA = NULL);
void LeagueSignupDisable(); // if "internet game" button is switched off in lobby: Remove from league server
bool LeagueSignupEnable(); // if "internet game" button is switched on in lobby: (re)Add to league server
void InvalidateReference(); // forces a recreation and re-send of the game reference in the next execution cycle
bool LeaguePlrAuth(C4PlayerInfo *pInfo); // client: get authentication for a player from the league server
bool LeaguePlrAuthCheck(C4PlayerInfo *pInfo); // host: check AUID of player info with league server
void LeagueNotifyDisconnect(int32_t iClientID, enum C4LeagueDisconnectReason eReason); //
void LeagueWaitNotBusy(); // block until league serveris no longer busy. Process update reply if last message was an update
void LeagueSurrender(); // forfeit in league - just fake a disconnect
void LeagueShowError(const char *szMsg); // show league error msg box in fullscreen; just log in console
// voting
void Vote(C4ControlVoteType eType, bool fApprove = true, int32_t iData = 0);
void AddVote(const C4ControlVote &Vote);
C4IDPacket *GetVote(int32_t iClientID, C4ControlVoteType eType, int32_t iData);
void EndVote(C4ControlVoteType eType, bool fApprove, int32_t iData);
void OpenVoteDialog();
void OpenSurrenderDialog(C4ControlVoteType eType, int32_t iData);
void OnVoteDialogClosed();
// lobby countdown
void StartLobbyCountdown(int32_t iCountdownTime);
void AbortLobbyCountdown();
bool isLobbyCountDown() { return pLobbyCountdown != 0; }
// streaming
size_t getPendingStreamData() const { return StreamingBuf.getSize() - StreamCompressor.avail_out; }
bool isStreaming() const;
bool StartStreaming(C4Record *pRecord);
bool FinishStreaming();
bool StopStreaming();
protected:
using C4ApplicationSec1Timer::Execute; // to avoid "virtual ... is hidden" warning
// net i/o initialization
bool InitNetIO(bool fNoClientID, bool fHost);
// handling of own packets
void HandleConn(const class C4PacketConn &Pkt, C4Network2IOConnection *pConn, C4Network2Client *pClient);
bool CheckConn(const C4ClientCore &CCore, C4Network2IOConnection *pConn, C4Network2Client *pClient, StdStrBuf * szReply);
bool HostConnect(const C4ClientCore &CCore, C4Network2IOConnection *pConn, StdStrBuf *szReply);
bool Join(C4ClientCore &CCore, C4Network2IOConnection *pConn, StdStrBuf *szReply);
void HandleConnRe(const class C4PacketConnRe &Pkt, C4Network2IOConnection *pConn, C4Network2Client *pClient);
void HandleStatus(const C4Network2Status &nStatus);
void HandleStatusAck(const C4Network2Status &nStatus, C4Network2Client *pClient);
void HandleActivateReq(int32_t iTick, C4Network2Client *pClient);
void HandleJoinData(const class C4PacketJoinData &rPkt);
// events
void OnConnect(C4Network2Client *pClient, C4Network2IOConnection *pConn, const char *szMsg, bool fFirstConnection);
void OnConnectFail(C4Network2IOConnection *pConn);
void OnDisconnect(C4Network2Client *pClient, C4Network2IOConnection *pConn);
void OnClientConnect(C4Network2Client *pClient, C4Network2IOConnection *pConn);
void OnClientDisconnect(C4Network2Client *pClient);
void SendJoinData(C4Network2Client *pClient);
// resource list
bool CreateDynamic(bool fInit);
void RemoveDynamic();
// status changes
bool PauseGame(bool fAutoContinue);
bool ChangeGameStatus(C4NetGameState enState, int32_t iTargetCtrlTick, int32_t iCtrlMode = -1);
void CheckStatusReached(bool fFromFinalInit = false);
void CheckStatusAck();
void OnStatusReached();
void OnStatusAck();
// chase
void UpdateChaseTarget();
// league
bool InitLeague(bool *pCancel);
void DeinitLeague();
bool LeagueStart(bool *pCancel);
bool LeagueUpdate();
bool LeagueUpdateProcessReply();
bool LeagueEnd(const char *szRecordName = NULL, const BYTE *pRecordSHA = NULL);
// streaming
bool StreamIn(bool fFinish);
bool StreamOut();
};
extern C4Network2 Network;
class C4VoteDialog : public C4GUI::MessageDialog
{
public:
C4VoteDialog(const char *szText, C4ControlVoteType eVoteType, int32_t iVoteData, bool fSurrender);
private:
C4ControlVoteType eVoteType;
int32_t iVoteData;
bool fSurrender;
public:
C4ControlVoteType getVoteType() const { return eVoteType; }
int32_t getVoteData() const { return iVoteData; }
private:
virtual bool OnEnter() { UserClose(false); return true; } // the vote dialog defaults to "No" [MarkFra]
virtual void OnClosed(bool fOK);
// true for dialogs that receive full keyboard and mouse input even in shared mode
virtual bool IsExclusiveDialog() { return true; }
};
// * Packets *
class C4PacketJoinData : public C4PacketBase
{
public:
C4PacketJoinData() { }
protected:
// the client ID
int32_t iClientID;
// Dynamic data to boot
C4Network2ResCore Dynamic;
// network status
C4Network2Status GameStatus;
// control tick
int32_t iStartCtrlTick;
public:
// the game parameters
C4GameParameters Parameters;
public:
const int32_t &getClientID() const { return iClientID; }
const C4Network2ResCore&getDynamicCore() const { return Dynamic; }
const C4Network2Status &getStatus() const { return GameStatus; }
int32_t getStartCtrlTick() const { return iStartCtrlTick; }
void SetClientID(int32_t inClientID) { iClientID = inClientID; }
void SetGameStatus(const C4Network2Status &Status) { GameStatus = Status; }
void SetDynamicCore(const C4Network2ResCore &Core) { Dynamic = Core; }
void SetStartCtrlTick(int32_t iTick) { iStartCtrlTick = iTick; }
virtual void CompileFunc(StdCompiler *pComp);
};
class C4PacketActivateReq : public C4PacketBase
{
public:
C4PacketActivateReq(int32_t iTick = -1) : iTick(iTick) { }
protected:
int32_t iTick;
public:
int32_t getTick() const { return iTick; }
virtual void CompileFunc(StdCompiler *pComp);
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,441 +1,443 @@
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 2004-2008 Peter Wortmann
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de
*
* Portions might be copyrighted by other authors who have contributed
* to OpenClonk.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
* See isc_license.txt for full license and disclaimer.
*
* "Clonk" is a registered trademark of Matthes Bender.
* See clonk_trademark_license.txt for full license.
*/
#ifndef INC_C4Network2IO
#define INC_C4Network2IO
#include "C4NetIO.h"
#include "C4Client.h"
#include "C4InteractiveThread.h"
class C4Network2IOConnection;
// enums & constants
enum C4Network2IOProtocol
{
P_UDP, P_TCP, P_NONE = -1
};
const int C4NetTimer = 500, // ms
C4NetPingFreq = 1000, // ms
C4NetStatisticsFreq = 1000, // ms
C4NetAcceptTimeout = 10, // s
C4NetPingTimeout = 30000;// ms
// client count
const int C4NetMaxClients = 256;
class C4Network2IO
: protected C4InteractiveThread::Callback,
protected C4NetIO::CBClass,
protected StdSchedulerProc
{
public:
C4Network2IO();
virtual ~C4Network2IO();
protected:
// main traffic net i/o classes
C4NetIO *pNetIO_TCP, *pNetIO_UDP;
// discovery net i/o
class C4Network2IODiscover *pNetIODiscover;
// reference server
class C4Network2RefServer *pRefServer;
// UPnP port mapping manager
class C4Network2UPnP *UPnPMgr;
// local client core
C4ClientCore LCCore;
CStdCSec LCCoreCSec;
// connection list
C4Network2IOConnection *pConnList;
CStdCSec ConnListCSec, BroadcastCSec;
// next connection ID to use
uint32_t iNextConnID;
// allow incoming connections?
bool fAllowConnect;
// connection acceptance
struct AutoAccept
{
C4ClientCore CCore;
AutoAccept *Next;
}
*pAutoAcceptList;
CStdCSec AutoAcceptCSec;
// make sure only one connection is established?
bool fExclusiveConn;
// timer & ping
unsigned long iLastExecute, iLastPing;
// statistics
unsigned long iLastStatistic;
int iTCPIRate, iTCPORate, iTCPBCRate,
iUDPIRate, iUDPORate, iUDPBCRate;
// punching
C4NetIO::addr_t PuncherAddr;
public:
bool hasTCP() const { return !! pNetIO_TCP; }
bool hasUDP() const { return !! pNetIO_UDP; }
// initialization
bool Init(int16_t iPortTCP, int16_t iPortUDP, int16_t iPortDiscovery = -1, int16_t iPortRefServer = -1, bool fBroadcast = false); // by main thread
void Clear(); // by main thread
void SetLocalCCore(const C4ClientCore &CCore); // by main thread
// i/o types
C4NetIO *MsgIO(); // by both
C4NetIO *DataIO(); // by both
// connections
bool Connect(const C4NetIO::addr_t &addr, C4Network2IOProtocol eProt, const C4ClientCore &nCCore, const char *szPassword = NULL); // by main thread
void SetAcceptMode(bool fAcceptAll); // by main thread
void SetExclusiveConnMode(bool fExclusiveConn); // by main thread
int getConnectionCount(); // by main thread
void ClearAutoAccept(); // by main thread
void AddAutoAccept(const C4ClientCore &CCore); // by main thread
void RemoveAutoAccept(const C4ClientCore &CCore); // by main thread
C4Network2IOConnection *GetMsgConnection(int iClientID); // by both (returns referenced connection!)
C4Network2IOConnection *GetDataConnection(int iClientID); // by both (returns referenced connection!)
// broadcasting
void BeginBroadcast(bool fSelectAll = false); // by both
void EndBroadcast(); // by both
bool Broadcast(const C4NetIOPacket &rPkt); // by both
// sending helpers
bool SendMsgToClient(C4NetIOPacket &rPkt, int iClient); // by both
bool BroadcastMsg(const C4NetIOPacket &rPkt); // by both
// punch
bool Punch(C4NetIO::addr_t PuncherAddr); // by main thread
// stuff
C4NetIO *getNetIO(C4Network2IOProtocol eProt); // by both
const char *getNetIOName(C4NetIO *pNetIO);
C4Network2IOProtocol getNetIOProt(C4NetIO *pNetIO);
// statistics
int getProtIRate(C4Network2IOProtocol eProt) const { return eProt == P_TCP ? iTCPIRate : iUDPIRate; }
int getProtORate(C4Network2IOProtocol eProt) const { return eProt == P_TCP ? iTCPORate : iUDPORate; }
int getProtBCRate(C4Network2IOProtocol eProt) const { return eProt == P_TCP ? iTCPBCRate : iUDPBCRate; }
// reference
void SetReference(class C4Network2Reference *pReference);
bool IsReferenceNeeded();
protected:
// *** callbacks
// C4NetIO-Callbacks
virtual bool OnConn(const C4NetIO::addr_t &addr, const C4NetIO::addr_t &AddrConnect, const C4NetIO::addr_t *pOwnAddr, C4NetIO *pNetIO);
virtual void OnDisconn(const C4NetIO::addr_t &addr, C4NetIO *pNetIO, const char *szReason);
virtual void OnPacket(const C4NetIOPacket &rPacket, C4NetIO *pNetIO);
// C4NetIOMan
virtual void OnError(const char *strError, C4NetIO *pNetIO);
// StdSchedulerProc
virtual bool Execute(int iTimeout, pollfd *);
virtual int GetNextTick(int Now);
// Event callback by C4InteractiveThread
void OnThreadEvent(C4InteractiveEventType eEvent, void *pEventData); // by main thread
// connections list
void AddConnection(C4Network2IOConnection *pConn); // by both
void RemoveConnection(C4Network2IOConnection *pConn); // by both
C4Network2IOConnection *GetConnection(const C4NetIO::addr_t &addr, C4NetIO *pNetIO); // by both
C4Network2IOConnection *GetConnectionByConnAddr(const C4NetIO::addr_t &addr, C4NetIO *pNetIO); // by both
C4Network2IOConnection *GetConnectionByID(uint32_t iConnID); // by thread
// network events (signals to main thread)
struct NetEvPacketData;
// connection acceptance
bool doAutoAccept(const C4ClientCore &CCore, const C4Network2IOConnection &Conn);
// general packet handling (= forward in most cases)
bool HandlePacket(const C4NetIOPacket &rPacket, C4Network2IOConnection *pConn, bool fThread); // by both
void CallHandlers(int iHandlers, const class C4IDPacket *pPacket, C4Network2IOConnection *pConn, bool fThread); // by both
// packet handling (some are really handled here)
void HandlePacket(char cStatus, const C4PacketBase *pPacket, C4Network2IOConnection *pConn);
void HandleFwdReq(const class C4PacketFwd &rFwd, C4Network2IOConnection *pBy);
// misc
bool Ping();
void CheckTimeout();
void GenerateStatistics(int iInterval);
void SendConnPackets();
// puncher
void OnPunch(C4NetIO::addr_t addr);
};
enum C4Network2IOConnStatus
{
CS_Connect, // waiting for connection
CS_Connected, // waiting for Conn
CS_HalfAccepted, // got Conn (peer identified, client class created if neccessary)
CS_Accepted, // got ConnRe (peer did accept)
CS_Closed,
CS_ConnectFail // got closed before HalfAccepted was reached
};
class C4Network2IOConnection // shared
{
friend class C4Network2IO;
public:
C4Network2IOConnection();
~C4Network2IOConnection();
protected:
// connection data
class C4NetIO *pNetClass;
C4Network2IOProtocol eProt;
C4NetIO::addr_t PeerAddr, ConnectAddr;
// status data
C4Network2IOConnStatus Status;
uint32_t iID, iRemoteID; // connection ID for this and the remote client
bool fAutoAccept; // auto accepted by thread?
bool fBroadcastTarget; // broadcast target?
time_t iTimestamp; // timestamp of last status change
int iPingTime; // ping
unsigned long iLastPing; // if > iLastPong, it's the first ping that hasn't been answered yet
unsigned long iLastPong; // last pong received
C4ClientCore CCore; // client core (>= CS_HalfAccepted)
CStdCSec CCoreCSec;
int iIRate, iORate; // input/output rates (by C4NetIO, in b/s)
int iPacketLoss; // lost packets (in the last seconds)
StdCopyStrBuf Password; // password to use for connect
bool fConnSent; // initial connection packet send
bool fPostMortemSent; // post mortem send
// packet backlog
uint32_t iOutPacketCounter, iInPacketCounter;
struct PacketLogEntry
{
uint32_t Number;
C4NetIOPacket Pkt;
PacketLogEntry *Next;
};
PacketLogEntry *pPacketLog;
CStdCSec PacketLogCSec;
// list (C4Network2IO)
C4Network2IOConnection *pNext;
// reference counter
long iRefCnt;
public:
C4NetIO *getNetClass() const { return pNetClass; }
C4Network2IOProtocol getProtocol() const { return eProt; }
const C4NetIO::addr_t &getPeerAddr() const { return PeerAddr.sin_port ? PeerAddr : ConnectAddr; }
const C4NetIO::addr_t &getConnectAddr() const { return ConnectAddr; }
uint32_t getID() const { return iID; }
uint32_t getRemoteID() const { return iRemoteID; }
time_t getTimestamp() const { return iTimestamp; }
const C4ClientCore &getCCore() const { return CCore; }
CStdCSec &getCCoreCSec() { return CCoreCSec; }
int getClientID() const { return CCore.getID(); }
bool isHost() const { return CCore.isHost(); }
int getPingTime() const { return iPingTime; }
int getLag() const;
int getIRate() const { return iIRate; }
int getORate() const { return iORate; }
int getPacketLoss() const { return iPacketLoss; }
const char *getPassword() const { return Password.getData(); }
bool isConnSent() const { return fConnSent; }
uint32_t getInPacketCounter() const { return iInPacketCounter; }
uint32_t getOutPacketCounter() const { return iOutPacketCounter; }
bool isConnecting() const { return Status == CS_Connect; }
bool isOpen() const { return Status != CS_Connect && Status != CS_Closed && Status != CS_ConnectFail; }
bool isHalfAccepted()const { return Status == CS_HalfAccepted || Status == CS_Accepted; }
bool isAccepted() const { return Status == CS_Accepted; }
bool isClosed() const { return Status == CS_Closed || Status == CS_ConnectFail; }
bool isAutoAccepted()const { return fAutoAccept; }
bool isBroadcastTarget() const { return fBroadcastTarget; }
bool isFailed() const { return Status == CS_ConnectFail; }
protected:
// called by C4Network2IO only
void Set(C4NetIO *pnNetClass, C4Network2IOProtocol eProt, const C4NetIO::addr_t &nPeerAddr, const C4NetIO::addr_t &nConnectAddr, C4Network2IOConnStatus nStatus, const char *szPassword, uint32_t iID);
void SetRemoteID(uint32_t iRemoteID);
void SetPeerAddr(const C4NetIO::addr_t &nPeerAddr);
void OnPing();
void SetPingTime(int iPingTime);
void SetStatus(C4Network2IOConnStatus nStatus);
void SetAutoAccepted();
void OnPacketReceived(uint8_t iPacketType);
void ClearPacketLog(uint32_t iStartNumber = ~0);
public:
// status changing
void SetHalfAccepted() { SetStatus(CS_HalfAccepted); }
void SetAccepted() { SetStatus(CS_Accepted); }
void SetCCore(const C4ClientCore &nCCore);
void ResetAutoAccepted() { fAutoAccept = false; }
void SetConnSent() { fConnSent = true; }
// connection operations
bool Connect();
void Close();
bool Send(const C4NetIOPacket &rPkt);
void SetBroadcastTarget(bool fSet); // (only call after C4Network2IO::BeginBroadcast!)
// statistics
void DoStatistics(int iInterval, int *pIRateSum, int *pORateSum);
// reference counting
void AddRef(); void DelRef();
// post mortem
bool CreatePostMortem(class C4PacketPostMortem *pPkt);
};
// * Packets *
class C4PacketPing : public C4PacketBase
{
public:
C4PacketPing(uint32_t iPacketCounter = 0, uint32_t iRemotePacketCounter = 0);
protected:
uint32_t iTime;
uint32_t iPacketCounter;
public:
uint32_t getTravelTime() const;
uint32_t getPacketCounter() const { return iPacketCounter; }
virtual void CompileFunc(StdCompiler *pComp);
};
class C4PacketConn : public C4PacketBase
{
public:
C4PacketConn();
C4PacketConn(const class C4ClientCore &nCCore, uint32_t iConnID, const char *szPassword = NULL);
protected:
int32_t iVer;
uint32_t iConnID;
C4ClientCore CCore;
StdCopyStrBuf Password;
public:
int32_t getVer() const { return iVer; }
uint32_t getConnID() const { return iConnID; }
const C4ClientCore &getCCore() const { return CCore; }
const char *getPassword() const { return Password.getData(); }
virtual void CompileFunc(StdCompiler *pComp);
};
class C4PacketConnRe : public C4PacketBase
{
public:
C4PacketConnRe();
C4PacketConnRe(bool fOK, bool fWrongPassword, const char *szMsg = NULL);
protected:
bool fOK, fWrongPassword;
StdStrBuf szMsg;
public:
bool isOK() const { return fOK; }
bool isPasswordWrong() const { return fWrongPassword; }
const char *getMsg() const { return szMsg.getData(); }
virtual void CompileFunc(StdCompiler *pComp);
};
class C4PacketFwd : public C4PacketBase
{
public:
C4PacketFwd();
C4PacketFwd(const StdBuf &Pkt);
protected:
bool fNegativeList;
int32_t iClients[C4NetMaxClients];
int32_t iClientCnt;
StdCopyBuf Data;
public:
const StdCopyBuf &getData() const { return Data; }
bool isNegativeList() const { return fNegativeList; }
int32_t getClient(int32_t i) const { return iClients[i]; }
int32_t getClientCnt() const { return iClientCnt; }
bool DoFwdTo(int32_t iClient) const;
void SetData(const StdBuf &Pkt);
void SetListType(bool fnNegativeList);
void AddClient(int32_t iClient);
virtual void CompileFunc(StdCompiler *pComp);
};
class C4PacketPostMortem : public C4PacketBase
{
public:
C4PacketPostMortem();
~C4PacketPostMortem();
private:
uint32_t iConnID;
uint32_t iPacketCounter; // last packet counter of dead connection
uint32_t iPacketCount;
struct PacketLink
{
C4NetIOPacket Pkt;
PacketLink *Next;
};
PacketLink *pPackets;
public:
uint32_t getConnID() const { return iConnID; }
uint32_t getPacketCount() const { return iPacketCount; }
void SetConnID(uint32_t inConnID) { iConnID = inConnID; }
const C4NetIOPacket *getPacket(uint32_t iNumber) const;
void SetPacketCounter(uint32_t iPacketCounter);
void Add(const C4NetIOPacket &rPkt);
virtual void CompileFunc(StdCompiler *pComp);
};
#endif
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 2004-2008 Peter Wortmann
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de
*
* Portions might be copyrighted by other authors who have contributed
* to OpenClonk.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
* See isc_license.txt for full license and disclaimer.
*
* "Clonk" is a registered trademark of Matthes Bender.
* See clonk_trademark_license.txt for full license.
*/
#ifndef INC_C4Network2IO
#define INC_C4Network2IO
#include "C4NetIO.h"
#include "C4Client.h"
#include "C4InteractiveThread.h"
class C4Network2IOConnection;
// enums & constants
enum C4Network2IOProtocol
{
P_UDP, P_TCP, P_NONE = -1
};
const int C4NetTimer = 500, // ms
C4NetPingFreq = 1000, // ms
C4NetStatisticsFreq = 1000, // ms
C4NetAcceptTimeout = 10, // s
C4NetPingTimeout = 30000;// ms
// client count
const int C4NetMaxClients = 256;
class C4Network2IO
: protected C4InteractiveThread::Callback,
protected C4NetIO::CBClass,
protected StdSchedulerProc
{
public:
C4Network2IO();
virtual ~C4Network2IO();
protected:
// main traffic net i/o classes
C4NetIO *pNetIO_TCP, *pNetIO_UDP;
// discovery net i/o
class C4Network2IODiscover *pNetIODiscover;
// reference server
class C4Network2RefServer *pRefServer;
// UPnP port mapping manager
class C4Network2UPnP *UPnPMgr;
// local client core
C4ClientCore LCCore;
CStdCSec LCCoreCSec;
// connection list
C4Network2IOConnection *pConnList;
CStdCSec ConnListCSec, BroadcastCSec;
// next connection ID to use
uint32_t iNextConnID;
// allow incoming connections?
bool fAllowConnect;
// connection acceptance
struct AutoAccept
{
C4ClientCore CCore;
AutoAccept *Next;
}
*pAutoAcceptList;
CStdCSec AutoAcceptCSec;
// make sure only one connection is established?
bool fExclusiveConn;
// timer & ping
time_t tLastExecute;
time_t tLastPing;
// statistics
time_t tLastStatistic;
int iTCPIRate, iTCPORate, iTCPBCRate,
iUDPIRate, iUDPORate, iUDPBCRate;
// punching
C4NetIO::addr_t PuncherAddr;
public:
bool hasTCP() const { return !! pNetIO_TCP; }
bool hasUDP() const { return !! pNetIO_UDP; }
// initialization
bool Init(int16_t iPortTCP, int16_t iPortUDP, int16_t iPortDiscovery = -1, int16_t iPortRefServer = -1, bool fBroadcast = false); // by main thread
void Clear(); // by main thread
void SetLocalCCore(const C4ClientCore &CCore); // by main thread
// i/o types
C4NetIO *MsgIO(); // by both
C4NetIO *DataIO(); // by both
// connections
bool Connect(const C4NetIO::addr_t &addr, C4Network2IOProtocol eProt, const C4ClientCore &nCCore, const char *szPassword = NULL); // by main thread
void SetAcceptMode(bool fAcceptAll); // by main thread
void SetExclusiveConnMode(bool fExclusiveConn); // by main thread
int getConnectionCount(); // by main thread
void ClearAutoAccept(); // by main thread
void AddAutoAccept(const C4ClientCore &CCore); // by main thread
void RemoveAutoAccept(const C4ClientCore &CCore); // by main thread
C4Network2IOConnection *GetMsgConnection(int iClientID); // by both (returns referenced connection!)
C4Network2IOConnection *GetDataConnection(int iClientID); // by both (returns referenced connection!)
// broadcasting
void BeginBroadcast(bool fSelectAll = false); // by both
void EndBroadcast(); // by both
bool Broadcast(const C4NetIOPacket &rPkt); // by both
// sending helpers
bool SendMsgToClient(C4NetIOPacket &rPkt, int iClient); // by both
bool BroadcastMsg(const C4NetIOPacket &rPkt); // by both
// punch
bool Punch(C4NetIO::addr_t PuncherAddr); // by main thread
// stuff
C4NetIO *getNetIO(C4Network2IOProtocol eProt); // by both
const char *getNetIOName(C4NetIO *pNetIO);
C4Network2IOProtocol getNetIOProt(C4NetIO *pNetIO);
// statistics
int getProtIRate(C4Network2IOProtocol eProt) const { return eProt == P_TCP ? iTCPIRate : iUDPIRate; }
int getProtORate(C4Network2IOProtocol eProt) const { return eProt == P_TCP ? iTCPORate : iUDPORate; }
int getProtBCRate(C4Network2IOProtocol eProt) const { return eProt == P_TCP ? iTCPBCRate : iUDPBCRate; }
// reference
void SetReference(class C4Network2Reference *pReference);
bool IsReferenceNeeded();
protected:
// *** callbacks
// C4NetIO-Callbacks
virtual bool OnConn(const C4NetIO::addr_t &addr, const C4NetIO::addr_t &AddrConnect, const C4NetIO::addr_t *pOwnAddr, C4NetIO *pNetIO);
virtual void OnDisconn(const C4NetIO::addr_t &addr, C4NetIO *pNetIO, const char *szReason);
virtual void OnPacket(const C4NetIOPacket &rPacket, C4NetIO *pNetIO);
// C4NetIOMan
virtual void OnError(const char *strError, C4NetIO *pNetIO);
// StdSchedulerProc
virtual bool Execute(int iTimeout, pollfd *);
virtual time_t GetNextTick(time_t Now);
virtual bool IsScheduledExecution() { return true; }
// Event callback by C4InteractiveThread
void OnThreadEvent(C4InteractiveEventType eEvent, void *pEventData); // by main thread
// connections list
void AddConnection(C4Network2IOConnection *pConn); // by both
void RemoveConnection(C4Network2IOConnection *pConn); // by both
C4Network2IOConnection *GetConnection(const C4NetIO::addr_t &addr, C4NetIO *pNetIO); // by both
C4Network2IOConnection *GetConnectionByConnAddr(const C4NetIO::addr_t &addr, C4NetIO *pNetIO); // by both
C4Network2IOConnection *GetConnectionByID(uint32_t iConnID); // by thread
// network events (signals to main thread)
struct NetEvPacketData;
// connection acceptance
bool doAutoAccept(const C4ClientCore &CCore, const C4Network2IOConnection &Conn);
// general packet handling (= forward in most cases)
bool HandlePacket(const C4NetIOPacket &rPacket, C4Network2IOConnection *pConn, bool fThread); // by both
void CallHandlers(int iHandlers, const class C4IDPacket *pPacket, C4Network2IOConnection *pConn, bool fThread); // by both
// packet handling (some are really handled here)
void HandlePacket(char cStatus, const C4PacketBase *pPacket, C4Network2IOConnection *pConn);
void HandleFwdReq(const class C4PacketFwd &rFwd, C4Network2IOConnection *pBy);
// misc
bool Ping();
void CheckTimeout();
void GenerateStatistics(int iInterval);
void SendConnPackets();
// puncher
void OnPunch(C4NetIO::addr_t addr);
};
enum C4Network2IOConnStatus
{
CS_Connect, // waiting for connection
CS_Connected, // waiting for Conn
CS_HalfAccepted, // got Conn (peer identified, client class created if neccessary)
CS_Accepted, // got ConnRe (peer did accept)
CS_Closed,
CS_ConnectFail // got closed before HalfAccepted was reached
};
class C4Network2IOConnection // shared
{
friend class C4Network2IO;
public:
C4Network2IOConnection();
~C4Network2IOConnection();
protected:
// connection data
class C4NetIO *pNetClass;
C4Network2IOProtocol eProt;
C4NetIO::addr_t PeerAddr, ConnectAddr;
// status data
C4Network2IOConnStatus Status;
uint32_t iID, iRemoteID; // connection ID for this and the remote client
bool fAutoAccept; // auto accepted by thread?
bool fBroadcastTarget; // broadcast target?
time_t iTimestamp; // timestamp of last status change
int iPingTime; // ping
time_t tLastPing; // if > iLastPong, it's the first ping that hasn't been answered yet
time_t tLastPong; // last pong received
C4ClientCore CCore; // client core (>= CS_HalfAccepted)
CStdCSec CCoreCSec;
int iIRate, iORate; // input/output rates (by C4NetIO, in b/s)
int iPacketLoss; // lost packets (in the last seconds)
StdCopyStrBuf Password; // password to use for connect
bool fConnSent; // initial connection packet send
bool fPostMortemSent; // post mortem send
// packet backlog
uint32_t iOutPacketCounter, iInPacketCounter;
struct PacketLogEntry
{
uint32_t Number;
C4NetIOPacket Pkt;
PacketLogEntry *Next;
};
PacketLogEntry *pPacketLog;
CStdCSec PacketLogCSec;
// list (C4Network2IO)
C4Network2IOConnection *pNext;
// reference counter
long iRefCnt;
public:
C4NetIO *getNetClass() const { return pNetClass; }
C4Network2IOProtocol getProtocol() const { return eProt; }
const C4NetIO::addr_t &getPeerAddr() const { return PeerAddr.sin_port ? PeerAddr : ConnectAddr; }
const C4NetIO::addr_t &getConnectAddr() const { return ConnectAddr; }
uint32_t getID() const { return iID; }
uint32_t getRemoteID() const { return iRemoteID; }
time_t getTimestamp() const { return iTimestamp; }
const C4ClientCore &getCCore() const { return CCore; }
CStdCSec &getCCoreCSec() { return CCoreCSec; }
int getClientID() const { return CCore.getID(); }
bool isHost() const { return CCore.isHost(); }
int getPingTime() const { return iPingTime; }
int getLag() const;
int getIRate() const { return iIRate; }
int getORate() const { return iORate; }
int getPacketLoss() const { return iPacketLoss; }
const char *getPassword() const { return Password.getData(); }
bool isConnSent() const { return fConnSent; }
uint32_t getInPacketCounter() const { return iInPacketCounter; }
uint32_t getOutPacketCounter() const { return iOutPacketCounter; }
bool isConnecting() const { return Status == CS_Connect; }
bool isOpen() const { return Status != CS_Connect && Status != CS_Closed && Status != CS_ConnectFail; }
bool isHalfAccepted()const { return Status == CS_HalfAccepted || Status == CS_Accepted; }
bool isAccepted() const { return Status == CS_Accepted; }
bool isClosed() const { return Status == CS_Closed || Status == CS_ConnectFail; }
bool isAutoAccepted()const { return fAutoAccept; }
bool isBroadcastTarget() const { return fBroadcastTarget; }
bool isFailed() const { return Status == CS_ConnectFail; }
protected:
// called by C4Network2IO only
void Set(C4NetIO *pnNetClass, C4Network2IOProtocol eProt, const C4NetIO::addr_t &nPeerAddr, const C4NetIO::addr_t &nConnectAddr, C4Network2IOConnStatus nStatus, const char *szPassword, uint32_t iID);
void SetRemoteID(uint32_t iRemoteID);
void SetPeerAddr(const C4NetIO::addr_t &nPeerAddr);
void OnPing();
void SetPingTime(int iPingTime);
void SetStatus(C4Network2IOConnStatus nStatus);
void SetAutoAccepted();
void OnPacketReceived(uint8_t iPacketType);
void ClearPacketLog(uint32_t iStartNumber = ~0);
public:
// status changing
void SetHalfAccepted() { SetStatus(CS_HalfAccepted); }
void SetAccepted() { SetStatus(CS_Accepted); }
void SetCCore(const C4ClientCore &nCCore);
void ResetAutoAccepted() { fAutoAccept = false; }
void SetConnSent() { fConnSent = true; }
// connection operations
bool Connect();
void Close();
bool Send(const C4NetIOPacket &rPkt);
void SetBroadcastTarget(bool fSet); // (only call after C4Network2IO::BeginBroadcast!)
// statistics
void DoStatistics(int iInterval, int *pIRateSum, int *pORateSum);
// reference counting
void AddRef(); void DelRef();
// post mortem
bool CreatePostMortem(class C4PacketPostMortem *pPkt);
};
// * Packets *
class C4PacketPing : public C4PacketBase
{
public:
C4PacketPing(uint32_t iPacketCounter = 0, uint32_t iRemotePacketCounter = 0);
protected:
time_t tTime;
uint32_t iPacketCounter;
public:
uint32_t getTravelTime() const;
uint32_t getPacketCounter() const { return iPacketCounter; }
virtual void CompileFunc(StdCompiler *pComp);
};
class C4PacketConn : public C4PacketBase
{
public:
C4PacketConn();
C4PacketConn(const class C4ClientCore &nCCore, uint32_t iConnID, const char *szPassword = NULL);
protected:
int32_t iVer;
uint32_t iConnID;
C4ClientCore CCore;
StdCopyStrBuf Password;
public:
int32_t getVer() const { return iVer; }
uint32_t getConnID() const { return iConnID; }
const C4ClientCore &getCCore() const { return CCore; }
const char *getPassword() const { return Password.getData(); }
virtual void CompileFunc(StdCompiler *pComp);
};
class C4PacketConnRe : public C4PacketBase
{
public:
C4PacketConnRe();
C4PacketConnRe(bool fOK, bool fWrongPassword, const char *szMsg = NULL);
protected:
bool fOK, fWrongPassword;
StdStrBuf szMsg;
public:
bool isOK() const { return fOK; }
bool isPasswordWrong() const { return fWrongPassword; }
const char *getMsg() const { return szMsg.getData(); }
virtual void CompileFunc(StdCompiler *pComp);
};
class C4PacketFwd : public C4PacketBase
{
public:
C4PacketFwd();
C4PacketFwd(const StdBuf &Pkt);
protected:
bool fNegativeList;
int32_t iClients[C4NetMaxClients];
int32_t iClientCnt;
StdCopyBuf Data;
public:
const StdCopyBuf &getData() const { return Data; }
bool isNegativeList() const { return fNegativeList; }
int32_t getClient(int32_t i) const { return iClients[i]; }
int32_t getClientCnt() const { return iClientCnt; }
bool DoFwdTo(int32_t iClient) const;
void SetData(const StdBuf &Pkt);
void SetListType(bool fnNegativeList);
void AddClient(int32_t iClient);
virtual void CompileFunc(StdCompiler *pComp);
};
class C4PacketPostMortem : public C4PacketBase
{
public:
C4PacketPostMortem();
~C4PacketPostMortem();
private:
uint32_t iConnID;
uint32_t iPacketCounter; // last packet counter of dead connection
uint32_t iPacketCount;
struct PacketLink
{
C4NetIOPacket Pkt;
PacketLink *Next;
};
PacketLink *pPackets;
public:
uint32_t getConnID() const { return iConnID; }
uint32_t getPacketCount() const { return iPacketCount; }
void SetConnID(uint32_t inConnID) { iConnID = inConnID; }
const C4NetIOPacket *getPacket(uint32_t iNumber) const;
void SetPacketCounter(uint32_t iPacketCounter);
void Add(const C4NetIOPacket &rPkt);
virtual void CompileFunc(StdCompiler *pComp);
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,217 +1,218 @@
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 2006-2007 Peter Wortmann
* Copyright (c) 2007-2008 Sven Eberhardt
* Copyright (c) 2010 Tobias Zwick
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de
*
* Portions might be copyrighted by other authors who have contributed
* to OpenClonk.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
* See isc_license.txt for full license and disclaimer.
*
* "Clonk" is a registered trademark of Matthes Bender.
* See clonk_trademark_license.txt for full license.
*/
#ifndef C4NETWORK2REFERENCE_H
#define C4NETWORK2REFERENCE_H
#include "C4Network2.h"
#include "C4Network2Client.h"
#include "C4GameParameters.h"
#include "C4Version.h"
#include "C4GameVersion.h"
#include "C4InputValidation.h"
const int C4Network2HTTPQueryTimeout = 10; // (s)
// Session data
class C4Network2Reference
{
public:
C4Network2Reference();
~C4Network2Reference();
// Game parameters
C4GameParameters Parameters;
private:
// General information
int32_t Icon;
ValidatedStdCopyStrBuf<C4InVal::VAL_NameExNoEmpty> Title;
C4Network2Status GameStatus;
int32_t Time;
int32_t Frame;
int32_t StartTime;
int32_t LeaguePerformance; // custom settlement league performance if scenario doesn't use elapsed frames
ValidatedStdCopyStrBuf<C4InVal::VAL_Comment> Comment;
bool JoinAllowed;
bool ObservingAllowed;
bool PasswordNeeded;
bool OfficialServer;
// Engine information
C4GameVersion Game;
// Network addresses
uint8_t iAddrCnt;
C4Network2Address Addrs[C4ClientMaxAddr];
public:
const C4Network2Address &getAddr(int i) const { return Addrs[i]; }
int getAddrCnt() const { return iAddrCnt; }
const char *getTitle() const { return Title.getData(); }
int32_t getIcon() const { return Icon; }
C4Network2Status getGameStatus() const { return GameStatus; }
const char *getComment() const { return Comment.getData(); }
const C4GameVersion &getGameVersion() const { return Game; }
bool isPasswordNeeded() const { return PasswordNeeded; }
bool isJoinAllowed() const { return JoinAllowed; }
bool isOfficialServer() const { return OfficialServer; }
int32_t getSortOrder() const;
int32_t getTime() const { return Time; }
int32_t getStartTime() const { return StartTime; }
void SetSourceIP(in_addr ip);
void InitLocal();
void SortNullIPsBack();
void CompileFunc(StdCompiler *pComp);
};
// Serves references (mini-HTTP-server)
class C4Network2RefServer : public C4NetIOTCP
{
public:
C4Network2RefServer();
virtual ~C4Network2RefServer();
private:
CStdCSec RefCSec;
C4Network2Reference *pReference;
public:
void Clear();
void SetReference(C4Network2Reference *pReference);
protected:
// Overridden
virtual void PackPacket(const C4NetIOPacket &rPacket, StdBuf &rOutBuf);
virtual size_t UnpackPacket(const StdBuf &rInBuf, const C4NetIO::addr_t &addr);
private:
// Responses
void RespondNotImplemented(const C4NetIO::addr_t &addr, const char *szMessage);
void RespondReference(const C4NetIO::addr_t &addr);
};
// mini HTTP client
class C4Network2HTTPClient : public C4NetIOTCP, private C4NetIO::CBClass
{
public:
C4Network2HTTPClient();
virtual ~C4Network2HTTPClient();
private:
// Address information
C4NetIO::addr_t ServerAddr, PeerAddr;
StdCopyStrBuf Server, RequestPath;
bool fBinary;
bool fBusy, fSuccess, fConnected;
size_t iDataOffset;
StdCopyBuf Request;
time_t iRequestTimeout;
// Response header data
size_t iDownloadedSize, iTotalSize;
bool fCompressed;
// Event queue to use for notify when something happens
class C4InteractiveThread *pNotify;
protected:
StdCopyBuf ResultBin; // set if fBinary
StdCopyStrBuf ResultString; // set if !fBinary
protected:
// Overridden
virtual void PackPacket(const C4NetIOPacket &rPacket, StdBuf &rOutBuf);
virtual size_t UnpackPacket(const StdBuf &rInBuf, const C4NetIO::addr_t &addr);
// Callbacks
bool OnConn(const C4NetIO::addr_t &AddrPeer, const C4NetIO::addr_t &AddrConnect, const addr_t *pOwnAddr, C4NetIO *pNetIO);
void OnDisconn(const C4NetIO::addr_t &AddrPeer, C4NetIO *pNetIO, const char *szReason);
void OnPacket(const class C4NetIOPacket &rPacket, C4NetIO *pNetIO);
void ResetRequestTimeout();
virtual int32_t GetDefaultPort() { return 80; }
public:
bool Query(const StdBuf &Data, bool fBinary);
bool Query(const char *szData, bool fBinary) { return Query(StdBuf(szData, SLen(szData)), fBinary); }
bool isBusy() const { return fBusy; }
bool isSuccess() const { return fSuccess; }
bool isConnected() const { return fConnected; }
size_t getTotalSize() const { return iTotalSize; }
size_t getDownloadedSize() const { return iDownloadedSize; }
const StdBuf &getResultBin() const { assert(fBinary); return ResultBin; }
const char *getResultString() const { assert(!fBinary); return ResultString.getData(); }
const char *getServerName() const { return Server.getData(); }
const char *getRequest() const { return RequestPath.getData(); }
const C4NetIO::addr_t &getServerAddress() const { return ServerAddr; }
void Cancel(const char *szReason);
void Clear();
bool SetServer(const char *szServerAddress);
void SetNotify(class C4InteractiveThread *pnNotify) { pNotify = pnNotify; }
// Overridden
virtual bool Execute(int iMaxTime, pollfd * readyfds) { return Execute(iMaxTime); }
virtual bool Execute(int iMaxTime = TO_INF);
virtual int GetNextTick(int Now);
private:
bool ReadHeader(StdStrBuf Data);
bool Decompress(StdBuf *pData);
};
// Loads current update url string (mini-HTTP-client)
class C4Network2UpdateClient : public C4Network2HTTPClient
{
protected:
virtual int32_t GetDefaultPort() { return C4NetStdPortHTTP; }
public:
C4Network2UpdateClient() : C4Network2HTTPClient() {}
bool QueryUpdateURL();
bool GetUpdateURL(StdStrBuf *pUpdateURL);
bool GetVersion(StdStrBuf *pVersion);
};
// Loads references + current update url string (mini-HTTP-client)
class C4Network2RefClient : public C4Network2UpdateClient
{
protected:
virtual int32_t GetDefaultPort() { return C4NetStdPortRefServer; }
public:
C4Network2RefClient() : C4Network2UpdateClient() {}
bool QueryReferences();
bool GetReferences(C4Network2Reference **&rpReferences, int32_t &rRefCount);
};
#endif // C4NETWORK2REFERENCE_H
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 2006-2007 Peter Wortmann
* Copyright (c) 2007-2008 Sven Eberhardt
* Copyright (c) 2010 Tobias Zwick
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de
*
* Portions might be copyrighted by other authors who have contributed
* to OpenClonk.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
* See isc_license.txt for full license and disclaimer.
*
* "Clonk" is a registered trademark of Matthes Bender.
* See clonk_trademark_license.txt for full license.
*/
#ifndef C4NETWORK2REFERENCE_H
#define C4NETWORK2REFERENCE_H
#include "C4Network2.h"
#include "C4Network2Client.h"
#include "C4GameParameters.h"
#include "C4Version.h"
#include "C4GameVersion.h"
#include "C4InputValidation.h"
const int C4Network2HTTPQueryTimeout = 10; // (s)
// Session data
class C4Network2Reference
{
public:
C4Network2Reference();
~C4Network2Reference();
// Game parameters
C4GameParameters Parameters;
private:
// General information
int32_t Icon;
ValidatedStdCopyStrBuf<C4InVal::VAL_NameExNoEmpty> Title;
C4Network2Status GameStatus;
int32_t Time;
int32_t Frame;
int32_t StartTime;
int32_t LeaguePerformance; // custom settlement league performance if scenario doesn't use elapsed frames
ValidatedStdCopyStrBuf<C4InVal::VAL_Comment> Comment;
bool JoinAllowed;
bool ObservingAllowed;
bool PasswordNeeded;
bool OfficialServer;
// Engine information
C4GameVersion Game;
// Network addresses
uint8_t iAddrCnt;
C4Network2Address Addrs[C4ClientMaxAddr];
public:
const C4Network2Address &getAddr(int i) const { return Addrs[i]; }
int getAddrCnt() const { return iAddrCnt; }
const char *getTitle() const { return Title.getData(); }
int32_t getIcon() const { return Icon; }
C4Network2Status getGameStatus() const { return GameStatus; }
const char *getComment() const { return Comment.getData(); }
const C4GameVersion &getGameVersion() const { return Game; }
bool isPasswordNeeded() const { return PasswordNeeded; }
bool isJoinAllowed() const { return JoinAllowed; }
bool isOfficialServer() const { return OfficialServer; }
int32_t getSortOrder() const;
int32_t getTime() const { return Time; }
int32_t getStartTime() const { return StartTime; }
void SetSourceIP(in_addr ip);
void InitLocal();
void SortNullIPsBack();
void CompileFunc(StdCompiler *pComp);
};
// Serves references (mini-HTTP-server)
class C4Network2RefServer : public C4NetIOTCP
{
public:
C4Network2RefServer();
virtual ~C4Network2RefServer();
private:
CStdCSec RefCSec;
C4Network2Reference *pReference;
public:
void Clear();
void SetReference(C4Network2Reference *pReference);
protected:
// Overridden
virtual void PackPacket(const C4NetIOPacket &rPacket, StdBuf &rOutBuf);
virtual size_t UnpackPacket(const StdBuf &rInBuf, const C4NetIO::addr_t &addr);
private:
// Responses
void RespondNotImplemented(const C4NetIO::addr_t &addr, const char *szMessage);
void RespondReference(const C4NetIO::addr_t &addr);
};
// mini HTTP client
class C4Network2HTTPClient : public C4NetIOTCP, private C4NetIO::CBClass
{
public:
C4Network2HTTPClient();
virtual ~C4Network2HTTPClient();
private:
// Address information
C4NetIO::addr_t ServerAddr, PeerAddr;
StdCopyStrBuf Server, RequestPath;
bool fBinary;
bool fBusy, fSuccess, fConnected;
size_t iDataOffset;
StdCopyBuf Request;
time_t iRequestTimeout;
// Response header data
size_t iDownloadedSize, iTotalSize;
bool fCompressed;
// Event queue to use for notify when something happens
class C4InteractiveThread *pNotify;
protected:
StdCopyBuf ResultBin; // set if fBinary
StdCopyStrBuf ResultString; // set if !fBinary
protected:
// Overridden
virtual void PackPacket(const C4NetIOPacket &rPacket, StdBuf &rOutBuf);
virtual size_t UnpackPacket(const StdBuf &rInBuf, const C4NetIO::addr_t &addr);
// Callbacks
bool OnConn(const C4NetIO::addr_t &AddrPeer, const C4NetIO::addr_t &AddrConnect, const addr_t *pOwnAddr, C4NetIO *pNetIO);
void OnDisconn(const C4NetIO::addr_t &AddrPeer, C4NetIO *pNetIO, const char *szReason);
void OnPacket(const class C4NetIOPacket &rPacket, C4NetIO *pNetIO);
void ResetRequestTimeout();
virtual int32_t GetDefaultPort() { return 80; }
public:
bool Query(const StdBuf &Data, bool fBinary);
bool Query(const char *szData, bool fBinary) { return Query(StdBuf(szData, SLen(szData)), fBinary); }
bool isBusy() const { return fBusy; }
bool isSuccess() const { return fSuccess; }
bool isConnected() const { return fConnected; }
size_t getTotalSize() const { return iTotalSize; }
size_t getDownloadedSize() const { return iDownloadedSize; }
const StdBuf &getResultBin() const { assert(fBinary); return ResultBin; }
const char *getResultString() const { assert(!fBinary); return ResultString.getData(); }
const char *getServerName() const { return Server.getData(); }
const char *getRequest() const { return RequestPath.getData(); }
const C4NetIO::addr_t &getServerAddress() const { return ServerAddr; }
void Cancel(const char *szReason);
void Clear();
bool SetServer(const char *szServerAddress);
void SetNotify(class C4InteractiveThread *pnNotify) { pNotify = pnNotify; }
// Overridden
virtual bool Execute(int iMaxTime, pollfd * readyfds) { return Execute(iMaxTime); }
virtual bool Execute(int iMaxTime = TO_INF);
virtual time_t GetNextTick(time_t tNow);
virtual bool IsScheduledExecution();
private:
bool ReadHeader(StdStrBuf Data);
bool Decompress(StdBuf *pData);
};
// Loads current update url string (mini-HTTP-client)
class C4Network2UpdateClient : public C4Network2HTTPClient
{
protected:
virtual int32_t GetDefaultPort() { return C4NetStdPortHTTP; }
public:
C4Network2UpdateClient() : C4Network2HTTPClient() {}
bool QueryUpdateURL();
bool GetUpdateURL(StdStrBuf *pUpdateURL);
bool GetVersion(StdStrBuf *pVersion);
};
// Loads references + current update url string (mini-HTTP-client)
class C4Network2RefClient : public C4Network2UpdateClient
{
protected:
virtual int32_t GetDefaultPort() { return C4NetStdPortRefServer; }
public:
C4Network2RefClient() : C4Network2UpdateClient() {}
bool QueryReferences();
bool GetReferences(C4Network2Reference **&rpReferences, int32_t &rRefCount);
};
#endif // C4NETWORK2REFERENCE_H

View File

@ -513,19 +513,23 @@ void C4PacketJoinData::CompileFunc(StdCompiler *pComp)
// *** C4PacketPing
C4PacketPing::C4PacketPing(uint32_t iPacketCounter, uint32_t iRemotePacketCounter)
: iTime(GetTime()),
: tTime(GetTime()),
iPacketCounter(iPacketCounter)
{
}
uint32_t C4PacketPing::getTravelTime() const
{
return GetTime() - iTime;
return GetTime() - tTime;
}
void C4PacketPing::CompileFunc(StdCompiler *pComp)
{
pComp->Value(mkNamingAdapt(iTime, "Time", 0U));
// FIXME: the compiler can't compile 64bit integers yet, the ping will return wrong times if GetTime() returns large ints
uint32_t time;
pComp->Value(mkNamingAdapt(time, "Time", 0U));
tTime = time;
pComp->Value(mkNamingAdapt(iPacketCounter, "PacketCounter", 0U));
}

View File

@ -24,7 +24,7 @@
#include <C4windowswrapper.h>
#include <mmsystem.h>
unsigned int GetTime()
time_t GetTime()
{
return timeGetTime();
}
@ -37,7 +37,7 @@ unsigned int GetTime()
#include <time.h>
#endif
unsigned int GetTime()
time_t GetTime()
{
#ifdef __APPLE__
static time_t sec_offset;

View File

@ -1,263 +1,263 @@
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 1998-2000, 2007 Matthes Bender
* Copyright (c) 2002, 2004-2005, 2007 Sven Eberhardt
* Copyright (c) 2004-2011 Günther Brammer
* Copyright (c) 2005, 2007, 2009 Peter Wortmann
* Copyright (c) 2009-2011 Nicolas Hake
* Copyright (c) 2010 Tobias Zwick
* Copyright (c) 2010 Martin Plicht
* Copyright (c) 2010-2011 Armin Burgmeier
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de
*
* Portions might be copyrighted by other authors who have contributed
* to OpenClonk.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
* See isc_license.txt for full license and disclaimer.
*
* "Clonk" is a registered trademark of Matthes Bender.
* See clonk_trademark_license.txt for full license.
*/
/* All the ifdefs in one place (Hah, I wish) */
#ifndef INC_PLATFORMABSTRACTION
#define INC_PLATFORMABSTRACTION
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif // HAVE_CONFIG_H
// We need to #define the target Windows version selector macros before we
// including any MinGW header.
#ifdef _WIN64
# define WINVER 0x0501
# define _WIN32_WINDOWS 0x0501
# define _WIN32_WINNT 0x0501
# define _WIN32_IE 0x0501
# define _AMD64_ 1
#elif defined(_WIN32)
# define WINVER 0x0500
# define _WIN32_WINDOWS 0x0500
# define _WIN32_WINNT 0x0501
# define _WIN32_IE 0x0501
# define _X86_ 1
#endif
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#define UNICODE
#define _UNICODE
#ifndef NOMINMAX
# define NOMINMAX
#endif
#endif
#if defined(_WIN32) && !defined(USE_CONSOLE) && !defined(USE_SDL_MAINLOOP) && !defined(USE_X11) && !defined(USE_COCOA)
#define USE_WIN32_WINDOWS
#endif
#ifdef _MSC_VER
#define DEPRECATED __declspec(deprecated)
#elif defined(__GNUC__)
#define DEPRECATED __attribute__((deprecated))
#else
#define DEPRECATED
#endif
#ifdef _MSC_VER
#pragma warning(disable : 4786) // long symbol names
#pragma warning(disable: 4706)
#pragma warning(disable: 4239)
#pragma warning(disable: 4521) // multiple copy constructors specified
// Get non-standard <cmath> constants (M_PI etc.)
# define _USE_MATH_DEFINES
#endif
// C++0x nullptr
#ifdef HAVE_NULLPTR
#undef NULL
#define NULL nullptr
#endif
// Integer dataypes
#ifdef HAVE_STDINT_H
#include <stdint.h>
#elif defined(_MSC_VER)
#include <cstddef>
typedef signed __int8 int8_t;
typedef signed __int16 int16_t;
typedef signed __int32 int32_t;
typedef signed __int64 int64_t;
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
// Copied from newer stddef.h
#ifndef _INTPTR_T_DEFINED
#ifdef _WIN64
typedef __int64 intptr_t;
#else
typedef __int32 intptr_t;
#endif
#define _INTPTR_T_DEFINED
#endif
#else
#error Could not find integer datatypes!
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#else
typedef ptrdiff_t ssize_t;
#endif
#ifndef HAVE_STATIC_ASSERT
#include <boost/static_assert.hpp>
#ifndef BOOST_HAS_STATIC_ASSERT
#define static_assert(x, y) BOOST_STATIC_ASSERT(x)
#endif
#endif
#if defined(__GNUC__)
// Allow checks for correct printf-usage
#define GNUC_FORMAT_ATTRIBUTE __attribute__ ((format (printf, 1, 2)))
#define GNUC_FORMAT_ATTRIBUTE_O __attribute__ ((format (printf, 2, 3)))
#define ALWAYS_INLINE inline __attribute__ ((always_inline))
#define NORETURN __attribute__ ((noreturn))
#else
#define GNUC_FORMAT_ATTRIBUTE
#define GNUC_FORMAT_ATTRIBUTE_O
#define ALWAYS_INLINE __forceinline
#define NORETURN
#endif
// Temporary-To-Reference-Fix
#if !defined(__clang__) && defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 3))
#define ALLOW_TEMP_TO_REF(ClassName) operator ClassName & () { return *this; }
#else
#define ALLOW_TEMP_TO_REF(ClassName)
#endif
#ifdef HAVE_RVALUE_REF
# define RREF &&
#else
# define RREF &
namespace std { template<typename T> inline T &move (T &t) { return t; } }
#endif
#if defined(_DEBUG) && defined(_MSC_VER)
// use inline assembler to invoke the "breakpoint exception"
# define BREAKPOINT_HERE __debugbreak()
#elif defined(_DEBUG) && defined(__GNUC__)
# define BREAKPOINT_HERE asm volatile("int $3")
#elif defined(_DEBUG) && defined(HAVE_SIGNAL_H)
# include <signal.h>
# if defined(SIGTRAP)
# define BREAKPOINT_HERE raise(SIGTRAP);
# else
# define BREAKPOINT_HERE
# endif
#else
# define BREAKPOINT_HERE
#endif
#ifdef _WIN32
typedef unsigned long DWORD;
typedef unsigned char BYTE;
typedef unsigned short WORD;
#else
// Windows integer types
typedef uint32_t DWORD;
typedef uint8_t BYTE;
typedef uint16_t WORD;
#include <strings.h>
inline int stricmp(const char *s1, const char *s2)
{
return strcasecmp(s1, s2);
}
#endif //_WIN32
#ifdef _WIN64
#define C4_OS "win-x86_64"
#elif defined(_WIN32)
#define C4_OS "win-x86"
#elif defined(__linux__)
#if defined(__x86_64__)
#define C4_OS "linux-x86_64"
#else
#define C4_OS "linux-x86"
#endif
#elif defined(__APPLE__)
#define C4_OS "mac-x86"
#else
#define C4_OS ""
#endif
// delete item to the recycle bin
bool EraseItemSafe(const char *szFilename);
// Check whether the OS is "German"
bool IsGermanSystem();
// open a weblink in an external browser
bool OpenURL(const char* szURL);
// Get a monotonically increasing timestamp in milliseconds
unsigned int GetTime();
#ifdef _WIN32
#include <io.h>
#define F_OK 0
#else
#include <dirent.h>
#include <limits.h>
#define _O_BINARY 0
#define _MAX_PATH PATH_MAX
#define _MAX_FNAME NAME_MAX
bool CopyFile(const char *szSource, const char *szTarget, bool FailIfExists);
#endif
#include <fcntl.h>
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
#endif
#ifdef _WIN32
#define DirSep "\\"
#define DirectorySeparator '\\'
#define AltDirectorySeparator '/'
#else
#define DirSep "/"
#define DirectorySeparator '/'
#define AltDirectorySeparator '\\'
#endif
#endif // INC_PLATFORMABSTRACTION
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 1998-2000, 2007 Matthes Bender
* Copyright (c) 2002, 2004-2005, 2007 Sven Eberhardt
* Copyright (c) 2004-2011 Günther Brammer
* Copyright (c) 2005, 2007, 2009 Peter Wortmann
* Copyright (c) 2009-2011 Nicolas Hake
* Copyright (c) 2010 Tobias Zwick
* Copyright (c) 2010 Martin Plicht
* Copyright (c) 2010-2011 Armin Burgmeier
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de
*
* Portions might be copyrighted by other authors who have contributed
* to OpenClonk.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
* See isc_license.txt for full license and disclaimer.
*
* "Clonk" is a registered trademark of Matthes Bender.
* See clonk_trademark_license.txt for full license.
*/
/* All the ifdefs in one place (Hah, I wish) */
#ifndef INC_PLATFORMABSTRACTION
#define INC_PLATFORMABSTRACTION
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif // HAVE_CONFIG_H
// We need to #define the target Windows version selector macros before we
// including any MinGW header.
#ifdef _WIN64
# define WINVER 0x0501
# define _WIN32_WINDOWS 0x0501
# define _WIN32_WINNT 0x0501
# define _WIN32_IE 0x0501
# define _AMD64_ 1
#elif defined(_WIN32)
# define WINVER 0x0500
# define _WIN32_WINDOWS 0x0500
# define _WIN32_WINNT 0x0501
# define _WIN32_IE 0x0501
# define _X86_ 1
#endif
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#define UNICODE
#define _UNICODE
#ifndef NOMINMAX
# define NOMINMAX
#endif
#endif
#if defined(_WIN32) && !defined(USE_CONSOLE) && !defined(USE_SDL_MAINLOOP) && !defined(USE_X11) && !defined(USE_COCOA)
#define USE_WIN32_WINDOWS
#endif
#ifdef _MSC_VER
#define DEPRECATED __declspec(deprecated)
#elif defined(__GNUC__)
#define DEPRECATED __attribute__((deprecated))
#else
#define DEPRECATED
#endif
#ifdef _MSC_VER
#pragma warning(disable : 4786) // long symbol names
#pragma warning(disable: 4706)
#pragma warning(disable: 4239)
#pragma warning(disable: 4521) // multiple copy constructors specified
// Get non-standard <cmath> constants (M_PI etc.)
# define _USE_MATH_DEFINES
#endif
// C++0x nullptr
#ifdef HAVE_NULLPTR
#undef NULL
#define NULL nullptr
#endif
// Integer dataypes
#ifdef HAVE_STDINT_H
#include <stdint.h>
#elif defined(_MSC_VER)
#include <cstddef>
typedef signed __int8 int8_t;
typedef signed __int16 int16_t;
typedef signed __int32 int32_t;
typedef signed __int64 int64_t;
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
// Copied from newer stddef.h
#ifndef _INTPTR_T_DEFINED
#ifdef _WIN64
typedef __int64 intptr_t;
#else
typedef __int32 intptr_t;
#endif
#define _INTPTR_T_DEFINED
#endif
#else
#error Could not find integer datatypes!
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#else
typedef ptrdiff_t ssize_t;
#endif
#ifndef HAVE_STATIC_ASSERT
#include <boost/static_assert.hpp>
#ifndef BOOST_HAS_STATIC_ASSERT
#define static_assert(x, y) BOOST_STATIC_ASSERT(x)
#endif
#endif
#if defined(__GNUC__)
// Allow checks for correct printf-usage
#define GNUC_FORMAT_ATTRIBUTE __attribute__ ((format (printf, 1, 2)))
#define GNUC_FORMAT_ATTRIBUTE_O __attribute__ ((format (printf, 2, 3)))
#define ALWAYS_INLINE inline __attribute__ ((always_inline))
#define NORETURN __attribute__ ((noreturn))
#else
#define GNUC_FORMAT_ATTRIBUTE
#define GNUC_FORMAT_ATTRIBUTE_O
#define ALWAYS_INLINE __forceinline
#define NORETURN
#endif
// Temporary-To-Reference-Fix
#if !defined(__clang__) && defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 3))
#define ALLOW_TEMP_TO_REF(ClassName) operator ClassName & () { return *this; }
#else
#define ALLOW_TEMP_TO_REF(ClassName)
#endif
#ifdef HAVE_RVALUE_REF
# define RREF &&
#else
# define RREF &
namespace std { template<typename T> inline T &move (T &t) { return t; } }
#endif
#if defined(_DEBUG) && defined(_MSC_VER)
// use inline assembler to invoke the "breakpoint exception"
# define BREAKPOINT_HERE __debugbreak()
#elif defined(_DEBUG) && defined(__GNUC__)
# define BREAKPOINT_HERE asm volatile("int $3")
#elif defined(_DEBUG) && defined(HAVE_SIGNAL_H)
# include <signal.h>
# if defined(SIGTRAP)
# define BREAKPOINT_HERE raise(SIGTRAP);
# else
# define BREAKPOINT_HERE
# endif
#else
# define BREAKPOINT_HERE
#endif
#ifdef _WIN32
typedef unsigned long DWORD;
typedef unsigned char BYTE;
typedef unsigned short WORD;
#else
// Windows integer types
typedef uint32_t DWORD;
typedef uint8_t BYTE;
typedef uint16_t WORD;
#include <strings.h>
inline int stricmp(const char *s1, const char *s2)
{
return strcasecmp(s1, s2);
}
#endif //_WIN32
#ifdef _WIN64
#define C4_OS "win-x86_64"
#elif defined(_WIN32)
#define C4_OS "win-x86"
#elif defined(__linux__)
#if defined(__x86_64__)
#define C4_OS "linux-x86_64"
#else
#define C4_OS "linux-x86"
#endif
#elif defined(__APPLE__)
#define C4_OS "mac-x86"
#else
#define C4_OS ""
#endif
// delete item to the recycle bin
bool EraseItemSafe(const char *szFilename);
// Check whether the OS is "German"
bool IsGermanSystem();
// open a weblink in an external browser
bool OpenURL(const char* szURL);
// Get a monotonically increasing timestamp in milliseconds
time_t GetTime();
#ifdef _WIN32
#include <io.h>
#define F_OK 0
#else
#include <dirent.h>
#include <limits.h>
#define _O_BINARY 0
#define _MAX_PATH PATH_MAX
#define _MAX_FNAME NAME_MAX
bool CopyFile(const char *szSource, const char *szTarget, bool FailIfExists);
#endif
#include <fcntl.h>
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
#endif
#ifdef _WIN32
#define DirSep "\\"
#define DirectorySeparator '\\'
#define AltDirectorySeparator '/'
#else
#define DirSep "/"
#define DirectorySeparator '/'
#define AltDirectorySeparator '\\'
#endif
#endif // INC_PLATFORMABSTRACTION

View File

@ -65,17 +65,17 @@ bool StdSchedulerProc::ExecuteUntil(int iTimeout)
if (!Execute())
return false;
// Calculate endpoint
unsigned int iStopTime = GetTime() + iTimeout;
time_t tStopTime = GetTime() + iTimeout;
for (;;)
{
// Call execute with given timeout
if (!Execute(Max(iTimeout, 0)))
return false;
// Calculate timeout
unsigned int iTime = GetTime();
if (iTime >= iStopTime)
time_t tTime = GetTime();
if (tTime >= tStopTime)
break;
iTimeout = int(iStopTime - iTime);
iTimeout = int(tStopTime - tTime);
}
// All ok.
return true;
@ -175,11 +175,18 @@ bool StdScheduler::ScheduleProcs(int iTimeout)
if (!iProcCnt) return false;
// Get timeout
int i; int iProcTick; int Now = GetTime();
int i;
time_t tProcTick;
time_t tNow = GetTime();
for (i = 0; i < iProcCnt; i++)
if ((iProcTick = ppProcs[i]->GetNextTick(Now)) >= 0)
if (iTimeout == -1 || iTimeout + Now > iProcTick)
iTimeout = Max(iProcTick - Now, 0);
{
if(ppProcs[i]->IsScheduledExecution())
{
tProcTick = ppProcs[i]->GetNextTick(tNow);
if (iTimeout == -1 || iTimeout + tNow > tProcTick)
iTimeout = Max<time_t>(tProcTick - tNow, 0);
}
}
#ifdef STDSCHEDULER_USE_EVENTS
@ -225,16 +232,19 @@ bool StdScheduler::ScheduleProcs(int iTimeout)
}
// Execute all processes with timeout
Now = GetTime();
tNow = GetTime();
for (i = 0; i < iProcCnt; i++)
{
iProcTick = ppProcs[i]->GetNextTick(Now);
if (iProcTick >= 0 && iProcTick <= Now)
if (!ppProcs[i]->Execute(0))
{
OnError(ppProcs[i]);
fSuccess = false;
}
if(ppProcs[i]->IsScheduledExecution())
{
tProcTick = ppProcs[i]->GetNextTick(tNow);
if (tProcTick <= tNow)
if (!ppProcs[i]->Execute(0))
{
OnError(ppProcs[i]);
fSuccess = false;
}
}
}
#else
@ -260,46 +270,49 @@ bool StdScheduler::ScheduleProcs(int iTimeout)
if (cnt >= 0)
{
bool any_executed = false;
Now = GetTime();
tNow = GetTime();
// Which process?
for (i = 0; i < iProcCnt; i++)
{
iProcTick = ppProcs[i]->GetNextTick(Now);
if (iProcTick >= 0 && iProcTick <= Now)
if (ppProcs[i]->IsScheduledExecution())
{
struct pollfd * pfd = 0;
if (fds_for_proc.find(ppProcs[i]) != fds_for_proc.end())
pfd = &fds[fds_for_proc[ppProcs[i]].first];
if (!ppProcs[i]->Execute(0, pfd))
tProcTick = ppProcs[i]->GetNextTick(tNow);
if (tProcTick <= tNow)
{
OnError(ppProcs[i]);
fSuccess = false;
}
any_executed = true;
continue;
}
// no fds?
if (fds_for_proc.find(ppProcs[i]) == fds_for_proc.end())
continue;
// Check intersection
unsigned int begin = fds_for_proc[ppProcs[i]].first;
unsigned int end = fds_for_proc[ppProcs[i]].second;
for (unsigned int j = begin; j < end; ++j)
{
if (fds[j].events & fds[j].revents)
{
if (any_executed && ppProcs[i]->IsLowPriority())
break;
if (!ppProcs[i]->Execute(0, &fds[begin]))
struct pollfd * pfd = 0;
if (fds_for_proc.find(ppProcs[i]) != fds_for_proc.end())
pfd = &fds[fds_for_proc[ppProcs[i]].first];
if (!ppProcs[i]->Execute(0, pfd))
{
OnError(ppProcs[i]);
fSuccess = false;
}
any_executed = true;
// the list of procs might have been changed, but procs must be in both ppProcs and
// fds_for_proc to be executed, which prevents execution of any proc not polled this round
// or deleted. Some procs might be skipped or executed twice, but that should be save.
break;
continue;
}
// no fds?
if (fds_for_proc.find(ppProcs[i]) == fds_for_proc.end())
continue;
// Check intersection
unsigned int begin = fds_for_proc[ppProcs[i]].first;
unsigned int end = fds_for_proc[ppProcs[i]].second;
for (unsigned int j = begin; j < end; ++j)
{
if (fds[j].events & fds[j].revents)
{
if (any_executed && ppProcs[i]->IsLowPriority())
break;
if (!ppProcs[i]->Execute(0, &fds[begin]))
{
OnError(ppProcs[i]);
fSuccess = false;
}
any_executed = true;
// the list of procs might have been changed, but procs must be in both ppProcs and
// fds_for_proc to be executed, which prevents execution of any proc not polled this round
// or deleted. Some procs might be skipped or executed twice, but that should be save.
break;
}
}
}
}

View File

@ -47,12 +47,6 @@ struct pollfd;
#endif // HAVE_PTHREAD
#endif // _WIN32
// helper
inline int MaxTimeout(int iTimeout1, int iTimeout2)
{
return (iTimeout1 == -1 || iTimeout2 == -1) ? -1 : Max(iTimeout1, iTimeout2);
}
typedef struct _GMainLoop GMainLoop;
// Abstract class for a process
@ -76,8 +70,9 @@ public:
#endif
// Call Execute() after this time has elapsed
// -1 means no timeout (infinity).
virtual int GetNextTick(int Now) { return -1; }
virtual time_t GetNextTick(time_t tNow) { return 0; };
virtual bool IsScheduledExecution() { return false; }
// Is the process signal currently set?
bool IsSignaled();
@ -91,30 +86,33 @@ public:
class CStdTimerProc : public StdSchedulerProc
{
public:
CStdTimerProc(uint32_t iDelay) : iLastTimer(0), iDelay(iDelay) { }
CStdTimerProc(uint32_t iDelay) : tLastTimer(0), iDelay(iDelay) { }
~CStdTimerProc() { }
private:
uint32_t iLastTimer, iDelay;
time_t tLastTimer;
uint32_t iDelay;
public:
void Set() { iLastTimer = 0; }
void Set() { tLastTimer = 0; }
void SetDelay(uint32_t inDelay) { iDelay = inDelay; }
bool CheckAndReset()
{
if (GetTime() < iLastTimer + iDelay) return false;
if (GetTime() < tLastTimer + iDelay) return false;
// Compensate light drifting
uint32_t iTime = GetTime();
uint32_t iDrift = iTime - iLastTimer - iDelay; // >= 0 because of Check()
iLastTimer = iTime - Min(iDrift, iDelay / 2);
time_t tTime = GetTime();
uint32_t iDrift = tTime - tLastTimer - iDelay; // >= 0 because of Check()
tLastTimer = tTime - Min(iDrift, iDelay / 2);
return true;
}
// StdSchedulerProc override
virtual int GetNextTick(int Now)
virtual time_t GetNextTick(time_t tNow)
{
return iLastTimer + iDelay;
return tLastTimer + iDelay;
}
virtual bool IsScheduledExecution() { return true; }
};
// A simple alertable proc