Ejemplo n.º 1
0
        async Task HandleMediaPlayerContextAsync(HttpListenerContext context, CancellationToken token)
        {
            long firstByte = 0;
            long lastByte  = Stream.Length - 1;

            var range = context.Request.Headers["Range"];

            if (range != null && range.StartsWith("bytes="))
            {
                Debug.WriteLine(string.Format("Client requested: {0}", range));
                var parts = range.Substring("bytes=".Length).Split(new[] { '-' }, StringSplitOptions.RemoveEmptyEntries);
                if (parts.Length == 1)
                {
                    firstByte = long.Parse(parts[0]);
                }
                else if (parts.Length == 2)
                {
                    firstByte = long.Parse(parts[0]);
                    lastByte  = long.Parse(parts[1]); // The range is inclusive, so we should add '1' to this offset so we send the last byte.
                }
            }

            // Clamp the last byte in case someone's player is over-reading. UWP likes to overread because it's terrible.
            if (lastByte > Stream.Length - 1)
            {
                lastByte = Stream.Length - 1;
            }

            // Some HTTP magic
            var buffer = new byte[64 * 1024];

            context.Response.SendChunked = true;
            context.Response.AppendHeader("Content-Range", $"bytes {firstByte}-{lastByte}");
            context.Response.StatusCode      = (int)HttpStatusCode.PartialContent;
            context.Response.ContentLength64 = lastByte - firstByte + 1;
            Debug.WriteLine($"Requested {firstByte} -> {lastByte}. Length: {context.Response.ContentLength64}");
            while (firstByte <= lastByte)
            {
                // Read the data and stream it back to the media player.
                try {
                    await ReadLocker.WaitAsync();

                    token.ThrowIfCancellationRequested();
                    if (Stream.Position != firstByte)
                    {
                        Stream.Seek(firstByte, SeekOrigin.Begin);
                    }
                    var read = await Stream.ReadAsync(buffer, 0, (int)Math.Min(lastByte - firstByte + 1, buffer.Length), token);

                    await context.Response.OutputStream.WriteAsync(buffer, 0, read, token);

                    await context.Response.OutputStream.FlushAsync(token);

                    firstByte += read;
                } finally {
                    ReadLocker.Release();
                }
            }
            Debug.WriteLine("Successfully transferred {0} -> {1}. Length: {2}", firstByte, lastByte, context.Response.ContentLength64);
        }
Ejemplo n.º 2
0
        async Task HandleMediaPlayerContextAsync(HttpListenerContext context, CancellationToken token)
        {
            long firstByte = 0;
            long lastByte  = Stream.Length - 1;

            var range = context.Request.Headers["Range"];

            if (range != null && range.StartsWith("bytes="))
            {
                Debug.WriteLine(string.Format("Client requested: {0}", range));
                var parts = range.Substring("bytes=".Length).Split(new[] { '-' }, StringSplitOptions.RemoveEmptyEntries);
                if (parts.Length == 1)
                {
                    firstByte = long.Parse(parts[0]);
                }
                else if (parts.Length == 2)
                {
                    firstByte = long.Parse(parts[0]);
                    lastByte  = long.Parse(parts[1]); // The range is inclusive, so we should add '1' to this offset so we send the last byte.
                }
            }

            // Clamp the last byte in case someone's player is over-reading. UWP likes to overread because it's terrible.
            if (lastByte > Stream.Length - 1)
            {
                lastByte = Stream.Length - 1;
            }

            // Some HTTP magic
            var buffer = new byte[64 * 1024];

            context.Response.SendChunked = true;
            context.Response.AppendHeader("Content-Range", $"bytes {firstByte}-{lastByte}");

            //--- CORS Policy Declined goes away. A lot of SocketExceptions and MonoTorrent.Tracker Exceptions happen. When reverting to original Pre-release 132 Nupackage. No exceptions thrown.
            //--- HTML5 Player uses HLS.JS and does something, enables play button. When going to Url obtained from CreateHttpStreamAsync, Download Failed - No File.
            //--- NodeJS Express Server CORS enabled is: 127.0.0.1:8888
            context.Response.AppendHeader("Access-Control-Allow-Origin", "*");  //-- should allow CORS from another domain.
            context.Response.AppendHeader("Access-Control-Allow-Headers", "Content-Type,x-requested-with");
            context.Response.AppendHeader("Access-Control-Allow-Methods", "GET,POST,PUT,HEAD,DELETE,OPTIONS");

            context.Response.StatusCode      = (int)HttpStatusCode.PartialContent;
            context.Response.ContentLength64 = lastByte - firstByte + 1;
            Debug.WriteLine($"Requested {firstByte} -> {lastByte}. Length: {context.Response.ContentLength64}");
            while (firstByte <= lastByte)
            {
                // Read the data and stream it back to the media player.
                try {
                    await ReadLocker.WaitAsync();

                    token.ThrowIfCancellationRequested();
                    if (Stream.Position != firstByte)
                    {
                        Stream.Seek(firstByte, SeekOrigin.Begin);
                    }
                    var read = await Stream.ReadAsync(buffer, 0, (int)Math.Min(lastByte - firstByte + 1, buffer.Length), token);

                    await context.Response.OutputStream.WriteAsync(buffer, 0, read, token);

                    await context.Response.OutputStream.FlushAsync(token);

                    firstByte += read;
                } finally {
                    ReadLocker.Release();
                }
            }
            Debug.WriteLine("Successfully transferred {0} -> {1}. Length: {2}", firstByte, lastByte, context.Response.ContentLength64);
        }