| 2939 | |
| 2940 | template <typename BindOrConnect> |
| 2941 | socket_t create_socket(const std::string &host, const std::string &ip, int port, |
| 2942 | int address_family, int socket_flags, bool tcp_nodelay, |
| 2943 | SocketOptions socket_options, |
| 2944 | BindOrConnect bind_or_connect) { |
| 2945 | // Get address info |
| 2946 | const char *node = nullptr; |
| 2947 | struct addrinfo hints; |
| 2948 | struct addrinfo *result; |
| 2949 | |
| 2950 | memset(&hints, 0, sizeof(struct addrinfo)); |
| 2951 | hints.ai_socktype = SOCK_STREAM; |
| 2952 | hints.ai_protocol = 0; |
| 2953 | |
| 2954 | if (!ip.empty()) { |
| 2955 | node = ip.c_str(); |
| 2956 | // Ask getaddrinfo to convert IP in c-string to address |
| 2957 | hints.ai_family = AF_UNSPEC; |
| 2958 | hints.ai_flags = AI_NUMERICHOST; |
| 2959 | } else { |
| 2960 | if (!host.empty()) { node = host.c_str(); } |
| 2961 | hints.ai_family = address_family; |
| 2962 | hints.ai_flags = socket_flags; |
| 2963 | } |
| 2964 | |
| 2965 | #ifndef _WIN32 |
| 2966 | if (hints.ai_family == AF_UNIX) { |
| 2967 | const auto addrlen = host.length(); |
| 2968 | if (addrlen > sizeof(sockaddr_un::sun_path)) return INVALID_SOCKET; |
| 2969 | |
| 2970 | auto sock = socket(hints.ai_family, hints.ai_socktype, hints.ai_protocol); |
| 2971 | if (sock != INVALID_SOCKET) { |
| 2972 | sockaddr_un addr{}; |
| 2973 | addr.sun_family = AF_UNIX; |
| 2974 | std::copy(host.begin(), host.end(), addr.sun_path); |
| 2975 | |
| 2976 | hints.ai_addr = reinterpret_cast<sockaddr *>(&addr); |
| 2977 | hints.ai_addrlen = static_cast<socklen_t>( |
| 2978 | sizeof(addr) - sizeof(addr.sun_path) + addrlen); |
| 2979 | |
| 2980 | fcntl(sock, F_SETFD, FD_CLOEXEC); |
| 2981 | if (socket_options) { socket_options(sock); } |
| 2982 | |
| 2983 | if (!bind_or_connect(sock, hints)) { |
| 2984 | close_socket(sock); |
| 2985 | sock = INVALID_SOCKET; |
| 2986 | } |
| 2987 | } |
| 2988 | return sock; |
| 2989 | } |
| 2990 | #endif |
| 2991 | |
| 2992 | auto service = std::to_string(port); |
| 2993 | |
| 2994 | if (getaddrinfo(node, service.c_str(), &hints, &result)) { |
| 2995 | #if defined __linux__ && !defined __ANDROID__ |
| 2996 | res_init(); |
| 2997 | #endif |
| 2998 | return INVALID_SOCKET; |
no test coverage detected