1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-04-15 11:46:56 +02:00
vcmi/lib/serializer/Connection.cpp

263 lines
6.1 KiB
C++
Raw Normal View History

/*
* Connection.cpp, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#include "StdInc.h"
#include "Connection.h"
#include "../registerTypes/RegisterTypes.h"
#include "../mapping/CMap.h"
#include "../CGameState.h"
VCMI_LIB_NAMESPACE_BEGIN
#if defined(__hppa__) || \
defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \
(defined(__MIPS__) && defined(__MISPEB__)) || \
defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \
defined(__sparc__)
#define BIG_ENDIAN
#else
#define LIL_ENDIAN
#endif
void CConnection::init()
{
2023-01-03 03:52:44 +04:00
buffer = new char[4096];
bufferSize = 0;
2016-11-13 12:44:46 +03:00
enableSmartPointerSerialization();
disableStackSendingByID();
registerTypes(iser);
registerTypes(oser);
#ifdef LIL_ENDIAN
myEndianess = true;
#else
myEndianess = false;
#endif
connected = true;
std::string pom;
//we got connection
oser & std::string("Aiya!\n") & name & uuid & myEndianess; //identify ourselves
iser & pom & pom & contactUuid & contactEndianess;
logNetwork->info("Established connection with %s. UUID: %s", pom, contactUuid);
mutexRead = std::make_shared<boost::mutex>();
mutexWrite = std::make_shared<boost::mutex>();
iser.fileVersion = SERIALIZATION_VERSION;
}
2023-01-03 03:52:44 +04:00
CConnection::CConnection(ENetHost * _client, ENetPeer * _peer, std::string Name, std::string UUID)
: client(_client), peer(_peer), iser(this), oser(this), name(Name), uuid(UUID), connectionID(0)
{
init();
}
CConnection::CConnection(ENetHost * _client, std::string host, ui16 port, std::string Name, std::string UUID)
: client(_client), iser(this), oser(this), name(Name), uuid(UUID), connectionID(0)
{
2023-01-03 03:52:44 +04:00
ENetAddress address;
enet_address_set_host(&address, host.c_str());
address.port = port;
peer = enet_host_connect(client, &address, 2, 0);
if(peer == NULL)
{
2023-01-03 03:52:44 +04:00
throw std::runtime_error("Can't establish connection :(");
}
2023-01-03 03:52:44 +04:00
ENetEvent event;
if(enet_host_service(client, &event, 10000) > 0 && event.type == ENET_EVENT_TYPE_CONNECT)
{
2023-01-03 03:52:44 +04:00
logNetwork->info("Connection succeded");
}
else
{
2023-01-03 03:52:44 +04:00
enet_peer_reset(peer);
throw std::runtime_error("Connection refused by server");
}
2023-01-03 03:52:44 +04:00
init();
}
2023-01-03 03:52:44 +04:00
int CConnection::write(const void * data, unsigned size)
{
2023-01-03 03:52:44 +04:00
ENetPacket * packet = enet_packet_create(data, size, ENET_PACKET_FLAG_RELIABLE);
enet_peer_send(peer, 0, packet);
enet_host_flush(client);
return size;
}
int CConnection::read(void * data, unsigned size)
{
2023-01-03 03:52:44 +04:00
ENetEvent event;
while(bufferSize < size)
{
2023-01-03 03:52:44 +04:00
if(enet_host_service(client, &event, 100) <= 0)
continue;
if(event.type == ENET_EVENT_TYPE_CONNECT)
throw std::runtime_error("Connectin event receieved while package expected");
if(event.type == ENET_EVENT_TYPE_RECEIVE)
{
if(event.packet->dataLength > 0)
{
memcpy(buffer + bufferSize, event.packet->data, event.packet->dataLength);
bufferSize += event.packet->dataLength;
}
}
enet_packet_destroy(event.packet);
}
2023-01-03 03:52:44 +04:00
assert(bufferSize == size);
unsigned ret = std::min(size, bufferSize);
memcpy(data, buffer, ret);
if(ret < bufferSize)
memcpy(buffer, buffer + ret, bufferSize);
bufferSize -= ret;
return ret;
}
2023-01-03 03:52:44 +04:00
CConnection::~CConnection()
{
2023-01-03 03:52:44 +04:00
delete[] buffer;
if(handler)
handler->join();
close();
}
template<class T>
CConnection & CConnection::operator&(const T &t) {
// throw std::exception();
//XXX this is temporaly ? solution to fix gcc (4.3.3, other?) compilation
// problem for more details contact t0@czlug.icis.pcz.pl or impono@gmail.com
// do not remove this exception it shoudnt be called
return *this;
}
void CConnection::close()
{
2023-01-03 03:52:44 +04:00
ENetEvent event;
enet_peer_disconnect(peer, 0);
while(enet_host_service(client, & event, 100) > 0)
{
2023-01-03 03:52:44 +04:00
switch (event.type)
{
case ENET_EVENT_TYPE_RECEIVE:
enet_packet_destroy(event.packet);
break;
case ENET_EVENT_TYPE_DISCONNECT:
return;
}
}
2023-01-03 03:52:44 +04:00
/* We've arrived here, so the disconnect attempt didn't */
/* succeed yet. Force the connection down. */
enet_peer_reset(peer);
}
bool CConnection::isOpen() const
{
2023-01-03 03:52:44 +04:00
return connected;
}
void CConnection::reportState(vstd::CLoggerBase * out)
{
2017-08-10 19:39:27 +03:00
out->debug("CConnection");
2023-01-03 03:52:44 +04:00
/*if(socket && socket->is_open())
{
2017-08-10 19:39:27 +03:00
out->debug("\tWe have an open and valid socket");
out->debug("\t %d bytes awaiting", socket->available());
2023-01-03 03:52:44 +04:00
}*/
}
CPack * CConnection::retrievePack()
{
CPack * pack = nullptr;
boost::unique_lock<boost::mutex> lock(*mutexRead);
iser & pack;
logNetwork->trace("Received CPack of type %s", (pack ? typeid(*pack).name() : "nullptr"));
if(pack == nullptr)
{
logNetwork->error("Received a nullptr CPack! You should check whether client and server ABI matches.");
}
else
{
pack->c = this->shared_from_this();
}
return pack;
}
void CConnection::sendPack(const CPack * pack)
{
boost::unique_lock<boost::mutex> lock(*mutexWrite);
logNetwork->trace("Sending a pack of type %s", typeid(*pack).name());
oser & pack;
}
void CConnection::disableStackSendingByID()
{
CSerializer::sendStackInstanceByIds = false;
}
void CConnection::enableStackSendingByID()
{
CSerializer::sendStackInstanceByIds = true;
}
void CConnection::disableSmartPointerSerialization()
{
iser.smartPointerSerialization = oser.smartPointerSerialization = false;
}
2016-11-13 12:44:46 +03:00
void CConnection::enableSmartPointerSerialization()
{
iser.smartPointerSerialization = oser.smartPointerSerialization = true;
}
void CConnection::enterLobbyConnectionMode()
{
iser.loadedPointers.clear();
oser.savedPointers.clear();
disableSmartVectorMemberSerialization();
disableSmartPointerSerialization();
}
void CConnection::enterGameplayConnectionMode(CGameState * gs)
{
enableStackSendingByID();
disableSmartPointerSerialization();
addStdVecItems(gs);
}
void CConnection::disableSmartVectorMemberSerialization()
{
CSerializer::smartVectorMembersSerialization = false;
}
void CConnection::enableSmartVectorMemberSerializatoin()
{
CSerializer::smartVectorMembersSerialization = true;
}
2017-08-11 16:50:00 +03:00
std::string CConnection::toString() const
{
boost::format fmt("Connection with %s (ID: %d UUID: %s)");
fmt % name % connectionID % uuid;
return fmt.str();
2017-08-11 16:50:00 +03:00
}
VCMI_LIB_NAMESPACE_END