scratch-link/scratch-link-common/SessionManager.cs

62 lines
2.2 KiB
C#
Raw Normal View History

2022-04-12 14:22:05 -07:00
// <copyright file="SessionManager.cs" company="Scratch Foundation">
// Copyright (c) Scratch Foundation. All rights reserved.
// </copyright>
namespace ScratchLink;
2022-07-07 17:40:49 -07:00
using System;
2022-05-03 09:10:24 -07:00
using System.Collections.Concurrent;
2022-04-12 14:22:05 -07:00
using System.Net.WebSockets;
2022-07-07 17:40:49 -07:00
using System.Threading.Tasks;
2022-04-12 14:22:05 -07:00
/// <summary>
/// This class connects a WebSocket to the appropriate session type and tracks the collection of active sessions.
/// </summary>
internal abstract class SessionManager
{
2022-05-03 09:10:24 -07:00
/// <summary>
/// Stores the set of active sessions. Implemented as a dictionary because ConcurrentHashSet doesn't exist.
/// </summary>
private readonly ConcurrentDictionary<Session, bool> sessions = new ();
2022-04-19 15:47:17 -07:00
2022-04-12 14:22:05 -07:00
/// <summary>
/// Activated when the number of active sessions changes.
/// </summary>
public event EventHandler ActiveSessionCountChanged;
/// <summary>
/// Gets the count of active connected WebSocket sessions.
/// </summary>
2022-05-03 09:10:24 -07:00
public int ActiveSessionCount { get => this.sessions.Count; }
2022-04-12 14:22:05 -07:00
/// <summary>
/// Call this with a new connection context to ask the SessionManager to build and manage a session for it.
/// </summary>
/// <param name="webSocketContext">The WebSocket context which the SessionManager should adopt and connect to a session.</param>
public void ClientDidConnect(WebSocketContext webSocketContext)
{
2022-05-03 09:10:24 -07:00
Task.Run(async () =>
{
using var session = this.MakeNewSession(webSocketContext);
this.sessions.TryAdd(session, true);
this.ActiveSessionCountChanged?.Invoke(this, EventArgs.Empty);
try
{
await session.Run();
}
finally
{
this.sessions.TryRemove(session, out _);
this.ActiveSessionCountChanged?.Invoke(this, EventArgs.Empty);
}
});
2022-04-12 14:22:05 -07:00
}
/// <summary>
/// Create a new Session object to handle a new WebSocket connection.
/// </summary>
/// <param name="webSocketContext">Create a Session to handle this connection.</param>
/// <returns>A new Session object connected to the provided context.</returns>
protected abstract Session MakeNewSession(WebSocketContext webSocketContext);
}