using Esiur.Core;
using Esiur.Misc;
using Esiur.Resource;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks;
namespace Esiur.Net.Sockets;
internal interface IPendingSendBudget
{
bool TryReserve(int byteCount);
void Release(int byteCount);
}
///
/// Adapts a platform to Esiur's socket abstraction.
///
public sealed class FrameworkWebSocket : ISocket
{
private sealed class PendingSend
{
public byte[] Buffer;
public AsyncReply Reply;
public IPendingSendBudget Budget;
}
public const string SubProtocol = "EP";
private const int ReceiveBufferSize = 16 * 1024;
private static readonly TimeSpan CloseTimeout = TimeSpan.FromSeconds(2);
private readonly object lifecycleLock = new object();
private readonly object sendLock = new object();
private readonly SemaphoreSlim sendOperation = new SemaphoreSlim(1, 1);
private readonly Queue sendQueue = new Queue();
private readonly byte[] receiveBuffer = new byte[ReceiveBufferSize];
private readonly NetworkBuffer receiveNetworkBuffer = new NetworkBuffer();
private readonly CancellationTokenSource lifetimeCancellation;
private readonly TaskCompletionSource