2014-02-16 01:38:03 +01:00
|
|
|
//////////////////////////////////////
|
|
|
|
// Created by Pontus Fransson 2013 //
|
|
|
|
// Modified by Dennis Andersen 2014 //
|
|
|
|
//////////////////////////////////////
|
2013-12-11 21:45:43 +01:00
|
|
|
#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"
|
|
|
|
|
2013-12-11 21:45:43 +01:00
|
|
|
#include "Translator.h"
|
|
|
|
#include "CustomNetProtocol.h"
|
2014-01-28 09:00:02 +01:00
|
|
|
#include "NetworkSession.h"
|
2013-12-11 21:45:43 +01:00
|
|
|
|
2014-02-23 18:38:20 +01:00
|
|
|
#include "../NetworkDependencies/ConnectionUDP.h"
|
2013-12-11 21:45:43 +01:00
|
|
|
#include "../NetworkDependencies/Connection.h"
|
|
|
|
#include "../NetworkDependencies/PostBox.h"
|
|
|
|
#include "../NetworkDependencies/WinsockFunctions.h"
|
|
|
|
|
2014-02-17 10:38:11 +01:00
|
|
|
#include "Utilities.h"
|
|
|
|
#include "Thread/IThreadObject.h"
|
|
|
|
#include "Thread/OysterThread.h"
|
|
|
|
#include "Packing/Packing.h"
|
2014-01-30 23:22:46 +01:00
|
|
|
|
|
|
|
#include <queue>
|
2014-01-31 22:52:52 +01:00
|
|
|
#include <WinSock2.h>
|
2013-12-11 21:45:43 +01:00
|
|
|
|
2014-02-23 20:23:15 +01:00
|
|
|
#include <thread>
|
|
|
|
|
2014-02-13 13:51:27 +01:00
|
|
|
//For conversion from wstring to string
|
|
|
|
#include <codecvt>
|
|
|
|
|
2013-12-10 08:32:08 +01:00
|
|
|
using namespace Oyster::Network;
|
2013-12-11 21:45:43 +01:00
|
|
|
using namespace Oyster::Thread;
|
|
|
|
using namespace Utility::DynamicMemory;
|
2014-01-28 09:00:02 +01:00
|
|
|
using namespace Utility::Container;
|
2014-01-30 23:22:46 +01:00
|
|
|
using namespace std;
|
2013-12-10 08:32:08 +01:00
|
|
|
|
|
|
|
/*************************************
|
|
|
|
PrivateData
|
|
|
|
*************************************/
|
2014-01-28 09:00:02 +01:00
|
|
|
typedef NetworkClient::ClientEventArgs CEA;
|
2014-01-29 10:18:01 +01:00
|
|
|
|
2014-02-12 09:02:44 +01:00
|
|
|
void OnRecieve_Default(NetEvent<NetworkClient*, NetworkClient::ClientEventArgs> e) {}
|
|
|
|
|
2014-01-29 10:18:01 +01:00
|
|
|
struct NetworkClient::PrivateData : public IThreadObject
|
|
|
|
{
|
2014-01-28 09:00:02 +01:00
|
|
|
NetworkSession *owner;
|
|
|
|
NetworkClient *parent;
|
2013-12-13 23:47:16 +01:00
|
|
|
Connection connection;
|
2013-12-11 21:45:43 +01:00
|
|
|
Translator translator;
|
2014-01-28 09:00:02 +01:00
|
|
|
OysterThread thread;
|
2014-02-20 08:33:07 +01:00
|
|
|
bool outputEvent;
|
2013-12-11 21:45:43 +01:00
|
|
|
|
2014-01-30 23:22:46 +01:00
|
|
|
OysterByte recieveBuffer;
|
2014-01-28 09:00:02 +01:00
|
|
|
|
|
|
|
//Message queue for sending and recieving
|
|
|
|
ThreadSafeQueue<CustomNetProtocol> sendQueue;
|
|
|
|
ThreadSafeQueue<NetEvent<NetworkClient*, NetworkClient::ClientEventArgs>> recieveQueue;
|
2014-01-30 23:22:46 +01:00
|
|
|
|
2014-02-22 22:38:28 +01:00
|
|
|
//Testing for eventSelect.
|
2014-02-23 20:23:15 +01:00
|
|
|
HANDLE socketEvents[2];
|
2014-02-22 22:38:28 +01:00
|
|
|
HANDLE shutdownEvent;
|
|
|
|
|
2014-02-23 20:23:15 +01:00
|
|
|
//Broadcasting
|
|
|
|
bool broadcastingStarted;
|
|
|
|
HANDLE broadcastEvent;
|
|
|
|
HANDLE broadcastShutdownEvent;
|
|
|
|
std::thread broadcastThread;
|
|
|
|
ConnectionUDP broadcastConnection;
|
|
|
|
OysterByte broadcastTempMessage;
|
|
|
|
Translator broadcastTranslator;
|
|
|
|
|
2014-02-22 22:38:28 +01:00
|
|
|
//The OysterByte each message is packed in.
|
|
|
|
OysterByte tempMessage;
|
|
|
|
|
|
|
|
//Used to buffer messages
|
|
|
|
OysterByte bufferedSend;
|
|
|
|
int numPackages;
|
|
|
|
|
2013-12-12 15:33:11 +01:00
|
|
|
//ID
|
|
|
|
static unsigned int currID;
|
|
|
|
const unsigned int ID;
|
2013-12-10 08:32:08 +01:00
|
|
|
|
2014-01-29 10:18:01 +01:00
|
|
|
PrivateData()
|
2014-01-28 09:00:02 +01:00
|
|
|
: ID(currID++)
|
|
|
|
, parent(0)
|
|
|
|
, owner(0)
|
2014-02-20 09:14:42 +01:00
|
|
|
, outputEvent(0)
|
2014-02-22 22:38:28 +01:00
|
|
|
{
|
2014-02-23 20:23:15 +01:00
|
|
|
broadcastingStarted = false;
|
2014-02-22 22:38:28 +01:00
|
|
|
numPackages = 0;
|
|
|
|
bufferedSend.Resize(MAX_NETWORK_MESSAGE_SIZE);
|
|
|
|
tempMessage.Resize(MAX_NETWORK_MESSAGE_SIZE);
|
2013-12-13 23:47:16 +01:00
|
|
|
InitWinSock();
|
2014-01-29 10:18:01 +01:00
|
|
|
this->thread.Create(this, false);
|
2014-01-28 09:00:02 +01:00
|
|
|
this->thread.SetPriority(Oyster::Thread::OYSTER_THREAD_PRIORITY_1);
|
2013-12-13 23:47:16 +01:00
|
|
|
}
|
2014-01-29 10:18:01 +01:00
|
|
|
~PrivateData()
|
2014-01-28 09:00:02 +01:00
|
|
|
{
|
2014-02-22 22:38:28 +01:00
|
|
|
SetEvent(shutdownEvent);
|
|
|
|
this->thread.Wait();
|
2014-02-04 16:27:18 +01:00
|
|
|
|
2013-12-13 23:47:16 +01:00
|
|
|
ShutdownWinSock();
|
2014-01-28 09:00:02 +01:00
|
|
|
this->connection.Disconnect();
|
|
|
|
this->owner = 0;
|
|
|
|
this->parent = 0;
|
2013-12-13 23:47:16 +01:00
|
|
|
}
|
2013-12-11 21:45:43 +01:00
|
|
|
|
2014-02-22 22:38:28 +01:00
|
|
|
void ThreadEntry()
|
|
|
|
{
|
|
|
|
//Create alla events used in the thread
|
|
|
|
shutdownEvent = CreateEvent(NULL, true, false, NULL);
|
|
|
|
socketEvents[0] = WSACreateEvent();
|
|
|
|
socketEvents[1] = WSACreateEvent();
|
|
|
|
|
|
|
|
if(socketEvents[0] == WSA_INVALID_EVENT)
|
|
|
|
{
|
|
|
|
//Error
|
|
|
|
}
|
|
|
|
|
|
|
|
if(WSAEventSelect(this->connection.GetSocket(), socketEvents[0], FD_READ) == SOCKET_ERROR)
|
|
|
|
{
|
|
|
|
//Error
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ThreadExit()
|
|
|
|
{
|
|
|
|
WSACloseEvent(socketEvents[0]);
|
|
|
|
WSACloseEvent(socketEvents[1]);
|
|
|
|
CloseHandle(shutdownEvent);
|
|
|
|
}
|
|
|
|
|
2014-02-23 20:23:15 +01:00
|
|
|
void BroadcastThread()
|
|
|
|
{
|
|
|
|
WSANETWORKEVENTS wsaEvents;
|
|
|
|
|
|
|
|
while(WaitForSingleObject(broadcastShutdownEvent, 0) != WAIT_OBJECT_0)
|
|
|
|
{
|
|
|
|
int result = WSAWaitForMultipleEvents(1, &broadcastEvent, FALSE, 100, FALSE) - WSA_WAIT_EVENT_0;
|
|
|
|
if(result == 0)
|
|
|
|
{
|
|
|
|
WSAEnumNetworkEvents(this->broadcastConnection.GetSocket(), broadcastEvent, &wsaEvents);
|
|
|
|
if((wsaEvents.lNetworkEvents & FD_READ) && (wsaEvents.iErrorCode[FD_READ_BIT] == 0))
|
|
|
|
{
|
|
|
|
//Recieve a message
|
|
|
|
RecvUDP();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-28 09:00:02 +01:00
|
|
|
bool DoWork() override
|
2013-12-11 21:45:43 +01:00
|
|
|
{
|
2014-02-22 22:38:28 +01:00
|
|
|
WSANETWORKEVENTS wsaEvents;
|
2014-01-30 23:22:46 +01:00
|
|
|
|
2014-02-22 22:38:28 +01:00
|
|
|
while(WaitForSingleObject(shutdownEvent, 0) != WAIT_OBJECT_0)
|
|
|
|
{
|
|
|
|
if(!this->connection.IsConnected()) return false;
|
|
|
|
|
2014-02-23 18:38:20 +01:00
|
|
|
int result = WSAWaitForMultipleEvents(3, socketEvents, FALSE, 100, FALSE) - WSA_WAIT_EVENT_0;
|
2014-02-22 22:38:28 +01:00
|
|
|
if(result == 0)
|
|
|
|
{
|
|
|
|
WSAEnumNetworkEvents(this->connection.GetSocket(), socketEvents[0], &wsaEvents);
|
|
|
|
if((wsaEvents.lNetworkEvents & FD_READ) && (wsaEvents.iErrorCode[FD_READ_BIT] == 0))
|
|
|
|
{
|
|
|
|
//Recieve a message
|
|
|
|
Recv();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(result == 1)
|
|
|
|
{
|
|
|
|
//Send all messages in the sendQueue
|
|
|
|
int i = this->sendQueue.Size();
|
|
|
|
WSAResetEvent(socketEvents[1]);
|
|
|
|
|
|
|
|
if(i == 1)
|
|
|
|
{
|
|
|
|
Send();
|
|
|
|
}
|
|
|
|
else if(i > 1)
|
|
|
|
{
|
|
|
|
for(int j = 0; j < i; j++)
|
|
|
|
BufferMessage();
|
|
|
|
|
|
|
|
SendBuffer();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-02-23 18:38:20 +01:00
|
|
|
void RecvUDP()
|
|
|
|
{
|
|
|
|
int errorCode = -1;
|
|
|
|
|
2014-02-23 20:23:15 +01:00
|
|
|
errorCode = this->broadcastConnection.Recieve(broadcastTempMessage);
|
2014-02-23 18:38:20 +01:00
|
|
|
|
2014-02-23 20:23:15 +01:00
|
|
|
if(errorCode == 0 && broadcastTempMessage.GetSize())
|
2014-02-23 18:38:20 +01:00
|
|
|
{
|
|
|
|
CustomNetProtocol protocol;
|
2014-02-23 20:23:15 +01:00
|
|
|
bool ok = this->broadcastTranslator.Unpack(protocol, broadcastTempMessage);
|
2014-02-23 18:38:20 +01:00
|
|
|
|
|
|
|
//Check if the protocol was unpacked correctly
|
|
|
|
if(ok)
|
|
|
|
{
|
|
|
|
CEA parg;
|
|
|
|
parg.type = CEA::EventType_ProtocolRecieved;
|
|
|
|
parg.data.protocol = protocol;
|
|
|
|
NetEvent<NetworkClient*, NetworkClient::ClientEventArgs> e;
|
|
|
|
e.sender = this->parent;
|
|
|
|
e.args.data.protocol = parg.data.protocol;
|
|
|
|
e.args.type = parg.type;
|
|
|
|
|
|
|
|
this->recieveQueue.Push(e);
|
|
|
|
|
|
|
|
if(this->outputEvent)
|
|
|
|
{
|
|
|
|
printf("\t(ID: %i | IP: %s | Protocol: %i) Message recieved!\n", this->ID, this->connection.GetIpAddress().c_str(), protocol[0].value.netShort);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(this->outputEvent)
|
|
|
|
{
|
|
|
|
printf("\t(ID: %i | IP: %s) Failed to unpack CustomNetProtocol!\n", this->ID, this->connection.GetIpAddress().c_str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-23 20:23:15 +01:00
|
|
|
broadcastTempMessage.Clear();
|
2014-02-23 18:38:20 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-22 22:38:28 +01:00
|
|
|
void SendBuffer()
|
|
|
|
{
|
|
|
|
if(bufferedSend.GetSize() > 0)
|
|
|
|
{
|
|
|
|
this->connection.Send(bufferedSend);
|
|
|
|
//printf("2. %d, %d\n", numPackages, bufferedSend.GetSize());
|
|
|
|
bufferedSend.Clear();
|
|
|
|
|
|
|
|
//Debug
|
|
|
|
numPackages = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void BufferMessage()
|
|
|
|
{
|
|
|
|
int errorCode = 0;
|
|
|
|
|
|
|
|
if(!this->sendQueue.IsEmpty())
|
|
|
|
{
|
|
|
|
CustomNetProtocol p = this->sendQueue.Pop();
|
|
|
|
|
|
|
|
this->translator.Pack(tempMessage, p);
|
|
|
|
|
|
|
|
|
|
|
|
if(tempMessage.GetSize() > MAX_NETWORK_MESSAGE_SIZE - bufferedSend.GetSize())
|
|
|
|
{
|
|
|
|
//Send buffered message
|
|
|
|
errorCode = this->connection.Send(bufferedSend);
|
|
|
|
//printf("2. %d, %d\n", numPackages, bufferedSend.GetSize());
|
|
|
|
bufferedSend.Clear();
|
|
|
|
|
|
|
|
//Debug
|
|
|
|
numPackages = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bufferedSend += tempMessage;
|
|
|
|
tempMessage.Clear();
|
|
|
|
|
|
|
|
//Debug
|
|
|
|
numPackages++;
|
|
|
|
|
|
|
|
if(errorCode != 0 && errorCode != WSAEWOULDBLOCK)
|
|
|
|
{
|
|
|
|
if( errorCode == WSAECONNABORTED || errorCode == WSAENOTCONN)
|
|
|
|
{
|
|
|
|
CEA parg;
|
|
|
|
parg.type = CEA::EventType_Disconnect;
|
|
|
|
parg.data.protocol = p;
|
|
|
|
NetEvent<NetworkClient*, CEA> e = { this->parent, parg };
|
|
|
|
this->recieveQueue.Push(e);
|
|
|
|
|
|
|
|
if(this->outputEvent)
|
|
|
|
{
|
|
|
|
printf("\t(ID: %i | IP: %s | Protocol: %i) - EventType_Disconnect && EventType_ProtocolFailedToSend \n", this->ID, this->connection.GetIpAddress().c_str(), p[0].value.netShort);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CEA parg;
|
|
|
|
parg.type = CEA::EventType_ProtocolFailedToSend;
|
|
|
|
parg.data.protocol = p;
|
|
|
|
NetEvent<NetworkClient*, CEA> e = { this->parent, parg };
|
|
|
|
this->recieveQueue.Push(e);
|
|
|
|
|
|
|
|
if(this->outputEvent)
|
|
|
|
{
|
|
|
|
printf("\t(ID: %i | IP: %s | Protocol: %i) - EventType_ProtocolFailedToSend\n", this->ID, this->connection.GetIpAddress().c_str(), p[0].value.netShort);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(this->outputEvent)
|
|
|
|
{
|
|
|
|
printf("\t(ID: %i | IP: %s | Protocol: %i) Message sent!\n", this->ID, this->connection.GetIpAddress().c_str(), p[0].value.netShort);
|
|
|
|
}
|
|
|
|
}
|
2013-12-13 23:47:16 +01:00
|
|
|
}
|
2014-02-22 22:38:28 +01:00
|
|
|
|
2013-12-13 23:47:16 +01:00
|
|
|
int Send()
|
2013-12-11 21:45:43 +01:00
|
|
|
{
|
2013-12-13 23:47:16 +01:00
|
|
|
int errorCode = 0;
|
2013-12-11 21:45:43 +01:00
|
|
|
|
2014-01-28 09:00:02 +01:00
|
|
|
if(!this->sendQueue.IsEmpty())
|
2013-12-13 23:47:16 +01:00
|
|
|
{
|
2014-02-04 16:07:10 +01:00
|
|
|
//printf("\t(%i)\n", this->sendQueue.Size());
|
2014-01-28 09:00:02 +01:00
|
|
|
CustomNetProtocol p = this->sendQueue.Pop();
|
2014-02-18 16:38:08 +01:00
|
|
|
|
2014-02-22 22:38:28 +01:00
|
|
|
this->translator.Pack(tempMessage, p);
|
|
|
|
errorCode = this->connection.Send(tempMessage);
|
|
|
|
tempMessage.Clear();
|
2014-01-30 23:22:46 +01:00
|
|
|
|
2014-01-31 22:52:52 +01:00
|
|
|
if(errorCode != 0 && errorCode != WSAEWOULDBLOCK)
|
2014-01-07 10:26:09 +01:00
|
|
|
{
|
2014-02-19 16:22:14 +01:00
|
|
|
if( errorCode == WSAECONNABORTED || errorCode == WSAENOTCONN)
|
|
|
|
{
|
|
|
|
CEA parg;
|
|
|
|
parg.type = CEA::EventType_Disconnect;
|
|
|
|
parg.data.protocol = p;
|
|
|
|
NetEvent<NetworkClient*, CEA> e = { this->parent, parg };
|
|
|
|
this->recieveQueue.Push(e);
|
2014-02-20 08:33:07 +01:00
|
|
|
|
|
|
|
if(this->outputEvent)
|
|
|
|
{
|
|
|
|
printf("\t(ID: %i | IP: %s | Protocol: %i) - EventType_Disconnect && EventType_ProtocolFailedToSend \n", this->ID, this->connection.GetIpAddress().c_str(), p[0].value.netShort);
|
|
|
|
}
|
2014-02-19 16:22:14 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CEA parg;
|
|
|
|
parg.type = CEA::EventType_ProtocolFailedToSend;
|
|
|
|
parg.data.protocol = p;
|
|
|
|
NetEvent<NetworkClient*, CEA> e = { this->parent, parg };
|
|
|
|
this->recieveQueue.Push(e);
|
2014-02-20 08:33:07 +01:00
|
|
|
|
|
|
|
if(this->outputEvent)
|
|
|
|
{
|
|
|
|
printf("\t(ID: %i | IP: %s | Protocol: %i) - EventType_ProtocolFailedToSend\n", this->ID, this->connection.GetIpAddress().c_str(), p[0].value.netShort);
|
|
|
|
}
|
2014-02-19 16:22:14 +01:00
|
|
|
}
|
2014-01-07 10:26:09 +01:00
|
|
|
}
|
2014-02-20 08:33:07 +01:00
|
|
|
|
|
|
|
if(this->outputEvent)
|
|
|
|
{
|
|
|
|
printf("\t(ID: %i | IP: %s | Protocol: %i) Message sent!\n", this->ID, this->connection.GetIpAddress().c_str(), p[0].value.netShort);
|
|
|
|
}
|
2013-12-13 23:47:16 +01:00
|
|
|
}
|
2013-12-11 21:45:43 +01:00
|
|
|
|
2013-12-13 23:47:16 +01:00
|
|
|
return errorCode;
|
|
|
|
}
|
|
|
|
int Recv()
|
2013-12-11 21:45:43 +01:00
|
|
|
{
|
2013-12-13 23:47:16 +01:00
|
|
|
int errorCode = -1;
|
|
|
|
|
2014-02-22 22:38:28 +01:00
|
|
|
errorCode = this->connection.Recieve(tempMessage);
|
2013-12-17 10:25:34 +01:00
|
|
|
|
2014-02-22 22:38:28 +01:00
|
|
|
if(errorCode == 0 && tempMessage.GetSize())
|
2013-12-11 21:45:43 +01:00
|
|
|
{
|
2014-02-22 22:38:28 +01:00
|
|
|
HandleRecievedData(tempMessage);
|
|
|
|
tempMessage.Clear();
|
2014-01-30 23:22:46 +01:00
|
|
|
|
|
|
|
|
|
|
|
/* Replaced with EmptyOutbufferedQueue() and HandleRecievedData(OysterByte)
|
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);
|
2014-01-30 23:22:46 +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-30 23:22:46 +01:00
|
|
|
}*/
|
|
|
|
|
2013-12-11 21:45:43 +01:00
|
|
|
}
|
2014-01-29 10:18:01 +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-11 21:45:43 +01:00
|
|
|
}
|
2014-01-30 23:22:46 +01:00
|
|
|
|
|
|
|
void HandleRecievedData(OysterByte& data)
|
|
|
|
{
|
|
|
|
//Loop through all packages that was recieved and add them to the queue.
|
|
|
|
unsigned int size = 0;
|
|
|
|
|
|
|
|
Oyster::Network::OysterByte msg;
|
|
|
|
|
|
|
|
//If there is part of a message in the buffer.
|
|
|
|
if(recieveBuffer.GetSize() > 0)
|
|
|
|
{
|
|
|
|
//cout << "the buffer size: " << recvBuffer.GetSize() <<endl;
|
|
|
|
unsigned int temp = recieveBuffer.GetSize();
|
|
|
|
size = Oyster::Packing::Unpacki(recieveBuffer);
|
|
|
|
|
|
|
|
if(temp + data.GetSize() > size)
|
|
|
|
{
|
|
|
|
msg = recieveBuffer;
|
|
|
|
recieveBuffer.Clear();
|
|
|
|
size -= msg.GetSize();
|
|
|
|
msg.AppendPartOfArray(data, 0, size);
|
|
|
|
UnpackMessageAndAddToQueue(msg);
|
|
|
|
}
|
|
|
|
else if(temp + data.GetSize() == size)
|
|
|
|
{
|
|
|
|
msg = recieveBuffer;
|
|
|
|
recieveBuffer.Clear();
|
|
|
|
size -= msg.GetSize();
|
|
|
|
msg += data;
|
|
|
|
UnpackMessageAndAddToQueue(msg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
recieveBuffer += data;
|
|
|
|
size = data.GetSize();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for(unsigned int i = size; i < data.GetSize(); i += size)
|
|
|
|
{
|
|
|
|
size = Oyster::Packing::Unpacki(&data.GetByteArray()[i]);
|
|
|
|
if(i+size > data.GetSize())
|
|
|
|
{
|
|
|
|
//Add it to the recvBuffer instead.
|
|
|
|
recieveBuffer.AppendPartOfArray(data, i, data.GetSize());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
msg.Clear();
|
|
|
|
msg.AppendPartOfArray(data, i, i+size);
|
|
|
|
UnpackMessageAndAddToQueue(msg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void UnpackMessageAndAddToQueue(OysterByte& msg)
|
|
|
|
{
|
|
|
|
CustomNetProtocol protocol;
|
|
|
|
bool ok = this->translator.Unpack(protocol, msg);
|
|
|
|
|
|
|
|
//Check if the protocol was unpacked correctly
|
|
|
|
if(ok)
|
|
|
|
{
|
|
|
|
CEA parg;
|
|
|
|
parg.type = CEA::EventType_ProtocolRecieved;
|
|
|
|
parg.data.protocol = protocol;
|
2014-02-04 16:07:10 +01:00
|
|
|
NetEvent<NetworkClient*, NetworkClient::ClientEventArgs> e;
|
|
|
|
e.sender = this->parent;
|
|
|
|
e.args.data.protocol = parg.data.protocol;
|
|
|
|
e.args.type = parg.type;
|
|
|
|
|
2014-01-30 23:22:46 +01:00
|
|
|
this->recieveQueue.Push(e);
|
2014-02-20 08:33:07 +01:00
|
|
|
|
|
|
|
if(this->outputEvent)
|
|
|
|
{
|
|
|
|
printf("\t(ID: %i | IP: %s | Protocol: %i) Message recieved!\n", this->ID, this->connection.GetIpAddress().c_str(), protocol[0].value.netShort);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(this->outputEvent)
|
|
|
|
{
|
|
|
|
printf("\t(ID: %i | IP: %s) Failed to unpack CustomNetProtocol!\n", this->ID, this->connection.GetIpAddress().c_str());
|
|
|
|
}
|
2014-01-30 23:22:46 +01:00
|
|
|
}
|
|
|
|
}
|
2013-12-13 23:47:16 +01:00
|
|
|
};
|
2014-01-29 10:18:01 +01:00
|
|
|
unsigned int NetworkClient::PrivateData::currID = 0;
|
2014-01-28 09:00:02 +01:00
|
|
|
|
2013-12-10 08:32:08 +01:00
|
|
|
/*************************************
|
|
|
|
NetworkClient
|
|
|
|
*************************************/
|
|
|
|
|
|
|
|
NetworkClient::NetworkClient()
|
2014-02-12 14:33:56 +01:00
|
|
|
: privateData(nullptr),
|
|
|
|
OnRecieve(OnRecieve_Default)
|
2014-01-28 09:00:02 +01:00
|
|
|
{ }
|
2013-12-11 21:45:43 +01:00
|
|
|
|
2014-01-28 09:00:02 +01:00
|
|
|
NetworkClient::~NetworkClient()
|
2013-12-11 21:45:43 +01:00
|
|
|
{
|
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-29 10:18:01 +01:00
|
|
|
return (this->privateData->ID == obj.privateData->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-29 10:18:01 +01:00
|
|
|
return this->privateData->ID == ID;
|
2013-12-12 12:14:53 +01:00
|
|
|
}
|
|
|
|
|
2014-01-29 10:18:01 +01:00
|
|
|
void NetworkClient::Update()
|
2013-12-10 08:32:08 +01:00
|
|
|
{
|
2014-01-31 08:41:08 +01:00
|
|
|
if(!this->privateData) return;
|
2014-01-29 10:18:01 +01:00
|
|
|
while (!this->privateData->recieveQueue.IsEmpty())
|
2013-12-11 21:45:43 +01:00
|
|
|
{
|
2014-01-29 10:18:01 +01:00
|
|
|
NetEvent<NetworkClient*, ClientEventArgs> temp = this->privateData->recieveQueue.Pop();
|
|
|
|
|
|
|
|
this->DataRecieved(temp);
|
2013-12-11 21:45:43 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-29 15:01:14 +01:00
|
|
|
bool NetworkClient::Connect(ConnectionInfo& socket)
|
2013-12-11 21:45:43 +01:00
|
|
|
{
|
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();
|
|
|
|
|
2014-02-22 22:38:28 +01:00
|
|
|
int result = this->privateData->connection.Connect(socket, true);
|
2013-12-11 21:45:43 +01:00
|
|
|
|
|
|
|
//Connect has succeeded
|
2014-01-29 10:18:01 +01:00
|
|
|
if(result != 0) return false;
|
|
|
|
|
|
|
|
this->privateData->parent = this;
|
|
|
|
this->privateData->thread.Start();
|
2013-12-16 11:05:24 +01:00
|
|
|
|
2014-01-28 09:00:02 +01:00
|
|
|
//Connect has failed
|
2014-01-29 10:18:01 +01:00
|
|
|
return true;
|
2014-01-28 09:00:02 +01:00
|
|
|
}
|
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[])
|
|
|
|
{
|
2014-02-19 14:49:20 +01:00
|
|
|
//Return true if you are already connected.
|
|
|
|
if(this->IsConnected())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if(!this->privateData)
|
|
|
|
this->privateData = new PrivateData();
|
2014-02-23 18:38:20 +01:00
|
|
|
|
2014-02-22 22:38:28 +01:00
|
|
|
int result = this->privateData->connection.Connect(port, serverIP, true);
|
2014-01-28 09:00:02 +01:00
|
|
|
|
|
|
|
//Connect has succeeded
|
2014-01-29 10:18:01 +01:00
|
|
|
if(result != 0) return false;
|
2014-01-31 08:41:08 +01:00
|
|
|
this->privateData->owner = 0;
|
2014-01-29 10:18:01 +01:00
|
|
|
this->privateData->parent = this;
|
|
|
|
this->privateData->thread.Start();
|
2013-12-12 09:24:57 +01:00
|
|
|
|
2013-12-11 21:45:43 +01:00
|
|
|
//Connect has failed
|
2014-01-29 10:18:01 +01:00
|
|
|
return true;
|
2013-12-10 08:32:08 +01:00
|
|
|
}
|
|
|
|
|
2014-02-13 13:51:27 +01:00
|
|
|
bool NetworkClient::Connect(unsigned short port, std::wstring serverIP)
|
|
|
|
{
|
|
|
|
//Convert from wstring to string.
|
|
|
|
typedef std::codecvt_utf8<wchar_t> convert_typeX;
|
|
|
|
std::wstring_convert<convert_typeX, wchar_t> converterX;
|
|
|
|
|
|
|
|
std::string ip = converterX.to_bytes(serverIP);
|
|
|
|
|
|
|
|
return this->Connect(port, ip.c_str());
|
|
|
|
}
|
|
|
|
|
2014-02-19 09:25:40 +01:00
|
|
|
bool NetworkClient::Reconnect()
|
|
|
|
{
|
2014-02-19 14:49:20 +01:00
|
|
|
//Return true if you are already connected.
|
2014-02-19 11:00:16 +01:00
|
|
|
if(this->IsConnected())
|
2014-02-19 14:49:20 +01:00
|
|
|
return true;
|
|
|
|
|
2014-02-19 11:00:16 +01:00
|
|
|
if(!this->privateData) this->privateData = new PrivateData();
|
|
|
|
|
|
|
|
int result = this->privateData->connection.Reconnect();
|
|
|
|
|
|
|
|
if(result != 0)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
this->privateData->owner = 0;
|
|
|
|
this->privateData->parent = this;
|
|
|
|
this->privateData->thread.Start();
|
|
|
|
|
|
|
|
return true;
|
2014-02-19 09:25:40 +01:00
|
|
|
}
|
|
|
|
|
2013-12-10 08:32:08 +01:00
|
|
|
void NetworkClient::Disconnect()
|
|
|
|
{
|
2014-01-31 10:50:38 +01:00
|
|
|
if(!privateData) return;
|
|
|
|
|
2014-02-22 22:38:28 +01:00
|
|
|
SetEvent(privateData->shutdownEvent);
|
|
|
|
privateData->thread.Wait();
|
|
|
|
|
2014-02-05 15:16:31 +01:00
|
|
|
privateData->connection.Disconnect();
|
|
|
|
this->privateData->sendQueue.Clear();
|
2014-02-09 16:42:26 +01:00
|
|
|
this->privateData->recieveQueue.Clear();
|
2013-12-10 08:32:08 +01:00
|
|
|
}
|
|
|
|
|
2013-12-12 10:32:43 +01:00
|
|
|
void NetworkClient::Send(CustomProtocolObject& protocol)
|
2013-12-10 08:32:08 +01:00
|
|
|
{
|
2014-01-31 22:52:52 +01:00
|
|
|
this->privateData->sendQueue.Push(protocol.GetProtocol());
|
2014-02-22 22:38:28 +01:00
|
|
|
WSASetEvent(this->privateData->socketEvents[1]);
|
2013-12-11 21:45:43 +01:00
|
|
|
}
|
2013-12-10 08:32:08 +01:00
|
|
|
|
2014-02-04 16:07:10 +01:00
|
|
|
void NetworkClient::Send(CustomNetProtocol& protocol)
|
2013-12-17 14:15:20 +01:00
|
|
|
{
|
2014-01-31 22:52:52 +01:00
|
|
|
this->privateData->sendQueue.Push(protocol);
|
2014-02-22 22:38:28 +01:00
|
|
|
WSASetEvent(this->privateData->socketEvents[1]);
|
2013-12-17 14:15:20 +01:00
|
|
|
}
|
|
|
|
|
2014-01-28 09:00:02 +01:00
|
|
|
void NetworkClient::SetOwner(NetworkSession* owner)
|
2013-12-11 21:45:43 +01:00
|
|
|
{
|
2014-01-29 10:18:01 +01:00
|
|
|
this->privateData->owner = owner;
|
2013-12-12 15:33:11 +01:00
|
|
|
}
|
|
|
|
|
2014-02-12 09:02:44 +01:00
|
|
|
void NetworkClient::SetMessagePump( NetworkClient::ClientEventFunction func )
|
|
|
|
{
|
|
|
|
if( func )
|
|
|
|
{
|
2014-02-12 14:33:56 +01:00
|
|
|
this->OnRecieve = func;
|
2014-02-12 09:02:44 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-02-12 14:33:56 +01:00
|
|
|
this->OnRecieve = OnRecieve_Default;
|
2014-02-12 09:02:44 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-28 09:00:02 +01:00
|
|
|
bool NetworkClient::IsConnected()
|
2013-12-12 15:33:11 +01:00
|
|
|
{
|
2014-01-28 09:00:02 +01:00
|
|
|
if(!this->privateData) return false;
|
2014-01-29 10:18:01 +01:00
|
|
|
return privateData->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-29 10:18:01 +01:00
|
|
|
return this->privateData->ID;
|
|
|
|
}
|
|
|
|
|
|
|
|
void NetworkClient::DataRecieved(NetEvent<NetworkClient*, ClientEventArgs> e)
|
|
|
|
{
|
|
|
|
if(this->privateData->owner)
|
|
|
|
{
|
|
|
|
this->privateData->owner->ClientEventCallback(e);
|
|
|
|
}
|
2014-02-12 09:02:44 +01:00
|
|
|
else
|
|
|
|
{
|
2014-02-12 14:33:56 +01:00
|
|
|
this->OnRecieve( e );
|
2014-02-12 09:02:44 +01:00
|
|
|
}
|
2013-12-16 09:00:11 +01:00
|
|
|
}
|
|
|
|
|
2014-01-29 15:01:14 +01:00
|
|
|
std::string NetworkClient::GetIpAddress()
|
|
|
|
{
|
|
|
|
return this->privateData->connection.GetIpAddress();
|
|
|
|
}
|
2014-02-20 08:33:07 +01:00
|
|
|
void NetworkClient::OutputEventData(bool output)
|
|
|
|
{
|
|
|
|
this->privateData->outputEvent;
|
2014-02-23 20:23:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool NetworkClient::StartListeningForBroadcasting(unsigned short port)
|
|
|
|
{
|
|
|
|
//Create privateData if it doesn't exists.
|
|
|
|
if(this->privateData == NULL)
|
|
|
|
{
|
|
|
|
privateData = new PrivateData;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Initiate broadcasting only if it's not started.
|
|
|
|
if(!this->privateData->broadcastingStarted)
|
|
|
|
{
|
|
|
|
//Create UDP connection
|
|
|
|
int result = this->privateData->broadcastConnection.InitiateBroadcastClient(port);
|
|
|
|
if(result)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Create event for closing the thread.
|
|
|
|
this->privateData->broadcastShutdownEvent = CreateEvent(NULL, true, false, NULL);
|
|
|
|
if(this->privateData->broadcastShutdownEvent == NULL)
|
|
|
|
{
|
|
|
|
this->privateData->broadcastConnection.Disconnect();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Creating event for broadcast messages on the UDP connection.
|
|
|
|
this->privateData->broadcastEvent = WSACreateEvent();
|
|
|
|
if(this->privateData->broadcastEvent == WSA_INVALID_EVENT)
|
|
|
|
{
|
|
|
|
this->privateData->broadcastConnection.Disconnect();
|
|
|
|
CloseHandle(this->privateData->broadcastShutdownEvent);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Set the event for only Receiving.
|
|
|
|
if(WSAEventSelect(this->privateData->broadcastConnection.GetSocket(), this->privateData->broadcastEvent, FD_READ) == SOCKET_ERROR)
|
|
|
|
{
|
|
|
|
this->privateData->broadcastConnection.Disconnect();
|
|
|
|
CloseHandle(this->privateData->broadcastShutdownEvent);
|
|
|
|
WSACloseEvent(this->privateData->broadcastEvent);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Start thread receiving broadcast messages.
|
|
|
|
this->privateData->broadcastThread = thread(&PrivateData::BroadcastThread, this->privateData);
|
|
|
|
if(!this->privateData->broadcastThread.joinable())
|
|
|
|
{
|
|
|
|
this->privateData->broadcastConnection.Disconnect();
|
|
|
|
CloseHandle(this->privateData->broadcastShutdownEvent);
|
|
|
|
WSACloseEvent(this->privateData->broadcastEvent);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
this->privateData->broadcastingStarted = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void NetworkClient::StopListeningForBroadcasting()
|
|
|
|
{
|
|
|
|
if(this->privateData->broadcastingStarted)
|
|
|
|
{
|
|
|
|
//Tell the thread to shutdown
|
|
|
|
WSASetEvent(this->privateData->broadcastShutdownEvent);
|
|
|
|
|
|
|
|
//Wait for thread
|
|
|
|
this->privateData->broadcastThread.join();
|
|
|
|
|
|
|
|
WSACloseEvent(this->privateData->broadcastEvent);
|
|
|
|
CloseHandle(this->privateData->broadcastShutdownEvent);
|
|
|
|
|
|
|
|
this->privateData->broadcastConnection.Disconnect();
|
|
|
|
|
|
|
|
this->privateData->broadcastingStarted = false;
|
|
|
|
}
|
|
|
|
}
|