Skip to content

Commit

Permalink
Big-endian networking fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
glebm committed Dec 15, 2024
1 parent a60a387 commit 0da67fb
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 37 deletions.
6 changes: 3 additions & 3 deletions Source/dvlnet/base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ bool base::SNetRegisterEventHandler(event_type evtype, SEVTHANDLER func)
bool base::SNetLeaveGame(int type)
{
auto pkt = pktfty->make_packet<PT_DISCONNECT>(plr_self, PLR_BROADCAST,
plr_self, type);
plr_self, static_cast<leaveinfo_t>(type));
send(*pkt);
plr_self = PLR_BROADCAST;
return true;
Expand All @@ -411,8 +411,8 @@ bool base::SNetDropPlayer(int playerid, uint32_t flags)
{
auto pkt = pktfty->make_packet<PT_DISCONNECT>(plr_self,
PLR_BROADCAST,
(plr_t)playerid,
(leaveinfo_t)flags);
static_cast<plr_t>(playerid),
static_cast<leaveinfo_t>(SDL_SwapLE32(flags)));
send(*pkt);
RecvLocal(*pkt);
return true;
Expand Down
8 changes: 5 additions & 3 deletions Source/dvlnet/base_protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -296,8 +296,10 @@ void base_protocol<P>::recv_decrypted(packet &pkt, endpoint_t sender)
size_t neededSize = sizeof(GameData) + (PlayerNameLength * MAX_PLRS);
if (pkt.Info().size() < neededSize)
return;
const GameData *gameData = (const GameData *)pkt.Info().data();
if (gameData->size != sizeof(GameData))
GameData gameData;
std::memcpy(&gameData, pkt.Info().data(), sizeof(GameData));
gameData.SwapLE();
if (gameData.size != sizeof(GameData))
return;
std::vector<std::string> playerNames;
for (size_t i = 0; i < Players.size(); i++) {
Expand All @@ -316,7 +318,7 @@ void base_protocol<P>::recv_decrypted(packet &pkt, endpoint_t sender)
size_t gameNameSize = pkt.Info().size() - neededSize;
gameName.resize(gameNameSize);
std::memcpy(&gameName[0], pkt.Info().data() + neededSize, gameNameSize);
game_list[gameName] = std::make_tuple(*gameData, playerNames, sender);
game_list[gameName] = std::make_tuple(gameData, playerNames, sender);
return;
}
recv_ingame(pkt, sender);
Expand Down
9 changes: 6 additions & 3 deletions Source/dvlnet/frame_queue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "appfat.h"
#include "dvlnet/packet.h"
#include "utils/attributes.h"
#include "utils/endian.hpp"

namespace devilution {
namespace net {
Expand Down Expand Up @@ -56,7 +57,7 @@ bool frame_queue::PacketReady()
if (Size() < sizeof(framesize_t))
return false;
auto szbuf = Read(sizeof(framesize_t));
std::memcpy(&nextsize, &szbuf[0], sizeof(framesize_t));
nextsize = LoadLE32(szbuf.data());
if (nextsize == 0)
FRAME_QUEUE_ERROR;
}
Expand All @@ -77,8 +78,10 @@ buffer_t frame_queue::MakeFrame(buffer_t packetbuf)
buffer_t ret;
if (packetbuf.size() > max_frame_size)
ABORT();
framesize_t size = packetbuf.size();
ret.insert(ret.end(), packet_out::begin(size), packet_out::end(size));
const framesize_t size = packetbuf.size();
unsigned char sizeBuf[4];
WriteLE32(sizeBuf, size);
ret.insert(ret.end(), sizeBuf, sizeBuf + 4);
ret.insert(ret.end(), packetbuf.begin(), packetbuf.end());
return ret;
}
Expand Down
22 changes: 19 additions & 3 deletions Source/dvlnet/packet.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ typedef uint8_t plr_t;
typedef uint8_t seq_t;
typedef uint32_t cookie_t;
typedef uint32_t timestamp_t;
typedef int leaveinfo_t; // also change later
typedef uint32_t leaveinfo_t;
#ifdef PACKET_ENCRYPTION
typedef std::array<unsigned char, crypto_secretbox_KEYBYTES> key_t;
#else
Expand Down Expand Up @@ -208,7 +208,13 @@ void packet_in::process_element(T &x)
#else
app_fatal("invalid packet");
#endif
std::memcpy(&x, decrypted_buffer.data(), sizeof(T));
if (sizeof(T) == 4) {
x = static_cast<T>(LoadLE32(decrypted_buffer.data()));
} else if (sizeof(T) == 2) {
x = static_cast<T>(LoadLE16(decrypted_buffer.data()));
} else {
std::memcpy(&x, decrypted_buffer.data(), sizeof(T));
}
decrypted_buffer.erase(decrypted_buffer.begin(),
decrypted_buffer.begin() + sizeof(T));
}
Expand Down Expand Up @@ -360,7 +366,17 @@ inline void packet_out::process_element(buffer_t &x)
template <class T>
void packet_out::process_element(T &x)
{
decrypted_buffer.insert(decrypted_buffer.end(), begin(x), end(x));
if (sizeof(T) == 4) {
unsigned char buf[4];
WriteLE32(buf, x);
decrypted_buffer.insert(decrypted_buffer.end(), buf, buf + 4);
} else if (sizeof(T) == 2) {
unsigned char buf[2];
WriteLE16(buf, x);
decrypted_buffer.insert(decrypted_buffer.end(), buf, buf + 2);
} else {
std::memcpy(&x, decrypted_buffer.data(), sizeof(T));
}
}

template <class T>
Expand Down
2 changes: 1 addition & 1 deletion Source/dvlnet/tcp_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ void tcp_server::DropConnection(const scc &con)
{
if (con->plr != PLR_BROADCAST) {
auto pkt = pktfty.make_packet<PT_DISCONNECT>(PLR_MASTER, PLR_BROADCAST,
con->plr, LEAVE_DROP);
con->plr, static_cast<leaveinfo_t>(LEAVE_DROP));
connections[con->plr] = nullptr;
SendPacket(*pkt);
// TODO: investigate if it is really ok for the server to
Expand Down
60 changes: 40 additions & 20 deletions Source/multi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/

#include <cstdint>
#include <cstring>
#include <ctime>

#include <SDL.h>
Expand Down Expand Up @@ -46,7 +47,7 @@ bool sgbSendDeltaTbl[MAX_PLRS];
GameData sgGameInitInfo;
bool gbSelectProvider;
int sglTimeoutStart;
int sgdwPlayerLeftReasonTbl[MAX_PLRS];
int32_t sgdwPlayerLeftReasonTbl[MAX_PLRS];
TBuffer lowPriorityBuffer;
uint32_t sgdwGameLoops;
/**
Expand Down Expand Up @@ -74,6 +75,13 @@ const event_type EventTypes[3] = {
EVENT_TYPE_PLAYER_MESSAGE
};

void GameData::SwapLE()
{
size = SDL_SwapLE32(size);
dwSeed = SDL_SwapLE32(dwSeed);
programid = SDL_SwapLE32(programid);
}

namespace {

constexpr uint16_t HeaderCheckVal =
Expand Down Expand Up @@ -376,34 +384,44 @@ void SetupLocalPositions()

void HandleEvents(_SNETEVENT *pEvt)
{
const uint32_t playerId = pEvt->playerid;
switch (pEvt->eventid) {
case EVENT_TYPE_PLAYER_CREATE_GAME: {
auto *gameData = (GameData *)pEvt->data;
if (gameData->size != sizeof(GameData))
app_fatal(StrCat("Invalid size of game data: ", gameData->size));
sgGameInitInfo = *gameData;
sgbPlayerTurnBitTbl[pEvt->playerid] = true;
break;
}
GameData gameData;
if (pEvt->databytes != sizeof(GameData))
app_fatal(StrCat("Invalid size of game data: ", gameData.size));
std::memcpy(&gameData, pEvt->data, sizeof(gameData));
gameData.SwapLE();
if (gameData.size != sizeof(GameData))
app_fatal(StrCat("Invalid size of game data: ", gameData.size));
sgGameInitInfo = gameData;
sgbPlayerTurnBitTbl[playerId] = true;
} break;
case EVENT_TYPE_PLAYER_LEAVE_GAME: {
sgbPlayerLeftGameTbl[pEvt->playerid] = true;
sgbPlayerTurnBitTbl[pEvt->playerid] = false;
sgbPlayerLeftGameTbl[playerId] = true;
sgbPlayerTurnBitTbl[playerId] = false;

int leftReason = 0;
if (pEvt->data != nullptr && pEvt->databytes >= sizeof(leftReason))
leftReason = *(int *)pEvt->data;
sgdwPlayerLeftReasonTbl[pEvt->playerid] = leftReason;
int32_t leftReason = 0;
if (pEvt->data != nullptr && pEvt->databytes >= sizeof(leftReason)) {
std::memcpy(&leftReason, pEvt->data, sizeof(leftReason));
leftReason = SDL_SwapLE32(leftReason);
}
sgdwPlayerLeftReasonTbl[playerId] = leftReason;
if (leftReason == LEAVE_ENDING)
gbSomebodyWonGameKludge = true;

sgbSendDeltaTbl[pEvt->playerid] = false;
sgbSendDeltaTbl[playerId] = false;

if (gbDeltaSender == pEvt->playerid)
if (gbDeltaSender == playerId)
gbDeltaSender = MAX_PLRS;
} break;
case EVENT_TYPE_PLAYER_MESSAGE:
EventPlrMsg((char *)pEvt->data);
break;
case EVENT_TYPE_PLAYER_MESSAGE: {
string_view data(static_cast<const char *>(pEvt->data), pEvt->databytes);
if (const size_t nullPos = data.find('\0'); nullPos != string_view::npos) {
data.remove_suffix(data.size() - nullPos);
}
EventPlrMsg(data);
} break;
}
}

Expand Down Expand Up @@ -432,7 +450,9 @@ bool InitSingle(GameData *gameData)
}

int unused = 0;
if (!SNetCreateGame("local", "local", (char *)&sgGameInitInfo, sizeof(sgGameInitInfo), &unused)) {
GameData gameInitInfo = sgGameInitInfo;
gameInitInfo.SwapLE();
if (!SNetCreateGame("local", "local", reinterpret_cast<char *>(&gameInitInfo), sizeof(gameInitInfo), &unused)) {
app_fatal(StrCat("SNetCreateGame1:\n", SDL_GetError()));
}

Expand Down
2 changes: 2 additions & 0 deletions Source/multi.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ struct GameData {
uint8_t bCowQuest;
uint8_t bFriendlyFire;
uint8_t fullQuests;

void SwapLE();
};

/* @brief Contains info of running public game (for game list browsing) */
Expand Down
8 changes: 4 additions & 4 deletions Source/storm/storm_net.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ struct _SNETCAPS {
};

struct _SNETEVENT {
uint32_t eventid;
uint32_t playerid;
void *data;
uint32_t databytes;
uint32_t eventid; // native-endian
uint32_t playerid; // native-endian
void *data; // little-endian
uint32_t databytes; // native-endian
};

#define PS_CONNECTED 0x10000
Expand Down

0 comments on commit 0da67fb

Please sign in to comment.