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
+1 -1
View File
@@ -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)); stream::launch_session_raise(make_launch_session(host_audio, args));
tree.put("root.<xmlattr>.status_code", 200); 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); tree.put("root.resume", 1);
} }
+34 -9
View File
@@ -9,6 +9,7 @@ extern "C" {
} }
#include <array> #include <array>
#include <cctype>
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include <boost/bind.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 print_msg(PRTSP_MESSAGE msg);
void cmd_not_found(tcp::socket &sock, msg_t &&req); 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> { class socket_t : public std::enable_shared_from_this<socket_t> {
public: public:
@@ -77,11 +79,17 @@ public:
socket->sock.close(); socket->sock.close();
}); });
msg_t req { new msg_t::element_type }; msg_t req { new msg_t::element_type {} };
auto &incomplete = socket->incomplete; auto &incomplete = socket->incomplete;
if(incomplete.empty()) { 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) { for(auto option = req->options; option != nullptr; option = option->next) {
if("Content-length"sv == option->option) { if("Content-length"sv == option->option) {
@@ -89,8 +97,11 @@ public:
// If content_length > bytes read, then we need to store current data read, // If content_length > bytes read, then we need to store current data read,
// to be appended by the next read. // to be appended by the next read.
auto content_length = util::from_view(option->content); std::string_view content { option->content };
if(content_length <= bytes) { 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; break;
} }
@@ -112,7 +123,17 @@ public:
std::copy_n(socket->msg_buf.data(), bytes, std::begin(incomplete) + incomplete_size); 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()); print_msg(req.get());
@@ -128,8 +149,10 @@ public:
tcp::socket sock; tcp::socket sock;
std::vector<char> incomplete; std::vector<char> incomplete;
std::size_t content_length = std::numeric_limits<std::size_t>::max();
std::array<char, 1024> msg_buf; std::array<char, 1024> msg_buf;
}; };
@@ -152,6 +175,8 @@ public:
return -1; return -1;
} }
acceptor.set_option(boost::asio::socket_base::reuse_address { true });
acceptor.bind(tcp::endpoint(tcp::v4(), port), ec); acceptor.bind(tcp::endpoint(tcp::v4(), port), ec);
if(ec) { if(ec) {
return -1; 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] = config.audio.flags[audio::config_t::HIGH_QUALITY] =
util::from_view(args.at("x-nv-audio.surround.AudioQuality"sv)); util::from_view(args.at("x-nv-audio.surround.AudioQuality"sv));
config.controlProtocolType = util::from_view(args.at("x-nv-general.useReliableUdp"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.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.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.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.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)); config.monitor.width = util::from_view(args.at("x-nv-video[0].clientViewportWd"sv));
+1 -1
View File
@@ -139,7 +139,7 @@ std::unique_ptr<platf::deinit_t> start() {
auto wm_http = std::to_string(map_port(confighttp::PORT_HTTPS)); auto wm_http = std::to_string(map_port(confighttp::PORT_HTTPS));
std::vector<mapping_t> mappings { 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 }, { video, video, "Video stream port"s, false },
{ audio, audio, "Control stream port"s, false }, { audio, audio, "Control stream port"s, false },
{ control, control, "Audio stream port"s, false }, { control, control, "Audio stream port"s, false },