private async Task FragmentHandler(IOwinContext ctx, ParsedRequest req, Channel channel) { var ct = ctx.Request.CallCancelled; using (var subscription = HLSChannelSink.GetSubscription(this, channel, ctx, req.Session)) { subscription.Stopped.ThrowIfCancellationRequested(); using (var cts = CancellationTokenSource.CreateLinkedTokenSource(ct, subscription.Stopped)) { cts.CancelAfter(10000); var segments = await subscription.Segmenter.GetSegmentsAsync(cts.Token).ConfigureAwait(false); var segment = segments.FirstOrDefault(s => s.Index == req.FragmentNumber); if (segment.Index == 0) { ctx.Response.StatusCode = (int)HttpStatusCode.NotFound; } else { ctx.Response.StatusCode = (int)HttpStatusCode.OK; ctx.Response.Headers.Add("Access-Control-Allow-Origin", new string[] { "*" }); ctx.Response.ContentType = "video/MP2T"; ctx.Response.ContentLength = segment.Data.LongLength; await ctx.Response.WriteAsync(segment.Data, cts.Token).ConfigureAwait(false); } } } }
private async Task PlayListHandler(IOwinContext ctx, ParsedRequest req, Channel channel) { var ct = ctx.Request.CallCancelled; var session = req.Session; if (String.IsNullOrWhiteSpace(session)) { var source = new IPEndPoint(IPAddress.Parse(ctx.Request.RemoteIpAddress), ctx.Request.RemotePort ?? 0).ToString(); using (var md5 = System.Security.Cryptography.MD5.Create()) { session = md5 .ComputeHash(System.Text.Encoding.ASCII.GetBytes(source)) .Aggregate(new System.Text.StringBuilder(), (builder, v) => builder.Append(v.ToString("X2"))) .ToString(); } var location = new UriBuilder(ctx.Request.Uri); if (String.IsNullOrEmpty(location.Query)) { location.Query = $"session={session}"; } else { location.Query = location.Query.Substring(1) + $"&session={session}"; } ctx.Response.Redirect(location.Uri.ToString()); return; } var pls = new M3U8PlayList(ctx.Request.Query.Get("scheme"), channel); ctx.Response.StatusCode = (int)HttpStatusCode.OK; ctx.Response.Headers.Add("Cache-Control", new string [] { "private" }); ctx.Response.Headers.Add("Cache-Disposition", new string [] { "inline" }); ctx.Response.Headers.Add("Access-Control-Allow-Origin", new string[] { "*" }); ctx.Response.ContentType = pls.MIMEType; using (var subscription = HLSChannelSink.GetSubscription(this, channel, ctx, session)) { subscription.Stopped.ThrowIfCancellationRequested(); byte[] body; try { var baseuri = new Uri( new Uri(ctx.Request.Uri.GetComponents(UriComponents.SchemeAndServer | UriComponents.UserInfo, UriFormat.UriEscaped)), "hls/"); var acinfo = ctx.GetAccessControlInfo(); using (var cts = CancellationTokenSource.CreateLinkedTokenSource(ct, subscription.Stopped)) { cts.CancelAfter(10000); if (acinfo.AuthorizationRequired) { var parameters = new Dictionary <string, string>() { { "auth", acinfo.AuthenticationKey.GetToken() }, { "session", subscription.SessionId }, }; body = await pls.CreatePlayListAsync(baseuri, parameters, subscription.Segmenter, cts.Token).ConfigureAwait(false); } else { var parameters = new Dictionary <string, string>() { { "session", subscription.SessionId }, }; body = await pls.CreatePlayListAsync(baseuri, parameters, subscription.Segmenter, cts.Token).ConfigureAwait(false); } } } catch (OperationCanceledException) { ctx.Response.StatusCode = (int)HttpStatusCode.GatewayTimeout; return; } ctx.Response.StatusCode = (int)HttpStatusCode.OK; await ctx.Response.WriteAsync(body, ct).ConfigureAwait(false); } }