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. */
|
2022-04-22 23:04:48 +00:00
|
|
|
#include <base/logger.h>
|
2008-08-14 17:19:13 +00:00
|
|
|
#include <base/system.h>
|
2007-07-13 13:40:04 +00:00
|
|
|
|
|
|
|
#include <cstdlib>
|
2022-06-15 19:22:36 +00:00
|
|
|
#include <iterator> // std::size
|
2007-07-13 13:40:04 +00:00
|
|
|
|
2022-05-18 16:00:05 +00:00
|
|
|
#include <thread>
|
|
|
|
|
2022-06-04 08:02:45 +00:00
|
|
|
struct SPacket
|
2007-07-13 13:40:04 +00:00
|
|
|
{
|
2022-06-04 08:02:45 +00:00
|
|
|
SPacket *m_pPrev;
|
|
|
|
SPacket *m_pNext;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
NETADDR m_SendTo;
|
2021-06-23 05:05:49 +00:00
|
|
|
int64_t m_Timestamp;
|
2011-02-12 10:40:36 +00:00
|
|
|
int m_ID;
|
2010-05-29 07:25:38 +00:00
|
|
|
int m_DataSize;
|
|
|
|
char m_aData[1];
|
2007-07-13 13:40:04 +00:00
|
|
|
};
|
|
|
|
|
2022-06-04 08:02:45 +00:00
|
|
|
static SPacket *g_pFirst = (SPacket *)0;
|
|
|
|
static SPacket *g_pLast = (SPacket *)0;
|
|
|
|
static int g_CurrentLatency = 0;
|
2008-10-20 19:59:33 +00:00
|
|
|
|
2022-06-04 08:02:45 +00:00
|
|
|
struct SPingConfig
|
2009-01-21 19:12:09 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
int m_Base;
|
|
|
|
int m_Flux;
|
|
|
|
int m_Spike;
|
|
|
|
int m_Loss;
|
|
|
|
int m_Delay;
|
|
|
|
int m_DelayFreq;
|
2009-01-21 19:12:09 +00:00
|
|
|
};
|
|
|
|
|
2022-06-04 08:02:45 +00:00
|
|
|
static SPingConfig g_aConfigPings[] = {
|
2020-09-26 19:41:58 +00:00
|
|
|
// base flux spike loss delay delayfreq
|
|
|
|
{0, 0, 0, 0, 0, 0},
|
|
|
|
{40, 20, 100, 0, 0, 0},
|
|
|
|
{140, 40, 200, 0, 0, 0},
|
2009-01-21 19:12:09 +00:00
|
|
|
};
|
|
|
|
|
2022-06-04 08:02:45 +00:00
|
|
|
static int g_ConfigNumpingconfs = std::size(g_aConfigPings);
|
|
|
|
static int g_ConfigInterval = 10; // seconds between different pingconfigs
|
|
|
|
static int g_ConfigLog = 0;
|
|
|
|
static int g_ConfigReorder = 0;
|
2007-07-13 13:40:04 +00:00
|
|
|
|
2014-12-31 12:04:31 +00:00
|
|
|
void Run(unsigned short Port, NETADDR Dest)
|
2007-07-13 13:40:04 +00:00
|
|
|
{
|
2020-09-26 19:41:58 +00:00
|
|
|
NETADDR Src = {NETTYPE_IPV4, {0, 0, 0, 0}, Port};
|
2010-05-29 07:25:38 +00:00
|
|
|
NETSOCKET Socket = net_udp_create(Src);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2011-02-12 10:40:36 +00:00
|
|
|
int ID = 0;
|
2010-05-29 07:25:38 +00:00
|
|
|
int Delaycounter = 0;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2022-02-14 23:12:52 +00:00
|
|
|
while(true)
|
2007-07-13 13:40:04 +00:00
|
|
|
{
|
2022-06-04 08:02:45 +00:00
|
|
|
static int s_Lastcfg = 0;
|
|
|
|
int n = ((time_get() / time_freq()) / g_ConfigInterval) % g_ConfigNumpingconfs;
|
|
|
|
SPingConfig Ping = g_aConfigPings[n];
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2022-06-04 08:02:45 +00:00
|
|
|
if(n != s_Lastcfg)
|
2009-01-21 19:12:09 +00:00
|
|
|
dbg_msg("crapnet", "cfg = %d", n);
|
2022-06-04 08:02:45 +00:00
|
|
|
s_Lastcfg = n;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2018-02-04 15:00:47 +00:00
|
|
|
// handle incoming packets
|
2022-02-14 23:12:52 +00:00
|
|
|
while(true)
|
2007-07-13 13:40:04 +00:00
|
|
|
{
|
|
|
|
// fetch data
|
2010-05-29 07:25:38 +00:00
|
|
|
int DataTrash = 0;
|
|
|
|
NETADDR From;
|
2018-12-17 21:23:50 +00:00
|
|
|
unsigned char *pData;
|
2022-03-01 18:27:48 +00:00
|
|
|
int Bytes = net_udp_recv(Socket, &From, &pData);
|
2010-05-29 07:25:38 +00:00
|
|
|
if(Bytes <= 0)
|
2007-07-13 13:40:04 +00:00
|
|
|
break;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
if((rand() % 100) < Ping.m_Loss) // drop the packet
|
2008-10-20 19:59:33 +00:00
|
|
|
{
|
2022-06-04 08:02:45 +00:00
|
|
|
if(g_ConfigLog)
|
2008-11-08 14:04:16 +00:00
|
|
|
dbg_msg("crapnet", "dropped packet");
|
2008-10-19 09:10:55 +00:00
|
|
|
continue;
|
2008-10-20 19:59:33 +00:00
|
|
|
}
|
2007-07-13 13:40:04 +00:00
|
|
|
|
2011-04-13 18:37:12 +00:00
|
|
|
// create new packet
|
2022-06-04 08:02:45 +00:00
|
|
|
SPacket *p = (SPacket *)malloc(sizeof(SPacket) + Bytes);
|
2007-07-13 13:40:04 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(net_addr_comp(&From, &Dest) == 0)
|
|
|
|
p->m_SendTo = Src; // from the server
|
2007-07-13 13:40:04 +00:00
|
|
|
else
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
Src = From; // from the client
|
|
|
|
p->m_SendTo = Dest;
|
2007-07-13 13:40:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// queue packet
|
2022-06-04 08:02:45 +00:00
|
|
|
p->m_pPrev = g_pLast;
|
2010-05-29 07:25:38 +00:00
|
|
|
p->m_pNext = 0;
|
2022-06-04 08:02:45 +00:00
|
|
|
if(g_pLast)
|
|
|
|
g_pLast->m_pNext = p;
|
2007-07-13 13:40:04 +00:00
|
|
|
else
|
|
|
|
{
|
2022-06-04 08:02:45 +00:00
|
|
|
g_pFirst = p;
|
|
|
|
g_pLast = p;
|
2007-07-13 13:40:04 +00:00
|
|
|
}
|
2022-06-04 08:02:45 +00:00
|
|
|
g_pLast = p;
|
2007-07-13 13:40:04 +00:00
|
|
|
|
2009-01-24 14:32:12 +00:00
|
|
|
// set data in packet
|
2010-05-29 07:25:38 +00:00
|
|
|
p->m_Timestamp = time_get();
|
|
|
|
p->m_DataSize = Bytes;
|
2011-02-12 10:40:36 +00:00
|
|
|
p->m_ID = ID++;
|
2018-12-17 21:23:50 +00:00
|
|
|
mem_copy(p->m_aData, pData, Bytes);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2011-02-12 10:40:36 +00:00
|
|
|
if(ID > 20 && Bytes > 6 && DataTrash)
|
2008-03-18 01:30:47 +00:00
|
|
|
{
|
2020-09-26 19:41:58 +00:00
|
|
|
p->m_aData[6 + (rand() % (Bytes - 6))] = rand() & 255; // modify a byte
|
|
|
|
if((rand() % 10) == 0)
|
2008-03-18 01:30:47 +00:00
|
|
|
{
|
2020-09-26 19:41:58 +00:00
|
|
|
p->m_DataSize -= rand() % 32;
|
2010-05-29 07:25:38 +00:00
|
|
|
if(p->m_DataSize < 6)
|
|
|
|
p->m_DataSize = 6;
|
2008-03-18 01:30:47 +00:00
|
|
|
}
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(Delaycounter <= 0)
|
2009-01-24 14:32:12 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(Ping.m_Delay)
|
2020-09-26 19:41:58 +00:00
|
|
|
p->m_Timestamp += (time_freq() * 1000) / Ping.m_Delay;
|
2010-05-29 07:25:38 +00:00
|
|
|
Delaycounter = Ping.m_DelayFreq;
|
2009-01-24 14:32:12 +00:00
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
Delaycounter--;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2022-06-04 08:02:45 +00:00
|
|
|
if(g_ConfigLog)
|
2011-03-30 10:08:33 +00:00
|
|
|
{
|
|
|
|
char aAddrStr[NETADDR_MAXSTRSIZE];
|
2011-12-29 22:36:53 +00:00
|
|
|
net_addr_str(&From, aAddrStr, sizeof(aAddrStr), true);
|
2011-03-30 10:08:33 +00:00
|
|
|
dbg_msg("crapnet", "<< %08d %s (%d)", p->m_ID, aAddrStr, p->m_DataSize);
|
|
|
|
}
|
2007-07-13 13:40:04 +00:00
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2022-06-04 08:02:45 +00:00
|
|
|
SPacket *pNext = g_pFirst;
|
2022-02-14 23:12:52 +00:00
|
|
|
while(true)
|
2007-07-13 13:40:04 +00:00
|
|
|
{
|
2022-10-30 12:30:12 +00:00
|
|
|
SPacket *p = pNext;
|
2009-01-24 14:32:12 +00:00
|
|
|
if(!p)
|
|
|
|
break;
|
2010-05-29 07:25:38 +00:00
|
|
|
pNext = p->m_pNext;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2022-06-04 08:02:45 +00:00
|
|
|
if((time_get() - p->m_Timestamp) > g_CurrentLatency)
|
2007-07-13 13:40:04 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
char aFlags[] = " ";
|
2008-10-20 19:59:33 +00:00
|
|
|
|
2022-06-04 08:02:45 +00:00
|
|
|
if(g_ConfigReorder && (rand() % 2) == 0 && p->m_pNext)
|
2007-07-13 13:40:04 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
aFlags[0] = 'R';
|
2022-06-04 08:02:45 +00:00
|
|
|
p = g_pFirst->m_pNext;
|
2007-07-13 13:40:04 +00:00
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(p->m_pNext)
|
|
|
|
p->m_pNext->m_pPrev = p->m_pPrev;
|
2008-10-20 19:59:33 +00:00
|
|
|
else
|
2022-06-04 08:02:45 +00:00
|
|
|
g_pLast = p->m_pPrev;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(p->m_pPrev)
|
|
|
|
p->m_pPrev->m_pNext = p->m_pNext;
|
2008-10-20 19:59:33 +00:00
|
|
|
else
|
2022-06-04 08:02:45 +00:00
|
|
|
g_pFirst = p->m_pNext;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2007-07-13 13:40:04 +00:00
|
|
|
// send and remove packet
|
2010-05-29 07:25:38 +00:00
|
|
|
net_udp_send(Socket, &p->m_SendTo, p->m_aData, p->m_DataSize);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2007-07-13 13:40:04 +00:00
|
|
|
// update lag
|
2020-09-26 19:41:58 +00:00
|
|
|
double Flux = rand() / (double)RAND_MAX;
|
2010-05-29 07:25:38 +00:00
|
|
|
int MsSpike = Ping.m_Spike;
|
|
|
|
int MsFlux = Ping.m_Flux;
|
|
|
|
int MsPing = Ping.m_Base;
|
2022-06-04 08:02:45 +00:00
|
|
|
g_CurrentLatency = ((time_freq() * MsPing) / 1000) + (int64_t)(((time_freq() * MsFlux) / 1000) * Flux); // 50ms
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
if(MsSpike && (p->m_ID % 100) == 0)
|
2008-10-20 19:59:33 +00:00
|
|
|
{
|
2022-06-04 08:02:45 +00:00
|
|
|
g_CurrentLatency += (time_freq() * MsSpike) / 1000;
|
2010-05-29 07:25:38 +00:00
|
|
|
aFlags[1] = 'S';
|
2008-10-20 19:59:33 +00:00
|
|
|
}
|
|
|
|
|
2022-06-04 08:02:45 +00:00
|
|
|
if(g_ConfigLog)
|
2008-10-20 19:59:33 +00:00
|
|
|
{
|
2011-03-30 10:08:33 +00:00
|
|
|
char aAddrStr[NETADDR_MAXSTRSIZE];
|
2011-12-29 22:36:53 +00:00
|
|
|
net_addr_str(&p->m_SendTo, aAddrStr, sizeof(aAddrStr), true);
|
2011-03-30 10:08:33 +00:00
|
|
|
dbg_msg("crapnet", ">> %08d %s (%d) %s", p->m_ID, aAddrStr, p->m_DataSize, aFlags);
|
2008-10-20 19:59:33 +00:00
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2018-04-09 09:56:39 +00:00
|
|
|
free(p);
|
2007-07-13 13:40:04 +00:00
|
|
|
}
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2022-05-18 16:00:05 +00:00
|
|
|
std::this_thread::sleep_for(std::chrono::microseconds(1000));
|
2007-07-13 13:40:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-16 19:54:11 +00:00
|
|
|
int main(int argc, const char **argv)
|
2007-07-13 13:40:04 +00:00
|
|
|
{
|
2022-06-13 16:07:29 +00:00
|
|
|
CCmdlineFix CmdlineFix(&argc, &argv);
|
2022-04-22 23:04:48 +00:00
|
|
|
log_set_global_logger_default();
|
2020-09-26 19:41:58 +00:00
|
|
|
NETADDR Addr = {NETTYPE_IPV4, {127, 0, 0, 1}, 8303};
|
2010-05-29 07:25:38 +00:00
|
|
|
Run(8302, Addr);
|
2007-07-13 13:40:04 +00:00
|
|
|
return 0;
|
|
|
|
}
|