public void ConsumingComplete(
            MemoryPoolIterator2 consumed,
            MemoryPoolIterator2 examined)
        {
            MemoryPoolBlock2 returnStart = null;
            MemoryPoolBlock2 returnEnd = null;
            lock (_sync)
            {
                if (!consumed.IsDefault)
                {
                    returnStart = _head;
                    returnEnd = consumed.Block;
                    _head = consumed.Block;
                    _head.Start = consumed.Index;
                }
                if (!examined.IsDefault &&
                    examined.IsEnd &&
                    RemoteIntakeFin == false &&
                    _awaitableError == null)
                {
                    _manualResetEvent.Reset();

                    var awaitableState = Interlocked.CompareExchange(
                        ref _awaitableState,
                        _awaitableIsNotCompleted,
                        _awaitableIsCompleted);
                }
            }
            while (returnStart != returnEnd)
            {
                var returnBlock = returnStart;
                returnStart = returnStart.Next;
                returnBlock.Pool.Return(returnBlock);
            }
        }
        public unsafe void Write(
            UvStreamHandle handle,
            MemoryPoolIterator2 start,
            MemoryPoolIterator2 end,
            int nBuffers,
            Action<UvWriteReq, int, Exception, object> callback,
            object state)
        {
            try
            {
                // add GCHandle to keeps this SafeHandle alive while request processing
                _pins.Add(GCHandle.Alloc(this, GCHandleType.Normal));

                var pBuffers = (Libuv.uv_buf_t*)_bufs;
                if (nBuffers > BUFFER_COUNT)
                {
                    // create and pin buffer array when it's larger than the pre-allocated one
                    var bufArray = new Libuv.uv_buf_t[nBuffers];
                    var gcHandle = GCHandle.Alloc(bufArray, GCHandleType.Pinned);
                    _pins.Add(gcHandle);
                    pBuffers = (Libuv.uv_buf_t*)gcHandle.AddrOfPinnedObject();
                }

                var block = start.Block;
                for (var index = 0; index < nBuffers; index++)
                {
                    var blockStart = block == start.Block ? start.Index : block.Data.Offset;
                    var blockEnd = block == end.Block ? end.Index : block.Data.Offset + block.Data.Count;

                    // create and pin each segment being written
                    pBuffers[index] = Libuv.buf_init(
                        block.Pin() + blockStart,
                        blockEnd - blockStart);

                    block = block.Next;
                }

                _callback = callback;
                _state = state;
                _uv.write(this, handle, pBuffers, nBuffers, _uv_write_cb);
            }
            catch
            {
                _callback = null;
                _state = null;
                Unpin(this);

                var block = start.Block;
                for (var index = 0; index < nBuffers; index++)
                {
                    block.Unpin();
                    block = block.Next;
                }

                throw;
            }
        }
        public void ProducingComplete(MemoryPoolIterator2 end)
        {
            var block = _producingBlock;
            while (block != end.Block)
            {
                _outputStream.Write(block.Data.Array, block.Data.Offset, block.Data.Count);

                var returnBlock = block;
                block = block.Next;
                returnBlock.Pool?.Return(returnBlock);
            }

            _outputStream.Write(end.Block.Array, end.Block.Data.Offset, end.Index - end.Block.Data.Offset);
            end.Block.Pool?.Return(end.Block);
        }
        /// <summary>
        /// Unescapes the string between given memory iterators in place.
        /// </summary>
        /// <param name="start">The iterator points to the beginning of the sequence.</param>
        /// <param name="end">The iterator points to the byte behind the end of the sequence.</param>
        /// <returns>The iterator points to the byte behind the end of the processed sequence.</returns>
        public static MemoryPoolIterator2 Unescape(MemoryPoolIterator2 start, MemoryPoolIterator2 end)
        {
            // the slot to read the input
            var reader = start;

            // the slot to write the unescaped byte
            var writer = reader;

            while (true)
            {
                if (CompareIterators(ref reader, ref end))
                {
                    return writer;
                }

                if (reader.Peek() == '%')
                {
                    var decodeReader = reader;

                    // If decoding process succeeds, the writer iterator will be moved
                    // to the next write-ready location. On the other hand if the scanned
                    // percent-encodings cannot be interpreted as sequence of UTF-8 octets,
                    // these bytes should be copied to output as is. 
                    // The decodeReader iterator is always moved to the first byte not yet 
                    // be scanned after the process. A failed decoding means the chars
                    // between the reader and decodeReader can be copied to output untouched. 
                    if (!DecodeCore(ref decodeReader, ref writer, end))
                    {
                        Copy(reader, decodeReader, ref writer);
                    }

                    reader = decodeReader;
                }
                else
                {
                    writer.Put((byte)reader.Take());
                }
            }
        }
        public void ProducingStartAndProducingCompleteCanBeUsedDirectly()
        {
            int nBuffers = 0;
            var nBufferWh = new ManualResetEventSlim();

            var mockLibuv = new MockLibuv
            {
                OnWrite = (socket, buffers, triggerCompleted) =>
                {
                    nBuffers = buffers;
                    nBufferWh.Set();
                    triggerCompleted(0);
                    return 0;
                }
            };

            using (var kestrelEngine = new KestrelEngine(mockLibuv, new TestServiceContext()))
            using (var memory = new MemoryPool2())
            {
                kestrelEngine.Start(count: 1);

                var kestrelThread = kestrelEngine.Threads[0];
                var socket = new MockSocket(kestrelThread.Loop.ThreadId, new TestKestrelTrace());
                var trace = new KestrelTrace(new TestKestrelTrace());
                var ltp = new LoggingThreadPool(trace);
                var socketOutput = new SocketOutput(kestrelThread, socket, memory, null, 0, trace, ltp, new Queue<UvWriteReq>());

                // block 1
                var start = socketOutput.ProducingStart();
                start.Block.End = start.Block.Data.Offset + start.Block.Data.Count;

                // block 2
                var block2 = memory.Lease();
                block2.End = block2.Data.Offset + block2.Data.Count;
                start.Block.Next = block2;

                var end = new MemoryPoolIterator2(block2, block2.End);

                socketOutput.ProducingComplete(end);

                // A call to Write is required to ensure a write is scheduled
                socketOutput.WriteAsync(default(ArraySegment<byte>));

                Assert.True(nBufferWh.Wait(1000));
                Assert.Equal(2, nBuffers);
            }
        }
        public MemoryPoolIterator2 ProducingStart()
        {
            lock (_returnLock)
            {
                Debug.Assert(_lastStart.IsDefault);

                if (_tail == null)
                {
                    throw new IOException("The socket has been closed.");
                }

                _lastStart = new MemoryPoolIterator2(_tail, _tail.End);

                return _lastStart;
            }
        }
 private void AssertIterator(MemoryPoolIterator2 iter, MemoryPoolBlock2 block, int index)
 {
     Assert.Same(block, iter.Block);
     Assert.Equal(index, iter.Index);
 }
        public string GetString(MemoryPoolIterator2 end)
        {
            if (IsDefault || end.IsDefault)
            {
                return default(string);
            }
            if (end._block == _block)
            {
                return _utf8.GetString(_block.Array, _index, end._index - _index);
            }

            var decoder = _utf8.GetDecoder();

            var length = GetLength(end);
            var charLength = length * 2;
            var chars = new char[charLength];
            var charIndex = 0;

            var block = _block;
            var index = _index;
            var remaining = length;
            while (true)
            {
                int bytesUsed;
                int charsUsed;
                bool completed;
                var following = block.End - index;
                if (remaining <= following)
                {
                    decoder.Convert(
                        block.Array,
                        index,
                        remaining,
                        chars,
                        charIndex,
                        charLength - charIndex,
                        true,
                        out bytesUsed,
                        out charsUsed,
                        out completed);
                    return new string(chars, 0, charIndex + charsUsed);
                }
                else if (block.Next == null)
                {
                    decoder.Convert(
                        block.Array,
                        index,
                        following,
                        chars,
                        charIndex,
                        charLength - charIndex,
                        true,
                        out bytesUsed,
                        out charsUsed,
                        out completed);
                    return new string(chars, 0, charIndex + charsUsed);
                }
                else
                {
                    decoder.Convert(
                        block.Array,
                        index,
                        following,
                        chars,
                        charIndex,
                        charLength - charIndex,
                        false,
                        out bytesUsed,
                        out charsUsed,
                        out completed);
                    charIndex += charsUsed;
                    remaining -= following;
                    block = block.Next;
                    index = block.Start;
                }
            }
        }
        public ArraySegment<byte> GetArraySegment(MemoryPoolIterator2 end)
        {
            if (IsDefault || end.IsDefault)
            {
                return default(ArraySegment<byte>);
            }
            if (end._block == _block)
            {
                return new ArraySegment<byte>(_block.Array, _index, end._index - _index);
            }

            var length = GetLength(end);
            var array = new byte[length];
            CopyTo(array, 0, length, out length);
            return new ArraySegment<byte>(array, 0, length);
        }
 private static bool CompareIterators(ref MemoryPoolIterator2 lhs, ref MemoryPoolIterator2 rhs)
 {
     // uses ref parameter to save cost of copying
     return (lhs.Block == rhs.Block) && (lhs.Index == rhs.Index);
 }
        /// <summary>
        /// Read the percent-encoding and try unescape it.
        /// 
        /// The operation first peek at the character the <paramref name="scan"/> 
        /// iterator points at. If it is % the <paramref name="scan"/> is then 
        /// moved on to scan the following to characters. If the two following 
        /// characters are hexadecimal literals they will be unescaped and the 
        /// value will be returned.
        /// 
        /// If the first character is not % the <paramref name="scan"/> iterator 
        /// will be removed beyond the location of % and -1 will be returned.
        /// 
        /// If the following two characters can't be successfully unescaped the 
        /// <paramref name="scan"/> iterator will be move behind the % and -1 
        /// will be returned.
        /// </summary>
        /// <param name="scan">The value to read</param>
        /// <param name="end">The end of the sequence</param>
        /// <returns>The unescaped byte if success. Otherwise return -1.</returns>
        private static int UnescapePercentEncoding(ref MemoryPoolIterator2 scan, MemoryPoolIterator2 end)
        {
            if (scan.Take() != '%')
            {
                return -1;
            }

            var probe = scan;

            int value1 = ReadHex(ref probe, end);
            if (value1 == -1)
            {
                return -1;
            }

            int value2 = ReadHex(ref probe, end);
            if (value2 == -1)
            {
                return -1;
            }

            if (SkipUnescape(value1, value2))
            {
                return -1;
            }

            scan = probe;
            return (value1 << 4) + value2;
        }
            public void Reset()
            {
                _lockedStart = default(MemoryPoolIterator2);
                _lockedEnd = default(MemoryPoolIterator2);
                _bufferCount = 0;
                ByteCount = 0;

                SocketShutdownSend = false;
                SocketDisconnect = false;

                WriteStatus = 0;
                WriteError = null;

                ShutdownSendStatus = 0;
            }
            private void LockWrite()
            {
                var head = Self._head;
                var tail = Self._tail;

                if (head == null || tail == null)
                {
                    // ReturnAllBlocks has already bee called. Nothing to do here.
                    // Write will no-op since _byteCount will remain 0.
                    return;
                }

                _lockedStart = new MemoryPoolIterator2(head, head.Start);
                _lockedEnd = new MemoryPoolIterator2(tail, tail.End);

                BytesBetween(_lockedStart, _lockedEnd, out ByteCount, out _bufferCount);
            }
        private static void BytesBetween(MemoryPoolIterator2 start, MemoryPoolIterator2 end, out int bytes, out int buffers)
        {
            if (start.Block == end.Block)
            {
                bytes = end.Index - start.Index;
                buffers = 1;
                return;
            }

            bytes = start.Block.Data.Offset + start.Block.Data.Count - start.Index;
            buffers = 1;

            for (var block = start.Block.Next; block != end.Block; block = block.Next)
            {
                bytes += block.Data.Count;
                buffers++;
            }

            bytes += end.Index - end.Block.Data.Offset;
            buffers++;
        }
        private void ProducingCompleteNoPreComplete(MemoryPoolIterator2 end)
        {
            MemoryPoolBlock2 blockToReturn = null;

            lock (_returnLock)
            {
                Debug.Assert(!_lastStart.IsDefault);

                // If the socket has been closed, return the produced blocks
                // instead of advancing the now non-existent tail.
                if (_tail != null)
                {
                    _tail = end.Block;
                    _tail.End = end.Index;
                }
                else
                {
                    blockToReturn = _lastStart.Block;
                }

                _lastStart = default(MemoryPoolIterator2);
            }

            if (blockToReturn != null)
            {
                ThreadPool.QueueUserWorkItem(_returnBlocks, blockToReturn);
            }
        }
        public void ProducingComplete(MemoryPoolIterator2 end)
        {
            Debug.Assert(!_lastStart.IsDefault);

            int bytesProduced, buffersIncluded;
            BytesBetween(_lastStart, end, out bytesProduced, out buffersIncluded);

            lock (_contextLock)
            {
                _numBytesPreCompleted += bytesProduced;
            }

            ProducingCompleteNoPreComplete(end);
        }
 private static void Copy(MemoryPoolIterator2 head, MemoryPoolIterator2 tail, ref MemoryPoolIterator2 writer)
 {
     while (!CompareIterators(ref head, ref tail))
     {
         writer.Put((byte)head.Take());
     }
 }
        private MemoryPoolIterator2 GetIterator(MemoryPoolIterator2 begin, int displacement)
        {
            var result = begin;
            for (int i = 0; i < displacement; ++i)
            {
                result.Take();
            }

            return result;
        }
        /// <summary>
        /// Read the next char and convert it into hexadecimal value.
        /// 
        /// The <paramref name="scan"/> iterator will be moved to the next
        /// byte no matter no matter whether the operation successes.
        /// </summary>
        /// <param name="scan">The value to read</param>
        /// <param name="end">The end of the sequence</param>
        /// <returns>The hexadecimal value if successes, otherwise -1.</returns>
        private static int ReadHex(ref MemoryPoolIterator2 scan, MemoryPoolIterator2 end)
        {
            if (CompareIterators(ref scan, ref end))
            {
                return -1;
            }

            var value = scan.Take();
            var isHead = (((value >= '0') && (value <= '9')) ||
                          ((value >= 'A') && (value <= 'F')) ||
                          ((value >= 'a') && (value <= 'f')));

            if (!isHead)
            {
                return -1;
            }

            if (value <= '9')
            {
                return value - '0';
            }
            else if (value <= 'F')
            {
                return (value - 'A') + 10;
            }
            else // a - f
            {
                return (value - 'a') + 10;
            }
        }
        public void ServerPipeListenForConnections()
        {
            var loop = new UvLoopHandle(_logger);
            var serverListenPipe = new UvPipeHandle(_logger);

            loop.Init(_uv);
            serverListenPipe.Init(loop, false);
            serverListenPipe.Bind(@"\\.\pipe\ServerPipeListenForConnections");
            serverListenPipe.Listen(128, (_1, status, error, _2) =>
            {
                var serverConnectionPipe = new UvPipeHandle(_logger);
                serverConnectionPipe.Init(loop, true);
                try
                {
                    serverListenPipe.Accept(serverConnectionPipe);
                }
                catch (Exception)
                {
                    serverConnectionPipe.Dispose();
                    return;
                }

                var writeRequest = new UvWriteReq(new KestrelTrace(new TestKestrelTrace()));
                writeRequest.Init(loop);
                var block = MemoryPoolBlock2.Create(
                    new ArraySegment<byte>(new byte[] { 1, 2, 3, 4 }),
                    dataPtr: IntPtr.Zero,
                    pool: null,
                    slab: null);
                var start = new MemoryPoolIterator2(block, 0);
                var end = new MemoryPoolIterator2(block, block.Data.Count);
                writeRequest.Write(
                    serverConnectionPipe,
                    start, 
                    end,
                    1,
                    (_3, status2, error2, _4) =>
                    {
                        writeRequest.Dispose();
                        serverConnectionPipe.Dispose();
                        serverListenPipe.Dispose();
                        block.Unpin();
                    },
                    null);

            }, null);

            var worker = new Thread(() =>
            {
                var loop2 = new UvLoopHandle(_logger);
                var clientConnectionPipe = new UvPipeHandle(_logger);
                var connect = new UvConnectRequest(new KestrelTrace(new TestKestrelTrace()));

                loop2.Init(_uv);
                clientConnectionPipe.Init(loop2, true);
                connect.Init(loop2);
                connect.Connect(clientConnectionPipe, @"\\.\pipe\ServerPipeListenForConnections", (_1, status, error, _2) =>
                {
                    var buf = loop2.Libuv.buf_init(Marshal.AllocHGlobal(8192), 8192);

                    connect.Dispose();
                    clientConnectionPipe.ReadStart(
                        (_3, cb, _4) => buf,
                        (_3, status2, _4) =>
                        {
                            if (status2 == 0)
                            {
                                clientConnectionPipe.Dispose();
                            }
                        },
                        null);
                }, null);
                loop2.Run();
                loop2.Dispose();
            });
            worker.Start();
            loop.Run();
            loop.Dispose();
            worker.Join();
        }
        /// <summary>
        /// Unescape the percent-encodings
        /// </summary>
        /// <param name="reader">The iterator point to the first % char</param>
        /// <param name="writer">The place to write to</param>
        /// <param name="end">The end of the sequence</param>
        private static bool DecodeCore(ref MemoryPoolIterator2 reader, ref MemoryPoolIterator2 writer, MemoryPoolIterator2 end)
        {
            // preserves the original head. if the percent-encodings cannot be interpreted as sequence of UTF-8 octets,
            // bytes from this till the last scanned one will be copied to the memory pointed by writer.
            var byte1 = UnescapePercentEncoding(ref reader, end);
            if (byte1 == -1)
            {
                return false;
            }

            if (byte1 <= 0x7F)
            {
                // first byte < U+007f, it is a single byte ASCII
                writer.Put((byte)byte1);
                return true;
            }

            int byte2 = 0, byte3 = 0, byte4 = 0;

            // anticipate more bytes
            var currentDecodeBits = 0;
            var byteCount = 1;
            var expectValueMin = 0;
            if ((byte1 & 0xE0) == 0xC0)
            {
                // 110x xxxx, expect one more byte
                currentDecodeBits = byte1 & 0x1F;
                byteCount = 2;
                expectValueMin = 0x80;
            }
            else if ((byte1 & 0xF0) == 0xE0)
            {
                // 1110 xxxx, expect two more bytes
                currentDecodeBits = byte1 & 0x0F;
                byteCount = 3;
                expectValueMin = 0x800;
            }
            else if ((byte1 & 0xF8) == 0xF0)
            {
                // 1111 0xxx, expect three more bytes
                currentDecodeBits = byte1 & 0x07;
                byteCount = 4;
                expectValueMin = 0x10000;
            }
            else
            {
                // invalid first byte
                return false;
            }

            var remainingBytes = byteCount - 1;
            while (remainingBytes > 0)
            {
                // read following three chars
                if (CompareIterators(ref reader, ref end))
                {
                    return false;
                }

                var nextItr = reader;
                var nextByte = UnescapePercentEncoding(ref nextItr, end);
                if (nextByte == -1)
                {
                    return false;
                }

                if ((nextByte & 0xC0) != 0x80)
                {
                    // the follow up byte is not in form of 10xx xxxx
                    return false;
                }

                currentDecodeBits = (currentDecodeBits << 6) | (nextByte & 0x3F);
                remainingBytes--;

                if (remainingBytes == 1 && currentDecodeBits >= 0x360 && currentDecodeBits <= 0x37F)
                {
                    // this is going to end up in the range of 0xD800-0xDFFF UTF-16 surrogates that
                    // are not allowed in UTF-8;
                    return false;
                }

                if (remainingBytes == 2 && currentDecodeBits >= 0x110)
                {
                    // this is going to be out of the upper Unicode bound 0x10FFFF.
                    return false;
                }

                reader = nextItr;
                if (byteCount - remainingBytes == 2)
                {
                    byte2 = nextByte;
                }
                else if (byteCount - remainingBytes == 3)
                {
                    byte3 = nextByte;
                }
                else if (byteCount - remainingBytes == 4)
                {
                    byte4 = nextByte;
                }
            }

            if (currentDecodeBits < expectValueMin)
            {
                // overlong encoding (e.g. using 2 bytes to encode something that only needed 1).
                return false;
            }

            // all bytes are verified, write to the output
            if (byteCount > 0)
            {
                writer.Put((byte)byte1);
            }
            if (byteCount > 1)
            {
                writer.Put((byte)byte2);
            }
            if (byteCount > 2)
            {
                writer.Put((byte)byte3);
            }
            if (byteCount > 3)
            {
                writer.Put((byte)byte4);
            }

            return true;
        }
        public static ArraySegment<byte> GetArraySegment(this MemoryPoolIterator2 start, MemoryPoolIterator2 end)
        {
            if (start.IsDefault || end.IsDefault)
            {
                return default(ArraySegment<byte>);
            }
            if (end.Block == start.Block)
            {
                return new ArraySegment<byte>(start.Block.Array, start.Index, end.Index - start.Index);
            }

            var length = start.GetLength(end);
            var array = new byte[length];
            start.CopyTo(array, 0, length, out length);
            return new ArraySegment<byte>(array, 0, length);
        }
        public int GetLength(MemoryPoolIterator2 end)
        {
            if (IsDefault || end.IsDefault)
            {
                return -1;
            }

            var block = _block;
            var index = _index;
            var length = 0;
            while (true)
            {
                if (block == end._block)
                {
                    return length + end._index - index;
                }
                else if (block.Next == null)
                {
                    throw new InvalidOperationException("end did not follow iterator");
                }
                else
                {
                    length += block.End - index;
                    block = block.Next;
                    index = block.Start;
                }
            }
        }
        /// <summary>
        /// Checks that up to 8 bytes from <paramref name="begin"/> correspond to a known HTTP method.
        /// </summary>
        /// <remarks>
        /// A "known HTTP method" can be an HTTP method name defined in the HTTP/1.1 RFC.
        /// Since all of those fit in at most 8 bytes, they can be optimally looked up by reading those bytes as a long. Once
        /// in that format, it can be checked against the known method. 
        /// The Known Methods (CONNECT, DELETE, GET, HEAD, PATCH, POST, PUT, OPTIONS, TRACE) are all less than 8 bytes 
        /// and will be compared with the required space. A mask is used if the Known method is less than 8 bytes.
        /// To optimize performance the GET method will be checked first.
        /// </remarks>
        /// <param name="begin">The iterator from which to start the known string lookup.</param>
        /// <param name="scan">If we found a valid method, then scan will be updated to new position</param>
        /// <param name="knownMethod">A reference to a pre-allocated known string, if the input matches any.</param>
        /// <returns><c>true</c> if the input matches a known string, <c>false</c> otherwise.</returns>
        public static bool GetKnownMethod(this MemoryPoolIterator2 begin, ref MemoryPoolIterator2 scan, out string knownMethod)
        {
            knownMethod = null;
            var value = begin.PeekLong();

            if ((value & _mask4Chars) == _httpGetMethodLong)
            {
                knownMethod = HttpGetMethod;
                scan.Skip(4);
                return true;
            }
            foreach (var x in _knownMethods)
            {
                if ((value & x.Item1) == x.Item2)
                {
                    knownMethod = x.Item3;
                    scan.Skip(knownMethod.Length + 1);
                    return true;
                }
            }

            return false;
        }
        public async Task SocketCanReadAndWrite()
        {
            var loop = new UvLoopHandle(_logger);
            loop.Init(_uv);
            var tcp = new UvTcpHandle(_logger);
            tcp.Init(loop);
            var address = ServerAddress.FromUrl("http://localhost:54321/");
            tcp.Bind(address);
            tcp.Listen(10, (_, status, error, state) =>
            {
                Console.WriteLine("Connected");
                var tcp2 = new UvTcpHandle(_logger);
                tcp2.Init(loop);
                tcp.Accept(tcp2);
                var data = Marshal.AllocCoTaskMem(500);
                tcp2.ReadStart(
                    (a, b, c) => tcp2.Libuv.buf_init(data, 500),
                    (__, nread, state2) =>
                    {
                        if (nread <= 0)
                        {
                            tcp2.Dispose();
                        }
                        else
                        {
                            for (var x = 0; x < 2; x++)
                            {
                                var req = new UvWriteReq(new KestrelTrace(new TestKestrelTrace()));
                                req.Init(loop);
                                var block = MemoryPoolBlock2.Create(
                                    new ArraySegment<byte>(new byte[] { 65, 66, 67, 68, 69 }),
                                    dataPtr: IntPtr.Zero,
                                    pool: null,
                                    slab: null);
                                var start = new MemoryPoolIterator2(block, 0);
                                var end = new MemoryPoolIterator2(block, block.Data.Count);
                                req.Write(
                                    tcp2,
                                    start,
                                    end,
                                    1,
                                    (_1, _2, _3, _4) =>
                                    {
                                        block.Unpin();
                                    },
                                    null);
                            }
                        }
                    },
                    null);
                tcp.Dispose();
            }, null);
            Console.WriteLine("Task.Run");
            var t = Task.Run(async () =>
            {
                var socket = new Socket(
                    AddressFamily.InterNetwork,
                    SocketType.Stream,
                    ProtocolType.Tcp);
#if DNX451
                await Task.Factory.FromAsync(
                    socket.BeginConnect,
                    socket.EndConnect,
                    new IPEndPoint(IPAddress.Loopback, 54321),
                    null,
                    TaskCreationOptions.None);
                await Task.Factory.FromAsync(
                    socket.BeginSend,
                    socket.EndSend,
                    new[] { new ArraySegment<byte>(new byte[] { 1, 2, 3, 4, 5 }) },
                    SocketFlags.None,
                    null,
                    TaskCreationOptions.None);
#else
                await socket.ConnectAsync(new IPEndPoint(IPAddress.Loopback, 54321));
                await socket.SendAsync(new[] { new ArraySegment<byte>(new byte[] { 1, 2, 3, 4, 5 }) },
                                       SocketFlags.None);
#endif
                socket.Shutdown(SocketShutdown.Send);
                var buffer = new ArraySegment<byte>(new byte[2048]);
                while (true)
                {
#if DNX451
                    var count = await Task.Factory.FromAsync(
                        socket.BeginReceive,
                        socket.EndReceive,
                        new[] { buffer },
                        SocketFlags.None,
                        null,
                        TaskCreationOptions.None);
#else
                    var count = await socket.ReceiveAsync(new[] { buffer }, SocketFlags.None);
#endif
                    Console.WriteLine("count {0} {1}",
                        count,
                        System.Text.Encoding.ASCII.GetString(buffer.Array, 0, count));
                    if (count <= 0) break;
                }
                socket.Dispose();
            });
            loop.Run();
            loop.Dispose();
            await t;
        }
        /// <summary>
        /// Checks 9 bytes from <paramref name="begin"/>  correspond to a known HTTP version.
        /// </summary>
        /// <remarks>
        /// A "known HTTP version" Is is either HTTP/1.0 or HTTP/1.1.
        /// Since those fit in 8 bytes, they can be optimally looked up by reading those bytes as a long. Once
        /// in that format, it can be checked against the known versions.
        /// The Known versions will be checked with the required '\r'.
        /// To optimize performance the HTTP/1.1 will be checked first.
        /// </remarks>
        /// <param name="begin">The iterator from which to start the known string lookup.</param>
        /// <param name="scan">If we found a valid method, then scan will be updated to new position</param>
        /// <param name="knownMethod">A reference to a pre-allocated known string, if the input matches any.</param>
        /// <returns><c>true</c> if the input matches a known string, <c>false</c> otherwise.</returns>
        public static bool GetKnownVersion(this MemoryPoolIterator2 begin, ref MemoryPoolIterator2 scan, out string knownVersion)
        {
            knownVersion = null;
            var value = begin.PeekLong();

            if (value == _http11VersionLong)
            {
                knownVersion = Http11Version;
                scan.Skip(8);
                if (scan.Take() == '\r')
                {
                    return true;
                }
            }
            else if (value == _http10VersionLong)
            {
                knownVersion = Http10Version;
                scan.Skip(8);
                if (scan.Take() == '\r')
                {
                    return true;
                }
            }

            knownVersion = null;
            return false;
        }
 protected void CopyToFast(ref MemoryPoolIterator2 output)
 {
     
         if (((_bits & 1L) != 0)) 
         { 
                 foreach (var value in _CacheControl)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 0, 17);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 2L) != 0)) 
         { 
             if (_rawConnection != null) 
             {
                 output.CopyFrom(_rawConnection, 0, _rawConnection.Length);
             } 
             else 
                 foreach (var value in _Connection)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 17, 14);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 4L) != 0)) 
         { 
             if (_rawDate != null) 
             {
                 output.CopyFrom(_rawDate, 0, _rawDate.Length);
             } 
             else 
                 foreach (var value in _Date)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 31, 8);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 8L) != 0)) 
         { 
                 foreach (var value in _KeepAlive)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 39, 14);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 16L) != 0)) 
         { 
                 foreach (var value in _Pragma)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 53, 10);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 32L) != 0)) 
         { 
                 foreach (var value in _Trailer)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 63, 11);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 64L) != 0)) 
         { 
             if (_rawTransferEncoding != null) 
             {
                 output.CopyFrom(_rawTransferEncoding, 0, _rawTransferEncoding.Length);
             } 
             else 
                 foreach (var value in _TransferEncoding)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 74, 21);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 128L) != 0)) 
         { 
                 foreach (var value in _Upgrade)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 95, 11);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 256L) != 0)) 
         { 
                 foreach (var value in _Via)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 106, 7);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 512L) != 0)) 
         { 
                 foreach (var value in _Warning)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 113, 11);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 1024L) != 0)) 
         { 
                 foreach (var value in _Allow)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 124, 9);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 2048L) != 0)) 
         { 
             if (_rawContentLength != null) 
             {
                 output.CopyFrom(_rawContentLength, 0, _rawContentLength.Length);
             } 
             else 
                 foreach (var value in _ContentLength)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 133, 18);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 4096L) != 0)) 
         { 
                 foreach (var value in _ContentType)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 151, 16);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 8192L) != 0)) 
         { 
                 foreach (var value in _ContentEncoding)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 167, 20);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 16384L) != 0)) 
         { 
                 foreach (var value in _ContentLanguage)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 187, 20);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 32768L) != 0)) 
         { 
                 foreach (var value in _ContentLocation)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 207, 20);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 65536L) != 0)) 
         { 
                 foreach (var value in _ContentMD5)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 227, 15);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 131072L) != 0)) 
         { 
                 foreach (var value in _ContentRange)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 242, 17);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 262144L) != 0)) 
         { 
                 foreach (var value in _Expires)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 259, 11);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 524288L) != 0)) 
         { 
                 foreach (var value in _LastModified)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 270, 17);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 1048576L) != 0)) 
         { 
                 foreach (var value in _AcceptRanges)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 287, 17);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 2097152L) != 0)) 
         { 
                 foreach (var value in _Age)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 304, 7);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 4194304L) != 0)) 
         { 
                 foreach (var value in _ETag)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 311, 8);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 8388608L) != 0)) 
         { 
                 foreach (var value in _Location)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 319, 12);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 16777216L) != 0)) 
         { 
                 foreach (var value in _ProxyAutheticate)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 331, 21);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 33554432L) != 0)) 
         { 
                 foreach (var value in _RetryAfter)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 352, 15);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 67108864L) != 0)) 
         { 
             if (_rawServer != null) 
             {
                 output.CopyFrom(_rawServer, 0, _rawServer.Length);
             } 
             else 
                 foreach (var value in _Server)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 367, 10);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 134217728L) != 0)) 
         { 
                 foreach (var value in _SetCookie)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 377, 14);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 268435456L) != 0)) 
         { 
                 foreach (var value in _Vary)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 391, 8);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 536870912L) != 0)) 
         { 
                 foreach (var value in _WWWAuthenticate)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 399, 20);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 1073741824L) != 0)) 
         { 
                 foreach (var value in _AccessControlAllowCredentials)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 419, 36);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 2147483648L) != 0)) 
         { 
                 foreach (var value in _AccessControlAllowHeaders)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 455, 32);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 4294967296L) != 0)) 
         { 
                 foreach (var value in _AccessControlAllowMethods)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 487, 32);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 8589934592L) != 0)) 
         { 
                 foreach (var value in _AccessControlAllowOrigin)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 519, 31);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 17179869184L) != 0)) 
         { 
                 foreach (var value in _AccessControlExposeHeaders)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 550, 33);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
         if (((_bits & 34359738368L) != 0)) 
         { 
                 foreach (var value in _AccessControlMaxAge)
                 {
                     if (value != null)
                     {
                         output.CopyFrom(_headerBytes, 583, 26);
                         output.CopyFromAscii(value);
                     }
                 }
         }
     
 }
        public unsafe static string GetAsciiString(this MemoryPoolIterator2 start, MemoryPoolIterator2 end)
        {
            if (start.IsDefault || end.IsDefault)
            {
                return null;
            }

            var length = start.GetLength(end);

            if (length == 0)
            {
                return null;
            }

            // Bytes out of the range of ascii are treated as "opaque data" 
            // and kept in string as a char value that casts to same input byte value
            // https://tools.ietf.org/html/rfc7230#section-3.2.4

            var inputOffset = start.Index;
            var block = start.Block;

            var asciiString = new string('\0', length);

            fixed (char* outputStart = asciiString)
            {
                var output = outputStart;
                var remaining = length;

                var endBlock = end.Block;
                var endIndex = end.Index;

                while (true)
                {
                    int following = (block != endBlock ? block.End : endIndex) - inputOffset;

                    if (following > 0)
                    {
                        fixed (byte* blockStart = block.Array)
                        {
                            var input = blockStart + inputOffset;
                            var i = 0;
                            while (i < following - 11)
                            {
                                i += 12;
                                *(output) = (char)*(input);
                                *(output + 1) = (char)*(input + 1);
                                *(output + 2) = (char)*(input + 2);
                                *(output + 3) = (char)*(input + 3);
                                *(output + 4) = (char)*(input + 4);
                                *(output + 5) = (char)*(input + 5);
                                *(output + 6) = (char)*(input + 6);
                                *(output + 7) = (char)*(input + 7);
                                *(output + 8) = (char)*(input + 8);
                                *(output + 9) = (char)*(input + 9);
                                *(output + 10) = (char)*(input + 10);
                                *(output + 11) = (char)*(input + 11);
                                output += 12;
                                input += 12;
                            }
                            if (i < following - 5)
                            {
                                i += 6;
                                *(output) = (char)*(input);
                                *(output + 1) = (char)*(input + 1);
                                *(output + 2) = (char)*(input + 2);
                                *(output + 3) = (char)*(input + 3);
                                *(output + 4) = (char)*(input + 4);
                                *(output + 5) = (char)*(input + 5);
                                output += 6;
                                input += 6;
                            }
                            if (i < following - 3)
                            {
                                i += 4;
                                *(output) = (char)*(input);
                                *(output + 1) = (char)*(input + 1);
                                *(output + 2) = (char)*(input + 2);
                                *(output + 3) = (char)*(input + 3);
                                output += 4;
                                input += 4;
                            }
                            while (i < following)
                            {
                                i++;
                                *output = (char)*input;
                                output++;
                                input++;
                            }
                        
                            remaining -= following;
                        }
                    }

                    if (remaining == 0)
                    {
                        break;
                    }

                    block = block.Next;
                    inputOffset = block.Start;
                }
            }

            return asciiString;
        }