Danbias/Code/Network/NetworkAPI/NetworkClient.cpp

292 lines
6.9 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"
#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;
2013-12-10 08:32:08 +01:00
/*************************************
PrivateData
*************************************/
2013-12-13 23:47:16 +01:00
struct ClientDataContainer
2013-12-10 08:32:08 +01:00
{
2013-12-13 23:47:16 +01:00
Connection connection;
2013-12-10 08:32:08 +01:00
2013-12-12 12:14:53 +01:00
SmartPointer<IPostBox<CustomNetProtocol>> sendPostBox;
2013-12-13 23:47:16 +01:00
RecieverObject recvObj;
NetworkProtocolCallbackType callbackType;
Oyster::Thread::OysterThread thread;
std::mutex recvObjMutex;
std::mutex postBoxMutex;
Translator translator;
//ID
static unsigned int currID;
const unsigned int ID;
2013-12-10 08:32:08 +01:00
2013-12-13 23:47:16 +01:00
ClientDataContainer(IThreadObject* o)
: ID(currID++)
2013-12-13 23:47:16 +01:00
{
InitWinSock();
callbackType = NetworkProtocolCallbackType_Unknown;
sendPostBox = new PostBox<CustomNetProtocol>();
connection.InitiateClient();
connection.SetBlockingMode(false);
2013-12-17 13:39:10 +01:00
2013-12-13 23:47:16 +01:00
}
ClientDataContainer(IThreadObject* o, unsigned int socket )
:connection(socket), ID(currID++)
2013-12-13 23:47:16 +01:00
{
InitWinSock();
callbackType = NetworkProtocolCallbackType_Unknown;
sendPostBox = new PostBox<CustomNetProtocol>();
connection.InitiateClient();
2013-12-13 23:47:16 +01:00
connection.SetBlockingMode(false);
}
~ClientDataContainer()
{
connection.Disconnect();
thread.Stop();
2013-12-13 23:47:16 +01:00
callbackType = NetworkProtocolCallbackType_Unknown;
2013-12-13 23:47:16 +01:00
ShutdownWinSock();
}
};
unsigned int ClientDataContainer::currID = 0;
2014-01-20 15:47:52 +01:00
2013-12-13 23:47:16 +01:00
struct NetworkClient::PrivateData : public IThreadObject
{
2013-12-13 23:47:16 +01:00
Utility::DynamicMemory::SmartPointer<ClientDataContainer> data;
2013-12-13 23:47:16 +01:00
PrivateData() { this->data = new ClientDataContainer(this); }
PrivateData(unsigned int socket) { this->data = new ClientDataContainer(this, socket); }
~PrivateData() { }
2013-12-13 23:47:16 +01:00
bool DoWork()
{
2014-01-07 10:26:09 +01:00
if(!this->data) return false;
if(!this->data->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;
}
2014-01-20 15:47:52 +01:00
2013-12-13 23:47:16 +01:00
void Send(CustomNetProtocol* protocol)
{
if(!data) return;
2013-12-13 23:47:16 +01:00
this->data->postBoxMutex.lock();
this->data->sendPostBox->PostMessage(*protocol);
this->data->postBoxMutex.unlock();
}
2013-12-13 23:47:16 +01:00
int Send()
{
2013-12-13 23:47:16 +01:00
int errorCode = 0;
if(!data) return -1;
2013-12-13 23:47:16 +01:00
this->data->postBoxMutex.lock();
if(this->data->sendPostBox->IsFull())
{
SmartPointer<OysterByte> temp = new OysterByte();
this->data->translator.Pack(temp, this->data->sendPostBox->FetchMessage());
errorCode = this->data->connection.Send(temp);
2014-01-07 10:26:09 +01:00
if(errorCode != 0)
{
//Failed
this->data->connection.Disconnect();
this->data->recvObjMutex.lock();
if(this->data->callbackType == NetworkProtocolCallbackType_Function)
{
this->data->recvObj.protocolRecieverFnc();
}
else if(this->data->callbackType == NetworkProtocolCallbackType_Object)
{
this->data->recvObj.protocolRecievedObject->Disconnected();
}
this->data->recvObjMutex.unlock();
}
2013-12-13 23:47:16 +01:00
}
this->data->postBoxMutex.unlock();
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();
errorCode = this->data->connection.Recieve(temp);
if(errorCode == 0 && temp.GetSize())
{
2013-12-17 10:25:34 +01:00
CustomNetProtocol protocol;
bool ok = this->data->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)
{
this->data->recvObjMutex.lock();
if(this->data->callbackType == NetworkProtocolCallbackType_Function)
2013-12-13 23:47:16 +01:00
{
2013-12-17 10:25:34 +01:00
this->data->recvObj.protocolRecieverFnc(protocol);
2013-12-13 23:47:16 +01:00
}
2013-12-17 10:25:34 +01:00
else if(this->data->callbackType == NetworkProtocolCallbackType_Object)
{
2014-01-07 10:26:09 +01:00
this->data->recvObj.protocolRecievedObject->NetworkCallback(protocol);
2013-12-17 10:25:34 +01:00
}
this->data->recvObjMutex.unlock();
}
}
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
};
2013-12-10 08:32:08 +01:00
/*************************************
NetworkClient
*************************************/
NetworkClient::NetworkClient()
{
privateData = new PrivateData();
2014-01-20 15:47:52 +01:00
this->privateData->data->thread.SetPriority(Oyster::Thread::OYSTER_THREAD_PRIORITY_1);
}
NetworkClient::NetworkClient(unsigned int socket)
{
privateData = new PrivateData(socket);
this->privateData->data->thread.Create(this->privateData, true);
2014-01-20 15:47:52 +01:00
this->privateData->data->thread.SetPriority(Oyster::Thread::OYSTER_THREAD_PRIORITY_1);
}
2013-12-10 08:32:08 +01:00
NetworkClient::NetworkClient(RecieverObject recvObj, NetworkProtocolCallbackType type)
{
privateData = new PrivateData();
2013-12-17 13:39:10 +01:00
this->privateData->data->callbackType = type;
this->privateData->data->recvObj = recvObj;
}
NetworkClient::NetworkClient(RecieverObject recvObj, NetworkProtocolCallbackType type, unsigned int socket)
{
privateData = new PrivateData(socket);
2013-12-13 23:47:16 +01:00
this->privateData->data->callbackType = type;
2014-01-07 10:26:09 +01:00
this->privateData->data->recvObj = recvObj;
this->privateData->data->thread.Create(this->privateData, true);
2014-01-20 15:47:52 +01:00
this->privateData->data->thread.SetPriority(Oyster::Thread::OYSTER_THREAD_PRIORITY_1);
2013-12-10 08:32:08 +01:00
}
2013-12-12 12:14:53 +01:00
NetworkClient::NetworkClient(const NetworkClient& obj)
{
2013-12-13 23:47:16 +01:00
this->privateData = new PrivateData(*obj.privateData);
2013-12-12 12:14:53 +01:00
}
NetworkClient& NetworkClient::operator =(const NetworkClient& obj)
{
delete privateData;
2013-12-13 23:47:16 +01:00
this->privateData = new PrivateData(*obj.privateData);
2013-12-12 12:14:53 +01:00
return *this;
}
2013-12-10 08:32:08 +01:00
NetworkClient::~NetworkClient()
{
if(privateData)
{
delete privateData;
privateData = NULL;
}
}
bool NetworkClient::Connect(unsigned short port, const char serverIP[])
{
privateData->data->connection.SetBlockingMode(true);
2013-12-13 23:47:16 +01:00
int result = this->privateData->data->connection.Connect(port, serverIP);
//Connect has succeeded
if(result == 0)
{
if(this->privateData->data->thread.IsCreated()) return false;
this->privateData->data->thread.Create(this->privateData, true);
2013-12-17 13:39:10 +01:00
privateData->data->connection.SetBlockingMode(false);
return true;
}
2013-12-10 08:32:08 +01:00
2013-12-17 13:39:10 +01:00
2013-12-12 09:24:57 +01:00
//Connect has failed
return false;
2013-12-10 08:32:08 +01:00
}
void NetworkClient::Disconnect()
{
2013-12-13 23:47:16 +01:00
privateData->data->connection.Disconnect();
privateData->data->thread.Terminate();
2013-12-10 08:32:08 +01:00
}
bool NetworkClient::IsConnected()
{
2013-12-13 23:47:16 +01:00
return privateData->data->connection.IsConnected();
2013-12-10 08:32:08 +01:00
}
void NetworkClient::Send(CustomProtocolObject& protocol)
2013-12-10 08:32:08 +01:00
{
2013-12-13 23:47:16 +01:00
this->privateData->Send(protocol.GetProtocol());
}
2013-12-10 08:32:08 +01:00
2013-12-17 14:15:20 +01:00
void NetworkClient::Send(CustomNetProtocol* protocol)
{
this->privateData->Send(protocol);
}
void NetworkClient::SetRecieverObject(RecieverObject recvObj, NetworkProtocolCallbackType type)
{
2013-12-16 19:58:31 +01:00
if (type == NetworkProtocolCallbackType_Unknown) return; //It should probably still be set even if it is unknown.
2013-12-13 23:47:16 +01:00
privateData->data->recvObjMutex.lock();
privateData->data->recvObj = recvObj;
privateData->data->callbackType = type;
privateData->data->recvObjMutex.unlock();
}
bool NetworkClient::operator ==(const NetworkClient& obj)
{
return (this->privateData->data->ID == obj.privateData->data->ID);
2013-12-16 09:00:11 +01:00
}
bool NetworkClient::operator ==(const int& ID)
{
return this->privateData->data->ID == ID;
}
2014-01-07 10:26:09 +01:00
int NetworkClient::GetID() const
2013-12-16 09:00:11 +01:00
{
return this->privateData->data->ID;
2013-12-10 08:32:08 +01:00
}