This commit is contained in:
2026-07-14 17:26:51 +03:00
parent 13898323dd
commit be2a24bfd9
30 changed files with 2285 additions and 105 deletions
+2 -1
View File
@@ -158,7 +158,8 @@ public class EpAuthPacket : Packet
if (Command == EpAuthPacketCommand.Initialize)
{
AuthMode = (AuthenticationMode)(data[offset] >> 2 & 0x3);
EncryptionMode = (EncryptionMode)(data[offset++] & 0x7);
// Authentication occupies bits 2-3; encryption is confined to bits 0-1.
EncryptionMode = (EncryptionMode)(data[offset++] & 0x3);
}
else if (Command == EpAuthPacketCommand.Acknowledge)
{
@@ -22,6 +22,7 @@ namespace Esiur.Net.Packets
Identity,
AuthenticationProtocol,
AuthenticationData,
ErrorMessage
ErrorMessage,
CipherNonce
}
}
@@ -28,6 +28,8 @@ namespace Esiur.Net.Sockets
ArraySegment<byte> websocketReceiveBufferSegment;
object sendLock = new object();
readonly SemaphoreSlim sendSemaphore = new SemaphoreSlim(1, 1);
int sendFailureNotified;
bool held;
public event DestroyedEvent OnDestroy;
@@ -70,7 +72,7 @@ namespace Esiur.Net.Sockets
public void Send(byte[] message)
{
byte[] queued = null;
lock (sendLock)
{
if (held)
@@ -79,16 +81,18 @@ namespace Esiur.Net.Sockets
}
else
{
totalSent += message.Length;
sock.SendAsync(new ArraySegment<byte>(message), WebSocketMessageType.Binary,
true, new System.Threading.CancellationToken());
queued = (byte[])message.Clone();
}
}
if (queued != null)
ObserveSend(QueueSend(queued));
}
public void Send(byte[] message, int offset, int size)
{
byte[] queued = null;
lock (sendLock)
{
if (held)
@@ -97,12 +101,13 @@ namespace Esiur.Net.Sockets
}
else
{
totalSent += size;
sock.SendAsync(new ArraySegment<byte>(message, offset, size),
WebSocketMessageType.Binary, true, new System.Threading.CancellationToken());
queued = new byte[size];
Buffer.BlockCopy(message, offset, queued, 0, size);
}
}
if (queued != null)
ObserveSend(QueueSend(queued));
}
@@ -184,41 +189,85 @@ namespace Esiur.Net.Sockets
public void Unhold()
{
byte[] message;
lock (sendLock)
{
held = false;
var message = sendNetworkBuffer.Read();
if (message == null)
return;
totalSent += message.Length;
sock.SendAsync(new ArraySegment<byte>(message), WebSocketMessageType.Binary,
true, new System.Threading.CancellationToken());
message = sendNetworkBuffer.Read();
}
if (message != null)
ObserveSend(QueueSend(message));
}
public async AsyncReply<bool> SendAsync(byte[] message, int offset, int length)
{
if (held)
byte[] queued = null;
lock (sendLock)
{
sendNetworkBuffer.Write(message, (uint)offset, (uint)length);
}
else
{
totalSent += length;
await sock.SendAsync(new ArraySegment<byte>(message, offset, length),
WebSocketMessageType.Binary, true, new System.Threading.CancellationToken());
if (held)
{
sendNetworkBuffer.Write(message, (uint)offset, (uint)length);
}
else
{
queued = new byte[length];
Buffer.BlockCopy(message, offset, queued, 0, length);
}
}
if (queued != null)
await QueueSend(queued);
return true;
}
async Task QueueSend(byte[] message)
{
await sendSemaphore.WaitAsync();
try
{
var socket = sock ?? throw new InvalidOperationException("WebSocket is closed.");
await socket.SendAsync(
new ArraySegment<byte>(message),
WebSocketMessageType.Binary,
true,
CancellationToken.None);
Interlocked.Add(ref totalSent, message.Length);
}
catch
{
NotifySendFailure();
throw;
}
finally
{
sendSemaphore.Release();
}
}
void ObserveSend(Task task)
{
_ = task.ContinueWith(
completed =>
{
// Observe the exception; QueueSend already closed/notified the receiver.
_ = completed.Exception;
},
CancellationToken.None,
TaskContinuationOptions.OnlyOnFaulted,
TaskScheduler.Default);
}
void NotifySendFailure()
{
if (Interlocked.Exchange(ref sendFailureNotified, 1) == 0)
{
try { sock?.Abort(); } catch { }
Receiver?.NetworkClose(this);
}
}
public ISocket Accept()
{
throw new NotImplementedException();