|
|
@@ -0,0 +1,103 @@ |
|
|
|
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; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |