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();