Photon 1.0.0
Loading...
Searching...
No Matches
tcp_client.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#ifdef _WIN32
7#error include tcp_client-windows.h instead
8#endif
9
10// tcp client helper
11#include <spdlog/common.h>
12#include <spdlog/details/os.h>
13
14#include <sys/socket.h>
15#include <arpa/inet.h>
16#include <unistd.h>
17#include <netdb.h>
18#include <netinet/tcp.h>
19#include <netinet/in.h>
20
21#include <string>
22
23namespace spdlog
24{
25 namespace details
26 {
27 class tcp_client
28 {
29 int socket_ = -1;
30
31 public:
32 bool is_connected() const
33 {
34 return socket_ != -1;
35 }
36
37 void close()
38 {
39 if (is_connected())
40 {
42 socket_ = -1;
43 }
44 }
45
46 int fd() const
47 {
48 return socket_;
49 }
50
52 {
53 close();
54 }
55
56 // try to connect or throw on failure
57 void connect(const std::string& host, int port)
58 {
59 close();
60 struct addrinfo hints
61 {
62 };
63 memset(&hints, 0, sizeof(struct addrinfo));
64 hints.ai_family = AF_INET; // IPv4
65 hints.ai_socktype = SOCK_STREAM; // TCP
66 hints.ai_flags = AI_NUMERICSERV; // port passed as as numeric value
67 hints.ai_protocol = 0;
68
69 auto port_str = std::to_string(port);
70 struct addrinfo* addrinfo_result;
71 auto rv = ::getaddrinfo(host.c_str(), port_str.c_str(), &hints, &addrinfo_result);
72 if (rv != 0)
73 {
74 throw_spdlog_ex(fmt_lib::format("::getaddrinfo failed: {}", gai_strerror(rv)));
75 }
76
77 // Try each address until we successfully connect(2).
78 int last_errno = 0;
79 for (auto* rp = addrinfo_result; rp != nullptr; rp = rp->ai_next)
80 {
81#if defined(SOCK_CLOEXEC)
82 const int flags = SOCK_CLOEXEC;
83#else
84 const int flags = 0;
85#endif
86 socket_ = ::socket(rp->ai_family, rp->ai_socktype | flags, rp->ai_protocol);
87 if (socket_ == -1)
88 {
89 last_errno = errno;
90 continue;
91 }
92 rv = ::connect(socket_, rp->ai_addr, rp->ai_addrlen);
93 if (rv == 0)
94 {
95 break;
96 }
97 last_errno = errno;
99 socket_ = -1;
100 }
101 ::freeaddrinfo(addrinfo_result);
102 if (socket_ == -1)
103 {
104 throw_spdlog_ex("::connect failed", last_errno);
105 }
106
107 // set TCP_NODELAY
108 int enable_flag = 1;
109 ::setsockopt(socket_, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&enable_flag), sizeof(enable_flag));
110
111 // prevent sigpipe on systems where MSG_NOSIGNAL is not available
112#if defined(SO_NOSIGPIPE) && !defined(MSG_NOSIGNAL)
113 ::setsockopt(socket_, SOL_SOCKET, SO_NOSIGPIPE, reinterpret_cast<char*>(&enable_flag), sizeof(enable_flag));
114#endif
115
116#if !defined(SO_NOSIGPIPE) && !defined(MSG_NOSIGNAL)
117#error "tcp_sink would raise SIGPIPE since neither SO_NOSIGPIPE nor MSG_NOSIGNAL are available"
118#endif
119 }
120
121 // Send exactly n_bytes of the given data.
122 // On error close the connection and throw.
123 void send(const char* data, size_t n_bytes)
124 {
125 size_t bytes_sent = 0;
126 while (bytes_sent < n_bytes)
127 {
128#if defined(MSG_NOSIGNAL)
129 const int send_flags = MSG_NOSIGNAL;
130#else
131 const int send_flags = 0;
132#endif
133 auto write_result = ::send(socket_, data + bytes_sent, n_bytes - bytes_sent, send_flags);
134 if (write_result < 0)
135 {
136 close();
137 throw_spdlog_ex("write(2) failed", errno);
138 }
139
140 if (write_result == 0) // (probably should not happen but in any case..)
141 {
142 break;
143 }
144 bytes_sent += static_cast<size_t>(write_result);
145 }
146 }
147 };
148 } // namespace details
149} // namespace spdlog
bool is_connected() const
Definition tcp_client.h:32
int fd() const
Definition tcp_client.h:46
void connect(const std::string &host, int port)
Definition tcp_client.h:57
~tcp_client()
Definition tcp_client.h:51
void send(const char *data, size_t n_bytes)
Definition tcp_client.h:123
void close()
Definition tcp_client.h:37
SOCKET socket_
Definition tcp_client-windows.h:28
Definition async.h:26
SPDLOG_INLINE void throw_spdlog_ex(const std::string &msg, int last_errno)
Definition common-inl.h:75
Definition format.h:1901
rp
Definition tag_strings.h:66
annotation details
Definition tag_strings.h:125