Danbias/Code/Network/NetworkAPI/NetworkClient.cpp

267 lines
5.8 KiB
C++
Raw Normal View History

#ifndef INCLUDE_WINSOCK_LIB
#define INCLUDE_WINSOCK_LIB
#pragma comment(lib, "ws2_32.lib")
#endif
2013-12-10 08:32:08 +01:00
#include "NetworkClient.h"
#include "Translator.h"
#include "CustomNetProtocol.h"
2014-01-28 09:00:02 +01:00
#include "NetworkSession.h"
#include "../NetworkDependencies/Connection.h"
#include "../NetworkDependencies/PostBox.h"
#include "../NetworkDependencies/WinsockFunctions.h"
#include "../../Misc/Utilities.h"
#include "../../Misc/Thread/IThreadObject.h"
#include "../../Misc/Thread/OysterThread.h"
2013-12-10 08:32:08 +01:00
using namespace Oyster::Network;
using namespace Oyster::Thread;
using namespace Utility::DynamicMemory;
2014-01-28 09:00:02 +01:00
using namespace Utility::Container;
2013-12-10 08:32:08 +01:00
/*************************************
PrivateData
*************************************/
2014-01-28 09:00:02 +01:00
typedef NetworkClient::ClientEventArgs CEA;
struct NetDataContainer : public IThreadObject
{ //This struct is contained within a smart pointer. To avoide dependencies in link its implemented here..
NetworkSession *owner;
NetworkClient *parent;
2013-12-13 23:47:16 +01:00
Connection connection;
Translator translator;
2014-01-28 09:00:02 +01:00
OysterThread thread;
2014-01-28 09:00:02 +01:00
//Message queue for sending and recieving
ThreadSafeQueue<CustomNetProtocol> sendQueue;
ThreadSafeQueue<NetEvent<NetworkClient*, NetworkClient::ClientEventArgs>> recieveQueue;
//ID
static unsigned int currID;
const unsigned int ID;
2013-12-10 08:32:08 +01:00
2014-01-28 09:00:02 +01:00
NetDataContainer()
: ID(currID++)
, parent(0)
, owner(0)
{
2013-12-17 13:39:10 +01:00
2013-12-13 23:47:16 +01:00
InitWinSock();
2014-01-28 09:00:02 +01:00
this->thread.Create(this, true);
this->thread.SetPriority(Oyster::Thread::OYSTER_THREAD_PRIORITY_1);
2013-12-13 23:47:16 +01:00
}
2014-01-28 09:00:02 +01:00
NetDataContainer(const NetDataContainer& obj)
:ID(obj.ID) { }
~NetDataContainer()
{
2013-12-13 23:47:16 +01:00
ShutdownWinSock();
2014-01-28 09:00:02 +01:00
this->connection.Disconnect();
this->thread.Terminate();
this->owner = 0;
this->parent = 0;
2013-12-13 23:47:16 +01:00
}
2014-01-28 09:00:02 +01:00
bool DoWork() override
{
2014-01-28 09:00:02 +01:00
if(!this->connection.IsConnected()) return false;
2013-12-17 10:25:34 +01:00
2013-12-13 23:47:16 +01:00
Send();
Recv();
2013-12-17 10:25:34 +01:00
2013-12-13 23:47:16 +01:00
return true;
}
2013-12-13 23:47:16 +01:00
int Send()
{
2013-12-13 23:47:16 +01:00
int errorCode = 0;
2014-01-28 09:00:02 +01:00
if(!this->sendQueue.IsEmpty())
2013-12-13 23:47:16 +01:00
{
SmartPointer<OysterByte> temp = new OysterByte();
2014-01-28 09:00:02 +01:00
CustomNetProtocol p = this->sendQueue.Pop();
this->translator.Pack(temp, p);
errorCode = this->connection.Send(temp);
2014-01-07 10:26:09 +01:00
if(errorCode != 0)
{
2014-01-28 09:00:02 +01:00
CEA parg;
parg.type = CEA::EventType_ProtocolFailedToSend;
parg.data.protocol = p;
NetEvent<NetworkClient*, CEA> e = { this->parent, parg };
this->recieveQueue.Push(e);
2014-01-07 10:26:09 +01:00
}
2013-12-13 23:47:16 +01:00
}
2013-12-13 23:47:16 +01:00
return errorCode;
}
2013-12-13 23:47:16 +01:00
int Recv()
{
2013-12-13 23:47:16 +01:00
int errorCode = -1;
2013-12-17 10:25:34 +01:00
OysterByte temp = OysterByte();
2014-01-28 09:00:02 +01:00
errorCode = this->connection.Recieve(temp);
2013-12-17 10:25:34 +01:00
if(errorCode == 0 && temp.GetSize())
{
2013-12-17 10:25:34 +01:00
CustomNetProtocol protocol;
2014-01-28 09:00:02 +01:00
bool ok = this->translator.Unpack(protocol, temp);
2013-12-13 23:47:16 +01:00
2013-12-17 10:25:34 +01:00
//Check if the protocol was unpacked correctly
if(ok)
{
2014-01-28 09:00:02 +01:00
CEA parg;
parg.type = CEA::EventType_ProtocolRecieved;
parg.data.protocol = protocol;
NetEvent<NetworkClient*, NetworkClient::ClientEventArgs> e = { this->parent, parg };
this->recieveQueue.Push(e);
}
}
2014-01-28 09:00:02 +01:00
else
{
CEA parg;
parg.type = CEA::EventType_ProtocolFailedToRecieve;
parg.data.nothing = 0;
NetEvent<NetworkClient*, NetworkClient::ClientEventArgs> e = { this->parent, parg };
this->recieveQueue.Push(e);
}
2013-12-17 10:25:34 +01:00
2013-12-13 23:47:16 +01:00
return errorCode;
}
2013-12-13 23:47:16 +01:00
};
2014-01-28 09:00:02 +01:00
struct NetworkClient::PrivateData
{
SmartPointer<NetDataContainer> dat;
public:
PrivateData()
{ this->dat = new NetDataContainer(); }
PrivateData(const PrivateData& obj)
{ this->dat = obj.dat; }
~PrivateData()
{ this->dat = 0; }
};
unsigned int NetDataContainer::currID = 0;
2013-12-10 08:32:08 +01:00
/*************************************
NetworkClient
*************************************/
NetworkClient::NetworkClient()
2014-01-28 09:00:02 +01:00
: privateData(0)
{ }
2014-01-28 09:00:02 +01:00
NetworkClient::NetworkClient(const NetworkClient& obj)
{
2014-01-28 09:00:02 +01:00
if(obj.privateData) this->privateData = new PrivateData(*obj.privateData);
else this->privateData = 0;
}
2013-12-10 08:32:08 +01:00
2014-01-28 09:00:02 +01:00
NetworkClient& NetworkClient::operator =(const NetworkClient& obj)
{
2014-01-28 09:00:02 +01:00
delete privateData;
this->privateData = 0;
if(obj.privateData) this->privateData = new PrivateData(*obj.privateData);
return *this;
}
2014-01-28 09:00:02 +01:00
NetworkClient::~NetworkClient()
{
2014-01-28 09:00:02 +01:00
if(this->privateData)
{
delete this->privateData;
this->privateData = NULL;
}
2013-12-10 08:32:08 +01:00
}
2014-01-28 09:00:02 +01:00
bool NetworkClient::operator ==(const NetworkClient& obj)
2013-12-12 12:14:53 +01:00
{
2014-01-28 09:00:02 +01:00
return (this->privateData->dat->ID == obj.privateData->dat->ID);
2013-12-12 12:14:53 +01:00
}
2014-01-28 09:00:02 +01:00
bool NetworkClient::operator ==(const int& ID)
2013-12-12 12:14:53 +01:00
{
2014-01-28 09:00:02 +01:00
return this->privateData->dat->ID == ID;
2013-12-12 12:14:53 +01:00
}
2014-01-28 09:00:02 +01:00
void NetworkClient::ProcessMessages()
2013-12-10 08:32:08 +01:00
{
2014-01-28 09:00:02 +01:00
while (!this->privateData->dat->recieveQueue.IsEmpty())
{
2014-01-28 09:00:02 +01:00
if(this->privateData->dat->owner)
{
this->privateData->dat->owner->ClientEventCallback(this->privateData->dat->recieveQueue.Pop());
}
}
}
2014-01-28 09:00:02 +01:00
bool NetworkClient::Connect(int socket)
{
2014-01-28 09:00:02 +01:00
if(this->IsConnected()) return true;
if(this->privateData) return false;
if(!this->privateData) this->privateData = new PrivateData();
int result = this->privateData->dat->connection.Connect(socket, true);
//Connect has succeeded
2014-01-28 09:00:02 +01:00
if(result == 0) return true;
2014-01-28 09:00:02 +01:00
//Connect has failed
return false;
}
2013-12-10 08:32:08 +01:00
2014-01-28 09:00:02 +01:00
bool NetworkClient::Connect(unsigned short port, const char serverIP[])
{
if(this->IsConnected()) return false;
if(this->privateData) return false;
if(!this->privateData) this->privateData = new PrivateData();
2013-12-17 13:39:10 +01:00
2014-01-28 09:00:02 +01:00
int result = this->privateData->dat->connection.Connect(port, serverIP, false);
//Connect has succeeded
if(result == 0) return true;
2013-12-12 09:24:57 +01:00
//Connect has failed
return false;
2013-12-10 08:32:08 +01:00
}
void NetworkClient::Disconnect()
{
2014-01-28 09:00:02 +01:00
privateData->dat->connection.Disconnect();
privateData->dat->thread.Terminate();
2013-12-10 08:32:08 +01:00
}
void NetworkClient::Send(CustomProtocolObject& protocol)
2013-12-10 08:32:08 +01:00
{
2014-01-28 09:00:02 +01:00
this->privateData->dat->sendQueue.Push(*protocol.GetProtocol());
}
2013-12-10 08:32:08 +01:00
2013-12-17 14:15:20 +01:00
void NetworkClient::Send(CustomNetProtocol* protocol)
{
2014-01-28 09:00:02 +01:00
this->privateData->dat->sendQueue.Push(*protocol);
2013-12-17 14:15:20 +01:00
}
2014-01-28 09:00:02 +01:00
void NetworkClient::SetOwner(NetworkSession* owner)
{
2014-01-28 09:00:02 +01:00
this->privateData->dat->owner = owner;
}
2014-01-28 09:00:02 +01:00
bool NetworkClient::IsConnected()
{
2014-01-28 09:00:02 +01:00
if(!this->privateData) return false;
return privateData->dat->connection.IsConnected();
2013-12-16 09:00:11 +01:00
}
2014-01-28 09:00:02 +01:00
int NetworkClient::GetID() const
2013-12-16 09:00:11 +01:00
{
2014-01-28 09:00:02 +01:00
return this->privateData->dat->ID;
2013-12-16 09:00:11 +01:00
}
2014-01-28 09:00:02 +01:00