Discord.Net/experiment/Discord.Net.Relay/RelayServer.cs
2024-06-13 17:47:39 +12:00

103 lines
3.3 KiB
C#

using Discord.API;
using Discord.Logging;
using Discord.Net.Rest;
using Discord.Net.WebSockets;
using Discord.Rest;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using WebSocketClient = System.Net.WebSockets.WebSocket;
namespace Discord.Relay
{
public class RelayServer
{
public event Func<LogMessage, Task> Log { add { _logEvent.Add(value); } remove { _logEvent.Remove(value); } }
internal readonly AsyncEvent<Func<LogMessage, Task>> _logEvent = new AsyncEvent<Func<LogMessage, Task>>();
private readonly HashSet<RelayConnection> _connections;
private readonly SemaphoreSlim _lock;
private readonly JsonSerializer _serializer;
private readonly DiscordSocketApiClient _discord;
private int _nextId;
internal LogManager LogManager { get; }
internal RelayServer(Action<RelayServer> configAction)
{
_connections = new HashSet<RelayConnection>();
_lock = new SemaphoreSlim(1, 1);
_serializer = new JsonSerializer();
_discord = new DiscordSocketApiClient(
DefaultRestClientProvider.Instance,
DefaultWebSocketProvider.Instance,
DiscordRestConfig.UserAgent);
configAction?.Invoke(this);
LogManager = new LogManager(LogSeverity.Debug);
LogManager.Message += async msg => await _logEvent.InvokeAsync(msg).ConfigureAwait(false);
}
internal async Task AcceptAsync(HttpContext context)
{
WebSocketClient socket;
try
{
socket = await context.WebSockets.AcceptWebSocketAsync().ConfigureAwait(false);
}
catch { return; }
var _ = Task.Run(async () =>
{
var conn = new RelayConnection(this, socket, Interlocked.Increment(ref _nextId));
await AddConnection(conn).ConfigureAwait(false);
try
{
await conn.RunAsync().ConfigureAwait(false);
}
finally { await RemoveConnection(conn).ConfigureAwait(false); }
});
}
internal void StartAsync()
{
Task.Run(async () =>
{
await _discord.ConnectAsync().ConfigureAwait(false);
});
}
internal async Task AddConnection(RelayConnection conn)
{
await _lock.WaitAsync().ConfigureAwait(false);
try
{
_connections.Add(conn);
}
finally { _lock.Release(); }
}
internal async Task RemoveConnection(RelayConnection conn)
{
await _lock.WaitAsync().ConfigureAwait(false);
try
{
_connections.Remove(conn);
}
finally { _lock.Release(); }
}
internal int Serialize(object obj, byte[] buffer)
{
using (var stream = new MemoryStream(buffer))
using (var writer = new StreamWriter(stream))
{
_serializer.Serialize(writer, obj);
return (int)stream.Position;
}
}
}
}