commit ff52cb5d55febb8d5ca3560e397e6112cfb8eecb Author: Julian Nießner Date: Sun Jan 13 22:00:23 2019 +0100 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..49261d1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +build/ +.vs/ +.vscode/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..2b194a1 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,41 @@ +cmake_minimum_required(VERSION 3.0) +project(DarkRP2D_DEDICATED_SERVER) +set (CMAKE_CXX_STANDARD 11) +include(ExternalProject) + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE RELEASE) + add_definitions(-DNDEBUG) +endif(NOT CMAKE_BUILD_TYPE) + +MESSAGE( STATUS "PROJECT_SOURCE_DIR: " ${PROJECT_SOURCE_DIR} ) +MESSAGE( STATUS "DarkRP2D_DEDICATED_SERVER_SOURCE_DIR: " ${DarkRP2D_DEDICATED_SERVER_SOURCE_DIR} ) + +set(DarkRP2D_EXTERNAL_DIR ${DarkRP2D_DEDICATED_SERVER_SOURCE_DIR}/../external) +set(SDL2_net_DIR ${DarkRP2D_EXTERNAL_DIR}/SDL2_net-2.0.1) +set(SDL2_DIR ${DarkRP2D_EXTERNAL_DIR}/SDL2-2.0.8) + +#Libs + +find_package(SDL2 REQUIRED CONFIG) +include_directories(${SDL2_INCLUDE_DIRS}) + +find_package(SDL2_net REQUIRED CONFIG) +include_directories(${SDL2_NET_INCLUDE_DIRS}) + +MESSAGE( STATUS "SDL2 Lib: " ${SDL2_LIBRARIES} ) +MESSAGE( STATUS "SDL2_NET Lib: " ${SDL2_NET_LIBRARIES} ) + +file(GLOB_RECURSE DarkRP2D_DEDICATED_SERVER_SOURCE_FILES ${DarkRP2D_DEDICATED_SERVER_SOURCE_DIR}/src/*.cpp) + +add_executable(DarkRP2DDServer ${DarkRP2D_DEDICATED_SERVER_SOURCE_FILES}) + +target_link_libraries(DarkRP2DDServer ${SDL2_LIBRARIES} + ${SDL2_NET_LIBRARIES} ) + +add_custom_target(CopyBinaries + COMMAND ${CMAKE_COMMAND} -E copy ${SDL2_DLL} ${CMAKE_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E copy ${SDL2_NET_DLL} ${CMAKE_BINARY_DIR} +) + +add_dependencies(DarkRP2DDServer CopyBinaries) \ No newline at end of file diff --git a/src/Constants.h b/src/Constants.h new file mode 100644 index 0000000..129704e --- /dev/null +++ b/src/Constants.h @@ -0,0 +1,9 @@ +#pragma once + +namespace constants { + + const int CLIENT_PORT = 9999; + const int MAX_CLIENTS = 128; + +} + diff --git a/src/DarkRP2DDedicatedServer.cpp b/src/DarkRP2DDedicatedServer.cpp new file mode 100644 index 0000000..9fa1483 --- /dev/null +++ b/src/DarkRP2DDedicatedServer.cpp @@ -0,0 +1,85 @@ +#include +#include + +#include +#include + +#include + +int main(int argc, char *argv[]) +{ + TCPsocket sd, csd; /* Socket descriptor, Client socket descriptor */ + IPaddress ip, *remoteIP; + int quit, quit2; + char buffer[512]; + + std::cout << "Starting DarkRP2D Server..." << std::endl; + + if (SDLNet_Init() < 0) + { + fprintf(stderr, "SDLNet_Init: %s\n", SDLNet_GetError()); + exit(EXIT_FAILURE); + } + + /* Resolving the host using NULL make network interface to listen */ + if (SDLNet_ResolveHost(&ip, NULL, 9999) < 0) + { + fprintf(stderr, "SDLNet_ResolveHost: %s\n", SDLNet_GetError()); + exit(EXIT_FAILURE); + } + + /* Open a connection with the IP provided (listen on the host's port) */ + if (!(sd = SDLNet_TCP_Open(&ip))) + { + fprintf(stderr, "SDLNet_TCP_Open: %s\n", SDLNet_GetError()); + exit(EXIT_FAILURE); + } + + std::cout << "DarkRP2D Server started." << std::endl; + std::cout << "Waiting for a Connection!" << std::endl; + + /* Wait for a connection, send data and term */ quit = 0; + while (!quit) + { /* This check the sd if there is a pending connection. * If there is one, accept that, and open a new socket for communicating */ + if ((csd = SDLNet_TCP_Accept(sd))) + { /* Now we can communicate with the client using csd socket * sd will remain opened waiting other connections */ + + /* Get the remote address */ + if ((remoteIP = SDLNet_TCP_GetPeerAddress(csd))) /* Print the address, converting in the host format */ + printf("Host connected: %x %d\n", SDLNet_Read32(&remoteIP->host), SDLNet_Read16(&remoteIP->port)); + else + fprintf(stderr, "SDLNet_TCP_GetPeerAddress: %s\n", SDLNet_GetError()); + + quit2 = 0; + while (!quit2) + { + if (SDLNet_TCP_Recv(csd, buffer, 512) > 0) + { + printf("Client say: %s\n", buffer); + + if (strcmp(buffer, "exit") == 0) /* Terminate this connection */ + { + quit2 = 1; + printf("Terminate connection\n"); + } + if (strcmp(buffer, "quit") == 0) /* Quit the program */ + { + quit2 = 1; + quit = 1; + printf("Quit program\n"); + } + } + } + + /* Close the client socket */ SDLNet_TCP_Close(csd); + } + } + std::cout << "Server is closing..." << std::endl; + SDLNet_TCP_Close(sd); + SDLNet_Quit(); + std::cout << "Server closed!" << std::endl; + + return EXIT_SUCCESS; + + return 0; +} \ No newline at end of file diff --git a/src/Protocoll.h b/src/Protocoll.h new file mode 100644 index 0000000..dc4befe --- /dev/null +++ b/src/Protocoll.h @@ -0,0 +1,22 @@ +#pragma once + +#define CONNECTION_REQUEST 0x01 +#define CONNECTION_ACCEPTED 0x02 +#define CONNECTION_DENIED 0x03 + +struct ConnectionRequest { + ConnectionRequest() : type(CONNECTION_REQUEST) {} + char type = CONNECTION_REQUEST; +}; + +struct ConnectionAccepted { + ConnectionAccepted() : type(CONNECTION_ACCEPTED) {} + char type; + int index; +}; + +struct ConnectionDenied { + ConnectionDenied() : type(CONNECTION_DENIED) {} + char type; +}; + diff --git a/src/Server.cpp b/src/Server.cpp new file mode 100644 index 0000000..7b29ebb --- /dev/null +++ b/src/Server.cpp @@ -0,0 +1,164 @@ +#include "Server.h" +#include "Protocoll.h" + +#include +#include +#include + +Server::Server(int port) : m_maxClients(constants::MAX_CLIENTS), m_clientConnected{0} +{ + udpSocket = SDLNet_UDP_Open(port); + + if (udpSocket == nullptr) + { + std::cout << "\tSDLNet_UDP_Open failed : " << SDLNet_GetError() << std::endl; + } + std::cout << "Server was started and is listening on port: " << port << std::endl; + + //Creating ConnectionAccepted packet! + // Allocate udp packet with 512 byte size + connectionAccepted = SDLNet_AllocPacket(512); + + if (connectionAccepted == nullptr) + { + std::cout << "\tSDLNet_AllocPacket failed : " << SDLNet_GetError() << std::endl; + } + ConnectionAccepted conAcc = ConnectionAccepted(); + memcpy(connectionAccepted->data, &conAcc, sizeof(ConnectionAccepted)); + connectionAccepted->len = sizeof(ConnectionAccepted); + + connectionDenied = SDLNet_AllocPacket(512); + + if (connectionDenied == nullptr) + { + std::cout << "\tSDLNet_AllocPacket failed : " << SDLNet_GetError() << std::endl; + } + ConnectionDenied conDen = ConnectionDenied(); + memcpy(connectionDenied->data, &conDen, sizeof(ConnectionDenied)); + connectionDenied->len = sizeof(ConnectionDenied); + + //Creating receiver packet! + receivedPacket = SDLNet_AllocPacket(512); + + if (receivedPacket == nullptr) + { + std::cout << "\tSDLNet_AllocPacket failed : " << SDLNet_GetError() << std::endl; + } +} + +int Server::FindFreeClientIndex() const +{ + for (int i = 0; i < m_maxClients; ++i) + { + if (!m_clientConnected[i]) + return i; + } + return -1; +} + +int Server::FindExistingClientIndex(const IPaddress &ip) const +{ + for (int i = 0; i < m_maxClients; ++i) + { + if (m_clientConnected[i] && m_clients[i].host == ip.host && m_clients[i].port == ip.port) + return i; + } + return -1; +} + +bool Server::IsClientConnected(int clientIndex) const +{ + return m_clientConnected[clientIndex]; +} + +const IPaddress &Server::GetClientAddress(int clientIndex) const +{ + return m_clients[clientIndex]; +} + +void Server::update(unsigned int delta) +{ + //Receive packages + if (SDLNet_UDP_Recv(udpSocket, receivedPacket)) + { + switch (*(receivedPacket->data)) + { + case CONNECTION_REQUEST: + std::cout << "Connection request package received\n"; + int freeIndex; + if ((freeIndex = this->FindFreeClientIndex()) == -1) + { + std::cout << "Connection denied because server full" << std::endl; + //Send Connection denied + this->sendConnectionDenied(receivedPacket->address); + break; + } + std::cout << "Free index found: " << freeIndex << std::endl; + int indexOfExistingClient; + if ((indexOfExistingClient = FindExistingClientIndex(receivedPacket->address)) == -1) + { + std::cout << "Client doesent exist create new" << std::endl; + m_clients[freeIndex] = receivedPacket->address; + m_clientConnected[freeIndex] = true; + //Send connection accepted with index + this->sendConnectionAccepted(receivedPacket->address, freeIndex); + m_numConnectedClients++; + break; + } + else + { + std::cout << "Client exist sending accepted" << std::endl; + //Send connection accepted with index + this->sendConnectionAccepted(receivedPacket->address, indexOfExistingClient); + } + break; + default: + break; + } + } + + //Wait 10 sec + using namespace std::chrono_literals; + std::this_thread::sleep_for(1s); + + //Send data + /*for(auto &value: clients) { + value.send(this->udpSocket,*helloWorldPacket); + } + std::cout << "Data was send!!" << std::endl;*/ +} + +bool Server::sendPacket(UDPpacket &packet) +{ + // Send + // SDLNet_UDP_Send returns number of packets sent. 0 means error + if (SDLNet_UDP_Send(this->udpSocket, -1, &packet) == 0) + { + std::cout << "\tSDLNet_UDP_Send failed : " << SDLNet_GetError() << "\n" + << "==========================================================================================================\n"; + return false; + } + return true; +} + +bool Server::sendConnectionDenied(IPaddress dest) +{ + this->connectionDenied->address.host = dest.host; + this->connectionDenied->address.port = dest.port; + return this->sendPacket(*connectionDenied); +} + +bool Server::sendConnectionAccepted(IPaddress dest, int index) +{ + this->connectionAccepted->address.host = dest.host; + this->connectionAccepted->address.port = dest.port; + ((ConnectionAccepted *) connectionAccepted->data)->index = index; + return this->sendPacket(*connectionAccepted); +} + +Server::~Server() +{ + SDLNet_FreePacket(receivedPacket); + SDLNet_FreePacket(connectionAccepted); + SDLNet_UDP_Close(udpSocket); +} \ No newline at end of file diff --git a/src/Server.h b/src/Server.h new file mode 100644 index 0000000..fc51500 --- /dev/null +++ b/src/Server.h @@ -0,0 +1,36 @@ +#pragma once + +#include +#include "Constants.h" + +class Server { + public: + Server(int port); + ~Server(); + + int FindFreeClientIndex() const; + int FindExistingClientIndex( const IPaddress &ip ) const; + bool IsClientConnected( int clientIndex ) const; + const IPaddress & GetClientAddress( int clientIndex ) const; + + void update(unsigned int delta); + + void gameTick(); + + private: + UDPsocket udpSocket; + + UDPpacket *connectionDenied; + UDPpacket *connectionAccepted; + UDPpacket *receivedPacket; + + int m_maxClients; + int m_numConnectedClients; + bool m_clientConnected[constants::MAX_CLIENTS]; + IPaddress m_clients[constants::MAX_CLIENTS]; + + bool sendPacket(UDPpacket &packet); + + bool sendConnectionDenied(IPaddress dest); + bool sendConnectionAccepted(IPaddress dest, int index); +}; \ No newline at end of file