* @brief Enables QoS on the given socket for traffic to the specified destination. * @param native_socket The native socket handle. * @param address The destination address for traffic sent on this socket. * @param port The destination port for traffic sent on this socket. * @param data_type The type of traffic sent on this socket. * @param dscp_tagging Specifies whether to enable D
| 1614 | * @param dscp_tagging Specifies whether to enable DSCP tagging on outgoing traffic. |
| 1615 | */ |
| 1616 | std::unique_ptr<deinit_t> enable_socket_qos(uintptr_t native_socket, boost::asio::ip::address &address, uint16_t port, qos_data_type_e data_type, bool dscp_tagging) { |
| 1617 | SOCKADDR_IN saddr_v4; |
| 1618 | SOCKADDR_IN6 saddr_v6; |
| 1619 | PSOCKADDR dest_addr; |
| 1620 | bool using_connect_hack = false; |
| 1621 | |
| 1622 | // Windows doesn't support any concept of traffic priority without DSCP tagging |
| 1623 | if (!dscp_tagging) { |
| 1624 | return nullptr; |
| 1625 | } |
| 1626 | |
| 1627 | static std::once_flag load_qwave_once_flag; |
| 1628 | std::call_once(load_qwave_once_flag, []() { |
| 1629 | // qWAVE is not installed by default on Windows Server, so we load it dynamically |
| 1630 | HMODULE qwave = LoadLibraryExA("qwave.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32); |
| 1631 | if (!qwave) { |
| 1632 | BOOST_LOG(debug) << "qwave.dll is not available on this OS"sv; |
| 1633 | return; |
| 1634 | } |
| 1635 | |
| 1636 | fn_QOSCreateHandle = (decltype(fn_QOSCreateHandle)) GetProcAddress(qwave, "QOSCreateHandle"); |
| 1637 | fn_QOSAddSocketToFlow = (decltype(fn_QOSAddSocketToFlow)) GetProcAddress(qwave, "QOSAddSocketToFlow"); |
| 1638 | fn_QOSRemoveSocketFromFlow = (decltype(fn_QOSRemoveSocketFromFlow)) GetProcAddress(qwave, "QOSRemoveSocketFromFlow"); |
| 1639 | |
| 1640 | if (!fn_QOSCreateHandle || !fn_QOSAddSocketToFlow || !fn_QOSRemoveSocketFromFlow) { |
| 1641 | BOOST_LOG(error) << "qwave.dll is missing exports?"sv; |
| 1642 | |
| 1643 | fn_QOSCreateHandle = nullptr; |
| 1644 | fn_QOSAddSocketToFlow = nullptr; |
| 1645 | fn_QOSRemoveSocketFromFlow = nullptr; |
| 1646 | |
| 1647 | FreeLibrary(qwave); |
| 1648 | return; |
| 1649 | } |
| 1650 | |
| 1651 | QOS_VERSION qos_version {1, 0}; |
| 1652 | if (!fn_QOSCreateHandle(&qos_version, &qos_handle)) { |
| 1653 | auto winerr = GetLastError(); |
| 1654 | BOOST_LOG(warning) << "QOSCreateHandle() failed: "sv << winerr; |
| 1655 | return; |
| 1656 | } |
| 1657 | }); |
| 1658 | |
| 1659 | // If qWAVE is unavailable, just return |
| 1660 | if (!fn_QOSAddSocketToFlow || !qos_handle) { |
| 1661 | return nullptr; |
| 1662 | } |
| 1663 | |
| 1664 | auto disconnect_fg = util::fail_guard([&]() { |
| 1665 | if (using_connect_hack) { |
| 1666 | SOCKADDR_IN6 empty = {}; |
| 1667 | empty.sin6_family = AF_INET6; |
| 1668 | if (connect((SOCKET) native_socket, (PSOCKADDR) &empty, sizeof(empty)) < 0) { |
| 1669 | auto wsaerr = WSAGetLastError(); |
| 1670 | BOOST_LOG(error) << "qWAVE dual-stack workaround failed: "sv << wsaerr; |
| 1671 | } |
| 1672 | } |
| 1673 | }); |
nothing calls this directly
no test coverage detected