| 2694 | #endif |
| 2695 | |
| 2696 | inline socket_t create_client_socket( |
| 2697 | const char *host, const char *ip, int port, int address_family, |
| 2698 | bool tcp_nodelay, SocketOptions socket_options, |
| 2699 | time_t connection_timeout_sec, time_t connection_timeout_usec, |
| 2700 | time_t read_timeout_sec, time_t read_timeout_usec, time_t write_timeout_sec, |
| 2701 | time_t write_timeout_usec, const std::string &intf, Error &error) { |
| 2702 | auto sock = create_socket( |
| 2703 | host, ip, port, address_family, 0, tcp_nodelay, std::move(socket_options), |
| 2704 | [&](socket_t sock2, struct addrinfo &ai) -> bool { |
| 2705 | if (!intf.empty()) { |
| 2706 | #ifdef USE_IF2IP |
| 2707 | auto ip = if2ip(address_family, intf); |
| 2708 | if (ip.empty()) { ip = intf; } |
| 2709 | if (!bind_ip_address(sock2, ip.c_str())) { |
| 2710 | error = Error::BindIPAddress; |
| 2711 | return false; |
| 2712 | } |
| 2713 | #endif |
| 2714 | } |
| 2715 | |
| 2716 | set_nonblocking(sock2, true); |
| 2717 | |
| 2718 | auto ret = |
| 2719 | ::connect(sock2, ai.ai_addr, static_cast<socklen_t>(ai.ai_addrlen)); |
| 2720 | |
| 2721 | if (ret < 0) { |
| 2722 | if (is_connection_error()) { |
| 2723 | error = Error::Connection; |
| 2724 | return false; |
| 2725 | } |
| 2726 | error = wait_until_socket_is_ready(sock2, connection_timeout_sec, |
| 2727 | connection_timeout_usec); |
| 2728 | if (error != Error::Success) { return false; } |
| 2729 | } |
| 2730 | |
| 2731 | set_nonblocking(sock2, false); |
| 2732 | |
| 2733 | { |
| 2734 | #ifdef _WIN32 |
| 2735 | auto timeout = static_cast<uint32_t>(read_timeout_sec * 1000 + |
| 2736 | read_timeout_usec / 1000); |
| 2737 | setsockopt(sock2, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, |
| 2738 | sizeof(timeout)); |
| 2739 | #else |
| 2740 | timeval tv; |
| 2741 | tv.tv_sec = static_cast<long>(read_timeout_sec); |
| 2742 | tv.tv_usec = static_cast<decltype(tv.tv_usec)>(read_timeout_usec); |
| 2743 | setsockopt(sock2, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)); |
| 2744 | #endif |
| 2745 | } |
| 2746 | { |
| 2747 | |
| 2748 | #ifdef _WIN32 |
| 2749 | auto timeout = static_cast<uint32_t>(write_timeout_sec * 1000 + |
| 2750 | write_timeout_usec / 1000); |
| 2751 | setsockopt(sock2, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, |
| 2752 | sizeof(timeout)); |
| 2753 | #else |
no test coverage detected