Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/boost_process_compat.h → src/compat/boost_process.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* @file src/boost_process_compat.h
* @file src/compat/boost_process.h
* @brief Includes Boost.Process while isolating third-party deprecation diagnostics.
*/
#pragma once
Expand Down
36 changes: 36 additions & 0 deletions src/compat/moonlight.h
Comment thread
ReenigneArcher marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* @file src/compat/moonlight.h
* @brief Import Moonlight's C declarations without changing C++ errno definitions.
*/
#pragma once

// standard includes
// Load the CRT definitions before saving them, even when this is the first include.
#include <cerrno>

// PlatformSockets.h maps these names to Winsock values for Moonlight's C code.
// Let that code see its mappings, but do not leak them into Boost or the C++ library.
#ifdef _WIN32
#pragma push_macro("EAGAIN")
#pragma push_macro("EINTR")
#pragma push_macro("EWOULDBLOCK")
#pragma push_macro("EINPROGRESS")
#pragma push_macro("ETIMEDOUT")
#pragma push_macro("ECONNREFUSED")
#pragma push_macro("EMSGSIZE")
#endif

// lib includes
extern "C" {
#include <moonlight-common-c/src/Limelight-internal.h>
}

#ifdef _WIN32
#pragma pop_macro("EMSGSIZE")
#pragma pop_macro("ECONNREFUSED")
#pragma pop_macro("ETIMEDOUT")
#pragma pop_macro("EINPROGRESS")
#pragma pop_macro("EWOULDBLOCK")
#pragma pop_macro("EINTR")
#pragma pop_macro("EAGAIN")
#endif
2 changes: 1 addition & 1 deletion src/platform/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

// local includes
#ifndef _WIN32
#include "src/boost_process_compat.h"
#include "src/compat/boost_process.h"
#endif
#include "src/config.h"
#include "src/logging.h"
Expand Down
2 changes: 1 addition & 1 deletion src/platform/linux/misc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
// local includes
#include "graphics.h"
#include "misc.h"
#include "src/boost_process_compat.h"
#include "src/compat/boost_process.h"
#include "src/config.h"
#include "src/entry_handler.h"
#include "src/globals.h"
Expand Down
2 changes: 1 addition & 1 deletion src/platform/macos/misc.mm
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@

// local includes
#include "misc.h"
#include "src/boost_process_compat.h"
#include "src/compat/boost_process.h"
#include "src/config.h"
#include "src/entry_handler.h"
#include "src/logging.h"
Expand Down
2 changes: 1 addition & 1 deletion src/platform/windows/display_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

// local includes required before library includes
// Boost.Process must be included before MinHook pulls in Windows.h so Boost.Asio sees WinSock2.h first.
#include "src/boost_process_compat.h"
#include "src/compat/boost_process.h"

// lib includes
#include <boost/algorithm/string/join.hpp>
Expand Down
2 changes: 1 addition & 1 deletion src/platform/windows/misc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
#include <boost/range/algorithm/find_if.hpp>

// local includes required before platform includes
#include "src/boost_process_compat.h"
#include "src/compat/boost_process.h"

// platform includes
// prevent clang format from "optimizing" the header include order
Expand Down
2 changes: 1 addition & 1 deletion src/process.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#include "config.h"
#include "platform/common.h"
#include "rtsp.h"
#include "src/boost_process_compat.h"
#include "src/compat/boost_process.h"
#include "utility.h"

/**
Expand Down
3 changes: 2 additions & 1 deletion src/rtsp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
*/
#define BOOST_BIND_GLOBAL_PLACEHOLDERS

#include "compat/moonlight.h"

extern "C" {
#include <moonlight-common-c/src/Limelight-internal.h>
#include <moonlight-common-c/src/Rtsp.h>
}

Expand Down
7 changes: 2 additions & 5 deletions src/stream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,8 @@
#include <openssl/err.h>
#include <rs.h>

extern "C" {
// clang-format off
#include <moonlight-common-c/src/Limelight-internal.h>
// clang-format on
}
// Keep this separate so clang-format preserves the include order.
#include "compat/moonlight.h"

// local includes
#include "config.h"
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/test_external_commands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#include <vector>

// local includes
#include "src/boost_process_compat.h"
#include "src/compat/boost_process.h"
#include "src/platform/common.h"

// Test data structure for parameterized testing
Expand Down
69 changes: 69 additions & 0 deletions tests/unit/moonlight_common_first_include.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/**
* @file tests/unit/moonlight_common_first_include.cpp
* @brief Capture errno when the Moonlight wrapper is the first include in its translation unit.
*/

// local includes
#include <src/compat/moonlight.h>

namespace {
// Capture before any other include. Missing macros use zero only to keep a
// broken wrapper testable at runtime; the separate completeness flag must pass.
constexpr int errno_after_first_include[7] /* NOSONAR(cpp:S5945): No extra headers before the errno snapshot. */ {
#ifdef EAGAIN
EAGAIN,
#else
0,
#endif
#ifdef EINTR
EINTR,
#else
0,
#endif
#ifdef EWOULDBLOCK
EWOULDBLOCK,
#else
0,
#endif
#ifdef EINPROGRESS
EINPROGRESS,
#else
0,
#endif
#ifdef ETIMEDOUT
ETIMEDOUT,
#else
0,
#endif
#ifdef ECONNREFUSED
ECONNREFUSED,
#else
0,
#endif
#ifdef EMSGSIZE
EMSGSIZE
#else
0
#endif
}; ///< Errno values captured immediately after the first include.

#if defined(EAGAIN) && defined(EINTR) && defined(EWOULDBLOCK) && defined(EINPROGRESS) && defined(ETIMEDOUT) && defined(ECONNREFUSED) && defined(EMSGSIZE)
constexpr bool errno_complete = true; ///< Every required errno name was defined.
#else
constexpr bool errno_complete = false; ///< At least one required errno name was absent.
#endif
} // namespace

namespace moonlight_common_tests {
/**
* @brief Copy the first-include errno snapshot without sharing library types across translation units.
* @param values Destination for seven errno values.
* @return Whether all seven errno names were defined.
*/
bool first_include_errno(int *values) {
for (int index = 0; index < 7; ++index) {
values[index] = errno_after_first_include[index];
}
return errno_complete;
}
} // namespace moonlight_common_tests
111 changes: 111 additions & 0 deletions tests/unit/test_moonlight_common.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/**
* @file tests/unit/test_moonlight_common.cpp
* @brief Verify that importing Moonlight does not change C++ errno constants.
*/

// The shared test header includes Boost. Keep it after the errno snapshots and
// the explicit Boost include so it cannot mask this regression.

// standard includes
#include <array>
#include <cerrno>
Comment thread
ReenigneArcher marked this conversation as resolved.

namespace {
constexpr std::array<int, 7> errno_before_moonlight {
EAGAIN,
EINTR,
EWOULDBLOCK,
EINPROGRESS,
ETIMEDOUT,
ECONNREFUSED,
EMSGSIZE
}; ///< CRT errno values before including Moonlight.
}

// local includes
// Capture errno immediately after including Moonlight.
#include <src/compat/moonlight.h> // NOSONAR(cpp:S954): The baseline must precede this include.

namespace {
constexpr std::array<int, 7> errno_after_moonlight {
EAGAIN,
EINTR,
EWOULDBLOCK,
EINPROGRESS,
ETIMEDOUT,
ECONNREFUSED,
EMSGSIZE
}; ///< Errno values immediately after including Moonlight.
}

// lib includes
// Boost must be parsed after the wrapper for this regression test.
#include <boost/system/error_code.hpp>

// test includes
#include "../tests_common.h"

namespace moonlight_common_tests {
/**
* @brief Copy the first-include errno snapshot without sharing library types across translation units.
* @param values Destination for seven errno values in the baseline array's order.
* @return Whether all seven errno names were defined.
*/
bool first_include_errno(int *values);
} // namespace moonlight_common_tests

/**
* @brief Including Moonlight preserves the CRT errno values.
*/
TEST(MoonlightCommonTests, PreservesCrtErrno) {
EXPECT_EQ(errno_before_moonlight, errno_after_moonlight);
}

/**
* @brief Boost's error constants match the original CRT errno values.
*/
TEST(MoonlightCommonTests, PreservesBoostErrno) {
const std::array<int, 7> boost_errno {
boost::system::errc::resource_unavailable_try_again,
boost::system::errc::interrupted,
boost::system::errc::operation_would_block,
boost::system::errc::operation_in_progress,
boost::system::errc::timed_out,
boost::system::errc::connection_refused,
boost::system::errc::message_size
};
EXPECT_EQ(errno_before_moonlight, boost_errno);
}

/**
* @brief The wrapper initializes errno even when it is the first include.
*/
TEST(MoonlightCommonTests, FirstIncludePreservesCrtErrno) {
std::array<int, 7> first_include_values {};
EXPECT_TRUE(moonlight_common_tests::first_include_errno(first_include_values.data()));
EXPECT_EQ(errno_before_moonlight, first_include_values);
}

/**
* @brief Native connection-refused errors match Boost's generic condition.
*/
TEST(MoonlightCommonTests, ConnectionRefusedCondition) {
#ifdef _WIN32
const boost::system::error_code ec {WSAECONNREFUSED, boost::system::system_category()};
#else
const boost::system::error_code ec {ECONNREFUSED, boost::system::system_category()};
#endif
EXPECT_EQ(ec, boost::system::errc::connection_refused);
}

/**
* @brief Native timeouts match Boost's generic condition.
*/
TEST(MoonlightCommonTests, TimedOutCondition) {
#ifdef _WIN32
const boost::system::error_code ec {WSAETIMEDOUT, boost::system::system_category()};
#else
const boost::system::error_code ec {ETIMEDOUT, boost::system::system_category()};
#endif
EXPECT_EQ(ec, boost::system::errc::timed_out);
}