Photon 1.0.0
Loading...
Searching...
No Matches
tcp_client-windows.h
Go to the documentation of this file.
1// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
2// Distributed under the MIT License (http://opensource.org/licenses/MIT)
3
4#pragma once
5
6#define WIN32_LEAN_AND_MEAN
7// tcp client helper
8#include <spdlog/common.h>
9#include <spdlog/details/os.h>
10
11#include <winsock2.h>
12#include <windows.h>
13#include <ws2tcpip.h>
14#include <stdlib.h>
15#include <stdio.h>
16#include <string>
17
18#pragma comment(lib, "Ws2_32.lib")
19#pragma comment(lib, "Mswsock.lib")
20#pragma comment(lib, "AdvApi32.lib")
21
22namespace spdlog
23{
24 namespace details
25 {
27 {
29
30 static void init_winsock_()
31 {
32 WSADATA wsaData;
33 auto rv = WSAStartup(MAKEWORD(2, 2), &wsaData);
34 if (rv != 0)
35 {
36 throw_winsock_error_("WSAStartup failed", ::WSAGetLastError());
37 }
38 }
39
40 static void throw_winsock_error_(const std::string& msg, int last_error)
41 {
42 char buf[512];
43 ::FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, last_error,
44 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, (sizeof(buf) / sizeof(char)), NULL);
45
46 throw_spdlog_ex(fmt_lib::format("tcp_sink - {}: {}", msg, buf));
47 }
48
49 public:
51 {
53 }
54
56 {
57 close();
58 ::WSACleanup();
59 }
60
61 bool is_connected() const
62 {
63 return socket_ != INVALID_SOCKET;
64 }
65
66 void close()
67 {
70 }
71
72 SOCKET fd() const
73 {
74 return socket_;
75 }
76
77 // try to connect or throw on failure
78 void connect(const std::string& host, int port)
79 {
80 if (is_connected())
81 {
82 close();
83 }
84 struct addrinfo hints
85 {
86 };
87 ZeroMemory(&hints, sizeof(hints));
88
89 hints.ai_family = AF_INET; // IPv4
90 hints.ai_socktype = SOCK_STREAM; // TCP
91 hints.ai_flags = AI_NUMERICSERV; // port passed as as numeric value
92 hints.ai_protocol = 0;
93
94 auto port_str = std::to_string(port);
95 struct addrinfo* addrinfo_result;
96 auto rv = ::getaddrinfo(host.c_str(), port_str.c_str(), &hints, &addrinfo_result);
97 int last_error = 0;
98 if (rv != 0)
99 {
100 last_error = ::WSAGetLastError();
101 WSACleanup();
102 throw_winsock_error_("getaddrinfo failed", last_error);
103 }
104
105 // Try each address until we successfully connect(2).
106
107 for (auto* rp = addrinfo_result; rp != nullptr; rp = rp->ai_next)
108 {
109 socket_ = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
110 if (socket_ == INVALID_SOCKET)
111 {
112 last_error = ::WSAGetLastError();
113 WSACleanup();
114 continue;
115 }
116 if (::connect(socket_, rp->ai_addr, (int)rp->ai_addrlen) == 0)
117 {
118 break;
119 }
120 else
121 {
122 last_error = ::WSAGetLastError();
123 close();
124 }
125 }
126 ::freeaddrinfo(addrinfo_result);
127 if (socket_ == INVALID_SOCKET)
128 {
129 WSACleanup();
130 throw_winsock_error_("connect failed", last_error);
131 }
132
133 // set TCP_NODELAY
134 int enable_flag = 1;
135 ::setsockopt(socket_, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&enable_flag), sizeof(enable_flag));
136 }
137
138 // Send exactly n_bytes of the given data.
139 // On error close the connection and throw.
140 void send(const char* data, size_t n_bytes)
141 {
142 size_t bytes_sent = 0;
143 while (bytes_sent < n_bytes)
144 {
145 const int send_flags = 0;
146 auto write_result = ::send(socket_, data + bytes_sent, (int)(n_bytes - bytes_sent), send_flags);
147 if (write_result == SOCKET_ERROR)
148 {
149 int last_error = ::WSAGetLastError();
150 close();
151 throw_winsock_error_("send failed", last_error);
152 }
153
154 if (write_result == 0) // (probably should not happen but in any case..)
155 {
156 break;
157 }
158 bytes_sent += static_cast<size_t>(write_result);
159 }
160 }
161 };
162 } // namespace details
163} // namespace spdlog
#define PHOTON_CLOSE
Definition Socket.hpp:38
#define SOCKET_ERROR
Definition Socket.hpp:27
#define WSAGetLastError()
Definition Socket.hpp:30
Definition tcp_client-windows.h:27
static void init_winsock_()
Definition tcp_client-windows.h:30
bool is_connected() const
Definition tcp_client-windows.h:61
void connect(const std::string &host, int port)
Definition tcp_client-windows.h:78
~tcp_client()
Definition tcp_client-windows.h:55
void send(const char *data, size_t n_bytes)
Definition tcp_client-windows.h:140
tcp_client()
Definition tcp_client-windows.h:50
SOCKET fd() const
Definition tcp_client-windows.h:72
static void throw_winsock_error_(const std::string &msg, int last_error)
Definition tcp_client-windows.h:40
void close()
Definition tcp_client-windows.h:66
SOCKET socket_
Definition tcp_client-windows.h:28
#define INVALID_SOCKET
Definition Config.hpp:44
Definition async.h:26
SPDLOG_INLINE void throw_spdlog_ex(const std::string &msg, int last_errno)
Definition common-inl.h:75
#define NULL
Definition strtod.cpp:30
Definition format.h:1901
rp
Definition tag_strings.h:66
annotation details
Definition tag_strings.h:125