123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267 |
- #include <iostream>
- #include <cstring>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <unistd.h>
- #include <poll.h>
- #include "server/network/Server.h"
- Server::ConnectedClient::ConnectedClient() : th([]() {}), socket(-1)
- {
- }
- Server::Server(uint16_t port, uint16_t maxClients, const IServerListener& listener) :
- shouldRun(false), port(port), maxClients(maxClients), serverListener(listener),
- listenerSocket(-1), clientAmount(0), clients(nullptr)
- {
-
-
-
-
- listenerSocket = socket(AF_INET, SOCK_STREAM, 0);
- if(listenerSocket == -1)
- {
- printError("cannot create listener socket");
- return;
- }
-
-
-
- struct linger sl;
- sl.l_onoff = 1;
- sl.l_linger = 0;
-
-
-
- if(setsockopt(listenerSocket, SOL_SOCKET, SO_LINGER, &sl, sizeof(struct linger)) == -1)
- {
- printError("cannot set non lingering");
- return;
- }
-
-
- struct sockaddr_in connectSocketData;
-
- memset(&connectSocketData, 0, sizeof(struct sockaddr_in));
-
- connectSocketData.sin_family = AF_INET;
-
- connectSocketData.sin_port = htons(port);
-
- connectSocketData.sin_addr.s_addr = htons(INADDR_ANY);
-
- if(bind(listenerSocket, (struct sockaddr*) &connectSocketData, sizeof(struct sockaddr_in)) == -1)
- {
- printError("cannot bind listener socket");
- return;
- }
-
-
-
- if(listen(listenerSocket, 5) == -1)
- {
- printError("cannot start listening on socket");
- return;
- }
-
- shouldRun = true;
- listenerThread = std::thread(&Server::listenForClients, this);
-
- clients = new ConnectedClient[maxClients];
- }
- Server::~Server()
- {
- shouldRun = false;
- listenerThread.join();
-
- if(listenerSocket != -1)
- {
- if(close(listenerSocket) == -1)
- {
- printError("cannot close listener socket");
- }
- }
-
- if(clients != nullptr)
- {
- for(uint16_t i = 0; i < maxClients; i++)
- {
- if(clients[i].socket != -1)
- {
- if(shutdown(clients[i].socket, SHUT_RDWR))
- {
- printError("cannot shutdown client socket");
- }
- if(close(clients[i].socket) == -1)
- {
- printError("cannot close client socket");
- }
- }
- if(clients[i].th.joinable())
- {
- clients[i].th.join();
- }
- else
- {
- std::cout << "cannot join client connection thread " << std::endl;
- }
- }
- delete[] clients;
- }
- }
- bool Server::isRunning() const
- {
- return shouldRun;
- }
- void Server::printError(const char* message) const
- {
- std::cout << message << ": " << strerror(errno) << std::endl;
- }
- void Server::listenForClients()
- {
- while(shouldRun)
- {
-
-
- struct pollfd fds;
- fds.fd = listenerSocket;
- fds.events = POLLIN;
- fds.revents = 0;
-
-
-
- int pollData = poll(&fds, 1, 100);
- if(pollData > 0)
- {
- struct sockaddr_in clientSocketData;
-
-
- socklen_t addrlen = sizeof(struct sockaddr_in);
- int clientSocket = accept(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::addClient(int clientSocket)
- {
- std::lock_guard<std::mutex> lg(clientMutex);
- if(clientAmount >= maxClients)
- {
- serverListener.onFullServerClientConnect(clientSocket);
- return true;
- }
- else
- {
-
- uint16_t index = 0;
- while(index < maxClients)
- {
- if(clients[index].socket == -1)
- {
- break;
- }
- index++;
- }
-
- if(index >= maxClients)
- {
- std::cout << "cannot find free slot - even if there should be one" << std::endl;
- return true;
- }
-
- if(!clients[index].th.joinable())
- {
- std::cout << "cannot join thread of non used client connection" << std::endl;
- return true;
- }
- clients[index].th.join();
- clients[index].socket = clientSocket;
- clients[index].th = std::thread(&Server::listenOnClient, this, std::ref(clients[index]));
- clientAmount++;
- return false;
- }
- }
- void Server::listenOnClient(ConnectedClient& cc)
- {
-
- struct pollfd fds;
- fds.fd = cc.socket;
- fds.events = POLLIN;
- fds.revents = 0;
-
- serverListener.onClientConnect(cc.socket);
-
- Stream st;
- while(shouldRun)
- {
-
-
-
- int pollData = poll(&fds, 1, 100);
- if(pollData > 0)
- {
- st.readSocket(cc.socket);
- if(st.hasData())
- {
- serverListener.onClientPackage(cc.socket, st);
- }
- else
- {
-
- break;
- }
- }
- else if(pollData == -1)
- {
- printError("cannot poll from client");
- break;
- }
- }
-
- serverListener.onClientDisconnect(cc.socket);
-
-
- if(shouldRun)
- {
- std::lock_guard<std::mutex> lg(clientMutex);
- if(close(cc.socket) == -1)
- {
- printError("cannot close socket of client");
- }
- cc.socket = -1;
- clientAmount--;
- }
- }
|