Exemplo n.º 1
0
        /// <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 MemoryPoolIterator scan, MemoryPoolIterator 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);
        }
Exemplo n.º 2
0
        private void ProducingCompleteNoPreComplete(MemoryPoolIterator end)
        {
            MemoryPoolBlock 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(MemoryPoolIterator);
            }

            if (blockToReturn != null)
            {
                ThreadPool.QueueUserWorkItem(_returnBlocks, blockToReturn);
            }
        }
Exemplo n.º 3
0
 private static void Copy(MemoryPoolIterator head, MemoryPoolIterator tail, ref MemoryPoolIterator writer)
 {
     while (!CompareIterators(ref head, ref tail))
     {
         writer.Put((byte)head.Take());
     }
 }
Exemplo n.º 4
0
        public static int WriteBeginChunkBytes(ref MemoryPoolIterator start, int dataCount)
        {
            var chunkSegment = BeginChunkBytes(dataCount);

            start.CopyFrom(chunkSegment);
            return(chunkSegment.Count);
        }
        public void ConsumingComplete(
            MemoryPoolIterator consumed,
            MemoryPoolIterator examined)
        {
            MemoryPoolBlock returnStart = null;
            MemoryPoolBlock returnEnd   = null;

            lock (_sync)
            {
                if (!_disposed)
                {
                    if (!consumed.IsDefault)
                    {
                        // Compute lengthConsumed before modifying _head or consumed
                        var lengthConsumed = 0;
                        if (_bufferSizeControl != null)
                        {
                            lengthConsumed = new MemoryPoolIterator(_head).GetLength(consumed);
                        }

                        returnStart = _head;
                        returnEnd   = consumed.Block;
                        _head       = consumed.Block;
                        _head.Start = consumed.Index;

                        // Must call Subtract() after _head has been advanced, to avoid producer starting too early and growing
                        // buffer beyond max length.
                        _bufferSizeControl?.Subtract(lengthConsumed);
                    }

                    if (!examined.IsDefault &&
                        examined.IsEnd &&
                        RemoteIntakeFin == false &&
                        _awaitableError == null)
                    {
                        _manualResetEvent.Reset();

                        Interlocked.CompareExchange(
                            ref _awaitableState,
                            _awaitableIsNotCompleted,
                            _awaitableIsCompleted);
                    }
                }
                else
                {
                    returnStart = _head;
                    returnEnd   = null;
                    _head       = null;
                    _tail       = null;
                }

                ReturnBlocks(returnStart, returnEnd);

                if (!_consuming)
                {
                    throw new InvalidOperationException("No ongoing consuming operation to complete.");
                }
                _consuming = false;
            }
        }
        public void IncomingData(byte[] buffer, int offset, int count)
        {
            lock (_sync)
            {
                // Must call Add() before bytes are available to consumer, to ensure that Length is >= 0
                _bufferSizeControl?.Add(count);

                if (count > 0)
                {
                    if (_tail == null)
                    {
                        _tail = _memory.Lease();
                    }

                    var iterator = new MemoryPoolIterator(_tail, _tail.End);
                    iterator.CopyFrom(buffer, offset, count);

                    if (_head == null)
                    {
                        _head = _tail;
                    }

                    _tail = iterator.Block;
                }
                else
                {
                    RemoteIntakeFin = true;
                }

                Complete();
            }
        }
Exemplo n.º 7
0
        private void ProducingCompleteNoPreComplete(MemoryPoolIterator end)
        {
            MemoryPoolBlock blockToReturn = null;

            lock (_returnLock)
            {
                // Both ProducingComplete and WriteAsync should not call this method
                // if _lastStart was not set.
                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(MemoryPoolIterator);
            }

            if (blockToReturn != null)
            {
                _threadPool.UnsafeRun(_returnBlocks, blockToReturn);
            }
        }
Exemplo n.º 8
0
        public void IncomingData(byte[] buffer, int offset, int count)
        {
            lock (_sync)
            {
                if (count > 0)
                {
                    if (_tail == null)
                    {
                        _tail = _memory.Lease();
                    }

                    var iterator = new MemoryPoolIterator(_tail, _tail.End);
                    iterator.CopyFrom(buffer, offset, count);

                    if (_head == null)
                    {
                        _head = _tail;
                    }

                    _tail = iterator.Block;
                }
                else
                {
                    RemoteIntakeFin = true;
                }

                Complete();
            }
        }
        public void ConsumingOutOfOrderFailsGracefully()
        {
            var defultIter = new MemoryPoolIterator();

            // Calling ConsumingComplete without a preceding calling to ConsumingStart fails
            using (var socketInput = new SocketInput(null, null))
            {
                Assert.Throws <InvalidOperationException>(() => socketInput.ConsumingComplete(defultIter, defultIter));
            }

            // Calling ConsumingComplete twice in a row fails
            using (var socketInput = new SocketInput(null, null))
            {
                socketInput.ConsumingStart();
                socketInput.ConsumingComplete(defultIter, defultIter);
                Assert.Throws <InvalidOperationException>(() => socketInput.ConsumingComplete(defultIter, defultIter));
            }

            // Calling ConsumingStart twice in a row fails
            using (var socketInput = new SocketInput(null, null))
            {
                socketInput.ConsumingStart();
                Assert.Throws <InvalidOperationException>(() => socketInput.ConsumingStart());
            }
        }
Exemplo n.º 10
0
        /// <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 MemoryPoolIterator scan, MemoryPoolIterator 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);
            }
        }
Exemplo n.º 11
0
        public unsafe void Write(
            UvStreamHandle handle,
            MemoryPoolIterator start,
            MemoryPoolIterator 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;
            }
        }
        private MemoryPoolIterator GetIterator(MemoryPoolIterator begin, int displacement)
        {
            var result = begin;

            for (int i = 0; i < displacement; ++i)
            {
                result.Take();
            }

            return(result);
        }
Exemplo n.º 13
0
            public void Reset()
            {
                _lockedStart = default(MemoryPoolIterator);
                _lockedEnd   = default(MemoryPoolIterator);
                _bufferCount = 0;
                ByteCount    = 0;

                SocketShutdownSend = false;
                SocketDisconnect   = false;

                WriteStatus = 0;
                WriteError  = null;
            }
Exemplo n.º 14
0
        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 memory = new MemoryPool())
                using (var kestrelEngine = new KestrelEngine(mockLibuv, new TestServiceContext()))
                {
                    kestrelEngine.Start(count: 1);

                    var kestrelThread = kestrelEngine.Threads[0];
                    var socket        = new MockSocket(mockLibuv, kestrelThread.Loop.ThreadId, new TestKestrelTrace());
                    var trace         = new KestrelTrace(new TestKestrelTrace());
                    var ltp           = new LoggingThreadPool(trace);
                    var socketOutput  = new SocketOutput(kestrelThread, socket, memory, new MockConnection(), "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 MemoryPoolIterator(block2, block2.End);

                    socketOutput.ProducingComplete(end);

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

                    Assert.True(nBufferWh.Wait(1000));
                    Assert.Equal(2, nBuffers);

                    // Cleanup
                    var cleanupTask = socketOutput.WriteAsync(
                        default(ArraySegment <byte>), default(CancellationToken), socketDisconnect: true);
                }
        }
Exemplo n.º 15
0
        public void ProducingComplete(MemoryPoolIterator end)
        {
            Debug.Assert(!_lastStart.IsDefault);

            int bytesProduced, buffersIncluded;

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

            lock (_contextLock)
            {
                _numBytesPreCompleted += bytesProduced;
            }

            ProducingCompleteNoPreComplete(end);
        }
        public MemoryPoolIterator ProducingStart()
        {
            lock (_returnLock)
            {
                Debug.Assert(_lastStart.IsDefault);

                if (_tail == null)
                {
                    return(default(MemoryPoolIterator));
                }

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

                return(_lastStart);
            }
        }
Exemplo n.º 17
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 MemoryPoolIterator(head, head.Start);
                _lockedEnd   = new MemoryPoolIterator(tail, tail.End);

                BytesBetween(_lockedStart, _lockedEnd, out ByteCount, out _bufferCount);
            }
Exemplo n.º 18
0
        public void FindFirstEqualByteSlow()
        {
            var bytes = Enumerable.Repeat <byte>(0xff, Vector <byte> .Count).ToArray();

            for (int i = 0; i < Vector <byte> .Count; i++)
            {
                Vector <byte> vector = new Vector <byte>(bytes);
                Assert.Equal(i, MemoryPoolIterator.FindFirstEqualByteSlow(ref vector));
                bytes[i] = 0;
            }

            for (int i = 0; i < Vector <byte> .Count; i++)
            {
                bytes[i] = 1;
                Vector <byte> vector = new Vector <byte>(bytes);
                Assert.Equal(i, MemoryPoolIterator.FindFirstEqualByteSlow(ref vector));
                bytes[i] = 0;
            }
        }
Exemplo n.º 19
0
        public void ConsumingComplete(
            MemoryPoolIterator consumed,
            MemoryPoolIterator examined)
        {
            lock (_sync)
            {
                MemoryPoolBlock returnStart = null;
                MemoryPoolBlock returnEnd   = null;

                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();

                    Interlocked.CompareExchange(
                        ref _awaitableState,
                        _awaitableIsNotCompleted,
                        _awaitableIsCompleted);
                }

                while (returnStart != returnEnd)
                {
                    var returnBlock = returnStart;
                    returnStart = returnStart.Next;
                    returnBlock.Pool.Return(returnBlock);
                }

                if (Interlocked.CompareExchange(ref _consumingState, 0, 1) != 1)
                {
                    throw new InvalidOperationException("No ongoing consuming operation to complete.");
                }
            }
        }
Exemplo n.º 20
0
 public void CopyTo(ref MemoryPoolIterator output)
 {
     CopyToFast(ref output);
     if (MaybeUnknown != null)
     {
         foreach (var kv in MaybeUnknown)
         {
             foreach (var value in kv.Value)
             {
                 if (value != null)
                 {
                     output.CopyFrom(_CrLf, 0, 2);
                     output.CopyFromAscii(kv.Key);
                     output.CopyFrom(_colonSpace, 0, 2);
                     output.CopyFromAscii(value);
                 }
             }
         }
     }
 }
Exemplo n.º 21
0
        private static void BytesBetween(MemoryPoolIterator start, MemoryPoolIterator 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++;
        }
        public void ProducingComplete(MemoryPoolIterator end)
        {
            var block = _producingBlock;

            while (block != end.Block)
            {
                // If we don't handle an exception from _outputStream.Write() here, we'll leak memory blocks.
                if (_canWrite)
                {
                    try
                    {
                        _outputStream.Write(block.Data.Array, block.Data.Offset, block.Data.Count);
                    }
                    catch (Exception ex)
                    {
                        _canWrite = false;
                        _logger.ConnectionError(_connectionId, ex);
                    }
                }

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

            if (_canWrite)
            {
                try
                {
                    _outputStream.Write(end.Block.Array, end.Block.Data.Offset, end.Index - end.Block.Data.Offset);
                }
                catch (Exception ex)
                {
                    _canWrite = false;
                    _logger.ConnectionError(_connectionId, ex);
                }
            }

            end.Block.Pool.Return(end.Block);
        }
Exemplo n.º 23
0
        public MemoryPoolIterator ProducingStart()
        {
            lock (_returnLock)
            {
                Debug.Assert(_lastStart.IsDefault);

                if (_closed)
                {
                    return(default(MemoryPoolIterator));
                }

                if (_tail == null)
                {
                    _head = _thread.Memory.Lease();
                    _tail = _head;
                }

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

                return(_lastStart);
            }
        }
Exemplo n.º 24
0
        /// <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 MemoryPoolIterator Unescape(MemoryPoolIterator start, MemoryPoolIterator 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 async Task SocketCanReadAndWrite()
        {
            var loop = new UvLoopHandle(_logger);

            loop.Init(_uv);
            var tcp = new UvTcpHandle(_logger);

            tcp.Init(loop, (a, b) => { });
            var address = ServerAddress.FromUrl($"http://127.0.0.1:0/");

            tcp.Bind(address);
            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),
                    (__, 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 pool = new MemoryPool();
                            var block = pool.Lease();
                            block.GetIterator().CopyFrom(new ArraySegment <byte>(new byte[] { 65, 66, 67, 68, 69 }));

                            var start = new MemoryPoolIterator(block, 0);
                            var end   = new MemoryPoolIterator(block, block.Data.Count);
                            req.Write(
                                tcp2,
                                start,
                                end,
                                1,
                                (_1, _2, _3, _4) =>
                            {
                                pool.Return(block);
                                pool.Dispose();
                            },
                                null);
                        }
                    }
                },
                    null);
                tcp.Dispose();
            }, null);
            var t = Task.Run(async() =>
            {
                var socket = TestConnection.CreateConnectedLoopbackSocket(port);
#if NET451
                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.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 NET451
                    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
                    if (count <= 0)
                    {
                        break;
                    }
                }
                socket.Dispose();
            });

            loop.Run();
            loop.Dispose();
            await t;
        }
Exemplo n.º 26
0
        public void ConsumingComplete(
            MemoryPoolIterator consumed,
            MemoryPoolIterator examined)
        {
            bool            isConsuming;
            MemoryPoolBlock returnStart = null;
            MemoryPoolBlock returnEnd   = null;

            lock (_sync)
            {
                if (!_disposed)
                {
                    if (!consumed.IsDefault)
                    {
                        // Compute lengthConsumed before modifying _head or consumed
                        var lengthConsumed = 0;
                        if (_bufferSizeControl != null)
                        {
                            lengthConsumed = new MemoryPoolIterator(_head).GetLength(consumed);
                        }

                        returnStart = _head;

                        var consumedAll = !consumed.IsDefault && consumed.IsEnd;
                        if (consumedAll && _pinned != _tail)
                        {
                            // Everything has been consumed and no data is being written to the
                            // _tail block, so return all blocks between _head and _tail inclusive.
                            _head = null;
                            _tail = null;
                        }
                        else
                        {
                            returnEnd   = consumed.Block;
                            _head       = consumed.Block;
                            _head.Start = consumed.Index;
                        }

                        // Must call Subtract() after _head has been advanced, to avoid producer starting too early and growing
                        // buffer beyond max length.
                        _bufferSizeControl?.Subtract(lengthConsumed);
                    }

                    // If _head is null, everything has been consumed and examined.
                    var examinedAll = (!examined.IsDefault && examined.IsEnd) || _head == null;
                    if (examinedAll && ReadingInput)
                    {
                        _manualResetEvent.Reset();

                        Interlocked.CompareExchange(
                            ref _awaitableState,
                            _awaitableIsNotCompleted,
                            _awaitableIsCompleted);
                    }
                }
                else
                {
                    // Dispose won't have returned the blocks if we were consuming, so return them now
                    returnStart = _head;
                    _head       = null;
                    _tail       = null;
                }

                isConsuming = _consuming;
                _consuming  = false;
            }

            ReturnBlocks(returnStart, returnEnd);

            if (!isConsuming)
            {
                throw new InvalidOperationException("No ongoing consuming operation to complete.");
            }
        }
Exemplo n.º 27
0
        public static MemoryPoolIterator Add(this MemoryPoolIterator iterator, int count)
        {
            int actual;

            return(iterator.CopyTo(new byte[count], 0, count, out actual));
        }
Exemplo n.º 28
0
        /// <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 MemoryPoolIterator reader, ref MemoryPoolIterator writer, MemoryPoolIterator 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 == 0)
            {
                throw BadHttpRequestException.GetException(RequestRejectionReason.PathContainsNullCharacters);
            }

            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);
        }
Exemplo n.º 29
0
        public void ServerPipeListenForConnections()
        {
            const string pipeName = @"\\.\pipe\ServerPipeListenForConnections";

            var loop             = new UvLoopHandle(_logger);
            var serverListenPipe = new UvPipeHandle(_logger);

            loop.Init(_uv);
            serverListenPipe.Init(loop, (a, b) => { }, false);
            serverListenPipe.Bind(pipeName);
            serverListenPipe.Listen(128, (backlog, status, error, state) =>
            {
                var serverConnectionPipe = new UvPipeHandle(_logger);
                serverConnectionPipe.Init(loop, (a, b) => { }, true);

                try
                {
                    serverListenPipe.Accept(serverConnectionPipe);
                }
                catch (Exception)
                {
                    serverConnectionPipe.Dispose();
                    return;
                }

                var writeRequest = new UvWriteReq(new KestrelTrace(new TestKestrelTrace()));
                writeRequest.Init(loop);

                var pool  = new MemoryPool();
                var block = pool.Lease();
                block.GetIterator().CopyFrom(new ArraySegment <byte>(new byte[] { 1, 2, 3, 4 }));

                var start = new MemoryPoolIterator(block, 0);
                var end   = new MemoryPoolIterator(block, block.Data.Count);
                writeRequest.Write(
                    serverConnectionPipe,
                    start,
                    end,
                    1,
                    (handle, status2, error2, state2) =>
                {
                    writeRequest.Dispose();
                    serverConnectionPipe.Dispose();
                    serverListenPipe.Dispose();
                    pool.Return(block);
                    pool.Dispose();
                },
                    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, (a, b) => { }, true);
                connect.Init(loop2);
                connect.Connect(clientConnectionPipe, pipeName, (handle, status, error, state) =>
                {
                    var buf = loop2.Libuv.buf_init(Marshal.AllocHGlobal(8192), 8192);
                    connect.Dispose();

                    clientConnectionPipe.ReadStart(
                        (handle2, cb, state2) => buf,
                        (handle2, status2, state2) =>
                    {
                        if (status2 == Constants.EOF)
                        {
                            clientConnectionPipe.Dispose();
                        }
                    },
                        null);
                }, null);
                loop2.Run();
                loop2.Dispose();
            });

            worker.Start();
            loop.Run();
            loop.Dispose();
            worker.Join();
        }
Exemplo n.º 30
0
 private static bool CompareIterators(ref MemoryPoolIterator lhs, ref MemoryPoolIterator rhs)
 {
     // uses ref parameter to save cost of copying
     return((lhs.Block == rhs.Block) && (lhs.Index == rhs.Index));
 }