예제 #1
0
 void SerializeError(RecyclableMemoryStream response, string error)
 {
     response.Position = 0;
     response.SetLength(0);
     _serializer.SerializeException(response, error);
     response.Position = 0;
 }
예제 #2
0
        private RecyclableMemoryStream Encrypt(byte[] buffer, long bufferlength, int size, out int sizePadded)
        {
            sizePadded = size + (RijndaelStream.AES_KEY.Length - (size % RijndaelStream.AES_KEY.Length));
            RecyclableMemoryStream result = new RecyclableMemoryStream();

            result.SetLength(sizePadded);
            byte[] temp = new byte[sizePadded];

            unsafe
            {
                fixed(byte *source = buffer, dest = temp)
                {
                    for (int i = 0; i < bufferlength; i++)
                    {
                        dest[i] = source[i];
                    }

                    using (Rijndael aes = Rijndael.Create())
                    {
                        aes.Mode = CipherMode.ECB;
                        using (ICryptoTransform encrypt = aes.CreateEncryptor(RijndaelStream.RAW_AES_KEY, new byte[16]))
                            encrypt.TransformBlock(temp, 0, sizePadded, result.GetBuffer(), 0);
                    }
                }
            }
            result.Position = 0;
            return(result);
        }
        public void CanDecreaseLength()
        {
            using var stream = new RecyclableMemoryStream();
            stream.WriteByte(0xCA);
            stream.WriteByte(0xFE);
            Assert.That(stream.Length, Is.EqualTo(2));
            Assert.That(stream.Position, Is.EqualTo(2));

            stream.SetLength(1);

            Assert.That(stream.Length, Is.EqualTo(1));
            Assert.That(stream.Position, Is.EqualTo(1));
        }
        public void UpdatedLongBufferIsClean()
        {
            var stream = new RecyclableMemoryStream();

            stream.WriteByte(0x42);
            stream.SetLength(11);
            Assert.That(stream.Length, Is.EqualTo(11));

            stream.Position = 0;
            Assert.That(stream.ReadByte(), Is.EqualTo(0x42));
            for (int i = 0; i < 10; i++)
            {
                Assert.That(stream.ReadByte(), Is.EqualTo(0));
            }

            stream.SetLength(80 * 1024);
            stream.Position = 1;
            for (int i = 1; i < stream.Length; i++)
            {
                Assert.That(stream.ReadByte(), Is.EqualTo(0));
            }

            stream.Dispose();
        }
예제 #5
0
        /// <summary>
        ///     Remove everything used for the last message
        /// </summary>
        public void Clear()
        {
            _bytesTransferred = 0;
            _bytesLeftToSend  = 0;
            _payloadPosition  = 0;
            _contentLengths   = null;
            if (_disposeBodyStream)
            {
                //bodyStream is null for channels that connected
                //but never sent a message.

                _bodyStream?.Dispose();
                _bodyStream = null;
            }

            _headerStream.SetLength(0);
            _contentStream.SetLength(0);

            _headerIsSent      = _headerCreated = false;
            _message           = null;
            _disposeBodyStream = false;
        }
        public void PublicMethodThrowAfterDispose()
        {
            var stream = new RecyclableMemoryStream();

            stream.Dispose();

            byte[] buffer = new byte[1];
            Assert.That(
                () => stream.SetLength(10),
                Throws.InstanceOf <ObjectDisposedException>());
            Assert.That(
                () => stream.WriteByte(0x00),
                Throws.InstanceOf <ObjectDisposedException>());
            Assert.That(
                () => stream.Write(buffer, 0, 1),
                Throws.InstanceOf <ObjectDisposedException>());
            Assert.That(
                () => stream.ReadByte(),
                Throws.InstanceOf <ObjectDisposedException>());
            Assert.That(
                () => stream.Read(buffer, 0, 1),
                Throws.InstanceOf <ObjectDisposedException>());
        }
예제 #7
0
        private void RunWriteQueueAction()
        {
            //Dequeue all items until threshold is passed
            long totalLength = 0;
            RecyclableMemoryStream stream = null;
            var timestamp = GetTimestamp();

            while (totalLength < Connection.CoalescingThreshold)
            {
                OperationState state = null;
                while (_writeQueue.TryDequeue(out var tempState))
                {
                    if (tempState.CanBeWritten())
                    {
                        state = tempState;
                        break;
                    }

                    DecrementInFlight();
                }

                if (state == null)
                {
                    //No more items in the write queue
                    break;
                }

                if (!_freeOperations.TryPop(out short streamId))
                {
                    //Queue it up for later.
                    _writeQueue.Enqueue(state);
                    //When receiving the next complete message, we can process it.
                    Connection.Logger.Info("Enqueued, no streamIds available. If this message is recurrent consider configuring more connections per host or lower the pressure");
                    break;
                }
                Connection.Logger.Verbose("Sending #{0} for {1} to {2}", streamId, state.Request.GetType().Name, EndPoint.EndpointFriendlyName);
                if (_isCanceled)
                {
                    DecrementInFlight();
                    state.InvokeCallback(RequestError.CreateClientError(new SocketException((int)SocketError.NotConnected), true), timestamp);
                    break;
                }
                _pendingOperations.AddOrUpdate(streamId, state, (k, oldValue) => state);
                var startLength = stream?.Length ?? 0;
                try
                {
                    //lazy initialize the stream
                    stream = stream ?? (RecyclableMemoryStream)Configuration.BufferPool.GetStream(Connection.StreamWriteTag);
                    var frameLength = state.WriteFrame(streamId, stream, Serializer, timestamp);
                    _connectionObserver.OnBytesSent(frameLength);
                    totalLength += frameLength;
                }
                catch (Exception ex)
                {
                    //There was an error while serializing or begin sending
                    Connection.Logger.Error(ex);
                    //The request was not written, clear it from pending operations
                    RemoveFromPending(streamId);
                    //Callback with the Exception
                    state.InvokeCallback(RequestError.CreateClientError(ex, true), timestamp);

                    //Reset the stream to before we started writing this frame
                    stream?.SetLength(startLength);
                    break;
                }
            }
            if (totalLength == 0L)
            {
                // Nothing to write, set the queue as not running
                Interlocked.CompareExchange(ref _writeState, Connection.WriteStateInit, Connection.WriteStateRunning);
                // Until now, we were preventing other threads to running the queue.
                // Check if we can now write:
                // a read could have finished (freeing streamIds) or new request could have been added to the queue
                if (!_freeOperations.IsEmpty && !_writeQueue.IsEmpty)
                {
                    //The write queue is not empty
                    //An item was added to the queue but we were running: try to launch a new queue
                    RunWriteQueue();
                }
                if (stream != null)
                {
                    //The stream instance could be created if there was an exception while generating the frame
                    stream.Dispose();
                }
                return;
            }
            //Write and close the stream when flushed
            // ReSharper disable once PossibleNullReferenceException : if totalLength > 0 the stream is initialized
            _tcpSocket.Write(stream, () => stream.Dispose());
        }
예제 #8
0
        async Task IRequestHandler.HandleRequest(IRequest req)
        {
            Exception  ex     = null;
            object     result = null;
            MethodCall call   = null;

            try
            {
                if (req.Data is RecyclableMemoryStream || req.Data is MemoryStream)
                {
                    call = _serializer.DeserializeCall(req.Data, _binder, _selector, req.Context);
                }
                else
                {
                    using var copy = new RecyclableMemoryStream(StreamPool.Shared);
                    await req.Data.CopyToAsync(copy);

                    req.Data.Dispose();
                    copy.Position = 0;
                    call          = _serializer.DeserializeCall(copy, _binder, _selector, req.Context);
                }
            }
            catch (Exception e)
            {
                ex = e;
            }
            if (call != null)
            {
                object res = null;
                try
                {
                    if (_interceptor != null)
                    {
                        res = _interceptor.Intercept(call, req.Context,
                                                     () => ConvertToTask(call.Method.Invoke(call.Target, call.Arguments)));
                    }
                    else
                    {
                        res = call.Method.Invoke(call.Target, call.Arguments);
                    }
                }
                catch (Exception e)
                {
                    ex = e;
                }
                if (res != null)
                {
                    var task = res as Task;
                    if (task == null)
                    {
                        result = res;
                    }
                    else
                    {
                        try
                        {
                            await task;
                            if (call.Method.ReturnType != typeof(Task))
                            {
                                result = task.GetType().GetProperty("Result")?.GetValue(task);
                            }
                        }
                        catch (Exception e)
                        {
                            ex = e;
                        }
                    }
                }
            }

            using var response = new RecyclableMemoryStream(StreamPool.Shared);
            if (ex == null)
            {
                try
                {
                    _serializer.SerializeResult(response, result);
                    response.Position = 0;
                }
                catch (Exception e)
                {
                    ex = e;
                }
            }

            if (ex != null)
            {
                response.Position = 0;
                response.SetLength(0);
                _serializer.SerializeException(response, ex.ToString());
                response.Position = 0;
            }

            try
            {
                await req.RespondAsync(response);
            }
            catch
            {
                //TODO: redirect it somewhere?
            }
        }
 public void CanIncreaseLength()
 {
     using var stream = new RecyclableMemoryStream();
     Assert.That(() => stream.SetLength(4), Throws.Nothing);
     Assert.That(stream.Length, Is.EqualTo(4));
 }