From a0bf9e862ac544e72bc97659bbd80076a7fbe6bf Mon Sep 17 00:00:00 2001 From: Pontus Fransson Date: Sun, 23 Feb 2014 18:38:20 +0100 Subject: [PATCH 1/9] Started implementing broadcasting. --- Code/Game/GameProtocols/GeneralProtocols.h | 33 +++++++++ .../GameProtocols/ProtocolIdentificationID.h | 1 + .../GameServer/Implementation/GameServer.cpp | 9 +++ Code/Network/NetworkAPI/NetworkClient.cpp | 71 ++++++++++++++++++- Code/Network/NetworkAPI/NetworkServer.cpp | 63 +++++++++++++++- .../NetworkDependencies/ConnectionUDP.cpp | 57 +++++++++++++-- .../NetworkDependencies/ConnectionUDP.h | 6 +- 7 files changed, 227 insertions(+), 13 deletions(-) diff --git a/Code/Game/GameProtocols/GeneralProtocols.h b/Code/Game/GameProtocols/GeneralProtocols.h index db50b61f..5e46aa10 100644 --- a/Code/Game/GameProtocols/GeneralProtocols.h +++ b/Code/Game/GameProtocols/GeneralProtocols.h @@ -72,5 +72,38 @@ namespace GameLogic Oyster::Network::CustomNetProtocol protocol; }; + //#define protocol_Broadcast_Test 102 + struct Protocol_Broadcast_Test :public Oyster::Network::CustomProtocolObject + { + int test; + + Protocol_Broadcast_Test() + { + this->protocol[0].type = Oyster::Network::NetAttributeType_Short; + this->protocol[0].value.netShort = protocol_Broadcast_Test; + this->protocol[1].type = Oyster::Network::NetAttributeType_Int; + this->test = 0; + } + Protocol_Broadcast_Test(int test) + { + this->protocol[0].type = Oyster::Network::NetAttributeType_Short; + this->protocol[0].value.netShort = protocol_Broadcast_Test; + this->protocol[1].type = Oyster::Network::NetAttributeType_Int; + this->test = test; + } + Protocol_Broadcast_Test(Oyster::Network::CustomNetProtocol& p) + { + this->test = p[1].value.netInt; + } + Oyster::Network::CustomNetProtocol GetProtocol() override + { + this->protocol[1].value = this->test; + + return protocol; + } + + private: + Oyster::Network::CustomNetProtocol protocol; + }; } #endif //!GAMELOGIC_CONTROL_PROTOCOLS_H \ No newline at end of file diff --git a/Code/Game/GameProtocols/ProtocolIdentificationID.h b/Code/Game/GameProtocols/ProtocolIdentificationID.h index 79235e2f..e1a23850 100644 --- a/Code/Game/GameProtocols/ProtocolIdentificationID.h +++ b/Code/Game/GameProtocols/ProtocolIdentificationID.h @@ -20,6 +20,7 @@ #define protocol_GeneralMIN 100 #define protocol_General_Status 100 #define protocol_General_Text 101 +#define protocol_Broadcast_Test 102 #define protocol_GeneralMAX 199 diff --git a/Code/Game/GameServer/Implementation/GameServer.cpp b/Code/Game/GameServer/Implementation/GameServer.cpp index f003fc50..2c2eb20d 100644 --- a/Code/Game/GameServer/Implementation/GameServer.cpp +++ b/Code/Game/GameServer/Implementation/GameServer.cpp @@ -10,6 +10,8 @@ #include "..\GameLobby.h" #include "..\GameSession.h" +#include "..\GameProtocols\GeneralProtocols.h" + #include #include @@ -47,6 +49,13 @@ DanBiasServerReturn GameServerAPI::ServerInitiate(const ServerInitDesc& desc) ServerOptions opt; opt.mainOptions.listenPort = desc.listenPort; opt.mainOptions.ownerSession = &lobby; + + GameLogic::Protocol_Broadcast_Test broadcastMessage(2); + + opt.broadcastOptions.broadcast = true; + opt.broadcastOptions.broadcastInterval = 1.0f; + opt.broadcastOptions.broadcastMessage = broadcastMessage.GetProtocol(); + if(server.Init(opt) == NetworkServer::ServerReturnCode_Error) { return DanBiasServerReturn_Error; diff --git a/Code/Network/NetworkAPI/NetworkClient.cpp b/Code/Network/NetworkAPI/NetworkClient.cpp index 56425109..f6d838fd 100644 --- a/Code/Network/NetworkAPI/NetworkClient.cpp +++ b/Code/Network/NetworkAPI/NetworkClient.cpp @@ -13,6 +13,7 @@ #include "CustomNetProtocol.h" #include "NetworkSession.h" +#include "../NetworkDependencies/ConnectionUDP.h" #include "../NetworkDependencies/Connection.h" #include "../NetworkDependencies/PostBox.h" #include "../NetworkDependencies/WinsockFunctions.h" @@ -56,8 +57,11 @@ struct NetworkClient::PrivateData : public IThreadObject ThreadSafeQueue sendQueue; ThreadSafeQueue> recieveQueue; + //Broadcast + ConnectionUDP broadcastConnection; + //Testing for eventSelect. - HANDLE socketEvents[2]; + HANDLE socketEvents[3]; HANDLE shutdownEvent; //The OysterByte each message is packed in. @@ -101,6 +105,7 @@ 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) { @@ -111,12 +116,18 @@ 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); } @@ -128,7 +139,7 @@ struct NetworkClient::PrivateData : public IThreadObject { if(!this->connection.IsConnected()) return false; - int result = WSAWaitForMultipleEvents(2, socketEvents, FALSE, 100, FALSE) - WSA_WAIT_EVENT_0; + int result = WSAWaitForMultipleEvents(3, socketEvents, FALSE, 100, FALSE) - WSA_WAIT_EVENT_0; if(result == 0) { WSAEnumNetworkEvents(this->connection.GetSocket(), socketEvents[0], &wsaEvents); @@ -156,11 +167,64 @@ 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; } + void RecvUDP() + { + int errorCode = -1; + + errorCode = this->broadcastConnection.Recieve(tempMessage); + + if(errorCode == 0 && tempMessage.GetSize()) + { + CustomNetProtocol protocol; + bool ok = this->translator.Unpack(protocol, tempMessage); + + //Check if the protocol was unpacked correctly + if(ok) + { + CEA parg; + parg.type = CEA::EventType_ProtocolRecieved; + parg.data.protocol = protocol; + NetEvent 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()); + } + } + + tempMessage.Clear(); + } + } + void SendBuffer() { if(bufferedSend.GetSize() > 0) @@ -483,6 +547,9 @@ 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); //Connect has succeeded diff --git a/Code/Network/NetworkAPI/NetworkServer.cpp b/Code/Network/NetworkAPI/NetworkServer.cpp index 7d1cbdc5..d666ca49 100644 --- a/Code/Network/NetworkAPI/NetworkServer.cpp +++ b/Code/Network/NetworkAPI/NetworkServer.cpp @@ -10,6 +10,8 @@ #include "NetworkServer.h" +#include "Translator.h" +#include "../NetworkDependencies/ConnectionUDP.h" #include "../NetworkDependencies/Listener.h" #include "../NetworkDependencies/PostBox.h" #include "../NetworkDependencies/WinsockFunctions.h" @@ -81,7 +83,14 @@ public: , port(-1) , broadcast(0) , broadcastTime(1.0f, 0.0f) - { } + { + InitWinSock(); + serverOptions.broadcastOptions.broadcastInterval = 1.0f; + serverOptions.broadcastOptions.broadcast = true; + broadcastMessage.Resize(MAX_NETWORK_MESSAGE_SIZE); + + broadcastConnection.InitiateBroadcastServer(15151, "255.255.255.255"); + } ~PrivateData() { if(listener) @@ -91,6 +100,12 @@ public: } } + + void SendBroadcast() + { + broadcastConnection.Send(broadcastMessage); + } + bool DoWork(); public: @@ -106,6 +121,11 @@ public: int port; bool broadcast; + ServerOptions serverOptions; + + ConnectionUDP broadcastConnection; + OysterByte broadcastMessage; + TimeInstance broadcastTime; Utility::WinTimer serverTimer; @@ -113,11 +133,17 @@ public: bool NetworkServer::PrivateData::DoWork() { - if(broadcast) + if(serverOptions.broadcastOptions.broadcast) { if( (this->serverTimer.getElapsedSeconds() - this->broadcastTime.previous) >= this->broadcastTime.length ) { - Broadcast(); + broadcastMessage.Clear(); + Translator t; + t.Pack(broadcastMessage, serverOptions.broadcastOptions.broadcastMessage); + serverTimer.reset(); + //Broadcast(); + SendBroadcast(); + } } @@ -197,6 +223,8 @@ NetworkServer::ServerReturnCode NetworkServer::Init(ServerOptions& options) return NetworkServer::ServerReturnCode_Error; } + this->privateData->serverOptions.broadcastOptions = options.broadcastOptions; + this->privateData->isInitiated = true; this->privateData->isReleased = false; return NetworkServer::ServerReturnCode_Sucess; @@ -319,6 +347,35 @@ int NetworkServer::GetPort() return this->privateData->port; } +/*************************************** + Broadcast functions +***************************************/ +//Set broadcast settings. +void NetworkServer::SetBroadcast(CustomNetProtocol& broadcastMessage, float interval, bool enable) +{ + this->privateData->serverOptions.broadcastOptions.broadcast = enable; + this->privateData->serverOptions.broadcastOptions.broadcastMessage = broadcastMessage; + this->privateData->serverOptions.broadcastOptions.broadcastInterval = interval; + Translator t; + t.Pack(this->privateData->broadcastMessage, broadcastMessage); +} +//Set broadcast settings. +void NetworkServer::SetBroadcastMessage(CustomNetProtocol& broadcastMessage) +{ + this->privateData->serverOptions.broadcastOptions.broadcastMessage = broadcastMessage; + Translator t; + t.Pack(this->privateData->broadcastMessage, broadcastMessage); +} +//Enable/disable broadcast. +void NetworkServer::SetBroadcast(bool enable) +{ + this->privateData->serverOptions.broadcastOptions.broadcast = enable; +} +//Set interval between each broadcast message in seconds. +void NetworkServer::SetBroadcastInterval(float interval) +{ + this->privateData->serverOptions.broadcastOptions.broadcastInterval = interval; +} \ No newline at end of file diff --git a/Code/Network/NetworkDependencies/ConnectionUDP.cpp b/Code/Network/NetworkDependencies/ConnectionUDP.cpp index 44a49d2d..580e2a2f 100644 --- a/Code/Network/NetworkDependencies/ConnectionUDP.cpp +++ b/Code/Network/NetworkDependencies/ConnectionUDP.cpp @@ -41,8 +41,24 @@ int ConnectionUDP::Connect(unsigned short port, const char serverName[]) } + //this->Address = htonl(0xffffffff); this->Address = *(unsigned long*)hostEnt->h_addr; this->port = htons(this->port); + + if(this->Address == 0) + { + sockaddr_in addr; + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_family = AF_INET; + addr.sin_port = this->port; + + int result = bind(socket, (const sockaddr*)&addr, sizeof(addr)); + if(result) + { + int a = 0; + } + } + return 0; } @@ -89,19 +105,46 @@ int ConnectionUDP::InitiateClient() return InitiateSocket(); } -int ConnectionUDP::InitiateBroadcast(unsigned short port) +int ConnectionUDP::InitiateBroadcastServer(unsigned short port, const char serverName[]) { int result = InitiateSocket(); - int flag = 1; - result = setsockopt(this->socket, /* socket affected */ - SOL_SOCKET, /* set option at TCP level */ - SO_BROADCAST, /* name of option */ - (char *) &flag, /* the cast is historical cruft */ - sizeof(flag)); /* length of option value */ + result = setsockopt(this->socket, SOL_SOCKET, SO_BROADCAST, (char *) &flag, sizeof(flag)); if (result < 0) return -1; + + closed = false; + stillSending = true; + + struct hostent *hostEnt; + if((hostEnt = gethostbyname(serverName)) == NULL) + { + return SOCKET_ERROR; + } + + this->Address = *(unsigned long*)hostEnt->h_addr; + this->port = htons(port); + + return 0; +} + +int ConnectionUDP::InitiateBroadcastClient(unsigned short port) +{ + int result = InitiateSocket(); + + struct sockaddr_in recvAddr; + recvAddr.sin_family = AF_INET; + recvAddr.sin_addr.s_addr = INADDR_ANY; + recvAddr.sin_port = htons(port); + + if(bind(this->socket, (sockaddr*)&recvAddr, sizeof(recvAddr)) == SOCKET_ERROR) + { + closesocket(this->socket); + return SOCKET_ERROR; + } + + return result; } int ConnectionUDP::Send(OysterByte &bytes) diff --git a/Code/Network/NetworkDependencies/ConnectionUDP.h b/Code/Network/NetworkDependencies/ConnectionUDP.h index 163ad741..5dde5281 100644 --- a/Code/Network/NetworkDependencies/ConnectionUDP.h +++ b/Code/Network/NetworkDependencies/ConnectionUDP.h @@ -22,13 +22,17 @@ namespace Oyster virtual int InitiateServer( unsigned short port ); virtual int InitiateClient(); - virtual int InitiateBroadcast(unsigned short port); + virtual int InitiateBroadcastServer(unsigned short port, const char serverName[]); + virtual int InitiateBroadcastClient(unsigned short port); virtual int Send ( OysterByte &byte ); virtual int Recieve( OysterByte &byte ); virtual int Connect( unsigned short port, const char serverName[] ); + //Doesn't do anything now. + virtual int Reconnect() { return 0; } + virtual int Disconnect(); bool IsSending(); From d64f3d7a20c1a984efb0a2f23d3099763b154a80 Mon Sep 17 00:00:00 2001 From: Pontus Fransson Date: Sun, 23 Feb 2014 20:23:15 +0100 Subject: [PATCH 2/9] Broadcasting works and I am getting the protocols out to LanMenuState! --- .../GameClientState/LanMenuState.cpp | 47 ++++++ .../GameClient/GameClientState/LanMenuState.h | 2 + Code/Network/NetworkAPI/NetworkClient.cpp | 147 ++++++++++++++---- Code/Network/NetworkAPI/NetworkClient.h | 13 ++ .../NetworkDependencies/ConnectionUDP.cpp | 6 + .../NetworkDependencies/ConnectionUDP.h | 1 + 6 files changed, 185 insertions(+), 31 deletions(-) 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 ); From be1c3e2af099d49c4e239a1d8ff25f50a2333ac4 Mon Sep 17 00:00:00 2001 From: Pontus Fransson Date: Sun, 23 Feb 2014 20:40:29 +0100 Subject: [PATCH 3/9] Sending strings in broadcast message. --- .../GameClientState/LanMenuState.cpp | 6 +++- Code/Game/GameProtocols/GeneralProtocols.h | 28 +++++++++++++------ .../GameServer/Implementation/GameServer.cpp | 2 +- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/Code/Game/GameClient/GameClientState/LanMenuState.cpp b/Code/Game/GameClient/GameClientState/LanMenuState.cpp index 05ba435c..0eaa4d95 100644 --- a/Code/Game/GameClient/GameClientState/LanMenuState.cpp +++ b/Code/Game/GameClient/GameClientState/LanMenuState.cpp @@ -190,7 +190,11 @@ const GameClientState::NetEvent& LanMenuState::DataRecieved( const NetEvent &mes { Protocol_Broadcast_Test decoded(data); - int test = decoded.test; + unsigned short port = decoded.port; + std::string ip = decoded.ip; + std::string name = decoded.name; + printf("Broadcast message: %d: %s: %s\n", port, ip.c_str(), name.c_str()); + this->privData->connectIP->AppendText(L"Hej"); } break; diff --git a/Code/Game/GameProtocols/GeneralProtocols.h b/Code/Game/GameProtocols/GeneralProtocols.h index 5e46aa10..cb58f3f8 100644 --- a/Code/Game/GameProtocols/GeneralProtocols.h +++ b/Code/Game/GameProtocols/GeneralProtocols.h @@ -75,29 +75,41 @@ namespace GameLogic //#define protocol_Broadcast_Test 102 struct Protocol_Broadcast_Test :public Oyster::Network::CustomProtocolObject { - int test; + unsigned short port; + std::string ip; + std::string name; Protocol_Broadcast_Test() { this->protocol[0].type = Oyster::Network::NetAttributeType_Short; this->protocol[0].value.netShort = protocol_Broadcast_Test; - this->protocol[1].type = Oyster::Network::NetAttributeType_Int; - this->test = 0; + this->protocol[1].type = Oyster::Network::NetAttributeType_UnsignedShort; + this->protocol[2].type = Oyster::Network::NetAttributeType_CharArray; + this->protocol[3].type = Oyster::Network::NetAttributeType_CharArray; + this->port = 0; } - Protocol_Broadcast_Test(int test) + Protocol_Broadcast_Test(unsigned short port, std::string ip, std::string name) { this->protocol[0].type = Oyster::Network::NetAttributeType_Short; this->protocol[0].value.netShort = protocol_Broadcast_Test; - this->protocol[1].type = Oyster::Network::NetAttributeType_Int; - this->test = test; + this->protocol[1].type = Oyster::Network::NetAttributeType_UnsignedShort; + this->port = port; + this->protocol[2].type = Oyster::Network::NetAttributeType_CharArray; + this->ip = ip; + this->protocol[3].type = Oyster::Network::NetAttributeType_CharArray; + this->name = name; } Protocol_Broadcast_Test(Oyster::Network::CustomNetProtocol& p) { - this->test = p[1].value.netInt; + this->port = p[1].value.netUShort; + this->ip.assign(p[2].value.netCharPtr); + this->name.assign(p[3].value.netCharPtr); } Oyster::Network::CustomNetProtocol GetProtocol() override { - this->protocol[1].value = this->test; + this->protocol[1].value = this->port; + this->protocol.Set(2, ip); + this->protocol.Set(3, name); return protocol; } diff --git a/Code/Game/GameServer/Implementation/GameServer.cpp b/Code/Game/GameServer/Implementation/GameServer.cpp index 2c2eb20d..a4545a80 100644 --- a/Code/Game/GameServer/Implementation/GameServer.cpp +++ b/Code/Game/GameServer/Implementation/GameServer.cpp @@ -50,7 +50,7 @@ DanBiasServerReturn GameServerAPI::ServerInitiate(const ServerInitDesc& desc) opt.mainOptions.listenPort = desc.listenPort; opt.mainOptions.ownerSession = &lobby; - GameLogic::Protocol_Broadcast_Test broadcastMessage(2); + GameLogic::Protocol_Broadcast_Test broadcastMessage(opt.mainOptions.listenPort, "127.0.0.1", "ServerName"); opt.broadcastOptions.broadcast = true; opt.broadcastOptions.broadcastInterval = 1.0f; From 0cb7940baed7aa3c776c5c9601d5b7cc35f81f74 Mon Sep 17 00:00:00 2001 From: Pontus Fransson Date: Sun, 23 Feb 2014 21:15:16 +0100 Subject: [PATCH 4/9] Sending real ip address, port and server name. --- .../GameServer/Implementation/GameServer.cpp | 17 +++++++++++++++-- Code/Network/NetworkAPI/NetworkClient.cpp | 1 + 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Code/Game/GameServer/Implementation/GameServer.cpp b/Code/Game/GameServer/Implementation/GameServer.cpp index a4545a80..d2b86332 100644 --- a/Code/Game/GameServer/Implementation/GameServer.cpp +++ b/Code/Game/GameServer/Implementation/GameServer.cpp @@ -20,6 +20,9 @@ #include #include +//For conversion from wstring to string +#include + using namespace DanBias; using namespace Oyster::Network; using namespace Oyster::Thread; @@ -43,6 +46,11 @@ namespace } +std::string wstring_to_utf8 (const std::wstring& str) +{ + std::wstring_convert> myconv; + return myconv.to_bytes(str); +} DanBiasServerReturn GameServerAPI::ServerInitiate(const ServerInitDesc& desc) { @@ -50,7 +58,9 @@ DanBiasServerReturn GameServerAPI::ServerInitiate(const ServerInitDesc& desc) opt.mainOptions.listenPort = desc.listenPort; opt.mainOptions.ownerSession = &lobby; - GameLogic::Protocol_Broadcast_Test broadcastMessage(opt.mainOptions.listenPort, "127.0.0.1", "ServerName"); + std::string serverName = wstring_to_utf8(desc.serverName); + + GameLogic::Protocol_Broadcast_Test broadcastMessage(opt.mainOptions.listenPort, "127.0.0.1", serverName); opt.broadcastOptions.broadcast = true; opt.broadcastOptions.broadcastInterval = 1.0f; @@ -63,7 +73,10 @@ DanBiasServerReturn GameServerAPI::ServerInitiate(const ServerInitDesc& desc) GameSession::GameDescription d; std::printf("Server created!\t-\t%s: [%i]\n\n", server.GetLanAddress().c_str(), desc.listenPort); - + + GameLogic::Protocol_Broadcast_Test broadcastMessage2(opt.mainOptions.listenPort, server.GetLanAddress(), serverName); + server.SetBroadcastMessage(broadcastMessage2.GetProtocol()); + return DanBiasServerReturn_Sucess; } void GameServerAPI::ServerStart() diff --git a/Code/Network/NetworkAPI/NetworkClient.cpp b/Code/Network/NetworkAPI/NetworkClient.cpp index 9f26121b..91bd13cb 100644 --- a/Code/Network/NetworkAPI/NetworkClient.cpp +++ b/Code/Network/NetworkAPI/NetworkClient.cpp @@ -133,6 +133,7 @@ struct NetworkClient::PrivateData : public IThreadObject CloseHandle(shutdownEvent); } + //Thread for receiving broadcast messages void BroadcastThread() { WSANETWORKEVENTS wsaEvents; From 203220f43b6f2e517bbb8a78e852321dbb3c4763 Mon Sep 17 00:00:00 2001 From: Pontus Fransson Date: Sun, 23 Feb 2014 22:06:18 +0100 Subject: [PATCH 5/9] When OysterThread was idle it was using a lot of cpu power. --- Code/Misc/Utilities/Thread/OysterThread_Impl.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Code/Misc/Utilities/Thread/OysterThread_Impl.cpp b/Code/Misc/Utilities/Thread/OysterThread_Impl.cpp index 91430eab..e2809c4f 100644 --- a/Code/Misc/Utilities/Thread/OysterThread_Impl.cpp +++ b/Code/Misc/Utilities/Thread/OysterThread_Impl.cpp @@ -193,8 +193,11 @@ using namespace Utility::DynamicMemory; if(w->msec > 0) std::this_thread::sleep_for(std::chrono::milliseconds(w->msec)); - while (w->state == OYSTER_THREAD_STATE_IDLE) + while (w->state == OYSTER_THREAD_STATE_IDLE) + { + CheckPriority(w); std::this_thread::yield(); + } } static void ThreadingFunction(ThreadData* w) { From 5fe89f1d8f6073e64ad959904bafc16267047b88 Mon Sep 17 00:00:00 2001 From: Pontus Fransson Date: Sun, 23 Feb 2014 22:07:33 +0100 Subject: [PATCH 6/9] Fixed some crashes and added mutex around broadcast options on network server. --- .../GameClientState/LanMenuState.cpp | 1 - Code/Network/NetworkAPI/NetworkClient.cpp | 21 ++++++----- Code/Network/NetworkAPI/NetworkServer.cpp | 36 ++++++++++++------- 3 files changed, 35 insertions(+), 23 deletions(-) diff --git a/Code/Game/GameClient/GameClientState/LanMenuState.cpp b/Code/Game/GameClient/GameClientState/LanMenuState.cpp index 0eaa4d95..432770b9 100644 --- a/Code/Game/GameClient/GameClientState/LanMenuState.cpp +++ b/Code/Game/GameClient/GameClientState/LanMenuState.cpp @@ -194,7 +194,6 @@ const GameClientState::NetEvent& LanMenuState::DataRecieved( const NetEvent &mes std::string ip = decoded.ip; std::string name = decoded.name; printf("Broadcast message: %d: %s: %s\n", port, ip.c_str(), name.c_str()); - this->privData->connectIP->AppendText(L"Hej"); } break; diff --git a/Code/Network/NetworkAPI/NetworkClient.cpp b/Code/Network/NetworkAPI/NetworkClient.cpp index 91bd13cb..57155ef7 100644 --- a/Code/Network/NetworkAPI/NetworkClient.cpp +++ b/Code/Network/NetworkAPI/NetworkClient.cpp @@ -736,19 +736,22 @@ bool NetworkClient::StartListeningForBroadcasting(unsigned short port) void NetworkClient::StopListeningForBroadcasting() { - if(this->privateData->broadcastingStarted) + if(this->privateData) { - //Tell the thread to shutdown - WSASetEvent(this->privateData->broadcastShutdownEvent); + if(this->privateData->broadcastingStarted) + { + //Tell the thread to shutdown + WSASetEvent(this->privateData->broadcastShutdownEvent); - //Wait for thread - this->privateData->broadcastThread.join(); + //Wait for thread + this->privateData->broadcastThread.join(); - WSACloseEvent(this->privateData->broadcastEvent); - CloseHandle(this->privateData->broadcastShutdownEvent); + WSACloseEvent(this->privateData->broadcastEvent); + CloseHandle(this->privateData->broadcastShutdownEvent); - this->privateData->broadcastConnection.Disconnect(); + this->privateData->broadcastConnection.Disconnect(); - this->privateData->broadcastingStarted = false; + this->privateData->broadcastingStarted = false; + } } } diff --git a/Code/Network/NetworkAPI/NetworkServer.cpp b/Code/Network/NetworkAPI/NetworkServer.cpp index d666ca49..a761c207 100644 --- a/Code/Network/NetworkAPI/NetworkServer.cpp +++ b/Code/Network/NetworkAPI/NetworkServer.cpp @@ -20,6 +20,7 @@ #include "Thread/OysterThread.h" #include "WinTimer.h" +#include using namespace Oyster::Network; using namespace Utility::DynamicMemory; @@ -83,6 +84,7 @@ public: , port(-1) , broadcast(0) , broadcastTime(1.0f, 0.0f) + , broadcastMutex(new std::mutex) { InitWinSock(); serverOptions.broadcastOptions.broadcastInterval = 1.0f; @@ -100,12 +102,6 @@ public: } } - - void SendBroadcast() - { - broadcastConnection.Send(broadcastMessage); - } - bool DoWork(); public: @@ -123,6 +119,7 @@ public: ServerOptions serverOptions; + SmartPointer broadcastMutex; ConnectionUDP broadcastConnection; OysterByte broadcastMessage; @@ -135,15 +132,16 @@ bool NetworkServer::PrivateData::DoWork() { if(serverOptions.broadcastOptions.broadcast) { - if( (this->serverTimer.getElapsedSeconds() - this->broadcastTime.previous) >= this->broadcastTime.length ) + if( (this->serverTimer.getElapsedSeconds() - this->broadcastTime.previous) >= this->serverOptions.broadcastOptions.broadcastInterval ) { - broadcastMessage.Clear(); - Translator t; - t.Pack(broadcastMessage, serverOptions.broadcastOptions.broadcastMessage); + //broadcastMessage.Clear(); + //Translator t; + //t.Pack(broadcastMessage, serverOptions.broadcastOptions.broadcastMessage); serverTimer.reset(); - //Broadcast(); - SendBroadcast(); - + + broadcastMutex->lock(); + broadcastConnection.Send(broadcastMessage); + broadcastMutex->unlock(); } } @@ -353,29 +351,41 @@ int NetworkServer::GetPort() //Set broadcast settings. void NetworkServer::SetBroadcast(CustomNetProtocol& broadcastMessage, float interval, bool enable) { + this->privateData->broadcastMutex->lock(); this->privateData->serverOptions.broadcastOptions.broadcast = enable; this->privateData->serverOptions.broadcastOptions.broadcastMessage = broadcastMessage; this->privateData->serverOptions.broadcastOptions.broadcastInterval = interval; + + this->privateData->broadcastMessage.Clear(); Translator t; t.Pack(this->privateData->broadcastMessage, broadcastMessage); + this->privateData->broadcastMutex->unlock(); } //Set broadcast settings. void NetworkServer::SetBroadcastMessage(CustomNetProtocol& broadcastMessage) { + this->privateData->broadcastMutex->lock(); this->privateData->serverOptions.broadcastOptions.broadcastMessage = broadcastMessage; + + this->privateData->broadcastMessage.Clear(); Translator t; t.Pack(this->privateData->broadcastMessage, broadcastMessage); + this->privateData->broadcastMutex->unlock(); } //Enable/disable broadcast. void NetworkServer::SetBroadcast(bool enable) { + this->privateData->broadcastMutex->lock(); this->privateData->serverOptions.broadcastOptions.broadcast = enable; + this->privateData->broadcastMutex->unlock(); } //Set interval between each broadcast message in seconds. void NetworkServer::SetBroadcastInterval(float interval) { + this->privateData->broadcastMutex->lock(); this->privateData->serverOptions.broadcastOptions.broadcastInterval = interval; + this->privateData->broadcastMutex->unlock(); } \ No newline at end of file From bf07ef5f5fd7472b6db0488dbf3e020200da8eac Mon Sep 17 00:00:00 2001 From: Pontus Fransson Date: Sun, 23 Feb 2014 22:25:41 +0100 Subject: [PATCH 7/9] Connecting to the ip and port received in the last broadcast message. --- Code/Game/GameClient/GameClientState/LanMenuState.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Code/Game/GameClient/GameClientState/LanMenuState.cpp b/Code/Game/GameClient/GameClientState/LanMenuState.cpp index 432770b9..28b1fb84 100644 --- a/Code/Game/GameClient/GameClientState/LanMenuState.cpp +++ b/Code/Game/GameClient/GameClientState/LanMenuState.cpp @@ -37,6 +37,9 @@ struct LanMenuState::MyData TextField *connectIP; unsigned short connectPort; + + std::string ip; + } privData; void OnButtonInteract_Connect( Oyster::Event::ButtonEvent& e ); @@ -139,7 +142,7 @@ void LanMenuState::ChangeState( ClientState next ) { case GameClientState::ClientState_Lobby: // attempt to connect to lobby - if( !this->privData->nwClient->Connect(this->privData->connectPort, (*this->privData->connectIP)[0]) ) + if( !this->privData->nwClient->Connect(this->privData->connectPort, this->privData->ip.c_str()) ) return; break; default: break; @@ -194,6 +197,9 @@ const GameClientState::NetEvent& LanMenuState::DataRecieved( const NetEvent &mes std::string ip = decoded.ip; std::string name = decoded.name; printf("Broadcast message: %d: %s: %s\n", port, ip.c_str(), name.c_str()); + + this->privData->connectPort = port; + this->privData->ip = ip; } break; From 9ccdbd55e2927a65d94d4bf0611439cd2d6a5eec Mon Sep 17 00:00:00 2001 From: Pontus Fransson Date: Mon, 24 Feb 2014 16:18:47 +0100 Subject: [PATCH 8/9] Not connecting with broadcast anymore. --- Code/Game/GameClient/GameClientState/LanMenuState.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Code/Game/GameClient/GameClientState/LanMenuState.cpp b/Code/Game/GameClient/GameClientState/LanMenuState.cpp index 28b1fb84..bfea6d01 100644 --- a/Code/Game/GameClient/GameClientState/LanMenuState.cpp +++ b/Code/Game/GameClient/GameClientState/LanMenuState.cpp @@ -142,7 +142,7 @@ void LanMenuState::ChangeState( ClientState next ) { case GameClientState::ClientState_Lobby: // attempt to connect to lobby - if( !this->privData->nwClient->Connect(this->privData->connectPort, this->privData->ip.c_str()) ) + if( !this->privData->nwClient->Connect(this->privData->connectPort, (*this->privData->connectIP)[0]) ) return; break; default: break; @@ -198,8 +198,8 @@ const GameClientState::NetEvent& LanMenuState::DataRecieved( const NetEvent &mes std::string name = decoded.name; printf("Broadcast message: %d: %s: %s\n", port, ip.c_str(), name.c_str()); - this->privData->connectPort = port; - this->privData->ip = ip; + //this->privData->connectPort = port; + //this->privData->ip = ip; } break; From 2f19390cd252401452364e140f3d16e60a412a19 Mon Sep 17 00:00:00 2001 From: Robin Engman Date: Wed, 26 Feb 2014 10:05:18 +0100 Subject: [PATCH 9/9] Fixed player jump --- Code/Game/GameLogic/Player.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Code/Game/GameLogic/Player.cpp b/Code/Game/GameLogic/Player.cpp index 5d36dbd9..68bac4e2 100644 --- a/Code/Game/GameLogic/Player.cpp +++ b/Code/Game/GameLogic/Player.cpp @@ -72,7 +72,7 @@ void Player::BeginFrame() Oyster::Math::Float maxSpeed = 30; // Rotate player accordingly - this->rigidBody->AddRotationAroundY(this->rotationUp); + this->rigidBody->AddRotationAroundY(this->rotationUp); this->rigidBody->SetUp(this->rigidBody->GetState().centerPos.GetNormalized()); // Direction data @@ -121,7 +121,7 @@ void Player::BeginFrame() } // Dampen velocity if certain keys are not pressed - if(key_jump <= 0.001 && IsWalking()) + if(key_jump <= 0.001 && IsWalking()) { if(key_forward <= 0.001 && key_backward <= 0.001) { @@ -148,7 +148,7 @@ void Player::BeginFrame() walkDirection.Normalize(); // If on the ground, accelerate normally - if(IsWalking()) + if(IsWalking()) { if(forwardSpeed < maxSpeed) { @@ -160,7 +160,7 @@ void Player::BeginFrame() } } // If in the air, accelerate slower - if(IsJumping()) + if(IsJumping()) { if(forwardSpeed < maxSpeed) { @@ -306,11 +306,11 @@ bool Player::IsWalking() } bool Player::IsJumping() { - return (this->rigidBody->GetLambda() < 1.0f); + return (this->rigidBody->GetLambda() == 1.0f); } bool Player::IsIdle() { - return (this->rigidBody->GetLambda() < 1.0f && this->rigidBody->GetLinearVelocity().GetMagnitude() < 0.0001f); + return (this->rigidBody->GetLambda() == 1.0f && this->rigidBody->GetLinearVelocity().GetMagnitude() < 0.0001f); } void Player::Inactivate()