m.Http.Backend.Tcp.WebSocketSession.TryDecodeNextMessage C# (CSharp) Method

TryDecodeNextMessage() private method

private TryDecodeNextMessage ( OpCode &opCode, byte &messagePayload ) : bool
opCode OpCode
messagePayload byte
return bool
        bool TryDecodeNextMessage(out OpCode opCode, out byte[] messagePayload)
        {
            while (true)
            {
                switch (decodeState)
                {
                    case DecodeState.DecodeHeader:
                        if (FrameDecoder.TryDecodeHeader(readBuffer, ref dataStart, readBufferOffset, out isFin, out frameOpCode, out isMasked, out framePayloadLength, mask))
                        {
                            decodeState = DecodeState.DecodePayload;

                            switch (frameOpCode)
                            {
                                case OpCode.Continuation:
                                    if (framePayloadLength > 0)
                                    {
                                        BufferUtils.Expand(ref messageBuffer, framePayloadLength); //TODO: limit, sanity guard
                                    }
                                    break;

                                case OpCode.Text:
                                case OpCode.Binary:
                                    messageOpCode = frameOpCode;
                                    messageBuffer = new byte[framePayloadLength];
                                    messageBufferOffset = 0;
                                    break;

                                case OpCode.Close:
                                case OpCode.Ping:
                                case OpCode.Pong:
                                    if (!isFin)
                                    {
                                        throw new WebSocketException("Control frame cannot be fragmented");
                                    }
                                    break;
                            }
                            
                            continue;
                        }
                        break;
    
                    case DecodeState.DecodePayload:
                        var decodeStart = dataStart;
                        if (FrameDecoder.TryDecodePayload(readBuffer, ref dataStart, readBufferOffset, framePayloadLength, isMasked, mask))
                        {
                            decodeState = DecodeState.DecodeHeader;

                            switch (frameOpCode)
                            {
                                case OpCode.Continuation:
                                case OpCode.Text:
                                case OpCode.Binary:
                                    Array.Copy(readBuffer, decodeStart, messageBuffer, messageBufferOffset, framePayloadLength);
                                    CompactReadBuffer(ref dataStart);
                                    if (isFin)
                                    {
                                        opCode = messageOpCode;
                                        messagePayload = messageBuffer;
                                        messageBuffer = null;
                                        messageBufferOffset = 0;
                                        return true;
                                    }
                                    else
                                    {
                                        messageBufferOffset += framePayloadLength;
                                        continue;
                                    }

                                case OpCode.Close:
                                case OpCode.Ping:
                                case OpCode.Pong:
                                    opCode = frameOpCode;
                                    messagePayload = new byte[framePayloadLength];
                                    Array.Copy(readBuffer, decodeStart, messagePayload, 0, framePayloadLength);
                                    CompactReadBuffer(ref dataStart);
                                    return true; // must be Fin
                            }
                        }
                        break;
                }

                opCode = OpCode.Continuation;
                messagePayload = null;
                return false;
            }
        }