Server.cpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. #include <iostream>
  2. #include <cstring>
  3. #include <vector>
  4. #include <atomic>
  5. #include <thread>
  6. #include <mutex>
  7. #include <sys/socket.h>
  8. #include <netinet/in.h>
  9. #include <unistd.h>
  10. #include <poll.h>
  11. #include "server/network/Server.h"
  12. static void printError(const char* message) {
  13. std::cout << message << ": " << strerror(errno) << "\n";
  14. }
  15. struct ConnectedClient {
  16. ~ConnectedClient() {
  17. if(socket != -1) {
  18. if(shutdown(socket, SHUT_RDWR)) {
  19. printError("cannot shutdown client socket");
  20. }
  21. if(close(socket) == -1) {
  22. printError("cannot close client socket");
  23. }
  24. }
  25. if(th.joinable()) {
  26. th.join();
  27. } else {
  28. std::cout << "cannot join client connection thread\n";
  29. }
  30. }
  31. std::thread th = std::thread([]() {
  32. });
  33. int socket = -1;
  34. };
  35. struct InternServer final {
  36. InternServer() : listenerSocket(-1), listenerThread([]() {
  37. })
  38. , shouldRun(true), clients(nullptr) {
  39. }
  40. ~InternServer() {
  41. shouldRun = false;
  42. listenerThread.join();
  43. if(listenerSocket != -1) {
  44. if(close(listenerSocket) == -1) {
  45. printError("cannot close listener socket");
  46. }
  47. }
  48. if(clients != nullptr) {
  49. delete[] clients;
  50. }
  51. }
  52. int listenerSocket;
  53. std::thread listenerThread;
  54. std::atomic_bool shouldRun;
  55. ConnectedClient* clients;
  56. };
  57. static InternServer server;
  58. static void defaultFullServerClientConnect(int) {
  59. std::cout << "default onFullServerClientConnectFunction\n";
  60. }
  61. static void defaultClientConnect(int) {
  62. std::cout << "default onClientConnectFunction\n";
  63. }
  64. static void defaultClientPackage(int, Stream&) {
  65. std::cout << "default onClientPackageFunction\n";
  66. }
  67. static void defaultClientDisconnect(int) {
  68. std::cout << "default onClientDisconnectFunction\n";
  69. }
  70. static std::mutex clientMutex;
  71. static u16 clientAmount = 0;
  72. static u16 maxClients = 0;
  73. static Server::FullServerClientConnectFunction onFullServerClientConnect = defaultFullServerClientConnect;
  74. static Server::ClientConnectFunction onClientConnect = defaultClientConnect;
  75. static Server::ClientPackageFunction onClientPackage = defaultClientPackage;
  76. static Server::ClientDisconnectFunction onClientDisconnect = defaultClientDisconnect;
  77. void Server::setFullServerClientConnectFunction(Server::FullServerClientConnectFunction f) {
  78. onFullServerClientConnect = f;
  79. }
  80. void Server::setClientConnectFunction(Server::ClientConnectFunction f) {
  81. onClientConnect = f;
  82. }
  83. void Server::setClientPackageFunction(Server::ClientPackageFunction f) {
  84. onClientPackage = f;
  85. }
  86. void Server::setClientDisconnectFunction(Server::ClientDisconnectFunction f) {
  87. onClientDisconnect = f;
  88. }
  89. static void listenOnClient(ConnectedClient& cc) {
  90. // poll data
  91. struct pollfd fds;
  92. fds.fd = cc.socket; // file descriptor for polling
  93. fds.events = POLLIN; // wait until data is ready to read
  94. fds.revents = 0; // return events - none
  95. onClientConnect(cc.socket);
  96. Stream st;
  97. while(server.shouldRun) {
  98. // nfds_t - 1 - amount of passed in structs
  99. // timeout - 100 - milliseconds to wait until an event occurs
  100. // returns 0 on timeout, -1 on error, and >0 on success
  101. int pollData = poll(&fds, 1, 100);
  102. if(pollData > 0) {
  103. st.readSocket(cc.socket);
  104. if(st.hasData()) {
  105. onClientPackage(cc.socket, st);
  106. } else {
  107. // client closed connection
  108. break;
  109. }
  110. } else if(pollData == -1) {
  111. printError("cannot poll from client");
  112. break;
  113. }
  114. }
  115. onClientDisconnect(cc.socket);
  116. // reset slot for another client
  117. if(server.shouldRun) {
  118. std::lock_guard<std::mutex> lg(clientMutex);
  119. if(close(cc.socket) == -1) {
  120. printError("cannot close socket of client");
  121. }
  122. cc.socket = -1;
  123. clientAmount--;
  124. }
  125. }
  126. static bool addClient(int clientSocket) {
  127. std::lock_guard<std::mutex> lg(clientMutex);
  128. if(clientAmount >= maxClients) {
  129. onFullServerClientConnect(clientSocket);
  130. return true;
  131. } else {
  132. // search for free slot
  133. uint16_t index = 0;
  134. while(index < maxClients) {
  135. if(server.clients[index].socket == -1) {
  136. break;
  137. }
  138. index++;
  139. }
  140. if(index >= maxClients) {
  141. std::cout << "cannot find free slot - even if there should be one\n";
  142. return true;
  143. }
  144. //ensure old thread has ended
  145. if(!server.clients[index].th.joinable()) {
  146. std::cout << "cannot join thread of non used client connection\n";
  147. return true;
  148. }
  149. server.clients[index].th.join();
  150. server.clients[index].socket = clientSocket;
  151. server.clients[index].th = std::thread(listenOnClient, std::ref(server.clients[index]));
  152. clientAmount++;
  153. return false;
  154. }
  155. }
  156. static void listenForClients() {
  157. while(server.shouldRun) {
  158. // wait until a connection arrives with timeout, this prevents being
  159. // stuck in accept
  160. struct pollfd fds;
  161. fds.fd = server.listenerSocket; // file descriptor for polling
  162. fds.events = POLLIN; // wait until data is ready to read
  163. fds.revents = 0; // return events - none
  164. // nfds_t - 1 - amount of passed in structs
  165. // timeout - 100 - milliseconds to wait until an event occurs
  166. // returns 0 on timeout, -1 on error, and >0 on success
  167. int pollData = poll(&fds, 1, 100);
  168. if(pollData > 0) {
  169. struct sockaddr_in clientSocketData;
  170. // accepts an incoming client connection and stores the data in the
  171. // given struct, returns a nonnegative file descriptor on success
  172. socklen_t addrlen = sizeof (struct sockaddr_in);
  173. int clientSocket = accept(server.listenerSocket, (struct sockaddr*) &clientSocketData, &addrlen);
  174. if(clientSocket >= 0) {
  175. if(addClient(clientSocket)) {
  176. if(close(clientSocket) == -1) {
  177. printError("cannot close client socket");
  178. }
  179. }
  180. } else {
  181. printError("accept error");
  182. break;
  183. }
  184. } else if(pollData == -1) {
  185. printError("poll error");
  186. break;
  187. }
  188. }
  189. }
  190. bool Server::start(u16 port, u16 inMaxClients) {
  191. // create socket for incoming connections
  192. // domain - AF_INET - IPv4 Internet protocols
  193. // type - SOCK_STREAM - two-way, connection-based byte streams
  194. // protocol - 0 - use standard protocol for the given socket type
  195. server.listenerSocket = socket(AF_INET, SOCK_STREAM, 0);
  196. if(server.listenerSocket == -1) {
  197. printError("cannot create listener socket");
  198. return false;
  199. }
  200. // prevents clients from blocking the port if the server exits
  201. // this is useful if server and client run on the same system
  202. struct linger sl;
  203. sl.l_onoff = 1; // nonzero to linger on close
  204. sl.l_linger = 0; // time to linger
  205. // sockfd - listenerSocket - modified socket
  206. // level - SOL_SOCKET - manipulate options at the sockets API level
  207. // optname - SO_LINGER - identifier of the option
  208. if(setsockopt(server.listenerSocket, SOL_SOCKET, SO_LINGER, &sl, sizeof (struct linger)) == -1) {
  209. printError("cannot set non lingering");
  210. return false;
  211. }
  212. // specify binding data
  213. struct sockaddr_in connectSocketData;
  214. // clear padding
  215. memset(&connectSocketData, 0, sizeof (struct sockaddr_in));
  216. // IPv4 Internet protocols
  217. connectSocketData.sin_family = AF_INET;
  218. // port in network byte order
  219. connectSocketData.sin_port = htons(port);
  220. // address in network byte order, accept any incoming messages
  221. connectSocketData.sin_addr.s_addr = htons(INADDR_ANY);
  222. // bind the socket
  223. if(bind(server.listenerSocket, (struct sockaddr*) &connectSocketData, sizeof (struct sockaddr_in)) == -1) {
  224. printError("cannot bind listener socket");
  225. return false;
  226. }
  227. // mark the socket as handler for connection requests
  228. // backlog - 5 - max queue length of pending connections
  229. if(listen(server.listenerSocket, 5) == -1) {
  230. printError("cannot start listening on socket");
  231. return false;
  232. }
  233. server.shouldRun = true;
  234. maxClients = inMaxClients;
  235. server.clients = new ConnectedClient[inMaxClients];
  236. // join empty spawn thread
  237. server.listenerThread.join();
  238. server.listenerThread = std::thread(listenForClients);
  239. return true;
  240. }