forked from Mirrors/openclonk
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
parent
ecf538cd1f
commit
7b9c1d5a9e
|
@ -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.
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
@ -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
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue