/// <summary> /// Checks to see if the <see cref="ReadOnlyBuffer"/> is Equal to the specified <see cref="Span{Byte}"/>. /// </summary> /// <param name="value">The <see cref="Span{Byte}"/> to compare to</param> /// <returns>True if the bytes are equal, false if not</returns> public static bool EqualsTo(this ReadOnlyBuffer <byte> buffer, Span <byte> value) { if (value.Length != buffer.Length) { return(false); } if (buffer.IsSingleSegment) { return(buffer.First.Span.SequenceEqual(value)); } foreach (var memory in buffer) { var compare = value.Slice(0, memory.Length); if (!memory.Span.SequenceEqual(compare)) { return(false); } value = value.Slice(memory.Length); } return(true); }
public void TechEmpowerRobRb() { var parser = new HttpParser(); var request = new Request(); ReadOnlyBuffer <byte> buffer = new ReadOnlyBuffer <byte>(_plaintextTechEmpowerRequestBytes); Assert.True(parser.ParseRequestLine(request, buffer, out var consumed, out var read)); Assert.True(parser.ParseHeaders(request, buffer.Slice(consumed), out consumed, out var examined, out var consumedBytes)); Assert.Equal(139, consumedBytes); // request line Assert.Equal(Http.Method.Get, request.Method); Assert.Equal(Http.Version.Http11, request.Version); Assert.Equal("/plaintext", request.Path); // headers Assert.Equal(3, request.Headers.Count); Assert.True(request.Headers.ContainsKey("Host")); Assert.True(request.Headers.ContainsKey("Accept")); Assert.True(request.Headers.ContainsKey("Connection")); Assert.Equal("localhost", request.Headers["Host"]); Assert.Equal("text/plain,text/html;q=0.9,application/xhtml+xml;q=0.9,application/xml;q=0.8,*/*;q=0.7", request.Headers["Accept"]); Assert.Equal("keep-alive", request.Headers["Connection"]); }
static bool FullRequest() { ReadOnlyBuffer <byte> buffer = new ReadOnlyBuffer <byte>(s_plaintextTechEmpowerRequestBytes); var parser = new HttpParser(); var request = new Request(); int consumedBytes = 0; SequencePosition examined; SequencePosition consumed = buffer.Start; bool success = true; foreach (var iteration in Benchmark.Iterations) { using (iteration.StartMeasurement()) { for (int i = 0; i < Benchmark.InnerIterationCount; i++) { success = success && parser.ParseRequestLine(request, buffer, out consumed, out examined); success = success && parser.ParseHeaders(request, buffer.Slice(consumed), out consumed, out examined, out consumedBytes); success = success && parser.ParseRequestLine(request, buffer, out consumed, out examined); success = success && parser.ParseHeaders(request, buffer.Slice(consumed), out consumed, out examined, out consumedBytes); success = success && parser.ParseRequestLine(request, buffer, out consumed, out examined); success = success && parser.ParseHeaders(request, buffer.Slice(consumed), out consumed, out examined, out consumedBytes); success = success && parser.ParseRequestLine(request, buffer, out consumed, out examined); success = success && parser.ParseHeaders(request, buffer.Slice(consumed), out consumed, out examined, out consumedBytes); success = success && parser.ParseRequestLine(request, buffer, out consumed, out examined); success = success && parser.ParseHeaders(request, buffer.Slice(consumed), out consumed, out examined, out consumedBytes); } } } return(success); }
public unsafe bool ParseRequestLine(TRequestHandler handler, ReadOnlyBuffer <byte> buffer, out SequencePosition consumed, out SequencePosition examined) { consumed = buffer.Start; examined = buffer.End; // Prepare the first span var span = buffer.First.Span; var lineIndex = span.IndexOf(ByteLF); if (lineIndex >= 0) { consumed = buffer.GetPosition(consumed, lineIndex + 1); span = span.Slice(0, lineIndex + 1); } else if (buffer.IsSingleSegment) { // No request line end return(false); } else if (TryGetNewLine(ref buffer, out var found)) { span = buffer.Slice(consumed, found).ToSpan(); consumed = found; }
static void BufferBasics(ReadOnlyBuffer <byte> buffer) { var span = buffer.Span; Assert.Equal(buffer.Length, span.Length); Assert.True(buffer.IsEmpty || buffer.Length != 0); Assert.True(!buffer.IsEmpty || buffer.Length == 0); var array = buffer.ToArray(); for (int i = 0; i < array.Length; i++) { Assert.Equal(array[i], span[i]); } if (buffer.Length > 0) { var slice = buffer.Slice(1); for (int i = 0; i < slice.Length; i++) { Assert.Equal(slice.Span[i], span[i + 1]); } } }
public static bool TryParseMessage(ReadOnlyBuffer <byte> input, out NegotiationMessage negotiationMessage) { if (!TextMessageParser.TryParseMessage(ref input, out var payload)) { throw new FormatException("Unable to parse payload as a negotiation message."); } using (var memoryStream = new MemoryStream(payload.ToArray())) { using (var reader = new JsonTextReader(new StreamReader(memoryStream))) { var token = JToken.ReadFrom(reader); if (token == null || token.Type != JTokenType.Object) { throw new FormatException($"Unexpected JSON Token Type '{token?.Type}'. Expected a JSON Object."); } var negotiationJObject = (JObject)token; var protocol = JsonUtils.GetRequiredProperty <string>(negotiationJObject, ProtocolPropertyName); negotiationMessage = new NegotiationMessage(protocol); } } return(true); }
static void BytesReaderBenchmarkBaseline() { int sections = 10; StringBuilder sb = new StringBuilder(); for (int i = 0; i < sections; i++) { sb.Append("1234 "); } var data = Encoding.UTF8.GetBytes(sb.ToString()); var readOnlyBytes = new ReadOnlyBuffer <byte>(data); var bytesRange = new ReadOnlyBuffer <byte>(data); var robReader = BufferReader.Create(readOnlyBytes); long robSum = 0; while (BufferReaderExtensions.TryParse(ref robReader, out int value)) { robSum += value; robReader.Advance(1); } var brReader = BufferReader.Create(bytesRange); long brSum = 0; while (BufferReaderExtensions.TryParse(ref brReader, out int value)) { brSum += value; brReader.Advance(1); } Assert.Equal(robSum, brSum); Assert.NotEqual(brSum, 0); }
public static bool ReadFrame(ReadOnlyBuffer <byte> readableBuffer, Http2Frame frame, out SequencePosition consumed, out SequencePosition examined) { consumed = readableBuffer.Start; examined = readableBuffer.End; if (readableBuffer.Length < Http2Frame.HeaderLength) { return(false); } var headerSlice = readableBuffer.Slice(0, Http2Frame.HeaderLength); headerSlice.CopyTo(frame.Raw); if (readableBuffer.Length < Http2Frame.HeaderLength + frame.Length) { return(false); } readableBuffer.Slice(Http2Frame.HeaderLength, frame.Length).CopyTo(frame.Payload); consumed = examined = readableBuffer.GetPosition(readableBuffer.Start, Http2Frame.HeaderLength + frame.Length); return(true); }
public void GetPositionDoesNotCrossOutsideBuffer() { var bufferSegment1 = new BufferSegment(); bufferSegment1.SetMemory(new OwnedArray <byte>(new byte[100]), 0, 100); var bufferSegment2 = new BufferSegment(); bufferSegment2.SetMemory(new OwnedArray <byte>(new byte[100]), 0, 100); var bufferSegment3 = new BufferSegment(); bufferSegment3.SetMemory(new OwnedArray <byte>(new byte[100]), 0, 0); bufferSegment1.SetNext(bufferSegment2); bufferSegment2.SetNext(bufferSegment3); var readableBuffer = new ReadOnlyBuffer <byte>(bufferSegment1, 0, bufferSegment2, 100); var c1 = readableBuffer.GetPosition(readableBuffer.Start, 200); Assert.Equal(100, c1.Index); Assert.Equal(bufferSegment2, c1.Segment); }
public void ReadMultipleMessages() { var encoded = new byte[] { /* length: */ 0x00, /* body: <empty> */ /* length: */ 0x0E, /* body: */ 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x2C, 0x0D, 0x0A, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21, }; ReadOnlyBuffer <byte> buffer = encoded; var messages = new List <byte[]>(); while (BinaryMessageParser.TryParseMessage(ref buffer, out var message)) { messages.Add(message.ToArray()); } Assert.Equal(0, buffer.Length); Assert.Equal(2, messages.Count); Assert.Equal(new byte[0], messages[0]); Assert.Equal(Encoding.UTF8.GetBytes("Hello,\r\nWorld!"), messages[1]); }
public static ReadableBufferSequence AsSequence(this ReadOnlyBuffer buffer) { return(new ReadableBufferSequence(buffer)); }
public ParseResult ParseMessage(ReadOnlyBuffer buffer, out Position consumed, out Position examined, out byte[] message) { consumed = buffer.Start; examined = buffer.End; message = null; var start = consumed; var end = examined; while (buffer.Length > 0) { if (ReadOnlyBuffer.Seek(start, end, out var lineEnd, ByteLF) == -1) { // For the case of data: Foo\r\n\r\<Anytine except \n> if (_internalParserState == InternalParseState.ReadEndOfMessage) { if (ConvertBufferToSpan(buffer.Slice(start, buffer.End)).Length > 1) { throw new FormatException("Expected a \\r\\n frame ending"); } } // Partial message. We need to read more. return(ParseResult.Incomplete); } lineEnd = buffer.Move(lineEnd, 1); var line = ConvertBufferToSpan(buffer.Slice(start, lineEnd)); buffer = buffer.Slice(line.Length); if (line.Length <= 1) { throw new FormatException("There was an error in the frame format"); } // Skip comments if (line[0] == ByteColon) { start = lineEnd; consumed = lineEnd; continue; } if (IsMessageEnd(line)) { _internalParserState = InternalParseState.ReadEndOfMessage; } // To ensure that the \n was preceded by a \r // since messages can't contain \n. // data: foo\n\bar should be encoded as // data: foo\r\n // data: bar\r\n else if (line[line.Length - _sseLineEnding.Length] != ByteCR) { throw new FormatException("Unexpected '\n' in message. A '\n' character can only be used as part of the newline sequence '\r\n'"); } else { EnsureStartsWithDataPrefix(line); } var payload = Array.Empty <byte>(); switch (_internalParserState) { case InternalParseState.ReadMessagePayload: EnsureStartsWithDataPrefix(line); // Slice away the 'data: ' var payloadLength = line.Length - (_dataPrefix.Length + _sseLineEnding.Length); var newData = line.Slice(_dataPrefix.Length, payloadLength).ToArray(); _data.Add(newData); start = lineEnd; consumed = lineEnd; break; case InternalParseState.ReadEndOfMessage: if (_data.Count == 1) { payload = _data[0]; } else if (_data.Count > 1) { // Find the final size of the payload var payloadSize = 0; foreach (var dataLine in _data) { payloadSize += dataLine.Length; } payloadSize += _newLine.Length * _data.Count; // Allocate space in the payload buffer for the data and the new lines. // Subtract newLine length because we don't want a trailing newline. payload = new byte[payloadSize - _newLine.Length]; var offset = 0; foreach (var dataLine in _data) { dataLine.CopyTo(payload, offset); offset += dataLine.Length; if (offset < payload.Length) { _newLine.CopyTo(payload, offset); offset += _newLine.Length; } } } message = payload; consumed = lineEnd; examined = consumed; return(ParseResult.Completed); } if (buffer.Length > 0 && buffer.First.Span[0] == ByteCR) { _internalParserState = InternalParseState.ReadEndOfMessage; } } return(ParseResult.Incomplete); }
public ParseResult ParseRequest(ReadOnlyBuffer buffer, out Position consumed, out Position examined) { consumed = buffer.Start; examined = buffer.Start; if (_state == ParsingState.StartLine) { if (!buffer.TrySliceTo((byte)'\r', (byte)'\n', out ReadOnlyBuffer startLine, out Position delim)) { return(ParseResult.Incomplete); } // Move the buffer to the rest buffer = buffer.Slice(delim).Slice(2); if (!startLine.TrySliceTo((byte)' ', out ReadOnlyBuffer method, out delim)) { return(ParseResult.BadRequest); } _method = method.ToArray(); // Skip ' ' startLine = startLine.Slice(delim).Slice(1); if (!startLine.TrySliceTo((byte)' ', out ReadOnlyBuffer path, out delim)) { return(ParseResult.BadRequest); } _path = path.ToArray(); // Skip ' ' startLine = startLine.Slice(delim).Slice(1); var httpVersion = startLine; if (httpVersion.IsEmpty) { return(ParseResult.BadRequest); } _httpVersion = httpVersion.ToArray(); _state = ParsingState.Headers; consumed = buffer.Start; examined = buffer.Start; } // Parse headers // key: value\r\n while (!buffer.IsEmpty) { var headerValue = default(ReadOnlyBuffer); if (!buffer.TrySliceTo((byte)'\r', (byte)'\n', out ReadOnlyBuffer headerPair, out Position delim)) { return(ParseResult.Incomplete); } buffer = buffer.Slice(delim).Slice(2); consumed = buffer.Start; examined = buffer.Start; // End of headers if (headerPair.IsEmpty) { return(ParseResult.Complete); } // : if (!headerPair.TrySliceTo((byte)':', out ReadOnlyBuffer headerName, out delim)) { return(ParseResult.BadRequest); } headerName = headerName.TrimStart(); headerPair = headerPair.Slice(delim).Slice(1); headerValue = headerPair.TrimStart(); RequestHeaders.SetHeader(ref headerName, ref headerValue); } return(ParseResult.Incomplete); }
protected override bool Read(ReadOnlyBuffer <byte> readableBuffer, PipeWriter writableBuffer, out SequencePosition consumed, out SequencePosition examined) { consumed = default(SequencePosition); examined = default(SequencePosition); while (_mode < Mode.Trailer) { if (_mode == Mode.Prefix) { ParseChunkedPrefix(readableBuffer, out consumed, out examined); if (_mode == Mode.Prefix) { return(false); } readableBuffer = readableBuffer.Slice(consumed); } if (_mode == Mode.Extension) { ParseExtension(readableBuffer, out consumed, out examined); if (_mode == Mode.Extension) { return(false); } readableBuffer = readableBuffer.Slice(consumed); } if (_mode == Mode.Data) { ReadChunkedData(readableBuffer, writableBuffer, out consumed, out examined); if (_mode == Mode.Data) { return(false); } readableBuffer = readableBuffer.Slice(consumed); } if (_mode == Mode.Suffix) { ParseChunkedSuffix(readableBuffer, out consumed, out examined); if (_mode == Mode.Suffix) { return(false); } readableBuffer = readableBuffer.Slice(consumed); } } // Chunks finished, parse trailers if (_mode == Mode.Trailer) { ParseChunkedTrailer(readableBuffer, out consumed, out examined); if (_mode == Mode.Trailer) { return(false); } readableBuffer = readableBuffer.Slice(consumed); } // _consumedBytes aren't tracked for trailer headers, since headers have seperate limits. if (_mode == Mode.TrailerHeaders) { if (_context.TakeMessageHeaders(readableBuffer, out consumed, out examined)) { _mode = Mode.Complete; } } return(_mode == Mode.Complete); }
internal SplitEnumerator(ReadOnlyBuffer <byte> remainder, byte delimiter) { _current = default; _remainder = remainder; _delimiter = delimiter; }
internal void Advance(Position consumed, Position examined) { BufferSegment returnStart = null; BufferSegment returnEnd = null; // Reading commit head shared with writer Action continuation = null; lock (_sync) { bool examinedEverything = false; if (examined.Segment == _commitHead) { examinedEverything = _commitHead != null ? examined.Index == _commitHeadIndex - _commitHead.Start : examined.Index == 0; } if (consumed.Segment != null) { if (_readHead == null) { PipelinesThrowHelper.ThrowInvalidOperationException(ExceptionResource.AdvanceToInvalidCursor); return; } var consumedSegment = (BufferSegment)consumed.Segment; returnStart = _readHead; returnEnd = consumedSegment; // Check if we crossed _maximumSizeLow and complete backpressure var consumedBytes = new ReadOnlyBuffer <byte>(returnStart, _readHeadIndex, consumedSegment, consumed.Index).Length; var oldLength = _length; _length -= consumedBytes; if (oldLength >= _maximumSizeLow && _length < _maximumSizeLow) { continuation = _writerAwaitable.Complete(); } // Check if we consumed entire last segment // if we are going to return commit head // we need to check that there is no writing operation that // might be using tailspace if (consumed.Index == returnEnd.Length && !(_commitHead == returnEnd && _writingState.IsStarted)) { var nextBlock = returnEnd.NextSegment; if (_commitHead == returnEnd) { _commitHead = nextBlock; _commitHeadIndex = 0; } _readHead = nextBlock; _readHeadIndex = 0; returnEnd = nextBlock; } else { _readHead = consumedSegment; _readHeadIndex = consumed.Index; } } // We reset the awaitable to not completed if we've examined everything the producer produced so far // but only if writer is not completed yet if (examinedEverything && !_writerCompletion.IsCompleted) { // Prevent deadlock where reader awaits new data and writer await backpressure if (!_writerAwaitable.IsCompleted) { PipelinesThrowHelper.ThrowInvalidOperationException(ExceptionResource.BackpressureDeadlock); } _readerAwaitable.Reset(); } _readingState.End(ExceptionResource.NoReadToComplete); while (returnStart != null && returnStart != returnEnd) { returnStart.ResetMemory(); ReturnSegmentUnsynchronized(returnStart); returnStart = returnStart.NextSegment; } } TrySchedule(_writerScheduler, continuation); }
protected virtual bool Read(ReadOnlyBuffer readableBuffer, WritableBuffer writableBuffer, out Position consumed, out Position examined) { throw new NotImplementedException(); }
private void InsertData(byte[] data) { _buffer = new ReadOnlyBuffer(data); }
/// <summary> /// Split a buffer into a sequence of tokens using a delimiter /// </summary> public static SplitEnumerable Split(this ReadOnlyBuffer buffer, byte delimiter) => new SplitEnumerable(buffer, delimiter);
public ReadOnlyBufferDebuggerView(ReadOnlyBuffer <T> buffer) { _buffer = buffer; }
protected abstract void WriteResponse(ref HttpRequest request, ReadOnlyBuffer <byte> body, TcpConnectionFormatter response);
public async Task SocketCanReadAndWrite() { var loop = new UvLoopHandle(_logger); loop.Init(_uv); var tcp = new UvTcpHandle(_logger); tcp.Init(loop, (a, b) => { }); var endPoint = new IPEndPoint(IPAddress.Loopback, 0); tcp.Bind(endPoint); var port = tcp.GetSockIPEndPoint().Port; tcp.Listen(10, (_, status, error, state) => { var tcp2 = new UvTcpHandle(_logger); tcp2.Init(loop, (a, b) => { }); tcp.Accept(tcp2); var data = Marshal.AllocCoTaskMem(500); tcp2.ReadStart( (a, b, c) => tcp2.Libuv.buf_init(data, 500), async(__, nread, state2) => { if (nread <= 0) { tcp2.Dispose(); } else { for (var x = 0; x < 2; x++) { var req = new UvWriteReq(_logger); req.DangerousInit(loop); var block = new ReadOnlyBuffer <byte>(new byte[] { 65, 66, 67, 68, 69 }); await req.WriteAsync( tcp2, block); } } }, null); tcp.Dispose(); }, null); var t = Task.Run(async() => { var socket = TestConnection.CreateConnectedLoopbackSocket(port); await socket.SendAsync(new[] { new ArraySegment <byte>(new byte[] { 1, 2, 3, 4, 5 }) }, SocketFlags.None); socket.Shutdown(SocketShutdown.Send); var buffer = new ArraySegment <byte>(new byte[2048]); while (true) { var count = await socket.ReceiveAsync(new[] { buffer }, SocketFlags.None); if (count <= 0) { break; } } socket.Dispose(); }); loop.Run(); loop.Dispose(); await t; }
public int Send(ReadOnlyBuffer <byte> buffer) { return(Send(buffer.Span)); }
public void TryReadingIncompleteMessage() { var message = new ReadOnlyBuffer <byte>(Encoding.UTF8.GetBytes("ABC")); Assert.False(TextMessageParser.TryParseMessage(ref message, out var payload)); }
protected virtual bool Read(ReadOnlyBuffer <byte> readableBuffer, PipeWriter writableBuffer, out SequencePosition consumed, out SequencePosition examined) { throw new NotImplementedException(); }
public Int32 GetPayloadLength(ReadOnlyBuffer <Byte> buffer) { return(0); }
public ReadableBufferSequence(ReadOnlyBuffer buffer) : this() { _buffer = buffer; }
public static void CreateAnimation(Viewport from, Viewport to, ref ReadOnlyBuffer <float> coordinates, int imageWidth, int imageHeight) { // Creating/handling the frames folder. if (Directory.Exists("frames")) { foreach (var f in Directory.GetFiles("frames")) { File.Delete(f); } } else { Directory.CreateDirectory("frames"); } Thread.Sleep(500); var previousMaxDensity = -1f; /// This just determines how many frames to render. var timeToTake = 1; // seconds var frameRate = 1000; var progress = 0; var watch = new Stopwatch(); watch.Start(); for (var i = 0; i < frameRate * timeToTake; i++) { var t = i / (float)(frameRate * timeToTake); t = Smoothing(t); var image = new PSprite(imageWidth, imageHeight); image.Art.SetPixels(GalaxyRenderer.Render( Viewport.Lerp(from, to, t), 1000, 1000, GalaxyRenderer.DefaultColorMapping, i == 0 ? (float?)null : previousMaxDensity, out previousMaxDensity, ref coordinates)); if (!(image is null)) { image.Save(@"frames\" + i.ToString("000000") + ".png"); image.Dispose(); } progress++; #region Logging progress per frame Console.WriteLine(progress + " / " + (frameRate * timeToTake) + " - " + ((progress * 100) / (double)(frameRate * timeToTake)).ToString("0.00") + "%"); var secondsPerFrame = watch.Elapsed.TotalSeconds / progress; var framesRemaining = (frameRate * timeToTake) - progress; var timeRemaining = new TimeSpan((long)(10000000 * (framesRemaining * secondsPerFrame))); Console.WriteLine("Estimated time remaining: " + timeRemaining.Hours.ToString("00") + ":" + timeRemaining.Minutes.ToString("00") + ":" + timeRemaining.Seconds.ToString("00")); Console.WriteLine("Average time per frame: " + secondsPerFrame.ToString("0.00") + " seconds."); #endregion } Console.WriteLine("Frame rendering complete. Compiling video..."); var info = new ProcessStartInfo() { FileName = "ffmpeg", Arguments = string.Format(" -framerate {0} -i %06d.png -c:v libx264 -r {0} {1}.mp4", frameRate, "out"), WorkingDirectory = "frames", }; var p = Process.Start(info); p.WaitForExit(); Console.WriteLine("Finished. Saved video as out.mp4."); Console.Read(); }
public void Create_WorksWithArray() { var readableBuffer = new ReadOnlyBuffer <byte>(new byte[] { 1, 2, 3, 4, 5 }, 2, 3); Assert.Equal(readableBuffer.ToArray(), new byte[] { 3, 4, 5 }); }
public abstract TPackageInfo ResolvePackage(ReadOnlyBuffer <byte> buffer);