ddnet/src/engine/shared/network_conn.cpp

532 lines
14 KiB
C++
Raw Normal View History

2010-11-20 10:37:14 +00:00
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
/* If you are missing that file, acquire a complete release at teeworlds.com. */
2010-05-29 07:25:38 +00:00
#include "config.h"
#include "network.h"
#include <base/system.h>
2009-10-27 14:38:53 +00:00
2017-03-21 10:24:44 +00:00
SECURITY_TOKEN ToSecurityToken(unsigned char *pData)
{
return (int)pData[0] | (pData[1] << 8) | (pData[2] << 16) | (pData[3] << 24);
}
2009-10-27 14:38:53 +00:00
void CNetConnection::ResetStats()
{
mem_zero(&m_Stats, sizeof(m_Stats));
mem_zero(&m_PeerAddr, sizeof(m_PeerAddr));
m_LastUpdateTime = 0;
2009-10-27 14:38:53 +00:00
}
2015-08-23 16:12:13 +00:00
void CNetConnection::Reset(bool Rejoin)
2009-10-27 14:38:53 +00:00
{
m_Sequence = 0;
m_Ack = 0;
m_PeerAck = 0;
2009-10-27 14:38:53 +00:00
m_RemoteClosed = 0;
if(!Rejoin)
2015-08-23 16:12:13 +00:00
{
2015-08-28 10:23:37 +00:00
m_TimeoutProtected = false;
m_TimeoutSituation = false;
2015-08-23 16:12:13 +00:00
m_State = NET_CONNSTATE_OFFLINE;
m_Token = -1;
m_SecurityToken = NET_SECURITY_TOKEN_UNKNOWN;
2020-03-29 02:36:38 +00:00
m_Sixup = false;
2015-08-23 16:12:13 +00:00
}
2009-10-27 14:38:53 +00:00
m_LastSendTime = 0;
m_LastRecvTime = 0;
//m_LastUpdateTime = 0;
2015-08-23 16:12:13 +00:00
mem_zero(&m_aConnectAddrs, sizeof(m_aConnectAddrs));
m_NumConnectAddrs = 0;
//mem_zero(&m_PeerAddr, sizeof(m_PeerAddr));
m_UnknownSeq = false;
2009-10-27 14:38:53 +00:00
m_Buffer.Init();
2009-10-27 14:38:53 +00:00
mem_zero(&m_Construct, sizeof(m_Construct));
}
const char *CNetConnection::ErrorString()
{
2020-10-27 17:57:14 +00:00
return m_aErrorString;
2009-10-27 14:38:53 +00:00
}
void CNetConnection::SetError(const char *pString)
{
2022-07-09 16:14:56 +00:00
str_copy(m_aErrorString, pString);
2009-10-27 14:38:53 +00:00
}
void CNetConnection::Init(NETSOCKET Socket, bool BlockCloseMsg)
2009-10-27 14:38:53 +00:00
{
Reset();
ResetStats();
2009-10-27 14:38:53 +00:00
m_Socket = Socket;
m_BlockCloseMsg = BlockCloseMsg;
2020-10-27 17:57:14 +00:00
mem_zero(m_aErrorString, sizeof(m_aErrorString));
2009-10-27 14:38:53 +00:00
}
void CNetConnection::AckChunks(int Ack)
{
2022-02-14 23:12:52 +00:00
while(true)
2009-10-27 14:38:53 +00:00
{
CNetChunkResend *pResend = m_Buffer.First();
if(!pResend)
break;
2009-10-27 14:38:53 +00:00
if(CNetBase::IsSeqInBackroom(pResend->m_Sequence, Ack))
m_Buffer.PopFirst();
else
break;
}
}
void CNetConnection::SignalResend()
{
m_Construct.m_Flags |= NET_PACKETFLAG_RESEND;
}
int CNetConnection::Flush()
{
int NumChunks = m_Construct.m_NumChunks;
if(!NumChunks && !m_Construct.m_Flags)
return 0;
2010-05-29 07:25:38 +00:00
// send of the packets
2009-10-27 14:38:53 +00:00
m_Construct.m_Ack = m_Ack;
2020-03-29 02:36:38 +00:00
CNetBase::SendPacket(m_Socket, &m_PeerAddr, &m_Construct, m_SecurityToken, m_Sixup);
2010-05-29 07:25:38 +00:00
// update send times
2009-10-27 14:38:53 +00:00
m_LastSendTime = time_get();
2010-05-29 07:25:38 +00:00
// clear construct so we can start building a new package
2009-10-27 14:38:53 +00:00
mem_zero(&m_Construct, sizeof(m_Construct));
return NumChunks;
}
2010-05-29 07:25:38 +00:00
int CNetConnection::QueueChunkEx(int Flags, int DataSize, const void *pData, int Sequence)
2009-10-27 14:38:53 +00:00
{
if(m_State == NET_CONNSTATE_OFFLINE || m_State == NET_CONNSTATE_ERROR)
return -1;
2009-10-27 14:38:53 +00:00
unsigned char *pChunkData;
2010-05-29 07:25:38 +00:00
// check if we have space for it, if not, flush the connection
if(m_Construct.m_DataSize + DataSize + NET_MAX_CHUNKHEADERSIZE > (int)sizeof(m_Construct.m_aChunkData) - (int)sizeof(SECURITY_TOKEN))
2009-10-27 14:38:53 +00:00
Flush();
2010-05-29 07:25:38 +00:00
// pack all the data
2009-10-27 14:38:53 +00:00
CNetChunkHeader Header;
Header.m_Flags = Flags;
Header.m_Size = DataSize;
Header.m_Sequence = Sequence;
pChunkData = &m_Construct.m_aChunkData[m_Construct.m_DataSize];
2020-03-29 02:36:38 +00:00
pChunkData = Header.Pack(pChunkData, m_Sixup ? 6 : 4);
2009-10-27 14:38:53 +00:00
mem_copy(pChunkData, pData, DataSize);
pChunkData += DataSize;
2010-05-29 07:25:38 +00:00
//
2009-10-27 14:38:53 +00:00
m_Construct.m_NumChunks++;
m_Construct.m_DataSize = (int)(pChunkData - m_Construct.m_aChunkData);
2018-02-04 15:00:47 +00:00
// set packet flags as well
if(Flags & NET_CHUNKFLAG_VITAL && !(Flags & NET_CHUNKFLAG_RESEND))
2009-10-27 14:38:53 +00:00
{
2010-05-29 07:25:38 +00:00
// save packet if we need to resend
CNetChunkResend *pResend = m_Buffer.Allocate(sizeof(CNetChunkResend) + DataSize);
2009-10-27 14:38:53 +00:00
if(pResend)
{
pResend->m_Sequence = Sequence;
pResend->m_Flags = Flags;
pResend->m_DataSize = DataSize;
pResend->m_pData = (unsigned char *)(pResend + 1);
2009-10-27 14:38:53 +00:00
pResend->m_FirstSendTime = time_get();
pResend->m_LastSendTime = pResend->m_FirstSendTime;
mem_copy(pResend->m_pData, pData, DataSize);
}
else
{
2013-07-30 20:48:31 +00:00
// out of buffer, don't save the packet and hope nobody will ask for resend
2010-05-29 07:25:38 +00:00
return -1;
2009-10-27 14:38:53 +00:00
}
}
2010-05-29 07:25:38 +00:00
return 0;
2009-10-27 14:38:53 +00:00
}
2010-05-29 07:25:38 +00:00
int CNetConnection::QueueChunk(int Flags, int DataSize, const void *pData)
2009-10-27 14:38:53 +00:00
{
if(Flags & NET_CHUNKFLAG_VITAL)
m_Sequence = (m_Sequence + 1) % NET_MAX_SEQUENCE;
2010-05-29 07:25:38 +00:00
return QueueChunkEx(Flags, DataSize, pData, m_Sequence);
2009-10-27 14:38:53 +00:00
}
void CNetConnection::SendConnect()
{
// send the connect message
m_LastSendTime = time_get();
for(int i = 0; i < m_NumConnectAddrs; i++)
{
CNetBase::SendControlMsg(m_Socket, &m_aConnectAddrs[i], m_Ack, NET_CTRLMSG_CONNECT, SECURITY_TOKEN_MAGIC, sizeof(SECURITY_TOKEN_MAGIC), m_SecurityToken, m_Sixup);
}
}
2009-10-27 14:38:53 +00:00
void CNetConnection::SendControl(int ControlMsg, const void *pExtra, int ExtraSize)
{
2010-05-29 07:25:38 +00:00
// send the control message
2009-10-27 14:38:53 +00:00
m_LastSendTime = time_get();
2020-03-29 02:36:38 +00:00
CNetBase::SendControlMsg(m_Socket, &m_PeerAddr, m_Ack, ControlMsg, pExtra, ExtraSize, m_SecurityToken, m_Sixup);
2009-10-27 14:38:53 +00:00
}
void CNetConnection::ResendChunk(CNetChunkResend *pResend)
{
QueueChunkEx(pResend->m_Flags | NET_CHUNKFLAG_RESEND, pResend->m_DataSize, pResend->m_pData, pResend->m_Sequence);
2009-10-27 14:38:53 +00:00
pResend->m_LastSendTime = time_get();
}
void CNetConnection::Resend()
{
2010-05-29 07:25:38 +00:00
for(CNetChunkResend *pResend = m_Buffer.First(); pResend; pResend = m_Buffer.Next(pResend))
2009-10-27 14:38:53 +00:00
ResendChunk(pResend);
}
int CNetConnection::Connect(const NETADDR *pAddr, int NumAddrs)
2009-10-27 14:38:53 +00:00
{
if(State() != NET_CONNSTATE_OFFLINE)
return -1;
2010-05-29 07:25:38 +00:00
// init connection
2009-10-27 14:38:53 +00:00
Reset();
mem_zero(&m_PeerAddr, sizeof(m_PeerAddr));
for(int i = 0; i < NumAddrs; i++)
{
m_aConnectAddrs[i] = pAddr[i];
}
m_NumConnectAddrs = NumAddrs;
2020-10-27 17:57:14 +00:00
mem_zero(m_aErrorString, sizeof(m_aErrorString));
2009-10-27 14:38:53 +00:00
m_State = NET_CONNSTATE_CONNECT;
SendConnect();
2009-10-27 14:38:53 +00:00
return 0;
}
void CNetConnection::Disconnect(const char *pReason)
{
if(State() == NET_CONNSTATE_OFFLINE)
return;
if(m_RemoteClosed == 0)
{
2016-07-08 15:00:47 +00:00
if(!m_TimeoutSituation)
{
if(pReason)
SendControl(NET_CTRLMSG_CLOSE, pReason, str_length(pReason) + 1);
2016-07-08 15:00:47 +00:00
else
SendControl(NET_CTRLMSG_CLOSE, 0, 0);
}
2009-10-27 14:38:53 +00:00
2020-10-27 17:57:14 +00:00
if(pReason != m_aErrorString)
{
2020-10-27 17:57:14 +00:00
m_aErrorString[0] = 0;
if(pReason)
2022-07-09 16:14:56 +00:00
str_copy(m_aErrorString, pReason);
}
2009-10-27 14:38:53 +00:00
}
2009-10-27 14:38:53 +00:00
Reset();
}
Mark parameters as `const` when possible According to cppchecker's `constParameter` error: ``` src\engine\gfx\image_manipulation.cpp:7:58: style: Parameter 'pSrc' can be declared as pointer to const [constParameter] static void Dilate(int w, int h, int BPP, unsigned char *pSrc, unsigned char *pDest, unsigned char AlphaThreshold = TW_DILATE_ALPHA_THRESHOLD) ^ src\engine\gfx\image_manipulation.cpp:58:67: style: Parameter 'pSrc' can be declared as pointer to const [constParameter] static void CopyColorValues(int w, int h, int BPP, unsigned char *pSrc, unsigned char *pDest) ^ src\engine\shared\network_conn.cpp:241:42: style: Parameter 'Addr' can be declared as reference to const [constParameter] void CNetConnection::DirectInit(NETADDR &Addr, SECURITY_TOKEN SecurityToken, SECURITY_TOKEN Token, bool Sixup) ^ src\base\system.cpp:4060:71: style: Parameter 'random' can be declared as pointer to const [constParameter] void generate_password(char *buffer, unsigned length, unsigned short *random, unsigned random_length) ^ src\engine\client\backend\vulkan\backend_vulkan.cpp:263:38: style: Parameter 'AllocatedMemory' can be declared as reference to const [constParameter] void Free(SMemoryHeapQueueElement &AllocatedMemory) ^ src\engine\client\backend\vulkan\backend_vulkan.cpp:1708:47: style: Parameter 'ImgExtent' can be declared as reference to const [constParameter] static size_t ImageMipLevelCount(VkExtent3D &ImgExtent) ^ src\engine\client\backend\vulkan\backend_vulkan.cpp:2801:29: style: Parameter 'Image' can be declared as reference to const [constParameter] void ImageBarrier(VkImage &Image, size_t MipMapBase, size_t MipMapCount, size_t LayerBase, size_t LayerCount, VkFormat Format, VkImageLayout OldLayout, VkImageLayout NewLayout) ^ src\engine\client\backend\vulkan\backend_vulkan.cpp:6495:46: style: Parameter 'ExecBuffer' can be declared as reference to const [constParameter] void Cmd_Clear(SRenderCommandExecuteBuffer &ExecBuffer, const CCommandBuffer::SCommand_Clear *pCommand) ^ src\game\client\components\skins.cpp:83:72: style: Parameter 'pImg' can be declared as pointer to const [constParameter] static void CheckMetrics(CSkin::SSkinMetricVariable &Metrics, uint8_t *pImg, int ImgWidth, int ImgX, int ImgY, int CheckWidth, int CheckHeight) ^ src\game\client\prediction\entities\character.h:106:37: style: Parameter 'pNewInput' can be declared as pointer to const [constParameter] void SetInput(CNetObj_PlayerInput *pNewInput) ^ src\game\client\prediction\gameworld.cpp:245:106: style: Parameter 'pNotThis' can be declared as pointer to const [constParameter] CCharacter *CGameWorld::IntersectCharacter(vec2 Pos0, vec2 Pos1, float Radius, vec2 &NewPos, CCharacter *pNotThis, int CollideWith, class CCharacter *pThisOnly) ^ src\game\client\prediction\gameworld.cpp:245:151: style: Parameter 'pThisOnly' can be declared as pointer to const [constParameter] CCharacter *CGameWorld::IntersectCharacter(vec2 Pos0, vec2 Pos1, float Radius, vec2 &NewPos, CCharacter *pNotThis, int CollideWith, class CCharacter *pThisOnly) ^ src\game\client\prediction\gameworld.cpp:283:116: style: Parameter 'pNotThis' can be declared as pointer to const [constParameter] std::list<class CCharacter *> CGameWorld::IntersectedCharacters(vec2 Pos0, vec2 Pos1, float Radius, class CEntity *pNotThis) ^ src\game\client\ui.cpp:522:180: style: Parameter 'pReadCursor' can be declared as pointer to const [constParameter] void CUI::DoLabel(CUIElement::SUIElementRect &RectEl, const CUIRect *pRect, const char *pText, float Size, int Align, const SLabelProperties &LabelProps, int StrLen, CTextCursor *pReadCursor) ^ src\game\client\ui_scrollregion.cpp:23:86: style: Parameter 'pParams' can be declared as pointer to const [constParameter] void CScrollRegion::Begin(CUIRect *pClipRect, vec2 *pOutOffset, CScrollRegionParams *pParams) ^ src\game\server\scoreworker.h:239:29: style: Parameter 'aTimeCp' can be declared as const array [constParameter] void Set(float Time, float aTimeCp[NUM_CHECKPOINTS]) ^ src\game\server\score.cpp:135:80: style: Parameter 'aTimeCp' can be declared as const array [constParameter] void CScore::SaveScore(int ClientID, float Time, const char *pTimestamp, float aTimeCp[NUM_CHECKPOINTS], bool NotEligible) ^ src\game\server\teeinfo.cpp:40:57: style: Parameter 'pUseCustomColors' can be declared as pointer to const [constParameter] CTeeInfo::CTeeInfo(const char *apSkinPartNames[6], int *pUseCustomColors, int *pSkinPartColors) ^ src\game\server\teeinfo.cpp:40:80: style: Parameter 'pSkinPartColors' can be declared as pointer to const [constParameter] CTeeInfo::CTeeInfo(const char *apSkinPartNames[6], int *pUseCustomColors, int *pSkinPartColors) ^ ```
2022-11-13 14:32:53 +00:00
void CNetConnection::DirectInit(const NETADDR &Addr, SECURITY_TOKEN SecurityToken, SECURITY_TOKEN Token, bool Sixup)
2015-08-12 20:43:37 +00:00
{
Reset();
m_State = NET_CONNSTATE_ONLINE;
m_PeerAddr = Addr;
2020-10-27 17:57:14 +00:00
mem_zero(m_aErrorString, sizeof(m_aErrorString));
2015-08-12 20:43:37 +00:00
2021-06-23 05:05:49 +00:00
int64_t Now = time_get();
2015-08-12 20:43:37 +00:00
m_LastSendTime = Now;
m_LastRecvTime = Now;
m_LastUpdateTime = Now;
m_SecurityToken = SecurityToken;
2020-03-29 02:36:38 +00:00
m_Token = Token;
m_Sixup = Sixup;
2015-08-12 20:43:37 +00:00
}
int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr, SECURITY_TOKEN SecurityToken)
2009-10-27 14:38:53 +00:00
{
// Disregard packets from the wrong address, unless we don't know our peer yet.
if(State() != NET_CONNSTATE_OFFLINE && State() != NET_CONNSTATE_CONNECT && *pAddr != m_PeerAddr)
{
return 0;
}
if(!m_Sixup && State() != NET_CONNSTATE_OFFLINE && m_SecurityToken != NET_SECURITY_TOKEN_UNKNOWN && m_SecurityToken != NET_SECURITY_TOKEN_UNSUPPORTED)
{
// supposed to have a valid token in this packet, check it
if(pPacket->m_DataSize < (int)sizeof(m_SecurityToken))
return 0;
pPacket->m_DataSize -= sizeof(m_SecurityToken);
if(m_SecurityToken != ToSecurityToken(&pPacket->m_aChunkData[pPacket->m_DataSize]))
{
if(g_Config.m_Debug)
dbg_msg("security", "token mismatch, expected %d got %d", m_SecurityToken, ToSecurityToken(&pPacket->m_aChunkData[pPacket->m_DataSize]));
return 0;
}
}
2020-03-29 02:36:38 +00:00
if(m_Sixup && SecurityToken != m_Token)
return 0;
// check if actual ack value is valid(own sequence..latest peer ack)
if(m_Sequence >= m_PeerAck)
{
if(pPacket->m_Ack < m_PeerAck || pPacket->m_Ack > m_Sequence)
return 0;
}
else
{
if(pPacket->m_Ack < m_PeerAck && pPacket->m_Ack > m_Sequence)
return 0;
}
m_PeerAck = pPacket->m_Ack;
2021-06-23 05:05:49 +00:00
int64_t Now = time_get();
2010-05-29 07:25:38 +00:00
// check if resend is requested
if(pPacket->m_Flags & NET_PACKETFLAG_RESEND)
2009-10-27 14:38:53 +00:00
Resend();
2010-05-29 07:25:38 +00:00
//
if(pPacket->m_Flags & NET_PACKETFLAG_CONTROL)
2009-10-27 14:38:53 +00:00
{
int CtrlMsg = pPacket->m_aChunkData[0];
2009-10-27 14:38:53 +00:00
if(CtrlMsg == NET_CTRLMSG_CLOSE)
{
bool IsPeer;
if(m_State != NET_CONNSTATE_CONNECT)
{
IsPeer = m_PeerAddr == *pAddr;
}
else
{
IsPeer = false;
for(int i = 0; i < m_NumConnectAddrs; i++)
{
IsPeer = IsPeer || m_aConnectAddrs[i] == *pAddr;
}
}
if(IsPeer)
2009-10-27 14:38:53 +00:00
{
2010-05-29 07:25:38 +00:00
m_State = NET_CONNSTATE_ERROR;
m_RemoteClosed = 1;
2020-10-27 17:57:14 +00:00
char aStr[128] = {0};
if(pPacket->m_DataSize > 1)
2010-05-29 07:25:38 +00:00
{
// make sure to sanitize the error string form the other party
str_copy(aStr, (char *)&pPacket->m_aChunkData[1], minimum(pPacket->m_DataSize, (int)sizeof(aStr)));
2020-11-18 13:31:05 +00:00
str_sanitize_cc(aStr);
}
if(!m_BlockCloseMsg)
{
2010-05-29 07:25:38 +00:00
// set the error string
2020-10-27 17:57:14 +00:00
SetError(aStr);
2010-05-29 07:25:38 +00:00
}
2010-05-29 07:25:38 +00:00
if(g_Config.m_Debug)
2020-10-27 17:57:14 +00:00
dbg_msg("conn", "closed reason='%s'", aStr);
2009-10-27 14:38:53 +00:00
}
return 0;
2009-10-27 14:38:53 +00:00
}
else
{
if(State() == NET_CONNSTATE_OFFLINE)
2009-10-27 14:38:53 +00:00
{
if(CtrlMsg == NET_CTRLMSG_CONNECT)
{
2018-10-08 18:04:04 +00:00
if(net_addr_comp_noport(&m_PeerAddr, pAddr) == 0 && time_get() - m_LastUpdateTime < time_freq() * 3)
return 0;
2010-05-29 07:25:38 +00:00
// send response and init connection
2009-10-27 14:38:53 +00:00
Reset();
m_State = NET_CONNSTATE_PENDING;
m_PeerAddr = *pAddr;
2020-10-27 17:57:14 +00:00
mem_zero(m_aErrorString, sizeof(m_aErrorString));
2010-05-29 07:25:38 +00:00
m_LastSendTime = Now;
m_LastRecvTime = Now;
m_LastUpdateTime = Now;
if(m_SecurityToken == NET_SECURITY_TOKEN_UNKNOWN && pPacket->m_DataSize >= (int)(1 + sizeof(SECURITY_TOKEN_MAGIC) + sizeof(m_SecurityToken)) && !mem_comp(&pPacket->m_aChunkData[1], SECURITY_TOKEN_MAGIC, sizeof(SECURITY_TOKEN_MAGIC)))
{
2020-03-29 02:36:38 +00:00
m_SecurityToken = NET_SECURITY_TOKEN_UNSUPPORTED;
if(g_Config.m_Debug)
dbg_msg("security", "generated token %d", m_SecurityToken);
}
else
{
if(g_Config.m_Debug)
dbg_msg("security", "token not supported by client (packet size %d)", pPacket->m_DataSize);
m_SecurityToken = NET_SECURITY_TOKEN_UNSUPPORTED;
}
SendControl(NET_CTRLMSG_CONNECTACCEPT, SECURITY_TOKEN_MAGIC, sizeof(SECURITY_TOKEN_MAGIC));
2010-05-29 07:25:38 +00:00
if(g_Config.m_Debug)
dbg_msg("connection", "got connection, sending connect+accept");
2009-10-27 14:38:53 +00:00
}
}
else if(State() == NET_CONNSTATE_CONNECT)
{
2010-05-29 07:25:38 +00:00
// connection made
2009-10-27 14:38:53 +00:00
if(CtrlMsg == NET_CTRLMSG_CONNECTACCEPT)
{
m_PeerAddr = *pAddr;
if(m_SecurityToken == NET_SECURITY_TOKEN_UNKNOWN && pPacket->m_DataSize >= (int)(1 + sizeof(SECURITY_TOKEN_MAGIC) + sizeof(m_SecurityToken)) && !mem_comp(&pPacket->m_aChunkData[1], SECURITY_TOKEN_MAGIC, sizeof(SECURITY_TOKEN_MAGIC)))
{
m_SecurityToken = ToSecurityToken(&pPacket->m_aChunkData[1 + sizeof(SECURITY_TOKEN_MAGIC)]);
if(g_Config.m_Debug)
dbg_msg("security", "got token %d", m_SecurityToken);
}
else
{
m_SecurityToken = NET_SECURITY_TOKEN_UNSUPPORTED;
if(g_Config.m_Debug)
dbg_msg("security", "token not supported by server");
}
m_LastRecvTime = Now;
2009-10-27 14:38:53 +00:00
SendControl(NET_CTRLMSG_ACCEPT, 0, 0);
m_State = NET_CONNSTATE_ONLINE;
2010-05-29 07:25:38 +00:00
if(g_Config.m_Debug)
2009-10-27 14:38:53 +00:00
dbg_msg("connection", "got connect+accept, sending accept. connection online");
}
}
}
}
else
{
if(State() == NET_CONNSTATE_PENDING)
{
m_LastRecvTime = Now;
2009-10-27 14:38:53 +00:00
m_State = NET_CONNSTATE_ONLINE;
2010-05-29 07:25:38 +00:00
if(g_Config.m_Debug)
2009-10-27 14:38:53 +00:00
dbg_msg("connection", "connecting online");
}
}
2009-10-27 14:38:53 +00:00
if(State() == NET_CONNSTATE_ONLINE)
{
m_LastRecvTime = Now;
2009-10-27 14:38:53 +00:00
AckChunks(pPacket->m_Ack);
}
2009-10-27 14:38:53 +00:00
return 1;
}
int CNetConnection::Update()
{
2021-06-23 05:05:49 +00:00
int64_t Now = time_get();
2009-10-27 14:38:53 +00:00
if(State() == NET_CONNSTATE_ERROR && m_TimeoutSituation && (Now - m_LastRecvTime) > time_freq() * g_Config.m_ConnTimeoutProtection)
2014-08-15 15:47:38 +00:00
{
2014-08-16 13:51:25 +00:00
m_TimeoutSituation = false;
SetError("Timeout Protection over");
2014-08-15 15:47:38 +00:00
}
2014-08-09 13:37:10 +00:00
2009-10-27 14:38:53 +00:00
if(State() == NET_CONNSTATE_OFFLINE || State() == NET_CONNSTATE_ERROR)
return 0;
2014-08-16 13:51:25 +00:00
m_TimeoutSituation = false;
2010-05-29 07:25:38 +00:00
// check for timeout
2009-10-27 14:38:53 +00:00
if(State() != NET_CONNSTATE_OFFLINE &&
State() != NET_CONNSTATE_CONNECT &&
(Now - m_LastRecvTime) > time_freq() * g_Config.m_ConnTimeout)
2009-10-27 14:38:53 +00:00
{
m_State = NET_CONNSTATE_ERROR;
SetError("Timeout");
m_TimeoutSituation = true;
2009-10-27 14:38:53 +00:00
}
2010-05-29 07:25:38 +00:00
// fix resends
2009-10-27 14:38:53 +00:00
if(m_Buffer.First())
{
CNetChunkResend *pResend = m_Buffer.First();
2010-05-29 07:25:38 +00:00
// check if we have some really old stuff laying around and abort if not acked
if(Now - pResend->m_FirstSendTime > time_freq() * g_Config.m_ConnTimeout)
2009-10-27 14:38:53 +00:00
{
m_State = NET_CONNSTATE_ERROR;
char aBuf[512];
str_format(aBuf, sizeof(aBuf), "Too weak connection (not acked for %d seconds)", g_Config.m_ConnTimeout);
SetError(aBuf);
m_TimeoutSituation = true;
2009-10-27 14:38:53 +00:00
}
else
{
2018-07-10 09:29:02 +00:00
// resend packet if we haven't got it acked in 1 second
if(Now - pResend->m_LastSendTime > time_freq())
2009-10-27 14:38:53 +00:00
ResendChunk(pResend);
}
}
2018-02-04 15:00:47 +00:00
// send keep alives if nothing has happened for 250ms
2009-10-27 14:38:53 +00:00
if(State() == NET_CONNSTATE_ONLINE)
{
if(time_get() - m_LastSendTime > time_freq() / 2) // flush connection after 500ms if needed
2009-10-27 14:38:53 +00:00
{
int NumFlushedChunks = Flush();
2010-05-29 07:25:38 +00:00
if(NumFlushedChunks && g_Config.m_Debug)
2009-10-27 14:38:53 +00:00
dbg_msg("connection", "flushed connection due to timeout. %d chunks.", NumFlushedChunks);
}
if(time_get() - m_LastSendTime > time_freq())
2009-10-27 14:38:53 +00:00
SendControl(NET_CTRLMSG_KEEPALIVE, 0, 0);
}
else if(State() == NET_CONNSTATE_CONNECT)
{
if(time_get() - m_LastSendTime > time_freq() / 2) // send a new connect every 500ms
SendConnect();
2009-10-27 14:38:53 +00:00
}
else if(State() == NET_CONNSTATE_PENDING)
{
if(time_get() - m_LastSendTime > time_freq() / 2) // send a new connect/accept every 500ms
SendControl(NET_CTRLMSG_CONNECTACCEPT, SECURITY_TOKEN_MAGIC, sizeof(SECURITY_TOKEN_MAGIC));
2009-10-27 14:38:53 +00:00
}
2009-10-27 14:38:53 +00:00
return 0;
}
2014-08-09 15:25:29 +00:00
2020-10-27 17:57:14 +00:00
void CNetConnection::SetTimedOut(const NETADDR *pAddr, int Sequence, int Ack, SECURITY_TOKEN SecurityToken, CStaticRingBuffer<CNetChunkResend, NET_CONN_BUFFERSIZE> *pResendBuffer, bool Sixup)
2014-08-09 15:25:29 +00:00
{
2021-06-23 05:05:49 +00:00
int64_t Now = time_get();
2014-08-09 15:53:24 +00:00
m_Sequence = Sequence;
m_Ack = Ack;
m_RemoteClosed = 0;
2014-08-09 15:25:29 +00:00
m_State = NET_CONNSTATE_ONLINE;
m_PeerAddr = *pAddr;
2020-10-27 17:57:14 +00:00
mem_zero(m_aErrorString, sizeof(m_aErrorString));
2014-08-09 15:25:29 +00:00
m_LastSendTime = Now;
m_LastRecvTime = Now;
m_LastUpdateTime = Now;
m_SecurityToken = SecurityToken;
2020-06-20 16:50:14 +00:00
m_Sixup = Sixup;
// copy resend buffer
2014-08-09 15:25:29 +00:00
m_Buffer.Init();
while(pResendBuffer->First())
{
2020-10-27 17:57:14 +00:00
CNetChunkResend *pFirst = pResendBuffer->First();
2020-10-27 17:57:14 +00:00
CNetChunkResend *pResend = m_Buffer.Allocate(sizeof(CNetChunkResend) + pFirst->m_DataSize);
mem_copy(pResend, pFirst, sizeof(CNetChunkResend) + pFirst->m_DataSize);
pResendBuffer->PopFirst();
}
2014-08-09 15:25:29 +00:00
}