|  | @@ -1,7 +1,6 @@
 | 
	
		
			
				|  |  |  #include <iostream>
 | 
	
		
			
				|  |  |  #include <cstring>
 | 
	
		
			
				|  |  |  #include <vector>
 | 
	
		
			
				|  |  | -#include <atomic>
 | 
	
		
			
				|  |  |  #include <thread>
 | 
	
		
			
				|  |  |  #include <mutex>
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -11,8 +10,40 @@
 | 
	
		
			
				|  |  |  #include <poll.h>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #include "server/network/Server.h"
 | 
	
		
			
				|  |  | +#include "server/network/Socket.h"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static void printError(const char* message) {
 | 
	
		
			
				|  |  | +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";
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -40,28 +71,16 @@ struct ConnectedClient {
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  struct InternServer final {
 | 
	
		
			
				|  |  | -    InternServer() : listenerSocket(-1), listenerThread([]() {
 | 
	
		
			
				|  |  | -    })
 | 
	
		
			
				|  |  | -, shouldRun(true), clients(nullptr) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    InternServer() : clients(nullptr) {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      ~InternServer() {
 | 
	
		
			
				|  |  | -        shouldRun = false;
 | 
	
		
			
				|  |  | -        listenerThread.join();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        if(listenerSocket != -1) {
 | 
	
		
			
				|  |  | -            if(close(listenerSocket) == -1) {
 | 
	
		
			
				|  |  | -                printError("cannot close listener socket");
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  |          if(clients != nullptr) {
 | 
	
		
			
				|  |  |              delete[] clients;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    int listenerSocket;
 | 
	
		
			
				|  |  | -    std::thread listenerThread;
 | 
	
		
			
				|  |  | -    std::atomic_bool shouldRun;
 | 
	
		
			
				|  |  |      ConnectedClient* clients;
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -84,8 +103,6 @@ static void defaultClientDisconnect(int) {
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static std::mutex clientMutex;
 | 
	
		
			
				|  |  | -static u16 clientAmount = 0;
 | 
	
		
			
				|  |  | -static u16 maxClients = 0;
 | 
	
		
			
				|  |  |  static Server::FullServerClientConnectFunction onFullServerClientConnect = defaultFullServerClientConnect;
 | 
	
		
			
				|  |  |  static Server::ClientConnectFunction onClientConnect = defaultClientConnect;
 | 
	
		
			
				|  |  |  static Server::ClientPackageFunction onClientPackage = defaultClientPackage;
 | 
	
	
		
			
				|  | @@ -114,7 +131,7 @@ static void listenOnClient(ConnectedClient& cc) {
 | 
	
		
			
				|  |  |      fds.events = POLLIN; // wait until data is ready to read
 | 
	
		
			
				|  |  |      fds.revents = 0; // return events - none
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    onClientConnect(cc.socket);
 | 
	
		
			
				|  |  | +    //onClientConnect(cc.socket);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      Stream st;
 | 
	
		
			
				|  |  |      while(server.shouldRun) {
 | 
	
	
		
			
				|  | @@ -183,96 +200,4 @@ static bool addClient(int clientSocket) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          return false;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static void listenForClients() {
 | 
	
		
			
				|  |  | -    while(server.shouldRun) {
 | 
	
		
			
				|  |  | -        // wait until a connection arrives with timeout, this prevents being 
 | 
	
		
			
				|  |  | -        // stuck in accept
 | 
	
		
			
				|  |  | -        struct pollfd fds;
 | 
	
		
			
				|  |  | -        fds.fd = server.listenerSocket; // file descriptor for polling
 | 
	
		
			
				|  |  | -        fds.events = POLLIN; // wait until data is ready to read
 | 
	
		
			
				|  |  | -        fds.revents = 0; // return events - none
 | 
	
		
			
				|  |  | -        // 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) {
 | 
	
		
			
				|  |  | -            struct sockaddr_in clientSocketData;
 | 
	
		
			
				|  |  | -            // accepts an incoming client connection and stores the data in the
 | 
	
		
			
				|  |  | -            // given struct, returns a nonnegative file descriptor on success
 | 
	
		
			
				|  |  | -            socklen_t addrlen = sizeof (struct sockaddr_in);
 | 
	
		
			
				|  |  | -            int clientSocket = accept(server.listenerSocket, (struct sockaddr*) &clientSocketData, &addrlen);
 | 
	
		
			
				|  |  | -            if(clientSocket >= 0) {
 | 
	
		
			
				|  |  | -                if(addClient(clientSocket)) {
 | 
	
		
			
				|  |  | -                    if(close(clientSocket) == -1) {
 | 
	
		
			
				|  |  | -                        printError("cannot close client socket");
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -            } else {
 | 
	
		
			
				|  |  | -                printError("accept error");
 | 
	
		
			
				|  |  | -                break;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        } else if(pollData == -1) {
 | 
	
		
			
				|  |  | -            printError("poll error");
 | 
	
		
			
				|  |  | -            break;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -bool Server::start(u16 port, u16 inMaxClients) {
 | 
	
		
			
				|  |  | -    // create socket for incoming connections
 | 
	
		
			
				|  |  | -    // domain - AF_INET - IPv4 Internet protocols
 | 
	
		
			
				|  |  | -    // type - SOCK_STREAM - two-way, connection-based byte streams
 | 
	
		
			
				|  |  | -    // protocol - 0 - use standard protocol for the given socket type
 | 
	
		
			
				|  |  | -    server.listenerSocket = socket(AF_INET, SOCK_STREAM, 0);
 | 
	
		
			
				|  |  | -    if(server.listenerSocket == -1) {
 | 
	
		
			
				|  |  | -        printError("cannot create listener socket");
 | 
	
		
			
				|  |  | -        return false;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // prevents clients from blocking the port if the server exits
 | 
	
		
			
				|  |  | -    // this is useful if server and client run on the same system
 | 
	
		
			
				|  |  | -    struct linger sl;
 | 
	
		
			
				|  |  | -    sl.l_onoff = 1; // nonzero to linger on close
 | 
	
		
			
				|  |  | -    sl.l_linger = 0; // time to linger
 | 
	
		
			
				|  |  | -    // sockfd - listenerSocket - modified socket
 | 
	
		
			
				|  |  | -    // level - SOL_SOCKET - manipulate options at the sockets API level
 | 
	
		
			
				|  |  | -    // optname - SO_LINGER - identifier of the option
 | 
	
		
			
				|  |  | -    if(setsockopt(server.listenerSocket, SOL_SOCKET, SO_LINGER, &sl, sizeof (struct linger)) == -1) {
 | 
	
		
			
				|  |  | -        printError("cannot set non lingering");
 | 
	
		
			
				|  |  | -        return false;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // specify binding data
 | 
	
		
			
				|  |  | -    struct sockaddr_in connectSocketData;
 | 
	
		
			
				|  |  | -    // clear padding
 | 
	
		
			
				|  |  | -    memset(&connectSocketData, 0, sizeof (struct sockaddr_in));
 | 
	
		
			
				|  |  | -    // IPv4 Internet protocols
 | 
	
		
			
				|  |  | -    connectSocketData.sin_family = AF_INET;
 | 
	
		
			
				|  |  | -    // port in network byte order
 | 
	
		
			
				|  |  | -    connectSocketData.sin_port = htons(port);
 | 
	
		
			
				|  |  | -    // address in network byte order, accept any incoming messages
 | 
	
		
			
				|  |  | -    connectSocketData.sin_addr.s_addr = htons(INADDR_ANY);
 | 
	
		
			
				|  |  | -    // bind the socket
 | 
	
		
			
				|  |  | -    if(bind(server.listenerSocket, (struct sockaddr*) &connectSocketData, sizeof (struct sockaddr_in)) == -1) {
 | 
	
		
			
				|  |  | -        printError("cannot bind listener socket");
 | 
	
		
			
				|  |  | -        return false;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // mark the socket as handler for connection requests
 | 
	
		
			
				|  |  | -    // backlog - 5 - max queue length of pending connections
 | 
	
		
			
				|  |  | -    if(listen(server.listenerSocket, 5) == -1) {
 | 
	
		
			
				|  |  | -        printError("cannot start listening on socket");
 | 
	
		
			
				|  |  | -        return false;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    server.shouldRun = true;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    maxClients = inMaxClients;
 | 
	
		
			
				|  |  | -    server.clients = new ConnectedClient[inMaxClients];
 | 
	
		
			
				|  |  | -    // join empty spawn thread
 | 
	
		
			
				|  |  | -    server.listenerThread.join();
 | 
	
		
			
				|  |  | -    server.listenerThread = std::thread(listenForClients);
 | 
	
		
			
				|  |  | -    return true;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | +}*/
 |