1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2025-12-23 15:52:55 +01:00

allow host to specify password #2072

This commit is contained in:
zsilencer
2015-11-01 17:28:53 -07:00
committed by IntelOrca
parent d66eb70f56
commit 3b639ced47
11 changed files with 285 additions and 27 deletions

View File

@@ -3904,6 +3904,8 @@ STR_5562 :WARNING!
STR_5563 :This feature is currently unstable, take extra caution.
STR_5564 :Insert Corrupt Element
STR_5565 :{SMALLFONT}{BLACK}Inserts a corrupt map element at top of tile. This will hide any element above the corrupt element.
STR_5566 :Password:
STR_5567 :Advertise
#####################
# Rides/attractions #

View File

@@ -103,6 +103,7 @@
<ClCompile Include="..\src\windows\network_status.c" />
<ClCompile Include="..\src\windows\player_list.c" />
<ClCompile Include="..\src\windows\server_list.c" />
<ClCompile Include="..\src\windows\server_start.c" />
<ClCompile Include="..\src\windows\title_command_editor.c" />
<ClCompile Include="..\src\windows\title_editor.c" />
<ClCompile Include="..\src\windows\maze_construction.c" />

View File

@@ -546,6 +546,9 @@
<ClCompile Include="..\src\platform\linux.c">
<Filter>Source\Platform</Filter>
</ClCompile>
<ClCompile Include="..\src\windows\server_start.c">
<Filter>Source\Windows</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\management\award.h">

View File

@@ -239,7 +239,8 @@ config_property_definition _twitchDefinitions[] = {
config_property_definition _networkDefinitions[] = {
{ offsetof(network_configuration, player_name), "player_name", CONFIG_VALUE_TYPE_STRING, {.value_string = "Player" }, NULL },
{ offsetof(network_configuration, default_port), "default_port", CONFIG_VALUE_TYPE_UINT32, NETWORK_DEFAULT_PORT, NULL },
{ offsetof(network_configuration, stay_connected), "stay_connected", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL },
{ offsetof(network_configuration, stay_connected), "stay_connected", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL },
{ offsetof(network_configuration, advertise), "advertise", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL },
};
config_section_definition _sectionDefinitions[] = {

View File

@@ -214,6 +214,7 @@ typedef struct {
utf8string player_name;
uint32 default_port;
uint8 stay_connected;
uint8 advertise;
} network_configuration;
typedef struct theme_window {

View File

@@ -450,6 +450,7 @@ enum {
WC_PLAYER_LIST = 125,
WC_NETWORK_STATUS = 126,
WC_SERVER_LIST = 127,
WC_SERVER_START = 128,
// Only used for colour schemes
WC_STAFF = 220,
@@ -629,6 +630,7 @@ void window_player_list_open();
void window_network_status_open(const char* text);
void window_network_status_close();
void window_server_list_open();
void window_server_start_open();
void window_research_open();
void window_research_development_page_paint(rct_window *w, rct_drawpixelinfo *dpi, int baseWidgetIndex);

View File

@@ -2154,6 +2154,9 @@ enum {
STR_INSERT_CORRUPT = 5564,
STR_INSERT_CORRUPT_TIP = 5565,
STR_PASSWORD = 5566,
STR_ADVERTISE = 5567,
// Have to include resource strings (from scenarios and objects) for the time being now that language is partially working
STR_COUNT = 32768
};

View File

@@ -67,7 +67,8 @@ enum {
NETWORK_COMMAND_PING,
NETWORK_COMMAND_PINGLIST,
NETWORK_COMMAND_SETDISCONNECTMSG,
NETWORK_COMMAND_MAX
NETWORK_COMMAND_MAX,
NETWORK_COMMAND_INVALID = -1
};
const char *NetworkCommandNames[] = {
@@ -104,6 +105,15 @@ uint8* NetworkPacket::GetData()
return &(*data)[0];
}
uint32 NetworkPacket::GetCommand()
{
if (data->size() >= sizeof(uint32)) {
return ByteSwapBE(*(uint32*)(&(*data)[0]));
} else {
return NETWORK_COMMAND_INVALID;
}
}
void NetworkPacket::Write(uint8* bytes, unsigned int size)
{
data->insert(data->end(), bytes, bytes + size);
@@ -147,6 +157,18 @@ void NetworkPacket::Clear()
data->clear();
}
bool NetworkPacket::CommandRequiresAuth()
{
switch (GetCommand()) {
case NETWORK_COMMAND_PING:
return false;
case NETWORK_COMMAND_AUTH:
return false;
default:
return true;
}
}
NetworkPlayer::NetworkPlayer(const char* name)
{
safe_strncpy((char*)NetworkPlayer::name, name, sizeof(NetworkPlayer::name));
@@ -234,7 +256,7 @@ bool NetworkConnection::SendPacket(NetworkPacket& packet)
void NetworkConnection::QueuePacket(std::unique_ptr<NetworkPacket> packet)
{
if (authstatus == NETWORK_AUTH_OK || authstatus == NETWORK_AUTH_REQUESTED) {
if (authstatus == NETWORK_AUTH_OK || !packet->CommandRequiresAuth()) {
packet->size = (uint16)packet->data->size();
outboundpackets.push_back(std::move(packet));
}
@@ -573,7 +595,7 @@ void Network::UpdateClient()
bool connectfailed = false;
switch(status){
case NETWORK_STATUS_RESOLVING:{
if(server_address.GetResolveStatus() == NetworkAddress::RESOLVE_OK){
if (server_address.GetResolveStatus() == NetworkAddress::RESOLVE_OK) {
server_connection.socket = socket(server_address.ss->ss_family, SOCK_STREAM, IPPROTO_TCP);
if (server_connection.socket == INVALID_SOCKET) {
log_error("Unable to create socket.");
@@ -606,8 +628,7 @@ void Network::UpdateClient()
int error = 0;
socklen_t len = sizeof(error);
int result = getsockopt(server_connection.socket, SOL_SOCKET, SO_ERROR, (char*)&error, &len);
if (result != 0)
{
if (result != 0) {
log_error("getsockopt failed with error %d", LAST_SOCKET_ERROR());
break;
}
@@ -631,8 +652,7 @@ void Network::UpdateClient()
error = 0;
socklen_t len = sizeof(error);
result = getsockopt(server_connection.socket, SOL_SOCKET, SO_ERROR, (char*)&error, &len);
if (result != 0)
{
if (result != 0) {
log_error("getsockopt failed with error %d", LAST_SOCKET_ERROR());
break;
}
@@ -728,6 +748,26 @@ bool Network::CheckSRAND(uint32 tick, uint32 srand0)
return true;
}
void Network::KickPlayer(int playerId)
{
NetworkPlayer *player = GetPlayerByID(playerId);
for(auto it = client_connection_list.begin(); it != client_connection_list.end(); it++) {
if ((*it)->player->id == playerId) {
// Disconnect the client gracefully
(*it)->last_disconnect_reason = "Kicked";
Server_Send_SETDISCONNECTMSG(*(*it), "Get out of the server!");
shutdown((*it)->socket, SHUT_RD);
(*it)->SendQueuedPackets();
break;
}
}
}
void Network::SetPassword(const char* password)
{
safe_strncpy(Network::password, password, sizeof(Network::password));
}
void Network::Client_Send_AUTH(const char* gameversion, const char* name, const char* password)
{
std::unique_ptr<NetworkPacket> packet = std::move(NetworkPacket::Allocate());
@@ -846,7 +886,6 @@ void Network::Server_Send_SETDISCONNECTMSG(NetworkConnection& connection, const
bool Network::ProcessConnection(NetworkConnection& connection)
{
connection.SendQueuedPackets();
int packetStatus;
do {
packetStatus = connection.ReadPacket();
@@ -871,12 +910,11 @@ bool Network::ProcessConnection(NetworkConnection& connection)
break;
}
} while (packetStatus == NETWORK_READPACKET_MORE_DATA || packetStatus == NETWORK_READPACKET_SUCCESS);
#if !DEBUG
connection.SendQueuedPackets();
if (!connection.ReceivedPacketRecently()) {
connection.last_disconnect_reason = "No Data";
return false;
}
#endif
return true;
}
@@ -991,6 +1029,20 @@ void Network::PrintError()
int Network::Client_Handle_AUTH(NetworkConnection& connection, NetworkPacket& packet)
{
packet >> (uint32&)connection.authstatus >> (uint8&)player_id;
switch(connection.authstatus) {
case NETWORK_AUTH_BADNAME:
connection.last_disconnect_reason = "Bad Player Name";
shutdown(connection.socket, SHUT_RDWR);
break;
case NETWORK_AUTH_BADVERSION:
connection.last_disconnect_reason = "Incorrect Software Version";
shutdown(connection.socket, SHUT_RDWR);
break;
case NETWORK_AUTH_BADPASSWORD:
connection.last_disconnect_reason = "Bad Password";
shutdown(connection.socket, SHUT_RDWR);
break;
}
return 1;
}
@@ -1028,6 +1080,10 @@ int Network::Server_Handle_AUTH(NetworkConnection& connection, NetworkPacket& pa
std::unique_ptr<NetworkPacket> responsepacket = std::move(NetworkPacket::Allocate());
*responsepacket << (uint32)NETWORK_COMMAND_AUTH << (uint32)connection.authstatus << (uint8)playerid;
connection.QueuePacket(std::move(responsepacket));
if (connection.authstatus != NETWORK_AUTH_OK) {
shutdown(connection.socket, SHUT_RD);
connection.SendQueuedPackets();
}
}
return 1;
}
@@ -1300,25 +1356,16 @@ void network_send_gamecmd(uint32 eax, uint32 ebx, uint32 ecx, uint32 edx, uint32
}
}
void Network::KickPlayer(int playerId)
{
NetworkPlayer *player = GetPlayerByID(playerId);
for(auto it = client_connection_list.begin(); it != client_connection_list.end(); it++) {
if ((*it)->player->id == playerId) {
// Disconnect the client gracefully
(*it)->last_disconnect_reason = "Kicked";
Server_Send_SETDISCONNECTMSG(*(*it), "Get out of the server!");
shutdown((*it)->socket, SHUT_RD);
break;
}
}
}
void network_kick_player(int playerId)
{
gNetwork.KickPlayer(playerId);
}
void network_set_password(const char* password)
{
gNetwork.SetPassword(password);
}
#else
int network_get_mode() { return NETWORK_MODE_NONE; }
int network_get_status() { return NETWORK_STATUS_NONE; }
@@ -1335,6 +1382,7 @@ int network_get_player_ping(unsigned int index) { return 0; }
int network_get_player_id(unsigned int index) { return 0; }
void network_send_chat(const char* text) {}
void network_close() {}
void network_kick_player(int playerId) { }
void network_kick_player(int playerId) {}
void network_set_password(const char* password) {}
uint8 network_get_current_player_id() { return 0; }
#endif /* DISABLE_NETWORK */

View File

@@ -69,6 +69,9 @@ extern "C" {
#ifndef SHUT_RD
#define SHUT_RD SD_RECEIVE
#endif
#ifndef SHUT_RDWR
#define SHUT_RDWR SD_BOTH
#endif
#else
#include <arpa/inet.h>
#include <netdb.h>
@@ -109,6 +112,7 @@ public:
static std::unique_ptr<NetworkPacket> Allocate();
static std::unique_ptr<NetworkPacket> Duplicate(NetworkPacket& packet);
uint8* GetData();
uint32 GetCommand();
template <typename T>
NetworkPacket& operator<<(T value) { T swapped = ByteSwapBE(value); uint8* bytes = (uint8*)&swapped; data->insert(data->end(), bytes, bytes + sizeof(value)); return *this; }
void Write(uint8* bytes, unsigned int size);
@@ -118,6 +122,7 @@ public:
const uint8* Read(unsigned int size);
const char* ReadString();
void Clear();
bool CommandRequiresAuth();
uint16 size;
std::shared_ptr<std::vector<uint8>> data;
@@ -209,6 +214,7 @@ public:
void SendPacketToClients(NetworkPacket& packet);
bool CheckSRAND(uint32 tick, uint32 srand0);
void KickPlayer(int playerId);
void SetPassword(const char* password);
void Client_Send_AUTH(const char* gameversion, const char* name, const char* password);
void Server_Send_MAP(NetworkConnection* connection = nullptr);
@@ -314,6 +320,7 @@ void network_send_chat(const char* text);
void network_send_gamecmd(uint32 eax, uint32 ebx, uint32 ecx, uint32 edx, uint32 esi, uint32 edi, uint32 ebp, uint8 callback);
void network_kick_player(int playerId);
void network_set_password(const char* password);
void network_print_error();

View File

@@ -185,7 +185,7 @@ static void window_server_list_mouseup(rct_window *w, int widgetIndex)
break;
case WIDX_START_SERVER:
server_list_update_player_name();
window_loadsave_open(LOADSAVETYPE_LOAD | LOADSAVETYPE_GAME | LOADSAVETYPE_NETWORK, NULL);
window_server_start_open();
break;
}
}

190
src/windows/server_start.c Normal file
View File

@@ -0,0 +1,190 @@
/*****************************************************************************
* Copyright (c) 2014 Ted John
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* This file is part of OpenRCT2.
*
* OpenRCT2 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.
* This program 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/>.
*****************************************************************************/
#include "../config.h"
#include "../interface/themes.h"
#include "../interface/widget.h"
#include "../interface/window.h"
#include "../localisation/localisation.h"
#include "../network/network.h"
#include "../sprites.h"
#include "../util/util.h"
#include "error.h"
char _password[33];
enum {
WIDX_BACKGROUND,
WIDX_TITLE,
WIDX_CLOSE,
WIDX_PASSWORD_INPUT,
WIDX_ADVERTISE_CHECKBOX,
WIDX_START_SERVER
};
#define WW 300
#define WH 100
static rct_widget window_server_start_widgets[] = {
{ WWT_FRAME, 0, 0, WW-1, 0, WH-1, 0xFFFFFFFF, STR_NONE }, // panel / background
{ WWT_CAPTION, 0, 1, WW-2, 1, 14, STR_START_SERVER, STR_WINDOW_TITLE_TIP }, // title bar
{ WWT_CLOSEBOX, 0, WW-13, WW-3, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, // close x button
{ WWT_TEXT_BOX, 1, 150, WW-8, 20, 32, (uint32)_password, STR_NONE }, // password text box
{ WWT_CHECKBOX, 1, 6, WW-8, 36, 45, STR_ADVERTISE, STR_NONE }, // advertise checkbox
{ WWT_DROPDOWN_BUTTON, 1, 6, 106, WH-6-11, WH-6, STR_START_SERVER, STR_NONE }, // start server button
{ WIDGETS_END },
};
static void window_server_start_close(rct_window *w);
static void window_server_start_mouseup(rct_window *w, int widgetIndex);
static void window_server_start_update(rct_window *w);
static void window_server_start_textinput(rct_window *w, int widgetIndex, char *text);
static void window_server_start_invalidate(rct_window *w);
static void window_server_start_paint(rct_window *w, rct_drawpixelinfo *dpi);
static rct_window_event_list window_server_start_events = {
window_server_start_close,
window_server_start_mouseup,
NULL,
NULL,
NULL,
NULL,
window_server_start_update,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
window_server_start_textinput,
NULL,
NULL,
NULL,
NULL,
NULL,
window_server_start_invalidate,
window_server_start_paint,
NULL
};
void window_server_start_open()
{
rct_window* window;
// Check if window is already open
window = window_bring_to_front_by_class(WC_SERVER_START);
if (window != NULL)
return;
window = window_create_centred(WW, WH, &window_server_start_events, WC_SERVER_START, WF_10);
window->widgets = window_server_start_widgets;
window->enabled_widgets = (
(1 << WIDX_CLOSE) |
(1 << WIDX_PASSWORD_INPUT) |
(1 << WIDX_ADVERTISE_CHECKBOX) |
(1 << WIDX_START_SERVER)
);
window_init_scroll_widgets(window);
window->no_list_items = 0;
window->selected_list_item = -1;
window->frame_no = 0;
window->min_width = window->width;
window->min_height = window->height;
window->max_width = window->min_width;
window->max_height = window->min_height;
window->page = 0;
window->list_information_type = 0;
window->colours[0] = 1;
window->colours[1] = 26;
window->colours[2] = 26;
}
static void window_server_start_close(rct_window *w)
{
}
static void window_server_start_mouseup(rct_window *w, int widgetIndex)
{
switch (widgetIndex) {
case WIDX_CLOSE:
window_close(w);
break;
case WIDX_PASSWORD_INPUT:
window_start_textbox(w, widgetIndex, 1170, (uint32)_password, 32);
break;
case WIDX_ADVERTISE_CHECKBOX:
gConfigNetwork.advertise = !gConfigNetwork.advertise;
config_save_default();
window_invalidate(w);
break;
case WIDX_START_SERVER:
network_set_password(_password);
window_loadsave_open(LOADSAVETYPE_LOAD | LOADSAVETYPE_GAME | LOADSAVETYPE_NETWORK, NULL);
break;
}
}
static void window_server_start_update(rct_window *w)
{
if (gCurrentTextBox.window.classification == w->classification && gCurrentTextBox.window.number == w->number) {
window_update_textbox_caret();
widget_invalidate(w, WIDX_PASSWORD_INPUT);
}
}
static void window_server_start_textinput(rct_window *w, int widgetIndex, char *text)
{
if (text == NULL) return;
switch (widgetIndex) {
case WIDX_PASSWORD_INPUT:
if (strcmp(_password, text) == 0)
return;
memset(_password, 0, sizeof(_password));
if (strlen(text) > 0) {
safe_strncpy(_password, text, sizeof(_password));
}
widget_invalidate(w, WIDX_PASSWORD_INPUT);
break;
}
}
static void window_server_start_invalidate(rct_window *w)
{
widget_set_checkbox_value(w, WIDX_ADVERTISE_CHECKBOX, gConfigNetwork.advertise);
}
static void window_server_start_paint(rct_window *w, rct_drawpixelinfo *dpi)
{
window_draw_widgets(w, dpi);
gfx_draw_string_left(dpi, STR_PASSWORD, NULL, w->colours[1], w->x + 6, w->y + w->widgets[WIDX_PASSWORD_INPUT].top);
}