diff --git a/Code/Game/GameClient/GameClientState/LanMenuState.cpp b/Code/Game/GameClient/GameClientState/LanMenuState.cpp index 8c096617..05ba435c 100644 --- a/Code/Game/GameClient/GameClientState/LanMenuState.cpp +++ b/Code/Game/GameClient/GameClientState/LanMenuState.cpp @@ -9,6 +9,8 @@ #include "GameState.h" #include "../Network/NetworkAPI/NetworkClient.h" +#include + #include "EventHandler\EventHandler.h" #include "Buttons\ButtonRectangle.h" #include "Buttons\TextField.h" @@ -21,6 +23,7 @@ using namespace ::Oyster; using namespace ::Oyster::Network; using namespace ::Oyster::Event; using namespace ::Oyster::Math3D; +using namespace ::GameLogic; struct LanMenuState::MyData { @@ -80,6 +83,11 @@ bool LanMenuState::Init( SharedStateContent &shared ) this->privData->connectPort = 15151; + if(!this->privData->nwClient->StartListeningForBroadcasting(this->privData->connectPort)) + { + return false; + } + return true; } @@ -93,6 +101,8 @@ GameClientState::ClientState LanMenuState::Update( float deltaTime ) EventHandler::Instance().Update( mouseState ); + this->privData->nwClient->Update(); + return this->privData->nextState; } @@ -114,6 +124,11 @@ bool LanMenuState::Render( ) bool LanMenuState::Release() { + if(privData) + { + this->privData->nwClient->StopListeningForBroadcasting(); + } + privData = NULL; return true; } @@ -154,3 +169,35 @@ void OnButtonInteract_Exit( Oyster::Event::ButtonEvent& e ) 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; +} \ No newline at end of file diff --git a/Code/Game/GameClient/GameClientState/LanMenuState.h b/Code/Game/GameClient/GameClientState/LanMenuState.h index 57889eee..1edf1308 100644 --- a/Code/Game/GameClient/GameClientState/LanMenuState.h +++ b/Code/Game/GameClient/GameClientState/LanMenuState.h @@ -20,6 +20,8 @@ namespace DanBias virtual bool Render(); virtual bool Release(); void ChangeState( ClientState next ); + + virtual const NetEvent & DataRecieved( const NetEvent &message ); private: struct MyData; diff --git a/Code/Network/NetworkAPI/NetworkClient.cpp b/Code/Network/NetworkAPI/NetworkClient.cpp index f6d838fd..9f26121b 100644 --- a/Code/Network/NetworkAPI/NetworkClient.cpp +++ b/Code/Network/NetworkAPI/NetworkClient.cpp @@ -26,6 +26,8 @@ #include #include +#include + //For conversion from wstring to string #include @@ -57,13 +59,19 @@ struct NetworkClient::PrivateData : public IThreadObject ThreadSafeQueue sendQueue; ThreadSafeQueue> recieveQueue; - //Broadcast - ConnectionUDP broadcastConnection; - //Testing for eventSelect. - HANDLE socketEvents[3]; + HANDLE socketEvents[2]; 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. OysterByte tempMessage; @@ -81,6 +89,7 @@ struct NetworkClient::PrivateData : public IThreadObject , owner(0) , outputEvent(0) { + broadcastingStarted = false; numPackages = 0; bufferedSend.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); socketEvents[0] = WSACreateEvent(); socketEvents[1] = WSACreateEvent(); - socketEvents[2] = WSACreateEvent(); if(socketEvents[0] == WSA_INVALID_EVENT) { @@ -116,21 +124,34 @@ struct NetworkClient::PrivateData : public IThreadObject { //Error } - - if(WSAEventSelect(this->broadcastConnection.GetSocket(), socketEvents[2], FD_READ) == SOCKET_ERROR) - { - //Error - } } void ThreadExit() { WSACloseEvent(socketEvents[0]); WSACloseEvent(socketEvents[1]); - WSACloseEvent(socketEvents[2]); 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 { WSANETWORKEVENTS wsaEvents; @@ -167,18 +188,6 @@ struct NetworkClient::PrivateData : public IThreadObject 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; @@ -188,12 +197,12 @@ struct NetworkClient::PrivateData : public IThreadObject { 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; - bool ok = this->translator.Unpack(protocol, tempMessage); + bool ok = this->broadcastTranslator.Unpack(protocol, broadcastTempMessage); //Check if the protocol was unpacked correctly if(ok) @@ -221,7 +230,7 @@ struct NetworkClient::PrivateData : public IThreadObject } } - tempMessage.Clear(); + broadcastTempMessage.Clear(); } } @@ -546,9 +555,6 @@ bool NetworkClient::Connect(unsigned short port, const char serverIP[]) if(!this->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); @@ -665,4 +671,83 @@ std::string NetworkClient::GetIpAddress() void NetworkClient::OutputEventData(bool output) { this->privateData->outputEvent; -} \ No newline at end of file +} + +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; + } +} diff --git a/Code/Network/NetworkAPI/NetworkClient.h b/Code/Network/NetworkAPI/NetworkClient.h index dddef221..9a3a367f 100644 --- a/Code/Network/NetworkAPI/NetworkClient.h +++ b/Code/Network/NetworkAPI/NetworkClient.h @@ -153,6 +153,19 @@ namespace Oyster */ 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: NetworkClient(const NetworkClient& obj); NetworkClient& operator =(const NetworkClient& obj); diff --git a/Code/Network/NetworkDependencies/ConnectionUDP.cpp b/Code/Network/NetworkDependencies/ConnectionUDP.cpp index 580e2a2f..2c0e5b25 100644 --- a/Code/Network/NetworkDependencies/ConnectionUDP.cpp +++ b/Code/Network/NetworkDependencies/ConnectionUDP.cpp @@ -244,6 +244,12 @@ int ConnectionUDP::SetBlockingMode( bool blocking ) //Success return 0; } + +int ConnectionUDP::GetSocket() +{ + return socket; +} + ////////////////////////////////////// // Private Methods ////////////////////////////////////// diff --git a/Code/Network/NetworkDependencies/ConnectionUDP.h b/Code/Network/NetworkDependencies/ConnectionUDP.h index 5dde5281..83a48482 100644 --- a/Code/Network/NetworkDependencies/ConnectionUDP.h +++ b/Code/Network/NetworkDependencies/ConnectionUDP.h @@ -38,6 +38,7 @@ namespace Oyster bool IsSending(); bool IsConnected(); int GetIpSize(); + int GetSocket(); int SetBlockingMode( bool blocking );