| 2516 | |
| 2517 | template <typename BindOrConnect> |
| 2518 | socket_t create_socket(const char *host, const char *ip, int port, |
| 2519 | int address_family, int socket_flags, bool tcp_nodelay, |
| 2520 | SocketOptions socket_options, |
| 2521 | BindOrConnect bind_or_connect) { |
| 2522 | // Get address info |
| 2523 | const char *node = nullptr; |
| 2524 | struct addrinfo hints; |
| 2525 | struct addrinfo *result; |
| 2526 | |
| 2527 | memset(&hints, 0, sizeof(struct addrinfo)); |
| 2528 | hints.ai_socktype = SOCK_STREAM; |
| 2529 | hints.ai_protocol = 0; |
| 2530 | |
| 2531 | if (ip[0] != '\0') { |
| 2532 | node = ip; |
| 2533 | // Ask getaddrinfo to convert IP in c-string to address |
| 2534 | hints.ai_family = AF_UNSPEC; |
| 2535 | hints.ai_flags = AI_NUMERICHOST; |
| 2536 | } else { |
| 2537 | node = host; |
| 2538 | hints.ai_family = address_family; |
| 2539 | hints.ai_flags = socket_flags; |
| 2540 | } |
| 2541 | |
| 2542 | auto service = std::to_string(port); |
| 2543 | |
| 2544 | if (getaddrinfo(node, service.c_str(), &hints, &result)) { |
| 2545 | #if defined __linux__ && !defined __ANDROID__ |
| 2546 | res_init(); |
| 2547 | #endif |
| 2548 | return INVALID_SOCKET; |
| 2549 | } |
| 2550 | |
| 2551 | for (auto rp = result; rp; rp = rp->ai_next) { |
| 2552 | // Create a socket |
| 2553 | #ifdef _WIN32 |
| 2554 | auto sock = |
| 2555 | WSASocketW(rp->ai_family, rp->ai_socktype, rp->ai_protocol, nullptr, 0, |
| 2556 | WSA_FLAG_NO_HANDLE_INHERIT | WSA_FLAG_OVERLAPPED); |
| 2557 | /** |
| 2558 | * Since the WSA_FLAG_NO_HANDLE_INHERIT is only supported on Windows 7 SP1 |
| 2559 | * and above the socket creation fails on older Windows Systems. |
| 2560 | * |
| 2561 | * Let's try to create a socket the old way in this case. |
| 2562 | * |
| 2563 | * Reference: |
| 2564 | * https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsasocketa |
| 2565 | * |
| 2566 | * WSA_FLAG_NO_HANDLE_INHERIT: |
| 2567 | * This flag is supported on Windows 7 with SP1, Windows Server 2008 R2 with |
| 2568 | * SP1, and later |
| 2569 | * |
| 2570 | */ |
| 2571 | if (sock == INVALID_SOCKET) { |
| 2572 | sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); |
| 2573 | } |
| 2574 | #else |
| 2575 | auto sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); |
no test coverage detected