Example #1
0
        private async Task ListenAsync(CancellationToken cancellationToken)
        {
            try
            {
                while (!cancellationToken.IsCancellationRequested && WebSocket.State == WebSocketState.Open)
                {
                    try
                    {
                        while (true)
                        {
                            var buffer        = new ArraySegment <byte>(_arrayPool.Rent(_bufferSize));
                            var receiveResult =
                                await WebSocket.ReceiveAsync(buffer, cancellationToken).ConfigureAwait(false);

                            if (receiveResult.MessageType == WebSocketMessageType.Close)
                            {
                                await HandleCloseMessageAsync(receiveResult);

                                break;
                            }

                            if (receiveResult.MessageType != _webSocketMessageType)
                            {
                                CloseStatus            = WebSocketCloseStatus.InvalidMessageType;
                                CloseStatusDescription = "An unsupported message type was received";
                                throw new InvalidOperationException(CloseStatusDescription);
                            }

                            if (_jsonBuffer.Buffer.Length < receiveResult.Count + _jsonBuffer.BufferCurPos)
                            {
                                _jsonBuffer.IncreaseBuffer();
                            }

                            Buffer.BlockCopy(buffer.Array, 0, _jsonBuffer.Buffer, _jsonBuffer.BufferCurPos, receiveResult.Count);
                            _arrayPool.Return(buffer.Array, true);

                            _jsonBuffer.BufferCurPos += receiveResult.Count;
                            if (receiveResult.EndOfMessage)
                            {
                                break;
                            }
                        }

                        byte[] jsonBytes;
                        if (_jsonBuffer.TryExtractJsonFromBuffer(out jsonBytes))
                        {
                            var envelopeJson = Encoding.UTF8.GetString(jsonBytes);

                            if (_traceWriter != null &&
                                _traceWriter.IsEnabled)
                            {
                                await _traceWriter.TraceAsync(envelopeJson, DataOperation.Receive).ConfigureAwait(false);
                            }
                            var envelope = _envelopeSerializer.Deserialize(envelopeJson);
                            await _receivedEnvelopeBufferBlock.SendAsync(envelope, cancellationToken);
                        }
                    }
                    catch (OperationCanceledException) when(cancellationToken.IsCancellationRequested)
                    {
                        break;
                    }
                    catch (Exception ex)
                    {
                    }
                }
            }
            finally
            {
                StopListenerTask();
            }
        }
Example #2
0
        /// <summary>
        /// Reads one envelope from the stream.
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public override async Task <Envelope> ReceiveAsync(CancellationToken cancellationToken)
        {
            if (_stream == null)
            {
                throw new InvalidOperationException("The stream was not initialized. Call OpenAsync first.");
            }
            if (!_stream.CanRead)
            {
                throw new InvalidOperationException("Invalid stream state");
            }

            await _receiveSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);

            try
            {
                Envelope envelope = null;

                while (envelope == null)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    envelope = await GetEnvelopeFromBufferAsync().ConfigureAwait(false);

                    if (envelope == null && CanRead)
                    {
                        // The NetworkStream ReceiveAsync method doesn't supports cancellation
                        // http://stackoverflow.com/questions/21468137/async-network-operations-never-finish
                        // http://referencesource.microsoft.com/#mscorlib/system/io/stream.cs,421
                        var readTask = _stream
                                       .ReadAsync(
                            _jsonBuffer.Buffer,
                            _jsonBuffer.BufferCurPos,
                            _jsonBuffer.Buffer.Length - _jsonBuffer.BufferCurPos,
                            cancellationToken);

                        while (!readTask.IsCompleted && CanRead)
                        {
                            cancellationToken.ThrowIfCancellationRequested();

                            await Task
                            .WhenAny(
                                readTask,
                                Task.Delay(ReadTimeout, cancellationToken))
                            .ConfigureAwait(false);
                        }

                        // If is not possible to read, closes the transport and returns
                        if (!readTask.IsCompleted)
                        {
                            await CloseWithTimeoutAsync().ConfigureAwait(false);

                            break;
                        }

                        var read = await readTask.ConfigureAwait(false);

                        // https://msdn.microsoft.com/en-us/library/hh193669(v=vs.110).aspx
                        if (read == 0)
                        {
                            await CloseWithTimeoutAsync().ConfigureAwait(false);

                            break;
                        }

                        _jsonBuffer.BufferCurPos += read;

                        if (_jsonBuffer.BufferCurPos >= _jsonBuffer.Buffer.Length)
                        {
                            _jsonBuffer.IncreaseBuffer();
                        }
                    }
                }

                return(envelope);
            }
            catch (BufferOverflowException)
            {
                await TraceAsync($"{nameof(RemoteEndPoint)}: {RemoteEndPoint} - BufferOverflow: {Encoding.UTF8.GetString(_jsonBuffer.Buffer)}", DataOperation.Error).ConfigureAwait(false);
                await CloseWithTimeoutAsync().ConfigureAwait(false);

                throw;
            }
            finally
            {
                _receiveSemaphore.Release();
            }
        }
Example #3
0
        /// <summary>
        /// Reads one envelope from the stream.
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public override async Task <Envelope> ReceiveAsync(CancellationToken cancellationToken)
        {
            if (_stream == null)
            {
                throw new InvalidOperationException("The stream was not initialized. Call OpenAsync first.");
            }
            if (!_stream.CanRead)
            {
                throw new InvalidOperationException("Invalid stream state");
            }

            try
            {
                Envelope envelope = null;

                while (envelope == null)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    envelope = await GetEnvelopeFromBufferAsync().ConfigureAwait(false);

                    if (envelope == null && CanRead)
                    {
                        // The NetworkStream ReadAsync method doesn't supports cancellation
                        // http://stackoverflow.com/questions/21468137/async-network-operations-never-finish
                        // http://referencesource.microsoft.com/#mscorlib/system/io/stream.cs,421

                        // This is no longer true for .NET Core 3.0
                        // https://github.com/dotnet/corefx/pull/36516
                        // The problem persists only with ConnectAsync operations:
                        // https://github.com/dotnet/corefx/issues/37118
                        var read = await _stream
                                   .ReadAsync(
                            _jsonBuffer.Buffer,
                            _jsonBuffer.BufferCurPos,
                            _jsonBuffer.Buffer.Length - _jsonBuffer.BufferCurPos,
                            cancellationToken)
                                   .ConfigureAwait(false);

                        // https://msdn.microsoft.com/en-us/library/hh193669(v=vs.110).aspx
                        if (read == 0)
                        {
                            await CloseWithTimeoutAsync().ConfigureAwait(false);

                            break;
                        }

                        _jsonBuffer.BufferCurPos += read;

                        if (_jsonBuffer.BufferCurPos >= _jsonBuffer.Buffer.Length)
                        {
                            _jsonBuffer.IncreaseBuffer();
                        }
                    }
                }

                return(envelope);
            }
            catch (BufferOverflowException)
            {
                await TraceAsync($"{nameof(RemoteEndPoint)}: {RemoteEndPoint} - BufferOverflow: {Encoding.UTF8.GetString(_jsonBuffer.Buffer)}", DataOperation.Error).ConfigureAwait(false);
                await CloseWithTimeoutAsync().ConfigureAwait(false);

                throw;
            }
        }