separated connless packet handling and use random port for client's server connection

This commit is contained in:
oy 2015-03-18 18:58:33 +01:00
parent b9e4c7e979
commit d4c00097a5
11 changed files with 71 additions and 34 deletions

View file

@ -853,7 +853,7 @@ static int priv_net_close_all_sockets(NETSOCKET sock)
return 0;
}
static int priv_net_create_socket(int domain, int type, struct sockaddr *addr, int sockaddrlen)
static int priv_net_create_socket(int domain, int type, struct sockaddr *addr, int sockaddrlen, int use_random_port)
{
int sock, e;
@ -883,27 +883,46 @@ static int priv_net_create_socket(int domain, int type, struct sockaddr *addr, i
#endif
/* bind the socket */
e = bind(sock, addr, sockaddrlen);
if(e != 0)
while(1)
{
/* pick random port */
if(use_random_port)
{
int port = htons(rand()%16384+49152); /* 49152 to 65535 */
if(domain == AF_INET)
((struct sockaddr_in *)(addr))->sin_port = port;
else
((struct sockaddr_in6 *)(addr))->sin6_port = port;
}
e = bind(sock, addr, sockaddrlen);
if(e == 0)
break;
else
{
#if defined(CONF_FAMILY_WINDOWS)
char buf[128];
int error = WSAGetLastError();
if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, 0, error, 0, buf, sizeof(buf), 0) == 0)
buf[0] = 0;
dbg_msg("net", "failed to bind socket with domain %d and type %d (%d '%s')", domain, type, error, buf);
char buf[128];
int error = WSAGetLastError();
if(error == WSAEADDRINUSE && use_random_port)
continue;
if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, 0, error, 0, buf, sizeof(buf), 0) == 0)
buf[0] = 0;
dbg_msg("net", "failed to bind socket with domain %d and type %d (%d '%s')", domain, type, error, buf);
#else
dbg_msg("net", "failed to bind socket with domain %d and type %d (%d '%s')", domain, type, errno, strerror(errno));
if(errno == EADDRINUSE && use_random_port)
continue;
dbg_msg("net", "failed to bind socket with domain %d and type %d (%d '%s')", domain, type, errno, strerror(errno));
#endif
priv_net_close_socket(sock);
return -1;
priv_net_close_socket(sock);
return -1;
}
}
/* return the newly created socket */
return sock;
}
NETSOCKET net_udp_create(NETADDR bindaddr)
NETSOCKET net_udp_create(NETADDR bindaddr, int use_random_port)
{
NETSOCKET sock = invalid_socket;
NETADDR tmpbindaddr = bindaddr;
@ -918,7 +937,7 @@ NETSOCKET net_udp_create(NETADDR bindaddr)
/* bind, we should check for error */
tmpbindaddr.type = NETTYPE_IPV4;
netaddr_to_sockaddr_in(&tmpbindaddr, &addr);
socket = priv_net_create_socket(AF_INET, SOCK_DGRAM, (struct sockaddr *)&addr, sizeof(addr));
socket = priv_net_create_socket(AF_INET, SOCK_DGRAM, (struct sockaddr *)&addr, sizeof(addr), use_random_port);
if(socket >= 0)
{
sock.type |= NETTYPE_IPV4;
@ -940,7 +959,7 @@ NETSOCKET net_udp_create(NETADDR bindaddr)
/* bind, we should check for error */
tmpbindaddr.type = NETTYPE_IPV6;
netaddr_to_sockaddr_in6(&tmpbindaddr, &addr);
socket = priv_net_create_socket(AF_INET6, SOCK_DGRAM, (struct sockaddr *)&addr, sizeof(addr));
socket = priv_net_create_socket(AF_INET6, SOCK_DGRAM, (struct sockaddr *)&addr, sizeof(addr), use_random_port);
if(socket >= 0)
{
sock.type |= NETTYPE_IPV6;
@ -1077,7 +1096,7 @@ NETSOCKET net_tcp_create(NETADDR bindaddr)
/* bind, we should check for error */
tmpbindaddr.type = NETTYPE_IPV4;
netaddr_to_sockaddr_in(&tmpbindaddr, &addr);
socket = priv_net_create_socket(AF_INET, SOCK_STREAM, (struct sockaddr *)&addr, sizeof(addr));
socket = priv_net_create_socket(AF_INET, SOCK_STREAM, (struct sockaddr *)&addr, sizeof(addr), 0);
if(socket >= 0)
{
sock.type |= NETTYPE_IPV4;
@ -1093,7 +1112,7 @@ NETSOCKET net_tcp_create(NETADDR bindaddr)
/* bind, we should check for error */
tmpbindaddr.type = NETTYPE_IPV6;
netaddr_to_sockaddr_in6(&tmpbindaddr, &addr);
socket = priv_net_create_socket(AF_INET6, SOCK_STREAM, (struct sockaddr *)&addr, sizeof(addr));
socket = priv_net_create_socket(AF_INET6, SOCK_STREAM, (struct sockaddr *)&addr, sizeof(addr), 0);
if(socket >= 0)
{
sock.type |= NETTYPE_IPV6;

View file

@ -576,12 +576,13 @@ int net_addr_from_str(NETADDR *addr, const char *string);
Parameters:
bindaddr - Address to bind the socket to.
use_random_port - use a random port
Returns:
On success it returns an handle to the socket. On failure it
returns NETSOCKET_INVALID.
*/
NETSOCKET net_udp_create(NETADDR bindaddr);
NETSOCKET net_udp_create(NETADDR bindaddr, int use_random_port);
/*
Function: net_udp_send

View file

@ -884,7 +884,7 @@ void CClient::ProcessConnlessPacket(CNetChunk *pPacket)
Packet.m_pData = VERSIONSRV_GETMAPLIST;
Packet.m_DataSize = sizeof(VERSIONSRV_GETMAPLIST);
Packet.m_Flags = NETSENDFLAG_CONNLESS;
m_NetClient.Send(&Packet);
m_ContactClient.Send(&Packet);
}
// map version list
@ -1429,14 +1429,20 @@ void CClient::PumpNetwork()
}
}
// process packets
// process non-connless packets
CNetChunk Packet;
while(m_NetClient.Recv(&Packet))
{
if(Packet.m_ClientID != -1)
ProcessServerPacket(&Packet);
}
// process connless packets data
m_ContactClient.Update();
while(m_ContactClient.Recv(&Packet))
{
if(Packet.m_ClientID == -1)
ProcessConnlessPacket(&Packet);
else
ProcessServerPacket(&Packet);
}
}
@ -1652,7 +1658,7 @@ void CClient::VersionUpdate()
{
if(m_VersionInfo.m_State == CVersionInfo::STATE_INIT)
{
Engine()->HostLookup(&m_VersionInfo.m_VersionServeraddr, g_Config.m_ClVersionServer, m_NetClient.NetType());
Engine()->HostLookup(&m_VersionInfo.m_VersionServeraddr, g_Config.m_ClVersionServer, m_ContactClient.NetType());
m_VersionInfo.m_State = CVersionInfo::STATE_START;
}
else if(m_VersionInfo.m_State == CVersionInfo::STATE_START)
@ -1671,7 +1677,7 @@ void CClient::VersionUpdate()
Packet.m_DataSize = sizeof(VERSIONSRV_GETVERSION);
Packet.m_Flags = NETSENDFLAG_CONNLESS;
m_NetClient.Send(&Packet);
m_ContactClient.Send(&Packet);
m_VersionInfo.m_State = CVersionInfo::STATE_READY;
}
}
@ -1699,7 +1705,7 @@ void CClient::InitInterfaces()
m_pStorage = Kernel()->RequestInterface<IStorage>();
//
m_ServerBrowser.SetBaseInfo(&m_NetClient, m_pGameClient->NetVersion());
m_ServerBrowser.SetBaseInfo(&m_ContactClient, m_pGameClient->NetVersion());
m_Friends.Init();
}
@ -1753,9 +1759,15 @@ void CClient::Run()
mem_zero(&BindAddr, sizeof(BindAddr));
BindAddr.type = NETTYPE_ALL;
}
if(!m_NetClient.Open(BindAddr, 0))
if(!m_NetClient.Open(BindAddr, BindAddr.port ? 0 : NETCREATE_FLAG_RANDOMPORT))
{
dbg_msg("client", "couldn't open socket");
dbg_msg("client", "couldn't open socket(net)");
return;
}
BindAddr.port = 0;
if(!m_ContactClient.Open(BindAddr, 0))
{
dbg_msg("client", "couldn't open socket(contact)");
return;
}
}
@ -1767,7 +1779,7 @@ void CClient::Run()
Input()->Init();
// start refreshing addresses while we load
MasterServer()->RefreshAddresses(m_NetClient.NetType());
MasterServer()->RefreshAddresses(m_ContactClient.NetType());
// init the editor
m_pEditor->Init();

View file

@ -70,6 +70,7 @@ class CClient : public IClient, public CDemoPlayer::IListner
};
class CNetClient m_NetClient;
class CNetClient m_ContactClient;
class CDemoPlayer m_DemoPlayer;
class CDemoRecorder m_DemoRecorder;
class CServerBrowser m_ServerBrowser;

View file

@ -518,7 +518,7 @@ void CServerBrowser::Set(const NETADDR &Addr, int Type, int Token, const CServer
pEntry = Find(Addr);
if(!pEntry && m_ServerlistType == IServerBrowser::TYPE_LAN)
pEntry = Add(Addr);
if(pEntry && pEntry->m_InfoState == CServerEntry::STATE_PENDING && Token == pEntry->m_CurrentToken)
if(pEntry && ((pEntry->m_InfoState == CServerEntry::STATE_PENDING && Token == pEntry->m_CurrentToken) || m_ServerlistType == IServerBrowser::TYPE_LAN))
{
SetInfo(pEntry, *pInfo);
if(m_ServerlistType == IServerBrowser::TYPE_LAN)
@ -607,7 +607,7 @@ void CServerBrowser::RequestImpl(const NETADDR &Addr, CServerEntry *pEntry) cons
}
mem_copy(Buffer, SERVERBROWSE_GETINFO, sizeof(SERVERBROWSE_GETINFO));
Buffer[sizeof(SERVERBROWSE_GETINFO)] = pEntry->m_CurrentToken;
Buffer[sizeof(SERVERBROWSE_GETINFO)] = pEntry ? pEntry->m_CurrentToken : m_CurrentLanToken;
Packet.m_ClientID = -1;
Packet.m_Address = Addr;

View file

@ -1,5 +1,6 @@
/* (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 <stdlib.h> // srand
#include <base/system.h>
@ -57,6 +58,7 @@ public:
CEngine(const char *pAppname)
{
srand(time_get());
dbg_logger_stdout();
dbg_logger_debugger();

View file

@ -36,7 +36,9 @@ enum
NETSTATE_ONLINE,
NETBANTYPE_SOFT=1,
NETBANTYPE_DROP=2
NETBANTYPE_DROP=2,
NETCREATE_FLAG_RANDOMPORT=1
};

View file

@ -7,7 +7,7 @@ bool CNetClient::Open(NETADDR BindAddr, int Flags)
{
// open socket
NETSOCKET Socket;
Socket = net_udp_create(BindAddr);
Socket = net_udp_create(BindAddr, (Flags&NETCREATE_FLAG_RANDOMPORT) ? 1 : 0);
if(!Socket.type)
return false;

View file

@ -14,7 +14,7 @@ bool CNetServer::Open(NETADDR BindAddr, CNetBan *pNetBan, int MaxClients, int Ma
mem_zero(this, sizeof(*this));
// open socket
m_Socket = net_udp_create(BindAddr);
m_Socket = net_udp_create(BindAddr, 0);
if(!m_Socket.type)
return false;

View file

@ -45,7 +45,7 @@ static int m_ConfigReorder = 0;
void Run(unsigned short Port, NETADDR Dest)
{
NETADDR Src = {NETTYPE_IPV4, {0,0,0,0}, Port};
NETSOCKET Socket = net_udp_create(Src);
NETSOCKET Socket = net_udp_create(Src, 0);
char aBuffer[1024*2];
int ID = 0;

View file

@ -11,7 +11,7 @@ void Run(NETADDR Dest)
for(int i = 0; i < NUM_SOCKETS; i++)
{
NETADDR BindAddr = {NETTYPE_IPV4, {0}, 0};
aSockets[i] = net_udp_create(BindAddr);
aSockets[i] = net_udp_create(BindAddr, 0);
}
while(1)