1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
|
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
#include "LocalConnection.h"
#include "Net/Protocol/BaseNetProtocol.h"
#include "Exception.h"
#include "ProtocolDef.h"
#include "System/Log/ILog.h"
#include "System/SpringFormat.h"
namespace netcode {
// static stuff
unsigned CLocalConnection::instances = 0;
std::deque< std::shared_ptr<const RawPacket> > CLocalConnection::pqueues[2];
spring::mutex CLocalConnection::mutexes[2];
CLocalConnection::CLocalConnection()
{
if (instances > 1) {
throw network_error("Opening a third local connection is not allowed");
}
instance = instances;
instances++;
// clear data that might have been left over (if we reloaded)
pqueues[instance].clear();
// make sure protocoldef is initialized
CBaseNetProtocol::Get();
}
CLocalConnection::~CLocalConnection()
{
instances--;
}
void CLocalConnection::Close(bool flush)
{
if (flush) {
std::lock_guard<spring::mutex> scoped_lock(mutexes[instance]);
pqueues[instance].clear();
}
}
void CLocalConnection::SendData(std::shared_ptr<const RawPacket> packet)
{
if (!ProtocolDef::GetInstance()->IsValidPacket(packet->data, packet->length)) {
// having this check here makes it easier to find networking bugs
// also when testing locally
LOG_L(L_ERROR, "[LocalConn::%s] discarding invalid packet: ID %d, LEN %d",
__FUNCTION__, (packet->length > 0) ? (int)packet->data[0] : -1, packet->length);
return;
}
dataSent += packet->length;
// when sending from A to B we must lock B's queue
std::lock_guard<spring::mutex> scoped_lock(mutexes[OtherInstance()]);
pqueues[OtherInstance()].push_back(packet);
}
std::shared_ptr<const RawPacket> CLocalConnection::GetData()
{
std::lock_guard<spring::mutex> scoped_lock(mutexes[instance]);
if (!pqueues[instance].empty()) {
std::shared_ptr<const RawPacket> next = pqueues[instance].front();
pqueues[instance].pop_front();
dataRecv += next->length;
return next;
}
std::shared_ptr<const RawPacket> empty;
return empty;
}
std::shared_ptr<const RawPacket> CLocalConnection::Peek(unsigned ahead) const
{
std::lock_guard<spring::mutex> scoped_lock(mutexes[instance]);
if (ahead < pqueues[instance].size())
return pqueues[instance][ahead];
std::shared_ptr<const RawPacket> empty;
return empty;
}
void CLocalConnection::DeleteBufferPacketAt(unsigned index)
{
std::lock_guard<spring::mutex> scoped_lock(mutexes[instance]);
if (index >= pqueues[instance].size())
return;
pqueues[instance].erase(pqueues[instance].begin() + index);
}
std::string CLocalConnection::Statistics() const
{
std::string msg = "[LocalConnection::Statistics]\n";
msg += spring::format("\tReceived: %u bytes\n", dataRecv);
msg += spring::format("\tSent: %u bytes\n", dataSent);
return msg;
}
std::string CLocalConnection::GetFullAddress() const
{
return "Localhost";
}
bool CLocalConnection::HasIncomingData() const
{
std::lock_guard<spring::mutex> scoped_lock(mutexes[instance]);
return (!pqueues[instance].empty());
}
unsigned int CLocalConnection::GetPacketQueueSize() const
{
std::lock_guard<spring::mutex> scoped_lock(mutexes[instance]);
return (!pqueues[instance].size());
}
} // namespace netcode
|