* Creates a socket and connects to the specified node and service. * * @param node The node. * @param service The service. */
| 124 | * @param service The service. |
| 125 | */ |
| 126 | void TcpSocket::Connect(const String& node, const String& service) |
| 127 | { |
| 128 | addrinfo hints; |
| 129 | addrinfo *result; |
| 130 | int error = 0; |
| 131 | const char *func = nullptr; |
| 132 | |
| 133 | memset(&hints, 0, sizeof(hints)); |
| 134 | hints.ai_family = AF_UNSPEC; |
| 135 | hints.ai_socktype = SOCK_STREAM; |
| 136 | hints.ai_protocol = IPPROTO_TCP; |
| 137 | |
| 138 | int rc = getaddrinfo(node.CStr(), service.CStr(), &hints, &result); |
| 139 | |
| 140 | if (rc != 0) { |
| 141 | Log(LogCritical, "TcpSocket") |
| 142 | << "getaddrinfo() failed with error code " << rc << ", \"" << gai_strerror(rc) << "\""; |
| 143 | |
| 144 | BOOST_THROW_EXCEPTION(socket_error() |
| 145 | << boost::errinfo_api_function("getaddrinfo") |
| 146 | << errinfo_getaddrinfo_error(rc)); |
| 147 | } |
| 148 | |
| 149 | SOCKET fd = INVALID_SOCKET; |
| 150 | |
| 151 | for (addrinfo *info = result; info != nullptr; info = info->ai_next) { |
| 152 | fd = socket(info->ai_family, info->ai_socktype, info->ai_protocol); |
| 153 | |
| 154 | if (fd == INVALID_SOCKET) { |
| 155 | #ifdef _WIN32 |
| 156 | error = WSAGetLastError(); |
| 157 | #else /* _WIN32 */ |
| 158 | error = errno; |
| 159 | #endif /* _WIN32 */ |
| 160 | func = "socket"; |
| 161 | |
| 162 | continue; |
| 163 | } |
| 164 | |
| 165 | const int optTrue = 1; |
| 166 | if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, reinterpret_cast<const char *>(&optTrue), sizeof(optTrue)) != 0) { |
| 167 | #ifdef _WIN32 |
| 168 | error = WSAGetLastError(); |
| 169 | #else /* _WIN32 */ |
| 170 | error = errno; |
| 171 | #endif /* _WIN32 */ |
| 172 | Log(LogWarning, "TcpSocket") |
| 173 | << "setsockopt() unable to enable TCP keep-alives with error code " << rc; |
| 174 | } |
| 175 | |
| 176 | rc = connect(fd, info->ai_addr, info->ai_addrlen); |
| 177 | |
| 178 | if (rc < 0) { |
| 179 | #ifdef _WIN32 |
| 180 | error = WSAGetLastError(); |
| 181 | #else /* _WIN32 */ |
| 182 | error = errno; |
| 183 | #endif /* _WIN32 */ |
nothing calls this directly
no test coverage detected