#include #include #include #include #include #include #include #include #include #include "server/network/Server.h" #include "server/network/Socket.h" Server::Server(const Socket& connectionListener, u16 maxClients, GameServer& gameServer) : connectionListener(connectionListener), gameServer(gameServer), running(true), listenerThread(&Server::listenForClients, this) { (void) maxClients; } Server::~Server() { running = false; listenerThread.join(); } void Server::listenForClients() const { while(running) { WaitResult result = connectionListener.waitForConnection(100); if(result == WaitResult::ERROR) { break; } else if(result == WaitResult::TIMEOUT) { continue; } int clientSocket = connectionListener.acceptConnection(); if(clientSocket < 0) { continue; } /*if(addClient(clientSocket)) { if(close(clientSocket) == -1) { printError("cannot close client socket"); } }*/ } } /*static void printError(const char* message) { std::cout << message << ": " << strerror(errno) << "\n"; } struct ConnectedClient { ~ConnectedClient() { if(socket != -1) { if(shutdown(socket, SHUT_RDWR)) { printError("cannot shutdown client socket"); } if(close(socket) == -1) { printError("cannot close client socket"); } } if(th.joinable()) { th.join(); } else { std::cout << "cannot join client connection thread\n"; } } std::thread th = std::thread([]() { }); int socket = -1; }; struct InternServer final { InternServer() : clients(nullptr) { } ~InternServer() { if(clients != nullptr) { delete[] clients; } } ConnectedClient* clients; }; static InternServer server; static void defaultFullServerClientConnect(int) { std::cout << "default onFullServerClientConnectFunction\n"; } static void defaultClientConnect(int) { std::cout << "default onClientConnectFunction\n"; } static void defaultClientPackage(int, Stream&) { std::cout << "default onClientPackageFunction\n"; } static void defaultClientDisconnect(int) { std::cout << "default onClientDisconnectFunction\n"; } static std::mutex clientMutex; static Server::FullServerClientConnectFunction onFullServerClientConnect = defaultFullServerClientConnect; static Server::ClientConnectFunction onClientConnect = defaultClientConnect; static Server::ClientPackageFunction onClientPackage = defaultClientPackage; static Server::ClientDisconnectFunction onClientDisconnect = defaultClientDisconnect; void Server::setFullServerClientConnectFunction(Server::FullServerClientConnectFunction f) { onFullServerClientConnect = f; } void Server::setClientConnectFunction(Server::ClientConnectFunction f) { onClientConnect = f; } void Server::setClientPackageFunction(Server::ClientPackageFunction f) { onClientPackage = f; } void Server::setClientDisconnectFunction(Server::ClientDisconnectFunction f) { onClientDisconnect = f; } static void listenOnClient(ConnectedClient& cc) { // poll data struct pollfd fds; fds.fd = cc.socket; // file descriptor for polling fds.events = POLLIN; // wait until data is ready to read fds.revents = 0; // return events - none //onClientConnect(cc.socket); Stream st; while(server.shouldRun) { // nfds_t - 1 - amount of passed in structs // timeout - 100 - milliseconds to wait until an event occurs // returns 0 on timeout, -1 on error, and >0 on success int pollData = poll(&fds, 1, 100); if(pollData > 0) { st.readSocket(cc.socket); if(st.hasData()) { onClientPackage(cc.socket, st); } else { // client closed connection break; } } else if(pollData == -1) { printError("cannot poll from client"); break; } } onClientDisconnect(cc.socket); // reset slot for another client if(server.shouldRun) { std::lock_guard lg(clientMutex); if(close(cc.socket) == -1) { printError("cannot close socket of client"); } cc.socket = -1; clientAmount--; } } static bool addClient(int clientSocket) { std::lock_guard lg(clientMutex); if(clientAmount >= maxClients) { onFullServerClientConnect(clientSocket); return true; } else { // search for free slot uint16_t index = 0; while(index < maxClients) { if(server.clients[index].socket == -1) { break; } index++; } if(index >= maxClients) { std::cout << "cannot find free slot - even if there should be one\n"; return true; } //ensure old thread has ended if(!server.clients[index].th.joinable()) { std::cout << "cannot join thread of non used client connection\n"; return true; } server.clients[index].th.join(); server.clients[index].socket = clientSocket; server.clients[index].th = std::thread(listenOnClient, std::ref(server.clients[index])); clientAmount++; return false; } }*/