Handle RTSP packets that are broken up in more than two pieces

This commit is contained in:
loki 2021-07-04 18:57:55 +02:00
parent 616f62fb9f
commit 136e9c43a5
3 changed files with 36 additions and 11 deletions

@ -721,7 +721,7 @@ void resume(bool &host_audio, resp_https_t response, req_https_t request) {
stream::launch_session_raise(make_launch_session(host_audio, args));
tree.put("root.<xmlattr>.status_code", 200);
tree.put("root.sessionUrl0", "rtspru://"s + request->local_endpoint_address() + ':' + std::to_string(map_port(stream::RTSP_SETUP_PORT)));
tree.put("root.sessionUrl0", "rtsp://"s + request->local_endpoint_address() + ':' + std::to_string(map_port(stream::RTSP_SETUP_PORT)));
tree.put("root.resume", 1);
}

@ -9,6 +9,7 @@ extern "C" {
}
#include <array>
#include <cctype>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
@ -42,6 +43,7 @@ using cmd_func_t = std::function<void(rtsp_server_t *server, tcp::socket &, msg_
void print_msg(PRTSP_MESSAGE msg);
void cmd_not_found(tcp::socket &sock, msg_t &&req);
void respond(tcp::socket &sock, POPTION_ITEM options, int statuscode, const char *status_msg, int seqn, const std::string_view &payload);
class socket_t : public std::enable_shared_from_this<socket_t> {
public:
@ -77,11 +79,17 @@ public:
socket->sock.close();
});
msg_t req { new msg_t::element_type };
msg_t req { new msg_t::element_type {} };
auto &incomplete = socket->incomplete;
if(incomplete.empty()) {
parseRtspMessage(req.get(), socket->msg_buf.data(), bytes);
if(auto status = parseRtspMessage(req.get(), socket->msg_buf.data(), bytes)) {
BOOST_LOG(error) << "Malformed RTSP message: ["sv << status << ']';
respond(socket->sock, nullptr, 400, "BAD REQUEST", req->sequenceNumber, {});
return;
}
for(auto option = req->options; option != nullptr; option = option->next) {
if("Content-length"sv == option->option) {
@ -89,8 +97,11 @@ public:
// If content_length > bytes read, then we need to store current data read,
// to be appended by the next read.
auto content_length = util::from_view(option->content);
if(content_length <= bytes) {
std::string_view content { option->content };
auto begin = std::find_if(std::begin(content), std::end(content), [](auto ch) { return (bool)std::isdigit(ch); });
socket->content_length = util::from_chars(begin, std::end(content));
if(socket->content_length <= bytes + incomplete.size()) {
break;
}
@ -112,7 +123,17 @@ public:
std::copy_n(socket->msg_buf.data(), bytes, std::begin(incomplete) + incomplete_size);
parseRtspMessage(req.get(), incomplete.data(), incomplete.size());
if(incomplete.size() < socket->content_length) {
fg.disable();
return;
}
if(auto status = parseRtspMessage(req.get(), incomplete.data(), incomplete.size())) {
BOOST_LOG(error) << "Malformed RTSP message: ["sv << status << ']';
respond(socket->sock, nullptr, 400, "BAD REQUEST", req->sequenceNumber, {});
return;
}
}
print_msg(req.get());
@ -128,8 +149,10 @@ public:
tcp::socket sock;
std::vector<char> incomplete;
std::size_t content_length = std::numeric_limits<std::size_t>::max();
std::array<char, 1024> msg_buf;
};
@ -152,6 +175,8 @@ public:
return -1;
}
acceptor.set_option(boost::asio::socket_base::reuse_address { true });
acceptor.bind(tcp::endpoint(tcp::v4(), port), ec);
if(ec) {
return -1;
@ -532,10 +557,10 @@ void cmd_announce(rtsp_server_t *server, tcp::socket &sock, msg_t &&req) {
config.audio.flags[audio::config_t::HIGH_QUALITY] =
util::from_view(args.at("x-nv-audio.surround.AudioQuality"sv));
config.controlProtocolType = util::from_view(args.at("x-nv-general.useReliableUdp"sv));
config.packetsize = util::from_view(args.at("x-nv-video[0].packetSize"sv));
config.minRequiredFecPackets = util::from_view(args.at("x-nv-vqos[0].fec.minRequiredFecPackets"sv));
config.featureFlags = util::from_view(args.at("x-nv-general.featureFlags"sv));
config.controlProtocolType = util::from_view(args.at("x-nv-general.useReliableUdp"sv));
config.packetsize = util::from_view(args.at("x-nv-video[0].packetSize"sv));
config.minRequiredFecPackets = util::from_view(args.at("x-nv-vqos[0].fec.minRequiredFecPackets"sv));
config.featureFlags = util::from_view(args.at("x-nv-general.featureFlags"sv));
config.monitor.height = util::from_view(args.at("x-nv-video[0].clientViewportHt"sv));
config.monitor.width = util::from_view(args.at("x-nv-video[0].clientViewportWd"sv));

@ -139,7 +139,7 @@ std::unique_ptr<platf::deinit_t> start() {
auto wm_http = std::to_string(map_port(confighttp::PORT_HTTPS));
std::vector<mapping_t> mappings {
{ rtsp, rtsp, "RTSP setup port"s, false },
{ rtsp, rtsp, "RTSP setup port"s, true },
{ video, video, "Video stream port"s, false },
{ audio, audio, "Control stream port"s, false },
{ control, control, "Audio stream port"s, false },