in ClearScript/Util/Web/WebSocket.cs [44:160]
public async Task<Message> ReceiveMessageAsync()
{
using (await receiveSemaphore.CreateLockScopeAsync().ConfigureAwait(false))
{
bool? isBinary = null;
var payloads = new List<byte[]>();
while (true)
{
var frame = await ReceiveFrameAsync().ConfigureAwait(false);
if (frame.OpCode == OpCodes.Text)
{
if (isBinary.HasValue)
{
throw new Exception(ErrorCode.ProtocolError, "Received unexpected text frame from WebSocket");
}
isBinary = false;
payloads.Add(frame.Payload);
if (frame.Final)
{
break;
}
}
else if (frame.OpCode == OpCodes.Binary)
{
if (isBinary.HasValue)
{
throw new Exception(ErrorCode.ProtocolError, "Received unexpected binary frame from WebSocket");
}
isBinary = true;
payloads.Add(frame.Payload);
if (frame.Final)
{
break;
}
}
else if (frame.OpCode == OpCodes.Continuation)
{
if (!isBinary.HasValue)
{
throw new Exception(ErrorCode.ProtocolError, "Received unexpected continuation frame from WebSocket");
}
payloads.Add(frame.Payload);
if (frame.Final)
{
break;
}
}
else if (frame.OpCode == OpCodes.Ping)
{
var response = new Frame { Final = true, OpCode = OpCodes.Pong, Payload = frame.Payload };
await SendFrameAsync(response).ConfigureAwait(false);
}
else if (frame.OpCode == OpCodes.Pong)
{
}
else if (frame.OpCode == OpCodes.Close)
{
var errorCode = ErrorCode.NormalClosure;
var message = "The WebSocket was closed by the remote endpoint";
if (frame.Payload.Length >= 2)
{
errorCode = (ErrorCode)frame.Payload.ToHostUInt16();
if (frame.Payload.Length > 2)
{
message = Encoding.UTF8.GetString(frame.Payload, 2, frame.Payload.Length - 2);
}
}
throw new Exception(errorCode, message);
}
else
{
throw new Exception(ErrorCode.ProtocolError, "Received unrecognized frame from WebSocket");
}
}
var length = 0L;
var overflow = false;
try
{
length = payloads.Aggregate(0L, (tempLength, segment) => checked(tempLength + segment.LongLength));
}
catch (OverflowException)
{
overflow = true;
}
const long maxLength = 64 * 1024 * 1024;
if (overflow || (length > maxLength))
{
throw new Exception(ErrorCode.MessageTooBig, "Incoming WebSocket message payload is too large");
}
var fullPayload = new byte[length];
var index = 0L;
foreach (var payload in payloads)
{
Array.Copy(payload, 0L, fullPayload, index, payload.LongLength);
index += payload.LongLength;
}
// ReSharper disable once ConditionIsAlwaysTrueOrFalse
Debug.Assert(isBinary.HasValue);
return new Message { IsBinary = isBinary.Value, Payload = fullPayload };
}
}