int SetPreBindOptions()

in ctsTraffic/ctsConfig.cpp [3993:4222]


int SetPreBindOptions(SOCKET socket, const ctSockaddr& localAddress) noexcept
{
    ctsConfigInitOnce();

    if (g_configSettings->OutgoingIfIndex > 0)
    {
        constexpr int optlen{sizeof g_configSettings->OutgoingIfIndex};

        if (localAddress.family() == AF_INET)
        {
            // Interface index is in network byte order for IPPROTO_IP.
            const DWORD optionValue = htonl(g_configSettings->OutgoingIfIndex);
            if (::setsockopt(
                    socket,
                    IPPROTO_IP, // level
                    IP_UNICAST_IF, // optname
                    reinterpret_cast<const char*>(&optionValue),
                    optlen) != 0)
            {
                const auto gle = WSAGetLastError();
                PrintErrorIfFailed("setsockopt(IP_UNICAST_IF)", gle);
                return gle;
            }
        }
        else
        {
            // Interface index is in host byte order for IPPROTO_IPV6.
            if (::setsockopt(
                    socket,
                    IPPROTO_IPV6, // level
                    IPV6_UNICAST_IF, // optname
                    reinterpret_cast<const char*>(&g_configSettings->OutgoingIfIndex),
                    optlen) != 0)
            {
                const auto gle = WSAGetLastError();
                PrintErrorIfFailed("setsockopt(IPV6_UNICAST_IF)", gle);
                return gle;
            }
        }
    }

    //
    // if the user specified bind addresses, enable SO_PORT_SCALABILITY
    // - this will allow each unique IP address the full range of ephemeral ports
    // this option is not available when just binding to INET_ANY (making an ephemeral bind)
    // this option is also not used if the user is binding to an explicit port #
    // - since the port scalability rules no longer apply
    //
    // these only are applicable for outgoing connections
    //
    if (ProtocolType::TCP == g_configSettings->Protocol && !IsListening())
    {
        if (g_configSettings->Options & ReuseUnicastPort)
        {
            // the admin configured the system to use this socket option
            // it is not compatible with SO_PORT_SCALABILITY
            constexpr DWORD optval{1}; // BOOL
            constexpr int optlen{sizeof optval};
#ifndef SO_REUSE_UNICASTPORT
#define SO_REUSE_UNICASTPORT (SO_PORT_SCALABILITY + 1)
#endif
            if (::setsockopt(
                    socket,
                    SOL_SOCKET, // level
                    SO_REUSE_UNICASTPORT, // optname
                    reinterpret_cast<const char*>(&optval),
                    optlen) != 0)
            {
                const auto gle = WSAGetLastError();
                PrintErrorIfFailed("setsockopt(SO_REUSE_UNICASTPORT)", gle);
                return gle;
            }
        }
        else if (!localAddress.IsAddressAny() && localAddress.port() == 0)
        {
            constexpr DWORD optval{1}; // BOOL
            // ReSharper disable once CppTooWideScopeInitStatement
            constexpr int optlen{sizeof optval};

            if (::setsockopt(
                    socket,
                    SOL_SOCKET, // level
                    SO_PORT_SCALABILITY, // optname
                    reinterpret_cast<const char*>(&optval),
                    optlen) != 0)
            {
                const auto gle = WSAGetLastError();
                PrintErrorIfFailed("setsockopt(SO_PORT_SCALABILITY)", gle);
                return gle;
            }
        }
    }

    if (g_configSettings->Options & LoopbackFastPath)
    {
        DWORD inValue{1};
        DWORD bytesReturned{};

        if (::WSAIoctl(
                socket,
                SIO_LOOPBACK_FAST_PATH,
                &inValue, sizeof inValue,
                nullptr, 0,
                &bytesReturned,
                nullptr,
                nullptr) != 0)
        {
            const auto gle = WSAGetLastError();
            PrintErrorIfFailed("WSAIoctl(SIO_LOOPBACK_FAST_PATH)", gle);
            return gle;
        }
    }

    if (g_configSettings->KeepAliveValue > 0)
    {
        tcp_keepalive keepaliveValues{};
        keepaliveValues.onoff = 1;
        keepaliveValues.keepalivetime = g_configSettings->KeepAliveValue;
        keepaliveValues.keepaliveinterval = 1000; // continue to default to 1 second

        DWORD bytesReturned{};
        if (::WSAIoctl(
                socket,
                SIO_KEEPALIVE_VALS, // control code
                &keepaliveValues, sizeof keepaliveValues, // in params
                nullptr, 0, // out params
                &bytesReturned,
                nullptr,
                nullptr
            ) != 0)
        {
            const auto gle = WSAGetLastError();
            PrintErrorIfFailed("WSAIoctl(SIO_KEEPALIVE_VALS)", gle);
            return gle;
        }
    }
    else if (g_configSettings->Options & Keepalive)
    {
        constexpr DWORD optval{1};
        // ReSharper disable once CppTooWideScopeInitStatement
        constexpr int optlen{sizeof optval};

        if (::setsockopt(
                socket,
                SOL_SOCKET, // level
                SO_KEEPALIVE, // optname
                reinterpret_cast<const char*>(&optval),
                optlen) != 0)
        {
            const auto gle = WSAGetLastError();
            PrintErrorIfFailed("setsockopt(SO_KEEPALIVE)", gle);
            return gle;
        }
    }

    if (g_configSettings->Options & SetRecvBuf)
    {
        const auto recvBuff = g_configSettings->RecvBufValue;
        if (::setsockopt(
                socket,
                SOL_SOCKET,
                SO_RCVBUF,
                reinterpret_cast<const char*>(&recvBuff),
                static_cast<int>(sizeof recvBuff)) != 0)
        {
            const auto gle = WSAGetLastError();
            PrintErrorIfFailed("setsockopt(SO_RCVBUF)", gle);
            return gle;
        }
    }

    if (g_configSettings->Options & SetSendBuf)
    {
        const auto sendBuff = g_configSettings->SendBufValue;
        if (::setsockopt(
                socket,
                SOL_SOCKET,
                SO_SNDBUF,
                reinterpret_cast<const char*>(&sendBuff),
                static_cast<int>(sizeof sendBuff)) != 0)
        {
            const auto gle = WSAGetLastError();
            PrintErrorIfFailed("setsockopt(SO_SNDBUF)", gle);
            return gle;
        }
    }

    if (g_configSettings->Options & NonBlockingIo)
    {
        u_long enableNonBlocking = 1;
        if (::ioctlsocket(socket, FIONBIO, &enableNonBlocking) != 0)
        {
            const auto gle = WSAGetLastError();
            PrintErrorIfFailed("ioctlsocket(FIONBIO)", gle);
            return gle;
        }
    }

    if (g_configSettings->Options & EnableCircularQueueing)
    {
        DWORD bytesReturned{};
        // ReSharper disable once CppTooWideScopeInitStatement
        const auto error = ::WSAIoctl(
            socket,
            SIO_ENABLE_CIRCULAR_QUEUEING,
            nullptr, 0, // in buffer
            nullptr, 0, // out buffer
            &bytesReturned,
            nullptr,
            nullptr);
        if (error != 0)
        {
            const auto gle = WSAGetLastError();
            PrintErrorIfFailed("WSAIoctl(SIO_ENABLE_CIRCULAR_QUEUEING)", gle);
            return gle;
        }
    }

    if (g_configSettings->Options & HandleInlineIocp)
    {
        if (!::SetFileCompletionNotificationModes(reinterpret_cast<HANDLE>(socket), FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) // NOLINT(performance-no-int-to-ptr)
        {
            const auto gle = GetLastError();
            PrintErrorIfFailed("SetFileCompletionNotificationModes(FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)", gle);
            return static_cast<int>(gle);
        }
    }

    return NO_ERROR;
}