/* (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 #include struct CPacket { CPacket *m_pPrev; CPacket *m_pNext; NETADDR m_SendTo; int64_t m_Timestamp; int m_ID; int m_DataSize; char m_aData[1]; }; static CPacket *m_pFirst = (CPacket *)0; static CPacket *m_pLast = (CPacket *)0; static int m_CurrentLatency = 0; struct CPingConfig { int m_Base; int m_Flux; int m_Spike; int m_Loss; int m_Delay; int m_DelayFreq; }; static CPingConfig m_aConfigPings[] = { // base flux spike loss delay delayfreq {0, 0, 0, 0, 0, 0}, {40, 20, 100, 0, 0, 0}, {140, 40, 200, 0, 0, 0}, }; static int m_ConfigNumpingconfs = sizeof(m_aConfigPings) / sizeof(CPingConfig); static int m_ConfigInterval = 10; // seconds between different pingconfigs static int m_ConfigLog = 0; 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); int ID = 0; int Delaycounter = 0; while(true) { static int Lastcfg = 0; int n = ((time_get() / time_freq()) / m_ConfigInterval) % m_ConfigNumpingconfs; CPingConfig Ping = m_aConfigPings[n]; if(n != Lastcfg) dbg_msg("crapnet", "cfg = %d", n); Lastcfg = n; // handle incoming packets while(true) { // fetch data int DataTrash = 0; NETADDR From; unsigned char *pData; int Bytes = net_udp_recv(Socket, &From, &pData); if(Bytes <= 0) break; if((rand() % 100) < Ping.m_Loss) // drop the packet { if(m_ConfigLog) dbg_msg("crapnet", "dropped packet"); continue; } // create new packet CPacket *p = (CPacket *)malloc(sizeof(CPacket) + Bytes); if(net_addr_comp(&From, &Dest) == 0) p->m_SendTo = Src; // from the server else { Src = From; // from the client p->m_SendTo = Dest; } // queue packet p->m_pPrev = m_pLast; p->m_pNext = 0; if(m_pLast) m_pLast->m_pNext = p; else { m_pFirst = p; m_pLast = p; } m_pLast = p; // set data in packet p->m_Timestamp = time_get(); p->m_DataSize = Bytes; p->m_ID = ID++; mem_copy(p->m_aData, pData, Bytes); if(ID > 20 && Bytes > 6 && DataTrash) { p->m_aData[6 + (rand() % (Bytes - 6))] = rand() & 255; // modify a byte if((rand() % 10) == 0) { p->m_DataSize -= rand() % 32; if(p->m_DataSize < 6) p->m_DataSize = 6; } } if(Delaycounter <= 0) { if(Ping.m_Delay) p->m_Timestamp += (time_freq() * 1000) / Ping.m_Delay; Delaycounter = Ping.m_DelayFreq; } Delaycounter--; if(m_ConfigLog) { char aAddrStr[NETADDR_MAXSTRSIZE]; net_addr_str(&From, aAddrStr, sizeof(aAddrStr), true); dbg_msg("crapnet", "<< %08d %s (%d)", p->m_ID, aAddrStr, p->m_DataSize); } } // /*while(1) {*/ CPacket *p = 0; CPacket *pNext = m_pFirst; while(true) { p = pNext; if(!p) break; pNext = p->m_pNext; if((time_get() - p->m_Timestamp) > m_CurrentLatency) { char aFlags[] = " "; if(m_ConfigReorder && (rand() % 2) == 0 && p->m_pNext) { aFlags[0] = 'R'; p = m_pFirst->m_pNext; } if(p->m_pNext) p->m_pNext->m_pPrev = p->m_pPrev; else m_pLast = p->m_pPrev; if(p->m_pPrev) p->m_pPrev->m_pNext = p->m_pNext; else m_pFirst = p->m_pNext; /*CPacket *cur = first; while(cur) { dbg_assert(cur != p, "p still in list"); cur = cur->next; }*/ // send and remove packet //if((rand()%20) != 0) // heavy packetloss net_udp_send(Socket, &p->m_SendTo, p->m_aData, p->m_DataSize); // update lag double Flux = rand() / (double)RAND_MAX; int MsSpike = Ping.m_Spike; int MsFlux = Ping.m_Flux; int MsPing = Ping.m_Base; m_CurrentLatency = ((time_freq() * MsPing) / 1000) + (int64_t)(((time_freq() * MsFlux) / 1000) * Flux); // 50ms if(MsSpike && (p->m_ID % 100) == 0) { m_CurrentLatency += (time_freq() * MsSpike) / 1000; aFlags[1] = 'S'; } if(m_ConfigLog) { char aAddrStr[NETADDR_MAXSTRSIZE]; net_addr_str(&p->m_SendTo, aAddrStr, sizeof(aAddrStr), true); dbg_msg("crapnet", ">> %08d %s (%d) %s", p->m_ID, aAddrStr, p->m_DataSize, aFlags); } free(p); } } thread_sleep(1000); } } int main(int argc, const char **argv) { cmdline_fix(&argc, &argv); NETADDR Addr = {NETTYPE_IPV4, {127, 0, 0, 1}, 8303}; dbg_logger_stdout(); Run(8302, Addr); cmdline_free(argc, argv); return 0; }