Skip to content

Commit

Permalink
Add missing documentation to changed files in connection refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
Extremelyd1 committed Feb 12, 2025
1 parent deec768 commit 3363f1e
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 15 deletions.
47 changes: 40 additions & 7 deletions HKMP/Networking/Client/ClientConnectionManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,28 @@

namespace Hkmp.Networking.Client;

/// <summary>
/// Client-side manager for handling the initial connection to the server.
/// </summary>
internal class ClientConnectionManager : ConnectionManager {
/// <summary>
/// The client-side chunk sender used to handle sending chunks.
/// </summary>
private readonly ClientChunkSender _chunkSender;
/// <summary>
/// The client-side chunk received used to receive chunks.
/// </summary>
private readonly ClientChunkReceiver _chunkReceiver;

/// <summary>
/// Event that is called when server info is received from the server we are trying to connect to.
/// </summary>
public event Action<ServerInfo> ServerInfoReceivedEvent;

/// <summary>
/// Construct the connection manager with the given packet manager and chunk sender, and receiver instances.
/// Will register handlers in the packet manager that relate to the connection.
/// </summary>
public ClientConnectionManager(
PacketManager packetManager,
ClientChunkSender chunkSender,
Expand All @@ -29,40 +45,57 @@ ClientChunkReceiver chunkReceiver
_chunkReceiver.ChunkReceivedEvent += OnChunkReceived;
}

/// <summary>
/// Start establishing the connection to the server with the given information.
/// </summary>
/// <param name="username">The username of the player.</param>
/// <param name="authKey">The authentication key of the player.</param>
/// <param name="addonData">List of addon data that represents the enabled networked addons that the client uses.
/// </param>
public void StartConnection(string username, string authKey, List<AddonData> addonData) {
Logger.Debug("StartConnection");

SendUserInfo(username, authKey, addonData);
}

private void SendUserInfo(string username, string authKey, List<AddonData> addonData) {
// Create a connection packet that will be the entire chunk we will be sending
var connectionPacket = new ServerConnectionPacket();


// Set the client info data in the connection packet
connectionPacket.SetSendingPacketData(ServerConnectionPacketId.ClientInfo, new ClientInfo {
Username = username,
AuthKey = authKey,
AddonData = addonData
});

// Create the raw packet from the connection packet
var packet = new Packet.Packet();
connectionPacket.CreatePacket(packet);

// Enqueue the raw packet to be sent using the chunk sender
_chunkSender.EnqueuePacket(packet);
}

/// <summary>
/// Callback method for when server info is received from the server.
/// </summary>
/// <param name="serverInfo">The server info instance received from the server.</param>
private void OnServerInfoReceived(ServerInfo serverInfo) {
Logger.Debug($"ServerInfo received, connection accepted: {serverInfo.ConnectionResult}");

ServerInfoReceivedEvent?.Invoke(serverInfo);
}


/// <summary>
/// Callback method for when a new chunk is received from the server.
/// </summary>
/// <param name="packet">The raw packet that contains the data from the chunk.</param>
private void OnChunkReceived(Packet.Packet packet) {
// Create the connection packet instance and try to read it
var connectionPacket = new ClientConnectionPacket();
if (!connectionPacket.ReadPacket(packet)) {
Logger.Debug("Received malformed connection packet chunk from server");
return;
}


// Let the packet manager handle the connection packet, which will invoke the relevant data handlers
PacketManager.HandleClientConnectionPacket(connectionPacket);
}
}
12 changes: 12 additions & 0 deletions HKMP/Networking/Client/ClientConnectionStatus.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
namespace Hkmp.Networking.Client;

/// <summary>
/// Enumeration of connection statuses for the client.
/// </summary>
internal enum ClientConnectionStatus {
/// <summary>
/// Not connected to any server.
/// </summary>
NotConnected,
/// <summary>
/// Trying to establish a connection to a server.
/// </summary>
Connecting,
/// <summary>
/// Connected to a server.
/// </summary>
Connected
}
34 changes: 29 additions & 5 deletions HKMP/Networking/Client/ConnectionFailedResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,54 @@ namespace Hkmp.Networking.Client;
/// Class that encapsulates the result of a failed connection.
/// </summary>
internal class ConnectionFailedResult {
public ConnectionFailedReason Reason { get; set; }
/// <summary>
/// The reason that the connection failed.
/// </summary>
public ConnectionFailedReason Reason { get; init; }
}

/// <summary>
/// Specialization class of <seealso cref="ConnectionFailedResult"/> for invalid addons.
/// </summary>
internal class ConnectionInvalidAddonsResult : ConnectionFailedResult {
public List<AddonData> AddonData { get; set; }
/// <summary>
/// The list of addon data that the server uses to compare against for clients.
/// </summary>
public List<AddonData> AddonData { get; init; }
}

/// <summary>
/// Specialization class of <seealso cref="ConnectionFailedResult"/> for a generic failed connection with message.
/// </summary>
internal class ConnectionFailedMessageResult : ConnectionFailedResult {
public string Message { get; set; }
/// <summary>
/// The string message that describes the reason the connection failed.
/// </summary>
public string Message { get; init; }
}

/// <summary>
/// Enumeration of reasons why the connection failed.
/// </summary>
internal enum ConnectionFailedReason {
/// <summary>
/// The client and server addon do not match.
/// </summary>
InvalidAddons,
Other,
/// <summary>
/// The connection timed out (took too long to establish).
/// </summary>
TimedOut,
/// <summary>
/// A socket exception occurred while trying to establish the connection.
/// </summary>
SocketException,
IOException
/// <summary>
/// An IO exception occurred while trying to establish the connection.
/// </summary>
IOException,
/// <summary>
/// The reason is miscellaneous.
/// </summary>
Other,
}
2 changes: 1 addition & 1 deletion HKMP/Networking/ConnectionManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace Hkmp.Networking;

/// <summary>
/// Class that manages sending packets while establishing connection to a server.
/// Abstract base class that manages handling the initial connection to a server.
/// </summary>
internal abstract class ConnectionManager {
/// <summary>
Expand Down
20 changes: 19 additions & 1 deletion HKMP/Networking/Server/NetServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ internal class NetServer : INetServer {
/// </summary>
private readonly ConcurrentDictionary<IPAddress, Stopwatch> _throttledClients;

/// <summary>
/// Concurrent queue that contains received data from a client ready for processing.
/// </summary>
private readonly ConcurrentQueue<ReceivedData> _receivedQueue;

/// <summary>
Expand Down Expand Up @@ -272,6 +275,13 @@ private void HandleClientPackets(NetServerClient client, List<Packet.Packet> pac
}
}

/// <summary>
/// Callback method for when a connection request is received.
/// </summary>
/// <param name="clientId">The ID of the client.</param>
/// <param name="clientInfo">The client info instance containing details about the client.</param>
/// <param name="serverInfo">The server info instance that should be modified to reflect whether the client's
/// connection is accepted or not.</param>
private void OnConnectionRequest(ushort clientId, ClientInfo clientInfo, ServerInfo serverInfo) {
if (!_clientsById.TryGetValue(clientId, out var client)) {
Logger.Error($"Connection request for client without known ID: {clientId}");
Expand Down Expand Up @@ -305,7 +315,12 @@ private void OnConnectionRequest(ushort clientId, ClientInfo clientInfo, ServerI
});
}
}


/// <summary>
/// Callback method for when client info is received in a connection packet.
/// </summary>
/// <param name="clientId">The ID of the client that sent the client info.</param>
/// <param name="clientInfo">The client info instance.</param>
private void OnClientInfoReceived(ushort clientId, ClientInfo clientInfo) {
if (!_clientsById.TryGetValue(clientId, out var client)) {
Logger.Error($"ClientInfo received from client without known ID: {clientId}");
Expand Down Expand Up @@ -468,6 +483,9 @@ Func<TPacketId, IPacketData> packetInstantiator
/// Data class for storing received data from a given IP end-point.
/// </summary>
internal class ReceivedData {
/// <summary>
/// The DTLS server client that sent this data.
/// </summary>
public DtlsServerClient DtlsServerClient { get; init; }

/// <summary>
Expand Down
41 changes: 41 additions & 0 deletions HKMP/Networking/Server/ServerConnectionManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,36 @@

namespace Hkmp.Networking.Server;

/// <summary>
/// Server-side manager for handling the initial connection to a new client.
/// </summary>
internal class ServerConnectionManager : ConnectionManager {
/// <summary>
/// Server-side chunk sender used to handle sending chunks.
/// </summary>
private readonly ServerChunkSender _chunkSender;
/// <summary>
/// Server-side chunk received used to receive chunks.
/// </summary>
private readonly ServerChunkReceiver _chunkReceiver;

/// <summary>
/// The ID of the client that this class manages.
/// </summary>
private readonly ushort _clientId;

/// <summary>
/// Timer that triggers when the connection takes too long and thus times out.
/// </summary>
private readonly Timer _timeoutTimer;

/// <summary>
/// Event that is called when the client has sent the client info, and thus we can check the connection request.
/// </summary>
public event Action<ushort, ClientInfo, ServerInfo> ConnectionRequestEvent;
/// <summary>
/// Event that is called when the connection times out.
/// </summary>
public event Action ConnectionTimeoutEvent;

public ServerConnectionManager(
Expand All @@ -39,22 +60,37 @@ ushort clientId
_chunkReceiver.ChunkReceivedEvent += OnChunkReceived;
}

/// <summary>
/// Start accepting connections, which will start the timeout timer.
/// </summary>
public void StartAcceptingConnection() {
Logger.Debug("StartAcceptingConnection");

_timeoutTimer.Start();
}

/// <summary>
/// Stop accepting connections, which will stop the timeout timer.
/// </summary>
public void StopAcceptingConnection() {
Logger.Debug("StopAcceptingConnection");

_timeoutTimer.Stop();
}

/// <summary>
/// Finish up the connection and execute the given callback when it is finished.
/// </summary>
/// <param name="callback">The action to execute when the connection is finished.</param>
public void FinishConnection(Action callback) {
_chunkSender.FinishSendingData(callback);
}

/// <summary>
/// Process the given (received) client info. This will invoke the <see cref="ConnectionRequestEvent"/> and
/// communicate the resulting server info back to the client.
/// </summary>
/// <param name="clientInfo"></param>
public void ProcessClientInfo(ClientInfo clientInfo) {
Logger.Debug($"Received client info from client with ID: {_clientId}");

Expand All @@ -75,6 +111,11 @@ public void ProcessClientInfo(ClientInfo clientInfo) {
_chunkSender.EnqueuePacket(packet);
}

/// <summary>
/// Callback method for when a chunk is received. Will construct a connection packet and try to read the chunk
/// into it. If successful, will let the packet manager handle the data in it.
/// </summary>
/// <param name="packet">The raw packet that contains the data from the chunk.</param>
private void OnChunkReceived(Packet.Packet packet) {
var connectionPacket = new ServerConnectionPacket();
if (!connectionPacket.ReadPacket(packet)) {
Expand Down
3 changes: 2 additions & 1 deletion HKMP/Networking/UdpUpdateManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,8 @@ protected UdpUpdateManager() {
}

/// <summary>
/// Start the update manager and allow sending updates.
/// Start the update manager. This will start the send and heartbeat timers, which will respectively trigger
/// sending update packets and trigger on connection timing out.
/// </summary>
public void StartUpdates() {
_lastSendRate = CurrentSendRate;
Expand Down

0 comments on commit 3363f1e

Please sign in to comment.