Пример #1
0
        private async void ReadSource()
        {
            Exception possibleError = null;
            bool      tryAgain      = true;

            while (tryAgain)
            {
                tryAgain = false;
                currentAttemptStopwatch        = null;
                currentAttemptLastReceivedData = TimeSpan.Zero;
                currentAttemptReceivedBytes    = 0;
                Stream sourceStream;
                try
                {
                    var response = await getResponse(this.availableBytes);

                    this.response.TrySetResult(response);
                    if (this.availableBytes == 0)
                    {
#if WEBCLIENT
                        size = response.ContentLength != -1 ? response.ContentLength : (long?)null;
#else
                        var ce = response.Content.Headers.ContentEncoding;
                        if (ce == null || !ce.Any())
                        {
                            size = response.Content.Headers.ContentLength;
                        }
#endif
                    }
                    if (availableBytes != 0)
                    {
#if WEBCLIENT
                        var cr = response.Headers["Content-Range"];
                        // HACK: trust the server to return the expected range
                        if (string.IsNullOrEmpty(cr))
#else
                        if (response.Content == null || response.Content.Headers.ContentRange == null || response.Content.Headers.ContentRange.From.GetValueOrDefault(-1) != availableBytes)
#endif
                        {
                            response.Dispose();
                            throw new NotSupportedException("The web server did not return the expected range of data.");
                        }
                    }
                    if (data == null)
                    {
                        response.Dispose();
                        return;
                    }
#if WEBCLIENT
                    sourceStream = await TaskEx.Run(() => response.GetResponseStream());
#else
                    sourceStream = await response.Content.ReadAsStreamAsync();
#endif
                }
                catch (Exception ex)
                {
                    if (possibleError == null)
                    {
                        possibleError = ex;
                    }
                    break;
                }


                this.source = sourceStream;



                var timedOut = false;
                using (sourceStream)
                    using (var w = new Watchdog(Configuration_AudioReadTimeout, () => { timedOut = true; var s = sourceStream; if (s != null)
                                                                                        {
                                                                                            s.Dispose();
                                                                                        }
                                                }))
                    {
                        while (true)
                        {
                            if (data == null)
                            {
                                return;
                            }
                            byte[] slot;
                            if (currentSlotFreeSpace == 0)
                            {
                                slot = new byte[SlotSize];
                                MaybeCleanupOldSlots();
                                currentSlotFreeSpace = SlotSize;
                                data.Add(slot);
                            }
                            else
                            {
                                slot = data[data.Count - 1];
                            }

                            int waitAndRetry = 0;

                            try
                            {
                                var readBytes = source.Read(slot,
                                                            SlotSize - currentSlotFreeSpace,
                                                            Math.Min(currentSlotFreeSpace, ReadGranularity));

                                w.Pulse();



                                if (currentAttemptStopwatch == null)
                                {
                                    currentAttemptStopwatch = Stopwatch.StartNew();
                                }
                                currentAttemptLastReceivedData = currentAttemptStopwatch.Elapsed;

                                if (readBytes == 0)
                                {
                                    completed = true;
                                    CloseSource();
                                    if (size.HasValue)
                                    {
                                        EnsureCorrectNumberOfBytes(availableBytes, size.Value);
                                    }
                                    size = availableBytes;
                                    OnNewDataAvailable();
                                    currentAttemptStopwatch.Stop();
                                    return;
                                }
                                else
                                {
                                    possibleError = null;
                                    currentAttemptReceivedBytes += readBytes;
                                    var modified = availableBytes + readBytes;

                                    Interlocked.Exchange(ref availableBytes, modified);
                                    currentSlotFreeSpace -= readBytes;

                                    OnNewDataAvailable();
                                    if (availableBytes >= Configuration_PrefetchLength && (consumers == 0 || availableBytes > maxRequestedByte + Configuration_NonRequestedDataLimit))
                                    {
                                        await TaskEx.Delay(1000 *readBytes / (consumers == 0 ? Configuration_AfterPrefetchIdleSpeed : Configuration_IdleMaxSpeed));
                                    }
                                }
                            }
                            catch (Exception ex)
                            {
                                if (data == null)
                                {
                                    return;
                                }
                                if (timedOut)
                                {
                                    ex = new TimeoutException();
                                }
                                if (possibleError == null)
                                {
                                    possibleError = ex;
                                }
                                if (currentAttemptStopwatch != null)
                                {
                                    currentAttemptStopwatch.Stop();
                                }
                                if (currentAttemptReceivedBytes >= 1 * 1024 * 1024 && !(ex is InvalidDataException))
                                {
                                    waitAndRetry = 2;
                                }
                                else
                                {
                                    waitAndRetry = 1;
                                }
                            }
                            if (waitAndRetry != 0)
                            {
                                if (waitAndRetry == 2)
                                {
                                    await TaskEx.Delay(ZeroSpeedAfterSilenceMilliseconds);

                                    OnNewDataAvailable();
                                    await TaskEx.Delay(10000 - ZeroSpeedAfterSilenceMilliseconds);

                                    tryAgain = true;
                                }
                                break;
                            }
                        }
                    }
            }
            if (possibleError != null)
            {
                error = possibleError;
                OnNewDataAvailable();
                CloseSource();
            }
        }
Пример #2
0
        private async void ReadSource()
        {
            Exception possibleError = null;
            bool tryAgain = true;
            while (tryAgain)
            {
                tryAgain = false;
                currentAttemptStopwatch = null;
                currentAttemptLastReceivedData = TimeSpan.Zero;
                currentAttemptReceivedBytes = 0;
                Stream sourceStream;
                try
                {
                    var response = await getResponse(this.availableBytes);
                    if (this.availableBytes == 0)
                    {
#if WEBCLIENT
                        size = response.ContentLength != -1 ? response.ContentLength : (long?)null;
#else
                        var ce = response.Content.Headers.ContentEncoding;
                        if (ce == null || !ce.Any())
                            size = response.Content.Headers.ContentLength;
#endif
                    }
                    if (availableBytes != 0)
                    {
#if WEBCLIENT
                        var cr = response.Headers["Content-Range"];
                        // HACK: trust the server to return the expected range
                        if (string.IsNullOrEmpty(cr))
#else
                        if (response.Content == null || response.Content.Headers.ContentRange == null || response.Content.Headers.ContentRange.From.GetValueOrDefault(-1) != availableBytes)
#endif
                        {
                            response.Dispose();
                            throw new NotSupportedException("The web server did not return the expected range of data.");
                        }
                    }
                    if (data == null)
                    {
                        response.Dispose();
                        return;
                    }
#if WEBCLIENT
                    sourceStream = await TaskEx.Run(() => response.GetResponseStream());
#else
                    sourceStream = await response.Content.ReadAsStreamAsync();
#endif
                }
                catch (Exception ex)
                {
                    if (possibleError == null) possibleError = ex;
                    break;
                }


                this.source = sourceStream;





                var timedOut = false;
                using (sourceStream)
                using (var w = new Watchdog(Configuration_AudioReadTimeout, () => { timedOut = true; var s = sourceStream; if (s != null) s.Dispose(); }))
                {

                    while (true)
                    {
                        if (data == null) return;
                        byte[] slot;
                        if (currentSlotFreeSpace == 0)
                        {
                            slot = new byte[SlotSize];
                            MaybeCleanupOldSlots();
                            currentSlotFreeSpace = SlotSize;
                            data.Add(slot);
                        }
                        else
                        {
                            slot = data[data.Count - 1];
                        }

                        int waitAndRetry = 0;

                        try
                        {
                            var readBytes = source.Read(slot,
                                  SlotSize - currentSlotFreeSpace,
                                  Math.Min(currentSlotFreeSpace, ReadGranularity));

                            w.Pulse();



                            if (currentAttemptStopwatch == null)
                            {
                                currentAttemptStopwatch = Stopwatch.StartNew();
                            }
                            currentAttemptLastReceivedData = currentAttemptStopwatch.Elapsed;

                            if (readBytes == 0)
                            {
                                completed = true;
                                CloseSource();
                                if (size.HasValue) EnsureCorrectNumberOfBytes(availableBytes, size.Value);
                                size = availableBytes;
                                OnNewDataAvailable();
                                currentAttemptStopwatch.Stop();
                                return;
                            }
                            else
                            {
                                possibleError = null;
                                currentAttemptReceivedBytes += readBytes;
                                var modified = availableBytes + readBytes;

                                Interlocked.Exchange(ref availableBytes, modified);
                                currentSlotFreeSpace -= readBytes;

                                OnNewDataAvailable();
                                if (availableBytes >= Configuration_PrefetchLength && (consumers == 0 || availableBytes > maxRequestedByte + Configuration_NonRequestedDataLimit))
                                {
                                    await TaskEx.Delay(1000 * readBytes / (consumers == 0 ? Configuration_AfterPrefetchIdleSpeed : Configuration_IdleMaxSpeed));
                                }

                            }

                        }
                        catch (Exception ex)
                        {
                            if (data == null) return;
                            if (timedOut) ex = new TimeoutException();
                            if (possibleError == null) possibleError = ex;
                            if (currentAttemptStopwatch != null) currentAttemptStopwatch.Stop();
                            if (currentAttemptReceivedBytes >= 1 * 1024 * 1024 && !(ex is InvalidDataException)) waitAndRetry = 2;
                            else waitAndRetry = 1;
                        }
                        if (waitAndRetry != 0)
                        {
                            if (waitAndRetry == 2)
                            {
                                await TaskEx.Delay(ZeroSpeedAfterSilenceMilliseconds);
                                OnNewDataAvailable();
                                await TaskEx.Delay(10000 - ZeroSpeedAfterSilenceMilliseconds);
                                tryAgain = true;
                            }
                            break;
                        }

                    }
                }



            }
            if (possibleError != null)
            {
                error = possibleError;
                OnNewDataAvailable();
                CloseSource();
            }
        }