Advertisement
Nickel59

Untitled

Dec 6th, 2024
36
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.59 KB | None | 0 0
  1. #define WIN32_LEAN_AND_MEAN
  2.  
  3. #include <inttypes.h>
  4. #include <stdbool.h>
  5. #include <stdint.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <vcruntime.h>
  10. #include <windows.h>
  11. #include <winsock2.h>
  12. #include <ws2tcpip.h>
  13.  
  14. // Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
  15. #pragma comment(lib, "Ws2_32.lib")
  16. #pragma comment(lib, "Mswsock.lib")
  17. #pragma comment(lib, "AdvApi32.lib")
  18.  
  19. #define DEFAULT_BUFLEN 512
  20. #define DEFAULT_PORT "27015"
  21.  
  22. #define lengthof(x) (sizeof(x) / sizeof((x)[0]))
  23.  
  24. void *safemalloc(size_t size) {
  25.   void *block = malloc(size);
  26.   if (!block) {
  27.     (void)fputs("Memory allocation has failed.", stderr);
  28.     abort();
  29.   }
  30.   return block;
  31. }
  32.  
  33. void *saferealloc(void *block, size_t size) {
  34.   char *newBlock = realloc(block, size);
  35.   if (!newBlock) {
  36.     (void)fputs("Memory reallocation has failed.", stderr);
  37.     abort();
  38.   }
  39.   return newBlock;
  40. }
  41.  
  42. char *input(uint16_t maxLength) {
  43.   if (!maxLength) {
  44.     return NULL;
  45.   }
  46.   int32_t inputStringSize = maxLength + 2;
  47.   char *inputString = safemalloc(inputStringSize);
  48.   if (!fgets(inputString, inputStringSize, stdin)) {
  49.     free(inputString);
  50.     while (getchar() != '\n') {
  51.     }
  52.     return NULL;
  53.   }
  54.   if (inputString[0] == '\n') {
  55.     free(inputString);
  56.     return NULL;
  57.   }
  58.   size_t inputStringLength = strlen(inputString);
  59.   char *lastStringCharacterPtr = &(inputString[inputStringLength - 1]);
  60.   if (*lastStringCharacterPtr != '\n') {
  61.     free(inputString);
  62.     while (getchar() != '\n') {
  63.     }
  64.     return NULL;
  65.   }
  66.   *lastStringCharacterPtr = '\0';
  67.   return saferealloc(inputString, inputStringLength);
  68. }
  69.  
  70. uint64_t abs64(int64_t integer) { return integer < 0 ? -(uint64_t)integer : integer; }
  71.  
  72. typedef struct {
  73.   int64_t integer;
  74.   const char *error;
  75. } StringToIntResult;
  76. StringToIntResult *stringToInt(const char *string) {
  77.   StringToIntResult *result = safemalloc(sizeof(StringToIntResult));
  78.   if (!string) {
  79.     *result = (StringToIntResult){0, "Passed NULL."};
  80.     return result;
  81.   }
  82.   if (string[0] == '\0') {
  83.     *result = (StringToIntResult){0, "Invalid string."};
  84.     return result;
  85.   }
  86.   bool startsWithNegativeSign = (string[0] == '-');
  87.   if (startsWithNegativeSign) {
  88.     string = string + 1;
  89.   }
  90.   uint64_t maxInt = abs64(startsWithNegativeSign ? INT64_MIN : INT64_MAX);
  91.   uint8_t maxDigitNumber = snprintf( // NOLINT(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling)
  92.       NULL, 0, "%" PRIu64, maxInt);
  93.   size_t stringLength = strlen(string);
  94.   if (stringLength == 0 || string[0] == '0' || stringLength > maxDigitNumber) {
  95.     *result = (StringToIntResult){0, "Invalid string."};
  96.     return result;
  97.   }
  98.   for (uint32_t i = 0; i < stringLength; ++i) {
  99.     if (string[i] < '0' || string[i] > '9') {
  100.       *result = (StringToIntResult){0, "The string contains non numerical characters."};
  101.       return result;
  102.     }
  103.   }
  104.   if (stringLength == maxDigitNumber) {
  105.     char *maxString = safemalloc(maxDigitNumber + 1);
  106.     (void)snprintf(maxString, // NOLINT(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling)
  107.                    maxDigitNumber + 1, "%" PRIu64, maxInt);
  108.     for (uint32_t i = 0; i < stringLength; ++i) {
  109.       if (string[i] > maxString[i]) {
  110.         free(maxString);
  111.         *result = (StringToIntResult){0, "The resulting integer is too large."};
  112.         return result;
  113.       }
  114.     }
  115.     free(maxString);
  116.   }
  117.   int64_t integer = strtoll(string, NULL, 10);
  118.   if (startsWithNegativeSign) {
  119.     integer = -integer;
  120.   }
  121.   *result = (StringToIntResult){integer, NULL};
  122.   return result;
  123. }
  124.  
  125. int __cdecl main(int argc, char **argv) {
  126.   WSADATA wsaData;
  127.   SOCKET ConnectSocket = INVALID_SOCKET;
  128.   struct addrinfo *result = NULL, *ptr = NULL, hints;
  129.  
  130.   char recvbuf[DEFAULT_BUFLEN];
  131.   int iResult;
  132.   int recvbuflen = DEFAULT_BUFLEN;
  133.  
  134.   // Validate the parameters
  135.   if (argc != 2) {
  136.     printf("usage: %s server-name\n", argv[0]);
  137.     return 1;
  138.   }
  139.  
  140.   // Initialize Winsock
  141.   iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
  142.   if (iResult != 0) {
  143.     printf("WSAStartup failed with error: %d\n", iResult);
  144.     return 1;
  145.   }
  146.  
  147.   ZeroMemory(&hints, sizeof(hints));
  148.   hints.ai_family = AF_UNSPEC;
  149.   hints.ai_socktype = SOCK_STREAM;
  150.   hints.ai_protocol = IPPROTO_TCP;
  151.  
  152.   // Resolve the server address and port
  153.   iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result);
  154.   if (iResult != 0) {
  155.     printf("getaddrinfo failed with error: %d\n", iResult);
  156.     WSACleanup();
  157.     return 1;
  158.   }
  159.  
  160.   // Attempt to connect to an address until one succeeds
  161.   for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {
  162.  
  163.     // Create a SOCKET for connecting to server
  164.     ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
  165.     if (ConnectSocket == INVALID_SOCKET) {
  166.       printf("socket failed with error: %ld\n", WSAGetLastError());
  167.       WSACleanup();
  168.       return 1;
  169.     }
  170.  
  171.     // Connect to server.
  172.     iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
  173.     if (iResult == SOCKET_ERROR) {
  174.       closesocket(ConnectSocket);
  175.       ConnectSocket = INVALID_SOCKET;
  176.       continue;
  177.     }
  178.     break;
  179.   }
  180.  
  181.   freeaddrinfo(result);
  182.  
  183.   if (ConnectSocket == INVALID_SOCKET) {
  184.     printf("Unable to connect to server!\n");
  185.     WSACleanup();
  186.     return 1;
  187.   }
  188.  
  189.   // Receive until the peer closes the connection
  190.   do {
  191.     char *inputString = input(9);
  192.     if (!inputString) {
  193.       puts("Invalid input");
  194.       continue;
  195.     }
  196.     if (!strcmp("exit", inputString)) {
  197.       free(inputString);
  198.       puts("exiting connection");
  199.       break;
  200.     }
  201.     StringToIntResult *result = stringToInt(inputString);
  202.     free(inputString);
  203.     if (result->error) {
  204.       printf("%s\n", result->error);
  205.       free(result);
  206.       continue;
  207.     }
  208.     char sendbuf[DEFAULT_BUFLEN] = {0};
  209.     sprintf(sendbuf, "%lld", result->integer);
  210.     iResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0);
  211.     if (iResult == SOCKET_ERROR) {
  212.       printf("send failed with error: %d\n", WSAGetLastError());
  213.       closesocket(ConnectSocket);
  214.       WSACleanup();
  215.       return 1;
  216.     }
  217.  
  218.     for (uint32_t i = 0; i < recvbuflen; ++i) {
  219.       recvbuf[i] = '\0';
  220.     }
  221.  
  222.     iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
  223.     if (iResult > 0) {
  224.       printf("Bytes received: %d\n", iResult);
  225.       printf("%s", recvbuf);
  226.     } else if (iResult == 0)
  227.       printf("Connection closed\n");
  228.     else
  229.       printf("recv failed with error: %d\n", WSAGetLastError());
  230.  
  231.   } while (iResult > 0);
  232.  
  233.   // cleanup
  234.   closesocket(ConnectSocket);
  235.   WSACleanup();
  236.  
  237.   return 0;
  238. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement