private async Task HLSHandler(IOwinContext ctx)
        {
            var ct  = ctx.Request.CallCancelled;
            var req = ParsedRequest.Parse(ctx);

            if (!req.IsValid)
            {
                ctx.Response.StatusCode = (int)req.Status;
                return;
            }
            Channel channel;

            try {
                channel = await GetChannelAsync(ctx, req, ct).ConfigureAwait(false);
            }
            catch (TaskCanceledException) {
                ctx.Response.StatusCode = (int)HttpStatusCode.GatewayTimeout;
                return;
            }
            if (channel == null)
            {
                ctx.Response.StatusCode = (int)HttpStatusCode.NotFound;
                return;
            }

            if (req.FragmentNumber.HasValue)
            {
                await FragmentHandler(ctx, req, channel).ConfigureAwait(false);
            }
            else
            {
                await PlayListHandler(ctx, req, channel).ConfigureAwait(false);
            }
        }
Beispiel #2
0
        public void TestEmpty()
        {
            ParsedRequest parsedRequest;
            string        error;
            var           isOk = ParsedRequest.Parse("", 1, out parsedRequest, out error);

            Assert.False(isOk);
        }
Beispiel #3
0
        public void TestAge40()
        {
            ParsedRequest parsedRequest;
            string        error;
            var           isOk = ParsedRequest.Parse("40", 1, out parsedRequest, out error);

            Assert.True(isOk);
            Assert.Null(parsedRequest.phone);
            Assert.Equal(parsedRequest.age, 40);
        }
Beispiel #4
0
        public void TestMix()
        {
            ParsedRequest parsedRequest;
            string        error;
            var           isOk = ParsedRequest.Parse("A1B2C3", 1, out parsedRequest, out error);

            Assert.True(isOk);
            Assert.Equal(parsedRequest.name, "A1B2C3");
            Assert.Null(parsedRequest.phone);
            Assert.Null(parsedRequest.age);
        }
Beispiel #5
0
        public void TestPhone160()
        {
            ParsedRequest parsedRequest;
            string        error;
            var           isOk = ParsedRequest.Parse("160", 1, out parsedRequest, out error);

            Assert.True(isOk);
            Assert.Null(parsedRequest.name);
            Assert.Equal(parsedRequest.phone, "160");
            Assert.Null(parsedRequest.age);
        }
Beispiel #6
0
        public void TestNameWithSpaceAndAge()
        {
            ParsedRequest parsedRequest;
            string        error;
            var           isOk = ParsedRequest.Parse("ders Karl 24", 1, out parsedRequest, out error);

            Assert.True(isOk);
            Assert.Equal(parsedRequest.name, "ders Karl");
            Assert.Null(parsedRequest.phone);
            Assert.Equal(parsedRequest.age, 24);
        }
Beispiel #7
0
        public void TestAllComponents()
        {
            ParsedRequest parsedRequest;
            string        error;
            var           isOk = ParsedRequest.Parse("20 Johan 1234-567890", 1, out parsedRequest, out error);

            Assert.True(isOk);
            Assert.Equal(parsedRequest.name, "Johan");
            Assert.Equal(parsedRequest.phone, "1234-567890");
            Assert.Equal(parsedRequest.age, 20);
        }
        private static async Task StreamHandler(IOwinContext ctx)
        {
            var logger = new Logger(typeof(HTTPDirectOwinApp), $"{ctx.Request.RemoteIpAddress}:{ctx.Request.RemotePort}");
            var ct     = ctx.Request.CallCancelled;
            var req    = ParsedRequest.Parse(ctx);

            if (!req.IsValid)
            {
                ctx.Response.StatusCode = (int)req.Status;
                return;
            }
            Channel channel;

            try {
                channel = await GetChannelAsync(ctx, req, ct).ConfigureAwait(false);
            }
            catch (TaskCanceledException) {
                ctx.Response.StatusCode = (int)HttpStatusCode.GatewayTimeout;
                return;
            }
            if (channel == null)
            {
                ctx.Response.StatusCode = (int)HttpStatusCode.NotFound;
                return;
            }
            var sink = new ChannelSink(ctx);

            using (channel.AddOutputStream(sink))
                using (channel.AddContentSink(sink)) {
                    ctx.Response.StatusCode = (int)HttpStatusCode.OK;
                    bool asf =
                        channel.ChannelInfo.ContentType == "WMV" ||
                        channel.ChannelInfo.ContentType == "WMA" ||
                        channel.ChannelInfo.ContentType == "ASX";

                    if (asf && (!ctx.Request.Headers.TryGetValue("Pragma", out var values) || !values.Contains("xplaystrm=1", StringComparer.InvariantCultureIgnoreCase)))
                    {
                        ctx.Response.Headers.Add("Cache-Control", new string [] { "no-cache" });
                        ctx.Response.Headers.Add("Server", new string [] { "Rex/9.0.2980" });
                        ctx.Response.Headers.Add("Pragma", new string [] { "no-cache", @"features=""broadcast,playlist""" });
                        ctx.Response.Headers.Add("Access-Control-Allow-Origin", new string[] { "*" });
                        ctx.Response.ContentType = "application/vnd.ms.wms-hdr.asfv1";

                        try {
                            while (!ct.IsCancellationRequested)
                            {
                                var packet = await sink.DequeueAsync(ct).ConfigureAwait(false);

                                ctx.Response.ContentLength = packet.Content.Data.Length;
                                if (packet.Type == ChannelSink.ChannelMessage.MessageType.ContentHeader)
                                {
                                    await ctx.Response.WriteAsync(packet.Content.Data, ct).ConfigureAwait(false);

                                    logger.Debug("Sent ContentHeader pos {0}", packet.Content.Position);
                                    break;
                                }
                                else if (packet.Type == ChannelSink.ChannelMessage.MessageType.ChannelStopped)
                                {
                                    break;
                                }
                            }
                        }
                        catch (OperationCanceledException) {
                        }
                    }
                    else
                    {
                        if (asf)
                        {
                            ctx.Response.Headers.Add("Cache-Control", new string [] { "no-cache" });
                            ctx.Response.Headers.Add("Server", new string [] { "Rex/9.0.2980" });
                            ctx.Response.Headers.Add("Pragma", new string [] { "no-cache", @"features=""broadcast,playlist""" });
                            ctx.Response.Headers.Add("Access-Control-Allow-Origin", new string[] { "*" });
                            ctx.Response.ContentType = "application/x-mms-framed";
                            ctx.Response.Headers.Add("Connection", new string[] { "close" });
                        }
                        else
                        {
                            ctx.Response.ContentType = channel.ChannelInfo.MIMEType;
                            ctx.Response.Headers.Add("Access-Control-Allow-Origin", new string[] { "*" });
                            ctx.Response.Headers.Add("Transfer-Encoding", new string [] { "chunked" });
                        }

                        Content sent_header = null;
                        Content sent_packet = null;
                        try {
                            while (!ct.IsCancellationRequested)
                            {
                                var packet = await sink.DequeueAsync(ct).ConfigureAwait(false);

                                if (packet.Type == ChannelSink.ChannelMessage.MessageType.ContentHeader)
                                {
                                    if (sent_header != packet.Content && packet.Content != null)
                                    {
                                        await ctx.Response.WriteAsync(packet.Content.Data, ct).ConfigureAwait(false);

                                        logger.Debug("Sent ContentHeader pos {0}", packet.Content.Position);
                                        sent_header = packet.Content;
                                        sent_packet = packet.Content;
                                    }
                                }
                                else if (packet.Type == ChannelSink.ChannelMessage.MessageType.ContentBody)
                                {
                                    if (sent_header == null)
                                    {
                                        continue;
                                    }
                                    var c = packet.Content;
                                    if (c.Timestamp > sent_packet.Timestamp ||
                                        (c.Timestamp == sent_packet.Timestamp && c.Position > sent_packet.Position))
                                    {
                                        await ctx.Response.WriteAsync(c.Data, ct).ConfigureAwait(false);

                                        sent_packet = c;
                                    }
                                }
                                else if (packet.Type == ChannelSink.ChannelMessage.MessageType.ChannelStopped)
                                {
                                    break;
                                }
                            }
                        }
                        catch (OperationCanceledException) {
                        }
                    }
                }
        }
        private static async Task PlayListHandler(IOwinContext ctx)
        {
            var ct  = ctx.Request.CallCancelled;
            var req = ParsedRequest.Parse(ctx);

            if (!req.IsValid)
            {
                ctx.Response.StatusCode = (int)req.Status;
                return;
            }
            Channel channel;

            try {
                channel = await GetChannelAsync(ctx, req, ct).ConfigureAwait(false);
            }
            catch (TaskCanceledException) {
                ctx.Response.StatusCode = (int)HttpStatusCode.GatewayTimeout;
                return;
            }
            if (channel == null)
            {
                ctx.Response.StatusCode = (int)HttpStatusCode.NotFound;
                return;
            }

            var fmt = ctx.Request.Query.Get("pls") ?? req.Extension;

            //m3u8のプレイリストを要求された時はHLS用のパスに転送する
            if (fmt?.ToLowerInvariant() == "m3u8")
            {
                ctx.Response.StatusCode = (int)HttpStatusCode.MovedPermanently;
                var location = new UriBuilder(ctx.Request.Uri);
                location.Path = $"/hls/{req.ChannelId.ToString("N")}";
                if (location.Query.Contains("pls=m3u8"))
                {
                    var queries = location.Query.Substring(1).Split('&').Where(seg => seg != "pls=m3u8").ToArray();
                    if (queries.Length > 0)
                    {
                        location.Query = String.Join("&", queries);
                    }
                    else
                    {
                        location.Query = null;
                    }
                }
                ctx.Response.Headers.Add("Location", new string [] { location.Uri.ToString() });
                return;
            }

            var scheme = ctx.Request.Query.Get("scheme");
            var pls    = CreatePlaylist(channel, fmt, scheme);

            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;
            byte[] body;
            try {
                var baseuri = new Uri(
                    new Uri(ctx.Request.Uri.GetComponents(UriComponents.SchemeAndServer | UriComponents.UserInfo, UriFormat.UriEscaped)),
                    "stream/");
                var acinfo = ctx.GetAccessControlInfo();
                using (var cts = CancellationTokenSource.CreateLinkedTokenSource(ct)) {
                    cts.CancelAfter(10000);
                    if (acinfo.AuthorizationRequired)
                    {
                        var parameters = new Dictionary <string, string>()
                        {
                            { "auth", acinfo.AuthenticationKey.GetToken() },
                        };
                        body = await pls.CreatePlayListAsync(baseuri, parameters, cts.Token).ConfigureAwait(false);
                    }
                    else
                    {
                        body = await pls.CreatePlayListAsync(baseuri, Enumerable.Empty <KeyValuePair <string, string> >(), 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);
        }
Beispiel #10
0
        public async Task <Tuple <int, SearchResult> > GetResult(Tuple <string, int> key)
        {
            Tuple <int, SearchResult> result;

            if (_cache.TryGetValue(key, out result))
            {
                return(result);
            }

            var       log = new StringBuilder();
            Stopwatch sw  = new Stopwatch();

            sw.Start();
            ParsedRequest parsedRequest;
            string        error;

            if (ParsedRequest.Parse(key.Item1, key.Item2, out parsedRequest, out error))
            {
                var jsonParsedRequest = JsonConvert.SerializeObject(parsedRequest);
                log.AppendFormat("Parsed request: {0}\n", jsonParsedRequest);
                var peopleSearchUri = GetPeopleSearchUri(parsedRequest);

                CancellationTokenSource cts1 = new CancellationTokenSource();
                var peopleSearchResult       = await CreateClientRequest()
                                               .PostAsync(peopleSearchUri, new StringContent(jsonParsedRequest), cts1.Token);

                string requestId;
                try
                {
                    dynamic data =
                        JsonConvert.DeserializeObject(await peopleSearchResult.Content.ReadAsStringAsync());
                    requestId = data.id;
                }
                catch (RuntimeBinderException)
                {
                    requestId = null;
                }

                log.AppendFormat("Request id: {0}\n", requestId);

                if (requestId != null)
                {
                    var peopleSearchResultUri = GetPeopleSearchResultUri(requestId);

                    CancellationTokenSource cts2    = new CancellationTokenSource();
                    HttpResponseMessage     result2 = null;
                    var retries = 0;
                    while (result2 == null)
                    {
                        try
                        {
                            result2 = await CreateClientRequest().GetAsync(peopleSearchResultUri, cts2.Token);
                        }
                        catch (HttpRequestException ex)
                        {
                            if (retries++ > 20)
                            {
                                throw;
                            }

                            log.AppendFormat("Search result not ready yet ({0}), retrying...\n", ex.Message);
                            Thread.Sleep(500);
                        }
                    }

                    var strData = await result2.Content.ReadAsStringAsync();

                    var data = JsonConvert.DeserializeObject <Person[]>(strData);
                    sw.Stop();
                    var resultContent = new SearchResult
                    {
                        data      = data,
                        page      = key.Item2,
                        log       = log.ToString(),
                        requestId = requestId,
                        timestamp = DateTime.UtcNow,
                        duration  = sw.ElapsedMilliseconds
                    };

                    result = Tuple.Create(200, resultContent);
                }
                else
                {
                    log.AppendFormat("Cannot get requestId\n");
                    sw.Stop();
                    result = Tuple.Create(500, new SearchResult
                    {
                        data      = null,
                        log       = log.ToString(),
                        requestId = null,
                        timestamp = DateTime.UtcNow,
                        duration  = sw.ElapsedMilliseconds
                    });
                }
            }
            else
            {
                log.AppendFormat("Cannot parse query. Error: {0}\n", error);
                sw.Stop();

                result = Tuple.Create(400, new SearchResult
                {
                    data      = null,
                    log       = log.ToString(),
                    requestId = null,
                    timestamp = DateTime.UtcNow,
                    duration  = sw.ElapsedMilliseconds
                });
            }

            var options = new MemoryCacheEntryOptions()
                          // Keep in cache for this time, reset time if accessed.
                          .SetSlidingExpiration(TimeSpan.FromHours(1));

            _cache.Set(key, result, options);
            return(result);
        }