Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/ChatServer/ChatClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ public byte Index
/// <inheritdoc/>
public DateTime LastActivity { get; private set; }

/// <summary>
/// Gets the connection of this client, so that its traffic can be captured.
/// </summary>
internal IConnection? Connection => this._connection;

/// <inheritdoc/>
public async ValueTask SendMessageAsync(byte senderId, string message)
{
Expand Down
81 changes: 81 additions & 0 deletions src/ChatServer/ChatClientConnectionInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// <copyright file="ChatClientConnectionInfo.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>

namespace MUnique.OpenMU.ChatServer;

using MUnique.OpenMU.Interfaces;
using MUnique.OpenMU.Network;
using MUnique.OpenMU.Network.Analyzer;
using MUnique.OpenMU.Network.PlugIns;

/// <summary>
/// The <see cref="ICapturedConnectionInfo"/> of a client of the chat server.
/// </summary>
internal sealed class ChatClientConnectionInfo : ICapturedConnectionInfo
{
private readonly ChatClient _client;

private readonly IConnection _connection;

/// <summary>
/// Initializes a new instance of the <see cref="ChatClientConnectionInfo"/> class.
/// </summary>
/// <param name="client">The client.</param>
/// <param name="connection">The connection of the client.</param>
/// <param name="serverId">The identifier of the chat server.</param>
public ChatClientConnectionInfo(ChatClient client, IConnection connection, int serverId)
{
this._client = client;
this._connection = connection;
this.ServerId = serverId;
}

/// <inheritdoc />
public Guid Id => this._connection.Id;

/// <inheritdoc />
public ServerType ServerType => ServerType.ChatServer;

/// <inheritdoc />
public int ServerId { get; }

/// <summary>
/// Gets the name of the account. The chat server doesn't know the account of its clients,
/// so it's always <see langword="null"/>.
/// </summary>
public string? AccountName => null;

/// <summary>
/// Gets the name of the character. The chat clients authenticate with the name of the
/// character which joined the chat room.
/// </summary>
public string? CharacterName => this._client.Nickname;

/// <inheritdoc />
public string? RemoteEndPoint => this._connection.EndPoint?.ToString();

/// <summary>
/// Gets the client version. The chat protocol doesn't depend on it, so the default
/// version is used.
/// </summary>
public ClientVersion ClientVersion => default;

/// <inheritdoc />
public PacketDefinitionSet DefinitionSet => PacketDefinitionSet.ChatServer;

/// <inheritdoc />
public bool IsConnected => this._connection.Connected;

/// <inheritdoc />
public string DisplayName => this.CharacterName ?? this.RemoteEndPoint ?? this.Id.ToString();

/// <inheritdoc />
public void AddCaptureSink(IPacketCaptureSink sink) => this._connection.AddCaptureSink(sink);

/// <inheritdoc />
public void RemoveCaptureSink(IPacketCaptureSink sink) => this._connection.RemoveCaptureSink(sink);

/// <inheritdoc />
public ValueTask DisconnectAsync() => this._client.LogOffAsync();
}
17 changes: 16 additions & 1 deletion src/ChatServer/ChatServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@ namespace MUnique.OpenMU.ChatServer;
using Microsoft.Extensions.Logging;
using MUnique.OpenMU.Interfaces;
using MUnique.OpenMU.Network;
using MUnique.OpenMU.Network.Analyzer;
using MUnique.OpenMU.PlugIns;
using Timer = System.Timers.Timer;

/// <summary>
/// Chat Server Listener that accepts incoming connections.
/// </summary>
public sealed class ChatServer : IChatServer, IDisposable
public sealed class ChatServer : IChatServer, IDisposable, IConnectionSource
{
private readonly ChatRoomManager _manager;
private readonly ILogger<ChatServer> _logger;
Expand Down Expand Up @@ -95,6 +96,20 @@ private set

private ChatServerSettings Settings => this._settings ?? throw new InvalidOperationException("The server was not initialized before");

/// <inheritdoc />
public ValueTask<IReadOnlyList<ICapturedConnectionInfo>> GetConnectionsAsync()
{
IReadOnlyList<ICapturedConnectionInfo> result = this._connectedClients
.OfType<ChatClient>()
.Select(client => client.Connection is { } connection
? new ChatClientConnectionInfo(client, connection, this.Id)
: null)
.Where(info => info is not null)
.Select(info => (ICapturedConnectionInfo)info!)
.ToList();
return ValueTask.FromResult(result);
}

/// <inheritdoc/>
public async ValueTask<ChatServerAuthenticationInfo?> RegisterClientAsync(ushort roomId, string clientName)
{
Expand Down
1 change: 1 addition & 0 deletions src/ChatServer/MUnique.OpenMU.ChatServer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
<ItemGroup>
<ProjectReference Include="..\Interfaces\MUnique.OpenMU.Interfaces.csproj" />
<ProjectReference Include="..\Network\MUnique.OpenMU.Network.csproj" />
<ProjectReference Include="..\Network\Analyzer\MUnique.OpenMU.Network.Analyzer.csproj" />
<ProjectReference Include="..\Network\Packets\MUnique.OpenMU.Network.Packets.csproj" />
</ItemGroup>

Expand Down
76 changes: 76 additions & 0 deletions src/ConnectServer/ClientConnectionInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// <copyright file="ClientConnectionInfo.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>

namespace MUnique.OpenMU.ConnectServer;

using MUnique.OpenMU.Interfaces;
using MUnique.OpenMU.Network;
using MUnique.OpenMU.Network.Analyzer;
using MUnique.OpenMU.Network.PlugIns;

/// <summary>
/// The <see cref="ICapturedConnectionInfo"/> of a client of the connect server.
/// </summary>
internal sealed class ClientConnectionInfo : ICapturedConnectionInfo
{
private readonly Client _client;

/// <summary>
/// Initializes a new instance of the <see cref="ClientConnectionInfo"/> class.
/// </summary>
/// <param name="client">The client.</param>
/// <param name="serverId">The identifier of the connect server.</param>
/// <param name="clientVersion">The client version of the connect server.</param>
public ClientConnectionInfo(Client client, int serverId, ClientVersion clientVersion)
{
this._client = client;
this.ServerId = serverId;
this.ClientVersion = clientVersion;
}

/// <inheritdoc />
public Guid Id => this._client.Connection.Id;

/// <inheritdoc />
public ServerType ServerType => ServerType.ConnectServer;

/// <inheritdoc />
public int ServerId { get; }

/// <summary>
/// Gets the name of the account. The clients of a connect server are never logged in, so
/// it's always <see langword="null"/>.
/// </summary>
public string? AccountName => null;

/// <summary>
/// Gets the name of the character. The clients of a connect server never selected one, so
/// it's always <see langword="null"/>.
/// </summary>
public string? CharacterName => null;

/// <inheritdoc />
public string? RemoteEndPoint => this._client.Connection.EndPoint?.ToString();

/// <inheritdoc />
public ClientVersion ClientVersion { get; }

/// <inheritdoc />
public PacketDefinitionSet DefinitionSet => PacketDefinitionSet.ConnectServer;

/// <inheritdoc />
public bool IsConnected => this._client.Connection.Connected;

/// <inheritdoc />
public string DisplayName => this.RemoteEndPoint ?? this.Id.ToString();

/// <inheritdoc />
public void AddCaptureSink(IPacketCaptureSink sink) => this._client.Connection.AddCaptureSink(sink);

/// <inheritdoc />
public void RemoveCaptureSink(IPacketCaptureSink sink) => this._client.Connection.RemoveCaptureSink(sink);

/// <inheritdoc />
public ValueTask DisconnectAsync() => this._client.Connection.DisconnectAsync();
}
12 changes: 11 additions & 1 deletion src/ConnectServer/ConnectServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ namespace MUnique.OpenMU.ConnectServer;
using System.Threading;
using Microsoft.Extensions.Logging;
using MUnique.OpenMU.Interfaces;
using MUnique.OpenMU.Network.Analyzer;
using MUnique.OpenMU.Network.PlugIns;

/// <summary>
/// The connect server.
/// </summary>
public class ConnectServer : IConnectServer, OpenMU.Interfaces.IConnectServer
public class ConnectServer : IConnectServer, OpenMU.Interfaces.IConnectServer, IConnectionSource
{
private readonly ILoggerFactory _loggerFactory;
private readonly ILogger _logger;
Expand Down Expand Up @@ -114,6 +115,15 @@ private set
/// </summary>
internal ClientListener ClientListener { get; }

/// <inheritdoc />
public ValueTask<IReadOnlyList<ICapturedConnectionInfo>> GetConnectionsAsync()
{
IReadOnlyList<ICapturedConnectionInfo> result = this.ClientListener.Clients
.Select(client => new ClientConnectionInfo(client, this.Id, this.ClientVersion))
.ToList();
return ValueTask.FromResult(result);
}

/// <inheritdoc />
public async Task StartAsync(CancellationToken cancellationToken)
{
Expand Down
1 change: 1 addition & 0 deletions src/ConnectServer/MUnique.OpenMU.ConnectServer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
<ItemGroup>
<ProjectReference Include="..\Interfaces\MUnique.OpenMU.Interfaces.csproj" />
<ProjectReference Include="..\Network\MUnique.OpenMU.Network.csproj" />
<ProjectReference Include="..\Network\Analyzer\MUnique.OpenMU.Network.Analyzer.csproj" />
<ProjectReference Include="..\Network\Packets\MUnique.OpenMU.Network.Packets.csproj" />
</ItemGroup>

Expand Down
18 changes: 17 additions & 1 deletion src/GameServer/GameServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,17 @@ namespace MUnique.OpenMU.GameServer;
using MUnique.OpenMU.GameLogic.Views.Guild;
using MUnique.OpenMU.GameLogic.Views.Login;
using MUnique.OpenMU.GameLogic.Views.Messenger;
using MUnique.OpenMU.GameServer.RemoteView;
using MUnique.OpenMU.Interfaces;
using MUnique.OpenMU.Network.Analyzer;
using MUnique.OpenMU.Persistence;
using MUnique.OpenMU.PlugIns;
using Nito.AsyncEx;

/// <summary>
/// The game server to which game clients can connect.
/// </summary>
public sealed class GameServer : IGameServer, IDisposable, IGameServerContextProvider
public sealed class GameServer : IGameServer, IDisposable, IGameServerContextProvider, IConnectionSource
{
private readonly ILogger<GameServer> _logger;

Expand Down Expand Up @@ -421,6 +423,20 @@ public async ValueTask GuildHostilityChangedAsync(uint guildIdA, IReadOnlyList<u
this._gameContext.UpdateGuildHostility(guildIdA, allianceGuildIdsA, guildIdB, allianceGuildIdsB, created);
}

/// <inheritdoc />
public async ValueTask<IReadOnlyList<ICapturedConnectionInfo>> GetConnectionsAsync()
{
var players = await this._gameContext.GetPlayersAsync().ConfigureAwait(false);
return players
.OfType<RemotePlayer>()
.Select(player => player.Connection is { } connection
? new RemotePlayerConnectionInfo(player, connection, this.Id)
: null)
.Where(info => info is not null)
.Select(info => (ICapturedConnectionInfo)info!)
.ToList();
}

/// <summary>
/// Creates an instance of <see cref="ServerInfo"/> with the data of this instance.
/// </summary>
Expand Down
1 change: 1 addition & 0 deletions src/GameServer/MUnique.OpenMU.GameServer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
<ProjectReference Include="..\GameLogic\MUnique.OpenMU.GameLogic.csproj" />
<ProjectReference Include="..\Interfaces\MUnique.OpenMU.Interfaces.csproj" />
<ProjectReference Include="..\Network\MUnique.OpenMU.Network.csproj" />
<ProjectReference Include="..\Network\Analyzer\MUnique.OpenMU.Network.Analyzer.csproj" />
<ProjectReference Include="..\Network\Packets\MUnique.OpenMU.Network.Packets.csproj" />
<ProjectReference Include="..\Pathfinding\MUnique.OpenMU.Pathfinding.csproj" />
<ProjectReference Include="..\Persistence\MUnique.OpenMU.Persistence.csproj" />
Expand Down
73 changes: 73 additions & 0 deletions src/GameServer/RemotePlayerConnectionInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// <copyright file="RemotePlayerConnectionInfo.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>

namespace MUnique.OpenMU.GameServer;

using MUnique.OpenMU.GameServer.RemoteView;
using MUnique.OpenMU.Interfaces;
using MUnique.OpenMU.Network;
using MUnique.OpenMU.Network.Analyzer;
using MUnique.OpenMU.Network.PlugIns;

/// <summary>
/// The <see cref="ICapturedConnectionInfo"/> of a <see cref="RemotePlayer"/>.
/// </summary>
internal sealed class RemotePlayerConnectionInfo : ICapturedConnectionInfo
{
private readonly RemotePlayer _player;

private readonly IConnection _connection;

/// <summary>
/// Initializes a new instance of the <see cref="RemotePlayerConnectionInfo"/> class.
/// </summary>
/// <param name="player">The player.</param>
/// <param name="connection">The connection of the player.</param>
/// <param name="serverId">The identifier of the game server.</param>
public RemotePlayerConnectionInfo(RemotePlayer player, IConnection connection, int serverId)
{
this._player = player;
this._connection = connection;
this.ServerId = serverId;
}

/// <inheritdoc />
public Guid Id => this._connection.Id;

/// <inheritdoc />
public ServerType ServerType => ServerType.GameServer;

/// <inheritdoc />
public int ServerId { get; }

/// <inheritdoc />
public string? AccountName => this._player.Account?.LoginName;

/// <inheritdoc />
public string? CharacterName => this._player.SelectedCharacter?.Name;

/// <inheritdoc />
public string? RemoteEndPoint => this._connection.EndPoint?.ToString();

/// <inheritdoc />
public ClientVersion ClientVersion => this._player.ClientVersion;

/// <inheritdoc />
public PacketDefinitionSet DefinitionSet => PacketDefinitionSet.GameServer;

/// <inheritdoc />
public bool IsConnected => this._connection.Connected;

/// <inheritdoc />
public string DisplayName => this.CharacterName ?? this.AccountName ?? this.RemoteEndPoint ?? this.Id.ToString();

/// <inheritdoc />
public void AddCaptureSink(IPacketCaptureSink sink) => this._connection.AddCaptureSink(sink);

/// <inheritdoc />
public void RemoveCaptureSink(IPacketCaptureSink sink) => this._connection.RemoveCaptureSink(sink);

/// <inheritdoc />
public ValueTask DisconnectAsync() => this._player.DisconnectAsync();
}
Loading
Loading