X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fcommon%2Fcompressor.cpp;fp=src%2Fcommon%2Fcompressor.cpp;h=df08f93d9f3ae74a5fdca06c1b0af0bb35da3459;hp=816f26c8519784b3ea147acf5fd11ef360753473;hb=c1cf157116de7fc3da96203aa6f03c38c7ebb650;hpb=30b159cb876a9495de42e9a3e70ca050516f0805 diff --git a/src/common/compressor.cpp b/src/common/compressor.cpp index 816f26c8..df08f93d 100644 --- a/src/common/compressor.cpp +++ b/src/common/compressor.cpp @@ -23,15 +23,15 @@ #include #include -const int maxBufferSize = 64 * 1024 * 1024; // protect us from zip bombs -const int ioBufferSize = 64 * 1024; // chunk size for inflate/deflate; should not be too large as we preallocate that space! - -Compressor::Compressor(QTcpSocket *socket, Compressor::CompressionLevel level, QObject *parent) - : QObject(parent), - _socket(socket), - _level(level), - _inflater(nullptr), - _deflater(nullptr) +const int maxBufferSize = 64 * 1024 * 1024; // protect us from zip bombs +const int ioBufferSize = 64 * 1024; // chunk size for inflate/deflate; should not be too large as we preallocate that space! + +Compressor::Compressor(QTcpSocket* socket, Compressor::CompressionLevel level, QObject* parent) + : QObject(parent) + , _socket(socket) + , _level(level) + , _inflater(nullptr) + , _deflater(nullptr) { connect(socket, &QIODevice::readyRead, this, &Compressor::readData); @@ -51,7 +51,6 @@ Compressor::Compressor(QTcpSocket *socket, Compressor::CompressionLevel level, Q QTimer::singleShot(0, this, &Compressor::readData); } - Compressor::~Compressor() { // release resources allocated by zlib @@ -65,19 +64,18 @@ Compressor::~Compressor() } } - bool Compressor::initStreams() { int zlevel; - switch(compressionLevel()) { - case BestCompression: - zlevel = 9; - break; - case BestSpeed: - zlevel = 1; - break; - default: - zlevel = Z_DEFAULT_COMPRESSION; + switch (compressionLevel()) { + case BestCompression: + zlevel = 9; + break; + case BestSpeed: + zlevel = 1; + break; + default: + zlevel = Z_DEFAULT_COMPRESSION; } _inflater = new z_stream; @@ -94,23 +92,20 @@ bool Compressor::initStreams() return false; } - _inputBuffer.reserve(ioBufferSize); // pre-allocate space - _outputBuffer.resize(ioBufferSize); // not a typo; we never change the size of this buffer anyway (we *do* for _inputBuffer!) + _inputBuffer.reserve(ioBufferSize); // pre-allocate space + _outputBuffer.resize(ioBufferSize); // not a typo; we never change the size of this buffer anyway (we *do* for _inputBuffer!) qDebug() << "Enabling compression..."; return true; } - - qint64 Compressor::bytesAvailable() const { return _readBuffer.size(); } - -qint64 Compressor::read(char *data, qint64 maxSize) +qint64 Compressor::read(char* data, qint64 maxSize) { if (maxSize <= 0) maxSize = _readBuffer.size(); @@ -131,11 +126,10 @@ qint64 Compressor::read(char *data, qint64 maxSize) return n; } - // The usual usage pattern is to write a blocksize first, followed by the actual data. // By setting NoFlush, one can indicate that the write buffer should not immediately be // written, which should make things a bit more efficient. -qint64 Compressor::write(const char *data, qint64 count, WriteBufferHint flush) +qint64 Compressor::write(const char* data, qint64 count, WriteBufferHint flush) { int pos = _writeBuffer.size(); _writeBuffer.resize(pos + count); @@ -147,11 +141,10 @@ qint64 Compressor::write(const char *data, qint64 count, WriteBufferHint flush) return count; } - void Compressor::readData() { // don't try to read more data if we're already closing - if (_socket->state() != QAbstractSocket::ConnectedState) + if (_socket->state() != QAbstractSocket::ConnectedState) return; if (!_socket->bytesAvailable() || _readBuffer.size() >= maxBufferSize) @@ -173,17 +166,17 @@ void Compressor::readData() _readBuffer.resize(_readBuffer.size() + ioBufferSize); _inputBuffer.append(_socket->read(ioBufferSize - _inputBuffer.size())); - _inflater->next_in = reinterpret_cast(_inputBuffer.data()); + _inflater->next_in = reinterpret_cast(_inputBuffer.data()); _inflater->avail_in = _inputBuffer.size(); - _inflater->next_out = reinterpret_cast(_readBuffer.data() + _readBuffer.size() - ioBufferSize); + _inflater->next_out = reinterpret_cast(_readBuffer.data() + _readBuffer.size() - ioBufferSize); _inflater->avail_out = ioBufferSize; - const unsigned char *orig_out = _inflater->next_out; // so we see if we have actually produced any output + const unsigned char* orig_out = _inflater->next_out; // so we see if we have actually produced any output - int status = inflate(_inflater, Z_SYNC_FLUSH); // get as much data as possible + int status = inflate(_inflater, Z_SYNC_FLUSH); // get as much data as possible // adjust input and output buffers - _readBuffer.resize(_inflater->next_out - reinterpret_cast(_readBuffer.data())); + _readBuffer.resize(_inflater->next_out - reinterpret_cast(_readBuffer.data())); if (_inflater->avail_in > 0) memmove(_inputBuffer.data(), _inflater->next_in, _inflater->avail_in); _inputBuffer.resize(_inflater->avail_in); @@ -191,29 +184,28 @@ void Compressor::readData() if (_inflater->next_out != orig_out) emit readyRead(); - switch(status) { - case Z_NEED_DICT: - case Z_DATA_ERROR: - case Z_MEM_ERROR: - case Z_STREAM_ERROR: - qWarning() << "Error while decompressing stream:" << status; - emit error(StreamError); - return; - case Z_BUF_ERROR: - // means that we need more input to continue, so this is not an actual error - return; - case Z_STREAM_END: - qWarning() << "Reached end of zlib stream!"; // this should really never happen - return; - default: - // just try to get more out of the stream - break; + switch (status) { + case Z_NEED_DICT: + case Z_DATA_ERROR: + case Z_MEM_ERROR: + case Z_STREAM_ERROR: + qWarning() << "Error while decompressing stream:" << status; + emit error(StreamError); + return; + case Z_BUF_ERROR: + // means that we need more input to continue, so this is not an actual error + return; + case Z_STREAM_END: + qWarning() << "Reached end of zlib stream!"; // this should really never happen + return; + default: + // just try to get more out of the stream + break; } } - //qDebug() << "inflate in:" << _inflater->total_in << "out:" << _inflater->total_out << "ratio:" << (double)_inflater->total_in/_inflater->total_out; + // qDebug() << "inflate in:" << _inflater->total_in << "out:" << _inflater->total_out << "ratio:" << (double)_inflater->total_in/_inflater->total_out; } - void Compressor::writeData() { if (compressionLevel() == NoCompression) { @@ -222,12 +214,12 @@ void Compressor::writeData() return; } - _deflater->next_in = reinterpret_cast(_writeBuffer.data()); + _deflater->next_in = reinterpret_cast(_writeBuffer.data()); _deflater->avail_in = _writeBuffer.size(); int status; do { - _deflater->next_out = reinterpret_cast(_outputBuffer.data()); + _deflater->next_out = reinterpret_cast(_outputBuffer.data()); _deflater->avail_out = ioBufferSize; status = deflate(_deflater, Z_PARTIAL_FLUSH); if (status != Z_OK && status != Z_BUF_ERROR) { @@ -237,14 +229,14 @@ void Compressor::writeData() } if (_deflater->avail_out == static_cast(ioBufferSize)) - continue; // nothing to write here + continue; // nothing to write here if (!_socket->write(_outputBuffer.constData(), ioBufferSize - _deflater->avail_out)) { qWarning() << "Error while writing to socket:" << _socket->errorString(); emit error(DeviceError); return; } - } while (_deflater->avail_out == 0); // the output buffer being full is the only reason we should have to loop here! + } while (_deflater->avail_out == 0); // the output buffer being full is the only reason we should have to loop here! if (_deflater->avail_in > 0) { qWarning() << "Oops, something weird happened: data still remaining in write buffer!"; @@ -253,10 +245,9 @@ void Compressor::writeData() _writeBuffer.resize(0); - //qDebug() << "deflate in:" << _deflater->total_in << "out:" << _deflater->total_out << "ratio:" << (double)_deflater->total_out/_deflater->total_in; + // qDebug() << "deflate in:" << _deflater->total_in << "out:" << _deflater->total_out << "ratio:" << (double)_deflater->total_out/_deflater->total_in; } - void Compressor::flush() { if (compressionLevel() == NoCompression && _socket->state() == QAbstractSocket::ConnectedState)