Handle RTSP packets that are broken up in more than two pieces
This commit is contained in:
+1
-1
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+30
-5
@@ -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;
|
||||||
|
|||||||
+1
-1
@@ -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 },
|
||||||
|
|||||||
Reference in New Issue
Block a user