Broadcasting works and I am getting the protocols out to LanMenuState!

This commit is contained in:
Pontus Fransson 2014-02-23 20:23:15 +01:00
parent a0bf9e862a
commit d64f3d7a20
6 changed files with 185 additions and 31 deletions

View File

@ -9,6 +9,8 @@
#include "GameState.h" #include "GameState.h"
#include "../Network/NetworkAPI/NetworkClient.h" #include "../Network/NetworkAPI/NetworkClient.h"
#include <Protocols.h>
#include "EventHandler\EventHandler.h" #include "EventHandler\EventHandler.h"
#include "Buttons\ButtonRectangle.h" #include "Buttons\ButtonRectangle.h"
#include "Buttons\TextField.h" #include "Buttons\TextField.h"
@ -21,6 +23,7 @@ using namespace ::Oyster;
using namespace ::Oyster::Network; using namespace ::Oyster::Network;
using namespace ::Oyster::Event; using namespace ::Oyster::Event;
using namespace ::Oyster::Math3D; using namespace ::Oyster::Math3D;
using namespace ::GameLogic;
struct LanMenuState::MyData struct LanMenuState::MyData
{ {
@ -80,6 +83,11 @@ bool LanMenuState::Init( SharedStateContent &shared )
this->privData->connectPort = 15151; this->privData->connectPort = 15151;
if(!this->privData->nwClient->StartListeningForBroadcasting(this->privData->connectPort))
{
return false;
}
return true; return true;
} }
@ -93,6 +101,8 @@ GameClientState::ClientState LanMenuState::Update( float deltaTime )
EventHandler::Instance().Update( mouseState ); EventHandler::Instance().Update( mouseState );
this->privData->nwClient->Update();
return this->privData->nextState; return this->privData->nextState;
} }
@ -114,6 +124,11 @@ bool LanMenuState::Render( )
bool LanMenuState::Release() bool LanMenuState::Release()
{ {
if(privData)
{
this->privData->nwClient->StopListeningForBroadcasting();
}
privData = NULL; privData = NULL;
return true; return true;
} }
@ -154,3 +169,35 @@ void OnButtonInteract_Exit( Oyster::Event::ButtonEvent<LanMenuState*>& e )
default: break; default: break;
} }
} }
const GameClientState::NetEvent& LanMenuState::DataRecieved( const NetEvent &message )
{
if( message.args.type == NetworkClient::ClientEventArgs::EventType_ProtocolFailedToSend )
{ // TODO: Reconnect
const char *breakpoint = "temp trap";
this->privData->nwClient->Disconnect();
this->ChangeState( GameClientState::ClientState_Main );
}
// fetching the id data.
short ID = message.args.data.protocol[0].value.netShort;
CustomNetProtocol data = message.args.data.protocol;
switch(ID)
{
case protocol_Broadcast_Test:
{
Protocol_Broadcast_Test decoded(data);
int test = decoded.test;
}
break;
default:
break;
}
return message;
}

View File

@ -21,6 +21,8 @@ namespace DanBias
virtual bool Release(); virtual bool Release();
void ChangeState( ClientState next ); void ChangeState( ClientState next );
virtual const NetEvent & DataRecieved( const NetEvent &message );
private: private:
struct MyData; struct MyData;
::Utility::DynamicMemory::UniquePointer<MyData> privData; ::Utility::DynamicMemory::UniquePointer<MyData> privData;

View File

@ -26,6 +26,8 @@
#include <queue> #include <queue>
#include <WinSock2.h> #include <WinSock2.h>
#include <thread>
//For conversion from wstring to string //For conversion from wstring to string
#include <codecvt> #include <codecvt>
@ -57,13 +59,19 @@ struct NetworkClient::PrivateData : public IThreadObject
ThreadSafeQueue<CustomNetProtocol> sendQueue; ThreadSafeQueue<CustomNetProtocol> sendQueue;
ThreadSafeQueue<NetEvent<NetworkClient*, NetworkClient::ClientEventArgs>> recieveQueue; ThreadSafeQueue<NetEvent<NetworkClient*, NetworkClient::ClientEventArgs>> recieveQueue;
//Broadcast
ConnectionUDP broadcastConnection;
//Testing for eventSelect. //Testing for eventSelect.
HANDLE socketEvents[3]; HANDLE socketEvents[2];
HANDLE shutdownEvent; HANDLE shutdownEvent;
//Broadcasting
bool broadcastingStarted;
HANDLE broadcastEvent;
HANDLE broadcastShutdownEvent;
std::thread broadcastThread;
ConnectionUDP broadcastConnection;
OysterByte broadcastTempMessage;
Translator broadcastTranslator;
//The OysterByte each message is packed in. //The OysterByte each message is packed in.
OysterByte tempMessage; OysterByte tempMessage;
@ -81,6 +89,7 @@ struct NetworkClient::PrivateData : public IThreadObject
, owner(0) , owner(0)
, outputEvent(0) , outputEvent(0)
{ {
broadcastingStarted = false;
numPackages = 0; numPackages = 0;
bufferedSend.Resize(MAX_NETWORK_MESSAGE_SIZE); bufferedSend.Resize(MAX_NETWORK_MESSAGE_SIZE);
tempMessage.Resize(MAX_NETWORK_MESSAGE_SIZE); tempMessage.Resize(MAX_NETWORK_MESSAGE_SIZE);
@ -105,7 +114,6 @@ struct NetworkClient::PrivateData : public IThreadObject
shutdownEvent = CreateEvent(NULL, true, false, NULL); shutdownEvent = CreateEvent(NULL, true, false, NULL);
socketEvents[0] = WSACreateEvent(); socketEvents[0] = WSACreateEvent();
socketEvents[1] = WSACreateEvent(); socketEvents[1] = WSACreateEvent();
socketEvents[2] = WSACreateEvent();
if(socketEvents[0] == WSA_INVALID_EVENT) if(socketEvents[0] == WSA_INVALID_EVENT)
{ {
@ -116,21 +124,34 @@ struct NetworkClient::PrivateData : public IThreadObject
{ {
//Error //Error
} }
if(WSAEventSelect(this->broadcastConnection.GetSocket(), socketEvents[2], FD_READ) == SOCKET_ERROR)
{
//Error
}
} }
void ThreadExit() void ThreadExit()
{ {
WSACloseEvent(socketEvents[0]); WSACloseEvent(socketEvents[0]);
WSACloseEvent(socketEvents[1]); WSACloseEvent(socketEvents[1]);
WSACloseEvent(socketEvents[2]);
CloseHandle(shutdownEvent); CloseHandle(shutdownEvent);
} }
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();
}
}
}
}
bool DoWork() override bool DoWork() override
{ {
WSANETWORKEVENTS wsaEvents; WSANETWORKEVENTS wsaEvents;
@ -167,18 +188,6 @@ struct NetworkClient::PrivateData : public IThreadObject
SendBuffer(); SendBuffer();
} }
} }
else if(result == 2)
{
WSAEnumNetworkEvents(this->broadcastConnection.GetSocket(), socketEvents[2], &wsaEvents);
if((wsaEvents.lNetworkEvents & FD_READ) && (wsaEvents.iErrorCode[FD_READ_BIT] == 0))
{
//Recieve a message
}
}
if(broadcastConnection.GetSocket() > 0)
{
RecvUDP();
}
} }
return false; return false;
@ -188,12 +197,12 @@ struct NetworkClient::PrivateData : public IThreadObject
{ {
int errorCode = -1; int errorCode = -1;
errorCode = this->broadcastConnection.Recieve(tempMessage); errorCode = this->broadcastConnection.Recieve(broadcastTempMessage);
if(errorCode == 0 && tempMessage.GetSize()) if(errorCode == 0 && broadcastTempMessage.GetSize())
{ {
CustomNetProtocol protocol; CustomNetProtocol protocol;
bool ok = this->translator.Unpack(protocol, tempMessage); bool ok = this->broadcastTranslator.Unpack(protocol, broadcastTempMessage);
//Check if the protocol was unpacked correctly //Check if the protocol was unpacked correctly
if(ok) if(ok)
@ -221,7 +230,7 @@ struct NetworkClient::PrivateData : public IThreadObject
} }
} }
tempMessage.Clear(); broadcastTempMessage.Clear();
} }
} }
@ -547,9 +556,6 @@ bool NetworkClient::Connect(unsigned short port, const char serverIP[])
if(!this->privateData) if(!this->privateData)
this->privateData = new PrivateData(); this->privateData = new PrivateData();
this->privateData->broadcastConnection.InitiateClient();
this->privateData->broadcastConnection.Connect(port, "0.0.0.0");
int result = this->privateData->connection.Connect(port, serverIP, true); int result = this->privateData->connection.Connect(port, serverIP, true);
//Connect has succeeded //Connect has succeeded
@ -666,3 +672,82 @@ void NetworkClient::OutputEventData(bool output)
{ {
this->privateData->outputEvent; this->privateData->outputEvent;
} }
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;
}
}

View File

@ -153,6 +153,19 @@ namespace Oyster
*/ */
void SetOutputEventDataStream(FILE out); void SetOutputEventDataStream(FILE out);
/** Starts a seperate thread for listening to broadcast messages.
* @param port: The port to listen for messages on.
* @return Returns true if broadcasting is already started or if it started now.
Returns false if it failed to start broadcasting.
*/
bool StartListeningForBroadcasting(unsigned short port);
/** Stops the seperate thread for broadcast messages.
*
*/
void StopListeningForBroadcasting();
private: private:
NetworkClient(const NetworkClient& obj); NetworkClient(const NetworkClient& obj);
NetworkClient& operator =(const NetworkClient& obj); NetworkClient& operator =(const NetworkClient& obj);

View File

@ -244,6 +244,12 @@ int ConnectionUDP::SetBlockingMode( bool blocking )
//Success //Success
return 0; return 0;
} }
int ConnectionUDP::GetSocket()
{
return socket;
}
////////////////////////////////////// //////////////////////////////////////
// Private Methods // Private Methods
////////////////////////////////////// //////////////////////////////////////

View File

@ -38,6 +38,7 @@ namespace Oyster
bool IsSending(); bool IsSending();
bool IsConnected(); bool IsConnected();
int GetIpSize(); int GetIpSize();
int GetSocket();
int SetBlockingMode( bool blocking ); int SetBlockingMode( bool blocking );