complete password protected servers

closes #2290
This commit is contained in:
Matthias Mailänder
2013-10-05 13:02:47 +02:00
parent a6cdcea414
commit b618fc7cc2
17 changed files with 229 additions and 81 deletions

View File

@@ -49,9 +49,9 @@ namespace OpenRA
public static Renderer Renderer;
public static bool HasInputFocus = false;
public static void JoinServer(string host, int port)
public static void JoinServer(string host, int port, string password)
{
JoinInner(new OrderManager(host, port,
JoinInner(new OrderManager(host, port, password,
new ReplayRecorderConnection(new NetworkConnection(host, port), ChooseReplayFilename)));
}
@@ -70,12 +70,12 @@ namespace OpenRA
public static void JoinReplay(string replayFile)
{
JoinInner(new OrderManager("<no server>", -1, new ReplayConnection(replayFile)));
JoinInner(new OrderManager("<no server>", -1, "", new ReplayConnection(replayFile)));
}
static void JoinLocal()
{
JoinInner(new OrderManager("<no server>", -1, new EchoConnection()));
JoinInner(new OrderManager("<no server>", -1, "", new EchoConnection()));
}
public static int RenderFrame = 0;

View File

@@ -28,6 +28,7 @@ namespace OpenRA.GameRules
public int ListenPort = 1234;
public int ExternalPort = 1234;
public bool AdvertiseOnline = true;
public string Password = "";
public string MasterServer = "http://master.open-ra.org/";
public bool DiscoverNatDevices = false; // Allow users to disable NAT discovery if problems occur
public bool AllowPortForward = true; // let the user disable it even if compatible devices are found
@@ -51,6 +52,7 @@ namespace OpenRA.GameRules
ListenPort = other.ListenPort;
ExternalPort = other.ExternalPort;
AdvertiseOnline = other.AdvertiseOnline;
Password = other.Password;
MasterServer = other.MasterServer;
DiscoverNatDevices = other.DiscoverNatDevices;
AllowPortForward = other.AllowPortForward;

View File

@@ -135,7 +135,7 @@ namespace OpenRA.Network
{
var len = reader.ReadInt32();
var client = reader.ReadInt32();
var buf = reader.ReadBytes( len );
var buf = reader.ReadBytes(len);
if (len == 0)
throw new NotImplementedException();
lock (this)

View File

@@ -27,8 +27,10 @@ namespace OpenRA.Network
public readonly string Host;
public readonly int Port;
public readonly string Password = "";
public string ServerError = "Server is not responding.";
public string ServerError = "Server is not responding";
public bool AuthenticationFailed = false;
public int NetFrameNumber { get; private set; }
public int LocalFrameNumber;
@@ -52,10 +54,11 @@ namespace OpenRA.Network
Connection.Send(i, new List<byte[]>());
}
public OrderManager(string host, int port, IConnection conn)
public OrderManager(string host, int port, string password, IConnection conn)
{
this.Host = host;
this.Port = port;
Host = host;
Port = port;
Password = password;
Connection = conn;
syncReport = new SyncReport(this);
}

14
OpenRA.Game/Network/UnitOrders.cs Executable file → Normal file
View File

@@ -51,9 +51,11 @@ namespace OpenRA.Network
Game.AddChatLine(Color.White, "(player {0})".F(clientId), order.TargetString);
break;
}
case "Message": // Server message
Game.AddChatLine(Color.White, "Server", order.TargetString);
break;
case "Disconnected": /* reports that the target player disconnected */
{
var client = orderManager.LobbyInfo.ClientWithIndex(clientId);
@@ -146,7 +148,7 @@ namespace OpenRA.Network
{
Client = info,
Mods = localMods,
Password = "Foo"
Password = orderManager.Password
};
orderManager.IssueOrder(Order.HandshakeResponse(response.Serialize()));
@@ -156,6 +158,14 @@ namespace OpenRA.Network
case "ServerError":
{
orderManager.ServerError = order.TargetString;
orderManager.AuthenticationFailed = false;
break;
}
case "AuthenticationError":
{
orderManager.ServerError = order.TargetString;
orderManager.AuthenticationFailed = true;
break;
}
@@ -195,11 +205,13 @@ namespace OpenRA.Network
break;
}
case "Ping":
{
orderManager.IssueOrder(Order.Pong(order.TargetString));
break;
}
default:
{
if (!order.IsImmediate)

View File

@@ -239,6 +239,14 @@ namespace OpenRA.Server
var handshake = HandshakeResponse.Deserialize(data);
if (!string.IsNullOrEmpty(Settings.Password) && handshake.Password != Settings.Password)
{
var message = string.IsNullOrEmpty(handshake.Password) ? "Server requires a password" : "Incorrect password";
SendOrderTo(newConn, "AuthenticationError", message);
DropClient(newConn);
return;
}
var client = new Session.Client()
{
Name = handshake.Client.Name,
@@ -270,7 +278,7 @@ namespace OpenRA.Server
Log.Write("server", "Rejected connection from {0}; mods do not match.",
newConn.socket.RemoteEndPoint);
SendOrderTo(newConn, "ServerError", "Your mods don't match the server");
SendOrderTo(newConn, "ServerError", "Server is running an incompatible mod");
DropClient(newConn);
return;
}
@@ -283,7 +291,7 @@ namespace OpenRA.Server
Log.Write("server", "Rejected connection from {0}; Not running the same version.",
newConn.socket.RemoteEndPoint);
SendOrderTo(newConn, "ServerError", "Not running the same version.");
SendOrderTo(newConn, "ServerError", "Server is running an incompatible version");
DropClient(newConn);
return;
}
@@ -293,7 +301,7 @@ namespace OpenRA.Server
if (bans.Contains(client.IpAddress))
{
Log.Write("server", "Rejected connection from {0}; Banned.", newConn.socket.RemoteEndPoint);
SendOrderTo(newConn, "ServerError", "You are {0} from the server.".F(Settings.Ban.Contains(client.IpAddress) ? "banned" : "temporarily banned"));
SendOrderTo(newConn, "ServerError", "You have been {0} from the server".F(Settings.Ban.Contains(client.IpAddress) ? "banned" : "temporarily banned"));
DropClient(newConn);
return;
}

View File

@@ -137,6 +137,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
ConnectionLogic.Connect(IPAddress.Loopback.ToString(),
Game.CreateLocalServer(map),
"",
() => OpenLobbyPanel(MenuType.Main, true),
() => { Game.CloseServer(); menuType = MenuType.Main; });
}

View File

@@ -90,6 +90,7 @@ namespace OpenRA.Mods.RA
case "StartGame":
case "Disconnected":
case "ServerError":
case "AuthenticationError":
case "SyncInfo":
return;
}

View File

@@ -16,7 +16,8 @@ namespace OpenRA.Mods.RA.Widgets.Logic
{
public class ConnectionLogic
{
Action onConnect, onRetry, onAbort;
Action onConnect, onAbort;
Action<string> onRetry;
void ConnectionStateChanged(OrderManager om)
{
@@ -44,11 +45,11 @@ namespace OpenRA.Mods.RA.Widgets.Logic
}
[ObjectCreator.UseCtor]
public ConnectionLogic(Widget widget, string host, int port, Action onConnect, Action onRetry, Action onAbort)
public ConnectionLogic(Widget widget, string host, int port, Action onConnect, Action onAbort, Action<string> onRetry)
{
this.onConnect = onConnect;
this.onRetry = onRetry;
this.onAbort = onAbort;
this.onRetry = onRetry;
Game.ConnectionStateChanged += ConnectionStateChanged;
@@ -59,31 +60,81 @@ namespace OpenRA.Mods.RA.Widgets.Logic
"Connecting to {0}:{1}...".F(host, port);
}
public static void Connect(string host, int port, Action onConnect, Action onAbort)
public static void Connect(string host, int port, string password, Action onConnect, Action onAbort)
{
Game.JoinServer(host, port);
Game.JoinServer(host, port, password);
Action<string> onRetry = newPassword => Connect(host, port, newPassword, onConnect, onAbort);
Ui.OpenWindow("CONNECTING_PANEL", new WidgetArgs()
{
{ "host", host },
{ "port", port },
{ "onConnect", onConnect },
{ "onAbort", onAbort },
{ "onRetry", () => Connect(host, port, onConnect, onAbort) }
{ "onRetry", onRetry }
});
}
}
public class ConnectionFailedLogic
{
PasswordFieldWidget passwordField;
bool passwordOffsetAdjusted;
[ObjectCreator.UseCtor]
public ConnectionFailedLogic(Widget widget, OrderManager orderManager, Action onRetry, Action onAbort)
public ConnectionFailedLogic(Widget widget, OrderManager orderManager, Action onAbort, Action<string> onRetry)
{
var panel = widget;
panel.Get<ButtonWidget>("ABORT_BUTTON").OnClick = () => { Ui.CloseWindow(); onAbort(); };
panel.Get<ButtonWidget>("RETRY_BUTTON").OnClick = () => { Ui.CloseWindow(); onRetry(); };
var abortButton = panel.Get<ButtonWidget>("ABORT_BUTTON");
var retryButton = panel.Get<ButtonWidget>("RETRY_BUTTON");
abortButton.OnClick = () => { Ui.CloseWindow(); onAbort(); };
retryButton.OnClick = () =>
{
var password = passwordField != null && passwordField.IsVisible() ? passwordField.Text : orderManager.Password;
Ui.CloseWindow();
onRetry(password);
};
widget.Get<LabelWidget>("CONNECTING_DESC").GetText = () =>
"Could not connect to {0}:{1}\n{2}".F(orderManager.Host, orderManager.Port, orderManager.ServerError);
"Could not connect to {0}:{1}".F(orderManager.Host, orderManager.Port);
var connectionError = widget.Get<LabelWidget>("CONNECTION_ERROR");
connectionError.GetText = () => orderManager.ServerError;
passwordField = panel.GetOrNull<PasswordFieldWidget>("PASSWORD");
if (passwordField != null)
{
passwordField.Text = orderManager.Password;
passwordField.IsVisible = () => orderManager.AuthenticationFailed;
var passwordLabel = widget.Get<LabelWidget>("PASSWORD_LABEL");
passwordLabel.IsVisible = passwordField.IsVisible;
}
passwordOffsetAdjusted = false;
var connectionFailedTicker = panel.GetOrNull<LogicTickerWidget>("CONNECTION_FAILED_TICKER");
if (connectionFailedTicker != null)
{
connectionFailedTicker.OnTick = () =>
{
// Adjust the dialog once the AuthenticationError is parsed.
if (passwordField.IsVisible() && !passwordOffsetAdjusted)
{
var offset = passwordField.Bounds.Y - connectionError.Bounds.Y;
abortButton.Bounds.Y += offset;
retryButton.Bounds.Y += offset;
panel.Bounds.Height += offset;
panel.Bounds.Y -= offset / 2;
var background = panel.GetOrNull("CONNECTION_BACKGROUND");
if (background != null)
background.Bounds.Height += offset;
passwordOffsetAdjusted = true;
}
};
}
}
}
}

View File

@@ -34,7 +34,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
Game.Settings.Save();
Ui.CloseWindow();
ConnectionLogic.Connect(ipField.Text, port, openLobby, onExit);
ConnectionLogic.Connect(ipField.Text, port, "", openLobby, onExit);
};
panel.Get<ButtonWidget>("BACK_BUTTON").OnClick = () => { Ui.CloseWindow(); onExit(); };

View File

@@ -58,9 +58,9 @@ namespace OpenRA.Mods.RA.Widgets.Logic
});
};
Action onRetry = () =>
Action<string> onRetry = password =>
{
ConnectionLogic.Connect(om.Host, om.Port, onConnect, onExit);
ConnectionLogic.Connect(om.Host, om.Port, password, onConnect, onExit);
};
Ui.OpenWindow("CONNECTIONFAILED_PANEL", new WidgetArgs()

View File

@@ -109,13 +109,13 @@ namespace OpenRA.Mods.RA.Widgets.Logic
void Join(GameServer server)
{
if (server == null || !server.CanJoin())
return;
return;
var host = server.Address.Split(':')[0];
var port = int.Parse(server.Address.Split(':')[1]);
Ui.CloseWindow();
ConnectionLogic.Connect(host, port, OpenLobby, OnExit);
ConnectionLogic.Connect(host, port, "", OpenLobby, OnExit);
}
string GetPlayersLabel(GameServer game)

View File

@@ -32,6 +32,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
this.onExit = onExit;
var settings = Game.Settings;
panel.Get<ButtonWidget>("BACK_BUTTON").OnClick = () => { Ui.CloseWindow(); onExit(); };
panel.Get<ButtonWidget>("CREATE_BUTTON").OnClick = CreateAndJoin;
@@ -71,6 +72,10 @@ namespace OpenRA.Mods.RA.Widgets.Logic
UPnPCheckbox.IsChecked = () => allowPortForward;
UPnPCheckbox.OnClick = () => allowPortForward ^= true;
UPnPCheckbox.IsDisabled = () => !Game.Settings.Server.NatDeviceAvailable;
var passwordField = panel.GetOrNull<PasswordFieldWidget>("PASSWORD");
if (passwordField != null)
passwordField.Text = Game.Settings.Server.Password;
}
void CreateAndJoin()
@@ -83,6 +88,9 @@ namespace OpenRA.Mods.RA.Widgets.Logic
if (!int.TryParse(panel.Get<TextFieldWidget>("EXTERNAL_PORT").Text, out externalPort))
externalPort = 1234;
var passwordField = panel.GetOrNull<PasswordFieldWidget>("PASSWORD");
var password = passwordField != null ? passwordField.Text : "";
// Save new settings
Game.Settings.Server.Name = name;
Game.Settings.Server.ListenPort = listenPort;
@@ -90,6 +98,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
Game.Settings.Server.AdvertiseOnline = advertiseOnline;
Game.Settings.Server.AllowPortForward = allowPortForward;
Game.Settings.Server.Map = map.Uid;
Game.Settings.Server.Password = password;
Game.Settings.Save();
// Take a copy so that subsequent changes don't affect the server
@@ -98,7 +107,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
// Create and join the server
Game.CreateServer(settings);
Ui.CloseWindow();
ConnectionLogic.Connect(IPAddress.Loopback.ToString(), Game.Settings.Server.ListenPort, onCreate, onExit);
ConnectionLogic.Connect(IPAddress.Loopback.ToString(), Game.Settings.Server.ListenPort, password, onCreate, onExit);
}
}
}

View File

@@ -37,8 +37,9 @@ Container@CONNECTIONFAILED_PANEL:
X:(WINDOW_RIGHT - WIDTH)/2
Y:(WINDOW_BOTTOM - 90)/2
Width:370
Height:125
Height:129
Children:
LogicTicker@CONNECTION_FAILED_TICKER:
Label@TITLE:
Width:PARENT_RIGHT
Y:0-25
@@ -46,28 +47,48 @@ Container@CONNECTIONFAILED_PANEL:
Contrast:true
Align:Center
Text:Connection Failed
Background@bg:
Background@CONNECTION_BACKGROUND:
Width:370
Height:90
Height:85
Background:panel-black
Children:
Label@CONNECTING_DESC:
Y:(PARENT_BOTTOM-HEIGHT)/2
Y:15
Width:PARENT_RIGHT
Height:25
Text:Failed to connect
Font:Bold
Align:Center
Label@CONNECTION_ERROR:
Y:40
Width:PARENT_RIGHT
Height:25
Align:Center
Font:Bold
Label@PASSWORD_LABEL:
X:40
Y:79
Width:95
Height:25
Align:Right
Text:Password:
Font:Bold
PasswordField@PASSWORD:
X:140
Y:80
Width:155
MaxLength:20
Height:25
Button@RETRY_BUTTON:
Key:return
Y:89
Y:84
Width:140
Height:35
Text:Retry
Button@ABORT_BUTTON:
Key:escape
X:230
Y:89
Y:84
Width:140
Height:35
Text:Abort

View File

@@ -2,37 +2,37 @@ Container@CREATESERVER_PANEL:
Logic:ServerCreationLogic
X:(WINDOW_RIGHT - WIDTH)/2
Y:(WINDOW_BOTTOM - 260)/2
Width:604
Height:295
Width:521
Height:250
Children:
Label@TITLE:
Text:Create Server
Width:604
Width:PARENT_RIGHT
Y:0-25
Font:BigBold
Contrast:true
Align:Center
Background@bg:
Width:604
Height:260
Width:PARENT_RIGHT
Height:215
Background:panel-black
Children:
Background@MAP_BG:
X:PARENT_RIGHT-WIDTH-15
Y:15
Width:194
Height:194
Width:162
Height:162
Background:panel-gray
Children:
MapPreview@MAP_PREVIEW:
X:1
Y:1
Width:192
Height:192
Width:160
Height:160
Label@MAP_NAME:
X:PARENT_RIGHT-WIDTH-15
Y:220
Width:194
Y:PARENT_BOTTOM - 33
Width:162
Height:25
Align:Center
Font:Bold
@@ -46,67 +46,87 @@ Container@CREATESERVER_PANEL:
TextField@SERVER_NAME:
X:110
Y:15
Width:275
Width:215
MaxLength:50
Height:25
Text:My OpenRA Server
Label@PASSWORD_LABEL:
X:10
Y:49
Width:95
Height:25
Align:Right
Text:Password:
PasswordField@PASSWORD:
X:110
Y:50
Width:145
MaxLength:20
Height:25
Label@AFTER_PASSWORD_LABEL:
X:265
Y:49
Width:95
Height:25
Align:Left
Text:(optional)
Label@LISTEN_PORT_LABEL:
X:15
Y:119
Y:84
Width:90
Height:25
Align: Right
Text:Port:
TextField@LISTEN_PORT:
X:110
Y:120
Y:85
Width:50
MaxLength:5
Height:25
Text:1234
Label@EXTERNAL_PORT_LABEL:
X:180
Y:84
Width:90
Height:25
Align:Right
Text:External Port:
TextField@EXTERNAL_PORT:
X:275
Y:85
Width:50
MaxLength:5
Height:25
Text:1234
Checkbox@ADVERTISE_CHECKBOX:
X:110
Y:155
Y:135
Width:150
Height:20
Text:Advertise Online
Checkbox@UPNP_CHECKBOX:
X:110
Y:180
Y:165
Width:300
Height:20
Text:Automatic port forwarding
Label@EXTERNAL_PORT_LABEL:
X:15
Y:219
Width:90
Height:25
Align:Right
Text:External Port:
TextField@EXTERNAL_PORT:
X:110
Y:220
Width:50
MaxLength:5
Height:25
Text:1234
Button@BACK_BUTTON:
Key:escape
X:0
Y:259
Y:214
Width:140
Height:35
Text:Back
Button@MAP_BUTTON:
X:314
Y:259
X:231
Y:214
Width:140
Height:35
Text:Choose Map
Button@CREATE_BUTTON:
Key:return
X:464
Y:259
X:381
Y:214
Width:140
Height:35
Text:Create

View File

@@ -3,7 +3,7 @@ Container@DIRECTCONNECT_PANEL:
X:(WINDOW_RIGHT - WIDTH)/2
Y:(WINDOW_BOTTOM - 90)/2
Width:370
Height:125
Height:130
Children:
Label@TITLE:
Width:PARENT_RIGHT
@@ -14,7 +14,7 @@ Container@DIRECTCONNECT_PANEL:
Text:Connect to Server
Background@bg:
Width:370
Height:90
Height:95
Background:panel-black
Children:
Label@ADDRESS_LABEL:
@@ -44,14 +44,14 @@ Container@DIRECTCONNECT_PANEL:
Button@BACK_BUTTON:
Key:escape
X:0
Y:89
Y:94
Width:140
Height:35
Text:Back
Button@JOIN_BUTTON:
Key:return
X:230
Y:89
Y:94
Width:140
Height:35
Text:Join

View File

@@ -3,7 +3,7 @@ Background@CREATESERVER_BG:
X:(WINDOW_RIGHT - WIDTH)/2
Y:(WINDOW_BOTTOM - HEIGHT)/2
Width:400
Height:240
Height:300
Children:
Label@LABEL_TITLE:
X:0
@@ -27,42 +27,62 @@ Background@CREATESERVER_BG:
MaxLength:50
Height:25
Text:OpenRA Game
Label@EXTERNAL_PORT_LABEL:
Label@PASSWORD_LABEL:
X:50
Y:94
Width:95
Height:25
Align:Right
Text:Password:
PasswordField@PASSWORD:
X:150
Y:95
Width:145
MaxLength:20
Height:25
Label@AFTER_PASSWORD_LABEL:
X:300
Y:94
Width:95
Height:25
Align:Left
Text:(optional)
Label@EXTERNAL_PORT_LABEL:
X:50
Y:129
Width:95
Height:25
Align: Right
Text:External Port:
TextField@EXTERNAL_PORT:
X:150
Y:95
Y:130
Width:50
MaxLength:5
Height:25
Text:OpenRA Game
Label@LISTEN_PORT_LABEL:
X:210
Y:94
Y:129
Width:95
Height:25
Align: Right
Text:Listen Port:
TextField@LISTEN_PORT:
X:310
Y:95
Y:130
Width:50
MaxLength:5
Height:25
Checkbox@UPNP_CHECKBOX:
X:150
Y:130
Y:165
Width:300
Height:20
Text:Automatic port forwarding
Checkbox@ADVERTISE_CHECKBOX:
X:150
Y:165
Y:200
Width:300
Height:20
Text:Advertise game Online