Пример #1
0
        public async Task <int> ReadBytesAsync(ArraySegment <byte> buffer, CancellationToken cancellationToken)
        {
            var timer          = new Stopwatch();
            var totalBytesRead = 0;

            try {
                await _readSemaphore.LockAsync( // serialize receiving on a given transport
                    async() => {
                    var stream = _stream;       // so if the socket is reconnected, we don't read partially from different sockets
                    var socket = _tcpSocket;
                    _configuration.OnReading?.Invoke(_endpoint, buffer.Count);
                    timer.Start();
                    while (totalBytesRead < buffer.Count && !cancellationToken.IsCancellationRequested)
                    {
                        var bytesRemaining = buffer.Count - totalBytesRead;
                        _log.Verbose(() => LogEvent.Create($"Reading ({bytesRemaining}? bytes) from {_endpoint}"));
                        _configuration.OnReadingBytes?.Invoke(_endpoint, bytesRemaining);
                        var bytesRead   = await stream.ReadAsync(buffer.Array, buffer.Offset + totalBytesRead, bytesRemaining, cancellationToken).ConfigureAwait(false);
                        totalBytesRead += bytesRead;
                        _configuration.OnReadBytes?.Invoke(_endpoint, bytesRemaining, bytesRead, timer.Elapsed);
                        _log.Verbose(() => LogEvent.Create($"Read {bytesRead} bytes from {_endpoint}"));

                        if (bytesRead <= 0 && socket.Available == 0)
                        {
                            _socket.Disconnect(socket);
                            var ex = new ConnectionException(_endpoint);
                            _configuration.OnDisconnected?.Invoke(_endpoint, ex);
                            throw ex;
                        }
                    }
                    timer.Stop();
                    _configuration.OnRead?.Invoke(_endpoint, totalBytesRead, timer.Elapsed);
                }, cancellationToken).ConfigureAwait(false);
            } catch (Exception ex) {
                timer.Stop();
                _configuration.OnReadFailed?.Invoke(_endpoint, buffer.Count, timer.Elapsed, ex);
                if (_disposeCount > 0)
                {
                    throw new ObjectDisposedException(nameof(SslTransport));
                }
                throw;
            }
            return(totalBytesRead);
        }
Пример #2
0
        private async Task ProcessReadTaskAsync(Stream stream, SocketPayloadReadTask readTask)
        {
            using (readTask) {
                var totalBytesRead = 0;
                var timer          = new Stopwatch();
                try {
                    _configuration.OnReading?.Invoke(Endpoint, readTask.ReadSize);
                    var buffer = new byte[readTask.ReadSize];
                    timer.Start();
                    while (totalBytesRead < readTask.ReadSize)
                    {
                        var readSize = readTask.ReadSize - totalBytesRead;

                        _log.Debug(() => LogEvent.Create($"Reading ({readSize}? bytes) from {Endpoint}"));
                        _configuration.OnReadingChunk?.Invoke(Endpoint, readTask.ReadSize, totalBytesRead, timer.Elapsed);
                        var bytesRead = await stream.ReadAsync(buffer, totalBytesRead, readSize, readTask.CancellationToken).ConfigureAwait(false);

                        totalBytesRead += bytesRead;
                        var remainingBytes = readTask.ReadSize - totalBytesRead;
                        _configuration.OnReadChunk?.Invoke(Endpoint, readTask.ReadSize, remainingBytes, bytesRead, timer.Elapsed);
                        _log.Debug(() => LogEvent.Create($"Read {bytesRead} bytes from {Endpoint}{(readTask.CancellationToken.IsCancellationRequested ? " (cancelled)" : "")}"));

                        if (bytesRead <= 0)
                        {
                            using (_client) {
                                _client = null;
                                if (_disposeToken.IsCancellationRequested)
                                {
                                    _configuration.OnReadFailed?.Invoke(Endpoint, readTask.ReadSize, timer.Elapsed, new TaskCanceledException());
                                    return;
                                }

                                throw new ConnectionException(Endpoint);
                            }
                        }
                    }
                    timer.Stop();
                    _configuration.OnRead?.Invoke(Endpoint, buffer, timer.Elapsed);

                    readTask.Tcs.TrySetResult(buffer);
                    totalBytesRead = 0;
                } catch (Exception ex) {
                    timer.Stop();
                    _configuration.OnReadFailed?.Invoke(Endpoint, readTask.ReadSize, timer.Elapsed, ex);

                    Exception exception = null;
                    if (_disposeToken.IsCancellationRequested)
                    {
                        exception = new ObjectDisposedException($"Object is disposing (TcpSocket for {Endpoint})", ex);
                    }
                    else if ((_client == null || _client.Connected == false) && !(ex is ConnectionException))
                    {
                        exception = new ConnectionException(Endpoint, ex);
                    }

                    if (totalBytesRead > 0)
                    {
                        readTask.Tcs.TrySetException(new PartialReadException(totalBytesRead, readTask.ReadSize, exception ?? ex));
                    }
                    else
                    {
                        readTask.Tcs.TrySetException(exception ?? ex);
                    }
                    if (_disposeToken.IsCancellationRequested)
                    {
                        return;
                    }
                    if (exception != null)
                    {
                        throw exception;
                    }
                    throw;
                }
            }
        }