Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:12:41

0001 // Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
0002 // Distributed under the MIT License (http://opensource.org/licenses/MIT)
0003 
0004 #pragma once
0005 
0006 // Helper RAII over winsock udp client socket.
0007 // Will throw on construction if socket creation failed.
0008 
0009 #include <spdlog/common.h>
0010 #include <spdlog/details/os.h>
0011 #include <spdlog/details/windows_include.h>
0012 #include <winsock2.h>
0013 #include <ws2tcpip.h>
0014 #include <stdlib.h>
0015 #include <stdio.h>
0016 #include <string>
0017 
0018 #pragma comment(lib, "Ws2_32.lib")
0019 #pragma comment(lib, "Mswsock.lib")
0020 #pragma comment(lib, "AdvApi32.lib")
0021 
0022 namespace spdlog {
0023 namespace details {
0024 class udp_client
0025 {
0026     static constexpr int TX_BUFFER_SIZE = 1024 * 10;
0027     SOCKET socket_ = INVALID_SOCKET;
0028     sockaddr_in addr_ = {0};
0029 
0030     static void init_winsock_()
0031     {
0032         WSADATA wsaData;
0033         auto rv = ::WSAStartup(MAKEWORD(2, 2), &wsaData);
0034         if (rv != 0)
0035         {
0036             throw_winsock_error_("WSAStartup failed", ::WSAGetLastError());
0037         }
0038     }
0039 
0040     static void throw_winsock_error_(const std::string &msg, int last_error)
0041     {
0042         char buf[512];
0043         ::FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, last_error,
0044             MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, (sizeof(buf) / sizeof(char)), NULL);
0045 
0046         throw_spdlog_ex(fmt_lib::format("udp_sink - {}: {}", msg, buf));
0047     }
0048 
0049     void cleanup_()
0050     {
0051         if (socket_ != INVALID_SOCKET)
0052         {
0053             ::closesocket(socket_);
0054         }
0055         socket_ = INVALID_SOCKET;
0056         ::WSACleanup();
0057     }
0058 
0059 public:
0060     udp_client(const std::string &host, uint16_t port)
0061     {
0062         init_winsock_();
0063 
0064         addr_.sin_family = PF_INET;
0065         addr_.sin_port = htons(port);
0066         addr_.sin_addr.s_addr = INADDR_ANY;
0067         if (InetPtonA(PF_INET, host.c_str(), &addr_.sin_addr.s_addr) != 1)
0068         {
0069             int last_error = ::WSAGetLastError();
0070             ::WSACleanup();
0071             throw_winsock_error_("error: Invalid address!", last_error);
0072         }
0073 
0074         socket_ = ::socket(PF_INET, SOCK_DGRAM, 0);
0075         if (socket_ == INVALID_SOCKET)
0076         {
0077             int last_error = ::WSAGetLastError();
0078             ::WSACleanup();
0079             throw_winsock_error_("error: Create Socket failed", last_error);
0080         }
0081 
0082         int option_value = TX_BUFFER_SIZE;
0083         if (::setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, reinterpret_cast<const char *>(&option_value), sizeof(option_value)) < 0)
0084         {
0085             int last_error = ::WSAGetLastError();
0086             cleanup_();
0087             throw_winsock_error_("error: setsockopt(SO_SNDBUF) Failed!", last_error);
0088         }
0089     }
0090 
0091     ~udp_client()
0092     {
0093         cleanup_();
0094     }
0095 
0096     SOCKET fd() const
0097     {
0098         return socket_;
0099     }
0100 
0101     void send(const char *data, size_t n_bytes)
0102     {
0103         socklen_t tolen = sizeof(struct sockaddr);
0104         if (::sendto(socket_, data, static_cast<int>(n_bytes), 0, (struct sockaddr *)&addr_, tolen) == -1)
0105         {
0106             throw_spdlog_ex("sendto(2) failed", errno);
0107         }
0108     }
0109 };
0110 } // namespace details
0111 } // namespace spdlog