示例#1
0
        private static int ReadIncomingMsgs()
        {
            Task <int> readTask = readStream?.ReadAsync(tempBytes, 0, tempBytes.Length, readCancellationToken.Token);
            TimeSpan   ts       = TimeSpan.FromMilliseconds(100);

            for (int i = 0; i < 150; i++)
            {
                if (shutDown)
                {
                    readCancellationToken?.Cancel();
                    shutDown = true;
                    return(-1);
                }

                if ((readTask?.IsCompleted ?? true) || (readTask?.Wait(ts) ?? true))
                {
                    break;
                }
            }

            if (readTask == null || !readTask.IsCompleted)
            {
                readCancellationToken?.Cancel();
                shutDown = true;
                return(-1);
            }

            if (readTask.Status != TaskStatus.RanToCompletion)
            {
                shutDown = true;
                return(-1);
            }

            return(readTask.Result);
        }
        /// <summary>
        ///     Waits for the next command sent by the server.
        /// </summary>
        /// <returns>The command sent by the server.</returns>
        public virtual async Task<ServerCommandData> ReceiveAsync()
        {
            AssertNotDisposed();

            while (true)
            {
                if (_buffer.TryPop(out var command))
                    return command;

                try
                {
                    var task = _stream?.ReadAsync(_readBuffer, 0, _readBuffer.Length, _source.Token);

                    if (task == null)
                        throw new StreamCommunicationClientClosedException();

                    var len = await task;

                    if (_stream == null)
                        throw new StreamCommunicationClientClosedException();

                    if (_readBuffer.Length == len)
                    {
                        CoreLog.Log(CoreLogLevel.Error, "Network buffer overflow detected!");
                    }

                    _buffer.Push(_readBuffer, 0, len);
                }
                catch (TaskCanceledException)
                {
                    throw new StreamCommunicationClientClosedException();
                }
            }
        }
        public async Task ConnectToServerAsync(string msg)
        {
            try
            {
                _client = new TcpClient();
                await _client.ConnectAsync(_endPoint.Address, _endPoint.Port);

                Stream stream = null;
                if (!string.IsNullOrWhiteSpace(SSLServerName))
                {
                    SslStream sslStream =
                        new SslStream(_client.GetStream(), false,
                                      new RemoteCertificateValidationCallback(CertificateValidationCallback));
                    sslStream.AuthenticateAsClient(SSLServerName);
                    DisplaySSLInformation(SSLServerName, sslStream, true);
                    stream = sslStream;
                }
                else
                {
                    stream = _client.GetStream();
                }
                using (stream)
                {
                    // Get the bytes to send for the message
                    byte[] bytes = Encoding.ASCII.GetBytes(msg);

                    // send message
                    Console.WriteLine($"Sending message to server: {msg}");
                    await stream?.WriteAsync(bytes, 0, bytes.Length);

                    // Get the response
                    // Buffer to store the response bytes.
                    bytes = new byte[1024];

                    // Display the response
                    int bytesRead = await stream?.ReadAsync(bytes, 0, bytes.Length);

                    string serverResponse = Encoding.ASCII.GetString(bytes, 0, bytesRead);
                    Console.WriteLine($"Server said: {serverResponse}");
                }
            }
            catch (SocketException se)
            {
                Console.WriteLine($"There was an error talking to the server: {se}");
            }
            finally
            {
                Dispose();
            }
        }
示例#4
0
        /// <summary>
        ///     Waits for the next command sent by the server.
        /// </summary>
        /// <returns>The command sent by the server.</returns>
        public virtual async Task <ServerCommandData> ReceiveAsync()
        {
            AssertNotDisposed();

            while (true)
            {
                if (_buffer.TryPop(out var command))
                {
                    return(command);
                }

                try
                {
                    var task = _stream?.ReadAsync(_readBuffer, 0, _readBuffer.Length, _source.Token);

                    if (task == null)
                    {
                        throw new StreamCommunicationClientClosedException();
                    }

                    var len = await task;

                    if (_stream == null)
                    {
                        throw new StreamCommunicationClientClosedException();
                    }

                    if (_readBuffer.Length == len)
                    {
                        CoreLog.Log(CoreLogLevel.Error, "Network buffer overflow detected!");

                        // TODO: Could try and detect first valid command, but that could mean some vital commands were lost.
                    }

                    _buffer.Push(_readBuffer, 0, len);
                }
                catch (TaskCanceledException)
                {
                    throw new StreamCommunicationClientClosedException();
                }
            }
        }
示例#5
0
        async Task FlushContentsAsync(Stream stream, long contentLength)
        {
            var contentBuffer = new byte[Math.Min(4096, contentLength)];

            while (contentLength > 0)
            {
                var bytesRead = await stream.ReadAsync(contentBuffer, 0, (int)Math.Min(contentBuffer.Length, contentLength)).ConfigureAwait(false);
                if (bytesRead > 0)
                    contentLength -= bytesRead;
                else
                    break;
            }
        }
示例#6
0
        public override async Task <int> ReadAsync(char[] buffer, int index, int count)
        {
            if (buffer == null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }

            if (index < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(index));
            }

            if (count < 0 || index + count > buffer.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(count));
            }

            if (_stream == null)
            {
                throw new ObjectDisposedException("stream");
            }

            if (_charBufferIndex == _charsRead && await ReadIntoBufferAsync() == 0)
            {
                return(0);
            }

            var charsRead = 0;

            while (count > 0)
            {
                // n is the characters available in _charBuffer
                var n = _charsRead - _charBufferIndex;

                // charBuffer is empty, let's read from the stream
                if (n == 0)
                {
                    _charsRead       = 0;
                    _charBufferIndex = 0;
                    _bytesRead       = 0;

                    // We loop here so that we read in enough bytes to yield at least 1 char.
                    // We break out of the loop if the stream is blocked (EOF is reached).
                    do
                    {
                        Debug.Assert(n == 0);
                        _bytesRead = await _stream.ReadAsync(
                            _byteBuffer,
                            0,
                            _byteBufferSize);

                        if (_bytesRead == 0)  // EOF
                        {
                            _isBlocked = true;
                            break;
                        }

                        // _isBlocked == whether we read fewer bytes than we asked for.
                        _isBlocked = (_bytesRead < _byteBufferSize);

                        Debug.Assert(n == 0);

                        _charBufferIndex = 0;
                        n = _decoder.GetChars(
                            _byteBuffer,
                            0,
                            _bytesRead,
                            _charBuffer,
                            0);

                        Debug.Assert(n > 0);

                        _charsRead += n; // Number of chars in StreamReader's buffer.
                    }while (n == 0);

                    if (n == 0)
                    {
                        break; // We're at EOF
                    }
                }

                // Got more chars in charBuffer than the user requested
                if (n > count)
                {
                    n = count;
                }

                Buffer.BlockCopy(
                    _charBuffer,
                    _charBufferIndex * 2,
                    buffer,
                    (index + charsRead) * 2,
                    n * 2);

                _charBufferIndex += n;

                charsRead += n;
                count     -= n;

                // This function shouldn't block for an indefinite amount of time,
                // or reading from a network stream won't work right.  If we got
                // fewer bytes than we requested, then we want to break right here.
                if (_isBlocked)
                {
                    break;
                }
            }

            return(charsRead);
        }
示例#7
0
 public override Task <int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) => _stream.ReadAsync(buffer, offset, count, cancellationToken);
示例#8
0
    private static async ValueTask <(StreamCopyResult, Exception?)> CopyAsync(Stream input, Stream output, long promisedContentLength, StreamCopierTelemetry?telemetry, ActivityCancellationTokenSource activityToken, CancellationToken cancellation)
    {
        var buffer = ArrayPool <byte> .Shared.Rent(DefaultBufferSize);

        var  read          = 0;
        long contentLength = 0;

        try
        {
            while (true)
            {
                read = 0;

                // Issue a zero-byte read to the input stream to defer buffer allocation until data is available.
                // Note that if the underlying stream does not supporting blocking on zero byte reads, then this will
                // complete immediately and won't save any memory, but will still function correctly.
                var zeroByteReadTask = input.ReadAsync(Memory <byte> .Empty, cancellation);
                if (zeroByteReadTask.IsCompletedSuccessfully)
                {
                    // Consume the ValueTask's result in case it is backed by an IValueTaskSource
                    _ = zeroByteReadTask.Result;
                }
                else
                {
                    // Take care not to return the same buffer to the pool twice in case zeroByteReadTask throws
                    var bufferToReturn = buffer;
                    buffer = null;
                    ArrayPool <byte> .Shared.Return(bufferToReturn);

                    await zeroByteReadTask;

                    buffer = ArrayPool <byte> .Shared.Rent(DefaultBufferSize);
                }

                read = await input.ReadAsync(buffer.AsMemory(), cancellation);

                contentLength += read;
                // Normally this is enforced by the server, but it could get out of sync if something in the proxy modified the body.
                if (promisedContentLength != UnknownLength && contentLength > promisedContentLength)
                {
                    return(StreamCopyResult.InputError, new InvalidOperationException("More bytes received than the specified Content-Length."));
                }

                telemetry?.AfterRead(contentLength);

                // Success, reset the activity monitor.
                activityToken.ResetTimeout();

                // End of the source stream.
                if (read == 0)
                {
                    if (promisedContentLength == UnknownLength || contentLength == promisedContentLength)
                    {
                        return(StreamCopyResult.Success, null);
                    }
                    else
                    {
                        // This can happen if something in the proxy consumes or modifies part or all of the request body before proxying.
                        return(StreamCopyResult.InputError,
                               new InvalidOperationException($"Sent {contentLength} request content bytes, but Content-Length promised {promisedContentLength}."));
                    }
                }

                await output.WriteAsync(buffer.AsMemory(0, read), cancellation);

                telemetry?.AfterWrite();

                // Success, reset the activity monitor.
                activityToken.ResetTimeout();
            }
        }
        catch (Exception ex)
        {
            if (read == 0)
            {
                telemetry?.AfterRead(contentLength);
            }
            else
            {
                telemetry?.AfterWrite();
            }

            var result = ex is OperationCanceledException ? StreamCopyResult.Canceled :
                         (read == 0 ? StreamCopyResult.InputError : StreamCopyResult.OutputError);

            return(result, ex);
        }
        finally
        {
            if (buffer is not null)
            {
                ArrayPool <byte> .Shared.Return(buffer);
            }

            telemetry?.Stop();
        }
    }
示例#9
0
        private async Task OnReadInternal(int offset)
        {
            _timer.Change(Timeout.Infinite, Timeout.Infinite);

            // Continue reading until full header is received.
            // Especially important for multipart requests when the second part of the header arrives after a tiny delay
            // because the web browser has to measure the content length first.
            while (true)
            {
                try
                {
                    await _ms.WriteAsync(_buffer, 0, offset).ConfigureAwait(false);

                    if (_ms.Length > 32768)
                    {
                        Close(true);
                        return;
                    }
                }
                catch
                {
                    CloseSocket();
                    Unbind();
                    return;
                }

                if (offset == 0)
                {
                    CloseSocket();
                    Unbind();
                    return;
                }

                if (ProcessInput(_ms))
                {
                    if (!_context.HaveError)
                    {
                        _context.HttpListenerRequest.FinishInitialization();
                    }

                    if (_context.HaveError || !_epl.BindContext(_context))
                    {
                        Close(true);
                        return;
                    }

                    var listener = _context.Listener;
                    if (_lastListener != listener)
                    {
                        RemoveConnection();
                        listener.AddConnection(this);
                        _lastListener = listener;
                    }

                    _contextBound = true;
                    listener.RegisterContext(_context);
                    return;
                }

                offset = await Stream.ReadAsync(_buffer, 0, BufferSize).ConfigureAwait(false);
            }
        }
 /// <inheritdoc/>
 public override Task <int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
 {
     ThrowIfDisposed();
     return(_stream.ReadAsync(buffer, offset, count, cancellationToken));
 }
示例#11
0
 public Task BufferBytesAsync(Stream fs, long numberOfBytes)
 {
     Chunk = new byte[numberOfBytes];
     return(fs.ReadAsync(Chunk, 0, Chunk.Length));
 }
示例#12
0
        public async Task DoUpdate(bool restart = false, string exectuable = "", string parameter = "")
        {
            IsUpdating = true;
            try
            {
                if (_updatefiles.Length == 0)
                {
                    return;
                }

                string tempdir = (Path.GetRandomFileName() + Path.GetRandomFileName()).Replace(".", "");
                Directory.CreateDirectory(tempdir);

                NumFiles = _updatefiles.Length;

                int lengthsum = 0;
                for (int i = 0; i < _updatefiles.Length; i++)
                {
                    lengthsum += _updatefiles[i].length;
                }

                TotalBytes = lengthsum;

                int bytesCounter = 0;

                for (int i = 0; i < _updatefiles.Length; i++)
                {
                    CurrentFileNum  = i + 1;
                    CurrentFilename = _updatefiles[i].name;

                    using (FileStream fs = new FileStream(Path.Combine(tempdir, _updatefiles[i].name), FileMode.Create, FileAccess.Write))
                    {
                        HttpWebRequest request = WebRequest.CreateHttp(_baseurl + _updatefiles[i].name);
                        request.AllowAutoRedirect = true;

                        HttpWebResponse response = await request.GetResponseAsync() as HttpWebResponse;

                        Stream responseStream = response.GetResponseStream();

                        CurrentFileBytes = (int)response.ContentLength;

                        var buffer    = new byte[1024];
                        var bytesread = 0;
                        while (fs.Position < response.ContentLength)
                        {
                            bytesread = await responseStream.ReadAsync(buffer, 0, buffer.Length);

                            await fs.WriteAsync(buffer, 0, bytesread);

                            CurrentFileBytesDownloaded = (int)fs.Position;
                            TotalBytesDownloaded       = bytesCounter + CurrentFileBytesDownloaded;
                        }
                    }

                    bytesCounter += CurrentFileBytes;
                }

                string command =
                    "/C @echo off & for /l %a in (0) do TaskList /FI \"IMAGENAME eq " + exectuable + "\" 2>NUL | Find \"" + exectuable + "\" >NUL || " +                    //Waits on app termination
                    "(move /Y " + Path.Combine(tempdir, "*.*") + " . && rd /s /q " + tempdir + (restart ? (" && start " + exectuable + " " + parameter) : "") + " & EXIT)"; //actual update
                ProcessStartInfo psi = new ProcessStartInfo("cmd.exe", command);
                psi.CreateNoWindow   = true;
                psi.UseShellExecute  = false;
                psi.WorkingDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

                Process cmd = new Process();
                cmd.StartInfo = psi;
                cmd.Start();
                Environment.Exit(0);
            }
            catch (Exception e)
            {
                if (errorEvent != null)
                {
                    errorEvent(this, new ErrorEventArgs(e));
                }
            }

            IsUpdating = false;
        }
 public override Task <int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
 {
     count = GetAllowedCount(count);
     return(m_innerStream.ReadAsync(buffer, offset, count, cancellationToken));
 }
示例#14
0
        protected override async void Handle(TcpClient client, CancellationToken cancellationToken)
        {
            TcpClient             outgoingClient = null;
            CQRSProtocolType?     protocolType   = null;
            RelayConnectedService service        = null;
            Stopwatch             stopwatch      = null;
            bool responseStarted = false;

            var bufferOwner = BufferArrayPool <byte> .Rent(bufferLength);

            var buffer = bufferOwner.AsMemory();

            Stream incommingStream           = null;
            Stream incommingBodyStream       = null;
            Stream outgoingWritingBodyStream = null;

            Stream outgoingStream             = null;
            Stream outgoingBodyStream         = null;
            Stream incommingWritingBodyStream = null;

            try
            {
                incommingStream = client.GetStream();

                var headerPosition = 0;
                var headerLength   = 0;
                var headerEnd      = false;
                while (headerLength < TcpCommon.MaxProtocolHeaderPrefixLength)
                {
                    if (headerLength == buffer.Length)
                    {
                        throw new Exception($"{nameof(TcpRelay)} Header Too Long");
                    }

                    headerLength += await incommingStream.ReadAsync(buffer.Slice(headerPosition, buffer.Length - headerPosition), cancellationToken);
                }
                protocolType = TcpCommon.ReadProtocol(buffer.Span);

                string providerType;

                switch (protocolType.Value)
                {
                case CQRSProtocolType.TcpRaw:
                {
                    headerEnd = TcpRawCommon.ReadToHeaderEnd(buffer, ref headerPosition, headerLength);
                    while (!headerEnd)
                    {
                        if (headerLength == buffer.Length)
                        {
                            throw new Exception($"{nameof(TcpRelay)} Header Too Long");
                        }

                        headerLength += await incommingStream.ReadAsync(buffer.Slice(headerLength, buffer.Length - headerLength), cancellationToken);

                        headerEnd = TcpRawCommon.ReadToHeaderEnd(buffer, ref headerPosition, headerLength);
                    }
                    var header = TcpRawCommon.ReadHeader(buffer, headerPosition, headerLength);
                    providerType        = header.ProviderType;
                    incommingBodyStream = new TcpRawProtocolBodyStream(incommingStream, header.BodyStartBuffer, true);
                    break;
                }

                case CQRSProtocolType.Http:
                {
                    headerEnd = HttpCommon.ReadToHeaderEnd(buffer, ref headerPosition, headerLength);
                    while (!headerEnd)
                    {
                        if (headerLength == buffer.Length)
                        {
                            throw new Exception($"{nameof(TcpRelay)} Header Too Long");
                        }

                        headerLength += await incommingStream.ReadAsync(buffer.Slice(headerLength, buffer.Length - headerLength), cancellationToken);

                        headerEnd = HttpCommon.ReadToHeaderEnd(buffer, ref headerPosition, headerLength);
                    }
                    var header = HttpCommon.ReadHeader(buffer, headerPosition, headerLength);
                    providerType        = header.ProviderType;
                    incommingBodyStream = new HttpProtocolBodyStream(header.ContentLength, incommingStream, header.BodyStartBuffer, true);

                    if (header.RelayServiceAddRemove.HasValue)
                    {
                        if (header.RelayKey != relayKey)
                        {
                            throw new SecurityException("Invalid Relay Key");
                        }

                        var serviceInfo = await System.Text.Json.JsonSerializer.DeserializeAsync <ServiceInfo>(incommingBodyStream);

                        await incommingBodyStream.DisposeAsync();

                        incommingBodyStream = null;

                        if (header.RelayServiceAddRemove == true)
                        {
                            RelayConnectedServicesManager.AddOrUpdate(serviceInfo);
                        }
                        else
                        {
                            RelayConnectedServicesManager.Remove(serviceInfo.Url);
                        }

                        var requestHeaderLength = HttpCommon.BufferOkHeader(buffer);
                        await incommingStream.WriteAsync(buffer.Slice(0, requestHeaderLength), cancellationToken);

                        await incommingStream.FlushAsync();

                        await incommingStream.DisposeAsync();

                        incommingStream = null;
                        client.Dispose();
                        return;
                    }
                    break;
                }

                default: throw new NotImplementedException();
                }

                while (outgoingClient == null)
                {
                    service = RelayConnectedServicesManager.GetBestService(providerType);
                    if (service == null)
                    {
                        break;
                    }

                    try
                    {
                        _ = Log.TraceAsync($"Relaying {providerType} to {service.Url}");

                        var outgoingEndpoint = IPResolver.GetIPEndPoints(service.Url, 80).First();
                        if (outgoingEndpoint != null)
                        {
                            outgoingClient         = new TcpClient(outgoingEndpoint.AddressFamily);
                            outgoingClient.NoDelay = true;
                            await outgoingClient.ConnectAsync(outgoingEndpoint.Address, outgoingEndpoint.Port);

                            service.FlagConnectionSuccess();
                        }
                        else
                        {
                            service.FlagConnectionFailed();
                        }
                    }
                    catch
                    {
                        service.FlagConnectionFailed();
                    }
                }

                if (outgoingClient == null)
                {
                    _ = Log.TraceAsync($"Destination not found {providerType}");
                    switch (protocolType.Value)
                    {
                    case CQRSProtocolType.TcpRaw:
                    {
                        var requestHeaderLength = HttpCommon.BufferNotFoundHeader(buffer);
                        await incommingStream.WriteAsync(buffer.Slice(0, requestHeaderLength));

                        return;
                    }

                    case CQRSProtocolType.Http:
                    {
                        var requestHeaderLength = TcpRawCommon.BufferErrorHeader(buffer, null, default);
                        await incommingStream.WriteAsync(buffer.Slice(0, requestHeaderLength));

                        return;
                    }

                    default: throw new NotImplementedException();
                    }
                }

                outgoingStream = outgoingClient.GetStream();

                stopwatch = service.StartRequestRunning();

                responseStarted = true;
                await outgoingStream.WriteAsync(buffer.Slice(0, headerPosition), cancellationToken);

                switch (protocolType.Value)
                {
                case CQRSProtocolType.TcpRaw:
                {
                    outgoingWritingBodyStream = new TcpRawProtocolBodyStream(outgoingStream, null, true);
                    await incommingBodyStream.CopyToAsync(outgoingWritingBodyStream, cancellationToken);

                    await outgoingWritingBodyStream.FlushAsync();

                    break;
                }

                case CQRSProtocolType.Http:
                {
                    outgoingWritingBodyStream = new HttpProtocolBodyStream(null, outgoingStream, null, true);
                    await incommingBodyStream.CopyToAsync(outgoingWritingBodyStream, cancellationToken);

                    await outgoingWritingBodyStream.FlushAsync();

                    break;
                }

                default: throw new NotImplementedException();
                }

                await incommingBodyStream.DisposeAsync();

                incommingBodyStream = null;
                await outgoingWritingBodyStream.DisposeAsync();

                outgoingWritingBodyStream = null;

                //Response
                //-----------------------------------------------------------------------------------------------------------------------

                headerPosition = 0;
                headerLength   = 0;
                headerEnd      = false;
                switch (protocolType.Value)
                {
                case CQRSProtocolType.TcpRaw:
                {
                    while (!headerEnd)
                    {
                        if (headerLength == buffer.Length)
                        {
                            throw new Exception($"{nameof(TcpRelay)} Header Too Long");
                        }

                        headerLength += await outgoingStream.ReadAsync(buffer.Slice(headerLength, buffer.Length - headerLength));

                        headerEnd = TcpRawCommon.ReadToHeaderEnd(buffer, ref headerPosition, headerLength);
                    }
                    outgoingBodyStream = new TcpRawProtocolBodyStream(outgoingStream, buffer.Slice(headerPosition, headerLength - headerPosition), false);
                    break;
                }

                case CQRSProtocolType.Http:
                {
                    while (!headerEnd)
                    {
                        if (headerLength == buffer.Length)
                        {
                            throw new Exception($"{nameof(TcpRelay)} Header Too Long");
                        }

                        headerLength += await outgoingStream.ReadAsync(buffer.Slice(headerLength, buffer.Length - headerLength));

                        headerEnd = HttpCommon.ReadToHeaderEnd(buffer, ref headerPosition, headerLength);
                    }
                    var header = HttpCommon.ReadHeader(buffer, headerPosition, headerLength);
                    outgoingBodyStream = new HttpProtocolBodyStream(header.ContentLength, outgoingStream, header.BodyStartBuffer, false);
                    break;
                }
                }

                await incommingStream.WriteAsync(buffer.Slice(0, headerPosition), cancellationToken);

                switch (protocolType.Value)
                {
                case CQRSProtocolType.TcpRaw:
                {
                    incommingWritingBodyStream = new TcpRawProtocolBodyStream(incommingStream, null, false);
                    await outgoingBodyStream.CopyToAsync(incommingWritingBodyStream, cancellationToken);

                    await incommingWritingBodyStream.FlushAsync();

                    break;
                }

                case CQRSProtocolType.Http:
                {
                    incommingWritingBodyStream = new HttpProtocolBodyStream(null, incommingStream, null, false);
                    await outgoingBodyStream.CopyToAsync(incommingWritingBodyStream, cancellationToken);

                    await incommingWritingBodyStream.FlushAsync();

                    break;
                }

                default: throw new NotImplementedException();
                }

                await outgoingBodyStream.DisposeAsync();

                outgoingBodyStream = null;
                await incommingWritingBodyStream.DisposeAsync();

                incommingWritingBodyStream = null;
                outgoingClient.Dispose();
                client.Dispose();
            }
            catch (Exception ex)
            {
                if (ex is IOException ioException)
                {
                    if (ioException.InnerException != null && ioException.InnerException is SocketException socketException)
                    {
                        if (socketException.SocketErrorCode == SocketError.ConnectionAborted)
                        {
                            return;
                        }
                    }
                }

                _ = Log.ErrorAsync(null, ex);

                if (!responseStarted && incommingStream != null && protocolType.HasValue)
                {
                    try
                    {
                        switch (protocolType.Value)
                        {
                        case CQRSProtocolType.TcpRaw:
                        {
                            var requestHeaderLength = HttpCommon.BufferErrorHeader(buffer, null);
                            await incommingStream.WriteAsync(buffer.Slice(0, requestHeaderLength), cancellationToken);

                            break;
                        }

                        case CQRSProtocolType.Http:
                        {
                            var requestHeaderLength = TcpRawCommon.BufferErrorHeader(buffer, null, default);
                            await incommingStream.WriteAsync(buffer.Slice(0, requestHeaderLength), cancellationToken);

                            break;
                        }

                        default: throw new NotImplementedException();
                        }
                    }
                    catch (Exception ex2)
                    {
                        _ = Log.ErrorAsync(null, ex2);
                    }
                }

                if (outgoingWritingBodyStream != null)
                {
                    await outgoingWritingBodyStream.DisposeAsync();
                }
                if (outgoingBodyStream != null)
                {
                    await outgoingBodyStream.DisposeAsync();
                }
                if (outgoingStream != null)
                {
                    await outgoingStream.DisposeAsync();
                }
                if (incommingWritingBodyStream != null)
                {
                    await incommingWritingBodyStream.DisposeAsync();
                }
                if (incommingBodyStream != null)
                {
                    await incommingBodyStream.DisposeAsync();
                }
                if (incommingStream != null)
                {
                    await incommingStream.DisposeAsync();
                }

                if (outgoingClient != null)
                {
                    outgoingClient.Dispose();
                }

                client.Dispose();
            }
            finally
            {
                BufferArrayPool <byte> .Return(bufferOwner);

                if (service != null && stopwatch != null)
                {
                    service.EndRequestRunning(stopwatch);
                }
            }
        }
示例#15
0
        private async Task <int> ReadAsyncCore(byte[] buffer, int offset, int count, CancellationToken cancellationToken, bool useAsync)
        {
            // read <= count bytes from the input stream, transforming as we go.
            // Basic idea: first we deliver any bytes we already have in the
            // _OutputBuffer, because we know they're good.  Then, if asked to deliver
            // more bytes, we read & transform a block at a time until either there are
            // no bytes ready or we've delivered enough.
            int bytesToDeliver     = count;
            int currentOutputIndex = offset;

            if (_outputBufferIndex != 0)
            {
                // we have some already-transformed bytes in the output buffer
                if (_outputBufferIndex <= count)
                {
                    Buffer.BlockCopy(_outputBuffer, 0, buffer, offset, _outputBufferIndex);
                    bytesToDeliver     -= _outputBufferIndex;
                    currentOutputIndex += _outputBufferIndex;
                    int toClear = _outputBuffer.Length - _outputBufferIndex;
                    CryptographicOperations.ZeroMemory(new Span <byte>(_outputBuffer, _outputBufferIndex, toClear));
                    _outputBufferIndex = 0;
                }
                else
                {
                    Buffer.BlockCopy(_outputBuffer, 0, buffer, offset, count);
                    Buffer.BlockCopy(_outputBuffer, count, _outputBuffer, 0, _outputBufferIndex - count);
                    _outputBufferIndex -= count;

                    int toClear = _outputBuffer.Length - _outputBufferIndex;
                    CryptographicOperations.ZeroMemory(new Span <byte>(_outputBuffer, _outputBufferIndex, toClear));

                    return(count);
                }
            }
            // _finalBlockTransformed == true implies we're at the end of the input stream
            // if we got through the previous if block then _OutputBufferIndex = 0, meaning
            // we have no more transformed bytes to give
            // so return count-bytesToDeliver, the amount we were able to hand back
            // eventually, we'll just always return 0 here because there's no more to read
            if (_finalBlockTransformed)
            {
                return(count - bytesToDeliver);
            }
            // ok, now loop until we've delivered enough or there's nothing available
            int amountRead = 0;
            int numOutputBytes;

            // OK, see first if it's a multi-block transform and we can speed up things
            int blocksToProcess = bytesToDeliver / _outputBlockSize;

            if (blocksToProcess > 1 && _transform.CanTransformMultipleBlocks)
            {
                int numWholeBlocksInBytes = blocksToProcess * _inputBlockSize;

                // Use ArrayPool.Shared instead of CryptoPool because the array is passed out.
                byte[] tempInputBuffer = ArrayPool <byte> .Shared.Rent(numWholeBlocksInBytes);

                byte[] tempOutputBuffer = null;

                try
                {
                    amountRead = useAsync ?
                                 await _stream.ReadAsync(new Memory <byte>(tempInputBuffer, _inputBufferIndex, numWholeBlocksInBytes - _inputBufferIndex), cancellationToken).ConfigureAwait(false) :
                                 _stream.Read(tempInputBuffer, _inputBufferIndex, numWholeBlocksInBytes - _inputBufferIndex);

                    int totalInput = _inputBufferIndex + amountRead;

                    // If there's still less than a block, copy the new data into the hold buffer and move to the slow read.
                    if (totalInput < _inputBlockSize)
                    {
                        Buffer.BlockCopy(tempInputBuffer, _inputBufferIndex, _inputBuffer, _inputBufferIndex, amountRead);
                        _inputBufferIndex = totalInput;
                    }
                    else
                    {
                        // Copy any held data into tempInputBuffer now that we know we're proceeding
                        Buffer.BlockCopy(_inputBuffer, 0, tempInputBuffer, 0, _inputBufferIndex);
                        CryptographicOperations.ZeroMemory(new Span <byte>(_inputBuffer, 0, _inputBufferIndex));
                        amountRead       += _inputBufferIndex;
                        _inputBufferIndex = 0;

                        // Make amountRead an integral multiple of _InputBlockSize
                        int numWholeReadBlocks        = amountRead / _inputBlockSize;
                        int numWholeReadBlocksInBytes = numWholeReadBlocks * _inputBlockSize;
                        int numIgnoredBytes           = amountRead - numWholeReadBlocksInBytes;

                        if (numIgnoredBytes != 0)
                        {
                            _inputBufferIndex = numIgnoredBytes;
                            Buffer.BlockCopy(tempInputBuffer, numWholeReadBlocksInBytes, _inputBuffer, 0, numIgnoredBytes);
                        }

                        // Use ArrayPool.Shared instead of CryptoPool because the array is passed out.
                        tempOutputBuffer = ArrayPool <byte> .Shared.Rent(numWholeReadBlocks *_outputBlockSize);

                        numOutputBytes = _transform.TransformBlock(tempInputBuffer, 0, numWholeReadBlocksInBytes, tempOutputBuffer, 0);
                        Buffer.BlockCopy(tempOutputBuffer, 0, buffer, currentOutputIndex, numOutputBytes);

                        // Clear what was written while we know how much that was
                        CryptographicOperations.ZeroMemory(new Span <byte>(tempOutputBuffer, 0, numOutputBytes));
                        ArrayPool <byte> .Shared.Return(tempOutputBuffer);

                        tempOutputBuffer = null;

                        bytesToDeliver     -= numOutputBytes;
                        currentOutputIndex += numOutputBytes;
                    }

                    CryptographicOperations.ZeroMemory(new Span <byte>(tempInputBuffer, 0, numWholeBlocksInBytes));
                    ArrayPool <byte> .Shared.Return(tempInputBuffer);

                    tempInputBuffer = null;
                }
                catch
                {
                    // If we rented and then an exception happened we don't know how much was written to,
                    // clear the whole thing and let it get reclaimed by the GC.
                    if (tempOutputBuffer != null)
                    {
                        CryptographicOperations.ZeroMemory(tempOutputBuffer);
                        tempOutputBuffer = null;
                    }

                    // For the input buffer we know how much was written, so clear that.
                    // But still let it get reclaimed by the GC.
                    if (tempInputBuffer != null)
                    {
                        CryptographicOperations.ZeroMemory(new Span <byte>(tempInputBuffer, 0, numWholeBlocksInBytes));
                        tempInputBuffer = null;
                    }

                    throw;
                }
            }

            // try to fill _InputBuffer so we have something to transform
            while (bytesToDeliver > 0)
            {
                while (_inputBufferIndex < _inputBlockSize)
                {
                    amountRead = useAsync ?
                                 await _stream.ReadAsync(new Memory <byte>(_inputBuffer, _inputBufferIndex, _inputBlockSize - _inputBufferIndex), cancellationToken) : // ConfigureAwait not needed, as useAsync is only true if we're already on a TP thread
                                 _stream.Read(_inputBuffer, _inputBufferIndex, _inputBlockSize - _inputBufferIndex);

                    // first, check to see if we're at the end of the input stream
                    if (amountRead == 0)
                    {
                        goto ProcessFinalBlock;
                    }
                    _inputBufferIndex += amountRead;
                }

                numOutputBytes    = _transform.TransformBlock(_inputBuffer, 0, _inputBlockSize, _outputBuffer, 0);
                _inputBufferIndex = 0;

                if (bytesToDeliver >= numOutputBytes)
                {
                    Buffer.BlockCopy(_outputBuffer, 0, buffer, currentOutputIndex, numOutputBytes);
                    CryptographicOperations.ZeroMemory(new Span <byte>(_outputBuffer, 0, numOutputBytes));
                    currentOutputIndex += numOutputBytes;
                    bytesToDeliver     -= numOutputBytes;
                }
                else
                {
                    Buffer.BlockCopy(_outputBuffer, 0, buffer, currentOutputIndex, bytesToDeliver);
                    _outputBufferIndex = numOutputBytes - bytesToDeliver;
                    Buffer.BlockCopy(_outputBuffer, bytesToDeliver, _outputBuffer, 0, _outputBufferIndex);
                    int toClear = _outputBuffer.Length - _outputBufferIndex;
                    CryptographicOperations.ZeroMemory(new Span <byte>(_outputBuffer, _outputBufferIndex, toClear));
                    return(count);
                }
            }
            return(count);

ProcessFinalBlock:
            // if so, then call TransformFinalBlock to get whatever is left
            byte[] finalBytes = _transform.TransformFinalBlock(_inputBuffer, 0, _inputBufferIndex);
            // now, since _OutputBufferIndex must be 0 if we're in the while loop at this point,
            // reset it to be what we just got back
            _outputBuffer      = finalBytes;
            _outputBufferIndex = finalBytes.Length;
            // set the fact that we've transformed the final block
            _finalBlockTransformed = true;
            // now, return either everything we just got or just what's asked for, whichever is smaller
            if (bytesToDeliver < _outputBufferIndex)
            {
                Buffer.BlockCopy(_outputBuffer, 0, buffer, currentOutputIndex, bytesToDeliver);
                _outputBufferIndex -= bytesToDeliver;
                Buffer.BlockCopy(_outputBuffer, bytesToDeliver, _outputBuffer, 0, _outputBufferIndex);
                int toClear = _outputBuffer.Length - _outputBufferIndex;
                CryptographicOperations.ZeroMemory(new Span <byte>(_outputBuffer, _outputBufferIndex, toClear));
                return(count);
            }
            else
            {
                Buffer.BlockCopy(_outputBuffer, 0, buffer, currentOutputIndex, _outputBufferIndex);
                bytesToDeliver    -= _outputBufferIndex;
                _outputBufferIndex = 0;
                CryptographicOperations.ZeroMemory(_outputBuffer);
                return(count - bytesToDeliver);
            }
        }
示例#16
0
        /// <summary>
        /// Asynchronously reads the entire content of the stream and writes it to the given output stream.
        /// </summary>
        /// <param name="stream">The origin stream.</param>
        /// <param name="toStream">The destination stream.</param>
        /// <param name="bufferManager">IBufferManager instance to use. May be null.</param>
        /// <param name="copyLength">Number of bytes to copy from source stream to destination stream. Cannot be passed with a value for maxLength.</param>
        /// <param name="maxLength">Maximum length of the source stream. Cannot be passed with a value for copyLength.</param>
        /// <param name="calculateChecksum">A value indicating whether the checksums should be calculated.</param>
        /// <param name="executionState">An object that stores state of the operation.</param>
        /// <param name="streamCopyState">An object that represents the current state for the copy operation.</param>
        /// <param name="token">A CancellationToken to observe while waiting for the copy to complete.</param>
        /// <returns>The task object representing the asynchronous operation.</returns>
        internal static async Task WriteToAsync <T>(this Stream stream, Stream toStream, IBufferManager bufferManager, long?copyLength, long?maxLength, ChecksumRequested calculateChecksum, ExecutionState <T> executionState, StreamDescriptor streamCopyState, CancellationToken token)
        {
            if (copyLength.HasValue && maxLength.HasValue)
            {
                throw new ArgumentException(SR.StreamLengthMismatch);
            }

            if (stream.CanSeek && maxLength.HasValue && stream.Length - stream.Position > maxLength)
            {
                throw new InvalidOperationException(SR.StreamLengthError);
            }

            if (stream.CanSeek && copyLength.HasValue && stream.Length - stream.Position < copyLength)
            {
                throw new ArgumentOutOfRangeException("copyLength", SR.StreamLengthShortError);
            }

            if (streamCopyState != null && calculateChecksum.HasAny && streamCopyState.ChecksumWrapper == null)
            {
                streamCopyState.ChecksumWrapper = new ChecksumWrapper(calculateChecksum.MD5, calculateChecksum.CRC64);
            }

            CancellationTokenSource cts = null;

            byte[] buffer = bufferManager != null?bufferManager.TakeBuffer(GetBufferSize(stream)) : new byte[GetBufferSize(stream)];

            try
            {
                if (executionState.OperationExpiryTime.HasValue)
                {
                    // Setup token for timeout
                    cts = CancellationTokenSource.CreateLinkedTokenSource(token);
                    cts.CancelAfter(executionState.RemainingTimeout);

                    // Switch tokens
                    token = cts.Token;
                }

                long?bytesRemaining = copyLength;
                int  readCount;
                do
                {
                    // Determine how many bytes to read this time so that no more than count bytes are read
                    int bytesToRead = bytesRemaining.HasValue && bytesRemaining < buffer.Length ? (int)bytesRemaining : buffer.Length;

                    if (bytesToRead == 0)
                    {
                        break;
                    }

                    readCount = await stream.ReadAsync(buffer, 0, bytesToRead, token).ConfigureAwait(false);

                    if (bytesRemaining.HasValue)
                    {
                        bytesRemaining -= readCount;
                    }

                    if (readCount > 0)
                    {
                        await toStream.WriteAsync(buffer, 0, readCount, token).ConfigureAwait(false);

                        // Update the StreamDescriptor after the bytes are successfully committed to the output stream
                        if (streamCopyState != null)
                        {
                            streamCopyState.Length += readCount;

                            if (maxLength.HasValue && streamCopyState.Length > maxLength.Value)
                            {
                                throw new InvalidOperationException(SR.StreamLengthError);
                            }

                            if (streamCopyState.ChecksumWrapper != null)
                            {
                                streamCopyState.ChecksumWrapper.UpdateHash(buffer, 0, readCount);
                            }
                        }
                    }
                }while (readCount > 0);

                if (bytesRemaining.HasValue && bytesRemaining != 0)
                {
                    throw new ArgumentOutOfRangeException("copyLength", SR.StreamLengthShortError);
                }
            }
            finally
            {
                if (cts != null)
                {
                    cts.Dispose();
                    cts = null;
                }

                if (buffer != null && bufferManager != null)
                {
                    bufferManager.ReturnBuffer(buffer);
                }
            }

            // Streams opened with AsStreamForWrite extension need to be flushed
            // to write all buffered data to the underlying Windows Runtime stream.
            await toStream.FlushAsync().ConfigureAwait(false);

            if (streamCopyState != null && streamCopyState.ChecksumWrapper != null)
            {
                if (streamCopyState.ChecksumWrapper.CRC64 != null)
                {
                    streamCopyState.Crc64 = streamCopyState.ChecksumWrapper.CRC64.ComputeHash();
                }
                if (streamCopyState.ChecksumWrapper.MD5 != null)
                {
                    streamCopyState.Md5 = streamCopyState.ChecksumWrapper.MD5.ComputeHash();
                }
                streamCopyState.ChecksumWrapper = null;
            }
        }
示例#17
0
        /// <summary>
        /// Generate a forward-only sequence of substreams based on bufferSize.
        /// </summary>
        /// <returns>StreamPartition</returns>
        private async Task <StreamPartition> GetNextPartitionAsync(Func <long, Stream> streamSource, bool disposeStream, Func <long> getStartPosition, Action <int> incrementStartPosition, int size = Constants.DefaultBufferSize, bool async = true, CancellationToken ct = default)
        {
            if (async)
            {
                await _getNextPartitionAsync_Semaphore.WaitAsync(ct).ConfigureAwait(false);
            }
            else
            {
                _getNextPartitionAsync_Semaphore.Wait();
            }

            var    startPosition = getStartPosition();
            Stream stream        = streamSource(startPosition);

            IMemoryOwner <byte> buffer;

            lock (_memoryPool)
            {
                // TODO these operations should be simplified with Memory- and Span-accepting APIs in future NET Standard
                buffer = _memoryPool.Rent(size);
            }

            //Console.WriteLine($"Rented buffer of size {size} bytes");
            //this.logger?.LogTrace($"Rented buffer of size {size} bytes");

            if (MemoryMarshal.TryGetArray <byte>(buffer.Memory, out ArraySegment <byte> segment))
            {
                var count =
                    async
                    ? await stream.ReadAsync(segment.Array, 0, segment.Count, ct).ConfigureAwait(false)
                    : stream.Read(segment.Array, 0, segment.Count);

                if (disposeStream)
                {
                    stream.Dispose();
                }

                incrementStartPosition(count);

                _getNextPartitionAsync_Semaphore.Release();

                //this.logger?.LogTrace($"Read {count} bytes");

                var partition = new StreamPartition(
                    buffer.Memory,
                    startPosition,
                    count,
                    () =>
                {
                    buffer.Dispose();
                    //Console.WriteLine($"Disposed buffer of size {size} bytes");
                    //this.logger?.LogTrace($"Disposed buffer of size {size} bytes");
                },
                    ct
                    );

                //Console.WriteLine($"Creating partition {partition.ParentPosition}");

                return(partition);
            }
            else
            {
                if (disposeStream)
                {
                    stream.Dispose();
                }

                _getNextPartitionAsync_Semaphore.Release();
                throw Errors.UnableAccessArray();
            }
        }
示例#18
0
        private async void StartBackgroundUpdate()
        {
            if (this.State != UpdateState.NotStarted && this.State != UpdateState.Failed && this.State != UpdateState.UpToDate)
            {
                // Can only start updates from certain states.
                return;
            }

            this.State = UpdateState.DownloadingInfo;

            this.updateDownloadCancellationTokenSource = new CancellationTokenSource();

            await Task.Run(async() =>
            {
                try
                {
                    UpdateInfo updateInfo = await GetUpdateInfoAsync(CommonUtilities.Beta).ConfigureAwait(false);

                    if (updateInfo == null)
                    {
                        this.State = UpdateState.Failed;
                        this.logger.Log("Update download failed. Unable to get update info.");
                        return;
                    }

                    Version updateVersion = updateInfo.LatestVersion;
                    this.LatestVersion    = updateVersion;

                    if (updateVersion > Utilities.CurrentVersion)
                    {
                        // If an update is reported to be ready but the installer doesn't exist, clear out all the
                        // installer info and redownload.
                        string updateInstallerLocation = Config.UpdateInstallerLocation;
                        if (updateInstallerLocation != string.Empty && !File.Exists(updateInstallerLocation))
                        {
                            using (SQLiteTransaction transaction = Database.ThreadLocalConnection.BeginTransaction())
                            {
                                ClearUpdateMetadata();

                                transaction.Commit();
                            }

                            this.logger.Log("Downloaded update (" + updateInstallerLocation + ") could not be found. Re-downloading it.");
                        }

                        // If we have not finished the download update yet, start/resume the download.
                        if (Config.UpdateInstallerLocation == string.Empty)
                        {
                            string updateVersionText = updateVersion.ToShortString();

                            if (CommonUtilities.Beta)
                            {
                                updateVersionText += " Beta";
                            }

                            string newVersionStartedMessage = string.Format(MainRes.NewVersionDownloadStartedStatus, updateVersionText);
                            this.logger.Log(newVersionStartedMessage);

                            DispatchUtilities.BeginInvoke(() =>
                            {
                                this.logger.ShowStatus(newVersionStartedMessage);
                            });

                            this.State = UpdateState.DownloadingInstaller;
                            this.UpdateDownloadProgressFraction = 0;

                            string downloadLocation  = updateInfo.DownloadUrl;
                            string changelogLink     = updateInfo.ChangelogUrl;
                            string installerFileName = Path.GetFileName(downloadLocation);
                            string installerFilePath = Path.Combine(Utilities.UpdatesFolder, installerFileName);

                            Stream responseStream = null;
                            FileStream fileStream = null;

                            try
                            {
                                HttpClient client          = new HttpClient();
                                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, downloadLocation);

                                long bytesProgressTotal = 0;

                                if (File.Exists(installerFilePath))
                                {
                                    var fileInfo = new FileInfo(installerFilePath);

                                    request.Headers.Range = new RangeHeaderValue(fileInfo.Length, null);
                                    bytesProgressTotal    = fileInfo.Length;

                                    fileStream = new FileStream(installerFilePath, FileMode.Append, FileAccess.Write, FileShare.None);
                                }
                                else
                                {
                                    fileStream = new FileStream(installerFilePath, FileMode.Create, FileAccess.Write, FileShare.None);
                                }

                                var response   = await client.SendAsync(request).ConfigureAwait(false);
                                responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);

                                byte[] downloadBuffer = new byte[2048];
                                int bytesRead;

                                while ((bytesRead = await responseStream.ReadAsync(downloadBuffer, 0, downloadBuffer.Length).ConfigureAwait(false)) > 0 && !this.updateDownloadCancellationTokenSource.Token.IsCancellationRequested)
                                {
                                    fileStream.Write(downloadBuffer, 0, bytesRead);
                                    bytesProgressTotal += bytesRead;

                                    this.UpdateDownloadProgressFraction = (double)bytesProgressTotal / response.Content.Headers.ContentLength.Value;
                                }

                                if (bytesRead == 0)
                                {
                                    using (SQLiteTransaction transaction = Database.ThreadLocalConnection.BeginTransaction())
                                    {
                                        Config.UpdateVersion           = updateVersion.ToString();
                                        Config.UpdateInstallerLocation = installerFilePath;
                                        Config.UpdateChangelogLocation = changelogLink;

                                        transaction.Commit();
                                    }

                                    this.State = UpdateState.InstallerReady;
                                    this.UpdateDownloadProgressFraction = 1;

                                    string message = string.Format(MainRes.NewVersionDownloadFinishedStatus, updateVersionText);
                                    this.logger.Log(message);
                                    this.logger.ShowStatus(message);
                                }
                                else
                                {
                                    // In this case the download must have been cancelled.
                                    this.State = UpdateState.NotStarted;
                                }
                            }
                            finally
                            {
                                if (responseStream != null)
                                {
                                    responseStream.Close();
                                }

                                if (fileStream != null)
                                {
                                    fileStream.Close();
                                }
                            }
                        }
                        else
                        {
                            this.State = UpdateState.InstallerReady;
                        }
                    }
                    else
                    {
                        this.State = UpdateState.UpToDate;
                    }
                }
                catch (Exception exception)
                {
                    this.State = UpdateState.Failed;
                    this.logger.Log("Update download failed: " + exception.Message);
                }
                finally
                {
                    this.updateDownloadCancellationTokenSource?.Dispose();
                    this.updateDownloadCancellationTokenSource = null;
                }
            });
        }
        protected override bool ReadResponse(Stream response, int bytesToRead, out int bytesRead, CefCallback callback)
        {
            // if no data stream was specified, then nothing to read
            // and we should stop reading.
            // return false to indicate this.
            if (_dataStream == null)
            {
                bytesRead = 0;
                callback.Continue();
                callback.Dispose();
                return(false);
            }

            // when this is second call of ReadResponse, _bytesRead will be set to non negative number
            if (_bytesRead >= 0)
            {
                WriteReadBytes(out bytesRead);
                callback.Dispose();
                return(bytesRead != 0); //If read 0 bytes, then we should return in false
            }

            bytesRead = 0;
            _         = ReadDataAsync();

            return(true);


            // Copies read bytes into response and return true, if data is completed, owtherwize returns false
            async Task ReadDataAsync()
            {
                try
                {
                    if (_rentedBuffer == null)
                    {
                        _rentedBuffer = ArrayPool <byte> .Shared.Rent(_bufferSize);
                    }
                    //await _semaphore.WaitAsync();
                    _bytesRead = await _dataStream.ReadAsync(_rentedBuffer, 0, Math.Min(bytesToRead, _bufferSize), _cancellationTokenSource.Token);

                    //_semaphore.Release();
                }
                catch (TaskCanceledException)
                {
                    FreeResources();
                    _bytesRead = 0;
                    Logger.Instance.Log.Warn("Cancellation requested");
                }
                // Sometimes cef disposes object, before it is cancelled
                // then this exception is thrown
                // and i don't know how to fix this :(
                catch (ObjectDisposedException)
                {
                    FreeResources();
                    _bytesRead = 0;
                    Logger.Instance.Log.Warn("Cancellation requested");
                }
                catch (Exception ex)
                {
                    FreeResources();
                    _bytesRead = 0;

                    Logger.Instance.Log.Error(ex, "Exception thrown while loading resource");
                }
                finally
                {
                    callback.Continue();
                    callback.Dispose();
                }
            }

            bool WriteReadBytes(out int bytesAlreadyRead)
            {
                if (_bytesRead == 0) //if 0 bytes read, then no data was read and we should complete request
                {
                    bytesAlreadyRead = 0;
                    this.FreeResources();
                    return(true);
                }

                if (_bytesRead > 0) //writing read bytes into a buffer if there was something
                {
                    response.Write(_rentedBuffer, 0, _bytesRead);
                }

                bytesAlreadyRead = _bytesRead; //incrementing counters
                _totalRead      += _bytesRead;
                // Setting read bytes count to -1 to indicate, that nothing left to write
                // End on next call Read from source should be performed
                _bytesRead = -1;

                var dataSize = this.GetDataSize();

                // If datasize is known and we already read that amount, then stoping
                bool completed = dataSize >= 0 && _totalRead == dataSize;

                // if we completed data reading, freeing resources imediatly,
                // because this ReadResponse will never be called again
                // and any open file will left open forever
                if (completed)
                {
                    this.FreeResources();
                }

                return(completed);
            }
        }
示例#20
0
        // Receive from udp socket and push value to subscribers.
        async void RunReceiveLoop(Stream pipeStream, Func <CancellationToken, System.Threading.Tasks.Task> waitForConnection)
        {
RECONNECT:
            var token = cancellationTokenSource.Token;

            if (waitForConnection != null)
            {
                try
                {
                    await waitForConnection(token).ConfigureAwait(false);
                }
                catch (IOException)
                {
                    return; // connection closed.
                }
            }
            var buffer = new byte[65536];

            while (!token.IsCancellationRequested)
            {
                ReadOnlyMemory <byte> value = Array.Empty <byte>();
                try
                {
                    var readLen = await pipeStream.ReadAsync(buffer, 0, buffer.Length, token).ConfigureAwait(false);

                    if (readLen == 0)
                    {
                        if (waitForConnection != null)
                        {
                            server.Value.Dispose();
                            server     = CreateLazyServerStream();
                            pipeStream = server.Value;
                            goto RECONNECT; // end of stream(disconnect, wait reconnect)
                        }
                    }

                    var messageLen = MessageBuilder.FetchMessageLength(buffer);
                    if (readLen == (messageLen + 4))
                    {
                        value = buffer.AsMemory(4, messageLen); // skip length header
                    }
                    else
                    {
                        // read more
                        if (buffer.Length < (messageLen + 4))
                        {
                            Array.Resize(ref buffer, messageLen + 4);
                        }
                        var remain = messageLen - (readLen - 4);
                        await ReadFullyAsync(buffer, pipeStream, readLen, remain, token).ConfigureAwait(false);

                        value = buffer.AsMemory(4, messageLen);
                    }
                }
                catch (IOException)
                {
                    return; // connection closed.
                }
                catch (Exception ex)
                {
                    if (ex is OperationCanceledException)
                    {
                        return;
                    }
                    if (token.IsCancellationRequested)
                    {
                        return;
                    }

                    // network error, terminate.
                    options.UnhandledErrorHandler("network error, receive loop will terminate." + Environment.NewLine, ex);
                    return;
                }

                try
                {
                    var message = MessageBuilder.ReadPubSubMessage(value.ToArray()); // can avoid copy?
                    switch (message.MessageType)
                    {
                    case MessageType.PubSub:
                        publisher.Publish(message, message, CancellationToken.None);
                        break;

                    case MessageType.RemoteRequest:
                    {
                        // NOTE: should use without reflection(Expression.Compile)
                        var header = Deserialize <RequestHeader>(message.KeyMemory, options.MessagePackSerializerOptions);
                        var(mid, reqTypeName, resTypeName) = (header.MessageId, header.RequestType, header.ResponseType);
                        byte[] resultBytes;
                        try
                        {
                            var t                 = AsyncRequestHandlerRegistory.Get(reqTypeName, resTypeName);
                            var interfaceType     = t.GetInterfaces().First(x => x.IsGenericType && x.Name.StartsWith("IAsyncRequestHandler"));
                            var coreInterfaceType = t.GetInterfaces().First(x => x.IsGenericType && x.Name.StartsWith("IAsyncRequestHandlerCore"));
                            var service           = provider.GetRequiredService(interfaceType); // IAsyncRequestHandler<TRequest,TResponse>
                            var genericArgs       = interfaceType.GetGenericArguments();        // [TRequest, TResponse]
                            var request           = MessagePackSerializer.Deserialize(genericArgs[0], message.ValueMemory, options.MessagePackSerializerOptions);
                            var responseTask      = coreInterfaceType.GetMethod("InvokeAsync").Invoke(service, new[] { request, CancellationToken.None });
                            var task              = typeof(UniTask <>).MakeGenericType(genericArgs[1]).GetMethod("AsTask").Invoke(responseTask, null);
                            await((System.Threading.Tasks.Task)task);          // Task<T> -> Task
                            var result = task.GetType().GetProperty("Result").GetValue(task);
                            resultBytes = MessageBuilder.BuildRemoteResponseMessage(mid, genericArgs[1], result, options.MessagePackSerializerOptions);
                        }
                        catch (Exception ex)
                        {
                            // NOTE: ok to send stacktrace?
                            resultBytes = MessageBuilder.BuildRemoteResponseError(mid, ex.ToString(), options.MessagePackSerializerOptions);
                        }

                        await pipeStream.WriteAsync(resultBytes, 0, resultBytes.Length).ConfigureAwait(false);
                    }
                    break;

                    case MessageType.RemoteResponse:
                    case MessageType.RemoteError:
                    {
                        var mid = Deserialize <int>(message.KeyMemory, options.MessagePackSerializerOptions);
                        if (responseCompletions.TryRemove(mid, out var tcs))
                        {
                            if (message.MessageType == MessageType.RemoteResponse)
                            {
                                tcs.TrySetResult(message);         // synchronous completion, use memory buffer immediately.
                            }
                            else
                            {
                                var errorMsg = MessagePackSerializer.Deserialize <string>(message.ValueMemory, options.MessagePackSerializerOptions);
                                tcs.TrySetException(new RemoteRequestException(errorMsg));
                            }
                        }
                    }
                    break;

                    default:
                        break;
                    }
                }
                catch (IOException)
                {
                    return; // connection closed.
                }
                catch (Exception ex)
                {
                    if (ex is OperationCanceledException)
                    {
                        continue;
                    }
                    options.UnhandledErrorHandler("", ex);
                }
            }
        }
示例#21
0
        //https://github.com/dotnet/runtime/issues/31479#issuecomment-578436466
        /// <summary>
        /// Downloads a file from the specified Uri into the specified stream.
        /// </summary>
        /// <param name="cancellationToken">An optional CancellationToken that can be used to cancel the in-progress download.</param>
        /// <param name="progressCallback">If not null, will be called as the download progress. The first parameter will be the number of bytes downloaded so far, and the second the total size of the expected file after download.</param>
        /// <returns>A task that is completed once the download is complete.</returns>
        public async Task DownloadFileAsync(Uri uri, Stream toStream, CancellationToken cancellationToken = default, Action <long, long> progressCallback = null)
        {
            if (uri == null)
            {
                throw new ArgumentNullException(nameof(uri));
            }
            if (toStream == null)
            {
                throw new ArgumentNullException(nameof(toStream));
            }

            if (uri.IsFile)
            {
                using (Stream file = File.OpenRead(uri.LocalPath))
                {
                    if (progressCallback != null)
                    {
                        long   length = file.Length;
                        byte[] buffer = new byte[4096];
                        int    read;
                        int    totalRead = 0;
                        while ((read = await file.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) > 0)
                        {
                            await toStream.WriteAsync(buffer, 0, read, cancellationToken).ConfigureAwait(false);

                            totalRead += read;
                            progressCallback(totalRead, length);
                        }
                        Debug.Assert(totalRead == length || length == -1);
                    }
                    else
                    {
                        await file.CopyToAsync(toStream, 4096, cancellationToken).ConfigureAwait(false);
                    }
                }
            }
            else
            {
                using (HttpResponseMessage response = await _httpClient.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false))
                {
                    if (progressCallback != null)
                    {
                        long length = response.Content.Headers.ContentLength ?? -1;
                        using (Stream stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
                        {
                            byte[] buffer = new byte[16384];
                            int    read;
                            int    totalRead = 0;
                            while ((read = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) > 0)
                            {
                                await toStream.WriteAsync(buffer, 0, read, cancellationToken).ConfigureAwait(false);

                                totalRead += read;
                                progressCallback(totalRead, length);
                            }
                            Debug.Assert(totalRead == length || length == -1);
                        }
                    }
                    else
                    {
                        await response.Content.CopyToAsync(toStream).ConfigureAwait(false);
                    }
                }
            }
        }
示例#22
0
        public async ValueTask <BlittableJsonReaderObject> ParseToMemoryAsync(Stream stream, string documentId, BlittableJsonDocumentBuilder.UsageMode mode, ManagedPinnedBuffer bytes,
                                                                              CancellationToken?token = null,
                                                                              int maxSize             = int.MaxValue)
        {
            if (_disposed)
            {
                ThrowObjectDisposed();
            }

            _jsonParserState.Reset();
            UnmanagedJsonParser          parser  = null;
            BlittableJsonDocumentBuilder builder = null;
            var generation = _generation;

            try
            {
                parser  = new UnmanagedJsonParser(this, _jsonParserState, documentId);
                builder = new BlittableJsonDocumentBuilder(this, mode, documentId, parser, _jsonParserState);

                CachedProperties.NewDocument();
                builder.ReadObjectDocument();
                while (true)
                {
                    token?.ThrowIfCancellationRequested();
                    if (bytes.Valid == bytes.Used)
                    {
                        var read = token.HasValue
                            ? await stream.ReadAsync(bytes.Buffer.Array, bytes.Buffer.Offset, bytes.Length, token.Value)
                            : await stream.ReadAsync(bytes.Buffer.Array, bytes.Buffer.Offset, bytes.Length);

                        EnsureNotDisposed();

                        if (read == 0)
                        {
                            throw new EndOfStreamException("Stream ended without reaching end of json content");
                        }
                        bytes.Valid = read;
                        bytes.Used  = 0;
                        maxSize    -= read;
                        if (maxSize < 0)
                        {
                            throw new ArgumentException($"The maximum size allowed for {documentId} ({maxSize}) has been exceeded, aborting");
                        }
                    }
                    parser.SetBuffer(bytes);
                    var result = builder.Read();
                    bytes.Used += parser.BufferOffset;
                    if (result)
                    {
                        break;
                    }
                }
                builder.FinalizeDocument();

                var reader = builder.CreateReader();
                return(reader);
            }
            finally
            {
                DisposeIfNeeded(generation, parser, builder);
            }
        }
示例#23
0
 public override Task <int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
 {
     return(_innerStream.ReadAsync(buffer, offset, count, cancellationToken));
 }
示例#24
0
        /// <inheritdoc />
        public async Task <long> AppendDataAsync(string fileId, Stream stream, CancellationToken cancellationToken)
        {
            var internalFileId = new InternalFileId(fileId);

            var httpReadBuffer  = _bufferPool.Rent(_maxReadBufferSize);
            var fileWriteBuffer = _bufferPool.Rent(Math.Max(_maxWriteBufferSize, _maxReadBufferSize));

            try
            {
                var fileUploadLengthProvidedDuringCreate = await GetUploadLengthAsync(fileId, cancellationToken);

                using var diskFileStream = _fileRepFactory.Data(internalFileId).GetStream(FileMode.Append, FileAccess.Write, FileShare.None);

                var totalDiskFileLength = diskFileStream.Length;
                if (fileUploadLengthProvidedDuringCreate == totalDiskFileLength)
                {
                    return(0);
                }

                var chunkCompleteFile = InitializeChunk(internalFileId, totalDiskFileLength);

                int numberOfbytesReadFromClient;
                var bytesWrittenThisRequest      = 0L;
                var clientDisconnectedDuringRead = false;
                var writeBufferNextFreeIndex     = 0;

                do
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        break;
                    }

                    numberOfbytesReadFromClient = await stream.ReadAsync(httpReadBuffer, 0, _maxReadBufferSize, cancellationToken);

                    clientDisconnectedDuringRead = cancellationToken.IsCancellationRequested;

                    totalDiskFileLength += numberOfbytesReadFromClient;

                    if (totalDiskFileLength > fileUploadLengthProvidedDuringCreate)
                    {
                        throw new TusStoreException($"Stream contains more data than the file's upload length. Stream data: {totalDiskFileLength}, upload length: {fileUploadLengthProvidedDuringCreate}.");
                    }

                    // Can we fit the read data into the write buffer? If not flush it now.
                    if (writeBufferNextFreeIndex + numberOfbytesReadFromClient > _maxWriteBufferSize)
                    {
                        await FlushFileToDisk(fileWriteBuffer, diskFileStream, writeBufferNextFreeIndex);

                        writeBufferNextFreeIndex = 0;
                    }

                    Array.Copy(
                        sourceArray: httpReadBuffer,
                        sourceIndex: 0,
                        destinationArray: fileWriteBuffer,
                        destinationIndex: writeBufferNextFreeIndex,
                        length: numberOfbytesReadFromClient);

                    writeBufferNextFreeIndex += numberOfbytesReadFromClient;
                    bytesWrittenThisRequest  += numberOfbytesReadFromClient;
                } while (numberOfbytesReadFromClient != 0);

                // Flush the remaining buffer to disk.
                if (writeBufferNextFreeIndex != 0)
                {
                    await FlushFileToDisk(fileWriteBuffer, diskFileStream, writeBufferNextFreeIndex);
                }

                if (!clientDisconnectedDuringRead)
                {
                    MarkChunkComplete(chunkCompleteFile);
                }

                return(bytesWrittenThisRequest);
            }
            finally
            {
                _bufferPool.Return(httpReadBuffer);
                _bufferPool.Return(fileWriteBuffer);
            }
        }
示例#25
0
        public async Task CloudBlobClientMaximumExecutionTimeoutShouldNotBeHonoredForStreamsAsync()
        {
            CloudBlobClient    blobClient = GenerateCloudBlobClient();
            CloudBlobContainer container  = blobClient.GetContainerReference(Guid.NewGuid().ToString("N"));

            byte[] buffer = BlobTestBase.GetRandomBuffer(1024 * 1024);

            try
            {
                await container.CreateAsync();

                blobClient.DefaultRequestOptions.MaximumExecutionTime = TimeSpan.FromSeconds(30);
                CloudBlockBlob blockBlob = container.GetBlockBlobReference("blob1");
                CloudPageBlob  pageBlob  = container.GetPageBlobReference("blob2");
                blockBlob.StreamWriteSizeInBytes       = 1024 * 1024;
                blockBlob.StreamMinimumReadSizeInBytes = 1024 * 1024;
                pageBlob.StreamWriteSizeInBytes        = 1024 * 1024;
                pageBlob.StreamMinimumReadSizeInBytes  = 1024 * 1024;

                using (var bos = await blockBlob.OpenWriteAsync())
                {
                    DateTime start = DateTime.Now;
                    for (int i = 0; i < 7; i++)
                    {
                        await bos.WriteAsync(buffer, 0, buffer.Length);
                    }

                    // Sleep to ensure we are over the Max execution time when we do the last write
                    int msRemaining = (int)(blobClient.DefaultRequestOptions.MaximumExecutionTime.Value - (DateTime.Now - start)).TotalMilliseconds;

                    if (msRemaining > 0)
                    {
                        await Task.Delay(msRemaining);
                    }

                    await bos.WriteAsync(buffer, 0, buffer.Length);

                    await bos.CommitAsync();
                }

                using (Stream bis = (await blockBlob.OpenReadAsync()))
                {
                    DateTime start = DateTime.Now;
                    int      total = 0;
                    while (total < 7 * 1024 * 1024)
                    {
                        total += await bis.ReadAsync(buffer, 0, buffer.Length);
                    }

                    // Sleep to ensure we are over the Max execution time when we do the last read
                    int msRemaining = (int)(blobClient.DefaultRequestOptions.MaximumExecutionTime.Value - (DateTime.Now - start)).TotalMilliseconds;

                    if (msRemaining > 0)
                    {
                        await Task.Delay(msRemaining);
                    }

                    while (true)
                    {
                        int count = await bis.ReadAsync(buffer, 0, buffer.Length);

                        total += count;
                        if (count == 0)
                        {
                            break;
                        }
                    }
                }

                using (var bos = await pageBlob.OpenWriteAsync(8 * 1024 * 1024))
                {
                    DateTime start = DateTime.Now;
                    for (int i = 0; i < 7; i++)
                    {
                        await bos.WriteAsync(buffer, 0, buffer.Length);
                    }

                    // Sleep to ensure we are over the Max execution time when we do the last write
                    int msRemaining = (int)(blobClient.DefaultRequestOptions.MaximumExecutionTime.Value - (DateTime.Now - start)).TotalMilliseconds;

                    if (msRemaining > 0)
                    {
                        await Task.Delay(msRemaining);
                    }

                    await bos.WriteAsync(buffer, 0, buffer.Length);

                    await bos.CommitAsync();
                }

                using (Stream bis = (await pageBlob.OpenReadAsync()))
                {
                    DateTime start = DateTime.Now;
                    int      total = 0;
                    while (total < 7 * 1024 * 1024)
                    {
                        total += await bis.ReadAsync(buffer, 0, buffer.Length);
                    }

                    // Sleep to ensure we are over the Max execution time when we do the last read
                    int msRemaining = (int)(blobClient.DefaultRequestOptions.MaximumExecutionTime.Value - (DateTime.Now - start)).TotalMilliseconds;

                    if (msRemaining > 0)
                    {
                        await Task.Delay(msRemaining);
                    }

                    while (true)
                    {
                        int count = await bis.ReadAsync(buffer, 0, buffer.Length);

                        total += count;
                        if (count == 0)
                        {
                            break;
                        }
                    }
                }
            }

            finally
            {
                blobClient.DefaultRequestOptions.MaximumExecutionTime = null;
                container.DeleteIfExistsAsync().Wait();
            }
        }
示例#26
0
        /// <summary>
        /// Reads messages from the client stream and processes them in a loop until the client disconnects
        /// or until an action (such as a protocol violation) that leads to disconnecting of the client occurs.
        /// </summary>
        public async Task ReceiveMessageLoop()
        {
            log.Trace("()");

            try
            {
                if (UseTls)
                {
                    SslStream sslStream = (SslStream)Stream;
                    await sslStream.AuthenticateAsServerAsync(Base.Configuration.TcpServerTlsCertificate, false, SslProtocols.Tls12, false);
                }

                Stream       clientStream           = Stream;
                byte[]       messageHeaderBuffer    = new byte[ProtocolHelper.HeaderSize];
                byte[]       messageBuffer          = null;
                ClientStatus clientStatus           = ClientStatus.ReadingHeader;
                uint         messageSize            = 0;
                int          messageHeaderBytesRead = 0;
                int          messageBytesRead       = 0;

                while (!server.ShutdownSignaling.IsShutdown)
                {
                    Task <int> readTask = null;
                    int        remain   = 0;

                    log.Trace("Client status is '{0}'.", clientStatus);
                    switch (clientStatus)
                    {
                    case ClientStatus.ReadingHeader:
                    {
                        remain   = ProtocolHelper.HeaderSize - messageHeaderBytesRead;
                        readTask = clientStream.ReadAsync(messageHeaderBuffer, messageHeaderBytesRead, remain, server.ShutdownSignaling.ShutdownCancellationTokenSource.Token);
                        break;
                    }

                    case ClientStatus.ReadingBody:
                    {
                        remain   = (int)messageSize - messageBytesRead;
                        readTask = clientStream.ReadAsync(messageBuffer, ProtocolHelper.HeaderSize + messageBytesRead, remain, server.ShutdownSignaling.ShutdownCancellationTokenSource.Token);
                        break;
                    }

                    default:
                        log.Error("Invalid client status '{0}'.", clientStatus);
                        break;
                    }

                    if (readTask == null)
                    {
                        break;
                    }

                    log.Trace("{0} bytes remains to be read.", remain);

                    int readAmount = await readTask;
                    if (readAmount == 0)
                    {
                        log.Info("Connection has been closed.");
                        break;
                    }

                    log.Trace("Read completed: {0} bytes.", readAmount);

                    bool protoViolationDisconnect = false;
                    bool disconnect = false;
                    switch (clientStatus)
                    {
                    case ClientStatus.ReadingHeader:
                    {
                        messageHeaderBytesRead += readAmount;
                        if (readAmount == remain)
                        {
                            if (messageHeaderBuffer[0] == 0x0D)
                            {
                                uint hdr = ProtocolHelper.GetValueLittleEndian(messageHeaderBuffer, 1);
                                if (hdr + ProtocolHelper.HeaderSize <= ProtocolHelper.MaxSize)
                                {
                                    messageSize   = hdr;
                                    clientStatus  = ClientStatus.ReadingBody;
                                    messageBuffer = new byte[ProtocolHelper.HeaderSize + messageSize];
                                    Array.Copy(messageHeaderBuffer, messageBuffer, messageHeaderBuffer.Length);
                                    log.Trace("Reading of message header completed. Message size is {0} bytes.", messageSize);
                                }
                                else
                                {
                                    log.Warn("Client claimed message of size {0} which exceeds the maximum.", hdr + ProtocolHelper.HeaderSize);
                                    protoViolationDisconnect = true;
                                }
                            }
                            else
                            {
                                log.Warn("Message has invalid format - it's first byte is 0x{0:X2}, should be 0x0D.", messageHeaderBuffer[0]);
                                protoViolationDisconnect = true;
                            }
                        }
                        break;
                    }

                    case ClientStatus.ReadingBody:
                    {
                        messageBytesRead += readAmount;
                        if (readAmount == remain)
                        {
                            clientStatus           = ClientStatus.ReadingHeader;
                            messageBytesRead       = 0;
                            messageHeaderBytesRead = 0;
                            log.Trace("Reading of message size {0} completed.", messageSize);

                            Message incomingMessage = CreateMessageFromRawData(messageBuffer);
                            if (incomingMessage != null)
                            {
                                disconnect = !await messageProcessor.ProcessMessageAsync(this, incomingMessage);
                            }
                            else
                            {
                                protoViolationDisconnect = true;
                            }
                        }
                        break;
                    }
                    }

                    if (protoViolationDisconnect)
                    {
                        await messageProcessor.SendProtocolViolation(this);

                        break;
                    }

                    if (disconnect)
                    {
                        break;
                    }
                }
            }
            catch (Exception e)
            {
                if ((e is ObjectDisposedException) || (e is IOException))
                {
                    log.Info("Connection to client has been terminated.");
                }
                else
                {
                    log.Error("Exception occurred: {0}", e.ToString());
                }
            }

            log.Trace("(-)");
        }
示例#27
0
        ReadToEndAsync(
            Stream stream,
            CancellationToken cancellationToken)
        {
            int written = 0;

            byte[] rented = null;

            try
            {
                // Save the length to a local to be reused across awaits.
                int utf8BomLength = JsonConstants.Utf8Bom.Length;

                if (stream.CanSeek)
                {
                    // Ask for 1 more than the length to avoid resizing later,
                    // which is unnecessary in the common case where the stream length doesn't change.
                    long expectedLength = Math.Max(utf8BomLength, stream.Length - stream.Position) + 1;
                    rented = ArrayPool <byte> .Shared.Rent(checked ((int)expectedLength));
                }
                else
                {
                    rented = ArrayPool <byte> .Shared.Rent(UnseekableStreamInitialRentSize);
                }

                int lastRead;

                // Read up to 3 bytes to see if it's the UTF-8 BOM
                do
                {
                    // No need for checking for growth, the minimal rent sizes both guarantee it'll fit.
                    Debug.Assert(rented.Length >= JsonConstants.Utf8Bom.Length);

                    lastRead = await stream.ReadAsync(
                        rented,
                        written,
                        utf8BomLength - written,
                        cancellationToken).ConfigureAwait(false);

                    written += lastRead;
                } while (lastRead > 0 && written < utf8BomLength);

                // If we have 3 bytes, and they're the BOM, reset the write position to 0.
                if (written == utf8BomLength &&
                    JsonConstants.Utf8Bom.SequenceEqual(rented.AsSpan(0, utf8BomLength)))
                {
                    written = 0;
                }

                do
                {
                    if (rented.Length == written)
                    {
                        byte[] toReturn = rented;
                        rented = ArrayPool <byte> .Shared.Rent(toReturn.Length * 2);

                        Buffer.BlockCopy(toReturn, 0, rented, 0, toReturn.Length);
                        // Holds document content, clear it.
                        ArrayPool <byte> .Shared.Return(toReturn, clearArray : true);
                    }

                    lastRead = await stream.ReadAsync(
                        rented,
                        written,
                        rented.Length - written,
                        cancellationToken).ConfigureAwait(false);

                    written += lastRead;
                } while (lastRead > 0);

                return(new ArraySegment <byte>(rented, 0, written));
            }
            catch
            {
                if (rented != null)
                {
                    // Holds document content, clear it before returning it.
                    rented.AsSpan(0, written).Clear();
                    ArrayPool <byte> .Shared.Return(rented);
                }

                throw;
            }
        }
        public async Task GetAsync_CancelPendingRequests_DoesntCancelReadAsyncOnResponseStream(CancellationMode mode, bool copyToAsync)
        {
            if (IsNetfxHandler)
            {
                // throws ObjectDisposedException as part of Stream.CopyToAsync/ReadAsync
                return;
            }
            if (IsCurlHandler)
            {
                // Issue #27065
                // throws OperationCanceledException from Stream.CopyToAsync/ReadAsync
                return;
            }

            using (HttpClient client = CreateHttpClient())
            {
                client.Timeout = Timeout.InfiniteTimeSpan;

                await LoopbackServer.CreateServerAsync(async (server, url) =>
                {
                    var clientReadSomeBody = new TaskCompletionSource <bool>();
                    var clientFinished     = new TaskCompletionSource <bool>();

                    var responseContentSegment = new string('s', 3000);
                    int responseSegments       = 4;
                    int contentLength          = responseContentSegment.Length * responseSegments;

                    Task serverTask = server.AcceptConnectionAsync(async connection =>
                    {
                        await connection.ReadRequestHeaderAndSendCustomResponseAsync(
                            $"HTTP/1.1 200 OK\r\n" +
                            $"Date: {DateTimeOffset.UtcNow:R}\r\n" +
                            $"Content-Length: {contentLength}\r\n" +
                            $"\r\n");

                        for (int i = 0; i < responseSegments; i++)
                        {
                            await connection.Writer.WriteAsync(responseContentSegment);
                            if (i == 0)
                            {
                                await clientReadSomeBody.Task;
                            }
                        }

                        await clientFinished.Task;
                    });


                    using (HttpResponseMessage resp = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead))
                        using (Stream respStream = await resp.Content.ReadAsStreamAsync())
                        {
                            var result = new MemoryStream();
                            int b      = respStream.ReadByte();
                            Assert.NotEqual(-1, b);
                            result.WriteByte((byte)b);

                            Cancel(mode, client, null); // should not cancel the operation, as using ResponseHeadersRead
                            clientReadSomeBody.SetResult(true);

                            if (copyToAsync)
                            {
                                await respStream.CopyToAsync(result, 10, new CancellationTokenSource().Token);
                            }
                            else
                            {
                                byte[] buffer = new byte[10];
                                int bytesRead;
                                while ((bytesRead = await respStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
                                {
                                    result.Write(buffer, 0, bytesRead);
                                }
                            }

                            Assert.Equal(contentLength, result.Length);
                        }

                    clientFinished.SetResult(true);
                    await serverTask;
                });
            }
        }
        public async Task CloudFileClientMaximumExecutionTimeoutShouldNotBeHonoredForStreamsAsync()
        {
            CloudFileClient    fileClient    = GenerateCloudFileClient();
            CloudFileShare     share         = fileClient.GetShareReference(Guid.NewGuid().ToString("N"));
            CloudFileDirectory rootDirectory = share.GetRootDirectoryReference();

            byte[] buffer = FileTestBase.GetRandomBuffer(1024 * 1024);

            try
            {
                await share.CreateAsync();

                fileClient.DefaultRequestOptions.MaximumExecutionTime = TimeSpan.FromSeconds(30);
                CloudFile file = rootDirectory.GetFileReference("file");
                file.StreamMinimumReadSizeInBytes = 1024 * 1024;

                using (var fileStream = await file.OpenWriteAsync(8 * 1024 * 1024))
                {
                    Stream fos = fileStream;

                    DateTime start = DateTime.Now;
                    for (int i = 0; i < 7; i++)
                    {
                        await fos.WriteAsync(buffer, 0, buffer.Length);
                    }

                    // Sleep to ensure we are over the Max execution time when we do the last write
                    int msRemaining = (int)(fileClient.DefaultRequestOptions.MaximumExecutionTime.Value - (DateTime.Now - start)).TotalMilliseconds;

                    if (msRemaining > 0)
                    {
                        await Task.Delay(msRemaining);
                    }

                    await fos.WriteAsync(buffer, 0, buffer.Length);

                    await fileStream.CommitAsync();
                }

                using (var fileStream = await file.OpenReadAsync())
                {
                    Stream fis = fileStream;

                    DateTime start = DateTime.Now;
                    int      total = 0;
                    while (total < 7 * 1024 * 1024)
                    {
                        total += await fis.ReadAsync(buffer, 0, buffer.Length);
                    }

                    // Sleep to ensure we are over the Max execution time when we do the last read
                    int msRemaining = (int)(fileClient.DefaultRequestOptions.MaximumExecutionTime.Value - (DateTime.Now - start)).TotalMilliseconds;

                    if (msRemaining > 0)
                    {
                        await Task.Delay(msRemaining);
                    }

                    while (true)
                    {
                        int count = await fis.ReadAsync(buffer, 0, buffer.Length);

                        total += count;
                        if (count == 0)
                        {
                            break;
                        }
                    }
                }
            }
            finally
            {
                fileClient.DefaultRequestOptions.MaximumExecutionTime = null;
                share.DeleteIfExistsAsync().Wait();
            }
        }
示例#30
0
        public static async Task StreamTest(Stream stream, bool fSuppress)
        {
            string strValue;
            int    iValue;

            //[] We will first use the stream's 2 writing methods
            int iLength = 1 << 10;

            stream.Seek(0, SeekOrigin.Begin);

            for (int i = 0; i < iLength; i++)
            {
                stream.WriteByte(unchecked ((byte)i));
            }

            byte[] btArr = new byte[iLength];
            for (int i = 0; i < iLength; i++)
            {
                btArr[i] = unchecked ((byte)i);
            }
            stream.Write(btArr, 0, iLength);

            //we will write many things here using a binary writer
            BinaryWriter bw1 = new BinaryWriter(stream);

            bw1.Write(false);
            bw1.Write(true);

            for (int i = 0; i < 10; i++)
            {
                bw1.Write((byte)i);
                bw1.Write((sbyte)i);
                bw1.Write((short)i);
                bw1.Write((char)i);
                bw1.Write((ushort)i);
                bw1.Write(i);
                bw1.Write((uint)i);
                bw1.Write((long)i);
                bw1.Write((ulong)i);
                bw1.Write((float)i);
                bw1.Write((double)i);
            }

            //Some strings, chars and Bytes
            char[] chArr = new char[iLength];
            for (int i = 0; i < iLength; i++)
            {
                chArr[i] = (char)i;
            }

            bw1.Write(chArr);
            bw1.Write(chArr, 512, 512);

            bw1.Write(new string(chArr));
            bw1.Write(new string(chArr));

            //[] we will now read
            stream.Seek(0, SeekOrigin.Begin);
            for (int i = 0; i < iLength; i++)
            {
                Assert.Equal(i % 256, stream.ReadByte());
            }


            btArr = new byte[iLength];
            stream.Read(btArr, 0, iLength);
            for (int i = 0; i < iLength; i++)
            {
                Assert.Equal(unchecked ((byte)i), btArr[i]);
            }

            //Now, for the binary reader
            BinaryReader br1 = new BinaryReader(stream);

            Assert.False(br1.ReadBoolean());
            Assert.True(br1.ReadBoolean());

            for (int i = 0; i < 10; i++)
            {
                Assert.Equal((byte)i, br1.ReadByte());
                Assert.Equal((sbyte)i, br1.ReadSByte());
                Assert.Equal((short)i, br1.ReadInt16());
                Assert.Equal((char)i, br1.ReadChar());
                Assert.Equal((ushort)i, br1.ReadUInt16());
                Assert.Equal(i, br1.ReadInt32());
                Assert.Equal((uint)i, br1.ReadUInt32());
                Assert.Equal((long)i, br1.ReadInt64());
                Assert.Equal((ulong)i, br1.ReadUInt64());
                Assert.Equal((float)i, br1.ReadSingle());
                Assert.Equal((double)i, br1.ReadDouble());
            }

            chArr = br1.ReadChars(iLength);
            for (int i = 0; i < iLength; i++)
            {
                Assert.Equal((char)i, chArr[i]);
            }

            chArr = new char[512];
            chArr = br1.ReadChars(iLength / 2);
            for (int i = 0; i < iLength / 2; i++)
            {
                Assert.Equal((char)(iLength / 2 + i), chArr[i]);
            }

            chArr = new char[iLength];
            for (int i = 0; i < iLength; i++)
            {
                chArr[i] = (char)i;
            }
            strValue = br1.ReadString();
            Assert.Equal(new string(chArr), strValue);

            strValue = br1.ReadString();
            Assert.Equal(new string(chArr), strValue);

            stream.Seek(1, SeekOrigin.Current); // In the original test, success here would end the test

            //[] we will do some async tests here now
            stream.Position = 0;

            btArr = new byte[iLength];
            for (int i = 0; i < iLength; i++)
            {
                btArr[i] = unchecked ((byte)(i + 5));
            }

            await stream.WriteAsync(btArr, 0, btArr.Length);

            stream.Position = 0;
            for (int i = 0; i < iLength; i++)
            {
                Assert.Equal(unchecked ((byte)(i + 5)), stream.ReadByte());
            }

            //we will read asynchronously
            stream.Position = 0;

            byte[] compArr = new byte[iLength];

            iValue = await stream.ReadAsync(compArr, 0, compArr.Length);

            Assert.Equal(btArr.Length, iValue);

            for (int i = 0; i < iLength; i++)
            {
                Assert.Equal(compArr[i], btArr[i]);
            }
        }
示例#31
0
        public static async Task StreamTest(Stream stream, Boolean fSuppress)
        {

            string strValue;
            int iValue;

            //[] We will first use the stream's 2 writing methods
            int iLength = 1 << 10;
            stream.Seek(0, SeekOrigin.Begin);

            for (int i = 0; i < iLength; i++)
                stream.WriteByte((byte)i);

            byte[] btArr = new byte[iLength];
            for (int i = 0; i < iLength; i++)
                btArr[i] = (byte)i;
            stream.Write(btArr, 0, iLength);

            //we will write many things here using a binary writer
            BinaryWriter bw1 = new BinaryWriter(stream);
            bw1.Write(false);
            bw1.Write(true);

            for (int i = 0; i < 10; i++)
            {
                bw1.Write((byte)i);
                bw1.Write((sbyte)i);
                bw1.Write((short)i);
                bw1.Write((char)i);
                bw1.Write((UInt16)i);
                bw1.Write(i);
                bw1.Write((uint)i);
                bw1.Write((Int64)i);
                bw1.Write((ulong)i);
                bw1.Write((float)i);
                bw1.Write((double)i);
            }

            //Some strings, chars and Bytes
            char[] chArr = new char[iLength];
            for (int i = 0; i < iLength; i++)
                chArr[i] = (char)i;

            bw1.Write(chArr);
            bw1.Write(chArr, 512, 512);

            bw1.Write(new string(chArr));
            bw1.Write(new string(chArr));

            //[] we will now read
            stream.Seek(0, SeekOrigin.Begin);
            for (int i = 0; i < iLength; i++)
            {
                Assert.Equal(i % 256, stream.ReadByte());
            }


            btArr = new byte[iLength];
            stream.Read(btArr, 0, iLength);
            for (int i = 0; i < iLength; i++)
            {
                Assert.Equal((byte)i, btArr[i]);
            }

            //Now, for the binary reader
            BinaryReader br1 = new BinaryReader(stream);

            Assert.False(br1.ReadBoolean());
            Assert.True(br1.ReadBoolean());

            for (int i = 0; i < 10; i++)
            {
                Assert.Equal( (byte)i, br1.ReadByte());
                Assert.Equal((sbyte)i, br1.ReadSByte());
                Assert.Equal((short)i, br1.ReadInt16());
                Assert.Equal((char)i, br1.ReadChar());
                Assert.Equal((UInt16)i, br1.ReadUInt16());
                Assert.Equal(i, br1.ReadInt32());
                Assert.Equal((uint)i, br1.ReadUInt32());
                Assert.Equal((Int64)i, br1.ReadInt64());
                Assert.Equal((ulong)i, br1.ReadUInt64());
                Assert.Equal((float)i, br1.ReadSingle());
                Assert.Equal((double)i, br1.ReadDouble());
            }

            chArr = br1.ReadChars(iLength);
            for (int i = 0; i < iLength; i++)
            {
                Assert.Equal((char)i, chArr[i]);
            }

            chArr = new char[512];
            chArr = br1.ReadChars(iLength / 2);
            for (int i = 0; i < iLength / 2; i++)
            {
                Assert.Equal((char)(iLength / 2 + i), chArr[i]);
            }

            chArr = new char[iLength];
            for (int i = 0; i < iLength; i++)
                chArr[i] = (char)i;
            strValue = br1.ReadString();
            Assert.Equal(new string(chArr), strValue);

            strValue = br1.ReadString();
            Assert.Equal(new string(chArr), strValue);

            stream.Seek(1, SeekOrigin.Current); // In the original test, success here would end the test

            //[] we will do some async tests here now
            stream.Position = 0;

            btArr = new byte[iLength];
            for (int i = 0; i < iLength; i++)
                btArr[i] = (byte)(i + 5);

            await stream.WriteAsync(btArr, 0, btArr.Length);

            stream.Position = 0;
            for (int i = 0; i < iLength; i++)
            {
                Assert.Equal((byte)(i + 5), stream.ReadByte());
            }

            //we will read asynchronously
            stream.Position = 0;

            byte[] compArr = new byte[iLength];

            iValue = await stream.ReadAsync(compArr, 0, compArr.Length);

            Assert.Equal(btArr.Length, iValue);

            for (int i = 0; i < iLength; i++)
            {
                Assert.Equal(compArr[i], btArr[i]);
            }
        }
        public void ReadAsync_OffsetIsNegative_ThrowsArgumentOutOfRangeException()
        {
            Stream stream = MakeResponseStream();

            Assert.Throws <ArgumentOutOfRangeException>(() => { Task t = stream.ReadAsync(new byte[1], -1, 1); });
        }