2012-06-29 16:44:26 +02:00
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
|
// This file is part of Remere's Map Editor
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
2020-07-30 11:42:28 -03:00
|
|
|
// Remere's Map Editor 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 3 of the License, or
|
|
|
|
|
// (at your option) any later version.
|
|
|
|
|
//
|
|
|
|
|
// Remere's Map Editor 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
2012-06-29 16:44:26 +02:00
|
|
|
|
|
|
|
|
#include "main.h"
|
|
|
|
|
|
|
|
|
|
#include "live_peer.h"
|
|
|
|
|
#include "live_server.h"
|
2014-02-21 13:55:09 +01:00
|
|
|
#include "live_tab.h"
|
|
|
|
|
#include "live_action.h"
|
2012-06-29 16:44:26 +02:00
|
|
|
|
2014-02-21 13:55:09 +01:00
|
|
|
#include "editor.h"
|
2012-06-29 16:44:26 +02:00
|
|
|
|
2022-08-22 14:33:31 -03:00
|
|
|
LivePeer::LivePeer(LiveServer* server, asio::ip::tcp::socket socket) : LiveSocket(),
|
2014-02-21 13:55:09 +01:00
|
|
|
readMessage(), server(server), socket(std::move(socket)), color(), id(0), clientId(0), connected(false)
|
2012-06-29 16:44:26 +02:00
|
|
|
{
|
2014-02-21 13:55:09 +01:00
|
|
|
ASSERT(server != nullptr);
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LivePeer::~LivePeer()
|
|
|
|
|
{
|
2015-12-06 11:42:37 -03:00
|
|
|
if(socket.is_open()) {
|
2014-02-21 13:55:09 +01:00
|
|
|
socket.close();
|
|
|
|
|
}
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
|
|
|
|
|
2014-02-21 13:55:09 +01:00
|
|
|
void LivePeer::close()
|
|
|
|
|
{
|
|
|
|
|
server->removeClient(id);
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
|
|
|
|
|
2022-08-22 14:33:31 -03:00
|
|
|
bool LivePeer::handleError(const std::error_code& error)
|
2014-02-21 13:55:09 +01:00
|
|
|
{
|
2022-08-22 14:33:31 -03:00
|
|
|
if(error == asio::error::eof || error == asio::error::connection_reset) {
|
2016-11-05 15:28:14 +01:00
|
|
|
logMessage(wxString() + getHostName() + ": disconnected.");
|
2014-02-21 13:55:09 +01:00
|
|
|
close();
|
|
|
|
|
return true;
|
2022-08-22 14:33:31 -03:00
|
|
|
} else if(error == asio::error::connection_aborted) {
|
2016-11-05 15:28:14 +01:00
|
|
|
logMessage(name + " have left the server.");
|
2014-02-21 13:55:09 +01:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string LivePeer::getHostName() const
|
|
|
|
|
{
|
|
|
|
|
return socket.remote_endpoint().address().to_string();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LivePeer::receiveHeader()
|
|
|
|
|
{
|
|
|
|
|
readMessage.position = 0;
|
2022-08-22 14:33:31 -03:00
|
|
|
asio::async_read(socket,
|
|
|
|
|
asio::buffer(readMessage.buffer, 4),
|
|
|
|
|
[this](const std::error_code& error, size_t bytesReceived) -> void {
|
2015-12-06 11:42:37 -03:00
|
|
|
if(error) {
|
|
|
|
|
if(!handleError(error)) {
|
2016-11-05 15:28:14 +01:00
|
|
|
logMessage(wxString() + getHostName() + ": " + error.message());
|
2014-02-21 13:55:09 +01:00
|
|
|
}
|
2015-12-06 11:42:37 -03:00
|
|
|
} else if(bytesReceived < 4) {
|
2016-11-05 15:28:14 +01:00
|
|
|
logMessage(wxString() + getHostName() + ": Could not receive header[size: " + std::to_string(bytesReceived) + "], disconnecting client.");
|
2014-02-21 13:55:09 +01:00
|
|
|
} else {
|
|
|
|
|
receive(readMessage.read<uint32_t>());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LivePeer::receive(uint32_t packetSize)
|
|
|
|
|
{
|
|
|
|
|
readMessage.buffer.resize(readMessage.position + packetSize);
|
2022-08-22 14:33:31 -03:00
|
|
|
asio::async_read(socket,
|
|
|
|
|
asio::buffer(&readMessage.buffer[readMessage.position], packetSize),
|
|
|
|
|
[this](const std::error_code& error, size_t bytesReceived) -> void {
|
2015-12-06 11:42:37 -03:00
|
|
|
if(error) {
|
|
|
|
|
if(!handleError(error)) {
|
2016-11-05 15:28:14 +01:00
|
|
|
logMessage(wxString() + getHostName() + ": " + error.message());
|
2014-02-21 13:55:09 +01:00
|
|
|
}
|
2015-12-06 11:42:37 -03:00
|
|
|
} else if(bytesReceived < readMessage.buffer.size() - 4) {
|
2016-11-05 15:28:14 +01:00
|
|
|
logMessage(wxString() + getHostName() + ": Could not receive packet[size: " + std::to_string(bytesReceived) + "], disconnecting client.");
|
2014-02-21 13:55:09 +01:00
|
|
|
} else {
|
|
|
|
|
wxTheApp->CallAfter([this]() {
|
2015-12-06 11:42:37 -03:00
|
|
|
if(connected) {
|
2014-02-21 13:55:09 +01:00
|
|
|
parseEditorPacket(std::move(readMessage));
|
|
|
|
|
} else {
|
|
|
|
|
parseLoginPacket(std::move(readMessage));
|
|
|
|
|
}
|
|
|
|
|
receiveHeader();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LivePeer::send(NetworkMessage& message)
|
|
|
|
|
{
|
|
|
|
|
memcpy(&message.buffer[0], &message.size, 4);
|
2022-08-22 14:33:31 -03:00
|
|
|
asio::async_write(socket,
|
|
|
|
|
asio::buffer(message.buffer, message.size + 4),
|
|
|
|
|
[this](const std::error_code& error, size_t bytesTransferred) -> void {
|
2015-12-06 11:42:37 -03:00
|
|
|
if(error) {
|
2016-11-05 15:28:14 +01:00
|
|
|
logMessage(wxString() + getHostName() + ": " + error.message());
|
2014-02-21 13:55:09 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LivePeer::parseLoginPacket(NetworkMessage message)
|
|
|
|
|
{
|
|
|
|
|
uint8_t packetType;
|
2015-12-06 11:42:37 -03:00
|
|
|
while(message.position < message.buffer.size()) {
|
2014-02-21 13:55:09 +01:00
|
|
|
packetType = message.read<uint8_t>();
|
|
|
|
|
switch (packetType) {
|
|
|
|
|
case PACKET_HELLO_FROM_CLIENT:
|
|
|
|
|
parseHello(message);
|
|
|
|
|
break;
|
|
|
|
|
case PACKET_READY_CLIENT:
|
|
|
|
|
parseReady(message);
|
|
|
|
|
break;
|
|
|
|
|
default: {
|
2016-11-05 15:28:14 +01:00
|
|
|
log->Message("Invalid login packet receieved, connection severed.");
|
2014-02-21 13:55:09 +01:00
|
|
|
close();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
|
|
|
|
|
2014-02-21 13:55:09 +01:00
|
|
|
void LivePeer::parseEditorPacket(NetworkMessage message)
|
2012-06-29 16:44:26 +02:00
|
|
|
{
|
2014-02-21 13:55:09 +01:00
|
|
|
uint8_t packetType;
|
2015-12-06 11:42:37 -03:00
|
|
|
while(message.position < message.buffer.size()) {
|
2014-02-21 13:55:09 +01:00
|
|
|
packetType = message.read<uint8_t>();
|
|
|
|
|
switch (packetType) {
|
|
|
|
|
case PACKET_REQUEST_NODES:
|
|
|
|
|
parseNodeRequest(message);
|
|
|
|
|
break;
|
|
|
|
|
case PACKET_CHANGE_LIST:
|
|
|
|
|
parseReceiveChanges(message);
|
|
|
|
|
break;
|
|
|
|
|
case PACKET_ADD_HOUSE:
|
|
|
|
|
parseAddHouse(message);
|
|
|
|
|
break;
|
|
|
|
|
case PACKET_EDIT_HOUSE:
|
|
|
|
|
parseEditHouse(message);
|
|
|
|
|
break;
|
|
|
|
|
case PACKET_REMOVE_HOUSE:
|
|
|
|
|
parseRemoveHouse(message);
|
|
|
|
|
break;
|
|
|
|
|
case PACKET_CLIENT_UPDATE_CURSOR:
|
|
|
|
|
parseCursorUpdate(message);
|
|
|
|
|
break;
|
|
|
|
|
case PACKET_CLIENT_TALK:
|
|
|
|
|
parseChatMessage(message);
|
|
|
|
|
break;
|
|
|
|
|
default: {
|
2016-11-05 15:28:14 +01:00
|
|
|
log->Message("Invalid editor packet receieved, connection severed.");
|
2014-02-21 13:55:09 +01:00
|
|
|
close();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LivePeer::parseHello(NetworkMessage& message)
|
|
|
|
|
{
|
2015-12-06 11:42:37 -03:00
|
|
|
if(connected) {
|
2014-02-21 13:55:09 +01:00
|
|
|
close();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t rmeVersion = message.read<uint32_t>();
|
2015-12-06 11:42:37 -03:00
|
|
|
if(rmeVersion != __RME_VERSION_ID__) {
|
2014-02-21 13:55:09 +01:00
|
|
|
NetworkMessage outMessage;
|
|
|
|
|
outMessage.write<uint8_t>(PACKET_KICK);
|
|
|
|
|
outMessage.write<std::string>("Wrong editor version.");
|
|
|
|
|
|
|
|
|
|
send(outMessage);
|
|
|
|
|
close();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t netVersion = message.read<uint32_t>();
|
2015-12-06 11:42:37 -03:00
|
|
|
if(netVersion != __LIVE_NET_VERSION__) {
|
2014-02-21 13:55:09 +01:00
|
|
|
NetworkMessage outMessage;
|
|
|
|
|
outMessage.write<uint8_t>(PACKET_KICK);
|
|
|
|
|
outMessage.write<std::string>("Wrong protocol version.");
|
|
|
|
|
|
|
|
|
|
send(outMessage);
|
|
|
|
|
close();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t clientVersion = message.read<uint32_t>();
|
|
|
|
|
std::string nickname = message.read<std::string>();
|
|
|
|
|
std::string password = message.read<std::string>();
|
|
|
|
|
|
2015-12-06 11:42:37 -03:00
|
|
|
if(server->getPassword() != wxString(password.c_str(), wxConvUTF8)) {
|
2016-11-05 15:28:14 +01:00
|
|
|
log->Message("Client tried to connect, but used the wrong password, connection refused.");
|
2014-02-21 13:55:09 +01:00
|
|
|
close();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
name = wxString(nickname.c_str(), wxConvUTF8);
|
2016-11-05 15:28:14 +01:00
|
|
|
log->Message(name + " (" + getHostName() + ") connected.");
|
2014-02-21 13:55:09 +01:00
|
|
|
|
|
|
|
|
NetworkMessage outMessage;
|
2016-09-29 20:30:54 -03:00
|
|
|
if(static_cast<ClientVersionID>(clientVersion) != g_gui.GetCurrentVersionID()) {
|
2014-02-21 13:55:09 +01:00
|
|
|
outMessage.write<uint8_t>(PACKET_CHANGE_CLIENT_VERSION);
|
2016-09-29 20:30:54 -03:00
|
|
|
outMessage.write<uint32_t>(g_gui.GetCurrentVersionID());
|
2014-02-21 13:55:09 +01:00
|
|
|
} else {
|
|
|
|
|
outMessage.write<uint8_t>(PACKET_ACCEPTED_CLIENT);
|
|
|
|
|
}
|
|
|
|
|
send(outMessage);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LivePeer::parseReady(NetworkMessage& message)
|
|
|
|
|
{
|
2015-12-06 11:42:37 -03:00
|
|
|
if(connected) {
|
2014-02-21 13:55:09 +01:00
|
|
|
close();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
connected = true;
|
|
|
|
|
|
|
|
|
|
// Find free client id
|
|
|
|
|
clientId = server->getFreeClientId();
|
2015-12-06 11:42:37 -03:00
|
|
|
if(clientId == 0) {
|
2014-02-21 13:55:09 +01:00
|
|
|
NetworkMessage outMessage;
|
|
|
|
|
outMessage.write<uint8_t>(PACKET_KICK);
|
|
|
|
|
outMessage.write<std::string>("Server is full.");
|
|
|
|
|
|
|
|
|
|
send(outMessage);
|
|
|
|
|
close();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
server->updateClientList();
|
|
|
|
|
|
|
|
|
|
// Let's reply
|
|
|
|
|
NetworkMessage outMessage;
|
|
|
|
|
outMessage.write<uint8_t>(PACKET_HELLO_FROM_SERVER);
|
|
|
|
|
|
|
|
|
|
Map& map = server->getEditor()->map;
|
|
|
|
|
outMessage.write<std::string>(map.getName());
|
|
|
|
|
outMessage.write<uint16_t>(map.getWidth());
|
|
|
|
|
outMessage.write<uint16_t>(map.getHeight());
|
|
|
|
|
|
|
|
|
|
send(outMessage);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LivePeer::parseNodeRequest(NetworkMessage& message)
|
|
|
|
|
{
|
|
|
|
|
Map& map = server->getEditor()->map;
|
2015-12-06 11:42:37 -03:00
|
|
|
for(uint32_t nodes = message.read<uint32_t>(); nodes != 0; --nodes) {
|
2014-02-21 13:55:09 +01:00
|
|
|
uint32_t ind = message.read<uint32_t>();
|
|
|
|
|
|
|
|
|
|
int32_t ndx = ind >> 18;
|
|
|
|
|
int32_t ndy = (ind >> 4) & 0x3FFF;
|
|
|
|
|
bool underground = ind & 1;
|
2016-09-29 19:24:45 -03:00
|
|
|
|
2014-02-21 13:55:09 +01:00
|
|
|
QTreeNode* node = map.createLeaf(ndx * 4, ndy * 4);
|
2015-12-06 11:42:37 -03:00
|
|
|
if(node) {
|
2014-02-21 13:55:09 +01:00
|
|
|
sendNode(clientId, node, ndx, ndy, underground ? 0xFF00 : 0x00FF);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LivePeer::parseReceiveChanges(NetworkMessage& message)
|
|
|
|
|
{
|
|
|
|
|
Editor& editor = *server->getEditor();
|
|
|
|
|
|
|
|
|
|
// -1 on address since we skip the first START_NODE when sending
|
|
|
|
|
const std::string& data = message.read<std::string>();
|
|
|
|
|
mapReader.assign(reinterpret_cast<const uint8_t*>(data.c_str() - 1), data.size());
|
|
|
|
|
|
|
|
|
|
BinaryNode* rootNode = mapReader.getRootNode();
|
|
|
|
|
BinaryNode* tileNode = rootNode->getChild();
|
|
|
|
|
|
|
|
|
|
NetworkedAction* action = static_cast<NetworkedAction*>(editor.actionQueue->createAction(ACTION_REMOTE));
|
|
|
|
|
action->owner = clientId;
|
|
|
|
|
|
2015-12-06 11:42:37 -03:00
|
|
|
if(tileNode) do {
|
2014-02-21 13:55:09 +01:00
|
|
|
Tile* tile = readTile(tileNode, editor, nullptr);
|
2015-12-06 11:42:37 -03:00
|
|
|
if(tile) {
|
2014-02-21 13:55:09 +01:00
|
|
|
action->addChange(newd Change(tile));
|
|
|
|
|
}
|
2015-12-06 11:42:37 -03:00
|
|
|
} while(tileNode->advance());
|
2014-02-21 13:55:09 +01:00
|
|
|
mapReader.close();
|
|
|
|
|
|
|
|
|
|
editor.actionQueue->addAction(action);
|
|
|
|
|
|
2016-09-29 20:30:54 -03:00
|
|
|
g_gui.RefreshView();
|
|
|
|
|
g_gui.UpdateMinimap();
|
2014-02-21 13:55:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LivePeer::parseAddHouse(NetworkMessage& message)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LivePeer::parseEditHouse(NetworkMessage& message)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LivePeer::parseRemoveHouse(NetworkMessage& message)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LivePeer::parseCursorUpdate(NetworkMessage& message)
|
|
|
|
|
{
|
|
|
|
|
LiveCursor cursor = readCursor(message);
|
|
|
|
|
cursor.id = clientId;
|
|
|
|
|
|
2015-12-06 11:42:37 -03:00
|
|
|
if(cursor.color != color) {
|
2014-02-21 13:55:09 +01:00
|
|
|
setUsedColor(cursor.color);
|
|
|
|
|
server->updateClientList();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
server->broadcastCursor(cursor);
|
2016-09-29 20:30:54 -03:00
|
|
|
g_gui.RefreshView();
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
|
|
|
|
|
2014-02-21 13:55:09 +01:00
|
|
|
void LivePeer::parseChatMessage(NetworkMessage& message)
|
2012-06-29 16:44:26 +02:00
|
|
|
{
|
2014-02-21 13:55:09 +01:00
|
|
|
const std::string& chatMessage = message.read<std::string>();
|
|
|
|
|
server->broadcastChat(name, wxstr(chatMessage));
|
2014-01-23 21:06:52 -02:00
|
|
|
}
|