Example #1
0
        public void Execute()
        {
            _services.Trace.Event(TraceEventType.Start, TraceMessage.Connection);

            _baton = new Baton(_services.Memory);

            _fault = ex => { Debug.WriteLine(ex.Message); };

            _receiveSocketEvent = _services.Memory.AllocSocketEvent();
            _receiveSocketEvent.SetBuffer(_services.Memory.Empty, 0, 0);

            _frameConsumeCallback = frame =>
            {
                try
                {
                    Go(false, frame);
                }
                catch (Exception ex)
                {
                    _fault(ex);
                }
            };

            try
            {
                _socket.Blocking = false;
                _socket.NoDelay = true;
                Go(true, null);
            }
            catch (Exception ex)
            {
                _fault(ex);
            }
        }
Example #2
0
        public void SkipAdvancesBuffer()
        {
            // Arrange
            var baton = new Baton(new FakeMemoryPool()) {Buffer = "xxhello world".ToArraySegment()};
            baton.Skip(2);

            // Act
            baton.Skip(5);

            // Assert
            Assert.Equal(6, baton.Buffer.Count);
            Assert.Equal(" world", baton.Buffer.ToString(Encoding.Default));
        }
Example #3
0
        public void AvailableBufferReturnsAreaThatIsUnused()
        {
            // Arrange
            var baton = new Baton(new FakeMemoryPool()) {Buffer = "xxhello worldxx".ToArraySegment()};
            baton.Buffer = new ArraySegment<byte>(baton.Buffer.Array, 2, 5);

            // Act
            var buffer = baton.Available(0);

            // Assert
            Assert.Equal(8, buffer.Count);
            Assert.Equal(" worldxx", buffer.ToString(Encoding.Default));
        }
Example #4
0
        public void AvailableBufferBringsOffsetBackToZeroIfOccupiedSegmentIsZeroLength()
        {
            // Arrange
            var baton = new Baton(new FakeMemoryPool()) {Buffer = "xxhello worldxx".ToArraySegment()};
            baton.Buffer = new ArraySegment<byte>(baton.Buffer.Array, 2, 0);

            // Act
            var buffer = baton.Available(0);

            // Assert
            Assert.Equal(15, buffer.Count);
            Assert.Equal("xxhello worldxx", buffer.ToString(Encoding.Default));
        }
Example #5
0
        public void TakeAdvancesBufferAndReturnsTakenSegment()
        {
            // Arrange
            var baton = new Baton(new FakeMemoryPool()) {Buffer = "xxhello world".ToArraySegment()};
            baton.Skip(2);

            // Act
            var taken = baton.Take(5);

            // Assert
            Assert.Equal(6, baton.Buffer.Count);
            Assert.Equal(" world", baton.Buffer.ToString(Encoding.Default));
            Assert.Equal(5, taken.Count);
            Assert.Equal("hello", taken.ToString(Encoding.Default));
        }
Example #6
0
 public override bool TakeMessageHeader(Baton baton, out bool endOfHeaders)
 {
     endOfHeaders = false;
     var text = Encoding.Default.GetString(baton.Buffer.Array, baton.Buffer.Offset, baton.Buffer.Count);
     var lines = text.Split(new[] {"\r\n"}, StringSplitOptions.None);
     foreach (var line in lines)
     {
         if (line == "")
         {
             endOfHeaders = true;
             break;
         }
         var colonIndex = line.IndexOf(':');
         AddRequestHeader(line.Substring(0, colonIndex), line.Substring(colonIndex + 1));
     }
     return false;
 }
Example #7
0
        public void ExtendCausesArraySegmentToIncludeMoreBytesAtTheEnd()
        {
            // Arrange
            var baton = new Baton(new FakeMemoryPool()) {Buffer = "xxhello worldxx".ToArraySegment()};
            baton.Buffer = new ArraySegment<byte>(baton.Buffer.Array, 2, 5);

            // Act
            var before = baton.Buffer.ToString(Encoding.Default);
            baton.Extend(5);
            var after = baton.Buffer.ToString(Encoding.Default);

            // Assert
            Assert.Equal("hello", before);
            Assert.Equal("hello worl", after);
            Assert.Equal(2, baton.Buffer.Offset);
            Assert.Equal(10, baton.Buffer.Count);
        }
Example #8
0
            public override bool Consume(Baton baton, Action callback, Action<Exception> fault)
            {
                if (baton.RemoteIntakeFin)
                {
                    LocalIntakeFin = true;
                    _subscriber.End(null);
                    return false;
                }

                var consumed = baton.Take(baton.Buffer.Count);
                return _subscriber.Write(consumed) && _subscriber.Flush(callback);
            }
Example #9
0
            public override bool Consume(Baton baton, Action callback, Action<Exception> fault)
            {
                var consumeLength = Math.Min(_neededLength, baton.Buffer.Count);
                _neededLength -= consumeLength;

                var consumed = baton.Take(consumeLength);

                if (_neededLength != 0)
                {
                    // TODO: if check baton.Complete==true && neededlength != 0 then remote socket closed early
                    return _subscriber.Write(consumed) && _subscriber.Flush(callback);
                }

                LocalIntakeFin = true;

                if (consumed.Count != 0)
                {
                    if (_subscriber.Write(consumed) &&
                        _subscriber.Flush(
                            () =>
                            {
                                _subscriber.End(null);
                                callback();
                            }))
                    {
                        return true;
                    }
                }

                _subscriber.End(null);
                return false;
            }
Example #10
0
            private static bool TakeChunkedLine(Baton baton, ref int chunkSizeOut)
            {
                var remaining = baton.Buffer;
                if (remaining.Count < 2)
                {
                    return false;
                }
                var ch0 = remaining.Array[remaining.Offset];
                var chunkSize = 0;
                var mode = 0;
                for (var index = 0; index != remaining.Count - 1; ++index)
                {
                    var ch1 = remaining.Array[remaining.Offset + index + 1];

                    if (mode == 0)
                    {
                        if (ch0 >= '0' && ch0 <= '9')
                        {
                            chunkSize = chunkSize * 0x10 + (ch0 - '0');
                        }
                        else if (ch0 >= 'A' && ch0 <= 'F')
                        {
                            chunkSize = chunkSize * 0x10 + (ch0 - ('A' - 10));
                        }
                        else if (ch0 >= 'a' && ch0 <= 'f')
                        {
                            chunkSize = chunkSize * 0x10 + (ch0 - ('a' - 10));
                        }
                        else
                        {
                            throw new NotImplementedException("INVALID REQUEST FORMAT");
                        }
                        mode = 1;
                    }
                    else if (mode == 1)
                    {
                        if (ch0 >= '0' && ch0 <= '9')
                        {
                            chunkSize = chunkSize * 0x10 + (ch0 - '0');
                        }
                        else if (ch0 >= 'A' && ch0 <= 'F')
                        {
                            chunkSize = chunkSize * 0x10 + (ch0 - ('A' - 10));
                        }
                        else if (ch0 >= 'a' && ch0 <= 'f')
                        {
                            chunkSize = chunkSize * 0x10 + (ch0 - ('a' - 10));
                        }
                        else if (ch0 == ';')
                        {
                            mode = 2;
                        }
                        else if (ch0 == '\r' && ch1 == '\n')
                        {
                            baton.Skip(index + 2);
                            chunkSizeOut = chunkSize;
                            return true;
                        }
                        else
                        {
                            throw new NotImplementedException("INVALID REQUEST FORMAT");
                        }
                    }
                    else if (mode == 2)
                    {
                        if (ch0 == '\r' && ch1 == '\n')
                        {
                            baton.Skip(index + 2);
                            chunkSizeOut = chunkSize;
                            return true;
                        }
                        else
                        {
                            // chunk-extensions not currently parsed
                        }
                    }

                    ch0 = ch1;
                }
                return false;
            }
Example #11
0
            public override bool Consume(Baton baton, Action callback, Action<Exception> fault)
            {
                for (;;)
                {
                    switch (_mode)
                    {
                    case Mode.ChunkSizeLine:
                        var chunkSize = 0;
                        if (!TakeChunkedLine(baton, ref chunkSize))
                        {
                            return false;
                        }

                        _neededLength = chunkSize;
                        if (chunkSize == 0)
                        {
                            _mode = Mode.Complete;
                            LocalIntakeFin = true;
                            _subscriber.End(null);
                            return false;
                        }
                        _mode = Mode.ChunkData;
                        break;

                    case Mode.ChunkData:
                        if (_neededLength == 0)
                        {
                            _mode = Mode.ChunkDataCRLF;
                            break;
                        }
                        if (baton.Buffer.Count == 0)
                        {
                            return false;
                        }

                        var consumeLength = Math.Min(_neededLength, baton.Buffer.Count);
                        _neededLength -= consumeLength;
                        var consumed = baton.Take(consumeLength);

                        if (_subscriber.Write(consumed) &&
                            _subscriber.Flush(callback))
                        {
                            return true;
                        }
                        break;

                    case Mode.ChunkDataCRLF:
                        if (baton.Buffer.Count < 2)
                        {
                            return false;
                        }
                        var crlf = baton.Take(2);
                        if (crlf.Array[crlf.Offset] != '\r' ||
                            crlf.Array[crlf.Offset + 1] != '\n')
                        {
                            throw new NotImplementedException("INVALID REQUEST FORMAT");
                        }
                        _mode = Mode.ChunkSizeLine;
                        break;

                    default:
                        throw new NotImplementedException("INVALID REQUEST FORMAT");
                    }
                }
            }
Example #12
0
        public override bool TakeMessageHeader(Baton baton, out bool endOfHeaders)
        {
            var remaining = baton.Buffer;
            endOfHeaders = false;
            if (remaining.Count < 2)
            {
                return false;
            }
            var ch0 = remaining.Array[remaining.Offset];
            var ch1 = remaining.Array[remaining.Offset + 1];
            if (ch0 == '\r' && ch1 == '\n')
            {
                endOfHeaders = true;
                baton.Skip(2);
                return true;
            }

            if (remaining.Count < 3)
            {
                return false;
            }
            var wrappedHeaders = false;
            var colonIndex = -1;
            var valueStartIndex = -1;
            var valueEndIndex = -1;
            for (var index = 0; index != remaining.Count - 2; ++index)
            {
                var ch2 = remaining.Array[remaining.Offset + index + 2];
                if (ch0 == '\r' &&
                    ch1 == '\n' &&
                        ch2 != ' ' &&
                            ch2 != '\t')
                {
                    var name = Encoding.Default.GetString(remaining.Array, remaining.Offset, colonIndex);
                    var value = "";
                    if (valueEndIndex != -1)
                    {
                        value = Encoding.Default.GetString(
                            remaining.Array, remaining.Offset + valueStartIndex, valueEndIndex - valueStartIndex);
                    }
                    if (wrappedHeaders)
                    {
                        value = value.Replace("\r\n", " ");
                    }
                    AddRequestHeader(name, value);
                    baton.Skip(index + 2);
                    return true;
                }
                if (colonIndex == -1 && ch0 == ':')
                {
                    colonIndex = index;
                }
                else if (colonIndex != -1 &&
                    ch0 != ' ' &&
                        ch0 != '\t' &&
                            ch0 != '\r' &&
                                ch0 != '\n')
                {
                    if (valueStartIndex == -1)
                    {
                        valueStartIndex = index;
                    }
                    valueEndIndex = index + 1;
                }
                else if (!wrappedHeaders &&
                    ch0 == '\r' &&
                        ch1 == '\n' &&
                            (ch2 == ' ' ||
                                ch2 == '\t'))
                {
                    wrappedHeaders = true;
                }

                ch0 = ch1;
                ch1 = ch2;
            }
            return false;
        }
Example #13
0
 public override bool TakeMessageHeader(Baton baton, out bool endOfHeaders)
 {
     endOfHeaders = false;
     return false;
 }
Example #14
0
 public abstract bool TakeMessageHeader(Baton baton, out bool endOfHeaders);
Example #15
0
        public bool Consume(Baton baton, Action<Frame, Exception> callback)
        {
            for (; ;)
            {
                switch (_mode)
                {
                    case Mode.StartLine:
                        if (baton.RemoteIntakeFin)
                        {
                            _mode = Mode.Terminated;
                            return false;
                        }

                        if (!TakeStartLine(baton))
                        {
                            return false;
                        }

                        _mode = Mode.MessageHeader;
                        break;

                    case Mode.MessageHeader:
                        if (baton.RemoteIntakeFin)
                        {
                            _mode = Mode.Terminated;
                            return false;
                        }

                        var endOfHeaders = false;
                        while (!endOfHeaders)
                        {
                            if (!TakeMessageHeader(baton, out endOfHeaders))
                            {
                                return false;
                            }
                        }

                        var resumeBody = HandleExpectContinue(callback);
                        _messageBody = MessageBody.For(
                            _httpVersion,
                            _requestHeaders,
                            () =>
                            {
                                try
                                {
                                    if (Consume(baton, resumeBody))
                                        return;
                                }
                                catch (Exception ex)
                                {
                                    resumeBody.Invoke(this, ex);
                                    return;
                                }
                                resumeBody.Invoke(this, null);
                            });
                        _keepAlive = _messageBody.RequestKeepAlive;
                        _mode = Mode.MessageBody;
                        baton.Free();
                        Execute();
                        return true;

                    case Mode.MessageBody:
                        return _messageBody.Consume(baton, ex => callback(this, ex));

                    case Mode.Terminated:
                        return false;
                }
            }
        }
Example #16
0
        private bool TakeStartLine(Baton baton)
        {
            var remaining = baton.Buffer;
            if (remaining.Count < 2)
            {
                return false;
            }
            var firstSpace = -1;
            var secondSpace = -1;
            var questionMark = -1;
            var ch0 = remaining.Array[remaining.Offset];
            for (var index = 0; index != remaining.Count - 1; ++index)
            {
                var ch1 = remaining.Array[remaining.Offset + index + 1];
                if (ch0 == '\r' && ch1 == '\n')
                {
                    if (secondSpace == -1)
                    {
                        throw new InvalidOperationException("INVALID REQUEST FORMAT");
                    }
                    _method = GetString(remaining, 0, firstSpace);
                    _requestUri = GetString(remaining, firstSpace + 1, secondSpace);
                    if (questionMark == -1)
                    {
                        _path = _requestUri;
                        _queryString = string.Empty;
                    }
                    else
                    {
                        _path = GetString(remaining, firstSpace + 1, questionMark);
                        _queryString = GetString(remaining, questionMark + 1, secondSpace);
                    }
                    _httpVersion = GetString(remaining, secondSpace + 1, index);
                    baton.Skip(index + 2);
                    return true;
                }

                if (ch0 == ' ' && firstSpace == -1)
                {
                    firstSpace = index;
                }
                else if (ch0 == ' ' && firstSpace != -1 && secondSpace == -1)
                {
                    secondSpace = index;
                }
                else if (ch0 == '?' && firstSpace != -1 && questionMark == -1 && secondSpace == -1)
                {
                    questionMark = index;
                }
                ch0 = ch1;
            }
            return false;
        }
Example #17
0
 public abstract bool Consume(Baton baton, Action callback, Action<Exception> fault);
Example #18
0
        private bool TakeMessageHeader(Baton baton, out bool endOfHeaders)
        {
            var remaining = baton.Buffer;

            endOfHeaders = false;
            if (remaining.Count < 2)
            {
                return(false);
            }
            var ch0 = remaining.Array[remaining.Offset];
            var ch1 = remaining.Array[remaining.Offset + 1];

            if (ch0 == '\r' && ch1 == '\n')
            {
                endOfHeaders = true;
                baton.Skip(2);
                return(true);
            }

            if (remaining.Count < 3)
            {
                return(false);
            }
            var wrappedHeaders  = false;
            var colonIndex      = -1;
            var valueStartIndex = -1;
            var valueEndIndex   = -1;

            for (var index = 0; index != remaining.Count - 2; ++index)
            {
                var ch2 = remaining.Array[remaining.Offset + index + 2];
                if (ch0 == '\r' &&
                    ch1 == '\n' &&
                    ch2 != ' ' &&
                    ch2 != '\t')
                {
                    var name  = Encoding.ASCII.GetString(remaining.Array, remaining.Offset, colonIndex);
                    var value = "";
                    if (valueEndIndex != -1)
                    {
                        value = Encoding.ASCII.GetString(
                            remaining.Array, remaining.Offset + valueStartIndex, valueEndIndex - valueStartIndex);
                    }
                    if (wrappedHeaders)
                    {
                        value = value.Replace("\r\n", " ");
                    }
                    AddRequestHeader(name, value);
                    baton.Skip(index + 2);
                    return(true);
                }
                if (colonIndex == -1 && ch0 == ':')
                {
                    colonIndex = index;
                }
                else if (colonIndex != -1 &&
                         ch0 != ' ' &&
                         ch0 != '\t' &&
                         ch0 != '\r' &&
                         ch0 != '\n')
                {
                    if (valueStartIndex == -1)
                    {
                        valueStartIndex = index;
                    }
                    valueEndIndex = index + 1;
                }
                else if (!wrappedHeaders &&
                         ch0 == '\r' &&
                         ch1 == '\n' &&
                         (ch2 == ' ' ||
                          ch2 == '\t'))
                {
                    wrappedHeaders = true;
                }

                ch0 = ch1;
                ch1 = ch2;
            }
            return(false);
        }
Example #19
0
        public bool Consume(Baton baton, Action <Frame, Exception> callback)
        {
            for (; ;)
            {
                switch (_mode)
                {
                case Mode.StartLine:
                    if (baton.RemoteIntakeFin)
                    {
                        _mode = Mode.Terminated;
                        return(false);
                    }

                    if (!TakeStartLine(baton))
                    {
                        return(false);
                    }

                    _mode = Mode.MessageHeader;
                    break;

                case Mode.MessageHeader:
                    if (baton.RemoteIntakeFin)
                    {
                        _mode = Mode.Terminated;
                        return(false);
                    }

                    var endOfHeaders = false;
                    while (!endOfHeaders)
                    {
                        if (!TakeMessageHeader(baton, out endOfHeaders))
                        {
                            return(false);
                        }
                    }

                    var resumeBody = HandleExpectContinue(callback);
                    _messageBody = MessageBody.For(
                        _httpVersion,
                        _requestHeaders,
                        () =>
                    {
                        try
                        {
                            if (Consume(baton, resumeBody))
                            {
                                return;
                            }
                        }
                        catch (Exception ex)
                        {
                            resumeBody.Invoke(this, ex);
                            return;
                        }
                        resumeBody.Invoke(this, null);
                    });
                    _keepAlive = _messageBody.RequestKeepAlive;
                    _mode      = Mode.MessageBody;
                    baton.Free();
                    Execute();
                    return(true);

                case Mode.MessageBody:
                    return(_messageBody.Consume(baton, ex => callback(this, ex)));

                case Mode.Terminated:
                    return(false);
                }
            }
        }
Example #20
0
 public FakeInput()
 {
     Baton = new Baton(new FakeMemoryPool());
     WaitHandle = new ManualResetEvent(false);
     Encoding = Encoding.UTF8;
 }
Example #21
0
        static void Main(string[] args)
        {
            var datas = File.ReadAllText("Headers.txt")
                .Split(new[] {"\r\n\r\n"}, StringSplitOptions.RemoveEmptyEntries)
                .Select(chunk => Encoding.Default.GetBytes(chunk + "\r\n\r\nAll of the data"))
                .ToArray();

            for (;;)
            {
                var samples = Enumerable.Range(0, 10);

                var measures = Strats()
                    .Select(
                        s => new
                        {
                            Strat = s,
                            Stopwatch = samples
                                .Select(x => new Stopwatch())
                                .ToArray()
                        }).ToArray();

                Console.WriteLine("Starting");
                foreach (var sample in samples)
                {
                    foreach (var data in datas)
                    {
                        foreach (var measure in measures)
                        {
                            Action after = () => { };
                            measure.Stopwatch[sample].Start();
                            foreach (var loop in Enumerable.Range(0, 10000))
                            {
                                var strat = measure.Strat();

                                var baton = new Baton(new MemoryPool())
                                {
                                    Buffer = new ArraySegment<byte>(data),
                                    RemoteIntakeFin = false,
                                };
                                var endOfHeaders = false;
                                while (!endOfHeaders)
                                {
                                    if (!strat.TakeMessageHeader(baton, out endOfHeaders))
                                    {
                                        break;
                                    }
                                }

                                if (loop == 0 && sample == 0)
                                {
                                    after = () =>
                                    {
                                        Console.WriteLine("{0}", strat.GetType().Name);
                                        foreach (var kv in strat.Headers)
                                        {
                                            Console.WriteLine("  {0}: {1}", kv.Key, kv.Value);
                                        }
                                    };
                                }
                            }
                            measure.Stopwatch[sample].Stop();
                            after();
                        }
                    }
                }

                foreach (var measure in measures)
                {
                    Console.WriteLine(
                        "{0} {1}\r\n  {2}",
                        measure.Strat().GetType().Name,
                        measure.Stopwatch
                            .Aggregate(TimeSpan.Zero, (a, b) => a.Add(b.Elapsed)),
                        measure.Stopwatch
                            .Select(x => x.ElapsedTicks)
                            .OrderBy(x => x)
                            .Aggregate("", (a, b) => a + " " + b));
                }
                Console.WriteLine("Done");
                Console.ReadLine();
            }
        }