mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-13 11:38:19 +00:00
4fb050ccb7
These diagnostics are supposed to guide the user to problem resolution. They're displayed if no packet is received from the server within one second of connecting. No message if we don't have STUN servers. "Trying to determine UDP connectivity..." if no answer has been received from the STUN server yet and it hasn't timed out yet. "UDP seems to be filtered." if the STUN request has timed out. "UDP and TCP IP addresses seem to be different. Try disabling VPN, proxy or network accelerators." if the STUN request has returned an IP address different from the one obtained via HTTP from info2.ddnet.tw. "No answer from server yet." otherwise, if the STUN request has returned no interesting data, indicating that it's likely the game server's fault.
184 lines
4 KiB
C++
184 lines
4 KiB
C++
/* (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. */
|
|
#include "network.h"
|
|
#include <base/system.h>
|
|
|
|
bool CNetClient::Open(NETADDR BindAddr)
|
|
{
|
|
// open socket
|
|
NETSOCKET Socket;
|
|
Socket = net_udp_create(BindAddr);
|
|
if(!Socket)
|
|
return false;
|
|
|
|
// clean it
|
|
mem_zero(this, sizeof(*this));
|
|
|
|
// init
|
|
m_Socket = Socket;
|
|
m_pStun = new CStun(m_Socket);
|
|
m_Connection.Init(m_Socket, false);
|
|
|
|
return true;
|
|
}
|
|
|
|
int CNetClient::Close()
|
|
{
|
|
if(!m_Socket)
|
|
return 0;
|
|
if(m_pStun)
|
|
{
|
|
delete m_pStun;
|
|
m_pStun = nullptr;
|
|
}
|
|
return net_udp_close(m_Socket);
|
|
}
|
|
|
|
int CNetClient::Disconnect(const char *pReason)
|
|
{
|
|
//dbg_msg("netclient", "disconnected. reason=\"%s\"", pReason);
|
|
m_Connection.Disconnect(pReason);
|
|
return 0;
|
|
}
|
|
|
|
int CNetClient::Update()
|
|
{
|
|
m_Connection.Update();
|
|
if(m_Connection.State() == NET_CONNSTATE_ERROR)
|
|
Disconnect(m_Connection.ErrorString());
|
|
m_pStun->Update();
|
|
return 0;
|
|
}
|
|
|
|
int CNetClient::Connect(NETADDR *pAddr)
|
|
{
|
|
m_Connection.Connect(pAddr);
|
|
return 0;
|
|
}
|
|
|
|
int CNetClient::ResetErrorString()
|
|
{
|
|
m_Connection.ResetErrorString();
|
|
return 0;
|
|
}
|
|
|
|
int CNetClient::Recv(CNetChunk *pChunk)
|
|
{
|
|
while(true)
|
|
{
|
|
// check for a chunk
|
|
if(m_RecvUnpacker.FetchChunk(pChunk))
|
|
return 1;
|
|
|
|
// TODO: empty the recvinfo
|
|
NETADDR Addr;
|
|
unsigned char *pData;
|
|
int Bytes = net_udp_recv(m_Socket, &Addr, &pData);
|
|
|
|
// no more packets for now
|
|
if(Bytes <= 0)
|
|
break;
|
|
|
|
if(m_pStun->OnPacket(Addr, pData, Bytes))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
bool Sixup = false;
|
|
if(CNetBase::UnpackPacket(pData, Bytes, &m_RecvUnpacker.m_Data, Sixup) == 0)
|
|
{
|
|
if(m_RecvUnpacker.m_Data.m_Flags & NET_PACKETFLAG_CONNLESS)
|
|
{
|
|
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;
|
|
if(m_RecvUnpacker.m_Data.m_Flags & NET_PACKETFLAG_EXTENDED)
|
|
{
|
|
pChunk->m_Flags |= NETSENDFLAG_EXTENDED;
|
|
mem_copy(pChunk->m_aExtraData, m_RecvUnpacker.m_Data.m_aExtraData, sizeof(pChunk->m_aExtraData));
|
|
}
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
if(m_Connection.State() != NET_CONNSTATE_OFFLINE && m_Connection.State() != NET_CONNSTATE_ERROR && net_addr_comp(m_Connection.PeerAddress(), &Addr) == 0 && m_Connection.Feed(&m_RecvUnpacker.m_Data, &Addr))
|
|
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;
|
|
}
|
|
|
|
if(pChunk->m_Flags & NETSENDFLAG_CONNLESS)
|
|
{
|
|
// send connectionless packet
|
|
CNetBase::SendPacketConnless(m_Socket, &pChunk->m_Address, pChunk->m_pData, pChunk->m_DataSize,
|
|
pChunk->m_Flags & NETSENDFLAG_EXTENDED, pChunk->m_aExtraData);
|
|
}
|
|
else
|
|
{
|
|
int Flags = 0;
|
|
dbg_assert(pChunk->m_ClientID == 0, "erroneous client id");
|
|
|
|
if(pChunk->m_Flags & NETSENDFLAG_VITAL)
|
|
Flags = NET_CHUNKFLAG_VITAL;
|
|
|
|
m_Connection.QueueChunk(Flags, pChunk->m_DataSize, pChunk->m_pData);
|
|
|
|
if(pChunk->m_Flags & NETSENDFLAG_FLUSH)
|
|
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();
|
|
}
|
|
|
|
int CNetClient::GotProblems(int64_t MaxLatency) const
|
|
{
|
|
if(time_get() - m_Connection.LastRecvTime() > MaxLatency)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
const char *CNetClient::ErrorString() const
|
|
{
|
|
return m_Connection.ErrorString();
|
|
}
|
|
|
|
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);
|
|
}
|