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 "network.h"
|
2020-09-26 19:41:58 +00:00
|
|
|
#include <base/system.h>
|
2009-10-27 14:38:53 +00:00
|
|
|
|
2022-03-01 16:34:57 +00:00
|
|
|
bool CNetClient::Open(NETADDR BindAddr)
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
2011-03-28 18:11:28 +00:00
|
|
|
// open socket
|
|
|
|
NETSOCKET Socket;
|
|
|
|
Socket = net_udp_create(BindAddr);
|
2022-03-01 16:34:42 +00:00
|
|
|
if(!Socket)
|
2011-03-28 18:11:28 +00:00
|
|
|
return false;
|
|
|
|
|
2009-10-27 14:38:53 +00:00
|
|
|
// clean it
|
|
|
|
mem_zero(this, sizeof(*this));
|
|
|
|
|
2011-03-28 18:11:28 +00:00
|
|
|
// init
|
|
|
|
m_Socket = Socket;
|
2022-05-15 19:59:17 +00:00
|
|
|
m_pStun = new CStun(m_Socket);
|
2012-04-20 19:39:49 +00:00
|
|
|
m_Connection.Init(m_Socket, false);
|
2018-07-25 14:06:00 +00:00
|
|
|
|
2009-10-27 14:38:53 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CNetClient::Close()
|
|
|
|
{
|
2022-04-14 09:50:10 +00:00
|
|
|
if(!m_Socket)
|
|
|
|
return 0;
|
2022-05-15 19:59:17 +00:00
|
|
|
if(m_pStun)
|
|
|
|
{
|
|
|
|
delete m_pStun;
|
|
|
|
m_pStun = nullptr;
|
|
|
|
}
|
2022-04-14 09:50:10 +00:00
|
|
|
return net_udp_close(m_Socket);
|
2009-10-27 14:38:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int CNetClient::Disconnect(const char *pReason)
|
|
|
|
{
|
2010-08-17 22:06:00 +00:00
|
|
|
//dbg_msg("netclient", "disconnected. reason=\"%s\"", pReason);
|
2009-10-27 14:38:53 +00:00
|
|
|
m_Connection.Disconnect(pReason);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CNetClient::Update()
|
|
|
|
{
|
|
|
|
m_Connection.Update();
|
|
|
|
if(m_Connection.State() == NET_CONNSTATE_ERROR)
|
|
|
|
Disconnect(m_Connection.ErrorString());
|
2022-05-15 19:59:17 +00:00
|
|
|
m_pStun->Update();
|
2009-10-27 14:38:53 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-06-01 10:09:22 +00:00
|
|
|
int CNetClient::Connect(const NETADDR *pAddr, int NumAddrs)
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
2022-06-01 10:09:22 +00:00
|
|
|
m_Connection.Connect(pAddr, NumAddrs);
|
2009-10-27 14:38:53 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CNetClient::ResetErrorString()
|
|
|
|
{
|
|
|
|
m_Connection.ResetErrorString();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CNetClient::Recv(CNetChunk *pChunk)
|
|
|
|
{
|
2022-02-14 23:12:52 +00:00
|
|
|
while(true)
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
// check for a chunk
|
2009-10-27 14:38:53 +00:00
|
|
|
if(m_RecvUnpacker.FetchChunk(pChunk))
|
|
|
|
return 1;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// TODO: empty the recvinfo
|
2009-10-27 14:38:53 +00:00
|
|
|
NETADDR Addr;
|
2018-12-17 21:15:41 +00:00
|
|
|
unsigned char *pData;
|
2022-03-01 18:27:48 +00:00
|
|
|
int Bytes = net_udp_recv(m_Socket, &Addr, &pData);
|
2009-10-27 14:38:53 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// no more packets for now
|
2009-10-27 14:38:53 +00:00
|
|
|
if(Bytes <= 0)
|
|
|
|
break;
|
|
|
|
|
2022-05-15 19:59:17 +00:00
|
|
|
if(m_pStun->OnPacket(Addr, pData, Bytes))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2020-06-16 12:41:30 +00:00
|
|
|
bool Sixup = false;
|
2020-06-17 17:50:16 +00:00
|
|
|
if(CNetBase::UnpackPacket(pData, Bytes, &m_RecvUnpacker.m_Data, Sixup) == 0)
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
2020-09-26 19:41:58 +00:00
|
|
|
if(m_RecvUnpacker.m_Data.m_Flags & NET_PACKETFLAG_CONNLESS)
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
|
|
|
pChunk->m_Flags = NETSENDFLAG_CONNLESS;
|
|
|
|
pChunk->m_ClientID = -1;
|
|
|
|
pChunk->m_Address = Addr;
|
|
|
|
pChunk->m_DataSize = m_RecvUnpacker.m_Data.m_DataSize;
|
|
|
|
pChunk->m_pData = m_RecvUnpacker.m_Data.m_aChunkData;
|
2020-09-26 19:41:58 +00:00
|
|
|
if(m_RecvUnpacker.m_Data.m_Flags & NET_PACKETFLAG_EXTENDED)
|
2017-03-29 10:56:13 +00:00
|
|
|
{
|
|
|
|
pChunk->m_Flags |= NETSENDFLAG_EXTENDED;
|
|
|
|
mem_copy(pChunk->m_aExtraData, m_RecvUnpacker.m_Data.m_aExtraData, sizeof(pChunk->m_aExtraData));
|
|
|
|
}
|
2009-10-27 14:38:53 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-06-01 10:09:22 +00:00
|
|
|
if(m_Connection.State() != NET_CONNSTATE_OFFLINE && m_Connection.State() != NET_CONNSTATE_ERROR && m_Connection.Feed(&m_RecvUnpacker.m_Data, &Addr))
|
2009-10-27 14:38:53 +00:00
|
|
|
m_RecvUnpacker.Start(&Addr, &m_Connection, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CNetClient::Send(CNetChunk *pChunk)
|
|
|
|
{
|
|
|
|
if(pChunk->m_DataSize >= NET_MAX_PAYLOAD)
|
|
|
|
{
|
|
|
|
dbg_msg("netclient", "chunk payload too big. %d. dropping chunk", pChunk->m_DataSize);
|
|
|
|
return -1;
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
if(pChunk->m_Flags & NETSENDFLAG_CONNLESS)
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
// send connectionless packet
|
2017-03-29 10:56:13 +00:00
|
|
|
CNetBase::SendPacketConnless(m_Socket, &pChunk->m_Address, pChunk->m_pData, pChunk->m_DataSize,
|
2020-09-26 19:41:58 +00:00
|
|
|
pChunk->m_Flags & NETSENDFLAG_EXTENDED, pChunk->m_aExtraData);
|
2009-10-27 14:38:53 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int Flags = 0;
|
2022-02-21 14:54:55 +00:00
|
|
|
dbg_assert(pChunk->m_ClientID == 0, "erroneous client id");
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
if(pChunk->m_Flags & NETSENDFLAG_VITAL)
|
2009-10-27 14:38:53 +00:00
|
|
|
Flags = NET_CHUNKFLAG_VITAL;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2009-10-27 14:38:53 +00:00
|
|
|
m_Connection.QueueChunk(Flags, pChunk->m_DataSize, pChunk->m_pData);
|
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
if(pChunk->m_Flags & NETSENDFLAG_FLUSH)
|
2009-10-27 14:38:53 +00:00
|
|
|
m_Connection.Flush();
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CNetClient::State()
|
|
|
|
{
|
|
|
|
if(m_Connection.State() == NET_CONNSTATE_ONLINE)
|
|
|
|
return NETSTATE_ONLINE;
|
|
|
|
if(m_Connection.State() == NET_CONNSTATE_OFFLINE)
|
|
|
|
return NETSTATE_OFFLINE;
|
|
|
|
return NETSTATE_CONNECTING;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CNetClient::Flush()
|
|
|
|
{
|
|
|
|
return m_Connection.Flush();
|
|
|
|
}
|
|
|
|
|
2022-01-09 12:06:41 +00:00
|
|
|
int CNetClient::GotProblems(int64_t MaxLatency) const
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
2022-01-09 12:06:41 +00:00
|
|
|
if(time_get() - m_Connection.LastRecvTime() > MaxLatency)
|
2009-10-27 14:38:53 +00:00
|
|
|
return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-02-08 21:26:26 +00:00
|
|
|
const char *CNetClient::ErrorString() const
|
2009-10-27 14:38:53 +00:00
|
|
|
{
|
|
|
|
return m_Connection.ErrorString();
|
|
|
|
}
|
2022-05-15 19:59:17 +00:00
|
|
|
|
|
|
|
void CNetClient::FeedStunServer(NETADDR StunServer)
|
|
|
|
{
|
|
|
|
m_pStun->FeedStunServer(StunServer);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CNetClient::RefreshStun()
|
|
|
|
{
|
|
|
|
m_pStun->Refresh();
|
|
|
|
}
|
|
|
|
|
|
|
|
CONNECTIVITY CNetClient::GetConnectivity(int NetType, NETADDR *pGlobalAddr)
|
|
|
|
{
|
|
|
|
return m_pStun->GetConnectivity(NetType, pGlobalAddr);
|
|
|
|
}
|