From dfa437a639b95712222020a2f60bd27e2e61b724 Mon Sep 17 00:00:00 2001
From: "SmallChi(Koike)" <564952747@qq.com>
Date: Sat, 8 Aug 2020 23:44:51 +0800
Subject: [PATCH] =?UTF-8?q?1.=E5=AE=8C=E5=96=84hls=E6=96=87=E4=BB=B6?=
=?UTF-8?q?=E7=9A=84=E8=AF=BB=E5=8F=96=202.=E6=B7=BB=E5=8A=A0http=E5=8D=8F?=
=?UTF-8?q?=E8=B0=83=E5=99=A8=E5=AE=A2=E6=88=B7=E7=AB=AF?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../JT1078.Gateway.TestNormalHosting.csproj | 6 +++
.../wwwroot/demo/demo.m3u8 | 1 +
.../wwwroot/demo/demo.ts | 1 +
.../Configurations/JT1078Configuration.cs | 4 ++
.../Extensions/JT1078HttpContextExtensions.cs | 5 ++
.../JT1078CoordinatorHttpClient.cs | 29 ++++++++++
src/JT1078.Gateway/JT1078HttpServer.cs | 54 ++++++++++++++++++-
7 files changed, 99 insertions(+), 1 deletion(-)
create mode 100644 src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/demo.m3u8
create mode 100644 src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/demo.ts
create mode 100644 src/JT1078.Gateway/JT1078CoordinatorHttpClient.cs
diff --git a/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/JT1078.Gateway.TestNormalHosting.csproj b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/JT1078.Gateway.TestNormalHosting.csproj
index cde7db3..a88eb40 100644
--- a/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/JT1078.Gateway.TestNormalHosting.csproj
+++ b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/JT1078.Gateway.TestNormalHosting.csproj
@@ -20,5 +20,11 @@
Always
+
+ Always
+
+
+ Always
+
diff --git a/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/demo.m3u8 b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/demo.m3u8
new file mode 100644
index 0000000..de79cca
--- /dev/null
+++ b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/demo.m3u8
@@ -0,0 +1 @@
+m3u8 demo
\ No newline at end of file
diff --git a/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/demo.ts b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/demo.ts
new file mode 100644
index 0000000..1660b9e
--- /dev/null
+++ b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/demo.ts
@@ -0,0 +1 @@
+ts demo
\ No newline at end of file
diff --git a/src/JT1078.Gateway/Configurations/JT1078Configuration.cs b/src/JT1078.Gateway/Configurations/JT1078Configuration.cs
index 2793fcd..57f582e 100644
--- a/src/JT1078.Gateway/Configurations/JT1078Configuration.cs
+++ b/src/JT1078.Gateway/Configurations/JT1078Configuration.cs
@@ -29,6 +29,10 @@ namespace JT1078.Gateway.Configurations
/// Udp 60s检查一次
///
public int UdpReceiveTimeoutCheckTimeSeconds { get; set; } = 60;
+ ///
+ /// Hls根目录
+ ///
+ public string HlsRootDirectory { get; set; } = "wwwroot";
public JT1078Configuration Value => this;
}
diff --git a/src/JT1078.Gateway/Extensions/JT1078HttpContextExtensions.cs b/src/JT1078.Gateway/Extensions/JT1078HttpContextExtensions.cs
index 2253eb2..95f6374 100644
--- a/src/JT1078.Gateway/Extensions/JT1078HttpContextExtensions.cs
+++ b/src/JT1078.Gateway/Extensions/JT1078HttpContextExtensions.cs
@@ -19,6 +19,7 @@ namespace JT1078.Gateway.Extensions
context.Response.ContentLength64 = b.Length;
var output = context.Response.OutputStream;
await output.WriteAsync(b, 0, b.Length);
+ context.Response.OutputStream.Close();
context.Response.Close();
}
@@ -30,6 +31,7 @@ namespace JT1078.Gateway.Extensions
context.Response.ContentLength64 = b.Length;
var output = context.Response.OutputStream;
await output.WriteAsync(b, 0, b.Length);
+ context.Response.OutputStream.Close();
context.Response.Close();
}
@@ -37,6 +39,7 @@ namespace JT1078.Gateway.Extensions
{
context.Response.StatusCode = (int)HttpStatusCode.NotFound;
context.Response.KeepAlive = false;
+ context.Response.OutputStream.Close();
context.Response.Close();
}
@@ -48,6 +51,7 @@ namespace JT1078.Gateway.Extensions
context.Response.ContentLength64 = b.Length;
var output = context.Response.OutputStream;
await output.WriteAsync(b, 0, b.Length);
+ context.Response.OutputStream.Close();
context.Response.Close();
}
@@ -72,6 +76,7 @@ namespace JT1078.Gateway.Extensions
context.Context.Response.ContentLength64 = b.Length;
var output = context.Context.Response.OutputStream;
await output.WriteAsync(b, 0, b.Length);
+ context.Context.Response.OutputStream.Close();
context.Context.Response.Close();
}
diff --git a/src/JT1078.Gateway/JT1078CoordinatorHttpClient.cs b/src/JT1078.Gateway/JT1078CoordinatorHttpClient.cs
new file mode 100644
index 0000000..93bd045
--- /dev/null
+++ b/src/JT1078.Gateway/JT1078CoordinatorHttpClient.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Net.Http;
+using System.Text;
+
+namespace JT1078.Gateway
+{
+ ///
+ /// 协调器客户端
+ ///
+ public class JT1078CoordinatorHttpClient
+ {
+ private HttpClient httpClient;
+
+ public JT1078CoordinatorHttpClient(HttpClient httpClient)
+ {
+ this.httpClient = httpClient;
+ }
+
+ ///
+ /// 发送心跳至协调器中
+ ///
+ ///
+ public async void Heartbeat(string content)
+ {
+ await httpClient.PostAsync("/heartbeat", new StringContent(content));
+ }
+ }
+}
diff --git a/src/JT1078.Gateway/JT1078HttpServer.cs b/src/JT1078.Gateway/JT1078HttpServer.cs
index 3b827f5..bc9c078 100644
--- a/src/JT1078.Gateway/JT1078HttpServer.cs
+++ b/src/JT1078.Gateway/JT1078HttpServer.cs
@@ -88,13 +88,65 @@ namespace JT1078.Gateway
return Task.CompletedTask;
}
+ private const string m3u8Mime = "application/x-mpegURL";
+ private const string tsMime = "video/MP2T";
+
private async ValueTask ProcessRequestAsync(HttpListenerContext context, IPrincipal principal)
{
if(context.Request.RawUrl.StartsWith("/favicon.ico"))
{
context.Http404();
+ return;
+ }
+ var queryStringIndex = context.Request.RawUrl.IndexOf("?");
+ string url = "";
+ if (queryStringIndex > 0)
+ {
+ url = context.Request.RawUrl.Substring(1, queryStringIndex-1);
+ }
+ else
+ {
+ url = context.Request.RawUrl;
+ }
+ if (url.EndsWith(".m3u8") || url.EndsWith(".ts"))
+ {
+ string filename = Path.GetFileName(url);
+ string filepath = Path.Combine(Configuration.HlsRootDirectory, Path.GetFileNameWithoutExtension(filename), filename);
+ if (!File.Exists(filepath))
+ {
+ context.Http404();
+ return;
+ }
+ try
+ {
+ using (FileStream sr = new FileStream(filepath, FileMode.Open))
+ {
+ context.Response.ContentLength64 = sr.Length;
+ await sr.CopyToAsync(context.Response.OutputStream);
+ }
+ string ext = Path.GetExtension(filename);
+ if (ext == ".m3u8")
+ {
+ context.Response.ContentType = m3u8Mime;
+ }
+ else if (ext == ".ts")
+ {
+ context.Response.ContentType = tsMime;
+ }
+ context.Response.StatusCode = (int)HttpStatusCode.OK;
+ }
+ catch (Exception ex)
+ {
+ Logger.LogError(ex, $"{context.Request.RawUrl}");
+ context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
+ }
+ finally
+ {
+ context.Response.OutputStream.Close();
+ context.Response.Close();
+ }
+ return;
}
- //todo:.m3u8 .ts
if (Logger.IsEnabled(LogLevel.Trace))
{
Logger.LogTrace($"[http RequestTraceIdentifier]:{context.Request.RequestTraceIdentifier.ToString()}-{context.Request.RemoteEndPoint.ToString()}");