#ifndef INCLUDE_WINSOCK_LIB #define INCLUDE_WINSOCK_LIB #pragma comment(lib, "ws2_32.lib") #endif #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" using namespace Oyster::Network; using namespace Oyster::Thread; using namespace Utility::DynamicMemory; /************************************* PrivateData *************************************/ struct NetworkClient::PrivateData : public IThreadObject { PrivateData(); PrivateData(unsigned int socket); ~PrivateData(); void Start(); void Send(CustomNetProtocol& protocol); //Is called from the outside to add messages to send. //Called on from the thread int Send(); int Recv(); bool DoWork(); Connection* connection; IPostBox *sendPostBox; RecieverObject recvObj; NetworkProtocolCallbackType callbackType; Oyster::Thread::OysterThread thread; std::mutex recvObjMutex; std::mutex postBoxMutex; Translator translator; }; NetworkClient::PrivateData::PrivateData() { InitWinSock(); callbackType = NetworkProtocolCallbackType_Unknown; connection = new Connection(); sendPostBox = new PostBox; this->thread.Create(this, false); Start(); } NetworkClient::PrivateData::PrivateData(unsigned int socket) { InitWinSock(); callbackType = NetworkProtocolCallbackType_Unknown; connection = new Connection(socket); sendPostBox = new PostBox; this->thread.Create(this, false); connection->SetBlockingMode(false); Start(); } NetworkClient::PrivateData::~PrivateData() { thread.Stop(); if(connection) { delete connection; connection = NULL; } if(sendPostBox) { delete sendPostBox; sendPostBox = NULL; } callbackType = NetworkProtocolCallbackType_Unknown; ShutdownWinSock(); } bool NetworkClient::PrivateData::DoWork() { Send(); Recv(); return true; } void NetworkClient::PrivateData::Send(CustomNetProtocol& protocol) { postBoxMutex.lock(); sendPostBox->PostMessage(protocol); postBoxMutex.unlock(); } int NetworkClient::PrivateData::Send() { int errorCode = 0; postBoxMutex.lock(); if(sendPostBox->IsFull()) { SmartPointer temp = new OysterByte; this->translator.Pack(temp, sendPostBox->FetchMessage()); errorCode = this->connection->Send(temp); } postBoxMutex.unlock(); return errorCode; } int NetworkClient::PrivateData::Recv() { int errorCode = -1; SmartPointer temp = new OysterByte; errorCode = this->connection->Recieve(temp); if(errorCode == 0) { CustomNetProtocol protocol; bool ok = translator.Unpack(protocol, temp); //Check if the protocol was unpacked correctly if(ok) { recvObjMutex.lock(); if(callbackType == NetworkProtocolCallbackType_Function) { recvObj.protocolRecieverFnc(protocol); } else if(callbackType == NetworkProtocolCallbackType_Object) { recvObj.protocolRecievedObject->ProtocolRecievedCallback(protocol); } recvObjMutex.unlock(); } } return errorCode; } void NetworkClient::PrivateData::Start() { this->thread.Start(); } /************************************* NetworkClient *************************************/ NetworkClient::NetworkClient() { privateData = new PrivateData(); } NetworkClient::NetworkClient(unsigned int socket) { privateData = new PrivateData(socket); } NetworkClient::NetworkClient(RecieverObject recvObj, NetworkProtocolCallbackType type) { privateData = new PrivateData(); this->privateData->recvObj = recvObj; } NetworkClient::NetworkClient(RecieverObject recvObj, NetworkProtocolCallbackType type, unsigned int socket) { privateData = new PrivateData(socket); this->privateData->recvObj = recvObj; this->privateData->callbackType = type; } NetworkClient::~NetworkClient() { if(privateData) { delete privateData; privateData = NULL; } } bool NetworkClient::Connect(unsigned short port, const char serverIP[]) { int result = this->privateData->connection->Connect(port, serverIP); //Connect has succeeded if(result == 0) { privateData->Start(); return true; } privateData->connection->SetBlockingMode(false); //Connect has failed return false; } void NetworkClient::Disconnect() { privateData->connection->Disconnect(); } bool NetworkClient::IsConnected() { return privateData->connection->IsConnected(); } void NetworkClient::Send(CustomNetProtocol& protocol) { this->privateData->Send(protocol); } void NetworkClient::SetRecieverObject(RecieverObject recvObj, NetworkProtocolCallbackType type) { privateData->recvObjMutex.lock(); privateData->recvObj = recvObj; privateData->callbackType = type; privateData->recvObjMutex.unlock(); }