OpenMiner/source/common/network/CompressedPacket.cpp
2020-05-15 00:27:12 +02:00

101 lines
3.4 KiB
C++

/*
* =====================================================================================
*
* OpenMiner
*
* Copyright (C) 2018-2020 Unarelith, Quentin Bazin <openminer@unarelith.net>
* Copyright (C) 2019-2020 the OpenMiner contributors (see CONTRIBUTORS.md)
*
* This file is part of OpenMiner.
*
* OpenMiner is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* OpenMiner 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with OpenMiner; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* =====================================================================================
*/
#include <cassert>
#include <gk/core/Debug.hpp>
#include "CompressedPacket.hpp"
// Note: This class was implemented thanks to this SFML forum topic:
// https://en.sfml-dev.org/forums/index.php?topic=14344.0
const void* CompressedPacket::onSend(std::size_t& size) {
// We only support data with a maximum size of
// an unsigned short (so the size can be sent
// in the first two bytes of the packet)
assert(size <= 65535);
// Cast the data to a bytef pointer
const Bytef* srcData = static_cast<const Bytef*>(getData());
// Get the size of the packet to send
uLong srcSize = getDataSize();
// Compute the size of the compressed data
uLong dstSize = compressBound(srcSize);
// Resize the vector to accomodate the compressed data,
// plus two bytes for our uncompressed size
m_compressionBuffer.resize(dstSize + 2);
// Take the first 8 bytes of srcSize
m_compressionBuffer[0] = srcSize & 0xFF;
// And the second 8 bytes
m_compressionBuffer[1] = (srcSize >> 8) & 0xFF;
// Compress the data into the rest of the buffer
int result = compress(m_compressionBuffer.data() + 2, &dstSize, srcData, srcSize);
if (result != Z_OK)
gkError() << "Failed to compress packet";
// Set the size to the compressed size plus
// two bytes for the size marker
size = (dstSize + 2);
// Return data to send
return m_compressionBuffer.data();
}
void CompressedPacket::onReceive(const void* data, std::size_t size) {
// Cast the data to Bytef*, the format zlib deals with
const Bytef* srcData = static_cast<const Bytef*>(data);
// Extract the uncompressed data size from the first two
// bytes in the packet so we can use it for the buffer
sf::Uint16 uncompressedSize = srcData[1] << 8 | srcData[0];
// Resize the vector to accomodate the uncompressed data
m_compressionBuffer.resize(uncompressedSize);
// Declare a variable for the destination size
uLong dstSize = uncompressedSize;
// Uncompress the data (remove the first two bytes)
int result = uncompress(m_compressionBuffer.data(), &dstSize, (srcData + 2), size - 2);
if (result != Z_OK)
gkError() << "Failed to uncompress packet";
// Assert that the uncompressed size is the same as the
// size we were sent for the buffer
assert(dstSize == uncompressedSize);
// Append it to the packet
append(m_compressionBuffer.data(), dstSize);
}