mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-06-16 05:13:58 -07:00
134 lines
3.3 KiB
C++
134 lines
3.3 KiB
C++
/* Copyright (C) 2026 Wildfire Games.
|
|
* This file is part of 0 A.D.
|
|
*
|
|
* 0 A.D. is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* 0 A.D. 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
|
|
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "precompiled.h"
|
|
|
|
#include "NetHost.h"
|
|
|
|
#include "lib/debug.h"
|
|
#include "lib/external_libraries/enet.h"
|
|
#include "network/NetMessage.h"
|
|
#include "ps/CLogger.h"
|
|
|
|
#include <cstddef>
|
|
#include <numeric>
|
|
#include <vector>
|
|
|
|
std::vector<std::uint8_t> CNetHost::CreatePacket(const CNetMessage* message)
|
|
{
|
|
size_t size = message->GetSerializedLength();
|
|
|
|
ENSURE(size); // else we'll fail when accessing the 0th element
|
|
|
|
// Adjust buffer for message
|
|
std::vector<u8> buffer;
|
|
buffer.resize(size);
|
|
|
|
// Save message to internal buffer
|
|
message->Serialize(&buffer[0]);
|
|
|
|
return buffer;
|
|
}
|
|
|
|
void CNetHost::Initialize()
|
|
{
|
|
int ret = enet_initialize();
|
|
ENSURE(ret == 0);
|
|
}
|
|
|
|
void CNetHost::Deinitialize()
|
|
{
|
|
enet_deinitialize();
|
|
}
|
|
|
|
|
|
Stream::Stream(const std::int64_t streamId):
|
|
m_Id{streamId}
|
|
{}
|
|
|
|
void Stream::PushData(std::vector<std::uint8_t> data)
|
|
{
|
|
m_SendBuffer.push_back(std::move(data));
|
|
}
|
|
|
|
void Stream::PushMessage(const CNetMessage* message)
|
|
{
|
|
m_SendBuffer.push_back(CNetHost::CreatePacket(message));
|
|
}
|
|
|
|
std::optional<std::span<const std::uint8_t>> Stream::PeekData()
|
|
{
|
|
const std::size_t startOffset{m_SentOffset - m_AckedOffset};
|
|
std::size_t offset{0};
|
|
|
|
for (std::vector<std::uint8_t>& bytes : m_SendBuffer)
|
|
{
|
|
if (startOffset - offset < bytes.size())
|
|
{
|
|
const std::size_t temp{startOffset - offset};
|
|
return std::span{bytes.data() + temp, bytes.size() - temp};
|
|
}
|
|
|
|
offset += bytes.size();
|
|
}
|
|
|
|
return std::nullopt;
|
|
}
|
|
|
|
void Stream::MarkSent(const std::size_t offset)
|
|
{
|
|
m_SentOffset += offset;
|
|
}
|
|
|
|
void Stream::MarkAcknowledged(const std::size_t offset)
|
|
{
|
|
while (!m_SendBuffer.empty())
|
|
{
|
|
std::vector<uint8_t>& head{m_SendBuffer.front()};
|
|
if (m_AckedOffset + head.size() > offset)
|
|
break;
|
|
|
|
m_AckedOffset += head.size();
|
|
m_SendBuffer.pop_front();
|
|
}
|
|
}
|
|
|
|
std::optional<std::vector<std::uint8_t>> Stream::Receive(const std::span<const std::uint8_t> data)
|
|
{
|
|
m_ReceiveBuffer.emplace_back(data.begin(), data.end());
|
|
const std::size_t bufferSize{std::transform_reduce(m_ReceiveBuffer.begin(), m_ReceiveBuffer.end(),
|
|
static_cast<std::size_t>(0), std::plus<>{}, std::mem_fn(&std::vector<std::uint8_t>::size))};
|
|
if (bufferSize < 3)
|
|
return std::nullopt;
|
|
const auto& message = m_ReceiveBuffer.front();
|
|
|
|
auto bufferIter = message.begin();
|
|
std::size_t messageSize;
|
|
Deserialize_int_1(bufferIter, std::ignore);
|
|
Deserialize_int_2(bufferIter, messageSize);
|
|
if (messageSize > bufferSize)
|
|
return std::nullopt;
|
|
|
|
std::vector<std::uint8_t> messageCopy;
|
|
while (messageCopy.size() < messageSize)
|
|
{
|
|
messageCopy.insert(messageCopy.end(), m_ReceiveBuffer.front().begin(),
|
|
m_ReceiveBuffer.front().end());
|
|
m_ReceiveBuffer.pop_front();
|
|
}
|
|
return messageCopy;
|
|
}
|