c2e8263927
commit ccacceb16a184f00ecd384eede64ca9c4fab08a0 Author: Joonas Rikkonen <poe.regalis@gmail.com> Date: Mon Mar 25 14:05:59 2019 +0200 NetEntityEventManager checks the length of the event data (and logs an error if it's too long) before checking if there's still room to keep writing events in the packet. Checking the available room first could lead to situations where an excessively large event can't fit to any packet, "soft-locking" the EventManager without any error messages. commit 5ac8259372aa900adc724aa4da1fd81af41ca195 Author: Joonas Rikkonen <poe.regalis@gmail.com> Date: Mon Mar 25 13:41:52 2019 +0200 Don't display disabled limbs on sonar (i.e. severed limbs that have "faded out") commit 5f84df73ad86be96f3678c450351b3905e7317a4 Merge: b981f1635 dc429d6c4 Author: Joonas Rikkonen <poe.regalis@gmail.com> Date: Mon Mar 25 13:41:16 2019 +0200 Merge branch 'dev' of https://github.com/Regalis11/Barotrauma-development into dev commit b981f163575b2bfc9a83b9925c94eca19b9d4554 Author: Joonas Rikkonen <poe.regalis@gmail.com> Date: Mon Mar 25 13:36:19 2019 +0200 Multiplayer campaign fixes: - Server uses a different temp folder to decompress save/sub files into than the clients. Should fix files occasionally getting corrupted and exceptions when trying to read the files when hosting a server from the main executable. - Some additional debug logging. - Use the base names of the adjacent locations as level seeds (i.e. "Vorta" instead of "Vorta Outpost"). The levels should not change when the type (and full name) of the location changes. commit 42c5d18df77fc7acd5873d8e25f20bdd31b1ed76 Author: Joonas Rikkonen <poe.regalis@gmail.com> Date: Mon Mar 25 13:31:06 2019 +0200 Don't transfer files through the network when sending them to the owner of the server (i.e. a client hosting directly from the main executable), but simply tell the client where the file is located. commit dc429d6c450f4893fe29c51d3c830527e587a871 Author: Daniel Asteljoki <daniel.asteljoki@gmail.com> Date: Mon Mar 25 13:30:26 2019 +0200 Added labels next to periscopes in Humpback and Dugong commit 789f02a87a2917dd2ae378f136cbe8dd3236c60d Author: Joonas Rikkonen <poe.regalis@gmail.com> Date: Mon Mar 25 13:29:29 2019 +0200 If loading a submarine fails, wait a bit and retry up to 4 times. Fixes loading occasionally failing when running multiple instances of the game from the same directory. commit be9ea3a58832992b6226917117247e1bf1efeff9 Author: Joonas Rikkonen <poe.regalis@gmail.com> Date: Mon Mar 25 11:03:36 2019 +0200 Fixed a bunch of disconnection messages being in an incorrect format & DisconnectUnauthClient not getting the messages from the xml commit c6f744b4d6b3520720010f5cd4f22a25b42bfc8b Author: Joonas Rikkonen <poe.regalis@gmail.com> Date: Mon Mar 25 10:43:10 2019 +0200 Log entity event errors into server logs when verbose logging is enabled
512 lines
26 KiB
C#
512 lines
26 KiB
C#
using Lidgren.Network;
|
|
using Microsoft.Xna.Framework;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
|
|
namespace Barotrauma.Networking
|
|
{
|
|
class UnauthenticatedClient
|
|
{
|
|
public readonly NetConnection Connection;
|
|
public readonly ulong SteamID;
|
|
public Facepunch.Steamworks.ServerAuth.Status? SteamAuthStatus = null;
|
|
public readonly int Nonce;
|
|
|
|
public int FailedAttempts;
|
|
|
|
public float AuthTimer;
|
|
|
|
public UnauthenticatedClient(NetConnection connection, int nonce, ulong steamID = 0)
|
|
{
|
|
Connection = connection;
|
|
SteamID = steamID;
|
|
Nonce = nonce;
|
|
AuthTimer = 10.0f;
|
|
FailedAttempts = 0;
|
|
}
|
|
}
|
|
|
|
partial class GameServer : NetworkMember
|
|
{
|
|
private Int32 ownerKey = 0;
|
|
|
|
List<UnauthenticatedClient> unauthenticatedClients = new List<UnauthenticatedClient>();
|
|
|
|
private void ReadClientSteamAuthRequest(NetIncomingMessage inc, NetConnection senderConnection, out ulong clientSteamID)
|
|
{
|
|
clientSteamID = 0;
|
|
if (!Steam.SteamManager.USE_STEAM)
|
|
{
|
|
DebugConsole.Log("Received a Steam auth request from " + senderConnection.RemoteEndPoint + ". Steam authentication not required, handling auth normally.");
|
|
//not using steam, handle auth normally
|
|
HandleClientAuthRequest(senderConnection, 0);
|
|
return;
|
|
}
|
|
|
|
if (senderConnection == OwnerConnection)
|
|
{
|
|
//the client is the owner of the server, no need for authentication
|
|
//(it would fail with a "duplicate request" error anyway)
|
|
HandleClientAuthRequest(senderConnection, 0);
|
|
return;
|
|
}
|
|
|
|
clientSteamID = inc.ReadUInt64();
|
|
int authTicketLength = inc.ReadInt32();
|
|
inc.ReadBytes(authTicketLength, out byte[] authTicketData);
|
|
|
|
DebugConsole.Log("Received a Steam auth request");
|
|
DebugConsole.Log(" Steam ID: "+ clientSteamID);
|
|
DebugConsole.Log(" Auth ticket length: " + authTicketLength);
|
|
DebugConsole.Log(" Auth ticket data: " +
|
|
((authTicketData == null) ? "null" : ToolBox.LimitString(string.Concat(authTicketData.Select(b => b.ToString("X2"))), 16)));
|
|
|
|
if (senderConnection != OwnerConnection &&
|
|
serverSettings.BanList.IsBanned(senderConnection.RemoteEndPoint.Address, clientSteamID))
|
|
{
|
|
return;
|
|
}
|
|
ulong steamID = clientSteamID;
|
|
if (unauthenticatedClients.Any(uc => uc.Connection == inc.SenderConnection))
|
|
{
|
|
var steamAuthedClient = unauthenticatedClients.Find(uc =>
|
|
uc.Connection == inc.SenderConnection &&
|
|
uc.SteamID == steamID &&
|
|
uc.SteamAuthStatus == Facepunch.Steamworks.ServerAuth.Status.OK);
|
|
if (steamAuthedClient != null)
|
|
{
|
|
DebugConsole.Log("Client already authenticated, sending AUTH_RESPONSE again...");
|
|
HandleClientAuthRequest(inc.SenderConnection, steamID);
|
|
}
|
|
DebugConsole.Log("Steam authentication already pending...");
|
|
return;
|
|
}
|
|
|
|
if (authTicketData == null)
|
|
{
|
|
DebugConsole.Log("Invalid request");
|
|
return;
|
|
}
|
|
|
|
unauthenticatedClients.RemoveAll(uc => uc.Connection == senderConnection);
|
|
int nonce = CryptoRandom.Instance.Next();
|
|
var unauthClient = new UnauthenticatedClient(senderConnection, nonce, clientSteamID)
|
|
{
|
|
AuthTimer = 20
|
|
};
|
|
unauthenticatedClients.Add(unauthClient);
|
|
|
|
if (!Steam.SteamManager.StartAuthSession(authTicketData, clientSteamID))
|
|
{
|
|
unauthenticatedClients.Remove(unauthClient);
|
|
if (GameMain.Config.RequireSteamAuthentication)
|
|
{
|
|
unauthClient.Connection.Disconnect(DisconnectReason.SteamAuthenticationFailed.ToString());
|
|
Log("Disconnected unauthenticated client (Steam ID: " + steamID + "). Steam authentication failed.", ServerLog.MessageType.ServerMessage);
|
|
}
|
|
else
|
|
{
|
|
DebugConsole.Log("Steam authentication failed, skipping to basic auth...");
|
|
HandleClientAuthRequest(senderConnection);
|
|
return;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
public void OnAuthChange(ulong steamID, ulong ownerID, Facepunch.Steamworks.ServerAuth.Status status)
|
|
{
|
|
DebugConsole.Log("************ OnAuthChange");
|
|
DebugConsole.Log(" Steam ID: " + steamID);
|
|
DebugConsole.Log(" Owner ID: " + ownerID);
|
|
DebugConsole.Log(" Status: " + status);
|
|
|
|
UnauthenticatedClient unauthClient = unauthenticatedClients.Find(uc => uc.SteamID == ownerID);
|
|
if (unauthClient != null)
|
|
{
|
|
unauthClient.SteamAuthStatus = status;
|
|
switch (status)
|
|
{
|
|
case Facepunch.Steamworks.ServerAuth.Status.OK:
|
|
////steam authentication done, check password next
|
|
Log("Successfully authenticated client via Steam (Steam ID: " + steamID + ").", ServerLog.MessageType.ServerMessage);
|
|
HandleClientAuthRequest(unauthClient.Connection, unauthClient.SteamID);
|
|
break;
|
|
default:
|
|
unauthenticatedClients.Remove(unauthClient);
|
|
if (GameMain.Config.RequireSteamAuthentication)
|
|
{
|
|
Log("Disconnected unauthenticated client (Steam ID: " + steamID + "). Steam authentication failed, (" + status + ").", ServerLog.MessageType.ServerMessage);
|
|
unauthClient.Connection.Disconnect(DisconnectReason.SteamAuthenticationFailed.ToString() + "/ (" + status.ToString() + ")");
|
|
}
|
|
else
|
|
{
|
|
DebugConsole.Log("Steam authentication failed (" + status.ToString() + "), skipping to basic auth...");
|
|
HandleClientAuthRequest(unauthClient.Connection);
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
DebugConsole.Log(" No unauthenticated clients found with the Steam ID " + steamID);
|
|
}
|
|
|
|
//kick connected client if status becomes invalid (e.g. VAC banned, not connected to steam)
|
|
/*if (status != Facepunch.Steamworks.ServerAuth.Status.OK && GameMain.Config.RequireSteamAuthentication)
|
|
{
|
|
var connectedClient = connectedClients.Find(c => c.SteamID == ownerID);
|
|
if (connectedClient != null)
|
|
{
|
|
Log("Disconnecting client " + connectedClient.Name + " (Steam ID: " + steamID + "). Steam authentication no longer valid (" + status + ").", ServerLog.MessageType.ServerMessage);
|
|
KickClient(connectedClient, $"DisconnectMessage.SteamAuthNoLongerValid~[status]={status.ToString()}");
|
|
}
|
|
}*/
|
|
}
|
|
|
|
private bool IsServerOwner(NetIncomingMessage inc, NetConnection senderConnection)
|
|
{
|
|
string address = senderConnection.RemoteEndPoint.Address.MapToIPv4().ToString();
|
|
int incKey = inc.ReadInt32();
|
|
|
|
if (ownerKey == 0)
|
|
{
|
|
return false; //ownership key has been destroyed or has never existed
|
|
}
|
|
if (address.ToString() != "127.0.0.1")
|
|
{
|
|
return false; //not localhost
|
|
}
|
|
|
|
if (incKey != ownerKey)
|
|
{
|
|
return false; //incorrect owner key, how did this even happen
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private void HandleOwnership(NetIncomingMessage inc, NetConnection senderConnection)
|
|
{
|
|
DebugConsole.Log("HandleOwnership (" + senderConnection.RemoteEndPoint.Address + ")");
|
|
if (IsServerOwner(inc, senderConnection))
|
|
{
|
|
ownerKey = 0; //destroy owner key so nobody else can take ownership of the server
|
|
OwnerConnection = senderConnection;
|
|
DebugConsole.NewMessage("Successfully set up server owner", Color.Lime);
|
|
}
|
|
}
|
|
|
|
private void HandleClientAuthRequest(NetConnection connection, ulong steamID = 0)
|
|
{
|
|
DebugConsole.Log("HandleClientAuthRequest (steamID " + steamID + ")");
|
|
|
|
if (GameMain.Config.RequireSteamAuthentication && connection != OwnerConnection && steamID == 0)
|
|
{
|
|
DebugConsole.Log("Disconnecting " + connection.RemoteEndPoint + ", Steam authentication required.");
|
|
connection.Disconnect(DisconnectReason.SteamAuthenticationRequired.ToString());
|
|
return;
|
|
}
|
|
|
|
//client wants to know if server requires password
|
|
if (ConnectedClients.Find(c => c.Connection == connection) != null)
|
|
{
|
|
//this client has already been authenticated
|
|
return;
|
|
}
|
|
|
|
UnauthenticatedClient unauthClient = unauthenticatedClients.Find(uc => uc.Connection == connection);
|
|
if (unauthClient == null)
|
|
{
|
|
DebugConsole.Log("Unauthed client, generating a nonce...");
|
|
//new client, generate nonce and add to unauth queue
|
|
if (ConnectedClients.Count >= serverSettings.MaxPlayers)
|
|
{
|
|
//server is full, can't allow new connection
|
|
connection.Disconnect(DisconnectReason.ServerFull.ToString());
|
|
if (steamID > 0) { Steam.SteamManager.StopAuthSession(steamID); }
|
|
return;
|
|
}
|
|
|
|
int nonce = CryptoRandom.Instance.Next();
|
|
unauthClient = new UnauthenticatedClient(connection, nonce, steamID);
|
|
unauthenticatedClients.Add(unauthClient);
|
|
}
|
|
unauthClient.AuthTimer = 10.0f;
|
|
//if the client is already in the queue, getting another unauth request means that our response was lost; resend
|
|
NetOutgoingMessage nonceMsg = server.CreateMessage();
|
|
nonceMsg.Write((byte)ServerPacketHeader.AUTH_RESPONSE);
|
|
if (serverSettings.HasPassword && connection != OwnerConnection)
|
|
{
|
|
nonceMsg.Write(true); //true = password
|
|
nonceMsg.Write((Int32)unauthClient.Nonce); //here's nonce, encrypt with this
|
|
}
|
|
else
|
|
{
|
|
nonceMsg.Write(false); //false = no password
|
|
}
|
|
CompressOutgoingMessage(nonceMsg);
|
|
DebugConsole.Log("Sending auth response...");
|
|
server.SendMessage(nonceMsg, connection, NetDeliveryMethod.Unreliable);
|
|
}
|
|
|
|
private void ClientInitRequest(NetIncomingMessage inc)
|
|
{
|
|
DebugConsole.Log("Received client init request");
|
|
if (ConnectedClients.Find(c => c.Connection == inc.SenderConnection) != null)
|
|
{
|
|
//this client was already authenticated
|
|
//another init request means they didn't get any update packets yet
|
|
DebugConsole.Log("Client already connected, ignoring...");
|
|
return;
|
|
}
|
|
|
|
UnauthenticatedClient unauthClient = unauthenticatedClients.Find(uc => uc.Connection == inc.SenderConnection);
|
|
if (unauthClient == null)
|
|
{
|
|
//client did not ask for nonce first, can't authorize
|
|
inc.SenderConnection.Disconnect(DisconnectReason.AuthenticationRequired.ToString());
|
|
if (unauthClient.SteamID > 0) { Steam.SteamManager.StopAuthSession(unauthClient.SteamID); }
|
|
return;
|
|
}
|
|
|
|
if (serverSettings.HasPassword && inc.SenderConnection != OwnerConnection)
|
|
{
|
|
//decrypt message and compare password
|
|
string clPw = inc.ReadString();
|
|
if (!serverSettings.IsPasswordCorrect(clPw, unauthClient.Nonce))
|
|
{
|
|
unauthClient.FailedAttempts++;
|
|
if (unauthClient.FailedAttempts > 3)
|
|
{
|
|
//disconnect and ban after too many failed attempts
|
|
serverSettings.BanList.BanPlayer("Unnamed", unauthClient.Connection.RemoteEndPoint.Address, "DisconnectMessage.TooManyFailedLogins", duration: null);
|
|
DisconnectUnauthClient(inc, unauthClient, DisconnectReason.TooManyFailedLogins, "");
|
|
|
|
Log(inc.SenderConnection.RemoteEndPoint.Address.ToString() + " has been banned from the server (too many wrong passwords)", ServerLog.MessageType.Error);
|
|
DebugConsole.NewMessage(inc.SenderConnection.RemoteEndPoint.Address.ToString() + " has been banned from the server (too many wrong passwords)", Color.Red);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
//not disconnecting the player here, because they'll still use the same connection and nonce if they try logging in again
|
|
NetOutgoingMessage reject = server.CreateMessage();
|
|
reject.Write((byte)ServerPacketHeader.AUTH_FAILURE);
|
|
reject.Write("Wrong password! You have " + Convert.ToString(4 - unauthClient.FailedAttempts) + " more attempts before you're banned from the server.");
|
|
Log(inc.SenderConnection.RemoteEndPoint.Address.ToString() + " failed to join the server (incorrect password)", ServerLog.MessageType.Error);
|
|
DebugConsole.NewMessage(inc.SenderConnection.RemoteEndPoint.Address.ToString() + " failed to join the server (incorrect password)", Color.Red);
|
|
CompressOutgoingMessage(reject);
|
|
server.SendMessage(reject, unauthClient.Connection, NetDeliveryMethod.Unreliable);
|
|
unauthClient.AuthTimer = 10.0f;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
string clVersion = inc.ReadString();
|
|
|
|
UInt16 contentPackageCount = inc.ReadUInt16();
|
|
List<string> contentPackageNames = new List<string>();
|
|
List<string> contentPackageHashes = new List<string>();
|
|
for (int i = 0; i < contentPackageCount; i++)
|
|
{
|
|
string packageName = inc.ReadString();
|
|
string packageHash = inc.ReadString();
|
|
contentPackageNames.Add(packageName);
|
|
contentPackageHashes.Add(packageHash);
|
|
if (contentPackageCount == 0)
|
|
{
|
|
DebugConsole.Log("Client is using content package " +
|
|
(packageName ?? "null") + " (" + (packageHash ?? "null" + ")"));
|
|
}
|
|
}
|
|
|
|
if (contentPackageCount == 0)
|
|
{
|
|
DebugConsole.Log("Client did not list any content packages.");
|
|
}
|
|
|
|
string clName = Client.SanitizeName(inc.ReadString());
|
|
if (string.IsNullOrWhiteSpace(clName))
|
|
{
|
|
DisconnectUnauthClient(inc, unauthClient, DisconnectReason.NoName, "");
|
|
|
|
Log(inc.SenderConnection.RemoteEndPoint.Address.ToString() + " couldn't join the server (no name given)", ServerLog.MessageType.Error);
|
|
DebugConsole.NewMessage(inc.SenderConnection.RemoteEndPoint.Address.ToString() + " couldn't join the server (no name given)", Color.Red);
|
|
return;
|
|
}
|
|
|
|
if (clVersion != GameMain.Version.ToString())
|
|
{
|
|
DisconnectUnauthClient(inc, unauthClient, DisconnectReason.InvalidVersion,
|
|
$"DisconnectMessage.InvalidVersion~[version]={GameMain.Version.ToString()}~[clientversion]={clVersion}");
|
|
|
|
Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (wrong game version)", ServerLog.MessageType.Error);
|
|
DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (wrong game version)", Color.Red);
|
|
return;
|
|
}
|
|
|
|
//check if the client is missing any of the content packages the server requires
|
|
List<ContentPackage> missingPackages = new List<ContentPackage>();
|
|
foreach (ContentPackage contentPackage in GameMain.SelectedPackages)
|
|
{
|
|
if (!contentPackage.HasMultiplayerIncompatibleContent) continue;
|
|
bool packageFound = false;
|
|
for (int i = 0; i < contentPackageCount; i++)
|
|
{
|
|
if (contentPackageNames[i] == contentPackage.Name && contentPackageHashes[i] == contentPackage.MD5hash.Hash)
|
|
{
|
|
packageFound = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!packageFound) missingPackages.Add(contentPackage);
|
|
}
|
|
|
|
if (missingPackages.Count == 1)
|
|
{
|
|
DisconnectUnauthClient(inc, unauthClient, DisconnectReason.MissingContentPackage, $"DisconnectMessage.MissingContentPackage~[missingcontentpackage]={GetPackageStr(missingPackages[0])}");
|
|
Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (missing content package " + GetPackageStr(missingPackages[0]) + ")", ServerLog.MessageType.Error);
|
|
return;
|
|
}
|
|
else if (missingPackages.Count > 1)
|
|
{
|
|
List<string> packageStrs = new List<string>();
|
|
missingPackages.ForEach(cp => packageStrs.Add(GetPackageStr(cp)));
|
|
DisconnectUnauthClient(inc, unauthClient, DisconnectReason.MissingContentPackage, $"DisconnectMessage.MissingContentPackages~[missingcontentpackages]={string.Join(", ", packageStrs)}");
|
|
Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (missing content packages " + string.Join(", ", packageStrs) + ")", ServerLog.MessageType.Error);
|
|
return;
|
|
}
|
|
|
|
string GetPackageStr(ContentPackage contentPackage)
|
|
{
|
|
return "\"" + contentPackage.Name + "\" (hash " + contentPackage.MD5hash.ShortHash + ")";
|
|
}
|
|
|
|
//check if the client is using any contentpackages that are not compatible with the server
|
|
List<Pair<string, string>> incompatiblePackages = new List<Pair<string, string>>();
|
|
for (int i = 0; i < contentPackageNames.Count; i++)
|
|
{
|
|
if (!GameMain.Config.SelectedContentPackages.Any(cp => cp.Name == contentPackageNames[i] && cp.MD5hash.Hash == contentPackageHashes[i]))
|
|
{
|
|
incompatiblePackages.Add(new Pair<string, string>(contentPackageNames[i], contentPackageHashes[i]));
|
|
}
|
|
}
|
|
|
|
if (incompatiblePackages.Count == 1)
|
|
{
|
|
DisconnectUnauthClient(inc, unauthClient, DisconnectReason.IncompatibleContentPackage,
|
|
$"DisconnectMessage.IncompatibleContentPackage~[incompatiblecontentpackage]={GetPackageStr2(incompatiblePackages[0])}");
|
|
Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (incompatible content package " + GetPackageStr2(incompatiblePackages[0]) + ")", ServerLog.MessageType.Error);
|
|
return;
|
|
}
|
|
else if (incompatiblePackages.Count > 1)
|
|
{
|
|
List<string> packageStrs = new List<string>();
|
|
incompatiblePackages.ForEach(cp => packageStrs.Add(GetPackageStr2(cp)));
|
|
DisconnectUnauthClient(inc, unauthClient, DisconnectReason.IncompatibleContentPackage,
|
|
$"DisconnectMessage.IncompatibleContentPackages~[incompatiblecontentpackages]={string.Join(", ", packageStrs)}");
|
|
Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (incompatible content packages " + string.Join(", ", packageStrs) + ")", ServerLog.MessageType.Error);
|
|
return;
|
|
}
|
|
|
|
string GetPackageStr2(Pair<string, string> nameAndHash)
|
|
{
|
|
return "\"" + nameAndHash.First + "\" (hash " + Md5Hash.GetShortHash(nameAndHash.Second) + ")";
|
|
}
|
|
|
|
if (!serverSettings.Whitelist.IsWhiteListed(clName, inc.SenderConnection.RemoteEndPoint.Address))
|
|
{
|
|
DisconnectUnauthClient(inc, unauthClient, DisconnectReason.NotOnWhitelist, "");
|
|
Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (not in whitelist)", ServerLog.MessageType.Error);
|
|
DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (not in whitelist)", Color.Red);
|
|
return;
|
|
}
|
|
if (!Client.IsValidName(clName, this))
|
|
{
|
|
DisconnectUnauthClient(inc, unauthClient, DisconnectReason.InvalidName, "");
|
|
Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (invalid name)", ServerLog.MessageType.Error);
|
|
DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (invalid name)", Color.Red);
|
|
return;
|
|
}
|
|
if (inc.SenderConnection != OwnerConnection && Homoglyphs.Compare(clName.ToLower(),Name.ToLower()))
|
|
{
|
|
DisconnectUnauthClient(inc, unauthClient, DisconnectReason.NameTaken, "");
|
|
Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (name taken by the server)", ServerLog.MessageType.Error);
|
|
DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (name taken by the server)", Color.Red);
|
|
return;
|
|
}
|
|
Client nameTaken = ConnectedClients.Find(c => Homoglyphs.Compare(c.Name.ToLower(), clName.ToLower()));
|
|
if (nameTaken != null)
|
|
{
|
|
if (nameTaken.Connection.RemoteEndPoint.Address.ToString() == inc.SenderEndPoint.Address.ToString())
|
|
{
|
|
//both name and IP address match, replace this player's connection
|
|
nameTaken.Connection.Disconnect(DisconnectReason.SessionTaken.ToString());
|
|
nameTaken.Connection = unauthClient.Connection;
|
|
nameTaken.InitClientSync(); //reinitialize sync ids because this is a new connection
|
|
unauthenticatedClients.Remove(unauthClient);
|
|
unauthClient = null;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
//can't authorize this client
|
|
DisconnectUnauthClient(inc, unauthClient, DisconnectReason.NameTaken, "");
|
|
Log(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (name already taken)", ServerLog.MessageType.Error);
|
|
DebugConsole.NewMessage(clName + " (" + inc.SenderConnection.RemoteEndPoint.Address.ToString() + ") couldn't join the server (name already taken)", Color.Red);
|
|
return;
|
|
}
|
|
}
|
|
|
|
//new client
|
|
Client newClient = new Client(clName, GetNewClientID());
|
|
newClient.InitClientSync();
|
|
newClient.Connection = unauthClient.Connection;
|
|
newClient.SteamID = unauthClient.SteamID;
|
|
unauthenticatedClients.Remove(unauthClient);
|
|
unauthClient = null;
|
|
ConnectedClients.Add(newClient);
|
|
LastClientListUpdateID++;
|
|
|
|
if (newClient.Connection == OwnerConnection)
|
|
{
|
|
newClient.GivePermission(ClientPermissions.All);
|
|
newClient.PermittedConsoleCommands.AddRange(DebugConsole.Commands);
|
|
|
|
GameMain.Server.UpdateClientPermissions(newClient);
|
|
GameMain.Server.SendConsoleMessage("Granted all permissions to " + newClient.Name + ".", newClient);
|
|
}
|
|
|
|
GameMain.Server.SendChatMessage($"ServerMessage.JoinedServer~[client]={clName}", ChatMessageType.Server, null);
|
|
|
|
var savedPermissions = serverSettings.ClientPermissions.Find(cp =>
|
|
cp.SteamID > 0 ?
|
|
cp.SteamID == newClient.SteamID :
|
|
newClient.IPMatches(cp.IP));
|
|
|
|
if (savedPermissions != null)
|
|
{
|
|
newClient.SetPermissions(savedPermissions.Permissions, savedPermissions.PermittedCommands);
|
|
}
|
|
else
|
|
{
|
|
newClient.SetPermissions(ClientPermissions.None, new List<DebugConsole.Command>());
|
|
}
|
|
}
|
|
|
|
private void DisconnectUnauthClient(NetIncomingMessage inc, UnauthenticatedClient unauthClient, DisconnectReason reason, string message)
|
|
{
|
|
inc.SenderConnection.Disconnect(reason.ToString() + "/ " + TextManager.GetServerMessage(message));
|
|
if (unauthClient.SteamID > 0) { Steam.SteamManager.StopAuthSession(unauthClient.SteamID); }
|
|
if (unauthClient != null)
|
|
{
|
|
unauthenticatedClients.Remove(unauthClient);
|
|
}
|
|
}
|
|
}
|
|
}
|