mirror of
https://github.com/tswow/tswow
synced 2026-08-14 20:29:06 -04:00
288 lines
6.1 KiB
C++
288 lines
6.1 KiB
C++
#include "CustomPacketBase.h"
|
|
|
|
#include <string>
|
|
#include <stdexcept>
|
|
|
|
CustomPacketBase::CustomPacketBase(CustomPacketBase const& base)
|
|
: m_size(base.m_size)
|
|
, m_maxChunkSize(base.m_maxChunkSize)
|
|
, m_idx(0)
|
|
, m_global_idx(0)
|
|
, m_chunk(0)
|
|
, m_chunks(base.m_chunks)
|
|
, m_opcode(base.m_opcode)
|
|
{}
|
|
|
|
CustomPacketBase::CustomPacketBase()
|
|
: m_size(0)
|
|
, m_maxChunkSize(0)
|
|
, m_idx(0)
|
|
, m_global_idx(0)
|
|
, m_chunk(0)
|
|
, m_opcode(0)
|
|
{}
|
|
|
|
CustomPacketBase::CustomPacketBase(
|
|
opcode_t opcode
|
|
, chunkSize_t maxChunkSize
|
|
, totalSize_t initialSize
|
|
)
|
|
: m_size(0)
|
|
, m_idx(0)
|
|
, m_global_idx(0)
|
|
, m_chunk(0)
|
|
, m_maxChunkSize(maxChunkSize)
|
|
, m_opcode(opcode)
|
|
{
|
|
if (maxChunkSize <= CustomHeaderSize)
|
|
{
|
|
throw std::runtime_error(
|
|
"Maximum chunk size ("
|
|
+ std::to_string(maxChunkSize)
|
|
+ ") is <= message header size ("
|
|
+ std::to_string(CustomHeaderSize)
|
|
+ "), you can't send any messages!"
|
|
);
|
|
}
|
|
|
|
if (initialSize > 0)
|
|
{
|
|
Increase(initialSize);
|
|
}
|
|
}
|
|
|
|
std::vector<CustomPacketChunk> & CustomPacketBase::buildMessages()
|
|
{
|
|
for (chunkCount_t i = 0; i < m_chunks.size(); ++i)
|
|
{
|
|
CustomPacketChunk& chnk = m_chunks[i];
|
|
CustomPacketHeader* hdr = chnk.Header();
|
|
hdr->opcode = m_opcode;
|
|
hdr->fragmentId = i;
|
|
hdr->totalFrags = chunkCount_t(m_chunks.size());
|
|
}
|
|
return m_chunks;
|
|
}
|
|
|
|
void CustomPacketBase::Reset()
|
|
{
|
|
m_chunk = 0;
|
|
m_idx = 0;
|
|
m_global_idx = 0;
|
|
m_size = 0;
|
|
}
|
|
|
|
void CustomPacketBase::Destroy()
|
|
{
|
|
for (auto& chunk : m_chunks)
|
|
{
|
|
chunk.Destroy();
|
|
}
|
|
m_chunks.clear();
|
|
Reset();
|
|
}
|
|
|
|
void CustomPacketBase::Push(CustomPacketChunk& chnk)
|
|
{
|
|
m_size += chnk.Size();
|
|
m_chunks.push_back(chnk);
|
|
}
|
|
|
|
|
|
totalSize_t CustomPacketBase::Size()
|
|
{
|
|
return m_size;
|
|
}
|
|
|
|
|
|
CustomPacketChunk* CustomPacketBase::Chunk(chunkCount_t index)
|
|
{
|
|
return &m_chunks[index];
|
|
}
|
|
|
|
|
|
chunkSize_t CustomPacketBase::ChunkSize(chunkCount_t index)
|
|
{
|
|
return m_chunks[index].Size();
|
|
}
|
|
|
|
|
|
chunkCount_t CustomPacketBase::ChunkCount()
|
|
{
|
|
return chunkCount_t(m_chunks.size());
|
|
}
|
|
|
|
void CustomPacketBase::Print(
|
|
std::function<void(std::ostream&, uint8_t)> cb
|
|
, std::ostream& stream
|
|
) {
|
|
stream << "message [\n";
|
|
for (size_t chnkCtr = 0; chnkCtr < m_chunks.size(); ++chnkCtr)
|
|
{
|
|
CustomPacketChunk& chnk = m_chunks[chnkCtr];
|
|
chnk.Print(cb, stream, 2);
|
|
}
|
|
stream << "]\n";
|
|
}
|
|
|
|
|
|
void CustomPacketBase::PrintAscii(std::ostream& stream)
|
|
{
|
|
Print([](auto& stream, uint8_t byte) {
|
|
stream << char(byte);
|
|
}, stream);
|
|
}
|
|
|
|
void CustomPacketBase::PrintBytes(std::ostream& stream)
|
|
{
|
|
Print([](auto& stream, uint8_t byte) {
|
|
stream << "0x" << std::hex << uint32_t(byte);
|
|
}, stream);
|
|
}
|
|
|
|
|
|
|
|
|
|
chunkSize_t CustomPacketBase::MaxWritableChunkSize()
|
|
{
|
|
return m_maxChunkSize - CustomHeaderSize;
|
|
}
|
|
|
|
void CustomPacketBase::Increase(totalSize_t increase)
|
|
{
|
|
// increase size
|
|
if (m_chunks.size() > 0)
|
|
{
|
|
CustomPacketChunk& chnk = m_chunks[m_chunks.size() - 1];
|
|
chunkSize_t inc = std::min(
|
|
uint32_t(chnk.Size() + increase)
|
|
, uint32_t(MaxWritableChunkSize())
|
|
);
|
|
if (inc > 0)
|
|
{
|
|
chnk.Increase(inc);
|
|
}
|
|
}
|
|
|
|
totalSize_t newSize = m_size + increase;
|
|
chunkCount_t firstNewChunk = chunkCount_t(m_chunks.size());
|
|
m_chunks.resize(
|
|
chunkCount_t(std::ceil(double(newSize) / double(MaxWritableChunkSize())))
|
|
);
|
|
chunkCount_t remInc = newSize;
|
|
for (chunkCount_t i = firstNewChunk; i < m_chunks.size(); ++i)
|
|
{
|
|
chunkSize_t size = i == (m_chunks.size() - 1)
|
|
? remInc
|
|
: MaxWritableChunkSize();
|
|
remInc -= size;
|
|
m_chunks[i] = CustomPacketChunk(size);
|
|
}
|
|
m_size = newSize;
|
|
}
|
|
|
|
void CustomPacketBase::WriteBytes(totalSize_t size, char const* bytes)
|
|
{
|
|
while (size > 0)
|
|
{
|
|
if (m_chunk >= m_chunks.size())
|
|
{
|
|
chunkSize_t inc = chunkSize_t(
|
|
std::min(uint32_t(size)
|
|
, uint32_t(MaxWritableChunkSize()))
|
|
);
|
|
m_size += inc;
|
|
m_chunks.push_back(CustomPacketChunk(inc));
|
|
} else if (m_idx == MaxWritableChunkSize()) {
|
|
m_chunk++;
|
|
m_idx = 0;
|
|
continue;
|
|
}
|
|
|
|
CustomPacketChunk& chnk = m_chunks[m_chunk];
|
|
if (size >= chnk.RemBytes(m_idx))
|
|
{
|
|
totalSize_t inc = std::min(
|
|
uint32_t(size-chnk.RemBytes(m_idx))
|
|
, uint32_t(MaxWritableChunkSize()-chnk.Size())
|
|
);
|
|
chnk.Increase(inc);
|
|
m_size += inc;
|
|
}
|
|
|
|
totalSize_t written = chunkSize_t(
|
|
std::min(totalSize_t(chnk.RemBytes(m_idx)), size)
|
|
);
|
|
|
|
chnk.WriteBytes(m_idx, written, bytes);
|
|
bytes += written;
|
|
size -= written;
|
|
if (size == 0)
|
|
{
|
|
incIdx(written);
|
|
}
|
|
else
|
|
{
|
|
m_idx = 0;
|
|
++m_chunk;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CustomPacketBase::ReadBytes(totalSize_t size, char* bytes)
|
|
{
|
|
if (m_size - m_global_idx < size)
|
|
{
|
|
return;
|
|
}
|
|
totalSize_t offset = 0;
|
|
while (size > 0)
|
|
{
|
|
if (m_chunk >= m_chunks.size()) break;
|
|
CustomPacketChunk& chunk = m_chunks[m_chunk];
|
|
chunkSize_t read = chunkSize_t(std::min(
|
|
size
|
|
, totalSize_t(chunk.RemBytes(m_idx))
|
|
));
|
|
chunk.ReadBytes(m_idx, read, bytes + offset);
|
|
size -= read;
|
|
offset += read;
|
|
if (size == 0)
|
|
{
|
|
incIdx(read);
|
|
}
|
|
else
|
|
{
|
|
m_idx = 0;
|
|
++m_chunk;
|
|
}
|
|
}
|
|
}
|
|
|
|
char* CustomPacketBase::ReadBytes(totalSize_t size, bool padStr)
|
|
{
|
|
if (m_size - m_global_idx < size)
|
|
{
|
|
return nullptr;
|
|
}
|
|
char* c = new char[size + (padStr ? 1 : 0)];
|
|
ReadBytes(size, c);
|
|
return c;
|
|
}
|
|
|
|
void CustomPacketBase::Clear()
|
|
{
|
|
m_chunks.clear();
|
|
Reset();
|
|
}
|
|
|
|
opcode_t CustomPacketBase::Opcode()
|
|
{
|
|
return m_opcode;
|
|
}
|
|
|
|
void CustomPacketBase::incIdx(chunkSize_t amount)
|
|
{
|
|
m_idx += amount;
|
|
m_global_idx += amount;
|
|
}
|