Advertisement
Nickel59

Untitled

Dec 15th, 2024
24
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.63 KB | None | 0 0
  1. #define WIN32_LEAN_AND_MEAN
  2.  
  3. #include <windows.h>
  4.  
  5. #include <WinBase.h>
  6. #include <errhandlingapi.h>
  7. #include <handleapi.h>
  8. #include <inttypes.h>
  9. #include <minwindef.h>
  10. #include <process.h>
  11. #include <stdbool.h>
  12. #include <stdint.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <synchapi.h>
  17. #include <vcruntime.h>
  18. #include <winnt.h>
  19. #include <winsock2.h>
  20. #include <ws2tcpip.h>
  21.  
  22. #pragma comment(lib, "Ws2_32.lib")
  23.  
  24. #define lengthof(x) (sizeof(x) / sizeof((x)[0]))
  25.  
  26. #define PORT "27015"
  27.  
  28. enum CONSTANT { MAX_THREAD_NUMBER = 5 };
  29.  
  30. char *input(uint16_t maxLength) {
  31.   if (!maxLength) {
  32.     return NULL;
  33.   }
  34.   int32_t inputStringSize = maxLength + 2;
  35.   char *inputString = malloc(inputStringSize);
  36.   if (!inputString) {
  37.     return NULL;
  38.   }
  39.   if (!fgets(inputString, inputStringSize, stdin)) {
  40.     free(inputString);
  41.     while (getchar() != '\n') {
  42.     }
  43.     return NULL;
  44.   }
  45.   if (inputString[0] == '\n') {
  46.     free(inputString);
  47.     return NULL;
  48.   }
  49.   size_t inputStringLength = strlen(inputString);
  50.   char *lastStringCharacterPtr = &(inputString[inputStringLength - 1]);
  51.   if (*lastStringCharacterPtr != '\n') {
  52.     free(inputString);
  53.     while (getchar() != '\n') {
  54.     }
  55.     return NULL;
  56.   }
  57.   *lastStringCharacterPtr = '\0';
  58.   char *string = realloc(inputString, inputStringLength);
  59.   if (!string) {
  60.     free(inputString);
  61.     return NULL;
  62.   }
  63.   return string;
  64. }
  65.  
  66. struct addrinfo *setupServer() {
  67.   WSADATA wsaData = {0};
  68.   int error = WSAStartup(MAKEWORD(2, 2), &wsaData);
  69.   if (error != 0) {
  70.     printf("WSAStartup() failed with error: %d\n", error);
  71.     return NULL;
  72.   }
  73.   struct addrinfo *host = NULL;
  74.   error = getaddrinfo(
  75.       NULL, PORT,
  76.       &((struct addrinfo){
  77.           .ai_family = AF_INET, .ai_socktype = SOCK_STREAM, .ai_protocol = IPPROTO_TCP, .ai_flags = AI_PASSIVE}),
  78.       &host);
  79.   if (error != 0) {
  80.     printf("getaddrinfo() failed with error: %d\n", error);
  81.     WSACleanup();
  82.     return NULL;
  83.   }
  84.   return host;
  85. }
  86.  
  87. SOCKET getListeningSocket(int aiFamily, int type, int protocol, const struct sockaddr *name, int namelen) {
  88.   SOCKET listeningSocket = socket(aiFamily, type, protocol);
  89.   if (listeningSocket == INVALID_SOCKET) {
  90.     printf("socket() failed with error: %d\n", WSAGetLastError());
  91.     return INVALID_SOCKET;
  92.   }
  93.   if (bind(listeningSocket, name, namelen) == SOCKET_ERROR) {
  94.     printf("bind() failed with error: %d\n", WSAGetLastError());
  95.     closesocket(listeningSocket);
  96.     return INVALID_SOCKET;
  97.   }
  98.   if (listen(listeningSocket, SOMAXCONN) == SOCKET_ERROR) {
  99.     printf("listen() failed with error: %d\n", WSAGetLastError());
  100.     closesocket(listeningSocket);
  101.     return INVALID_SOCKET;
  102.   }
  103.   return listeningSocket;
  104. }
  105.  
  106. void inputThread(void *arguments) {
  107.   (void)arguments;
  108.   while (true) {
  109.     char *string = input(4);
  110.     if (!string) {
  111.       puts("Invalid input");
  112.       continue;
  113.     }
  114.     if (strcmp("exit", string) != 0) {
  115.       free(string);
  116.       continue;
  117.     }
  118.     free(string);
  119.     abort();
  120.     return;
  121.   }
  122. }
  123.  
  124. typedef struct {
  125.   SOCKET socket;
  126.   HANDLE semaphore;
  127.   uint64_t connectionNumber;
  128. } ArgumentStore;
  129.  
  130. void clientConnectionThread(void *arguments) {
  131.   ArgumentStore *argumentStorePtr = (ArgumentStore *)arguments;
  132.  
  133.   printf("Connected: %" PRIu64 "\n", argumentStorePtr->connectionNumber);
  134.  
  135.   int receivedByteNumber = 0;
  136.   char buffer[512] = {0};
  137.   do {
  138.     receivedByteNumber = recv(argumentStorePtr->socket, buffer, lengthof(buffer), 0);
  139.   } while (receivedByteNumber > 0);
  140.  
  141.   if (!receivedByteNumber) {
  142.     printf("Connection closing...\n");
  143.     if (shutdown(argumentStorePtr->socket, SD_SEND) == SOCKET_ERROR) {
  144.       printf("shutdown() failed with error: %d\n", WSAGetLastError());
  145.     }
  146.   } else {
  147.     printf("recv() failed with error: %d\n", WSAGetLastError());
  148.   }
  149.   closesocket(argumentStorePtr->socket);
  150.  
  151.   printf("Disconnected: %" PRIu64 "\n", argumentStorePtr->connectionNumber);
  152.  
  153.   if (!ReleaseSemaphore(argumentStorePtr->semaphore, 1, NULL)) {
  154.     printf("ReleaseSemaphore() failed with error: %lu\n", GetLastError());
  155.   }
  156.   free(argumentStorePtr);
  157. }
  158.  
  159. int main() {
  160.   _beginthread(inputThread, 0, NULL);
  161.  
  162.   struct addrinfo *host = setupServer();
  163.   if (host == NULL) {
  164.     return 1;
  165.   }
  166.  
  167.   HANDLE semaphore = CreateSemaphore(NULL, MAX_THREAD_NUMBER, MAX_THREAD_NUMBER, NULL);
  168.  
  169.   SOCKET listeningSocket = INVALID_SOCKET;
  170.   uint64_t connectionNumber = 0;
  171.   while (true) {
  172.     if (WaitForSingleObject(semaphore, 0) != WAIT_OBJECT_0) {
  173.       if (listeningSocket != INVALID_SOCKET) {
  174.         closesocket(listeningSocket);
  175.         listeningSocket = INVALID_SOCKET;
  176.       }
  177.       continue;
  178.     }
  179.     if (listeningSocket == INVALID_SOCKET) {
  180.       listeningSocket = getListeningSocket(host->ai_family, host->ai_socktype, host->ai_protocol, host->ai_addr,
  181.                                            (int)(host->ai_addrlen));
  182.     }
  183.     if (listeningSocket == INVALID_SOCKET) {
  184.       break;
  185.     }
  186.     SOCKET clientSocket = accept(listeningSocket, NULL, NULL);
  187.     if (clientSocket == INVALID_SOCKET) {
  188.       printf("accept() failed with error: %d\n", WSAGetLastError());
  189.       break;
  190.     }
  191.     ArgumentStore *argumentStorePtr = malloc(sizeof(*argumentStorePtr));
  192.     if (!argumentStorePtr) {
  193.       puts("malloc() failed");
  194.       break;
  195.     }
  196.     *argumentStorePtr = (ArgumentStore){clientSocket, semaphore, connectionNumber};
  197.     _beginthread(clientConnectionThread, 0, argumentStorePtr);
  198.     ++connectionNumber;
  199.   }
  200.  
  201.   freeaddrinfo(host);
  202.   if (listeningSocket != INVALID_SOCKET) {
  203.     closesocket(listeningSocket);
  204.   }
  205.   WSACleanup();
  206.   CloseHandle(semaphore);
  207.  
  208.   return 1;
  209. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement