Support unencrypted multiplayer games with no password
This commit is contained in:
parent
8b0808bd4a
commit
ffbbcc6d62
24 changed files with 316 additions and 167 deletions
|
|
@ -27,15 +27,13 @@ option(BINARY_RELEASE "Enable options for binary release" OFF)
|
|||
option(NIGHTLY_BUILD "Enable options for nightly build" OFF)
|
||||
option(USE_SDL1 "Use SDL1.2 instead of SDL2" OFF)
|
||||
option(NONET "Disable network support" OFF)
|
||||
cmake_dependent_option(DISABLE_TCP "Disable TCP multiplayer option" OFF "NOT NONET" ON)
|
||||
cmake_dependent_option(DISABLE_ZERO_TIER "Disable ZeroTier multiplayer option" OFF "NOT NONET" ON)
|
||||
cmake_dependent_option(PACKET_ENCRYPTION "Encrypt network packets" ON "NOT NONET" OFF)
|
||||
option(NOSOUND "Disable sound support" OFF)
|
||||
option(RUN_TESTS "Build and run tests" OFF)
|
||||
option(ENABLE_CODECOVERAGE "Instrument code for code coverage (only enabled with RUN_TESTS)" OFF)
|
||||
|
||||
if(NOT NONET)
|
||||
option(DISABLE_TCP "Disable TCP multiplayer option" OFF)
|
||||
option(DISABLE_ZERO_TIER "Disable ZeroTier multiplayer option" OFF)
|
||||
endif()
|
||||
|
||||
option(DISABLE_STREAMING_MUSIC "Disable streaming music (to work around broken platform implementations)" OFF)
|
||||
mark_as_advanced(DISABLE_STREAMING_MUSIC)
|
||||
option(DISABLE_STREAMING_SOUNDS "Disable streaming sounds (to work around broken platform implementations)" OFF)
|
||||
|
|
@ -65,6 +63,9 @@ if(NIGHTLY_BUILD OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
|
|||
set(CPACK ON)
|
||||
endif()
|
||||
|
||||
if(PACKET_ENCRYPTION)
|
||||
list(APPEND VCPKG_MANIFEST_FEATURES "encryption")
|
||||
endif()
|
||||
if(USE_GETTEXT_FROM_VCPKG)
|
||||
list(APPEND VCPKG_MANIFEST_FEATURES "translations")
|
||||
endif()
|
||||
|
|
@ -78,7 +79,7 @@ if(NOT NOSOUND)
|
|||
"DEVILUTIONX_SYSTEM_SDL_AUDIOLIB AND NOT DIST" ON)
|
||||
endif()
|
||||
|
||||
if(NOT NONET)
|
||||
if(PACKET_ENCRYPTION)
|
||||
option(DEVILUTIONX_SYSTEM_LIBSODIUM "Use system-provided libsodium" ON)
|
||||
cmake_dependent_option(DEVILUTIONX_STATIC_LIBSODIUM "Link static libsodium" OFF
|
||||
"DEVILUTIONX_SYSTEM_LIBSODIUM AND NOT DIST" ON)
|
||||
|
|
@ -216,6 +217,13 @@ if(PIE)
|
|||
set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
|
||||
endif()
|
||||
|
||||
if(NONET)
|
||||
# Fix dependent options if platform defs disable network
|
||||
set(DISABLE_TCP ON)
|
||||
set(DISABLE_ZERO_TIER ON)
|
||||
set(PACKET_ENCRYPTION OFF)
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
|
@ -227,7 +235,7 @@ if(NOT NINTENDO_3DS)
|
|||
find_package(Threads REQUIRED)
|
||||
endif()
|
||||
|
||||
if(NOT NONET)
|
||||
if(PACKET_ENCRYPTION)
|
||||
if(DEVILUTIONX_SYSTEM_LIBSODIUM)
|
||||
set(sodium_USE_STATIC_LIBS ${DEVILUTIONX_STATIC_LIBSODIUM})
|
||||
find_package(sodium REQUIRED)
|
||||
|
|
@ -531,18 +539,26 @@ if(NINTENDO_SWITCH)
|
|||
Source/platform/switch/network.cpp
|
||||
Source/platform/switch/keyboard.cpp
|
||||
Source/platform/switch/docking.cpp
|
||||
Source/platform/switch/random.cpp
|
||||
Source/platform/switch/asio/pause.c
|
||||
Source/platform/switch/asio/net/if.c
|
||||
Source/platform/switch/asio/sys/signal.c)
|
||||
|
||||
if(PACKET_ENCRYPTION)
|
||||
list(APPEND libdevilutionx_SRCS
|
||||
Source/platform/switch/random.cpp)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(VITA)
|
||||
list(APPEND libdevilutionx_SRCS
|
||||
Source/platform/vita/random.cpp
|
||||
Source/platform/vita/network.cpp
|
||||
Source/platform/vita/keyboard.cpp
|
||||
Source/platform/vita/touch.cpp)
|
||||
|
||||
if(PACKET_ENCRYPTION)
|
||||
list(APPEND libdevilutionx_SRCS
|
||||
Source/platform/vita/random.cpp)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NINTENDO_3DS)
|
||||
|
|
@ -551,13 +567,17 @@ if(NINTENDO_3DS)
|
|||
Source/platform/ctr/keyboard.cpp
|
||||
Source/platform/ctr/display.cpp
|
||||
Source/platform/ctr/messagebox.cpp
|
||||
Source/platform/ctr/random.cpp
|
||||
Source/platform/ctr/sockets.cpp
|
||||
Source/platform/ctr/locale.cpp
|
||||
Source/platform/ctr/asio/net/if.c
|
||||
Source/platform/ctr/asio/sys/socket.c
|
||||
Source/platform/ctr/asio/sys/uio.c)
|
||||
set(BIN_TARGET ${BIN_TARGET}.elf)
|
||||
|
||||
if(PACKET_ENCRYPTION)
|
||||
list(APPEND libdevilutionx_SRCS
|
||||
Source/platform/ctr/random.cpp)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(RUN_TESTS)
|
||||
|
|
@ -847,7 +867,9 @@ if(NOT NONET)
|
|||
if(NOT DISABLE_TCP)
|
||||
target_link_libraries(libdevilutionx PUBLIC asio)
|
||||
endif()
|
||||
target_link_libraries(libdevilutionx PUBLIC sodium)
|
||||
if(PACKET_ENCRYPTION)
|
||||
target_link_libraries(libdevilutionx PUBLIC sodium)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_link_libraries(libdevilutionx PUBLIC fmt::fmt)
|
||||
|
|
@ -874,6 +896,7 @@ foreach(
|
|||
GPERF_HEAP_MAIN
|
||||
GPERF_HEAP_FIRST_GAME_ITERATION
|
||||
STREAM_ALL_AUDIO
|
||||
PACKET_ENCRYPTION
|
||||
VIRTUAL_GAMEPAD
|
||||
)
|
||||
if(${def_name})
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ bool UiItemsWraps;
|
|||
char *UiTextInput;
|
||||
int UiTextInputLen;
|
||||
bool textInputActive = true;
|
||||
bool allowEmptyTextInput = false;
|
||||
|
||||
std::size_t SelectedItem = 0;
|
||||
|
||||
|
|
@ -111,6 +112,7 @@ void UiInitList(int count, void (*fnFocus)(int value), void (*fnSelect)(int valu
|
|||
auto *pItemUIEdit = static_cast<UiEdit *>(item.get());
|
||||
SDL_SetTextInputRect(&item->m_rect);
|
||||
textInputActive = true;
|
||||
allowEmptyTextInput = pItemUIEdit->m_allowEmpty;
|
||||
#ifdef __SWITCH__
|
||||
switch_start_text_input(pItemUIEdit->m_hint, pItemUIEdit->m_value, pItemUIEdit->m_max_length, /*multiline=*/0);
|
||||
#elif defined(__vita__)
|
||||
|
|
@ -425,7 +427,7 @@ void UiFocusNavigationSelect()
|
|||
{
|
||||
UiPlaySelectSound();
|
||||
if (textInputActive) {
|
||||
if (strlen(UiTextInput) == 0) {
|
||||
if (!allowEmptyTextInput && strlen(UiTextInput) == 0) {
|
||||
return;
|
||||
}
|
||||
#ifndef __SWITCH__
|
||||
|
|
|
|||
|
|
@ -41,8 +41,6 @@ std::vector<std::unique_ptr<UiItemBase>> vecSelGameDialog;
|
|||
std::vector<std::string> Gamelist;
|
||||
int HighlightedItem;
|
||||
|
||||
constexpr const char *DefaultPassword = "asd";
|
||||
|
||||
} // namespace
|
||||
|
||||
void selgame_FreeVectors()
|
||||
|
|
@ -89,11 +87,14 @@ void selgame_GameSelection_Init()
|
|||
SDL_Rect rect4 = { (Sint16)(PANEL_LEFT + 300), (Sint16)(UI_OFFSET_Y + 211), 295, 33 };
|
||||
vecSelGameDialog.push_back(std::make_unique<UiArtText>(_("Select Action"), rect4, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiSilver, 3));
|
||||
|
||||
#ifdef PACKET_ENCRYPTION
|
||||
vecSelGameDlgItems.push_back(std::make_unique<UiListItem>(_("Create Game"), 0));
|
||||
vecSelGameDlgItems.push_back(std::make_unique<UiListItem>(_("Join Game"), 1));
|
||||
#endif
|
||||
vecSelGameDlgItems.push_back(std::make_unique<UiListItem>(_("Create Public Game"), 1));
|
||||
vecSelGameDlgItems.push_back(std::make_unique<UiListItem>(_("Join Game"), 2));
|
||||
|
||||
for (unsigned i = 0; i < Gamelist.size(); i++) {
|
||||
vecSelGameDlgItems.push_back(std::make_unique<UiListItem>(Gamelist[i].c_str(), i + 2));
|
||||
vecSelGameDlgItems.push_back(std::make_unique<UiListItem>(Gamelist[i].c_str(), i + 3));
|
||||
}
|
||||
|
||||
vecSelGameDialog.push_back(std::make_unique<UiList>(vecSelGameDlgItems, PANEL_LEFT + 305, (UI_OFFSET_Y + 255), 285, 26, UiFlags::AlignCenter | UiFlags::FontSize24 | UiFlags::ColorUiGold));
|
||||
|
|
@ -104,7 +105,13 @@ void selgame_GameSelection_Init()
|
|||
SDL_Rect rect6 = { (Sint16)(PANEL_LEFT + 449), (Sint16)(UI_OFFSET_Y + 427), 140, 35 };
|
||||
vecSelGameDialog.push_back(std::make_unique<UiArtTextButton>(_("CANCEL"), &UiFocusNavigationEsc, rect6, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontSize30 | UiFlags::ColorUiGold));
|
||||
|
||||
UiInitList(vecSelGameDlgItems.size(), selgame_GameSelection_Focus, selgame_GameSelection_Select, selgame_GameSelection_Esc, vecSelGameDialog, true, nullptr, HighlightedItem);
|
||||
auto selectFn = [](int index) {
|
||||
// UiListItem::m_value could be different from
|
||||
// the index if packet encryption is disabled
|
||||
int itemValue = vecSelGameDlgItems[index]->m_value;
|
||||
selgame_GameSelection_Select(itemValue);
|
||||
};
|
||||
UiInitList(vecSelGameDlgItems.size(), selgame_GameSelection_Focus, selectFn, selgame_GameSelection_Esc, vecSelGameDialog, true, nullptr, HighlightedItem);
|
||||
}
|
||||
|
||||
void selgame_GameSelection_Focus(int value)
|
||||
|
|
@ -115,6 +122,9 @@ void selgame_GameSelection_Focus(int value)
|
|||
strncpy(selgame_Description, _("Create a new game with a difficulty setting of your choice."), sizeof(selgame_Description) - 1);
|
||||
break;
|
||||
case 1:
|
||||
strncpy(selgame_Description, _("Create a new public game that anyone can join with a difficulty setting of your choice."), sizeof(selgame_Description) - 1);
|
||||
break;
|
||||
case 2:
|
||||
strncpy(selgame_Description, _("Enter an IP or a hostname and join a game already in progress at that address."), sizeof(selgame_Description) - 1);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -143,9 +153,8 @@ void selgame_GameSelection_Select(int value)
|
|||
selgame_enteringGame = true;
|
||||
selgame_selectedGame = value;
|
||||
|
||||
if (value > 1 && selgame_selectedGame != 0) {
|
||||
strcpy(selgame_Ip, Gamelist[value - 2].c_str());
|
||||
strcpy(selgame_Password, DefaultPassword);
|
||||
if (value > 2) {
|
||||
strcpy(selgame_Ip, Gamelist[value - 3].c_str());
|
||||
selgame_Password_Select(value);
|
||||
return;
|
||||
}
|
||||
|
|
@ -167,7 +176,8 @@ void selgame_GameSelection_Select(int value)
|
|||
vecSelGameDialog.push_back(std::make_unique<UiArtText>(selgame_Description, rect3, UiFlags::FontSize12 | UiFlags::ColorUiSilverDark, 1, 16));
|
||||
|
||||
switch (value) {
|
||||
case 0: {
|
||||
case 0:
|
||||
case 1: {
|
||||
title = _("Create Game");
|
||||
|
||||
SDL_Rect rect4 = { (Sint16)(PANEL_LEFT + 299), (Sint16)(UI_OFFSET_Y + 211), 295, 35 };
|
||||
|
|
@ -188,14 +198,14 @@ void selgame_GameSelection_Select(int value)
|
|||
UiInitList(vecSelGameDlgItems.size(), selgame_Diff_Focus, selgame_Diff_Select, selgame_Diff_Esc, vecSelGameDialog, true);
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
case 2: {
|
||||
title = _("Join TCP Games");
|
||||
|
||||
SDL_Rect rect4 = { (Sint16)(PANEL_LEFT + 305), (Sint16)(UI_OFFSET_Y + 211), 285, 33 };
|
||||
vecSelGameDialog.push_back(std::make_unique<UiArtText>(_("Enter address"), rect4, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiSilver, 3));
|
||||
|
||||
SDL_Rect rect5 = { (Sint16)(PANEL_LEFT + 305), (Sint16)(UI_OFFSET_Y + 314), 285, 33 };
|
||||
vecSelGameDialog.push_back(std::make_unique<UiEdit>(_("Enter address"), selgame_Ip, 128, rect5, UiFlags::FontSize24 | UiFlags::ColorUiGold));
|
||||
vecSelGameDialog.push_back(std::make_unique<UiEdit>(_("Enter address"), selgame_Ip, 128, false, rect5, UiFlags::FontSize24 | UiFlags::ColorUiGold));
|
||||
|
||||
SDL_Rect rect6 = { (Sint16)(PANEL_LEFT + 299), (Sint16)(UI_OFFSET_Y + 427), 140, 35 };
|
||||
vecSelGameDialog.push_back(std::make_unique<UiArtTextButton>(_("OK"), &UiFocusNavigationSelect, rect6, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontSize30 | UiFlags::ColorUiGold));
|
||||
|
|
@ -204,7 +214,12 @@ void selgame_GameSelection_Select(int value)
|
|||
vecSelGameDialog.push_back(std::make_unique<UiArtTextButton>(_("CANCEL"), &UiFocusNavigationEsc, rect7, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontSize30 | UiFlags::ColorUiGold));
|
||||
|
||||
HighlightedItem = 0;
|
||||
|
||||
#ifdef PACKET_ENCRYPTION
|
||||
UiInitList(0, nullptr, selgame_Password_Init, selgame_GameSelection_Init, vecSelGameDialog);
|
||||
#else
|
||||
UiInitList(0, nullptr, selgame_Password_Select, selgame_GameSelection_Init, vecSelGameDialog);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -375,7 +390,7 @@ void selgame_Speed_Select(int value)
|
|||
{
|
||||
nTickRate = vecSelGameDlgItems[value]->m_value;
|
||||
|
||||
if (provider == SELCONN_LOOPBACK) {
|
||||
if (provider == SELCONN_LOOPBACK || selgame_selectedGame == 1) {
|
||||
selgame_Password_Select(0);
|
||||
return;
|
||||
}
|
||||
|
|
@ -404,8 +419,10 @@ void selgame_Password_Init(int /*value*/)
|
|||
SDL_Rect rect4 = { (Sint16)(PANEL_LEFT + 305), (Sint16)(UI_OFFSET_Y + 211), 285, 33 };
|
||||
vecSelGameDialog.push_back(std::make_unique<UiArtText>(_("Enter Password"), rect4, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiSilver, 3));
|
||||
|
||||
// Allow password to be empty only when joining games
|
||||
bool allowEmpty = selgame_selectedGame == 2;
|
||||
SDL_Rect rect5 = { (Sint16)(PANEL_LEFT + 305), (Sint16)(UI_OFFSET_Y + 314), 285, 33 };
|
||||
vecSelGameDialog.push_back(std::make_unique<UiEdit>(_("Enter Password"), selgame_Password, 15, rect5, UiFlags::FontSize24 | UiFlags::ColorUiGold));
|
||||
vecSelGameDialog.push_back(std::make_unique<UiEdit>(_("Enter Password"), selgame_Password, 15, allowEmpty, rect5, UiFlags::FontSize24 | UiFlags::ColorUiGold));
|
||||
|
||||
SDL_Rect rect6 = { (Sint16)(PANEL_LEFT + 299), (Sint16)(UI_OFFSET_Y + 427), 140, 35 };
|
||||
vecSelGameDialog.push_back(std::make_unique<UiArtTextButton>(_("OK"), &UiFocusNavigationSelect, rect6, UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::FontSize30 | UiFlags::ColorUiGold));
|
||||
|
|
@ -443,9 +460,15 @@ static bool IsGameCompatible(const GameData &data)
|
|||
|
||||
void selgame_Password_Select(int /*value*/)
|
||||
{
|
||||
if (selgame_selectedGame != 0) {
|
||||
char *gamePassword = nullptr;
|
||||
if (selgame_selectedGame == 0)
|
||||
gamePassword = selgame_Password;
|
||||
if (selgame_selectedGame == 2 && strlen(selgame_Password) > 0)
|
||||
gamePassword = selgame_Password;
|
||||
|
||||
if (selgame_selectedGame > 1) {
|
||||
strcpy(sgOptions.Network.szPreviousHost, selgame_Ip);
|
||||
if (SNetJoinGame(selgame_Ip, selgame_Password, gdwPlayerId)) {
|
||||
if (SNetJoinGame(selgame_Ip, gamePassword, gdwPlayerId)) {
|
||||
if (!IsGameCompatible(*m_game_data)) {
|
||||
selgame_GameSelection_Select(1);
|
||||
return;
|
||||
|
|
@ -468,7 +491,7 @@ void selgame_Password_Select(int /*value*/)
|
|||
m_game_data->bTheoQuest = sgOptions.Gameplay.bTheoQuest ? 1 : 0;
|
||||
m_game_data->bCowQuest = sgOptions.Gameplay.bCowQuest ? 1 : 0;
|
||||
|
||||
if (SNetCreateGame(nullptr, selgame_Password, (char *)m_game_data, sizeof(*m_game_data), gdwPlayerId)) {
|
||||
if (SNetCreateGame(nullptr, gamePassword, (char *)m_game_data, sizeof(*m_game_data), gdwPlayerId)) {
|
||||
UiInitList_clear();
|
||||
selgame_endMenu = true;
|
||||
} else {
|
||||
|
|
@ -481,8 +504,8 @@ void selgame_Password_Select(int /*value*/)
|
|||
|
||||
void selgame_Password_Esc()
|
||||
{
|
||||
if (selgame_selectedGame == 1)
|
||||
selgame_GameSelection_Select(1);
|
||||
if (selgame_selectedGame == 2)
|
||||
selgame_GameSelection_Select(2);
|
||||
else
|
||||
selgame_GameSpeedSelection();
|
||||
}
|
||||
|
|
@ -524,7 +547,7 @@ bool UiSelectGame(GameData *gameData, int *playerId)
|
|||
|
||||
selgame_endMenu = false;
|
||||
|
||||
DvlNet_SetPassword(DefaultPassword);
|
||||
DvlNet_ClearPassword();
|
||||
DvlNet_ClearGamelist();
|
||||
|
||||
while (!selgame_endMenu) {
|
||||
|
|
|
|||
|
|
@ -275,7 +275,7 @@ void SelheroClassSelectorSelect(int value)
|
|||
vecSelDlgItems.push_back(std::make_unique<UiArtText>(_("Enter Name"), rect1, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiSilver, 3));
|
||||
|
||||
SDL_Rect rect2 = { (Sint16)(PANEL_LEFT + 265), (Sint16)(UI_OFFSET_Y + 317), 320, 33 };
|
||||
vecSelDlgItems.push_back(std::make_unique<UiEdit>(_("Enter Name"), selhero_heroInfo.name, 15, rect2, UiFlags::FontSize24 | UiFlags::ColorUiGold));
|
||||
vecSelDlgItems.push_back(std::make_unique<UiEdit>(_("Enter Name"), selhero_heroInfo.name, 15, false, rect2, UiFlags::FontSize24 | UiFlags::ColorUiGold));
|
||||
|
||||
SDL_Rect rect3 = { (Sint16)(PANEL_LEFT + 279), (Sint16)(UI_OFFSET_Y + 429), 140, 35 };
|
||||
vecSelDlgItems.push_back(std::make_unique<UiArtTextButton>(_("OK"), &UiFocusNavigationSelect, rect3, UiFlags::AlignCenter | UiFlags::FontSize30 | UiFlags::ColorUiGold));
|
||||
|
|
|
|||
|
|
@ -224,11 +224,12 @@ public:
|
|||
|
||||
class UiEdit : public UiItemBase {
|
||||
public:
|
||||
UiEdit(const char *hint, char *value, std::size_t max_length, SDL_Rect rect, UiFlags flags = UiFlags::None)
|
||||
UiEdit(const char *hint, char *value, std::size_t max_length, bool allowEmpty, SDL_Rect rect, UiFlags flags = UiFlags::None)
|
||||
: UiItemBase(UiType::Edit, rect, flags)
|
||||
, m_hint(hint)
|
||||
, m_value(value)
|
||||
, m_max_length(max_length)
|
||||
, m_allowEmpty(allowEmpty)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -236,6 +237,7 @@ public:
|
|||
const char *m_hint;
|
||||
char *m_value;
|
||||
std::size_t m_max_length;
|
||||
bool m_allowEmpty;
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
|
|
|
|||
|
|
@ -466,11 +466,12 @@ void DrawAutomapText(const Surface &out)
|
|||
linePosition.y += 15;
|
||||
}
|
||||
|
||||
if (szPlayerDescript[0] != '\0') {
|
||||
if (!PublicGame)
|
||||
strcat(strcpy(desc, _("password: ")), szPlayerDescript);
|
||||
DrawString(out, desc, linePosition);
|
||||
linePosition.y += 15;
|
||||
}
|
||||
else
|
||||
strcpy(desc, _("Public Game"));
|
||||
DrawString(out, desc, linePosition);
|
||||
linePosition.y += 15;
|
||||
}
|
||||
|
||||
if (setlevel) {
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ public:
|
|||
|
||||
class abstract_net {
|
||||
public:
|
||||
virtual int create(std::string addrstr, std::string passwd) = 0;
|
||||
virtual int join(std::string addrstr, std::string passwd) = 0;
|
||||
virtual int create(std::string addrstr) = 0;
|
||||
virtual int join(std::string addrstr) = 0;
|
||||
virtual bool SNetReceiveMessage(int *sender, void **data, uint32_t *size) = 0;
|
||||
virtual bool SNetSendMessage(int dest, void *data, unsigned int size) = 0;
|
||||
virtual bool SNetReceiveTurns(char **data, size_t *size, uint32_t *status) = 0;
|
||||
|
|
@ -44,6 +44,10 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual void clear_password()
|
||||
{
|
||||
}
|
||||
|
||||
virtual void send_info_request()
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,11 @@ void base::setup_password(std::string pw)
|
|||
pktfty = std::make_unique<packet_factory>(pw);
|
||||
}
|
||||
|
||||
void base::clear_password()
|
||||
{
|
||||
pktfty = std::make_unique<packet_factory>();
|
||||
}
|
||||
|
||||
void base::RunEventHandler(_SNETEVENT &ev)
|
||||
{
|
||||
auto f = registered_handlers[static_cast<event_type>(ev.eventid)];
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ namespace net {
|
|||
|
||||
class base : public abstract_net {
|
||||
public:
|
||||
virtual int create(std::string addrstr, std::string passwd) = 0;
|
||||
virtual int join(std::string addrstr, std::string passwd) = 0;
|
||||
virtual int create(std::string addrstr) = 0;
|
||||
virtual int join(std::string addrstr) = 0;
|
||||
|
||||
virtual bool SNetReceiveMessage(int *sender, void **data, uint32_t *size);
|
||||
virtual bool SNetSendMessage(int playerId, void *data, unsigned int size);
|
||||
|
|
@ -37,6 +37,7 @@ public:
|
|||
void setup_gameinfo(buffer_t info);
|
||||
|
||||
virtual void setup_password(std::string pw);
|
||||
virtual void clear_password();
|
||||
|
||||
virtual ~base() = default;
|
||||
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ namespace net {
|
|||
template <class P>
|
||||
class base_protocol : public base {
|
||||
public:
|
||||
virtual int create(std::string addrstr, std::string passwd);
|
||||
virtual int join(std::string addrstr, std::string passwd);
|
||||
virtual int create(std::string addrstr);
|
||||
virtual int join(std::string addrstr);
|
||||
virtual void poll();
|
||||
virtual void send(packet &pkt);
|
||||
virtual void DisconnectNet(plr_t plr);
|
||||
|
|
@ -108,8 +108,7 @@ void base_protocol<P>::send_info_request()
|
|||
template <class P>
|
||||
void base_protocol<P>::wait_join()
|
||||
{
|
||||
randombytes_buf(reinterpret_cast<unsigned char *>(&cookie_self),
|
||||
sizeof(cookie_t));
|
||||
cookie_self = packet_out::GenerateCookie();
|
||||
auto pkt = pktfty->make_packet<PT_JOIN_REQUEST>(PLR_BROADCAST,
|
||||
PLR_MASTER, cookie_self, game_init_info);
|
||||
proto.send(firstpeer, pkt->Data());
|
||||
|
|
@ -122,9 +121,8 @@ void base_protocol<P>::wait_join()
|
|||
}
|
||||
|
||||
template <class P>
|
||||
int base_protocol<P>::create(std::string addrstr, std::string passwd)
|
||||
int base_protocol<P>::create(std::string addrstr)
|
||||
{
|
||||
setup_password(passwd);
|
||||
gamename = addrstr;
|
||||
|
||||
if (wait_network()) {
|
||||
|
|
@ -136,10 +134,8 @@ int base_protocol<P>::create(std::string addrstr, std::string passwd)
|
|||
}
|
||||
|
||||
template <class P>
|
||||
int base_protocol<P>::join(std::string addrstr, std::string passwd)
|
||||
int base_protocol<P>::join(std::string addrstr)
|
||||
{
|
||||
//addrstr = "fd80:56c2:e21c:0:199:931d:b14:c4d2";
|
||||
setup_password(passwd);
|
||||
gamename = addrstr;
|
||||
if (wait_network())
|
||||
if (wait_firstpeer())
|
||||
|
|
|
|||
|
|
@ -17,12 +17,13 @@ private:
|
|||
std::unique_ptr<abstract_net> dvlnet_wrap;
|
||||
std::map<event_type, SEVTHANDLER> registered_handlers;
|
||||
buffer_t game_init_info;
|
||||
std::optional<std::string> game_pw;
|
||||
|
||||
void reset();
|
||||
|
||||
public:
|
||||
virtual int create(std::string addrstr, std::string passwd);
|
||||
virtual int join(std::string addrstr, std::string passwd);
|
||||
virtual int create(std::string addrstr);
|
||||
virtual int join(std::string addrstr);
|
||||
virtual bool SNetReceiveMessage(int *sender, void **data, uint32_t *size);
|
||||
virtual bool SNetSendMessage(int dest, void *data, unsigned int size);
|
||||
virtual bool SNetReceiveTurns(char **data, size_t *size, uint32_t *status);
|
||||
|
|
@ -41,6 +42,7 @@ public:
|
|||
virtual void clear_gamelist();
|
||||
virtual std::vector<std::string> get_gamelist();
|
||||
virtual void setup_password(std::string pw);
|
||||
virtual void clear_password();
|
||||
|
||||
cdwrap();
|
||||
virtual ~cdwrap() = default;
|
||||
|
|
@ -58,23 +60,28 @@ void cdwrap<T>::reset()
|
|||
dvlnet_wrap.reset(new T);
|
||||
dvlnet_wrap->setup_gameinfo(game_init_info);
|
||||
|
||||
if (game_pw != std::nullopt)
|
||||
dvlnet_wrap->setup_password(*game_pw);
|
||||
else
|
||||
dvlnet_wrap->clear_password();
|
||||
|
||||
for (const auto &pair : registered_handlers)
|
||||
dvlnet_wrap->SNetRegisterEventHandler(pair.first, pair.second);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
int cdwrap<T>::create(std::string addrstr, std::string passwd)
|
||||
int cdwrap<T>::create(std::string addrstr)
|
||||
{
|
||||
reset();
|
||||
return dvlnet_wrap->create(addrstr, passwd);
|
||||
return dvlnet_wrap->create(addrstr);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
int cdwrap<T>::join(std::string addrstr, std::string passwd)
|
||||
int cdwrap<T>::join(std::string addrstr)
|
||||
{
|
||||
game_init_info = buffer_t();
|
||||
reset();
|
||||
return dvlnet_wrap->join(addrstr, passwd);
|
||||
return dvlnet_wrap->join(addrstr);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
|
|
@ -186,8 +193,16 @@ std::vector<std::string> cdwrap<T>::get_gamelist()
|
|||
template <class T>
|
||||
void cdwrap<T>::setup_password(std::string pw)
|
||||
{
|
||||
game_pw = pw;
|
||||
return dvlnet_wrap->setup_password(pw);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void cdwrap<T>::clear_password()
|
||||
{
|
||||
game_pw = std::nullopt;
|
||||
return dvlnet_wrap->clear_password();
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace devilution
|
||||
|
|
|
|||
|
|
@ -5,12 +5,12 @@
|
|||
namespace devilution {
|
||||
namespace net {
|
||||
|
||||
int loopback::create(std::string /*addrstr*/, std::string /*passwd*/)
|
||||
int loopback::create(std::string /*addrstr*/)
|
||||
{
|
||||
return plr_single;
|
||||
}
|
||||
|
||||
int loopback::join(std::string /*addrstr*/, std::string /*passwd*/)
|
||||
int loopback::join(std::string /*addrstr*/)
|
||||
{
|
||||
ABORT();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ public:
|
|||
plr_single = 0;
|
||||
};
|
||||
|
||||
virtual int create(std::string addrstr, std::string passwd);
|
||||
virtual int join(std::string addrstr, std::string passwd);
|
||||
virtual int create(std::string addrstr);
|
||||
virtual int join(std::string addrstr);
|
||||
virtual bool SNetReceiveMessage(int *sender, void **data, uint32_t *size);
|
||||
virtual bool SNetSendMessage(int dest, void *data, unsigned int size);
|
||||
virtual bool SNetReceiveTurns(char **data, size_t *size, uint32_t *status);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,52 @@
|
|||
#ifdef PACKET_ENCRYPTION
|
||||
#include <sodium.h>
|
||||
#else
|
||||
#include <chrono>
|
||||
#include <random>
|
||||
#endif
|
||||
|
||||
#include "dvlnet/packet.h"
|
||||
|
||||
namespace devilution {
|
||||
namespace net {
|
||||
|
||||
#ifndef NONET
|
||||
static constexpr bool DisableEncryption = false;
|
||||
#ifdef PACKET_ENCRYPTION
|
||||
|
||||
cookie_t packet_out::GenerateCookie()
|
||||
{
|
||||
cookie_t cookie;
|
||||
randombytes_buf(reinterpret_cast<unsigned char *>(&cookie),
|
||||
sizeof(cookie_t));
|
||||
return cookie;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
class cookie_generator {
|
||||
public:
|
||||
cookie_generator()
|
||||
{
|
||||
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
|
||||
generator.seed(seed);
|
||||
}
|
||||
|
||||
cookie_t NewCookie()
|
||||
{
|
||||
return distribution(generator);
|
||||
}
|
||||
|
||||
private:
|
||||
std::default_random_engine generator;
|
||||
std::uniform_int_distribution<cookie_t> distribution;
|
||||
};
|
||||
|
||||
cookie_generator CookieGenerator;
|
||||
|
||||
cookie_t packet_out::GenerateCookie()
|
||||
{
|
||||
return CookieGenerator.NewCookie();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
const char *packet_type_to_string(uint8_t packetType)
|
||||
|
|
@ -66,158 +108,153 @@ void CheckPacketTypeOneOf(std::initializer_list<packet_type> expectedTypes, std:
|
|||
|
||||
const buffer_t &packet::Data()
|
||||
{
|
||||
if (!have_decrypted || !have_encrypted)
|
||||
ABORT();
|
||||
return encrypted_buffer;
|
||||
assert(have_encrypted || have_decrypted);
|
||||
if (have_encrypted)
|
||||
return encrypted_buffer;
|
||||
return decrypted_buffer;
|
||||
}
|
||||
|
||||
packet_type packet::Type()
|
||||
{
|
||||
if (!have_decrypted)
|
||||
ABORT();
|
||||
assert(have_decrypted);
|
||||
return m_type;
|
||||
}
|
||||
|
||||
plr_t packet::Source() const
|
||||
{
|
||||
if (!have_decrypted)
|
||||
ABORT();
|
||||
assert(have_decrypted);
|
||||
return m_src;
|
||||
}
|
||||
|
||||
plr_t packet::Destination() const
|
||||
{
|
||||
if (!have_decrypted)
|
||||
ABORT();
|
||||
assert(have_decrypted);
|
||||
return m_dest;
|
||||
}
|
||||
|
||||
const buffer_t &packet::Message()
|
||||
{
|
||||
if (!have_decrypted)
|
||||
ABORT();
|
||||
assert(have_decrypted);
|
||||
CheckPacketTypeOneOf({ PT_MESSAGE }, m_type);
|
||||
return m_message;
|
||||
}
|
||||
|
||||
turn_t packet::Turn()
|
||||
{
|
||||
if (!have_decrypted)
|
||||
ABORT();
|
||||
assert(have_decrypted);
|
||||
CheckPacketTypeOneOf({ PT_TURN }, m_type);
|
||||
return m_turn;
|
||||
}
|
||||
|
||||
cookie_t packet::Cookie()
|
||||
{
|
||||
if (!have_decrypted)
|
||||
ABORT();
|
||||
assert(have_decrypted);
|
||||
CheckPacketTypeOneOf({ PT_JOIN_REQUEST, PT_JOIN_ACCEPT }, m_type);
|
||||
return m_cookie;
|
||||
}
|
||||
|
||||
plr_t packet::NewPlayer()
|
||||
{
|
||||
if (!have_decrypted)
|
||||
ABORT();
|
||||
assert(have_decrypted);
|
||||
CheckPacketTypeOneOf({ PT_JOIN_ACCEPT, PT_CONNECT, PT_DISCONNECT }, m_type);
|
||||
return m_newplr;
|
||||
}
|
||||
|
||||
const buffer_t &packet::Info()
|
||||
{
|
||||
if (!have_decrypted)
|
||||
ABORT();
|
||||
assert(have_decrypted);
|
||||
CheckPacketTypeOneOf({ PT_JOIN_REQUEST, PT_JOIN_ACCEPT, PT_CONNECT, PT_INFO_REPLY }, m_type);
|
||||
return m_info;
|
||||
}
|
||||
|
||||
leaveinfo_t packet::LeaveInfo()
|
||||
{
|
||||
if (!have_decrypted)
|
||||
ABORT();
|
||||
assert(have_decrypted);
|
||||
CheckPacketTypeOneOf({ PT_DISCONNECT }, m_type);
|
||||
return m_leaveinfo;
|
||||
}
|
||||
|
||||
void packet_in::Create(buffer_t buf)
|
||||
{
|
||||
if (have_encrypted || have_decrypted)
|
||||
ABORT();
|
||||
encrypted_buffer = std::move(buf);
|
||||
assert(!have_encrypted && !have_decrypted);
|
||||
if (buf.size() < sizeof(packet_type) + 2 * sizeof(plr_t))
|
||||
throw packet_exception();
|
||||
|
||||
decrypted_buffer = std::move(buf);
|
||||
have_decrypted = true;
|
||||
|
||||
// TCP server implementation forwards the original data to clients
|
||||
// so although we are not decrypting anything,
|
||||
// we save a copy in encrypted_buffer anyway
|
||||
encrypted_buffer = decrypted_buffer;
|
||||
have_encrypted = true;
|
||||
}
|
||||
|
||||
void packet_in::Decrypt()
|
||||
#ifdef PACKET_ENCRYPTION
|
||||
void packet_in::Decrypt(buffer_t buf)
|
||||
{
|
||||
if (!have_encrypted)
|
||||
ABORT();
|
||||
if (have_decrypted)
|
||||
return;
|
||||
#ifndef NONET
|
||||
if (!DisableEncryption) {
|
||||
if (encrypted_buffer.size() < crypto_secretbox_NONCEBYTES
|
||||
+ crypto_secretbox_MACBYTES
|
||||
+ sizeof(packet_type) + 2 * sizeof(plr_t))
|
||||
throw packet_exception();
|
||||
auto pktlen = (encrypted_buffer.size()
|
||||
- crypto_secretbox_NONCEBYTES
|
||||
- crypto_secretbox_MACBYTES);
|
||||
decrypted_buffer.resize(pktlen);
|
||||
int status = crypto_secretbox_open_easy(
|
||||
decrypted_buffer.data(),
|
||||
encrypted_buffer.data() + crypto_secretbox_NONCEBYTES,
|
||||
encrypted_buffer.size() - crypto_secretbox_NONCEBYTES,
|
||||
encrypted_buffer.data(),
|
||||
key.data());
|
||||
if (status != 0)
|
||||
throw packet_exception();
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (encrypted_buffer.size() < sizeof(packet_type) + 2 * sizeof(plr_t))
|
||||
throw packet_exception();
|
||||
decrypted_buffer = encrypted_buffer;
|
||||
}
|
||||
assert(!have_encrypted && !have_decrypted);
|
||||
encrypted_buffer = std::move(buf);
|
||||
have_encrypted = true;
|
||||
|
||||
process_data();
|
||||
if (encrypted_buffer.size() < crypto_secretbox_NONCEBYTES
|
||||
+ crypto_secretbox_MACBYTES
|
||||
+ sizeof(packet_type) + 2 * sizeof(plr_t))
|
||||
throw packet_exception();
|
||||
auto pktlen = (encrypted_buffer.size()
|
||||
- crypto_secretbox_NONCEBYTES
|
||||
- crypto_secretbox_MACBYTES);
|
||||
decrypted_buffer.resize(pktlen);
|
||||
int status = crypto_secretbox_open_easy(
|
||||
decrypted_buffer.data(),
|
||||
encrypted_buffer.data() + crypto_secretbox_NONCEBYTES,
|
||||
encrypted_buffer.size() - crypto_secretbox_NONCEBYTES,
|
||||
encrypted_buffer.data(),
|
||||
key.data());
|
||||
if (status != 0)
|
||||
throw packet_exception();
|
||||
|
||||
have_decrypted = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PACKET_ENCRYPTION
|
||||
void packet_out::Encrypt()
|
||||
{
|
||||
if (!have_decrypted)
|
||||
ABORT();
|
||||
assert(have_decrypted);
|
||||
|
||||
if (have_encrypted)
|
||||
return;
|
||||
|
||||
process_data();
|
||||
auto lenCleartext = decrypted_buffer.size();
|
||||
encrypted_buffer.insert(encrypted_buffer.begin(),
|
||||
crypto_secretbox_NONCEBYTES, 0);
|
||||
encrypted_buffer.insert(encrypted_buffer.end(),
|
||||
crypto_secretbox_MACBYTES + lenCleartext, 0);
|
||||
randombytes_buf(encrypted_buffer.data(), crypto_secretbox_NONCEBYTES);
|
||||
int status = crypto_secretbox_easy(
|
||||
encrypted_buffer.data() + crypto_secretbox_NONCEBYTES,
|
||||
decrypted_buffer.data(),
|
||||
lenCleartext,
|
||||
encrypted_buffer.data(),
|
||||
key.data());
|
||||
if (status != 0)
|
||||
ABORT();
|
||||
|
||||
#ifndef NONET
|
||||
if (!DisableEncryption) {
|
||||
auto lenCleartext = encrypted_buffer.size();
|
||||
encrypted_buffer.insert(encrypted_buffer.begin(),
|
||||
crypto_secretbox_NONCEBYTES, 0);
|
||||
encrypted_buffer.insert(encrypted_buffer.end(),
|
||||
crypto_secretbox_MACBYTES, 0);
|
||||
randombytes_buf(encrypted_buffer.data(), crypto_secretbox_NONCEBYTES);
|
||||
int status = crypto_secretbox_easy(
|
||||
encrypted_buffer.data() + crypto_secretbox_NONCEBYTES,
|
||||
encrypted_buffer.data() + crypto_secretbox_NONCEBYTES,
|
||||
lenCleartext,
|
||||
encrypted_buffer.data(),
|
||||
key.data());
|
||||
if (status != 0)
|
||||
ABORT();
|
||||
}
|
||||
#endif
|
||||
have_encrypted = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
packet_factory::packet_factory()
|
||||
{
|
||||
secure = false;
|
||||
}
|
||||
|
||||
packet_factory::packet_factory(std::string pw)
|
||||
{
|
||||
#ifndef NONET
|
||||
secure = false;
|
||||
|
||||
#ifdef PACKET_ENCRYPTION
|
||||
if (sodium_init() < 0)
|
||||
ABORT();
|
||||
pw.resize(std::min<std::size_t>(pw.size(), crypto_pwhash_argon2id_PASSWD_MAX));
|
||||
|
|
@ -235,6 +272,7 @@ packet_factory::packet_factory(std::string pw)
|
|||
crypto_pwhash_ALG_ARGON2ID13);
|
||||
if (status != 0)
|
||||
ABORT();
|
||||
secure = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
#include <memory>
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
#ifndef NONET
|
||||
#ifdef PACKET_ENCRYPTION
|
||||
#include <sodium.h>
|
||||
#endif
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ typedef uint8_t plr_t;
|
|||
typedef uint32_t cookie_t;
|
||||
typedef int turn_t; // change int to something else in devilution code later
|
||||
typedef int leaveinfo_t; // also change later
|
||||
#ifndef NONET
|
||||
#ifdef PACKET_ENCRYPTION
|
||||
typedef std::array<unsigned char, crypto_secretbox_KEYBYTES> key_t;
|
||||
#else
|
||||
// Stub out the key_t defintion as we're not doing any encryption.
|
||||
|
|
@ -115,7 +115,7 @@ public:
|
|||
void process_element(buffer_t &x);
|
||||
template <class T>
|
||||
void process_element(T &x);
|
||||
void Decrypt();
|
||||
void Decrypt(buffer_t buf);
|
||||
};
|
||||
|
||||
class packet_out : public packet_proc<packet_out> {
|
||||
|
|
@ -132,6 +132,7 @@ public:
|
|||
static const unsigned char *begin(const T &x);
|
||||
template <class T>
|
||||
static const unsigned char *end(const T &x);
|
||||
static cookie_t GenerateCookie();
|
||||
void Encrypt();
|
||||
};
|
||||
|
||||
|
|
@ -307,13 +308,13 @@ inline void packet_out::create<PT_DISCONNECT>(plr_t s, plr_t d, plr_t n,
|
|||
|
||||
inline void packet_out::process_element(buffer_t &x)
|
||||
{
|
||||
encrypted_buffer.insert(encrypted_buffer.end(), x.begin(), x.end());
|
||||
decrypted_buffer.insert(decrypted_buffer.end(), x.begin(), x.end());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void packet_out::process_element(T &x)
|
||||
{
|
||||
encrypted_buffer.insert(encrypted_buffer.end(), begin(x), end(x));
|
||||
decrypted_buffer.insert(decrypted_buffer.end(), begin(x), end(x));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
|
|
@ -330,11 +331,13 @@ const unsigned char *packet_out::end(const T &x)
|
|||
|
||||
class packet_factory {
|
||||
key_t key = {};
|
||||
bool secure;
|
||||
|
||||
public:
|
||||
static constexpr unsigned short max_packet_size = 0xFFFF;
|
||||
|
||||
packet_factory(std::string pw = "");
|
||||
packet_factory();
|
||||
packet_factory(std::string pw);
|
||||
std::unique_ptr<packet> make_packet(buffer_t buf);
|
||||
template <packet_type t, typename... Args>
|
||||
std::unique_ptr<packet> make_packet(Args... args);
|
||||
|
|
@ -343,8 +346,16 @@ public:
|
|||
inline std::unique_ptr<packet> packet_factory::make_packet(buffer_t buf)
|
||||
{
|
||||
auto ret = std::make_unique<packet_in>(key);
|
||||
#ifndef PACKET_ENCRYPTION
|
||||
ret->Create(std::move(buf));
|
||||
ret->Decrypt();
|
||||
#else
|
||||
if (!secure)
|
||||
ret->Create(std::move(buf));
|
||||
else
|
||||
ret->Decrypt(std::move(buf));
|
||||
#endif
|
||||
size_t size = ret->Data().size();
|
||||
ret->process_data();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -353,7 +364,11 @@ std::unique_ptr<packet> packet_factory::make_packet(Args... args)
|
|||
{
|
||||
auto ret = std::make_unique<packet_out>(key);
|
||||
ret->create<t>(args...);
|
||||
ret->Encrypt();
|
||||
ret->process_data();
|
||||
#ifdef PACKET_ENCRYPTION
|
||||
if (secure)
|
||||
ret->Encrypt();
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
#include <exception>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <sodium.h>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <system_error>
|
||||
|
|
@ -16,24 +15,23 @@
|
|||
namespace devilution {
|
||||
namespace net {
|
||||
|
||||
int tcp_client::create(std::string addrstr, std::string passwd)
|
||||
int tcp_client::create(std::string addrstr)
|
||||
{
|
||||
try {
|
||||
auto port = sgOptions.Network.nPort;
|
||||
local_server = std::make_unique<tcp_server>(ioc, addrstr, port, passwd);
|
||||
return join(local_server->LocalhostSelf(), passwd);
|
||||
local_server = std::make_unique<tcp_server>(ioc, addrstr, port, *pktfty);
|
||||
return join(local_server->LocalhostSelf());
|
||||
} catch (std::system_error &e) {
|
||||
SDL_SetError("%s", e.what());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int tcp_client::join(std::string addrstr, std::string passwd)
|
||||
int tcp_client::join(std::string addrstr)
|
||||
{
|
||||
constexpr int MsSleep = 10;
|
||||
constexpr int NoSleep = 250;
|
||||
|
||||
setup_password(passwd);
|
||||
try {
|
||||
std::stringstream port;
|
||||
port << sgOptions.Network.nPort;
|
||||
|
|
@ -46,8 +44,7 @@ int tcp_client::join(std::string addrstr, std::string passwd)
|
|||
}
|
||||
StartReceive();
|
||||
{
|
||||
randombytes_buf(reinterpret_cast<unsigned char *>(&cookie_self),
|
||||
sizeof(cookie_t));
|
||||
cookie_self = packet_out::GenerateCookie();
|
||||
auto pkt = pktfty->make_packet<PT_JOIN_REQUEST>(PLR_BROADCAST,
|
||||
PLR_MASTER, cookie_self,
|
||||
game_init_info);
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ namespace net {
|
|||
|
||||
class tcp_client : public base {
|
||||
public:
|
||||
int create(std::string addrstr, std::string passwd);
|
||||
int join(std::string addrstr, std::string passwd);
|
||||
int create(std::string addrstr);
|
||||
int join(std::string addrstr);
|
||||
|
||||
virtual void poll();
|
||||
virtual void send(packet &pkt);
|
||||
|
|
|
|||
|
|
@ -12,9 +12,9 @@ namespace devilution {
|
|||
namespace net {
|
||||
|
||||
tcp_server::tcp_server(asio::io_context &ioc, const std::string &bindaddr,
|
||||
unsigned short port, std::string pw)
|
||||
unsigned short port, packet_factory &pktfty)
|
||||
: ioc(ioc)
|
||||
, pktfty(std::move(pw))
|
||||
, pktfty(pktfty)
|
||||
{
|
||||
auto addr = asio::ip::address::from_string(bindaddr);
|
||||
auto ep = asio::ip::tcp::endpoint(addr, port);
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ public:
|
|||
class tcp_server {
|
||||
public:
|
||||
tcp_server(asio::io_context &ioc, const std::string &bindaddr,
|
||||
unsigned short port, std::string pw);
|
||||
unsigned short port, packet_factory &pktfty);
|
||||
std::string LocalhostSelf();
|
||||
void Close();
|
||||
virtual ~tcp_server();
|
||||
|
|
@ -52,7 +52,7 @@ private:
|
|||
typedef std::shared_ptr<client_connection> scc;
|
||||
|
||||
asio::io_context &ioc;
|
||||
packet_factory pktfty;
|
||||
packet_factory &pktfty;
|
||||
std::unique_ptr<asio::ip::tcp::acceptor> acceptor;
|
||||
std::array<scc, MAX_PLRS> connections;
|
||||
buffer_t game_init_info;
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ DWORD sgdwGameLoops;
|
|||
bool gbIsMultiplayer;
|
||||
bool sgbTimeout;
|
||||
char szPlayerName[128];
|
||||
bool PublicGame;
|
||||
BYTE gbDeltaSender;
|
||||
bool sgbNetInited;
|
||||
uint32_t player_state[MAX_PLRS];
|
||||
|
|
@ -752,6 +753,7 @@ bool NetInit(bool bSinglePlayer)
|
|||
nthread_terminate_game("SNetGetGameInfo1");
|
||||
if (!SNetGetGameInfo(GAMEINFO_PASSWORD, szPlayerDescript, 128))
|
||||
nthread_terminate_game("SNetGetGameInfo2");
|
||||
PublicGame = DvlNet_IsPublicGame();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ extern GameData sgGameInitInfo;
|
|||
extern bool gbSelectProvider;
|
||||
extern bool gbIsMultiplayer;
|
||||
extern char szPlayerName[128];
|
||||
extern bool PublicGame;
|
||||
extern BYTE gbDeltaSender;
|
||||
extern uint32_t player_state[MAX_PLRS];
|
||||
|
||||
|
|
|
|||
|
|
@ -293,5 +293,7 @@ void DvlNet_SendInfoRequest();
|
|||
void DvlNet_ClearGamelist();
|
||||
std::vector<std::string> DvlNet_GetGamelist();
|
||||
void DvlNet_SetPassword(std::string pw);
|
||||
void DvlNet_ClearPassword();
|
||||
bool DvlNet_IsPublicGame();
|
||||
|
||||
} // namespace devilution
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ namespace devilution {
|
|||
static std::unique_ptr<net::abstract_net> dvlnet_inst;
|
||||
static char gpszGameName[128] = {};
|
||||
static char gpszGamePassword[128] = {};
|
||||
static bool GameIsPublic = {};
|
||||
|
||||
#ifndef NONET
|
||||
static SdlMutex storm_net_mutex;
|
||||
|
|
@ -165,8 +166,10 @@ bool SNetCreateGame(const char *pszGameName, const char *pszGamePassword, char *
|
|||
|
||||
strncpy(gpszGameName, pszGameName, sizeof(gpszGameName) - 1);
|
||||
if (pszGamePassword != nullptr)
|
||||
strncpy(gpszGamePassword, pszGamePassword, sizeof(gpszGamePassword) - 1);
|
||||
*playerID = dvlnet_inst->create(pszGameName, pszGamePassword);
|
||||
DvlNet_SetPassword(pszGamePassword);
|
||||
else
|
||||
DvlNet_ClearPassword();
|
||||
*playerID = dvlnet_inst->create(pszGameName);
|
||||
return *playerID != -1;
|
||||
}
|
||||
|
||||
|
|
@ -178,8 +181,10 @@ bool SNetJoinGame(char *pszGameName, char *pszGamePassword, int *playerID)
|
|||
if (pszGameName != nullptr)
|
||||
strncpy(gpszGameName, pszGameName, sizeof(gpszGameName) - 1);
|
||||
if (pszGamePassword != nullptr)
|
||||
strncpy(gpszGamePassword, pszGamePassword, sizeof(gpszGamePassword) - 1);
|
||||
*playerID = dvlnet_inst->join(pszGameName, pszGamePassword);
|
||||
DvlNet_SetPassword(pszGamePassword);
|
||||
else
|
||||
DvlNet_ClearPassword();
|
||||
*playerID = dvlnet_inst->join(pszGameName);
|
||||
return *playerID != -1;
|
||||
}
|
||||
|
||||
|
|
@ -230,7 +235,21 @@ std::vector<std::string> DvlNet_GetGamelist()
|
|||
|
||||
void DvlNet_SetPassword(std::string pw)
|
||||
{
|
||||
GameIsPublic = false;
|
||||
strncpy(gpszGamePassword, pw.c_str(), sizeof(gpszGamePassword) - 1);
|
||||
dvlnet_inst->setup_password(std::move(pw));
|
||||
}
|
||||
|
||||
void DvlNet_ClearPassword()
|
||||
{
|
||||
GameIsPublic = true;
|
||||
gpszGamePassword[0] = '\0';
|
||||
dvlnet_inst->clear_password();
|
||||
}
|
||||
|
||||
bool DvlNet_IsPublicGame()
|
||||
{
|
||||
return GameIsPublic;
|
||||
}
|
||||
|
||||
} // namespace devilution
|
||||
|
|
|
|||
|
|
@ -4,10 +4,13 @@
|
|||
"dependencies": [
|
||||
"fmt",
|
||||
"libpng",
|
||||
"libsodium",
|
||||
"sdl2"
|
||||
],
|
||||
"features": {
|
||||
"encryption": {
|
||||
"description": "Build libsodium for packet encryption",
|
||||
"dependencies": [ "libsodium" ]
|
||||
},
|
||||
"translations": {
|
||||
"description": "Build translation files",
|
||||
"dependencies": [
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue