From 99e2e923d0c77b02f3fb4ff648ea916954868606 Mon Sep 17 00:00:00 2001 From: Yuqian Yang Date: Fri, 28 Feb 2025 23:13:39 +0800 Subject: chore(store): move everything to store. --- .../life/computer-network-experiment/Common.cpp | 142 +++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 store/works/life/computer-network-experiment/Common.cpp (limited to 'store/works/life/computer-network-experiment/Common.cpp') diff --git a/store/works/life/computer-network-experiment/Common.cpp b/store/works/life/computer-network-experiment/Common.cpp new file mode 100644 index 0000000..1df4d56 --- /dev/null +++ b/store/works/life/computer-network-experiment/Common.cpp @@ -0,0 +1,142 @@ +#include "Common.h" + +#include "IO.h" +#include + +#ifdef WIN32 +#include +#include +#else +#include +#include +#include +#include +#endif + +#include + +[[noreturn]] void PrintErrorMessageAndExit(StringView message, + bool print_last_error) { + + SendOutput(CRUT("{}\n"), message); + + if (print_last_error) { +#ifdef WIN32 + auto error_code = WSAGetLastError(); + SendOutput(OutputType::Error, CRUT("Error code is {}.\n"), error_code); + wchar_t buffer[500]; + if (!FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_ARGUMENT_ARRAY | + FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, error_code, 0, buffer, 500, nullptr)) { + SendOutput(OutputType::Error, CRUT("Failed to format error message.\n")); + } else { + SendOutput(OutputType::Error, CRUT("{}\n"), buffer); + } +#else +#endif + } + + BeforeExit(); + + std::exit(1); +} + +#ifdef WIN32 +namespace { +void InitWSA() { + WSADATA wsa_data; + + if (WSAStartup(MAKEWORD(2, 2), &wsa_data)) { // initialize wsa + PrintErrorMessageAndExit(CRUT("Failed to initialize wsa.")); + } +} +} // namespace + +#endif + +int CloseSocket(int socket) { +#ifdef WIN32 + return closesocket(socket); +#else + return close(socket); +#endif +} + +void BeforeExit() { +#ifdef WIN32 + WSACleanup(); +#endif + + SignalAndWaitForOutputThreadStop(); +} + +bool SafeSend(int socket, std::string_view buffer) { + const int total_byte_count = buffer.size(); + int byte_count_sent = 0; + int retry_count = 0; + + while (true) { + // Now we have sent all data. + if (byte_count_sent == total_byte_count) + return true; + + auto byte_actually_sent = send(socket, buffer.data() + byte_count_sent, + buffer.size() - byte_count_sent, 0); + + // send failed + if (byte_actually_sent == -1) { + return false; + } + + byte_count_sent += byte_actually_sent; + } +} + +bool SafeReadUntil(int socket, char c, std::string &data, std::string &rest) { + data = rest; + + const int buffer_size = 100; + char buffer[buffer_size]; + + while (true) { + int received_number = recv(socket, buffer, buffer_size, 0); + + if (received_number == -1) { + return false; + } + + bool end = false; + + for (int i = 0; i < received_number; i++) { + if (buffer[i] == c) { + data.append(buffer, i); + rest = std::string(buffer + i + 1, received_number - i - 1); + end = true; + break; + } + } + + if (end) + return true; + + data.append(buffer, received_number); + } +} + +int main() { +#ifdef WIN32 + HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE); + DWORD mode; + GetConsoleMode(h, &mode); + mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; + SetConsoleMode(h, mode); + + InitWSA(); +#endif + + int c = Main(); + + BeforeExit(); + return c; +} -- cgit v1.2.3