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. */
|
2009-10-27 14:38:53 +00:00
|
|
|
#include <base/system.h>
|
2010-05-29 07:25:38 +00:00
|
|
|
#include "config.h"
|
|
|
|
#include "network.h"
|
2009-10-27 14:38:53 +00:00
|
|
|
|
2017-03-21 10:24:44 +00:00
|
|
|
SECURITY_TOKEN ToSecurityToken(unsigned char *pData)
|
2015-04-18 21:54:19 +00:00
|
|
|
{
|
|
|
|
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));
|
2014-09-09 21:27:28 +00:00
|
|
|
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;
|
2015-03-19 08:57:47 +00:00
|
|
|
m_PeerAck = 0;
|
2009-10-27 14:38:53 +00:00
|
|
|
m_RemoteClosed = 0;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2015-08-23 16:12:13 +00:00
|
|
|
if (!Rejoin)
|
|
|
|
{
|
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;
|
2014-09-09 21:27:28 +00:00
|
|
|
//m_LastUpdateTime = 0;
|
2015-08-23 16:12:13 +00:00
|
|
|
|
2014-09-09 21:27:28 +00:00
|
|
|
//mem_zero(&m_PeerAddr, sizeof(m_PeerAddr));
|
2015-08-14 11:49:10 +00:00
|
|
|
m_UnknownSeq = false;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2009-10-27 14:38:53 +00:00
|
|
|
m_Buffer.Init();
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2009-10-27 14:38:53 +00:00
|
|
|
mem_zero(&m_Construct, sizeof(m_Construct));
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *CNetConnection::ErrorString()
|
|
|
|
{
|
|
|
|
return m_ErrorString;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CNetConnection::SetError(const char *pString)
|
|
|
|
{
|
|
|
|
str_copy(m_ErrorString, pString, sizeof(m_ErrorString));
|
|
|
|
}
|
|
|
|
|
2012-04-20 19:39:49 +00:00
|
|
|
void CNetConnection::Init(NETSOCKET Socket, bool BlockCloseMsg)
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
|
|
|
Reset();
|
|
|
|
ResetStats();
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2009-10-27 14:38:53 +00:00
|
|
|
m_Socket = Socket;
|
2012-04-20 19:39:49 +00:00
|
|
|
m_BlockCloseMsg = BlockCloseMsg;
|
2009-10-27 14:38:53 +00:00
|
|
|
mem_zero(m_ErrorString, sizeof(m_ErrorString));
|
|
|
|
}
|
|
|
|
|
|
|
|
void CNetConnection::AckChunks(int Ack)
|
|
|
|
{
|
|
|
|
while(1)
|
|
|
|
{
|
|
|
|
CNetChunkResend *pResend = m_Buffer.First();
|
|
|
|
if(!pResend)
|
|
|
|
break;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
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);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// update send times
|
2009-10-27 14:38:53 +00:00
|
|
|
m_LastSendTime = time_get();
|
2011-04-13 18:37:12 +00:00
|
|
|
|
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
|
|
|
{
|
2015-08-23 10:31:09 +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;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// check if we have space for it, if not, flush the connection
|
2015-03-04 08:38:34 +00:00
|
|
|
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);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2018-02-04 15:00:47 +00:00
|
|
|
// set packet flags as well
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2009-10-27 14:38:53 +00:00
|
|
|
if(Flags&NET_CHUNKFLAG_VITAL && !(Flags&NET_CHUNKFLAG_RESEND))
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
// save packet if we need to resend
|
2009-10-27 14:38:53 +00:00
|
|
|
CNetChunkResend *pResend = m_Buffer.Allocate(sizeof(CNetChunkResend)+DataSize);
|
|
|
|
if(pResend)
|
|
|
|
{
|
|
|
|
pResend->m_Sequence = Sequence;
|
|
|
|
pResend->m_Flags = Flags;
|
|
|
|
pResend->m_DataSize = DataSize;
|
|
|
|
pResend->m_pData = (unsigned char *)(pResend+1);
|
|
|
|
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::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);
|
|
|
|
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(NETADDR *pAddr)
|
|
|
|
{
|
|
|
|
if(State() != NET_CONNSTATE_OFFLINE)
|
|
|
|
return -1;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// init connection
|
2009-10-27 14:38:53 +00:00
|
|
|
Reset();
|
|
|
|
m_PeerAddr = *pAddr;
|
|
|
|
mem_zero(m_ErrorString, sizeof(m_ErrorString));
|
|
|
|
m_State = NET_CONNSTATE_CONNECT;
|
2015-03-04 08:38:34 +00:00
|
|
|
SendControl(NET_CTRLMSG_CONNECT, SECURITY_TOKEN_MAGIC, sizeof(SECURITY_TOKEN_MAGIC));
|
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);
|
|
|
|
else
|
|
|
|
SendControl(NET_CTRLMSG_CLOSE, 0, 0);
|
|
|
|
}
|
2009-10-27 14:38:53 +00:00
|
|
|
|
2015-09-11 10:08:35 +00:00
|
|
|
if(pReason != m_ErrorString)
|
|
|
|
{
|
|
|
|
m_ErrorString[0] = 0;
|
|
|
|
if(pReason)
|
|
|
|
str_copy(m_ErrorString, pReason, sizeof(m_ErrorString));
|
|
|
|
}
|
2009-10-27 14:38:53 +00:00
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2009-10-27 14:38:53 +00:00
|
|
|
Reset();
|
|
|
|
}
|
|
|
|
|
2020-03-29 02:36:38 +00:00
|
|
|
void CNetConnection::DirectInit(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;
|
|
|
|
mem_zero(m_ErrorString, sizeof(m_ErrorString));
|
|
|
|
|
|
|
|
int64 Now = time_get();
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2015-03-04 08:38:34 +00:00
|
|
|
int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr, SECURITY_TOKEN SecurityToken)
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
2020-03-29 02:36:38 +00:00
|
|
|
if (!m_Sixup && State() != NET_CONNSTATE_OFFLINE && m_SecurityToken != NET_SECURITY_TOKEN_UNKNOWN && m_SecurityToken != NET_SECURITY_TOKEN_UNSUPPORTED)
|
2015-03-04 08:38:34 +00:00
|
|
|
{
|
|
|
|
// supposed to have a valid token in this packet, check it
|
2015-04-18 19:33:51 +00:00
|
|
|
if (pPacket->m_DataSize < (int)sizeof(m_SecurityToken))
|
2015-03-06 06:33:01 +00:00
|
|
|
return 0;
|
2015-03-04 08:38:34 +00:00
|
|
|
pPacket->m_DataSize -= sizeof(m_SecurityToken);
|
2015-04-18 21:54:19 +00:00
|
|
|
if (m_SecurityToken != ToSecurityToken(&pPacket->m_aChunkData[pPacket->m_DataSize]))
|
2015-03-04 08:38:34 +00:00
|
|
|
{
|
|
|
|
if(g_Config.m_Debug)
|
2015-04-18 21:54:19 +00:00
|
|
|
dbg_msg("security", "token mismatch, expected %d got %d", m_SecurityToken, ToSecurityToken(&pPacket->m_aChunkData[pPacket->m_DataSize]));
|
2015-03-06 06:33:01 +00:00
|
|
|
return 0;
|
2015-03-04 08:38:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-29 02:36:38 +00:00
|
|
|
if(m_Sixup && SecurityToken != m_Token)
|
|
|
|
return 0;
|
|
|
|
|
2015-03-19 08:57:47 +00:00
|
|
|
// 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;
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
int64 Now = time_get();
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// check if resend is requested
|
2009-10-27 14:38:53 +00:00
|
|
|
if(pPacket->m_Flags&NET_PACKETFLAG_RESEND)
|
|
|
|
Resend();
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
//
|
2009-10-27 14:38:53 +00:00
|
|
|
if(pPacket->m_Flags&NET_PACKETFLAG_CONTROL)
|
|
|
|
{
|
|
|
|
int CtrlMsg = pPacket->m_aChunkData[0];
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2009-10-27 14:38:53 +00:00
|
|
|
if(CtrlMsg == NET_CTRLMSG_CLOSE)
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(net_addr_comp(&m_PeerAddr, pAddr) == 0)
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
m_State = NET_CONNSTATE_ERROR;
|
|
|
|
m_RemoteClosed = 1;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2013-02-20 15:49:21 +00:00
|
|
|
char Str[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
|
|
|
|
if(pPacket->m_DataSize < 128)
|
2013-02-20 15:49:21 +00:00
|
|
|
str_copy(Str, (char *)&pPacket->m_aChunkData[1], pPacket->m_DataSize);
|
2010-05-29 07:25:38 +00:00
|
|
|
else
|
2013-02-20 15:49:21 +00:00
|
|
|
str_copy(Str, (char *)&pPacket->m_aChunkData[1], sizeof(Str));
|
2010-05-29 07:25:38 +00:00
|
|
|
str_sanitize_strong(Str);
|
2013-02-20 15:49:21 +00:00
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2013-02-20 15:49:21 +00:00
|
|
|
if(!m_BlockCloseMsg)
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
// set the error string
|
|
|
|
SetError(Str);
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(g_Config.m_Debug)
|
2013-02-20 15:49:21 +00:00
|
|
|
dbg_msg("conn", "closed reason='%s'", Str);
|
2009-10-27 14:38:53 +00:00
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
return 0;
|
2009-10-27 14:38:53 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-08-18 21:50:24 +00:00
|
|
|
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)
|
2014-09-09 21:27:28 +00:00
|
|
|
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;
|
2012-07-08 16:37:32 +00:00
|
|
|
mem_zero(m_ErrorString, sizeof(m_ErrorString));
|
2010-05-29 07:25:38 +00:00
|
|
|
m_LastSendTime = Now;
|
|
|
|
m_LastRecvTime = Now;
|
|
|
|
m_LastUpdateTime = Now;
|
2015-03-04 08:38:34 +00:00
|
|
|
if (m_SecurityToken == NET_SECURITY_TOKEN_UNKNOWN
|
2015-04-18 19:33:51 +00:00
|
|
|
&& pPacket->m_DataSize >= (int)(1 + sizeof(SECURITY_TOKEN_MAGIC) + sizeof(m_SecurityToken))
|
2015-03-04 08:38:34 +00:00
|
|
|
&& !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;
|
2015-03-04 08:38:34 +00:00
|
|
|
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)
|
2011-04-13 18:37:12 +00:00
|
|
|
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)
|
|
|
|
{
|
2015-03-04 08:38:34 +00:00
|
|
|
if (m_SecurityToken == NET_SECURITY_TOKEN_UNKNOWN
|
2015-04-18 19:33:51 +00:00
|
|
|
&& pPacket->m_DataSize >= (int)(1 + sizeof(SECURITY_TOKEN_MAGIC) + sizeof(m_SecurityToken))
|
2015-03-04 08:38:34 +00:00
|
|
|
&& !mem_comp(&pPacket->m_aChunkData[1], SECURITY_TOKEN_MAGIC, sizeof(SECURITY_TOKEN_MAGIC)))
|
|
|
|
{
|
2015-04-18 21:54:19 +00:00
|
|
|
m_SecurityToken = ToSecurityToken(&pPacket->m_aChunkData[1 + sizeof(SECURITY_TOKEN_MAGIC)]);
|
2015-03-04 08:38:34 +00:00
|
|
|
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");
|
|
|
|
}
|
2010-11-01 10:42:43 +00:00
|
|
|
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)
|
|
|
|
{
|
2010-11-01 10:42:43 +00:00
|
|
|
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");
|
|
|
|
}
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2009-10-27 14:38:53 +00:00
|
|
|
if(State() == NET_CONNSTATE_ONLINE)
|
|
|
|
{
|
2010-11-01 10:42:43 +00:00
|
|
|
m_LastRecvTime = Now;
|
2009-10-27 14:38:53 +00:00
|
|
|
AckChunks(pPacket->m_Ack);
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2009-10-27 14:38:53 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CNetConnection::Update()
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
int64 Now = time_get();
|
2009-10-27 14:38:53 +00:00
|
|
|
|
2014-08-11 20:22:01 +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;
|
2014-08-09 16:08:00 +00:00
|
|
|
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;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
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 &&
|
2010-10-24 10:47:25 +00:00
|
|
|
(Now-m_LastRecvTime) > time_freq()*g_Config.m_ConnTimeout)
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
|
|
|
m_State = NET_CONNSTATE_ERROR;
|
2014-08-09 16:08:00 +00:00
|
|
|
SetError("Timeout");
|
2014-08-11 20:22:01 +00:00
|
|
|
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
|
2010-10-24 10:47:25 +00:00
|
|
|
if(Now-pResend->m_FirstSendTime > time_freq()*g_Config.m_ConnTimeout)
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
|
|
|
m_State = NET_CONNSTATE_ERROR;
|
2010-10-23 18:11:42 +00:00
|
|
|
char aBuf[512];
|
2010-10-24 10:47:25 +00:00
|
|
|
str_format(aBuf, sizeof(aBuf), "Too weak connection (not acked for %d seconds)", g_Config.m_ConnTimeout);
|
2010-10-23 18:11:42 +00:00
|
|
|
SetError(aBuf);
|
2014-08-11 20:22:01 +00:00
|
|
|
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
|
2010-05-29 07:25:38 +00:00
|
|
|
if(Now-pResend->m_LastSendTime > time_freq())
|
2009-10-27 14:38:53 +00:00
|
|
|
ResendChunk(pResend);
|
|
|
|
}
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
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)
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
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);
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2009-10-27 14:38:53 +00:00
|
|
|
if(time_get()-m_LastSendTime > time_freq())
|
|
|
|
SendControl(NET_CTRLMSG_KEEPALIVE, 0, 0);
|
|
|
|
}
|
|
|
|
else if(State() == NET_CONNSTATE_CONNECT)
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(time_get()-m_LastSendTime > time_freq()/2) // send a new connect every 500ms
|
2015-03-04 08:38:34 +00:00
|
|
|
SendControl(NET_CTRLMSG_CONNECT, SECURITY_TOKEN_MAGIC, sizeof(SECURITY_TOKEN_MAGIC));
|
2009-10-27 14:38:53 +00:00
|
|
|
}
|
|
|
|
else if(State() == NET_CONNSTATE_PENDING)
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(time_get()-m_LastSendTime > time_freq()/2) // send a new connect/accept every 500ms
|
2015-03-04 08:38:34 +00:00
|
|
|
SendControl(NET_CTRLMSG_CONNECTACCEPT, SECURITY_TOKEN_MAGIC, sizeof(SECURITY_TOKEN_MAGIC));
|
2009-10-27 14:38:53 +00:00
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2009-10-27 14:38:53 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2014-08-09 15:25:29 +00:00
|
|
|
|
2020-06-20 16:50:14 +00:00
|
|
|
void CNetConnection::SetTimedOut(const NETADDR *pAddr, int Sequence, int Ack, SECURITY_TOKEN SecurityToken, TStaticRingBuffer<CNetChunkResend, NET_CONN_BUFFERSIZE> *pResendBuffer, bool Sixup)
|
2014-08-09 15:25:29 +00:00
|
|
|
{
|
|
|
|
int64 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;
|
|
|
|
mem_zero(m_ErrorString, sizeof(m_ErrorString));
|
|
|
|
m_LastSendTime = Now;
|
|
|
|
m_LastRecvTime = Now;
|
|
|
|
m_LastUpdateTime = Now;
|
2015-03-06 06:33:01 +00:00
|
|
|
m_SecurityToken = SecurityToken;
|
2020-06-20 16:50:14 +00:00
|
|
|
m_Sixup = Sixup;
|
2016-05-07 17:28:16 +00:00
|
|
|
|
|
|
|
// copy resend buffer
|
2014-08-09 15:25:29 +00:00
|
|
|
m_Buffer.Init();
|
2016-05-07 17:28:16 +00:00
|
|
|
while (pResendBuffer->First())
|
|
|
|
{
|
|
|
|
CNetChunkResend *First = pResendBuffer->First();
|
|
|
|
|
|
|
|
CNetChunkResend *pResend = m_Buffer.Allocate(sizeof(CNetChunkResend)+First->m_DataSize);
|
|
|
|
mem_copy(pResend, First, sizeof(CNetChunkResend)+First->m_DataSize);
|
|
|
|
|
|
|
|
pResendBuffer->PopFirst();
|
|
|
|
}
|
2014-08-09 15:25:29 +00:00
|
|
|
}
|