m1dw0rd

Untitled

Jun 11th, 2022
47
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.92 KB | None | 0 0
  1. #pragma comment(lib, "Ws2_32.lib")
  2. #include <iostream>
  3. #include <winsock2.h>
  4. #include <ws2tcpip.h>
  5. #include <fstream>
  6.  
  7. int64_t GetFileSize(const std::string& fileName) {
  8.     // no idea how to get filesizes > 2.1 GB in a C++ kind-of way.
  9.     // I will cheat and use Microsoft's C-style file API
  10.     FILE* f;
  11.     if (fopen_s(&f, fileName.c_str(), "rb") != 0) {
  12.         return -1;
  13.     }
  14.     _fseeki64(f, 0, SEEK_END);
  15.     const int64_t len = _ftelli64(f);
  16.     fclose(f);
  17.     return len;
  18. }
  19.  
  20. ///
  21. /// Recieves data in to buffer until bufferSize value is met
  22. ///
  23. int RecvBuffer(SOCKET s, char* buffer, int bufferSize, int chunkSize = 4 * 1024) {
  24.     int i = 0;
  25.     while (i < bufferSize) {
  26.         const int l = recv(s, &buffer[i], __min(chunkSize, bufferSize - i), 0);
  27.         if (l < 0) { return l; } // this is an error
  28.         i += l;
  29.     }
  30.     return i;
  31. }
  32.  
  33. ///
  34. /// Sends data in buffer until bufferSize value is met
  35. ///
  36. int SendBuffer(SOCKET s, const char* buffer, int bufferSize, int chunkSize = 4 * 1024) {
  37.  
  38.     int i = 0;
  39.     while (i < bufferSize) {
  40.         const int l = send(s, &buffer[i], __min(chunkSize, bufferSize - i), 0);
  41.         if (l < 0) { return l; } // this is an error
  42.         i += l;
  43.     }
  44.     return i;
  45. }
  46.  
  47. //
  48. // Sends a file
  49. // returns size of file if success
  50. // returns -1 if file couldn't be opened for input
  51. // returns -2 if couldn't send file length properly
  52. // returns -3 if file couldn't be sent properly
  53. //
  54. int64_t SendFile(SOCKET s, const std::string& fileName, int chunkSize = 64 * 1024) {
  55.  
  56.     const int64_t fileSize = GetFileSize(fileName);
  57.     if (fileSize < 0) { return -1; }
  58.  
  59.     std::ifstream file(fileName, std::ifstream::binary);
  60.     if (file.fail()) { return -1; }
  61.  
  62.     if (SendBuffer(s, reinterpret_cast<const char*>(&fileSize),
  63.         sizeof(fileSize)) != sizeof(fileSize)) {
  64.         return -2;
  65.     }
  66.  
  67.     char* buffer = new char[chunkSize];
  68.     bool errored = false;
  69.     int64_t i = fileSize;
  70.     while (i != 0) {
  71.         const int64_t ssize = __min(i, (int64_t)chunkSize);
  72.         if (!file.read(buffer, ssize)) { errored = true; break; }
  73.         const int l = SendBuffer(s, buffer, (int)ssize);
  74.         if (l < 0) { errored = true; break; }
  75.         i -= l;
  76.     }
  77.     delete[] buffer;
  78.  
  79.     file.close();
  80.  
  81.     return errored ? -3 : fileSize;
  82. }
  83.  
  84. //
  85. // Receives a file
  86. // returns size of file if success
  87. // returns -1 if file couldn't be opened for output
  88. // returns -2 if couldn't receive file length properly
  89. // returns -3 if couldn't receive file properly
  90. //
  91. int64_t RecvFile(SOCKET s, const std::string& fileName, int chunkSize = 64 * 1024) {
  92.     std::ofstream file(fileName, std::ofstream::binary);
  93.     if (file.fail()) { return -1; }
  94.  
  95.     int64_t fileSize;
  96.     if (RecvBuffer(s, reinterpret_cast<char*>(&fileSize),
  97.         sizeof(fileSize)) != sizeof(fileSize)) {
  98.         return -2;
  99.     }
  100.  
  101.     char* buffer = new char[chunkSize];
  102.     bool errored = false;
  103.     int64_t i = fileSize;
  104.     while (i != 0) {
  105.         const int r = RecvBuffer(s, buffer, (int)__min(i, (int64_t)chunkSize));
  106.         if ((r < 0) || !file.write(buffer, r)) { errored = true; break; }
  107.         i -= r;
  108.     }
  109.     delete[] buffer;
  110.  
  111.     file.close();
  112.  
  113.     return errored ? -3 : fileSize;
  114. }
  115.  
  116.  
  117. DWORD __stdcall ClientProc(LPVOID param) {
  118.  
  119.     struct addrinfo hints = { 0 }, * result, * ptr;
  120.     hints.ai_family = AF_UNSPEC;
  121.     hints.ai_socktype = SOCK_STREAM;
  122.     hints.ai_protocol = IPPROTO_TCP;
  123.  
  124.     if (getaddrinfo("127.0.0.1", "9001", &hints, &result) != 0) {
  125.         return ~0;
  126.     }
  127.  
  128.     SOCKET client = INVALID_SOCKET;
  129.     for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {
  130.         client = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
  131.         if (client == SOCKET_ERROR) {
  132.             // TODO: failed (don't just return, cleanup)
  133.         }
  134.         if (connect(client, ptr->ai_addr, (int)ptr->ai_addrlen) == SOCKET_ERROR) {
  135.             closesocket(client);
  136.             client = INVALID_SOCKET;
  137.             continue;
  138.         }
  139.         break;
  140.     }
  141.     freeaddrinfo(result);
  142.  
  143.     if (client == SOCKET_ERROR) {
  144.         std::cout << "Couldn't create client socket" << std::endl;
  145.         return ~1;
  146.     }
  147.  
  148.     int64_t rc = SendFile(client, "C:\\Windows\\Temp\\logcz.zip");
  149.     if (rc < 0) {
  150.         std::cout << "Failed to send file: " << rc << std::endl;
  151.     }
  152.  
  153.     closesocket(client);
  154.  
  155.     return 0;
  156. }
  157.  
  158. int main()
  159. {
  160.     WSADATA wsaData;
  161.     WSAStartup(MAKEWORD(2, 2), &wsaData);
  162.  
  163.     {
  164.         struct addrinfo hints = { 0 };
  165.         hints.ai_family = AF_INET;
  166.         hints.ai_socktype = SOCK_STREAM;
  167.         hints.ai_protocol = IPPROTO_TCP;
  168.         hints.ai_flags = AI_PASSIVE;
  169.  
  170.         struct addrinfo* result = NULL;
  171.         if (0 != getaddrinfo(NULL, "9001", &hints, &result)) {
  172.             // TODO: failed (don't just return, clean up)
  173.         }
  174.  
  175.         SOCKET server = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
  176.         if (server == INVALID_SOCKET) {
  177.             // TODO: failed (don't just return, clean up)
  178.         }
  179.  
  180.         if (bind(server, result->ai_addr, (int)result->ai_addrlen) == INVALID_SOCKET) {
  181.             // TODO: failed (don't just return, clean up)
  182.         }
  183.         freeaddrinfo(result);
  184.  
  185.         if (listen(server, SOMAXCONN) == SOCKET_ERROR) {
  186.             // TODO: failed (don't just return, clean up)
  187.         }
  188.  
  189.         // start a client on another thread
  190.         HANDLE hClientThread = CreateThread(NULL, 0, ClientProc, NULL, 0, 0);
  191.  
  192.         SOCKET client = accept(server, NULL, NULL);
  193.  
  194.         const int64_t rc = RecvFile(client, "C:\\Users\\saaad\\Desktop\\test\\file.zip");
  195.         if (rc < 0) {
  196.             std::cout << "Failed to recv file: " << rc << std::endl;
  197.         }
  198.  
  199.         closesocket(client);
  200.         closesocket(server);
  201.  
  202.         WaitForSingleObject(hClientThread, INFINITE);
  203.         CloseHandle(hClientThread);
  204.     }
  205.     WSACleanup();
  206.     return 0;
  207. }
Advertisement
Add Comment
Please, Sign In to add comment