示例#1
0
        public void SetPrefetchedBytes(byte[] bytes, int offset, int count)
        {
            // argument checks
            if (bytes == null)
            {
                throw new ArgumentNullException(nameof(bytes));
            }
            if (offset < 0 || bytes.Length < offset)
            {
                throw new ArgumentOutOfRangeException(nameof(offset));
            }
            if (count <= 0 || bytes.Length - offset < count || ComponentFactory.MemoryBlockCache.MemoryBlockSize < count)
            {
                // Note that 0-count is not allowed.
                throw new ArgumentOutOfRangeException(nameof(count));
            }

            // mark the given bytes on the source as prefetched bytes
            // These bytes are part of the next message.
            byte[] memoryBlock = ComponentFactory.AllocMemoryBlock();
            try {
                Buffer.BlockCopy(bytes, offset, memoryBlock, 0, count);

                this.prefetchedBytesLength = count;
                this.prefetchedBytes       = memoryBlock;
            } catch {
                ComponentFactory.FreeMemoryBlock(memoryBlock);
                throw;
            }

            return;
        }
示例#2
0
        protected override byte[] UpdateMemoryBlock(byte[] currentMemoryBlock)
        {
            // calculate the base offset of the next memory block
            int newBaseOffset = this.currentMemoryBlockBaseOffset;

            if (currentMemoryBlock == null)
            {
                Debug.Assert(newBaseOffset == 0);
            }
            else
            {
                int increment = currentMemoryBlock.Length;
                if (int.MaxValue - newBaseOffset < increment)
                {
                    // header size exceeds 2G
                    throw new Exception("The header size must be smaller than 2G bytes.");
                }
                newBaseOffset += currentMemoryBlock.Length;
            }

            // allocate a new memory block
            byte[] newMemoryBlock = this.prefetchedBytes;
            if (newMemoryBlock != null)
            {
                // there is prefetched bytes which were read in the previous message processing
                this.prefetchedBytes = null;
                Debug.Assert(0 < this.prefetchedBytesLength);
                // Do not clear this.prefetchedBytesLength, which is used at the next ReadBytes() call
            }
            else
            {
                newMemoryBlock = ComponentFactory.AllocMemoryBlock();
            }
            try {
                this.memoryBlocks.Add(newMemoryBlock);
            } catch {
                ComponentFactory.FreeMemoryBlock(newMemoryBlock);
                throw;
            }

            // update its state
            this.currentMemoryBlockBaseOffset = newBaseOffset;

            return(newMemoryBlock);
        }
示例#3
0
        private static void Forward(ICommunicationOwner owner, CommunicationSubType type)
        {
            // argument checks
            Debug.Assert(owner != null);
            IMessageIO io;

            switch (type)
            {
            case CommunicationSubType.UpStream:
                io = owner.RequestIO;
                break;

            case CommunicationSubType.DownStream:
                io = owner.ResponseIO;
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(type));
            }
            Debug.Assert(io != null);

            Stream input = io.Input;

            Debug.Assert(input != null);
            Stream output = io.Output;

            Debug.Assert(output != null);

            // forward bytes from the input to the output
            try {
                // notify the owner
                owner.OnTunnelingStarted(type);

                // forward bytes
                byte[] buf = ComponentFactory.AllocMemoryBlock();
                try {
                    do
                    {
                        int readCount = input.Read(buf, 0, buf.Length);
                        if (readCount <= 0)
                        {
                            // the end of the stream
                            break;
                        }
                        output.Write(buf, 0, readCount);
                        output.Flush();
                    } while (true);
                } catch (EndOfStreamException) {
                    // continue
                } finally {
                    ComponentFactory.FreeMemoryBlock(buf);
                }

                // notify the owner of its normal closing
                owner.OnTunnelingClosing(type, null);
            } catch (Exception exception) {
                // notify the owner of the exception
                try {
                    owner.OnTunnelingClosing(type, exception);
                } catch {
                    // continue
                }
                // continue
            }

            return;
        }
示例#4
0
 protected virtual byte[] UpdateMemoryBlock(byte[] currentMemoryBlock)
 {
     // by default, reuse one memory block
     return((currentMemoryBlock != null) ? currentMemoryBlock : ComponentFactory.AllocMemoryBlock());
 }