Files
stationapi/udplibrary/udpserver.cpp
2019-03-10 11:55:27 -05:00

291 lines
7.7 KiB
C++
Executable File

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <assert.h>
#include <conio.h>
#include <ctype.h>
#include <sys\stat.h>
#include <sys\types.h>
#include <math.h>
#include <malloc.h>
#include <windows.h>
#include <winsock.h>
#ifdef _DEBUG
#include <crtdbg.h>
#endif
#include "UdpLibrary.hpp"
class Player : public UdpConnectionHandler
{
public:
Player(UdpConnection *con);
virtual ~Player();
virtual void OnRoutePacket(UdpConnection *con, const uchar *data, int dataLen);
public:
UdpConnection *mConnection;
};
class PlayerManager : public UdpManagerHandler
{
public:
PlayerManager();
~PlayerManager();
void AddPlayer(Player *player);
void GiveTime();
void DumpStats();
void SendPacketToAll(UdpChannel channel, void *data, int dataLen);
virtual void OnConnectRequest(UdpConnection *con);
protected:
Player *mPlayers[5000];
int mPlayersCount;
UdpMisc::ClockStamp mStartPacketTime;
int mLastIncomingLargeSoFar;
};
void MyCallbackRoutePacket(void *mainPassThrough, UdpConnection *con, const uchar *data, int dataLen);
void MyCallbackConnectRequest(void *mainPassThrough, UdpConnection *con);
UdpManager *myUdpManager;
int main(int argc, char **argv)
{
printf("UdpLibrary Test Server, press SHIFT-F12 to terminate.\n");
printf(" /PORT:xxx\n");
int listenPort = 9950;
for (int i = 0; i < argc; i++)
{
if (memicmp(argv[i], "/PORT:", 6) == 0)
listenPort = atoi(argv[i] + 6);
}
#ifdef _DEBUG
_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
#endif
//////////////////////////////////////////////////
// initialize everything
//////////////////////////////////////////////////
srand(clock());
PlayerManager *myPlayerManager = new PlayerManager();
UdpManager::Params params;
params.handler = myPlayerManager;
params.crcBytes = 2;
params.encryptMethod[0] = UdpManager::cEncryptMethodXorBuffer;
params.hashTableSize = 1000;
params.incomingBufferSize = 256 * 1024;
params.outgoingBufferSize = 256 * 1024;
params.clockSyncDelay = 0;
params.keepAliveDelay = 0;
params.maxConnections = 4000;
params.maxDataHoldSize = 400;
params.maxDataHoldTime = 60;
params.maxRawPacketSize = 256;
params.packetHistoryMax = 1000;
params.port = listenPort;
params.pooledPacketMax = 5000;
params.pooledPacketSize = 512;
#if 0
params.simulateIncomingByteRate = 2000;
params.simulateIncomingLossPercent = 0;
params.simulateOutgoingByteRate = 2000;
params.simulateOutgoingLossPercent = 0;
params.simulateDestinationOverloadLevel = 8000;
params.simulateOutgoingOverloadLevel = 8000;
#endif
params.reliable[0].maxInstandingPackets = 500;
params.reliable[0].maxOutstandingBytes = 200000;
params.reliable[0].maxOutstandingPackets = 500;
params.reliable[0].outOfOrder = false;
params.reliable[0].trickleRate = 0;
params.reliable[0].trickleSize = 0;
params.reliable[1].maxInstandingPackets = 30;
params.reliable[1].maxOutstandingBytes = 200000;
params.reliable[1].maxOutstandingPackets = 30;
params.reliable[1].outOfOrder = false;
params.reliable[1].trickleRate = 200;
params.reliable[1].trickleSize = 200;
params.reliable[2] = params.reliable[0];
params.reliable[2].outOfOrder = true;
params.reliable[3] = params.reliable[1];
params.reliable[3].outOfOrder = true;
myUdpManager = new UdpManager(&params);
//////////////////////////////////////////////////
// master loop (processing incoming data/connections)
//////////////////////////////////////////////////
printf("Listening on port %d\n", listenPort);
int count = 0;
for (;;)
{
// check for shutdown keys
if (kbhit())
{
int k = getch();
if ((k == 0 || k == 0xe0) && (getch() == 0x88))
break;
if (k == 32)
myPlayerManager->DumpStats();
}
if ((rand() % 300) == 0)
{
count++;
char buf[2000];
*(ushort *)buf = (ushort)count;
int len = (rand() % 1000) + 10;
*(ushort *)(buf + len - 2) = (ushort)count;
myPlayerManager->SendPacketToAll(cUdpChannelReliable1, buf, len);
printf("OUT=%d/%d LEN=%d \n", *(ushort *)buf, *(ushort *)(buf + len - 2), len);
}
myUdpManager->GiveTime();
myPlayerManager->GiveTime();
Sleep(10);
}
//////////////////////////////////////////////////
// terminate everything
//////////////////////////////////////////////////
delete myPlayerManager;
myUdpManager->Release();
return(0);
}
////////////////////////////////////////
// Player implementation
////////////////////////////////////////
Player::Player(UdpConnection *con)
{
mConnection = con;
mConnection->AddRef();
mConnection->SetHandler(this);
char hold[256];
printf("CONNECTION %s,%d \n", mConnection->GetDestinationIp().GetAddress(hold), mConnection->GetDestinationPort());
}
Player::~Player()
{
char hold[256];
printf("TERMINATE %s,%d \n", mConnection->GetDestinationIp().GetAddress(hold), mConnection->GetDestinationPort());
mConnection->SetHandler(NULL);
mConnection->Disconnect();
mConnection->Release();
}
void Player::OnRoutePacket(UdpConnection * /*con*/, const uchar *data, int dataLen)
{
for (int i = 1; i < dataLen; i++)
{
bool match = (data[i] == (i % 100));
assert(match);
}
char hold[256];
printf("FROM=%s,%d LEN=%d \n", mConnection->GetDestinationIp().GetAddress(hold), mConnection->GetDestinationPort(), dataLen);
#if 0
// reflect exact packet back to client
mConnection->Send(cUdpChannelReliable1, data, dataLen);
#endif
}
////////////////////////////////////////
// PlayerManager implementation
////////////////////////////////////////
PlayerManager::PlayerManager()
{
mPlayersCount = 0;
mStartPacketTime = 0;
mLastIncomingLargeSoFar = 90000000;
}
PlayerManager::~PlayerManager()
{
for (int i = mPlayersCount - 1; i >= 0; i--)
delete mPlayers[i];
}
void PlayerManager::OnConnectRequest(UdpConnection *con)
{
AddPlayer(new Player(con));
}
void PlayerManager::AddPlayer(Player *player)
{
mPlayers[mPlayersCount++] = player;
}
void PlayerManager::GiveTime()
{
// see if the player object is no longer connected
for (int i = 0; i < mPlayersCount; i++)
{
if (mPlayers[i]->mConnection->GetStatus() == UdpConnection::cStatusDisconnected || mPlayers[i]->mConnection->LastReceive() > 2000000)
{
Player *p = mPlayers[i];
mPlayersCount--;
memmove(&mPlayers[i], &mPlayers[i + 1], (mPlayersCount - i) * sizeof(Player *));
i--;
delete p;
}
}
if (mPlayersCount > 0)
{
UdpConnection::ChannelStatus cs;
mPlayers[0]->mConnection->GetChannelStatus(cUdpChannelReliable1, &cs);
UdpManagerStatistics ms;
myUdpManager->GetStats(&ms);
if (cs.incomingLargeSoFar < mLastIncomingLargeSoFar)
mStartPacketTime = UdpMisc::Clock();
mLastIncomingLargeSoFar = cs.incomingLargeSoFar;
int e = UdpMisc::ClockElapsed(mStartPacketTime);
if (e > 0)
fprintf(stderr, "%d of %d (%d bps)(%d) \r", cs.incomingLargeSoFar, cs.incomingLargeTotal, (int)(((__int64)cs.incomingLargeSoFar * 1000) / (__int64)e), ms.packetsReceived);
}
}
void PlayerManager::SendPacketToAll(UdpChannel channel, void *data, int dataLen)
{
LogicalPacket *lp = myUdpManager->CreatePacket(data, dataLen);
for (int i = 0; i < mPlayersCount; i++)
{
mPlayers[i]->mConnection->Send(channel, lp);
}
lp->Release();
}
void PlayerManager::DumpStats()
{
for (int i = 0; i < mPlayersCount; i++)
{
UdpConnectionStatistics stats;
mPlayers[i]->mConnection->GetStats(&stats);
char hold[256];
printf("%s,%d AVE=%d HIGH=%d LOW=%d MSTR=%d,%d CRC=%I64d ORD=%I64d %I64d<<%I64d %I64d>>%I64d\n", mPlayers[i]->mConnection->GetDestinationIp().GetAddress(hold), mPlayers[i]->mConnection->GetDestinationPort()
, stats.averagePingTime, stats.highPingTime, stats.lowPingTime, stats.masterPingTime, stats.masterPingAge, stats.crcRejectedPackets, stats.orderRejectedPackets, stats.syncOurReceived, stats.syncTheirSent
, stats.syncOurSent, stats.syncTheirReceived);
}
}