ddnet/src/engine/shared/network_client.cpp

155 lines
3.5 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. */
2009-10-27 14:38:53 +00:00
#include <base/system.h>
2010-05-29 07:25:38 +00:00
#include "network.h"
2009-10-27 14:38:53 +00:00
bool CNetClient::Open(NETADDR BindAddr, int Flags)
{
// open socket
NETSOCKET Socket;
Socket = net_udp_create(BindAddr);
if(!Socket.type)
return false;
2009-10-27 14:38:53 +00:00
// clean it
mem_zero(this, sizeof(*this));
// init
m_Socket = Socket;
m_Connection.Init(m_Socket, false);
2009-10-27 14:38:53 +00:00
return true;
}
int CNetClient::Close()
{
2010-05-29 07:25:38 +00:00
// TODO: implement me
2009-10-27 14:38:53 +00:00
return 0;
}
int CNetClient::Disconnect(const char *pReason)
{
//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());
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(1)
{
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;
2010-05-29 07:25:38 +00:00
// TODO: empty the recvinfo
2009-10-27 14:38:53 +00:00
NETADDR Addr;
int Bytes = net_udp_recv(m_Socket, &Addr, m_RecvUnpacker.m_aBuffer, NET_MAX_PACKETSIZE);
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;
if(CNetBase::UnpackPacket(m_RecvUnpacker.m_aBuffer, Bytes, &m_RecvUnpacker.m_Data) == 0)
2009-10-27 14:38:53 +00:00
{
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));
}
2009-10-27 14:38:53 +00:00
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))
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;
}
2009-10-27 14:38:53 +00:00
if(pChunk->m_Flags&NETSENDFLAG_CONNLESS)
{
2010-05-29 07:25:38 +00:00
// send connectionless packet
CNetBase::SendPacketConnless(m_Socket, &pChunk->m_Address, pChunk->m_pData, pChunk->m_DataSize,
pChunk->m_Flags&NETSENDFLAG_EXTENDED, pChunk->m_aExtraData);
2009-10-27 14:38:53 +00:00
}
else
{
int Flags = 0;
dbg_assert(pChunk->m_ClientID == 0, "errornous client id");
2009-10-27 14:38:53 +00:00
if(pChunk->m_Flags&NETSENDFLAG_VITAL)
Flags = NET_CHUNKFLAG_VITAL;
2009-10-27 14:38:53 +00:00
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()
{
if(time_get() - m_Connection.LastRecvTime() > time_freq())
return 1;
return 0;
}
const char *CNetClient::ErrorString()
{
return m_Connection.ErrorString();
}