internal async Task <int> ReadToBufferAsync() { var bufferRemaining = readBuffer.Length - readBufferOffset; if (bufferRemaining == 0) { BufferUtils.Expand(ref readBuffer, readBuffer.Length); // double buffer bufferRemaining = readBuffer.Length - readBufferOffset; } try { var bytesRead = await Stream.ReadAsync(readBuffer, readBufferOffset, bufferRemaining).ConfigureAwait(false); readBufferOffset += bytesRead; return(bytesRead); } catch (Exception e) { throw new SessionStreamException("Exception while reading from stream", e); } }
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); } }