mirror of
https://github.com/LizardByte/Sunshine.git
synced 2026-10-23 03:28:06 +09:00
102 lines
3.2 KiB
C++
102 lines
3.2 KiB
C++
/**
|
|
* @file tests/unit/test_rtsp.cpp
|
|
* @brief Verify RTSP response handlers through their common dispatcher signature.
|
|
*/
|
|
|
|
// standard includes
|
|
#include <array>
|
|
#include <string>
|
|
#include <utility>
|
|
|
|
// lib includes
|
|
#include <boost/asio.hpp>
|
|
extern "C" {
|
|
#include <moonlight-common-c/src/Rtsp.h>
|
|
}
|
|
|
|
// test includes
|
|
#include "../tests_common.h"
|
|
|
|
// local includes
|
|
#include <src/rtsp.h>
|
|
|
|
namespace rtsp_stream {
|
|
class rtsp_server_t;
|
|
|
|
/**
|
|
* @brief Release a parsed RTSP message and its allocation.
|
|
* @param message Message to release.
|
|
*/
|
|
void free_msg(PRTSP_MESSAGE message);
|
|
|
|
/**
|
|
* @brief Owning RTSP message type used by the dispatcher.
|
|
*/
|
|
using msg_t = util::safe_ptr<RTSP_MESSAGE, &free_msg>;
|
|
|
|
/**
|
|
* @brief Respond to OPTIONS through the common dispatcher signature.
|
|
* @param sock Connected client socket.
|
|
* @param session Launch session.
|
|
* @param req Request to handle.
|
|
*/
|
|
void cmd_option(rtsp_server_t *, boost::asio::ip::tcp::socket &sock, launch_session_t &session, msg_t &&req);
|
|
|
|
/**
|
|
* @brief Respond to DESCRIBE through the common dispatcher signature.
|
|
* @param sock Connected client socket.
|
|
* @param session Launch session.
|
|
* @param req Request to handle.
|
|
*/
|
|
void cmd_describe(rtsp_server_t *, boost::asio::ip::tcp::socket &sock, launch_session_t &session, msg_t &&req);
|
|
|
|
/**
|
|
* @brief Respond to PLAY through the common dispatcher signature.
|
|
* @param sock Connected client socket.
|
|
* @param session Launch session.
|
|
* @param req Request to handle.
|
|
*/
|
|
void cmd_play(rtsp_server_t *, boost::asio::ip::tcp::socket &sock, launch_session_t &session, msg_t &&req);
|
|
} // namespace rtsp_stream
|
|
|
|
/**
|
|
* @brief All three handlers respond with the request's sequence even without a server instance.
|
|
*/
|
|
TEST(RtspResponseTest, CommonDispatcherPreservesResponsesWithoutServerContext) {
|
|
using boost::asio::ip::tcp;
|
|
const std::array handlers {
|
|
&rtsp_stream::cmd_option,
|
|
&rtsp_stream::cmd_describe,
|
|
&rtsp_stream::cmd_play,
|
|
};
|
|
|
|
for (const auto handler : handlers) {
|
|
boost::asio::io_context io;
|
|
tcp::acceptor acceptor {io, {boost::asio::ip::address_v4::loopback(), 0}};
|
|
tcp::socket client {io};
|
|
client.connect(acceptor.local_endpoint());
|
|
auto server_socket = acceptor.accept();
|
|
|
|
rtsp_stream::launch_session_t session {};
|
|
rtsp_stream::msg_t request {new RTSP_MESSAGE {}};
|
|
request->sequenceNumber = 42;
|
|
handler(nullptr, server_socket, session, std::move(request));
|
|
server_socket.shutdown(tcp::socket::shutdown_send);
|
|
|
|
std::string response;
|
|
boost::system::error_code read_error;
|
|
boost::asio::read(client, boost::asio::dynamic_buffer(response), read_error);
|
|
ASSERT_EQ(read_error, boost::asio::error::eof);
|
|
EXPECT_TRUE(response.starts_with("RTSP/1.0 200 OK\r\n"));
|
|
EXPECT_NE(response.find("CSeq: 42\r\n"), std::string::npos);
|
|
|
|
if (handler == &rtsp_stream::cmd_describe) {
|
|
EXPECT_NE(response.find("a=x-ss-general.featureFlags:"), std::string::npos);
|
|
EXPECT_NE(response.find("a=x-ss-general.encryptionSupported:"), std::string::npos);
|
|
EXPECT_NE(response.find("a=fmtp:97 surround-params="), std::string::npos);
|
|
} else {
|
|
EXPECT_TRUE(response.ends_with("\r\n\r\n"));
|
|
}
|
|
}
|
|
}
|