src/iohandler/io_handler_chainer.cc
Rama master · réplica de lectura del repositorio original.
/*MT*
MediaTomb - http://www.mediatomb.cc/
io_handler_chainer.cc - this file is part of MediaTomb.
Copyright (C) 2005 Gena Batyan <bgeradz@mediatomb.cc>,
Sergey 'Jin' Bostandzhyan <jin@mediatomb.cc>
Copyright (C) 2006-2010 Gena Batyan <bgeradz@mediatomb.cc>,
Sergey 'Jin' Bostandzhyan <jin@mediatomb.cc>,
Leonhard Wimmer <leo@mediatomb.cc>
Copyright (C) 2016-2026 Gerbera Contributors
MediaTomb is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2
as published by the Free Software Foundation.
MediaTomb is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
version 2 along with MediaTomb; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
$Id$
*/
/// @file iohandler/io_handler_chainer.cc
#define GRB_LOG_FAC GrbLogFacility::iohandler
#include "io_handler_chainer.h" // API
#include "exceptions.h"
#include "util/logger.h"
#include <thread>
IOHandlerChainer::IOHandlerChainer(
std::unique_ptr<IOHandler> readFrom,
std::unique_ptr<IOHandler> writeTo,
unsigned int chunkSize)
{
if (chunkSize == 0)
throw_std_runtime_error("chunkSize {} must be positive", chunkSize);
if (!readFrom || !writeTo)
throw_std_runtime_error("readFrom and writeTo need to be set");
readFrom->open(UPNP_READ);
this->chunkSize = chunkSize;
this->readFrom = std::move(readFrom);
this->writeTo = std::move(writeTo);
buf = new std::byte[chunkSize];
startThread();
}
void IOHandlerChainer::threadProc()
{
try {
bool again;
do {
try {
writeTo->open(UPNP_WRITE);
again = false;
} catch (const TryAgainException&) {
again = true;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
} while (!threadShutdownCheck() && again);
bool stopLoop = false;
while (!threadShutdownCheck() && !stopLoop) {
int numRead = readFrom->read(buf, chunkSize);
if (numRead == 0) {
status = IOHC_NORMAL_SHUTDOWN;
stopLoop = true;
} else if (numRead < 0) {
status = IOHC_READ_ERROR;
stopLoop = true;
} else {
int numWritten = 0;
while (!threadShutdownCheck() && numWritten == 0 && !stopLoop) {
numWritten = writeTo->write(buf, numRead);
if (numWritten != 0 && numWritten != numRead) {
status = IOHC_WRITE_ERROR;
stopLoop = true;
}
}
}
}
} catch (const std::runtime_error& e) {
log_debug("{}", EX(e));
status = IOHC_EXCEPTION;
}
try {
if (threadShutdownCheck())
status = IOHC_FORCED_SHUTDOWN;
readFrom->close();
writeTo->close();
} catch (const std::runtime_error& e) {
log_debug("{}", EX(e));
status = IOHC_EXCEPTION;
}
}