Я думаю, что столкнулся с проблемой повышения безопасности ASIO. Позвольте мне объяснить:
Контекст:
Я использую Boost 1.68 с G ++ 4.8.4 для Ubuntu 14.04
Я пишу код C ++ для создания сервера MJPEG.
Вот несколько примеров моего кода, его работа довольно проста:
Пояснения к коду
(1) Заполнение HTTP-заголовка
(2) Вызов doWrite с HandleMJPEG в качестве обратного вызова
(3) DoWrite вызывает async_write с HandleMJPEG в качестве обратного вызова
(4) HandleMJPEG:
(4.1) добавляет--jpegBoundary to stream
(4.2) обратные вызовы doWrite, которые снова вызывают HandleMJPEG (4.3)
Фактический код
void Connection::main()
{
streamInitReply(_reply); // (1)
doWrite(
std::bind(&net::Reply::toBuffers, _reply),
std::bind(&Connection::handleMJPEG, this),
"'MJPEG Stream init header'"); // (2)
}
void streamInitReply(net::Reply& rep)
{
rep.status = net::Reply::Status::ok;
rep.headers.clear();
rep.content.clear();
rep.headers.push_back(net::Header("Connection", "close"));
rep.headers.push_back(net::Header("Max-Age", "0"));
rep.headers.push_back(net::Header("Expires", "0"));
rep.headers.push_back(net::Header("Cache-Control", "no-cache"));
rep.headers.push_back(net::Header("Pragma", "no-cache"));
rep.headers.push_back(
net::Header(
"Content-Type",
(boost::format("multipart/x-mixed-replace; boundary=%1%") % jpegBoundary).str()
)
);
void Connection::handleMJPEG()
{
// Write Boundaries, then write the actual image buffer
// then recall handleMJPEG() to loop and keep writing incoming image
streamBoundariesReply(_reply); // (4.1)
auto self(shared_from_this());
doWrite( // (4.2)
std::bind(&net::Reply::contentToBuffers, _reply),
[this, self](){
imageReply(_server.getImage(), _reply);
doWrite(
std::bind(&net::Reply::toBuffersWithoutStatus, _reply),
std::bind(&Connection::handleMJPEG, this), // 4.3
"'MJPEG Image'"
);
},
"'MJPEG Boundary'"
);
}
void Connection::doWrite(
std::function<std::vector<boost::asio::const_buffer>()> toBuffer,
std::function<void()> callbackOnSuccess,
const std::string& logInfo)
{
auto self(shared_from_this());
boost::asio::async_write(
_socket,
toBuffer(),
boost::asio::bind_executor(strand_, [this, self, logInfo, callbackOnSuccess](const boost::system::error_code& ec, std::size_t)
{
if(ec != boost::system::errc::success)
{
doStop();
}
else
{
callbackOnSuccess(); // (3)
}
}
));
}
TL; DR
Проблема заключается в следующем: этот код работает как 90% времени. Иногда, когда я хочу увидеть поток в браузере (Firefox 66.0.3 для Linux), вместо отображения изображений появляется всплывающее окно «download».
Когда я исследую пакеты, кажется, что естькакой-то заголовок отсутствует или написан с ошибкой:
1 / когда все в порядке
2 / когда все не в порядке
Именно поэтому есть подозрение на проблему с поддержкой потоков в boost asio, но я не знаю, гдесмотреть на ...