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); }
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); }