| 2848 | #endif |
| 2849 | |
| 2850 | inline socket_t create_client_socket( |
| 2851 | const std::string &host, const std::string &ip, int port, |
| 2852 | int address_family, bool tcp_nodelay, SocketOptions socket_options, |
| 2853 | time_t connection_timeout_sec, time_t connection_timeout_usec, |
| 2854 | time_t read_timeout_sec, time_t read_timeout_usec, time_t write_timeout_sec, |
| 2855 | time_t write_timeout_usec, const std::string &intf, Error &error) { |
| 2856 | auto sock = create_socket( |
| 2857 | host, ip, port, address_family, 0, tcp_nodelay, std::move(socket_options), |
| 2858 | [&](socket_t sock2, struct addrinfo &ai) -> bool { |
| 2859 | if (!intf.empty()) { |
| 2860 | #ifdef USE_IF2IP |
| 2861 | auto ip_from_if = if2ip(address_family, intf); |
| 2862 | if (ip_from_if.empty()) { ip_from_if = intf; } |
| 2863 | if (!bind_ip_address(sock2, ip_from_if.c_str())) { |
| 2864 | error = Error::BindIPAddress; |
| 2865 | return false; |
| 2866 | } |
| 2867 | #endif |
| 2868 | } |
| 2869 | |
| 2870 | set_nonblocking(sock2, true); |
| 2871 | |
| 2872 | auto ret = |
| 2873 | ::connect(sock2, ai.ai_addr, static_cast<socklen_t>(ai.ai_addrlen)); |
| 2874 | |
| 2875 | if (ret < 0) { |
| 2876 | if (is_connection_error()) { |
| 2877 | error = Error::Connection; |
| 2878 | return false; |
| 2879 | } |
| 2880 | error = wait_until_socket_is_ready(sock2, connection_timeout_sec, |
| 2881 | connection_timeout_usec); |
| 2882 | if (error != Error::Success) { return false; } |
| 2883 | } |
| 2884 | |
| 2885 | set_nonblocking(sock2, false); |
| 2886 | |
| 2887 | { |
| 2888 | #ifdef _WIN32 |
| 2889 | auto timeout = static_cast<uint32_t>(read_timeout_sec * 1000 + |
| 2890 | read_timeout_usec / 1000); |
| 2891 | setsockopt(sock2, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, |
| 2892 | sizeof(timeout)); |
| 2893 | #else |
| 2894 | timeval tv; |
| 2895 | tv.tv_sec = static_cast<long>(read_timeout_sec); |
| 2896 | tv.tv_usec = static_cast<decltype(tv.tv_usec)>(read_timeout_usec); |
| 2897 | setsockopt(sock2, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)); |
| 2898 | #endif |
| 2899 | } |
| 2900 | { |
| 2901 | |
| 2902 | #ifdef _WIN32 |
| 2903 | auto timeout = static_cast<uint32_t>(write_timeout_sec * 1000 + |
| 2904 | write_timeout_usec / 1000); |
| 2905 | setsockopt(sock2, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, |
| 2906 | sizeof(timeout)); |
| 2907 | #else |
no test coverage detected