Merge branch 'master' of https://github.com/Regalis11/Barotrauma into develop
This commit is contained in:
@@ -174,6 +174,22 @@ namespace Barotrauma.Networking
|
||||
return bannedPlayer != null;
|
||||
}
|
||||
|
||||
public bool IsBanned(AccountInfo accountInfo, out string reason)
|
||||
{
|
||||
if (accountInfo.AccountId.TryUnwrap(out var accountId) && IsBanned(accountId, out reason))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach (var otherId in accountInfo.OtherMatchingIds)
|
||||
{
|
||||
if (IsBanned(otherId, out reason)) { return true; }
|
||||
}
|
||||
|
||||
reason = "";
|
||||
return false;
|
||||
}
|
||||
|
||||
public void BanPlayer(string name, Endpoint endpoint, string reason, TimeSpan? duration)
|
||||
=> BanPlayer(name, endpoint.Address, reason, duration);
|
||||
|
||||
@@ -305,7 +321,7 @@ namespace Barotrauma.Networking
|
||||
else
|
||||
{
|
||||
outMsg.WriteBoolean(false); outMsg.WritePadBits();
|
||||
outMsg.WriteString(((SteamId)bannedPlayer.AddressOrAccountId).StringRepresentation);
|
||||
outMsg.WriteString(((AccountId)bannedPlayer.AddressOrAccountId).StringRepresentation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
private DateTime refreshMasterTimer;
|
||||
private readonly TimeSpan refreshMasterInterval = new TimeSpan(0, 0, 60);
|
||||
private bool registeredToMaster;
|
||||
private bool registeredToSteamMaster;
|
||||
|
||||
private DateTime roundStartTime;
|
||||
|
||||
@@ -123,7 +123,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
public NetworkConnection OwnerConnection { get; private set; }
|
||||
private readonly Option<int> ownerKey;
|
||||
private readonly Option<SteamId> ownerSteamId;
|
||||
private readonly Option<P2PEndpoint> ownerEndpoint;
|
||||
|
||||
public GameServer(
|
||||
string name,
|
||||
@@ -135,7 +135,7 @@ namespace Barotrauma.Networking
|
||||
bool attemptUPnP,
|
||||
int maxPlayers,
|
||||
Option<int> ownerKey,
|
||||
Option<SteamId> ownerSteamId)
|
||||
Option<P2PEndpoint> ownerEndpoint)
|
||||
{
|
||||
if (name.Length > NetConfig.ServerNameMaxLength)
|
||||
{
|
||||
@@ -153,7 +153,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
this.ownerKey = ownerKey;
|
||||
|
||||
this.ownerSteamId = ownerSteamId;
|
||||
this.ownerEndpoint = ownerEndpoint;
|
||||
|
||||
entityEventManager = new ServerEntityEventManager(this);
|
||||
}
|
||||
@@ -168,16 +168,18 @@ namespace Barotrauma.Networking
|
||||
OnInitializationComplete,
|
||||
GameMain.Instance.CloseServer,
|
||||
OnOwnerDetermined);
|
||||
|
||||
if (ownerSteamId.TryUnwrap(out var steamId))
|
||||
|
||||
if (ownerEndpoint.TryUnwrap(out var endpoint))
|
||||
{
|
||||
Log("Using SteamP2P networking.", ServerLog.MessageType.ServerMessage);
|
||||
serverPeer = new SteamP2PServerPeer(steamId, ownerKey.Fallback(0), ServerSettings, callbacks);
|
||||
Log("Using P2P networking.", ServerLog.MessageType.ServerMessage);
|
||||
serverPeer = new P2PServerPeer(endpoint, ownerKey.Fallback(0), ServerSettings, callbacks);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("Using Lidgren networking. Manual port forwarding may be required. If players cannot connect to the server, you may want to use the in-game hosting menu (which uses SteamP2P networking and does not require port forwarding).", ServerLog.MessageType.ServerMessage);
|
||||
Log("Using Lidgren networking. Manual port forwarding may be required. If players cannot connect to the server, you may want to use the in-game hosting menu (which uses Steamworks and EOS networking and does not require port forwarding).", ServerLog.MessageType.ServerMessage);
|
||||
serverPeer = new LidgrenServerPeer(ownerKey, ServerSettings, callbacks);
|
||||
registeredToSteamMaster = SteamManager.CreateServer(this, ServerSettings.IsPublic);
|
||||
Eos.EosSessionManager.UpdateOwnedSession(Option.None, ServerSettings);
|
||||
}
|
||||
|
||||
FileSender = new FileSender(serverPeer, MsgConstants.MTU);
|
||||
@@ -190,15 +192,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
VoipServer = new VoipServer(serverPeer);
|
||||
|
||||
if (serverPeer is LidgrenServerPeer)
|
||||
{
|
||||
#if USE_STEAM
|
||||
registeredToMaster = SteamManager.CreateServer(this, ServerSettings.IsPublic);
|
||||
#endif
|
||||
}
|
||||
|
||||
GameMain.LuaCs.Initialize();
|
||||
|
||||
Log("Server started", ServerLog.MessageType.ServerMessage);
|
||||
|
||||
GameMain.NetLobbyScreen.Select();
|
||||
@@ -658,20 +652,23 @@ namespace Barotrauma.Networking
|
||||
updateTimer = DateTime.Now + UpdateInterval;
|
||||
}
|
||||
|
||||
if (registeredToMaster && (DateTime.Now > refreshMasterTimer || ServerSettings.ServerDetailsChanged))
|
||||
if (DateTime.Now > refreshMasterTimer || ServerSettings.ServerDetailsChanged)
|
||||
{
|
||||
if (GameSettings.CurrentConfig.UseSteamMatchmaking)
|
||||
if (registeredToSteamMaster)
|
||||
{
|
||||
bool refreshSuccessful = SteamManager.RefreshServerDetails(this);
|
||||
if (GameSettings.CurrentConfig.VerboseLogging)
|
||||
{
|
||||
Log(refreshSuccessful ?
|
||||
"Refreshed server info on the server list." :
|
||||
"Refreshing server info on the server list failed.", ServerLog.MessageType.ServerMessage);
|
||||
"Refreshed server info on the Steam server list." :
|
||||
"Refreshing server info on the Steam server list failed.", ServerLog.MessageType.ServerMessage);
|
||||
}
|
||||
}
|
||||
refreshMasterTimer = DateTime.Now + refreshMasterInterval;
|
||||
|
||||
Eos.EosSessionManager.UpdateOwnedSession(Option.None, ServerSettings);
|
||||
|
||||
ServerSettings.ServerDetailsChanged = false;
|
||||
refreshMasterTimer = DateTime.Now + refreshMasterInterval;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3082,8 +3079,6 @@ namespace Barotrauma.Networking
|
||||
client.WaitForNextRoundRespawn = null;
|
||||
client.InGame = false;
|
||||
|
||||
if (client.AccountId.TryUnwrap<SteamId>(out var steamId)) { SteamManager.StopAuthSession(steamId); }
|
||||
|
||||
var previousPlayer = previousPlayers.Find(p => p.MatchesClient(client));
|
||||
if (previousPlayer == null)
|
||||
{
|
||||
@@ -3416,7 +3411,7 @@ namespace Barotrauma.Networking
|
||||
msg.WriteByte((byte)ServerPacketHeader.FILE_TRANSFER);
|
||||
msg.WriteByte((byte)FileTransferMessageType.Cancel);
|
||||
msg.WriteByte((byte)transfer.ID);
|
||||
serverPeer.Send(msg, transfer.Connection, DeliveryMethod.ReliableOrdered);
|
||||
serverPeer.Send(msg, transfer.Connection, DeliveryMethod.Reliable);
|
||||
}
|
||||
|
||||
public void UpdateVoteStatus(bool checkActiveVote = true)
|
||||
@@ -3602,13 +3597,13 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
public void IncrementStat(Character character, Identifier achievementIdentifier, int amount)
|
||||
public void IncrementStat(Character character, AchievementStat stat, int amount)
|
||||
{
|
||||
foreach (Client client in connectedClients)
|
||||
{
|
||||
if (client.Character == character)
|
||||
{
|
||||
IncrementStat(client, achievementIdentifier, amount);
|
||||
IncrementStat(client, stat, amount);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -3622,19 +3617,17 @@ namespace Barotrauma.Networking
|
||||
IWriteMessage msg = new WriteOnlyMessage();
|
||||
msg.WriteByte((byte)ServerPacketHeader.ACHIEVEMENT);
|
||||
msg.WriteIdentifier(achievementIdentifier);
|
||||
msg.WriteInt32(0);
|
||||
|
||||
serverPeer.Send(msg, client.Connection, DeliveryMethod.Reliable);
|
||||
}
|
||||
|
||||
public void IncrementStat(Client client, Identifier achievementIdentifier, int amount)
|
||||
public void IncrementStat(Client client, AchievementStat stat, int amount)
|
||||
{
|
||||
if (client.GivenAchievements.Contains(achievementIdentifier)) { return; }
|
||||
|
||||
IWriteMessage msg = new WriteOnlyMessage();
|
||||
msg.WriteByte((byte)ServerPacketHeader.ACHIEVEMENT);
|
||||
msg.WriteIdentifier(achievementIdentifier);
|
||||
msg.WriteInt32(amount);
|
||||
msg.WriteByte((byte)ServerPacketHeader.ACHIEVEMENT_STAT);
|
||||
|
||||
INetSerializableStruct incrementedStat = new NetIncrementedStat(stat, amount);
|
||||
incrementedStat.Write(msg);
|
||||
|
||||
serverPeer.Send(msg, client.Connection, DeliveryMethod.Reliable);
|
||||
}
|
||||
@@ -3642,7 +3635,7 @@ namespace Barotrauma.Networking
|
||||
public void SendTraitorMessage(WriteOnlyMessage msg, Client client)
|
||||
{
|
||||
if (client == null) { return; };
|
||||
serverPeer.Send(msg, client.Connection, DeliveryMethod.ReliableOrdered);
|
||||
serverPeer.Send(msg, client.Connection, DeliveryMethod.Reliable);
|
||||
}
|
||||
|
||||
public void UpdateCheatsEnabled()
|
||||
|
||||
+92
-89
@@ -1,24 +1,26 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Net;
|
||||
using System.Linq;
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Steam;
|
||||
using Lidgren.Network;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
{
|
||||
internal sealed class LidgrenServerPeer : ServerPeer
|
||||
internal sealed class LidgrenServerPeer : ServerPeer<LidgrenConnection>
|
||||
{
|
||||
private readonly NetPeerConfiguration netPeerConfiguration;
|
||||
private ImmutableDictionary<AuthenticationTicketKind, Authenticator>? authenticators;
|
||||
private NetServer? netServer;
|
||||
|
||||
private readonly List<NetIncomingMessage> incomingLidgrenMessages;
|
||||
|
||||
public LidgrenServerPeer(Option<int> ownKey, ServerSettings settings, Callbacks callbacks) : base(callbacks)
|
||||
public LidgrenServerPeer(Option<int> ownKey, ServerSettings settings, Callbacks callbacks) : base(callbacks, settings)
|
||||
{
|
||||
serverSettings = settings;
|
||||
|
||||
authenticators = null;
|
||||
netServer = null;
|
||||
|
||||
netPeerConfiguration = new NetPeerConfiguration("barotrauma")
|
||||
@@ -42,9 +44,6 @@ namespace Barotrauma.Networking
|
||||
|
||||
netPeerConfiguration.EnableMessageType(NetIncomingMessageType.ConnectionApproval);
|
||||
|
||||
connectedClients = new List<NetworkConnection>();
|
||||
pendingClients = new List<PendingClient>();
|
||||
|
||||
incomingLidgrenMessages = new List<NetIncomingMessage>();
|
||||
|
||||
ownerKey = ownKey;
|
||||
@@ -54,6 +53,8 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (netServer != null) { return; }
|
||||
|
||||
authenticators = Authenticator.GetAuthenticatorsForHost(Option.None);
|
||||
|
||||
incomingLidgrenMessages.Clear();
|
||||
|
||||
netServer = new NetServer(netPeerConfiguration);
|
||||
@@ -81,7 +82,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
for (int i = connectedClients.Count - 1; i >= 0; i--)
|
||||
{
|
||||
Disconnect(connectedClients[i], PeerDisconnectPacket.WithReason(DisconnectReason.ServerShutdown));
|
||||
Disconnect(connectedClients[i].Connection, PeerDisconnectPacket.WithReason(DisconnectReason.ServerShutdown));
|
||||
}
|
||||
|
||||
netServer.Shutdown(PeerDisconnectPacket.WithReason(DisconnectReason.ServerShutdown).ToLidgrenStringRepresentation());
|
||||
@@ -91,8 +92,6 @@ namespace Barotrauma.Networking
|
||||
|
||||
netServer = null;
|
||||
|
||||
Steamworks.SteamServer.OnValidateAuthTicketResponse -= OnAuthChange;
|
||||
|
||||
callbacks.OnShutdown.Invoke();
|
||||
}
|
||||
|
||||
@@ -166,9 +165,10 @@ namespace Barotrauma.Networking
|
||||
ToolBox.ThrowIfNull(netPeerConfiguration);
|
||||
|
||||
netServer.UPnP.ForwardPort(netPeerConfiguration.Port, "barotrauma");
|
||||
#if USE_STEAM
|
||||
netServer.UPnP.ForwardPort(serverSettings.QueryPort, "barotrauma");
|
||||
#endif
|
||||
if (SteamManager.IsInitialized)
|
||||
{
|
||||
netServer.UPnP.ForwardPort(serverSettings.QueryPort, "barotrauma");
|
||||
}
|
||||
}
|
||||
|
||||
private bool DiscoveringUPnP()
|
||||
@@ -209,7 +209,7 @@ namespace Barotrauma.Networking
|
||||
return;
|
||||
}
|
||||
|
||||
PendingClient? pendingClient = pendingClients.Find(c => c.Connection is LidgrenConnection l && l.NetConnection == inc.SenderConnection);
|
||||
PendingClient? pendingClient = pendingClients.Find(c => c.Connection.NetConnection == inc.SenderConnection);
|
||||
|
||||
if (pendingClient is null)
|
||||
{
|
||||
@@ -224,7 +224,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (netServer == null) { return; }
|
||||
|
||||
PendingClient? pendingClient = pendingClients.Find(c => c.Connection is LidgrenConnection l && l.NetConnection == lidgrenMsg.SenderConnection);
|
||||
PendingClient? pendingClient = pendingClients.Find(c => c.Connection.NetConnection == lidgrenMsg.SenderConnection);
|
||||
|
||||
IReadMessage inc = lidgrenMsg.ToReadMessage();
|
||||
|
||||
@@ -236,7 +236,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
else if (!packetHeader.IsConnectionInitializationStep())
|
||||
{
|
||||
if (connectedClients.Find(c => c is LidgrenConnection l && l.NetConnection == lidgrenMsg.SenderConnection) is not LidgrenConnection conn)
|
||||
if (connectedClients.Find(c => c.Connection.NetConnection == lidgrenMsg.SenderConnection) is not { Connection: LidgrenConnection conn })
|
||||
{
|
||||
if (pendingClient != null)
|
||||
{
|
||||
@@ -273,7 +273,7 @@ namespace Barotrauma.Networking
|
||||
switch (inc.SenderConnection.Status)
|
||||
{
|
||||
case NetConnectionStatus.Disconnected:
|
||||
LidgrenConnection? conn = connectedClients.Cast<LidgrenConnection>().FirstOrDefault(c => c.NetConnection == inc.SenderConnection);
|
||||
LidgrenConnection? conn = connectedClients.Select(c => c.Connection).FirstOrDefault(c => c.NetConnection == inc.SenderConnection);
|
||||
if (conn != null)
|
||||
{
|
||||
if (conn == OwnerConnection)
|
||||
@@ -300,12 +300,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
public override void InitializeSteamServerCallbacks()
|
||||
{
|
||||
Steamworks.SteamServer.OnValidateAuthTicketResponse += OnAuthChange;
|
||||
}
|
||||
|
||||
private void OnAuthChange(Steamworks.SteamId steamId, Steamworks.SteamId ownerId, Steamworks.AuthResponse status)
|
||||
private void OnSteamAuthChange(Steamworks.SteamId steamId, Steamworks.SteamId ownerId, Steamworks.AuthResponse status)
|
||||
{
|
||||
if (netServer == null) { return; }
|
||||
|
||||
@@ -317,8 +312,8 @@ namespace Barotrauma.Networking
|
||||
if (status == Steamworks.AuthResponse.OK) { return; }
|
||||
|
||||
if (connectedClients.Find(c
|
||||
=> c.AccountInfo.AccountId.TryUnwrap<SteamId>(out var id) && id.Value == steamId)
|
||||
is LidgrenConnection connection)
|
||||
=> c.Connection.AccountInfo.AccountId.TryUnwrap<SteamId>(out var id) && id.Value == steamId)
|
||||
is { Connection: LidgrenConnection connection })
|
||||
{
|
||||
Disconnect(connection, PeerDisconnectPacket.SteamAuthError(status));
|
||||
}
|
||||
@@ -351,9 +346,15 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (netServer == null) { return; }
|
||||
|
||||
if (!connectedClients.Contains(conn))
|
||||
if (conn is not LidgrenConnection lidgrenConnection)
|
||||
{
|
||||
DebugConsole.ThrowError($"Tried to send message to unauthenticated connection: {conn.Endpoint.StringRepresentation}");
|
||||
DebugConsole.ThrowError($"Tried to send message to connection of incorrect type: expected {nameof(LidgrenConnection)}, got {conn.GetType().Name}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!connectedClients.Any(cc => cc.Connection == lidgrenConnection))
|
||||
{
|
||||
DebugConsole.ThrowError($"Tried to send message to unauthenticated connection: {lidgrenConnection.Endpoint.StringRepresentation}");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -377,7 +378,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
Buffer = bufAux
|
||||
};
|
||||
SendMsgInternal(conn, headers, body);
|
||||
SendMsgInternal(lidgrenConnection, headers, body);
|
||||
}
|
||||
|
||||
public override void Disconnect(NetworkConnection conn, PeerDisconnectPacket peerDisconnectPacket)
|
||||
@@ -386,18 +387,21 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (conn is not LidgrenConnection lidgrenConn) { return; }
|
||||
|
||||
if (connectedClients.Contains(lidgrenConn))
|
||||
if (connectedClients.FindIndex(cc => cc.Connection == lidgrenConn) is >= 0 and var ccIndex)
|
||||
{
|
||||
lidgrenConn.Status = NetworkConnectionStatus.Disconnected;
|
||||
connectedClients.Remove(lidgrenConn);
|
||||
connectedClients.RemoveAt(ccIndex);
|
||||
callbacks.OnDisconnect.Invoke(conn, peerDisconnectPacket);
|
||||
if (conn.AccountInfo.AccountId.TryUnwrap<SteamId>(out var steamId)) { SteamManager.StopAuthSession(steamId); }
|
||||
if (conn.AccountInfo.AccountId.TryUnwrap(out var accountId))
|
||||
{
|
||||
authenticators?.Values.ForEach(authenticator => authenticator.EndAuthSession(accountId));
|
||||
}
|
||||
}
|
||||
|
||||
lidgrenConn.NetConnection.Disconnect(peerDisconnectPacket.ToLidgrenStringRepresentation());
|
||||
}
|
||||
|
||||
protected override void SendMsgInternal(NetworkConnection conn, PeerPacketHeaders headers, INetSerializableStruct? body)
|
||||
protected override void SendMsgInternal(LidgrenConnection conn, PeerPacketHeaders headers, INetSerializableStruct? body)
|
||||
{
|
||||
IWriteMessage msgToSend = new WriteOnlyMessage();
|
||||
msgToSend.WriteNetSerializableStruct(headers);
|
||||
@@ -412,75 +416,74 @@ namespace Barotrauma.Networking
|
||||
|
||||
protected override void CheckOwnership(PendingClient pendingClient)
|
||||
{
|
||||
if (OwnerConnection == null
|
||||
&& pendingClient.Connection is LidgrenConnection l
|
||||
&& IPAddress.IsLoopback(l.NetConnection.RemoteEndPoint.Address)
|
||||
&& ownerKey.IsSome() && pendingClient.OwnerKey == ownerKey)
|
||||
if (OwnerConnection != null
|
||||
|| pendingClient.Connection is not LidgrenConnection l
|
||||
|| !IPAddress.IsLoopback(l.NetConnection.RemoteEndPoint.Address)
|
||||
|| !ownerKey.IsSome() || pendingClient.OwnerKey != ownerKey)
|
||||
{
|
||||
ownerKey = Option<int>.None();
|
||||
OwnerConnection = pendingClient.Connection;
|
||||
callbacks.OnOwnerDetermined.Invoke(OwnerConnection);
|
||||
return;
|
||||
}
|
||||
|
||||
ownerKey = Option.None;
|
||||
OwnerConnection = pendingClient.Connection;
|
||||
callbacks.OnOwnerDetermined.Invoke(OwnerConnection);
|
||||
}
|
||||
|
||||
protected override void ProcessAuthTicket(ClientSteamTicketAndVersionPacket packet, PendingClient pendingClient)
|
||||
private enum AuthResult
|
||||
{
|
||||
if (pendingClient.AccountInfo.AccountId.IsNone())
|
||||
Success,
|
||||
Failure
|
||||
}
|
||||
|
||||
protected override void ProcessAuthTicket(ClientAuthTicketAndVersionPacket packet, PendingClient pendingClient)
|
||||
{
|
||||
if (pendingClient.AccountInfo.AccountId.IsSome())
|
||||
{
|
||||
if (pendingClient.AccountInfo.AccountId != packet.AccountId)
|
||||
{
|
||||
RemovePendingClient(pendingClient, PeerDisconnectPacket.WithReason(DisconnectReason.AuthenticationFailed));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void acceptClient(AccountInfo accountInfo)
|
||||
{
|
||||
pendingClient.Connection.SetAccountInfo(accountInfo);
|
||||
pendingClient.Name = packet.Name;
|
||||
pendingClient.OwnerKey = packet.OwnerKey;
|
||||
pendingClient.InitializationStep = serverSettings.HasPassword ? ConnectionInitialization.Password : ConnectionInitialization.ContentPackageOrder;
|
||||
}
|
||||
|
||||
void rejectClient()
|
||||
{
|
||||
RemovePendingClient(pendingClient, PeerDisconnectPacket.WithReason(DisconnectReason.AuthenticationFailed));
|
||||
}
|
||||
|
||||
if (authenticators is null
|
||||
|| !packet.AuthTicket.TryUnwrap(out var authTicket)
|
||||
|| !authenticators.TryGetValue(authTicket.Kind, out var authenticator))
|
||||
{
|
||||
bool requireSteamAuth = GameSettings.CurrentConfig.RequireSteamAuthentication;
|
||||
#if DEBUG
|
||||
requireSteamAuth = false;
|
||||
DebugConsole.NewMessage($"Debug server accepts unauthenticated connections", Microsoft.Xna.Framework.Color.Yellow);
|
||||
acceptClient(new AccountInfo(packet.AccountId));
|
||||
#else
|
||||
rejectClient();
|
||||
#endif
|
||||
bool hasSteamAuth = packet.SteamAuthTicket.TryUnwrap(out var ticket);
|
||||
|
||||
//steam auth cannot be done (SteamManager not initialized or no ticket given),
|
||||
//but it's not required either -> let the client join without auth
|
||||
if ((!SteamManager.IsInitialized || !hasSteamAuth) && !requireSteamAuth)
|
||||
{
|
||||
pendingClient.Name = packet.Name;
|
||||
pendingClient.OwnerKey = packet.OwnerKey;
|
||||
pendingClient.InitializationStep = serverSettings.HasPassword ? ConnectionInitialization.Password : ConnectionInitialization.ContentPackageOrder;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!packet.SteamId.TryUnwrap(out var id) || id is not SteamId steamId)
|
||||
{
|
||||
if (requireSteamAuth)
|
||||
{
|
||||
RemovePendingClient(pendingClient, PeerDisconnectPacket.WithReason(DisconnectReason.SteamAuthenticationFailed));
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Steamworks.BeginAuthResult authSessionStartState = SteamManager.StartAuthSession(ticket, steamId);
|
||||
if (authSessionStartState != Steamworks.BeginAuthResult.OK)
|
||||
{
|
||||
if (requireSteamAuth)
|
||||
{
|
||||
RemovePendingClient(pendingClient, PeerDisconnectPacket.SteamAuthError(authSessionStartState));
|
||||
}
|
||||
else
|
||||
{
|
||||
packet.SteamId = Option<AccountId>.None();
|
||||
pendingClient.InitializationStep = serverSettings.HasPassword ? ConnectionInitialization.Password : ConnectionInitialization.ContentPackageOrder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pendingClient.Connection.SetAccountInfo(new AccountInfo(packet.SteamId.Select(uid => (AccountId)uid)));
|
||||
pendingClient.Name = packet.Name;
|
||||
pendingClient.OwnerKey = packet.OwnerKey;
|
||||
pendingClient.AuthSessionStarted = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
pendingClient.AuthSessionStarted = true;
|
||||
TaskPool.Add($"{nameof(LidgrenServerPeer)}.ProcessAuth", authenticator.VerifyTicket(authTicket), t =>
|
||||
{
|
||||
if (pendingClient.AccountInfo.AccountId != packet.SteamId.Select(uid => (AccountId)uid))
|
||||
if (!t.TryGetResult(out AccountInfo accountInfo)
|
||||
|| accountInfo.IsNone)
|
||||
{
|
||||
RemovePendingClient(pendingClient, PeerDisconnectPacket.WithReason(DisconnectReason.SteamAuthenticationFailed));
|
||||
rejectClient();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
acceptClient(accountInfo);
|
||||
});
|
||||
}
|
||||
|
||||
private NetSendResult ForwardToLidgren(IWriteMessage msg, NetworkConnection connection, DeliveryMethod deliveryMethod)
|
||||
|
||||
+112
-103
@@ -1,30 +1,20 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
{
|
||||
internal sealed class SteamP2PServerPeer : ServerPeer
|
||||
internal sealed class P2PServerPeer : ServerPeer<P2PConnection>
|
||||
{
|
||||
private bool started;
|
||||
|
||||
private readonly SteamId ownerSteamId;
|
||||
private readonly P2PEndpoint ownerEndpoint;
|
||||
|
||||
private UInt64 ownerKey64 => unchecked((UInt64)ownerKey.Fallback(0));
|
||||
|
||||
private SteamId ReadSteamId(IReadMessage inc) => new SteamId(inc.ReadUInt64() ^ ownerKey64);
|
||||
private void WriteSteamId(IWriteMessage msg, SteamId val) => msg.WriteUInt64(val.Value ^ ownerKey64);
|
||||
|
||||
public SteamP2PServerPeer(SteamId steamId, int ownerKey, ServerSettings settings, Callbacks callbacks) : base(callbacks)
|
||||
public P2PServerPeer(P2PEndpoint ownerEp, int ownerKey, ServerSettings settings, Callbacks callbacks) : base(callbacks, settings)
|
||||
{
|
||||
serverSettings = settings;
|
||||
this.ownerKey = Option.Some(ownerKey);
|
||||
|
||||
connectedClients = new List<NetworkConnection>();
|
||||
pendingClients = new List<PendingClient>();
|
||||
|
||||
this.ownerKey = Option<int>.Some(ownerKey);
|
||||
|
||||
ownerSteamId = steamId;
|
||||
ownerEndpoint = ownerEp;
|
||||
|
||||
started = false;
|
||||
}
|
||||
@@ -37,7 +27,7 @@ namespace Barotrauma.Networking
|
||||
PacketHeader = PacketHeader.IsConnectionInitializationStep | PacketHeader.IsServerMessage,
|
||||
Initialization = null
|
||||
};
|
||||
SendMsgInternal(ownerSteamId, headers, null);
|
||||
SendMsgInternal(ownerEndpoint, headers, null);
|
||||
|
||||
started = true;
|
||||
}
|
||||
@@ -55,7 +45,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
for (int i = connectedClients.Count - 1; i >= 0; i--)
|
||||
{
|
||||
Disconnect(connectedClients[i], PeerDisconnectPacket.WithReason(DisconnectReason.ServerShutdown));
|
||||
Disconnect(connectedClients[i].Connection, PeerDisconnectPacket.WithReason(DisconnectReason.ServerShutdown));
|
||||
}
|
||||
|
||||
pendingClients.Clear();
|
||||
@@ -73,7 +63,7 @@ namespace Barotrauma.Networking
|
||||
//backwards for loop so we can remove elements while iterating
|
||||
for (int i = connectedClients.Count - 1; i >= 0; i--)
|
||||
{
|
||||
SteamP2PConnection conn = (SteamP2PConnection)connectedClients[i];
|
||||
var conn = connectedClients[i].Connection;
|
||||
conn.Decay(deltaTime);
|
||||
if (conn.Timeout < 0.0)
|
||||
{
|
||||
@@ -83,7 +73,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
try
|
||||
{
|
||||
while (ChildServerRelay.Read(out byte[] incBuf))
|
||||
foreach (var incBuf in ChildServerRelay.Read())
|
||||
{
|
||||
IReadMessage inc = new ReadOnlyMessage(incBuf, false, 0, incBuf.Length, OwnerConnection);
|
||||
|
||||
@@ -114,51 +104,34 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (!started) { return; }
|
||||
|
||||
SteamId senderSteamId = ReadSteamId(inc);
|
||||
SteamId sentOwnerSteamId = ReadSteamId(inc);
|
||||
|
||||
var (deliveryMethod, packetHeader, initialization) = INetSerializableStruct.Read<PeerPacketHeaders>(inc);
|
||||
|
||||
if (packetHeader.IsServerMessage())
|
||||
var senderInfo = INetSerializableStruct.Read<P2POwnerToServerHeader>(inc);
|
||||
if (!senderInfo.Endpoint.TryUnwrap(out var senderEndpoint))
|
||||
{
|
||||
DebugConsole.ThrowError($"Got server message from {senderSteamId}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (senderSteamId != ownerSteamId) //sender is remote, handle disconnects and heartbeats
|
||||
{
|
||||
bool connectionMatches(NetworkConnection conn) =>
|
||||
conn is SteamP2PConnection { Endpoint: SteamP2PEndpoint { SteamId: var steamId } }
|
||||
&& steamId == senderSteamId;
|
||||
var (_, packetHeader, initialization) = INetSerializableStruct.Read<PeerPacketHeaders>(inc);
|
||||
|
||||
PendingClient? pendingClient = pendingClients.Find(c => connectionMatches(c.Connection));
|
||||
SteamP2PConnection? connectedClient = connectedClients.Find(connectionMatches) as SteamP2PConnection;
|
||||
if (packetHeader.IsServerMessage())
|
||||
{
|
||||
DebugConsole.ThrowError($"Got server message from {senderEndpoint}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (senderEndpoint != ownerEndpoint) //sender is remote, handle disconnects and heartbeats
|
||||
{
|
||||
bool connectionMatches(P2PConnection conn) =>
|
||||
conn.Endpoint == senderEndpoint;
|
||||
|
||||
var pendingClient = pendingClients.Find(c => connectionMatches(c.Connection));
|
||||
var connectedClient = connectedClients.Find(c => connectionMatches(c.Connection));
|
||||
pendingClient?.Connection.SetAccountInfo(senderInfo.AccountInfo);
|
||||
|
||||
pendingClient?.Heartbeat();
|
||||
connectedClient?.Heartbeat();
|
||||
connectedClient?.Connection.Heartbeat();
|
||||
|
||||
if (packetHeader.IsConnectionInitializationStep())
|
||||
{
|
||||
if (!initialization.HasValue) { return; }
|
||||
ConnectionInitialization initializationStep = initialization.Value;
|
||||
|
||||
if (pendingClient != null)
|
||||
{
|
||||
pendingClient.Connection.SetAccountInfo(new AccountInfo(senderSteamId, sentOwnerSteamId));
|
||||
ReadConnectionInitializationStep(
|
||||
pendingClient,
|
||||
new ReadWriteMessage(inc.Buffer, inc.BitPosition, inc.LengthBits, false),
|
||||
initializationStep);
|
||||
}
|
||||
else if (initializationStep == ConnectionInitialization.ConnectionStarted)
|
||||
{
|
||||
pendingClient = new PendingClient(new SteamP2PConnection(senderSteamId));
|
||||
pendingClient.Connection.SetAccountInfo(new AccountInfo(senderSteamId, sentOwnerSteamId));
|
||||
pendingClients.Add(pendingClient);
|
||||
}
|
||||
}
|
||||
else if (serverSettings.BanList.IsBanned(senderSteamId, out string banReason) ||
|
||||
serverSettings.BanList.IsBanned(sentOwnerSteamId, out banReason))
|
||||
if (serverSettings.BanList.IsBanned(senderEndpoint, out string banReason)
|
||||
|| serverSettings.BanList.IsBanned(senderInfo.AccountInfo, out banReason))
|
||||
{
|
||||
if (pendingClient != null)
|
||||
{
|
||||
@@ -166,7 +139,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
else if (connectedClient != null)
|
||||
{
|
||||
Disconnect(connectedClient, PeerDisconnectPacket.Banned(banReason));
|
||||
Disconnect(connectedClient.Connection, PeerDisconnectPacket.Banned(banReason));
|
||||
}
|
||||
}
|
||||
else if (packetHeader.IsDisconnectMessage())
|
||||
@@ -177,7 +150,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
else if (connectedClient != null)
|
||||
{
|
||||
Disconnect(connectedClient, PeerDisconnectPacket.WithReason(DisconnectReason.Disconnected));
|
||||
Disconnect(connectedClient.Connection, PeerDisconnectPacket.WithReason(DisconnectReason.Disconnected));
|
||||
}
|
||||
}
|
||||
else if (packetHeader.IsHeartbeatMessage())
|
||||
@@ -185,16 +158,44 @@ namespace Barotrauma.Networking
|
||||
//message exists solely as a heartbeat, ignore its contents
|
||||
return;
|
||||
}
|
||||
else if (packetHeader.IsConnectionInitializationStep())
|
||||
{
|
||||
if (!initialization.HasValue) { return; }
|
||||
ConnectionInitialization initializationStep = initialization.Value;
|
||||
|
||||
if (pendingClient != null)
|
||||
{
|
||||
ReadConnectionInitializationStep(
|
||||
pendingClient,
|
||||
new ReadWriteMessage(inc.Buffer, inc.BitPosition, inc.LengthBits, false),
|
||||
initializationStep);
|
||||
}
|
||||
else if (initializationStep == ConnectionInitialization.ConnectionStarted)
|
||||
{
|
||||
pendingClients.Add(new PendingClient(senderEndpoint.MakeConnectionFromEndpoint()));
|
||||
}
|
||||
}
|
||||
else if (connectedClient != null)
|
||||
{
|
||||
var packet = INetSerializableStruct.Read<PeerPacketMessage>(inc);
|
||||
IReadMessage msg = new ReadOnlyMessage(packet.Buffer, packetHeader.IsCompressed(), 0, packet.Length, connectedClient);
|
||||
callbacks.OnMessageReceived.Invoke(connectedClient, msg);
|
||||
if (packetHeader.IsDataFragment())
|
||||
{
|
||||
var completeMessageOption = connectedClient.Defragmenter.ProcessIncomingFragment(INetSerializableStruct.Read<MessageFragment>(inc));
|
||||
if (!completeMessageOption.TryUnwrap(out var completeMessage)) { return; }
|
||||
|
||||
IReadMessage msg = new ReadOnlyMessage(completeMessage.ToArray(), false, 0, completeMessage.Length, connectedClient.Connection);
|
||||
callbacks.OnMessageReceived.Invoke(connectedClient.Connection, msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
var packet = INetSerializableStruct.Read<PeerPacketMessage>(inc);
|
||||
IReadMessage msg = new ReadOnlyMessage(packet.Buffer, packetHeader.IsCompressed(), 0, packet.Length, connectedClient.Connection);
|
||||
callbacks.OnMessageReceived.Invoke(connectedClient.Connection, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
else //sender is owner
|
||||
{
|
||||
(OwnerConnection as SteamP2PConnection)?.Heartbeat();
|
||||
OwnerConnection?.Heartbeat();
|
||||
|
||||
if (packetHeader.IsDisconnectMessage())
|
||||
{
|
||||
@@ -212,14 +213,12 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (OwnerConnection is null)
|
||||
{
|
||||
var packet = INetSerializableStruct.Read<SteamP2PInitializationOwnerPacket>(inc);
|
||||
OwnerConnection = new SteamP2PConnection(ownerSteamId)
|
||||
{
|
||||
Language = GameSettings.CurrentConfig.Language
|
||||
};
|
||||
OwnerConnection.SetAccountInfo(new AccountInfo(ownerSteamId, ownerSteamId));
|
||||
var packet = INetSerializableStruct.Read<P2PInitializationOwnerPacket>(inc);
|
||||
OwnerConnection = ownerEndpoint.MakeConnectionFromEndpoint();
|
||||
OwnerConnection.Language = GameSettings.CurrentConfig.Language;
|
||||
OwnerConnection.SetAccountInfo(senderInfo.AccountInfo);
|
||||
|
||||
callbacks.OnInitializationComplete.Invoke(OwnerConnection, packet.OwnerName);
|
||||
callbacks.OnInitializationComplete.Invoke(OwnerConnection, packet.Name);
|
||||
callbacks.OnOwnerDetermined.Invoke(OwnerConnection);
|
||||
}
|
||||
|
||||
@@ -239,27 +238,38 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
public override void InitializeSteamServerCallbacks()
|
||||
{
|
||||
throw new InvalidOperationException("Called InitializeSteamServerCallbacks on SteamP2PServerPeer!");
|
||||
}
|
||||
|
||||
public override void Send(IWriteMessage msg, NetworkConnection conn, DeliveryMethod deliveryMethod, bool compressPastThreshold = true)
|
||||
{
|
||||
if (!started) { return; }
|
||||
|
||||
if (conn is not SteamP2PConnection steamP2PConn) { return; }
|
||||
if (conn is not P2PConnection p2pConn) { return; }
|
||||
|
||||
if (!connectedClients.Contains(steamP2PConn) && conn != OwnerConnection)
|
||||
int ccIndex = connectedClients.FindIndex(cc => cc.Connection == p2pConn);
|
||||
if (ccIndex < 0 && conn != OwnerConnection)
|
||||
{
|
||||
DebugConsole.ThrowError($"Tried to send message to unauthenticated connection: {steamP2PConn.AccountInfo.AccountId}");
|
||||
DebugConsole.ThrowError($"Tried to send message to unauthenticated connection: {p2pConn.AccountInfo.AccountId}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!conn.AccountInfo.AccountId.TryUnwrap(out var connAccountId) || connAccountId is not SteamId) { return; }
|
||||
|
||||
byte[] bufAux = msg.PrepareForSending(compressPastThreshold, out bool isCompressed, out _);
|
||||
|
||||
if (bufAux.Length > MessageFragment.MaxSize && conn != OwnerConnection)
|
||||
{
|
||||
var cc = connectedClients[ccIndex];
|
||||
var fragments = cc.Fragmenter.FragmentMessage(msg.Buffer.AsSpan()[..msg.LengthBytes]);
|
||||
foreach (var fragment in fragments)
|
||||
{
|
||||
var fragmentHeaders = new PeerPacketHeaders
|
||||
{
|
||||
DeliveryMethod = DeliveryMethod.Reliable,
|
||||
PacketHeader = PacketHeader.IsDataFragment
|
||||
| PacketHeader.IsServerMessage,
|
||||
Initialization = null
|
||||
};
|
||||
SendMsgInternal(p2pConn, fragmentHeaders, fragment);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var headers = new PeerPacketHeaders
|
||||
{
|
||||
DeliveryMethod = deliveryMethod,
|
||||
@@ -271,10 +281,10 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
Buffer = bufAux
|
||||
};
|
||||
SendMsgInternal(steamP2PConn, headers, body);
|
||||
SendMsgInternal(p2pConn, headers, body);
|
||||
}
|
||||
|
||||
private void SendDisconnectMessage(SteamId steamId, PeerDisconnectPacket peerDisconnectPacket)
|
||||
private void SendDisconnectMessage(P2PEndpoint endpoint, PeerDisconnectPacket peerDisconnectPacket)
|
||||
{
|
||||
if (!started) { return; }
|
||||
|
||||
@@ -285,44 +295,41 @@ namespace Barotrauma.Networking
|
||||
Initialization = null
|
||||
};
|
||||
|
||||
SendMsgInternal(steamId, headers, peerDisconnectPacket);
|
||||
SendMsgInternal(endpoint, headers, peerDisconnectPacket);
|
||||
}
|
||||
|
||||
public override void Disconnect(NetworkConnection conn, PeerDisconnectPacket peerDisconnectPacket)
|
||||
{
|
||||
if (!started) { return; }
|
||||
|
||||
if (conn is not SteamP2PConnection steamp2pConn) { return; }
|
||||
if (conn is not P2PConnection p2pConn) { return; }
|
||||
|
||||
if (!conn.AccountInfo.AccountId.TryUnwrap(out var connAccountId) || connAccountId is not SteamId connSteamId) { return; }
|
||||
SendDisconnectMessage(p2pConn.Endpoint, peerDisconnectPacket);
|
||||
|
||||
SendDisconnectMessage(connSteamId, peerDisconnectPacket);
|
||||
|
||||
if (connectedClients.Contains(steamp2pConn))
|
||||
if (connectedClients.FindIndex(cc => cc.Connection == p2pConn) is >= 0 and var ccIndex)
|
||||
{
|
||||
steamp2pConn.Status = NetworkConnectionStatus.Disconnected;
|
||||
connectedClients.Remove(steamp2pConn);
|
||||
p2pConn.Status = NetworkConnectionStatus.Disconnected;
|
||||
connectedClients.RemoveAt(ccIndex);
|
||||
callbacks.OnDisconnect.Invoke(conn, peerDisconnectPacket);
|
||||
Steam.SteamManager.StopAuthSession(connSteamId);
|
||||
}
|
||||
else if (steamp2pConn == OwnerConnection)
|
||||
else if (p2pConn == OwnerConnection)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot disconnect owner peer");
|
||||
}
|
||||
}
|
||||
|
||||
protected override void SendMsgInternal(NetworkConnection conn, PeerPacketHeaders headers, INetSerializableStruct? body)
|
||||
protected override void SendMsgInternal(P2PConnection conn, PeerPacketHeaders headers, INetSerializableStruct? body)
|
||||
{
|
||||
var connSteamId = conn is SteamP2PConnection { Endpoint: SteamP2PEndpoint { SteamId: var id } } ? id : null;
|
||||
if (connSteamId is null) { return; }
|
||||
|
||||
SendMsgInternal(connSteamId, headers, body);
|
||||
SendMsgInternal(conn.Endpoint, headers, body);
|
||||
}
|
||||
|
||||
private void SendMsgInternal(SteamId connSteamId, PeerPacketHeaders headers, INetSerializableStruct? body)
|
||||
|
||||
private void SendMsgInternal(P2PEndpoint connEndpoint, PeerPacketHeaders headers, INetSerializableStruct? body)
|
||||
{
|
||||
IWriteMessage msgToSend = new WriteOnlyMessage();
|
||||
WriteSteamId(msgToSend, connSteamId);
|
||||
msgToSend.WriteNetSerializableStruct(new P2PServerToOwnerHeader
|
||||
{
|
||||
EndpointStr = connEndpoint.StringRepresentation
|
||||
});
|
||||
msgToSend.WriteNetSerializableStruct(headers);
|
||||
body?.Write(msgToSend);
|
||||
|
||||
@@ -336,11 +343,13 @@ namespace Barotrauma.Networking
|
||||
ChildServerRelay.Write(bufToSend);
|
||||
}
|
||||
|
||||
protected override void ProcessAuthTicket(ClientSteamTicketAndVersionPacket packet, PendingClient pendingClient)
|
||||
protected override void ProcessAuthTicket(ClientAuthTicketAndVersionPacket packet, PendingClient pendingClient)
|
||||
{
|
||||
// Do nothing with the auth ticket because that should be handled by the owner peer,
|
||||
// just assume that authentication succeeded
|
||||
pendingClient.InitializationStep = serverSettings.HasPassword ? ConnectionInitialization.Password : ConnectionInitialization.ContentPackageOrder;
|
||||
pendingClient.Name = packet.Name;
|
||||
pendingClient.AuthSessionStarted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+68
-49
@@ -7,28 +7,14 @@ using Barotrauma.Extensions;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
{
|
||||
internal abstract class ServerPeer
|
||||
internal abstract class ServerPeer<TConnection> : ServerPeer where TConnection : NetworkConnection
|
||||
{
|
||||
public readonly record struct Callbacks(
|
||||
Callbacks.MessageCallback OnMessageReceived,
|
||||
Callbacks.DisconnectCallback OnDisconnect,
|
||||
Callbacks.InitializationCompleteCallback OnInitializationComplete,
|
||||
Callbacks.ShutdownCallback OnShutdown,
|
||||
Callbacks.OwnerDeterminedCallback OnOwnerDetermined)
|
||||
{
|
||||
public delegate void MessageCallback(NetworkConnection connection, IReadMessage message);
|
||||
public delegate void DisconnectCallback(NetworkConnection connection, PeerDisconnectPacket peerDisconnectPacket);
|
||||
public delegate void InitializationCompleteCallback(NetworkConnection connection, string? clientName);
|
||||
public delegate void ShutdownCallback();
|
||||
public delegate void OwnerDeterminedCallback(NetworkConnection connection);
|
||||
}
|
||||
|
||||
protected readonly Callbacks callbacks;
|
||||
private readonly ImmutableArray<ContentPackage> contentPackages;
|
||||
|
||||
protected ServerPeer(Callbacks callbacks)
|
||||
protected ServerPeer(Callbacks callbacks, ServerSettings serverSettings) : base(callbacks)
|
||||
{
|
||||
this.callbacks = callbacks;
|
||||
this.serverSettings = serverSettings;
|
||||
this.connectedClients = new List<ConnectedClient>();
|
||||
this.pendingClients = new List<PendingClient>();
|
||||
|
||||
List<ContentPackage> contentPackageList = new List<ContentPackage>();
|
||||
foreach (var cp in ContentPackageManager.EnabledPackages.All)
|
||||
@@ -45,19 +31,13 @@ namespace Barotrauma.Networking
|
||||
contentPackageList.Add(cp);
|
||||
}
|
||||
contentPackages = contentPackageList.ToImmutableArray();
|
||||
}
|
||||
|
||||
public abstract void InitializeSteamServerCallbacks();
|
||||
|
||||
public abstract void Start();
|
||||
public abstract void Close();
|
||||
public abstract void Update(float deltaTime);
|
||||
}
|
||||
|
||||
public sealed class PendingClient
|
||||
{
|
||||
public string? Name;
|
||||
public Option<int> OwnerKey;
|
||||
public readonly NetworkConnection Connection;
|
||||
public readonly TConnection Connection;
|
||||
public ConnectionInitialization InitializationStep;
|
||||
public double UpdateTime;
|
||||
public double TimeOut;
|
||||
@@ -67,11 +47,11 @@ namespace Barotrauma.Networking
|
||||
|
||||
public AccountInfo AccountInfo => Connection.AccountInfo;
|
||||
|
||||
public PendingClient(NetworkConnection conn)
|
||||
public PendingClient(TConnection conn)
|
||||
{
|
||||
OwnerKey = Option<int>.None();
|
||||
OwnerKey = Option.None;
|
||||
Connection = conn;
|
||||
InitializationStep = ConnectionInitialization.SteamTicketAndVersion;
|
||||
InitializationStep = ConnectionInitialization.AuthInfoAndVersion;
|
||||
Retries = 0;
|
||||
PasswordSalt = null;
|
||||
UpdateTime = Timing.TotalTime + Timing.Step * 3.0;
|
||||
@@ -85,11 +65,26 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
protected List<NetworkConnection> connectedClients = null!;
|
||||
protected List<PendingClient> pendingClients = null!;
|
||||
protected ServerSettings serverSettings = null!;
|
||||
protected sealed class ConnectedClient
|
||||
{
|
||||
public readonly TConnection Connection;
|
||||
public readonly MessageFragmenter Fragmenter;
|
||||
public readonly MessageDefragmenter Defragmenter;
|
||||
|
||||
public ConnectedClient(TConnection connection)
|
||||
{
|
||||
Connection = connection;
|
||||
Fragmenter = new();
|
||||
Defragmenter = new();
|
||||
}
|
||||
}
|
||||
|
||||
protected readonly List<ConnectedClient> connectedClients;
|
||||
protected readonly List<PendingClient> pendingClients;
|
||||
protected readonly ServerSettings serverSettings;
|
||||
|
||||
protected TConnection? OwnerConnection;
|
||||
protected Option<int> ownerKey = Option.None;
|
||||
protected NetworkConnection? OwnerConnection;
|
||||
|
||||
protected void ReadConnectionInitializationStep(PendingClient pendingClient, IReadMessage inc, ConnectionInitialization initializationStep)
|
||||
{
|
||||
@@ -101,8 +96,8 @@ namespace Barotrauma.Networking
|
||||
|
||||
switch (initializationStep)
|
||||
{
|
||||
case ConnectionInitialization.SteamTicketAndVersion:
|
||||
var authPacket = INetSerializableStruct.Read<ClientSteamTicketAndVersionPacket>(inc);
|
||||
case ConnectionInitialization.AuthInfoAndVersion:
|
||||
var authPacket = INetSerializableStruct.Read<ClientAuthTicketAndVersionPacket>(inc);
|
||||
|
||||
if (!Client.IsValidName(authPacket.Name, serverSettings))
|
||||
{
|
||||
@@ -117,8 +112,8 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
RemovePendingClient(pendingClient, PeerDisconnectPacket.InvalidVersion());
|
||||
|
||||
GameServer.Log($"{authPacket.Name} ({authPacket.SteamId}) couldn't join the server (incompatible game version)", ServerLog.MessageType.Error);
|
||||
DebugConsole.NewMessage($"{authPacket.Name} ({authPacket.SteamId}) couldn't join the server (incompatible game version)", Microsoft.Xna.Framework.Color.Red);
|
||||
GameServer.Log($"{authPacket.Name} ({authPacket.AccountId}) couldn't join the server (incompatible game version)", ServerLog.MessageType.Error);
|
||||
DebugConsole.NewMessage($"{authPacket.Name} ({authPacket.AccountId}) couldn't join the server (incompatible game version)", Microsoft.Xna.Framework.Color.Red);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -128,7 +123,7 @@ namespace Barotrauma.Networking
|
||||
if (nameTaken != null)
|
||||
{
|
||||
RemovePendingClient(pendingClient, PeerDisconnectPacket.WithReason(DisconnectReason.NameTaken));
|
||||
GameServer.Log($"{authPacket.Name} ({authPacket.SteamId}) couldn't join the server (name too similar to the name of the client \"" + nameTaken.Name + "\").", ServerLog.MessageType.Error);
|
||||
GameServer.Log($"{authPacket.Name} ({authPacket.AccountId}) couldn't join the server (name too similar to the name of the client \"" + nameTaken.Name + "\").", ServerLog.MessageType.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -172,7 +167,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void ProcessAuthTicket(ClientSteamTicketAndVersionPacket packet, PendingClient pendingClient);
|
||||
protected abstract void ProcessAuthTicket(ClientAuthTicketAndVersionPacket packet, PendingClient pendingClient);
|
||||
|
||||
protected void BanPendingClient(PendingClient pendingClient, string banReason, TimeSpan? duration)
|
||||
{
|
||||
@@ -214,7 +209,7 @@ namespace Barotrauma.Networking
|
||||
return isBanned;
|
||||
}
|
||||
|
||||
protected abstract void SendMsgInternal(NetworkConnection conn, PeerPacketHeaders headers, INetSerializableStruct? body);
|
||||
protected abstract void SendMsgInternal(TConnection conn, PeerPacketHeaders headers, INetSerializableStruct? body);
|
||||
|
||||
protected void UpdatePendingClient(PendingClient pendingClient)
|
||||
{
|
||||
@@ -236,8 +231,8 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (pendingClient.InitializationStep == ConnectionInitialization.Success)
|
||||
{
|
||||
NetworkConnection newConnection = pendingClient.Connection;
|
||||
connectedClients.Add(newConnection);
|
||||
TConnection newConnection = pendingClient.Connection;
|
||||
connectedClients.Add(new ConnectedClient(newConnection));
|
||||
pendingClients.Remove(pendingClient);
|
||||
|
||||
callbacks.OnInitializationComplete.Invoke(newConnection, pendingClient.Name);
|
||||
@@ -310,14 +305,38 @@ namespace Barotrauma.Networking
|
||||
|
||||
pendingClients.Remove(pendingClient);
|
||||
|
||||
if (pendingClient.AuthSessionStarted && pendingClient.AccountInfo.AccountId.TryUnwrap<SteamId>(out var steamId))
|
||||
{
|
||||
Steam.SteamManager.StopAuthSession(steamId);
|
||||
pendingClient.Connection.SetAccountInfo(AccountInfo.None);
|
||||
pendingClient.AuthSessionStarted = false;
|
||||
}
|
||||
pendingClient.Connection.SetAccountInfo(AccountInfo.None);
|
||||
pendingClient.AuthSessionStarted = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract class ServerPeer
|
||||
{
|
||||
public readonly record struct Callbacks(
|
||||
Callbacks.MessageCallback OnMessageReceived,
|
||||
Callbacks.DisconnectCallback OnDisconnect,
|
||||
Callbacks.InitializationCompleteCallback OnInitializationComplete,
|
||||
Callbacks.ShutdownCallback OnShutdown,
|
||||
Callbacks.OwnerDeterminedCallback OnOwnerDetermined)
|
||||
{
|
||||
public delegate void MessageCallback(NetworkConnection connection, IReadMessage message);
|
||||
public delegate void DisconnectCallback(NetworkConnection connection, PeerDisconnectPacket peerDisconnectPacket);
|
||||
public delegate void InitializationCompleteCallback(NetworkConnection connection, string? clientName);
|
||||
public delegate void ShutdownCallback();
|
||||
public delegate void OwnerDeterminedCallback(NetworkConnection connection);
|
||||
}
|
||||
|
||||
protected readonly Callbacks callbacks;
|
||||
|
||||
protected ServerPeer(Callbacks callbacks)
|
||||
{
|
||||
this.callbacks = callbacks;
|
||||
}
|
||||
|
||||
public abstract void Start();
|
||||
public abstract void Close();
|
||||
public abstract void Update(float deltaTime);
|
||||
|
||||
public abstract void Send(IWriteMessage msg, NetworkConnection conn, DeliveryMethod deliveryMethod, bool compressPastThreshold = true);
|
||||
public abstract void Disconnect(NetworkConnection conn, PeerDisconnectPacket peerDisconnectPacket);
|
||||
|
||||
@@ -4,6 +4,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Steam;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
{
|
||||
@@ -281,9 +282,11 @@ namespace Barotrauma.Networking
|
||||
|
||||
doc.Root.SetAttributeValue("name", ServerName);
|
||||
doc.Root.SetAttributeValue("port", Port);
|
||||
#if USE_STEAM
|
||||
doc.Root.SetAttributeValue("queryport", QueryPort);
|
||||
#endif
|
||||
|
||||
if (QueryPort != 0)
|
||||
{
|
||||
doc.Root.SetAttributeValue("queryport", QueryPort);
|
||||
}
|
||||
doc.Root.SetAttributeValue("password", password ?? "");
|
||||
|
||||
doc.Root.SetAttributeValue("enableupnp", EnableUPnP);
|
||||
|
||||
Reference in New Issue
Block a user