Skip to content

Commit

Permalink
separated connless packet handling and use random port for client's s…
Browse files Browse the repository at this point in the history
…erver connection
  • Loading branch information
oy committed Mar 18, 2015
1 parent 8af77b6 commit 7c43b76
Show file tree
Hide file tree
Showing 11 changed files with 71 additions and 34 deletions.
51 changes: 35 additions & 16 deletions src/base/system.c
Original file line number Diff line number Diff line change
Expand Up @@ -852,7 +852,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;

Expand Down Expand Up @@ -882,27 +882,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;
Expand All @@ -917,7 +936,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;
Expand All @@ -939,7 +958,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;
Expand Down Expand Up @@ -1076,7 +1095,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;
Expand All @@ -1092,7 +1111,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;
Expand Down
3 changes: 2 additions & 1 deletion src/base/system.h
Original file line number Diff line number Diff line change
Expand Up @@ -566,12 +566,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
Expand Down
32 changes: 22 additions & 10 deletions src/engine/client/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -894,7 +894,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
Expand Down Expand Up @@ -1434,14 +1434,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);
}
}

Expand Down Expand Up @@ -1657,7 +1663,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)
Expand All @@ -1676,7 +1682,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;
}
}
Expand Down Expand Up @@ -1704,7 +1710,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();
}

Expand Down Expand Up @@ -1758,9 +1764,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(net)");
return;
}
BindAddr.port = 0;
if(!m_ContactClient.Open(BindAddr, 0))
{
dbg_msg("client", "couldn't open socket");
dbg_msg("client", "couldn't open socket(contact)");
return;
}
}
Expand All @@ -1772,7 +1784,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();
Expand Down
1 change: 1 addition & 0 deletions src/engine/client/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,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;
Expand Down
4 changes: 2 additions & 2 deletions src/engine/client/serverbrowser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,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)
Expand Down Expand Up @@ -534,7 +534,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;
Expand Down
2 changes: 2 additions & 0 deletions src/engine/shared/engine.cpp
Original file line number Diff line number Diff line change
@@ -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>

Expand Down Expand Up @@ -57,6 +58,7 @@ class CEngine : public IEngine

CEngine(const char *pAppname)
{
srand(time_get());
dbg_logger_stdout();
dbg_logger_debugger();

Expand Down
4 changes: 3 additions & 1 deletion src/engine/shared/network.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ enum
NETSTATE_ONLINE,

NETBANTYPE_SOFT=1,
NETBANTYPE_DROP=2
NETBANTYPE_DROP=2,

NETCREATE_FLAG_RANDOMPORT=1
};


Expand Down
2 changes: 1 addition & 1 deletion src/engine/shared/network_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion src/engine/shared/network_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion src/tools/crapnet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ static int m_ConfigReorder = 0;
void Run(int 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;
Expand Down
2 changes: 1 addition & 1 deletion src/tools/packetgen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 7c43b76

Please sign in to comment.