mirror of
https://github.com/rajkosto/mxoemu
synced 2026-08-14 02:26:05 -04:00
Ported udp server to alhem sockets as well, more fixes/workarounds
This commit is contained in:
parent
2c29aedc51
commit
885d3bc8d2
8 changed files with 257 additions and 225 deletions
|
|
@ -33,10 +33,11 @@
|
|||
#include "Database/Database.h"
|
||||
#include "Log.h"
|
||||
#include "GameServer.h"
|
||||
#include "GameSocket.h"
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
GameClient::GameClient(struct sockaddr_in address, SOCKET *sock)
|
||||
GameClient::GameClient(shared_ptr<SocketAddress> address, GameSocket *sock)
|
||||
{
|
||||
m_sock = sock;
|
||||
m_address = address;
|
||||
|
|
@ -70,7 +71,7 @@ GameClient::~GameClient()
|
|||
}
|
||||
}
|
||||
|
||||
void GameClient::HandlePacket(char *pData, uint16 nLength)
|
||||
void GameClient::HandlePacket( const char *pData, uint16 nLength )
|
||||
{
|
||||
if (nLength < 1 || m_validClient == false)
|
||||
return;
|
||||
|
|
@ -160,8 +161,7 @@ void GameClient::HandlePacket(char *pData, uint16 nLength)
|
|||
}
|
||||
beatPacket << uint16(swap16(numberOfBeats));
|
||||
|
||||
int clientlen=sizeof(m_address);
|
||||
sendto(*m_sock, beatPacket.contents(), beatPacket.size(), 0, (struct sockaddr*)&m_address, clientlen);
|
||||
m_sock->SendToBuf(*m_address, beatPacket.contents(), beatPacket.size(), 0);
|
||||
}
|
||||
|
||||
//notify margin that udp session is established
|
||||
|
|
@ -179,8 +179,7 @@ void GameClient::HandlePacket(char *pData, uint16 nLength)
|
|||
|
||||
if (m_worldLoaded == true && pData[0] != 0x01) // Ping...just reply with the same thing
|
||||
{
|
||||
int clientlen=sizeof(m_address);
|
||||
sendto(*m_sock, pData, nLength, 0, (struct sockaddr*)&m_address,clientlen );
|
||||
m_sock->SendToBuf(*m_address, pData, nLength, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -347,7 +346,7 @@ void GameClient::HandleOrdered( ByteBuffer &orderedData )
|
|||
}
|
||||
}
|
||||
|
||||
SequencedPacket GameClient::Decrypt(char *pData, uint16 nLength)
|
||||
SequencedPacket GameClient::Decrypt(const char *pData, uint16 nLength)
|
||||
{
|
||||
EncryptedPacket decryptedData(ByteBuffer(pData,nLength),m_TFDecrypt.get());
|
||||
return SequencedPacket(decryptedData);
|
||||
|
|
@ -363,8 +362,7 @@ void GameClient::SendEncrypted(SequencedPacket withSequences)
|
|||
sendMe << uint8(1);
|
||||
sendMe.append(withEncryption.toCipherText(m_TFEncrypt.get()));
|
||||
|
||||
int clientlen=sizeof(m_address);
|
||||
sendto(*m_sock, sendMe.contents(), (int)sendMe.size(), 0, (struct sockaddr*)&m_address,clientlen);
|
||||
m_sock->SendToBuf(*m_address, sendMe.contents(), sendMe.size(), 0);
|
||||
}
|
||||
|
||||
void GameClient::PSSChanged( uint8 oldPSS,uint8 newPSS )
|
||||
|
|
@ -575,10 +573,10 @@ void GameClient::CheckAndResend()
|
|||
bool deleted = false;
|
||||
|
||||
uint32 currTime = getMSTime();
|
||||
if (currTime - it->msTimeSent > 500) //500 is timeout for resend
|
||||
if (currTime - it->msTimeSent > 200) //200 is timeout for resend
|
||||
{
|
||||
//client obviously doesnt want to ack this packet
|
||||
if (it->resentCounter > 2)
|
||||
if (it->resentCounter > 10)
|
||||
{
|
||||
ByteBuffer resentPacketDumpedData;
|
||||
try
|
||||
|
|
@ -661,6 +659,7 @@ void GameClient::CheckAndResend()
|
|||
//reverse iterator because push_front inserts into reverse anyway
|
||||
for (list<MsgBlock>::reverse_iterator hurr=newPacket->msgBlocks.rbegin();hurr!=newPacket->msgBlocks.rend();++hurr)
|
||||
{
|
||||
uint16 oldSeqz = m_serverSequence;
|
||||
increaseServerSequence();
|
||||
m_sendQueue.push_front( PacketInQueue(oldClientPSS,m_serverSequence,oldClientSeq,oldAck,shared_ptr<OrderedPacket>(new OrderedPacket(*hurr))) );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,33 +29,27 @@
|
|||
#include "PlayerObject.h"
|
||||
#include "MessageTypes.h"
|
||||
#include "Log.h"
|
||||
#include <Sockets/SocketAddress.h>
|
||||
|
||||
class GameClient
|
||||
{
|
||||
public:
|
||||
GameClient(sockaddr_in address, SOCKET *sock);
|
||||
GameClient(shared_ptr<SocketAddress> address, class GameSocket *sock);
|
||||
~GameClient();
|
||||
|
||||
inline uint32 LastActive() { return m_lastActivity; }
|
||||
inline bool IsValid() { return m_validClient; }
|
||||
void Invalidate()
|
||||
{
|
||||
m_validClient=false;
|
||||
}
|
||||
string Address()
|
||||
{
|
||||
stringstream addressStr;
|
||||
addressStr << inet_ntoa(m_address.sin_addr) << ":" << ntohs(m_address.sin_port);
|
||||
return addressStr.str();
|
||||
}
|
||||
void Invalidate() { m_validClient=false;}
|
||||
string Address() { return m_address->Convert(true); }
|
||||
uint32 GetSessionId()
|
||||
{
|
||||
if (m_encryptionInitialized == true)
|
||||
return m_sessionId;
|
||||
return 0;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void HandlePacket(char *pData, uint16 Length);
|
||||
void HandlePacket(const char *pData, uint16 nLength);
|
||||
void HandleEncrypted(ByteBuffer &srcData);
|
||||
void HandleOther(ByteBuffer &otherData);
|
||||
void HandleOrdered(ByteBuffer &orderedData);
|
||||
|
|
@ -80,12 +74,49 @@ public:
|
|||
void FlushQueue();
|
||||
void CheckAndResend();
|
||||
private:
|
||||
SequencedPacket Decrypt(char *pData, uint16 nLength);
|
||||
SequencedPacket Decrypt(const char *pData, uint16 nLength);
|
||||
void PSSChanged(uint8 oldPSS,uint8 newPSS);
|
||||
bool PacketReceived(uint16 clientSeq)
|
||||
{
|
||||
bool wraparound=false;
|
||||
|
||||
if (isSequenceMoreRecent(clientSeq,m_lastClientSequence) == true)
|
||||
{
|
||||
if ( (m_lastClientSequence > 4096/2) && clientSeq < 4096/2 )
|
||||
wraparound=true;
|
||||
|
||||
m_lastClientSequence = clientSeq;
|
||||
}
|
||||
|
||||
if (wraparound == true)
|
||||
{
|
||||
size_t removedPacketsToAck = 0;
|
||||
for (deque<uint16>::iterator it=m_packetsToAck.begin();it!=m_packetsToAck.end();)
|
||||
{
|
||||
if (*it < 4096/2)
|
||||
{
|
||||
it = m_packetsToAck.erase(it);
|
||||
removedPacketsToAck++;
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
size_t flaggedActualPackets = 0;
|
||||
for (sendQueueList::iterator it=m_sendQueue.begin();it!=m_sendQueue.end();++it)
|
||||
{
|
||||
if (it->client_sequence < 4096/2)
|
||||
{
|
||||
it->client_sequence = m_lastClientSequence;
|
||||
it->ack = false;
|
||||
flaggedActualPackets++;
|
||||
}
|
||||
}
|
||||
|
||||
INFO_LOG(format("(%1) Purged %2% potential and %3% real acks due to client wraparound") % Address() % removedPacketsToAck % flaggedActualPackets);
|
||||
}
|
||||
|
||||
if (find(m_packetsToAck.begin(),m_packetsToAck.end(),clientSeq) != m_packetsToAck.end())
|
||||
return false;
|
||||
|
|
@ -196,14 +227,14 @@ private:
|
|||
increaseServerSequence();
|
||||
uint16 theServerSeq = m_serverSequence;
|
||||
ByteBuffer outputData = dataToSend->toBuf();
|
||||
if (outputData.size() > 0)
|
||||
/* if (outputData.size() > 0)
|
||||
{
|
||||
DEBUG_LOG(format("(%s) Queue SSeq: %d CSeq: %d Ack: %d Data: |%s|") % Address() % theServerSeq % clientSeq % ackPacket % Bin2Hex(outputData));
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(format("(%s) Queue SSeq: %d CSeq: %d Ack: %d No Data") % Address() % theServerSeq % clientSeq % ackPacket);
|
||||
}
|
||||
}*/
|
||||
m_sendQueue.push_back(PacketInQueue(m_clientPSS,theServerSeq,clientSeq,ackPacket,dataToSend,immediateOnly));
|
||||
}
|
||||
void AddPacketToQueue(msgBaseClassPtr dataToSend, bool immediateOnly=false)
|
||||
|
|
@ -228,8 +259,8 @@ private:
|
|||
bool m_characterSpawned;
|
||||
|
||||
// Master Sock handle, client's address structure, last received packet
|
||||
SOCKET *m_sock;
|
||||
struct sockaddr_in m_address;
|
||||
class GameSocket *m_sock;
|
||||
shared_ptr<SocketAddress> m_address;
|
||||
uint32 m_lastActivity;
|
||||
uint32 m_lastPacketReceivedMS;
|
||||
uint32 m_lastOrderedFlush;
|
||||
|
|
@ -247,7 +278,9 @@ private:
|
|||
{
|
||||
m_serverSequence++;
|
||||
if (m_serverSequence == 4096)
|
||||
{
|
||||
m_serverSequence=0;
|
||||
}
|
||||
}
|
||||
uint16 m_lastClientSequence;
|
||||
inline bool isSequenceMoreRecent( uint16 biggerSequence, uint16 smallerSequence, uint32 max_sequence=4096 )
|
||||
|
|
|
|||
|
|
@ -26,217 +26,64 @@
|
|||
#include "Log.h"
|
||||
#include "Timer.h"
|
||||
#include "Config.h"
|
||||
#include "Sockets.h"
|
||||
#include "GameSocket.h"
|
||||
#include <Sockets/Ipv4Address.h>
|
||||
|
||||
initialiseSingleton( GameServer );
|
||||
|
||||
bool GameServer::Start()
|
||||
{
|
||||
int Port;
|
||||
|
||||
Port = sConfig.GetIntDefault("GameServer.Port", 10000);
|
||||
|
||||
int Port = sConfig.GetIntDefault("GameServer.Port", 10000);
|
||||
INFO_LOG(format("Starting Game server on port %1%") % Port);
|
||||
|
||||
#if PLATFORM == PLATFORM_WIN32
|
||||
// Winsock Startup
|
||||
WSADATA wsa;
|
||||
memset(&wsa, 0x0, sizeof(WSADATA));
|
||||
if( WSAStartup( MAKEWORD(2,0), &wsa ) != 0x0 )
|
||||
m_mainSocket.reset(new GameSocket(m_udpHandler));
|
||||
port_t thePortToBind = Port;
|
||||
if (m_mainSocket->Bind(thePortToBind) != 0)
|
||||
{
|
||||
CRITICAL_LOG("Unable to initialize WinSock2!");
|
||||
ERROR_LOG(format("Error binding Game Server to port %1%") % thePortToBind);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
|
||||
if (m_socket == INVALID_SOCKET)
|
||||
{
|
||||
CRITICAL_LOG("Unable to create socket!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 0 = Blocking sockets - 1 = Non-blocking
|
||||
unsigned long mode = 1;
|
||||
|
||||
#if PLATFORM == PLATFORM_WIN32
|
||||
int ret = ioctlsocket(m_socket, FIONBIO, &mode );
|
||||
#else
|
||||
int ret = ioctl(m_socket, FIONBIO, &mode);
|
||||
#endif
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
CRITICAL_LOG("Unable to set socket to non blocking!");
|
||||
m_socket = INVALID_SOCKET;
|
||||
return false;
|
||||
}
|
||||
|
||||
memset(&listen_addr, 0, sizeof(listen_addr));
|
||||
listen_addr.sin_family = AF_INET;
|
||||
listen_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
listen_addr.sin_port = htons(Port);
|
||||
|
||||
if (::bind(m_socket, (struct sockaddr *) &listen_addr, sizeof(listen_addr)) < 0)
|
||||
{
|
||||
CRITICAL_LOG("Unable to bind socket!");
|
||||
m_socket = INVALID_SOCKET;
|
||||
return false;
|
||||
}
|
||||
m_lastCleanupTime = getTime();
|
||||
m_udpHandler.Add(m_mainSocket.get());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GameServer::Stop()
|
||||
{
|
||||
m_mainSocket.reset();
|
||||
INFO_LOG("Game Server shutdown");
|
||||
|
||||
#if PLATFORM == PLATFORM_WIN32
|
||||
closesocket(m_socket);
|
||||
WSACleanup();
|
||||
#else
|
||||
close(m_socket);
|
||||
#endif
|
||||
|
||||
m_socket = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
void GameServer::Loop(void)
|
||||
{
|
||||
FD_ZERO(&m_readable);
|
||||
FD_SET(m_socket, &m_readable);
|
||||
if (m_mainSocket == NULL)
|
||||
return;
|
||||
|
||||
m_timeout.tv_sec = 0;
|
||||
m_timeout.tv_usec = 100;
|
||||
|
||||
if (select(0, &m_readable, NULL, NULL, &m_timeout) == SOCKET_ERROR)
|
||||
{
|
||||
CRITICAL_LOG("Select() Failed, Shutting down World server");
|
||||
Stop();
|
||||
}
|
||||
|
||||
if (FD_ISSET(m_socket, &m_readable))
|
||||
{
|
||||
Handle_Incoming();
|
||||
}
|
||||
|
||||
CheckAndResend();
|
||||
|
||||
m_currTime = getTime();
|
||||
if ((m_currTime - m_lastCleanupTime) >= 5)
|
||||
{
|
||||
// Do client cleanup
|
||||
GClientList::iterator i = m_clients.begin();
|
||||
for (;;)
|
||||
{
|
||||
if (i == m_clients.end())
|
||||
break;
|
||||
|
||||
GameClient *Client = (*i).second;
|
||||
if (Client->IsValid() == false || (m_currTime
|
||||
- Client->LastActive()) >= 20)
|
||||
{
|
||||
DEBUG_LOG( format("Routine dead client removal [%1%]") % Client->Address() );
|
||||
m_clients.erase(i++);
|
||||
delete Client;
|
||||
}
|
||||
else
|
||||
++i;
|
||||
}
|
||||
m_lastCleanupTime = m_currTime;
|
||||
}
|
||||
m_mainSocket->PruneDeadClients();
|
||||
m_mainSocket->CheckAndResend();
|
||||
m_udpHandler.Select(0,4000); //4ms
|
||||
}
|
||||
|
||||
void GameServer::Handle_Incoming()
|
||||
{
|
||||
char Buffer[RECV_BUFFER_SIZE];
|
||||
|
||||
socklen_t addr_len = sizeof(inc_addr);
|
||||
|
||||
uint16 len = 0;
|
||||
std::stringstream IP;
|
||||
|
||||
len = recvfrom(m_socket, Buffer, RECV_BUFFER_SIZE, 0,
|
||||
(struct sockaddr*) &inc_addr, &addr_len);
|
||||
|
||||
if ((len > 0 && len <= RECV_BUFFER_SIZE && errno != EWOULDBLOCK) ||
|
||||
(len > 0 && len <= RECV_BUFFER_SIZE))
|
||||
{
|
||||
IP << inet_ntoa(inc_addr.sin_addr) << ":" << inc_addr.sin_port;
|
||||
GClientList::iterator i = m_clients.find(IP.str());
|
||||
if (i != m_clients.end())
|
||||
{
|
||||
if (m_clients[IP.str()]->IsValid() == false)
|
||||
{
|
||||
DEBUG_LOG( format("Removing dead client [%1%]") % IP.str() );
|
||||
delete m_clients[IP.str()];
|
||||
m_clients.erase(m_clients.find(IP.str()));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_clients[IP.str()]->HandlePacket(Buffer, len);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_clients[IP.str()] = new GameClient(inc_addr, &m_socket);
|
||||
DEBUG_LOG(format ("Client connected [%1%], now have [%2%] clients")
|
||||
% IP.str() % Clients_Connected());
|
||||
m_clients[IP.str()]->HandlePacket(Buffer, len);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GameServer::Broadcast( const ByteBuffer &message )
|
||||
{
|
||||
/*for (GClientList::iterator i = m_clients.begin();i != m_clients.end();++i)
|
||||
if (m_mainSocket != NULL)
|
||||
{
|
||||
i->second->QueueState(message);
|
||||
}*/
|
||||
}
|
||||
|
||||
GameClient *GameServer::GetClientWithSessionId(uint32 sessionId)
|
||||
{
|
||||
for (GClientList::iterator it=m_clients.begin();it!=m_clients.end();++it)
|
||||
{
|
||||
if (it->second->GetSessionId() == sessionId)
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void GameServer::CheckAndResend()
|
||||
{
|
||||
for (GClientList::iterator it=m_clients.begin();it!=m_clients.end();++it)
|
||||
{
|
||||
it->second->CheckAndResend();
|
||||
m_mainSocket->Broadcast(message);
|
||||
}
|
||||
}
|
||||
|
||||
void GameServer::AnnounceStateUpdate( class GameClient* clFrom,msgBaseClassPtr theMsg, bool immediateOnly )
|
||||
void GameServer::AnnounceStateUpdate( GameClient* clFrom,msgBaseClassPtr theMsg, bool immediateOnly )
|
||||
{
|
||||
for (GClientList::iterator it=m_clients.begin();it!=m_clients.end();++it)
|
||||
if (m_mainSocket != NULL)
|
||||
{
|
||||
if (it->second!=clFrom)
|
||||
{
|
||||
it->second->QueueState(theMsg,immediateOnly);
|
||||
}
|
||||
m_mainSocket->AnnounceStateUpdate(clFrom,theMsg,immediateOnly);
|
||||
}
|
||||
}
|
||||
|
||||
void GameServer::AnnounceCommand( class GameClient* clFrom,msgBaseClassPtr theCmd )
|
||||
void GameServer::AnnounceCommand( GameClient* clFrom,msgBaseClassPtr theCmd )
|
||||
{
|
||||
for (GClientList::iterator it=m_clients.begin();it!=m_clients.end();++it)
|
||||
if (m_mainSocket != NULL)
|
||||
{
|
||||
if (it->second!=clFrom)
|
||||
{
|
||||
it->second->QueueCommand(theCmd);
|
||||
}
|
||||
m_mainSocket->AnnounceCommand(clFrom,theCmd);
|
||||
}
|
||||
}
|
||||
|
|
@ -25,12 +25,10 @@
|
|||
#include "Common.h"
|
||||
#include "ByteBuffer.h"
|
||||
#include "Singleton.h"
|
||||
#include "Sockets.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include <Sockets/SocketHandler.h>
|
||||
#include "MessageTypes.h"
|
||||
|
||||
#define RECV_BUFFER_SIZE 2048
|
||||
|
||||
class GameServer : public Singleton <GameServer>
|
||||
{
|
||||
public:
|
||||
|
|
@ -39,30 +37,15 @@ public:
|
|||
bool Start();
|
||||
void Stop();
|
||||
void Loop();
|
||||
int Clients_Connected(void) { return (int)m_clients.size(); }
|
||||
void Handle_Incoming();
|
||||
ObjectMgr &getObjMgr() { return m_objMgr; }
|
||||
class GameClient *GetClientWithSessionId(uint32 sessionId);
|
||||
void CheckAndResend();
|
||||
void Broadcast(const ByteBuffer &message);
|
||||
void AnnounceStateUpdate(class GameClient* clFrom,msgBaseClassPtr theMsg, bool immediateOnly=false);
|
||||
void AnnounceCommand(class GameClient* clFrom,msgBaseClassPtr theCmd);
|
||||
ObjectMgr &getObjMgr() { return m_objMgr; }
|
||||
|
||||
private:
|
||||
// Client List
|
||||
typedef std::map<std::string, class GameClient*> GClientList;
|
||||
GClientList m_clients;
|
||||
struct sockaddr_in listen_addr, inc_addr;
|
||||
|
||||
// Socket stuff
|
||||
SOCKET m_socket;
|
||||
fd_set m_readable;
|
||||
|
||||
struct timeval m_timeout;
|
||||
uint32 m_lastCleanupTime;
|
||||
uint32 m_currTime;
|
||||
|
||||
ObjectMgr m_objMgr;
|
||||
SocketHandler m_udpHandler;
|
||||
shared_ptr<class GameSocket> m_mainSocket;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
126
Reality/Source/GameSocket.cpp
Normal file
126
Reality/Source/GameSocket.cpp
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
#include "Common.h"
|
||||
#include "GameSocket.h"
|
||||
#include "Log.h"
|
||||
#include "GameClient.h"
|
||||
#include "Timer.h"
|
||||
#include <Sockets/Ipv4Address.h>
|
||||
|
||||
GameSocket::GameSocket( ISocketHandler& theHandler ) : UdpSocket(theHandler)
|
||||
{
|
||||
m_lastCleanupTime = getTime();
|
||||
}
|
||||
|
||||
GameSocket::~GameSocket()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void GameSocket::OnRawData( const char *pData,size_t len,struct sockaddr *sa_from,socklen_t sa_len )
|
||||
{
|
||||
stringstream IP;
|
||||
struct sockaddr_in inc_addr;
|
||||
memcpy(&inc_addr,sa_from,sa_len);
|
||||
shared_ptr<SocketAddress> theAddr(new Ipv4Address(inc_addr));
|
||||
|
||||
if (theAddr->IsValid() == false)
|
||||
return;
|
||||
|
||||
string IPStr = theAddr->Convert(true);
|
||||
GClientList::iterator it = m_clients.find(IPStr);
|
||||
if (it != m_clients.end())
|
||||
{
|
||||
GameClient *Client = it->second;
|
||||
if (Client->IsValid() == false)
|
||||
{
|
||||
DEBUG_LOG( format("Removing dead client [%1%]") % IPStr );
|
||||
m_clients.erase(it);
|
||||
delete Client;
|
||||
}
|
||||
else
|
||||
{
|
||||
Client->HandlePacket(pData, len);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_clients[IPStr] = new GameClient(theAddr, this);
|
||||
DEBUG_LOG(format ("Client connected [%1%], now have [%2%] clients")
|
||||
% IPStr % Clients_Connected());
|
||||
|
||||
m_clients[IPStr]->HandlePacket(pData, len);
|
||||
}
|
||||
}
|
||||
|
||||
void GameSocket::PruneDeadClients()
|
||||
{
|
||||
m_currTime = getTime();
|
||||
if ((m_currTime - m_lastCleanupTime) >= 5)
|
||||
{
|
||||
// Do client cleanup
|
||||
for (GClientList::iterator it=m_clients.begin();it!=m_clients.end();)
|
||||
{
|
||||
GameClient *Client = it->second;
|
||||
if (Client->IsValid() == false || (m_currTime - Client->LastActive()) >= 20)
|
||||
{
|
||||
DEBUG_LOG( format("Routine dead client removal [%1%]") % Client->Address() );
|
||||
m_clients.erase(it++);
|
||||
delete Client;
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
m_lastCleanupTime = m_currTime;
|
||||
}
|
||||
}
|
||||
|
||||
GameClient * GameSocket::GetClientWithSessionId( uint32 sessionId )
|
||||
{
|
||||
for (GClientList::iterator it=m_clients.begin();it!=m_clients.end();++it)
|
||||
{
|
||||
if (it->second->GetSessionId() == sessionId)
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void GameSocket::CheckAndResend()
|
||||
{
|
||||
for (GClientList::iterator it=m_clients.begin();it!=m_clients.end();++it)
|
||||
{
|
||||
it->second->CheckAndResend();
|
||||
}
|
||||
}
|
||||
|
||||
void GameSocket::Broadcast( const ByteBuffer &message )
|
||||
{
|
||||
/*for (GClientList::iterator i = m_clients.begin();i != m_clients.end();++i)
|
||||
{
|
||||
i->second->QueueState(message);
|
||||
}*/
|
||||
}
|
||||
|
||||
void GameSocket::AnnounceStateUpdate( GameClient* clFrom,msgBaseClassPtr theMsg, bool immediateOnly/*=false*/ )
|
||||
{
|
||||
for (GClientList::iterator it=m_clients.begin();it!=m_clients.end();++it)
|
||||
{
|
||||
if (it->second!=clFrom)
|
||||
{
|
||||
it->second->QueueState(theMsg,immediateOnly);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GameSocket::AnnounceCommand( GameClient* clFrom,msgBaseClassPtr theCmd )
|
||||
{
|
||||
for (GClientList::iterator it=m_clients.begin();it!=m_clients.end();++it)
|
||||
{
|
||||
if (it->second!=clFrom)
|
||||
{
|
||||
it->second->QueueCommand(theCmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
34
Reality/Source/GameSocket.h
Normal file
34
Reality/Source/GameSocket.h
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#ifndef MXOSIM_GAMESOCKET_H
|
||||
#define MXOSIM_GAMESOCKET_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "ByteBuffer.h"
|
||||
#include "MessageTypes.h"
|
||||
#include <Sockets/UdpSocket.h>
|
||||
#include <Sockets/ISocketHandler.h>
|
||||
#include <Sockets/SocketAddress.h>
|
||||
|
||||
class GameSocket : public UdpSocket
|
||||
{
|
||||
public:
|
||||
GameSocket(ISocketHandler& theHandler);
|
||||
~GameSocket();
|
||||
void OnRawData( const char *pData,size_t len,struct sockaddr *sa_from,socklen_t sa_len );
|
||||
void PruneDeadClients();
|
||||
void CheckAndResend();
|
||||
size_t Clients_Connected(void) { return m_clients.size(); }
|
||||
class GameClient *GetClientWithSessionId(uint32 sessionId);
|
||||
void Broadcast(const ByteBuffer &message);
|
||||
void AnnounceStateUpdate(class GameClient* clFrom,msgBaseClassPtr theMsg, bool immediateOnly=false);
|
||||
void AnnounceCommand(class GameClient* clFrom,msgBaseClassPtr theCmd);
|
||||
private:
|
||||
// Client List
|
||||
typedef map<string, class GameClient*> GClientList;
|
||||
GClientList m_clients;
|
||||
|
||||
uint32 m_lastCleanupTime;
|
||||
uint32 m_currTime;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -343,6 +343,14 @@
|
|||
RelativePath=".\GameServer.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\GameSocket.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\GameSocket.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\LocationVector.h"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@
|
|||
<ItemGroup>
|
||||
<ClInclude Include="CrashHandler.h" />
|
||||
<ClInclude Include="CryptoTest.h" />
|
||||
<ClInclude Include="GameSocket.h" />
|
||||
<ClInclude Include="Master.h" />
|
||||
<ClInclude Include="seqchecktest.h" />
|
||||
<ClInclude Include="StackWalker.h" />
|
||||
|
|
@ -157,6 +158,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="CrashHandler.cpp" />
|
||||
<ClCompile Include="GameSocket.cpp" />
|
||||
<ClCompile Include="Main.cpp" />
|
||||
<ClCompile Include="Master.cpp" />
|
||||
<ClCompile Include="DotConfPP\dotconfpp.cpp" />
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue