瀏覽代碼

删除老项目

old
smallchi 5 年之前
父節點
當前提交
65f377f93f
共有 85 個檔案被更改,包括 0 行新增6465 行删除
  1. +0
    -1
      nuget.bat
  2. +0
    -5
      publish.bat
  3. +0
    -20
      src/JT1078.DotNetty.Core/Codecs/JT1078TcpDecoder.cs
  4. +0
    -21
      src/JT1078.DotNetty.Core/Codecs/JT1078UdpDecoder.cs
  5. +0
    -31
      src/JT1078.DotNetty.Core/Configurations/JT1078ClientConfiguration.cs
  6. +0
    -37
      src/JT1078.DotNetty.Core/Configurations/JT1078Configuration.cs
  7. +0
    -12
      src/JT1078.DotNetty.Core/Configurations/JT1078RemoteServerOptions.cs
  8. +0
    -26
      src/JT1078.DotNetty.Core/Converters/JsonIPAddressConverter.cs
  9. +0
    -32
      src/JT1078.DotNetty.Core/Converters/JsonIPEndPointConverter.cs
  10. +0
    -15
      src/JT1078.DotNetty.Core/Enums/JT1078TransportProtocolType.cs
  11. +0
    -36
      src/JT1078.DotNetty.Core/Extensions/JT1078HttpSessionExtensions.cs
  12. +0
    -19
      src/JT1078.DotNetty.Core/Impl/JT1078BuilderDefault.cs
  13. +0
    -14
      src/JT1078.DotNetty.Core/Interfaces/IHttpMiddleware.cs
  14. +0
    -13
      src/JT1078.DotNetty.Core/Interfaces/IJT1078Authorization.cs
  15. +0
    -12
      src/JT1078.DotNetty.Core/Interfaces/IJT1078Builder.cs
  16. +0
    -15
      src/JT1078.DotNetty.Core/Interfaces/IJT1078HttpBuilder.cs
  17. +0
    -14
      src/JT1078.DotNetty.Core/Interfaces/IJT1078TcpBuilder.cs
  18. +0
    -11
      src/JT1078.DotNetty.Core/Interfaces/IJT1078TcpMessageHandlers.cs
  19. +0
    -14
      src/JT1078.DotNetty.Core/Interfaces/IJT1078UdpBuilder.cs
  20. +0
    -11
      src/JT1078.DotNetty.Core/Interfaces/IJT1078UdpMessageHandlers.cs
  21. +0
    -43
      src/JT1078.DotNetty.Core/JT1078.DotNetty.Core.csproj
  22. +0
    -77
      src/JT1078.DotNetty.Core/JT1078CoreDotnettyExtensions.cs
  23. +0
    -49
      src/JT1078.DotNetty.Core/Metadata/JT1078AtomicCounter.cs
  24. +0
    -31
      src/JT1078.DotNetty.Core/Metadata/JT1078HttpSession.cs
  25. +0
    -20
      src/JT1078.DotNetty.Core/Metadata/JT1078Request.cs
  26. +0
    -10
      src/JT1078.DotNetty.Core/Metadata/JT1078Response.cs
  27. +0
    -29
      src/JT1078.DotNetty.Core/Metadata/JT1078TcpSession.cs
  28. +0
    -20
      src/JT1078.DotNetty.Core/Metadata/JT1078UdpPackage.cs
  29. +0
    -35
      src/JT1078.DotNetty.Core/Metadata/JT1078UdpSession.cs
  30. +0
    -13
      src/JT1078.DotNetty.Core/Properties/PublishProfiles/FolderProfile.pubxml
  31. +0
    -52
      src/JT1078.DotNetty.Core/Services/JT1078AtomicCounterService.cs
  32. +0
    -30
      src/JT1078.DotNetty.Core/Services/JT1078AtomicCounterServiceFactory.cs
  33. +0
    -64
      src/JT1078.DotNetty.Core/Session/JT1078HttpSessionManager.cs
  34. +0
    -100
      src/JT1078.DotNetty.Core/Session/JT1078TcpSessionManager.cs
  35. +0
    -116
      src/JT1078.DotNetty.Core/Session/JT1078UdpSessionManager.cs
  36. +0
    -32
      src/JT1078.DotNetty.Http/Authorization/JT1078AuthorizationDefault.cs
  37. +0
    -183
      src/JT1078.DotNetty.Http/Handlers/JT1078HttpServerHandler.cs
  38. +0
    -30
      src/JT1078.DotNetty.Http/JT1078.DotNetty.Http.csproj
  39. +0
    -36
      src/JT1078.DotNetty.Http/JT1078HttpBuilderDefault.cs
  40. +0
    -25
      src/JT1078.DotNetty.Http/JT1078HttpDotnettyExtensions.cs
  41. +0
    -99
      src/JT1078.DotNetty.Http/JT1078HttpServerHost.cs
  42. +0
    -99
      src/JT1078.DotNetty.Tcp/Handlers/JT1078TcpConnectionHandler.cs
  43. +0
    -18
      src/JT1078.DotNetty.Tcp/Handlers/JT1078TcpMessageProcessorEmptyImpl.cs
  44. +0
    -69
      src/JT1078.DotNetty.Tcp/Handlers/JT1078TcpServerHandler.cs
  45. +0
    -31
      src/JT1078.DotNetty.Tcp/JT1078.DotNetty.Tcp.csproj
  46. +0
    -30
      src/JT1078.DotNetty.Tcp/JT1078TcpBuilderDefault.cs
  47. +0
    -26
      src/JT1078.DotNetty.Tcp/JT1078TcpDotnettyExtensions.cs
  48. +0
    -94
      src/JT1078.DotNetty.Tcp/JT1078TcpServerHost.cs
  49. +0
    -13
      src/JT1078.DotNetty.Tcp/Properties/PublishProfiles/FolderProfile.pubxml
  50. +0
    -3106
      src/JT1078.DotNetty.TestHosting/Configs/NLog.xsd
  51. +0
    -56
      src/JT1078.DotNetty.TestHosting/Configs/nlog.unix.config
  52. +0
    -48
      src/JT1078.DotNetty.TestHosting/Configs/nlog.win.config
  53. +0
    -18
      src/JT1078.DotNetty.TestHosting/CustomHttpMiddleware.cs
  54. +0
    -109
      src/JT1078.DotNetty.TestHosting/HLS/FFMPEGHLSHostedService.cs
  55. +0
    -25
      src/JT1078.DotNetty.TestHosting/HLS/Startup.cs
  56. +0
    -9
      src/JT1078.DotNetty.TestHosting/HLS/appsettings.json
  57. +0
    -25
      src/JT1078.DotNetty.TestHosting/HLS/hls.html
  58. +0
    -2
      src/JT1078.DotNetty.TestHosting/HLS/hls.min.js
  59. +0
    -134
      src/JT1078.DotNetty.TestHosting/HTTPFLV/FFMPEGHTTPFLVHostedService.cs
  60. +0
    -26
      src/JT1078.DotNetty.TestHosting/HTTPFLV/flv.html
  61. +0
    -7
      src/JT1078.DotNetty.TestHosting/HTTPFLV/flv.min.js
  62. +0
    -42
      src/JT1078.DotNetty.TestHosting/Handlers/JT1078TcpMessageHandlers.cs
  63. +0
    -25
      src/JT1078.DotNetty.TestHosting/Handlers/JT1078UdpMessageHandlers.cs
  64. +0
    -24
      src/JT1078.DotNetty.TestHosting/HardwareCamera.cs
  65. +0
    -80
      src/JT1078.DotNetty.TestHosting/HexExtensions.cs
  66. +0
    -72
      src/JT1078.DotNetty.TestHosting/JT1078.DotNetty.TestHosting.csproj
  67. +0
    -17
      src/JT1078.DotNetty.TestHosting/JT1078WSFlv/JT1078WSFlvDataService.cs
  68. +0
    -105
      src/JT1078.DotNetty.TestHosting/JT1078WSFlv/JT1078WSFlvHostedService.cs
  69. +0
    -7
      src/JT1078.DotNetty.TestHosting/JT1078WSFlv/flv.min.js
  70. +0
    -41
      src/JT1078.DotNetty.TestHosting/JT1078WSFlv/index.html
  71. +0
    -89
      src/JT1078.DotNetty.TestHosting/Program.cs
  72. +0
    -59
      src/JT1078.DotNetty.TestHosting/RTMP/FFMPEGRTMPHostedService.cs
  73. +0
    -129
      src/JT1078.DotNetty.TestHosting/WSFLV/FFMPEGWSFLVHostedService.cs
  74. +0
    -7
      src/JT1078.DotNetty.TestHosting/WSFLV/flv.min.js
  75. +0
    -26
      src/JT1078.DotNetty.TestHosting/WSFLV/index.html
  76. +0
    -23
      src/JT1078.DotNetty.TestHosting/appsettings.json
  77. +0
    -18
      src/JT1078.DotNetty.Udp/Handlers/JT1078UdpMessageProcessorEmptyImpl.cs
  78. +0
    -70
      src/JT1078.DotNetty.Udp/Handlers/JT1078UdpServerHandler.cs
  79. +0
    -29
      src/JT1078.DotNetty.Udp/JT1078.DotNetty.Udp.csproj
  80. +0
    -30
      src/JT1078.DotNetty.Udp/JT1078UdpBuilderDefault.cs
  81. +0
    -26
      src/JT1078.DotNetty.Udp/JT1078UdpDotnettyExtensions.cs
  82. +0
    -76
      src/JT1078.DotNetty.Udp/JT1078UdpServerHost.cs
  83. +0
    -13
      src/JT1078.DotNetty.Udp/Properties/PublishProfiles/FolderProfile.pubxml
  84. +0
    -54
      src/JT1078DotNetty.sln
  85. +0
    -5
      src/Version.props

+ 0
- 1
nuget.bat 查看文件

@@ -1 +0,0 @@
dotnet nuget push .\nupkgs\*.nupkg -k apikey -s https://api.nuget.org/v3/index.json

+ 0
- 5
publish.bat 查看文件

@@ -1,5 +0,0 @@
dotnet pack .\src\JT1078.DotNetty.Core\JT1078.DotNetty.Core.csproj --no-build --output ../../nupkgs
dotnet pack .\src\JT1078.DotNetty.Http\JT1078.DotNetty.Http.csproj --no-build --output ../../nupkgs
dotnet pack .\src\JT1078.DotNetty.Tcp\JT1078.DotNetty.Tcp.csproj --no-build --output ../../nupkgs
dotnet pack .\src\JT1078.DotNetty.Udp\JT1078.DotNetty.Udp.csproj --no-build --output ../../nupkgs
pause

+ 0
- 20
src/JT1078.DotNetty.Core/Codecs/JT1078TcpDecoder.cs 查看文件

@@ -1,20 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Codecs;
using System.Collections.Generic;
using DotNetty.Transport.Channels;
using JT1078.Protocol;
using System;

namespace JT1078.DotNetty.Core.Codecs
{
public class JT1078TcpDecoder : ByteToMessageDecoder
{
protected override void Decode(IChannelHandlerContext context, IByteBuffer input, List<object> output)
{
byte[] buffer = new byte[input.Capacity+4];
input.ReadBytes(buffer, 4, input.Capacity);
Array.Copy(JT1078Package.FH_Bytes, 0,buffer, 0, 4);
output.Add(buffer);
}
}
}

+ 0
- 21
src/JT1078.DotNetty.Core/Codecs/JT1078UdpDecoder.cs 查看文件

@@ -1,21 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Codecs;
using DotNetty.Transport.Channels;
using System.Collections.Generic;
using DotNetty.Transport.Channels.Sockets;
using JT1078.DotNetty.Core.Metadata;

namespace JT1078.DotNetty.Core.Codecs
{
public class JT1078UdpDecoder : MessageToMessageDecoder<DatagramPacket>
{
protected override void Decode(IChannelHandlerContext context, DatagramPacket message, List<object> output)
{
if (!message.Content.IsReadable()) return;
IByteBuffer byteBuffer = message.Content;
byte[] buffer = new byte[byteBuffer.ReadableBytes];
byteBuffer.ReadBytes(buffer);
output.Add(new JT1078UdpPackage(buffer, message.Sender));
}
}
}

+ 0
- 31
src/JT1078.DotNetty.Core/Configurations/JT1078ClientConfiguration.cs 查看文件

@@ -1,31 +0,0 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;

namespace JT1078.DotNetty.Core.Configurations
{
public class JT1078ClientConfiguration
{
public string Host { get; set; }

public int Port { get; set; }

private EndPoint endPoint;

public EndPoint EndPoint
{
get
{
if (endPoint == null)
{
if (IPAddress.TryParse(Host, out IPAddress ip))
{
endPoint = new IPEndPoint(ip, Port);
}
}
return endPoint;
}
}
}
}

+ 0
- 37
src/JT1078.DotNetty.Core/Configurations/JT1078Configuration.cs 查看文件

@@ -1,37 +0,0 @@
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Text;

namespace JT1078.DotNetty.Core.Configurations
{
public class JT1078Configuration : IOptions<JT1078Configuration>
{
public int TcpPort { get; set; } = 1808;

public int UdpPort { get; set; } = 1808;
public int HttpPort { get; set; } = 1818;
public int QuietPeriodSeconds { get; set; } = 1;

public TimeSpan QuietPeriodTimeSpan => TimeSpan.FromSeconds(QuietPeriodSeconds);

public int ShutdownTimeoutSeconds { get; set; } = 3;

public TimeSpan ShutdownTimeoutTimeSpan => TimeSpan.FromSeconds(ShutdownTimeoutSeconds);

public int SoBacklog { get; set; } = 8192;

public int EventLoopCount { get; set; } = Environment.ProcessorCount;

public int ReaderIdleTimeSeconds { get; set; } = 3600;

public int WriterIdleTimeSeconds { get; set; } = 3600;

public int AllIdleTimeSeconds { get; set; } = 3600;

public JT1078RemoteServerOptions RemoteServerOptions { get; set; }

public JT1078Configuration Value => this;
}
}

+ 0
- 12
src/JT1078.DotNetty.Core/Configurations/JT1078RemoteServerOptions.cs 查看文件

@@ -1,12 +0,0 @@
using Microsoft.Extensions.Options;
using System.Collections.Generic;

namespace JT1078.DotNetty.Core.Configurations
{
public class JT1078RemoteServerOptions:IOptions<JT1078RemoteServerOptions>
{
public List<string> RemoteServers { get; set; }

public JT1078RemoteServerOptions Value => this;
}
}

+ 0
- 26
src/JT1078.DotNetty.Core/Converters/JsonIPAddressConverter.cs 查看文件

@@ -1,26 +0,0 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;

namespace JT1078.DotNetty.Core.Converters
{
public class JsonIPAddressConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(IPAddress));
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue(value.ToString());
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return IPAddress.Parse((string)reader.Value);
}
}
}

+ 0
- 32
src/JT1078.DotNetty.Core/Converters/JsonIPEndPointConverter.cs 查看文件

@@ -1,32 +0,0 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Net;

namespace JT1078.DotNetty.Core.Converters
{
public class JsonIPEndPointConverter: JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(IPEndPoint));
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
IPEndPoint ep = (IPEndPoint)value;
JObject jo = new JObject();
jo.Add("Host", JToken.FromObject(ep.Address, serializer));
jo.Add("Port", ep.Port);
jo.WriteTo(writer);
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jo = JObject.Load(reader);
IPAddress address = jo["Host"].ToObject<IPAddress>(serializer);
int port = (int)jo["Port"];
return new IPEndPoint(address, port);
}
}
}

+ 0
- 15
src/JT1078.DotNetty.Core/Enums/JT1078TransportProtocolType.cs 查看文件

@@ -1,15 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace JT1078.DotNetty.Core.Enums
{
/// <summary>
/// 传输协议类型
/// </summary>
public enum JT1078TransportProtocolType
{
tcp=1,
udp = 2
}
}

+ 0
- 36
src/JT1078.DotNetty.Core/Extensions/JT1078HttpSessionExtensions.cs 查看文件

@@ -1,36 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Codecs.Http;
using DotNetty.Codecs.Http.WebSockets;
using DotNetty.Common.Utilities;
using JT1078.DotNetty.Core.Metadata;
using System;
using System.Collections.Generic;
using System.Text;

namespace JT1078.DotNetty.Core.Extensions
{
public static class JT1078HttpSessionExtensions
{
private static readonly AsciiString ServerName = AsciiString.Cached("JT1078Netty");
private static readonly AsciiString DateEntity = HttpHeaderNames.Date;
private static readonly AsciiString ServerEntity = HttpHeaderNames.Server;
public static void SendBinaryWebSocketAsync(this JT1078HttpSession session,byte[] data)
{
session.Channel.WriteAndFlushAsync(new BinaryWebSocketFrame(Unpooled.WrappedBuffer(data)));
}
public static void SendHttpFirstChunkAsync(this JT1078HttpSession session, byte[] data)
{
DefaultHttpResponse firstRes = new DefaultHttpResponse(HttpVersion.Http11, HttpResponseStatus.OK);
firstRes.Headers.Set(ServerEntity, ServerName);
firstRes.Headers.Set(DateEntity, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"));
firstRes.Headers.Set(HttpHeaderNames.ContentType, (AsciiString)"video/x-flv");
HttpUtil.SetTransferEncodingChunked(firstRes, true);
session.Channel.WriteAsync(firstRes);
session.Channel.WriteAndFlushAsync(Unpooled.CopiedBuffer(data));
}
public static void SendHttpOtherChunkAsync(this JT1078HttpSession session, byte[] data)
{
session.Channel.WriteAndFlushAsync(Unpooled.CopiedBuffer(data));
}
}
}

+ 0
- 19
src/JT1078.DotNetty.Core/Impl/JT1078BuilderDefault.cs 查看文件

@@ -1,19 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
using JT1078.DotNetty.Core.Interfaces;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;

namespace JT1078.DotNetty.Core.Impl
{
sealed class JT1078BuilderDefault : IJT1078Builder
{
public IServiceCollection Services { get; }

public JT1078BuilderDefault(IServiceCollection services)
{
Services = services;
}
}
}

+ 0
- 14
src/JT1078.DotNetty.Core/Interfaces/IHttpMiddleware.cs 查看文件

@@ -1,14 +0,0 @@
using DotNetty.Codecs.Http;
using DotNetty.Transport.Channels;
using System;
using System.Collections.Generic;
using System.Security.Principal;
using System.Text;

namespace JT1078.DotNetty.Core.Interfaces
{
public interface IHttpMiddleware
{
void Next(IChannelHandlerContext ctx, IFullHttpRequest req, IPrincipal principal);
}
}

+ 0
- 13
src/JT1078.DotNetty.Core/Interfaces/IJT1078Authorization.cs 查看文件

@@ -1,13 +0,0 @@
using DotNetty.Codecs.Http;
using System;
using System.Collections.Generic;
using System.Security.Principal;
using System.Text;

namespace JT1078.DotNetty.Core.Interfaces
{
public interface IJT1078Authorization
{
bool Authorization(IFullHttpRequest request, out IPrincipal principal);
}
}

+ 0
- 12
src/JT1078.DotNetty.Core/Interfaces/IJT1078Builder.cs 查看文件

@@ -1,12 +0,0 @@
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Text;

namespace JT1078.DotNetty.Core.Interfaces
{
public interface IJT1078Builder
{
IServiceCollection Services { get; }
}
}

+ 0
- 15
src/JT1078.DotNetty.Core/Interfaces/IJT1078HttpBuilder.cs 查看文件

@@ -1,15 +0,0 @@
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Text;

namespace JT1078.DotNetty.Core.Interfaces
{
public interface IJT1078HttpBuilder
{
IJT1078Builder Instance { get; }
IJT1078Builder Builder();
IJT1078HttpBuilder Replace<T>() where T : IJT1078Authorization;
IJT1078HttpBuilder UseHttpMiddleware<T>() where T : IHttpMiddleware;
}
}

+ 0
- 14
src/JT1078.DotNetty.Core/Interfaces/IJT1078TcpBuilder.cs 查看文件

@@ -1,14 +0,0 @@
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Text;

namespace JT1078.DotNetty.Core.Interfaces
{
public interface IJT1078TcpBuilder
{
IJT1078Builder Instance { get;}
IJT1078Builder Builder();
IJT1078TcpBuilder Replace<T>() where T : IJT1078TcpMessageHandlers;
}
}

+ 0
- 11
src/JT1078.DotNetty.Core/Interfaces/IJT1078TcpMessageHandlers.cs 查看文件

@@ -1,11 +0,0 @@
using JT1078.DotNetty.Core.Metadata;
using JT1078.Protocol;
using System.Threading.Tasks;

namespace JT1078.DotNetty.Core.Interfaces
{
public interface IJT1078TcpMessageHandlers
{
Task<JT1078Response> Processor(JT1078Request request);
}
}

+ 0
- 14
src/JT1078.DotNetty.Core/Interfaces/IJT1078UdpBuilder.cs 查看文件

@@ -1,14 +0,0 @@
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Text;

namespace JT1078.DotNetty.Core.Interfaces
{
public interface IJT1078UdpBuilder
{
IJT1078Builder Instance { get; }
IJT1078Builder Builder();
IJT1078UdpBuilder Replace<T>() where T : IJT1078UdpMessageHandlers;
}
}

+ 0
- 11
src/JT1078.DotNetty.Core/Interfaces/IJT1078UdpMessageHandlers.cs 查看文件

@@ -1,11 +0,0 @@
using JT1078.DotNetty.Core.Metadata;
using JT1078.Protocol;
using System.Threading.Tasks;

namespace JT1078.DotNetty.Core.Interfaces
{
public interface IJT1078UdpMessageHandlers
{
Task<JT1078Response> Processor(JT1078Request request);
}
}

+ 0
- 43
src/JT1078.DotNetty.Core/JT1078.DotNetty.Core.csproj 查看文件

@@ -1,43 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\Version.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>7.3</LangVersion>
<Copyright>Copyright 2019.</Copyright>
<Authors>SmallChi(Koike)</Authors>
<PackageId>JT1078.DotNetty.Core</PackageId>
<Product>JT1078.DotNetty.Core</Product>
<Description>基于DotNetty实现的JT1078DotNetty的核心库</Description>
<PackageReleaseNotes>基于DotNetty实现的JT1078DotNetty的核心库</PackageReleaseNotes>
<RepositoryUrl>https://github.com/SmallChi/JT1078DotNetty</RepositoryUrl>
<PackageProjectUrl>https://github.com/SmallChi/JT1078DotNetty</PackageProjectUrl>
<licenseUrl>https://github.com/SmallChi/JT1078DotNetty/blob/master/LICENSE</licenseUrl>
<license>https://github.com/SmallChi/JT1078DotNetty/blob/master/LICENSE</license>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<SignAssembly>false</SignAssembly>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<Version>$(JT1078DotNettyPackageVersion)</Version>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="DotNetty.Codecs.Http" Version="0.6.0" />
<PackageReference Include="DotNetty.Handlers" Version="0.6.0" />
<PackageReference Include="DotNetty.Transport.Libuv" Version="0.6.0" />
<PackageReference Include="DotNetty.Codecs" Version="0.6.0" />
<PackageReference Include="JT1078" Version="1.0.1" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
<PackageReference Include="Microsoft.Extensions.Options" Version="3.0.0" />
</ItemGroup>

<ItemGroup>
<None Include="..\..\LICENSE" Pack="true" PackagePath="" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
</Project>

+ 0
- 77
src/JT1078.DotNetty.Core/JT1078CoreDotnettyExtensions.cs 查看文件

@@ -1,77 +0,0 @@
using JT1078.DotNetty.Core.Configurations;
using JT1078.DotNetty.Core.Converters;
using JT1078.DotNetty.Core.Impl;
using JT1078.DotNetty.Core.Interfaces;
using JT1078.DotNetty.Core.Services;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using System;
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("JT1078.DotNetty.Core.Test")]
[assembly: InternalsVisibleTo("JT1078.DotNetty.Tcp.Test")]
[assembly: InternalsVisibleTo("JT1078.DotNetty.Udp.Test")]
[assembly: InternalsVisibleTo("JT1078.DotNetty.Tcp")]
[assembly: InternalsVisibleTo("JT1078.DotNetty.Udp")]
namespace JT1078.DotNetty.Core
{
public static class JT1078CoreDotnettyExtensions
{
static JT1078CoreDotnettyExtensions()
{
JsonConvert.DefaultSettings = new Func<JsonSerializerSettings>(() =>
{
Newtonsoft.Json.JsonSerializerSettings settings = new Newtonsoft.Json.JsonSerializerSettings();
//日期类型默认格式化处理
settings.DateFormatHandling = Newtonsoft.Json.DateFormatHandling.MicrosoftDateFormat;
settings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
//空值处理
settings.NullValueHandling = NullValueHandling.Ignore;
settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
settings.Converters.Add(new JsonIPAddressConverter());
settings.Converters.Add(new JsonIPEndPointConverter());
return settings;
});
}

public static IJT1078Builder AddJT1078Core(this IServiceCollection serviceDescriptors, IConfiguration configuration, Newtonsoft.Json.JsonSerializerSettings settings=null)
{
if (settings != null)
{
JsonConvert.DefaultSettings = new Func<JsonSerializerSettings>(() =>
{
settings.Converters.Add(new JsonIPAddressConverter());
settings.Converters.Add(new JsonIPEndPointConverter());
settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
return settings;
});
}
IJT1078Builder builder = new JT1078BuilderDefault(serviceDescriptors);
builder.Services.Configure<JT1078Configuration>(configuration.GetSection("JT1078Configuration"));
builder.Services.TryAddSingleton<JT1078AtomicCounterServiceFactory>();
return builder;
}

public static IJT1078Builder AddJT1078Core(this IServiceCollection serviceDescriptors, Action<JT1078Configuration> jt1078Options, Newtonsoft.Json.JsonSerializerSettings settings = null)
{
if (settings != null)
{
JsonConvert.DefaultSettings = new Func<JsonSerializerSettings>(() =>
{
settings.Converters.Add(new JsonIPAddressConverter());
settings.Converters.Add(new JsonIPEndPointConverter());
settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
return settings;
});
}
IJT1078Builder builder = new JT1078BuilderDefault(serviceDescriptors);
builder.Services.Configure(jt1078Options);
builder.Services.TryAddSingleton<JT1078AtomicCounterService>();
builder.Services.TryAddSingleton<JT1078AtomicCounterServiceFactory>();
return builder;
}
}
}

+ 0
- 49
src/JT1078.DotNetty.Core/Metadata/JT1078AtomicCounter.cs 查看文件

@@ -1,49 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace JT1078.DotNetty.Core.Metadata
{
/// <summary>
///
/// <see cref="Grpc.Core.Internal"/>
/// </summary>
internal class JT1078AtomicCounter
{
long counter = 0;

public JT1078AtomicCounter(long initialCount = 0)
{
this.counter = initialCount;
}

public void Reset()
{
Interlocked.Exchange(ref counter, 0);
}

public long Increment()
{
return Interlocked.Increment(ref counter);
}

public long Add(long len)
{
return Interlocked.Add(ref counter,len);
}

public long Decrement()
{
return Interlocked.Decrement(ref counter);
}

public long Count
{
get
{
return Interlocked.Read(ref counter);
}
}
}
}

+ 0
- 31
src/JT1078.DotNetty.Core/Metadata/JT1078HttpSession.cs 查看文件

@@ -1,31 +0,0 @@
using DotNetty.Transport.Channels;
using System;
using System.Net;

namespace JT1078.DotNetty.Core.Metadata
{
public class JT1078HttpSession
{
public JT1078HttpSession(
IChannel channel,
string userId)
{
Channel = channel;
UserId = userId;
StartTime = DateTime.Now;
LastActiveTime = DateTime.Now;
}

public JT1078HttpSession() { }

public string UserId { get; set; }

public string AttachInfo { get; set; }

public IChannel Channel { get; set; }

public DateTime LastActiveTime { get; set; }

public DateTime StartTime { get; set; }
}
}

+ 0
- 20
src/JT1078.DotNetty.Core/Metadata/JT1078Request.cs 查看文件

@@ -1,20 +0,0 @@
using JT1078.Protocol;
using System;
using System.Collections.Generic;
using System.Text;

namespace JT1078.DotNetty.Core.Metadata
{
public class JT1078Request
{
public JT1078Request(JT1078Package package,byte[] src)
{
Package = package;
Src = src;
}

public JT1078Package Package { get; }

public byte[] Src { get; }
}
}

+ 0
- 10
src/JT1078.DotNetty.Core/Metadata/JT1078Response.cs 查看文件

@@ -1,10 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace JT1078.DotNetty.Core.Metadata
{
public class JT1078Response
{
}
}

+ 0
- 29
src/JT1078.DotNetty.Core/Metadata/JT1078TcpSession.cs 查看文件

@@ -1,29 +0,0 @@
using DotNetty.Transport.Channels;
using System;

namespace JT1078.DotNetty.Core.Metadata
{
public class JT1078TcpSession
{
public JT1078TcpSession(IChannel channel, string terminalPhoneNo)
{
Channel = channel;
TerminalPhoneNo = terminalPhoneNo;
StartTime = DateTime.Now;
LastActiveTime = DateTime.Now;
}

public JT1078TcpSession() { }

/// <summary>
/// 终端手机号
/// </summary>
public string TerminalPhoneNo { get; set; }

public IChannel Channel { get; set; }

public DateTime LastActiveTime { get; set; }

public DateTime StartTime { get; set; }
}
}

+ 0
- 20
src/JT1078.DotNetty.Core/Metadata/JT1078UdpPackage.cs 查看文件

@@ -1,20 +0,0 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;

namespace JT1078.DotNetty.Core.Metadata
{
public class JT1078UdpPackage
{
public JT1078UdpPackage(byte[] buffer, EndPoint sender)
{
Buffer = buffer;
Sender = sender;
}

public byte[] Buffer { get; }

public EndPoint Sender { get; }
}
}

+ 0
- 35
src/JT1078.DotNetty.Core/Metadata/JT1078UdpSession.cs 查看文件

@@ -1,35 +0,0 @@
using DotNetty.Transport.Channels;
using System;
using System.Net;

namespace JT1078.DotNetty.Core.Metadata
{
public class JT1078UdpSession
{
public JT1078UdpSession(IChannel channel,
EndPoint sender,
string terminalPhoneNo)
{
Channel = channel;
TerminalPhoneNo = terminalPhoneNo;
StartTime = DateTime.Now;
LastActiveTime = DateTime.Now;
Sender = sender;
}

public EndPoint Sender { get; set; }

public JT1078UdpSession() { }

/// <summary>
/// 终端手机号
/// </summary>
public string TerminalPhoneNo { get; set; }

public IChannel Channel { get; set; }

public DateTime LastActiveTime { get; set; }

public DateTime StartTime { get; set; }
}
}

+ 0
- 13
src/JT1078.DotNetty.Core/Properties/PublishProfiles/FolderProfile.pubxml 查看文件

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<PublishProtocol>FileSystem</PublishProtocol>
<Configuration>Release</Configuration>
<Platform>Any CPU</Platform>
<TargetFramework>netstandard2.0</TargetFramework>
<PublishDir>..\..\publish\</PublishDir>
</PropertyGroup>
</Project>

+ 0
- 52
src/JT1078.DotNetty.Core/Services/JT1078AtomicCounterService.cs 查看文件

@@ -1,52 +0,0 @@
using JT1078.DotNetty.Core.Metadata;

namespace JT1078.DotNetty.Core.Services
{
/// <summary>
/// 计数包服务
/// </summary>
public class JT1078AtomicCounterService
{
private readonly JT1078AtomicCounter MsgSuccessCounter;

private readonly JT1078AtomicCounter MsgFailCounter;

public JT1078AtomicCounterService()
{
MsgSuccessCounter=new JT1078AtomicCounter();
MsgFailCounter = new JT1078AtomicCounter();
}

public void Reset()
{
MsgSuccessCounter.Reset();
MsgFailCounter.Reset();
}

public long MsgSuccessIncrement()
{
return MsgSuccessCounter.Increment();
}

public long MsgSuccessCount
{
get
{
return MsgSuccessCounter.Count;
}
}

public long MsgFailIncrement()
{
return MsgFailCounter.Increment();
}

public long MsgFailCount
{
get
{
return MsgFailCounter.Count;
}
}
}
}

+ 0
- 30
src/JT1078.DotNetty.Core/Services/JT1078AtomicCounterServiceFactory.cs 查看文件

@@ -1,30 +0,0 @@
using JT1078.DotNetty.Core.Enums;
using System;
using System.Collections.Concurrent;

namespace JT1078.DotNetty.Core.Services
{
public class JT1078AtomicCounterServiceFactory
{
private readonly ConcurrentDictionary<JT1078TransportProtocolType, JT1078AtomicCounterService> cache;

public JT1078AtomicCounterServiceFactory()
{
cache = new ConcurrentDictionary<JT1078TransportProtocolType, JT1078AtomicCounterService>();
}

public JT1078AtomicCounterService Create(JT1078TransportProtocolType type)
{
if(cache.TryGetValue(type,out var service))
{
return service;
}
else
{
var serviceNew = new JT1078AtomicCounterService();
cache.TryAdd(type, serviceNew);
return serviceNew;
}
}
}
}

+ 0
- 64
src/JT1078.DotNetty.Core/Session/JT1078HttpSessionManager.cs 查看文件

@@ -1,64 +0,0 @@
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using DotNetty.Transport.Channels;
using JT1078.DotNetty.Core.Metadata;

namespace JT1078.DotNetty.Core.Session
{
/// <summary>
/// JT1078 http会话管理
/// </summary>
public class JT1078HttpSessionManager
{
private readonly ILogger<JT1078HttpSessionManager> logger;

public JT1078HttpSessionManager(
ILoggerFactory loggerFactory)
{
logger = loggerFactory.CreateLogger<JT1078HttpSessionManager>();
}

private ConcurrentDictionary<string, JT1078HttpSession> SessionDict = new ConcurrentDictionary<string, JT1078HttpSession>();

public int SessionCount
{
get
{
return SessionDict.Count;
}
}

public List<JT1078HttpSession> GetSessions(string userId)
{
return SessionDict.Where(m => m.Value.UserId == userId).Select(m=>m.Value).ToList();
}

public void TryAdd(string userId,IChannel channel)
{
SessionDict.TryAdd(channel.Id.AsShortText(), new JT1078HttpSession(channel, userId));
if (logger.IsEnabled(LogLevel.Information))
{
logger.LogInformation($">>>{userId},{channel.Id.AsShortText()} Channel Connection.");
}
}

public void RemoveSessionByChannel(IChannel channel)
{
if (channel.Open&& SessionDict.TryRemove(channel.Id.AsShortText(), out var session))
{
if (logger.IsEnabled(LogLevel.Information))
{
logger.LogInformation($">>>{session.UserId},{session.Channel.Id.AsShortText()} Channel Remove.");
}
}
}
public List<JT1078HttpSession> GetAll()
{
return SessionDict.Select(s => s.Value).ToList();
}
}
}


+ 0
- 100
src/JT1078.DotNetty.Core/Session/JT1078TcpSessionManager.cs 查看文件

@@ -1,100 +0,0 @@
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using DotNetty.Transport.Channels;
using JT1078.DotNetty.Core.Metadata;

namespace JT1078.DotNetty.Core.Session
{
/// <summary>
/// JT1078 Tcp会话管理
/// </summary>
public class JT1078TcpSessionManager
{
private readonly ILogger<JT1078TcpSessionManager> logger;

public JT1078TcpSessionManager(
ILoggerFactory loggerFactory)
{
logger = loggerFactory.CreateLogger<JT1078TcpSessionManager>();
}

private ConcurrentDictionary<string, JT1078TcpSession> SessionIdDict = new ConcurrentDictionary<string, JT1078TcpSession>(StringComparer.OrdinalIgnoreCase);

public int SessionCount
{
get
{
return SessionIdDict.Count;
}
}

public JT1078TcpSession GetSession(string terminalPhoneNo)
{
if (string.IsNullOrEmpty(terminalPhoneNo))
return default;
if (SessionIdDict.TryGetValue(terminalPhoneNo, out JT1078TcpSession targetSession))
{
return targetSession;
}
else
{
return default;
}
}

public void TryAdd(string terminalPhoneNo,IChannel channel)
{
if (SessionIdDict.TryGetValue(terminalPhoneNo, out JT1078TcpSession oldSession))
{
oldSession.LastActiveTime = DateTime.Now;
oldSession.Channel = channel;
SessionIdDict.TryUpdate(terminalPhoneNo, oldSession, oldSession);
}
else
{
JT1078TcpSession session = new JT1078TcpSession(channel, terminalPhoneNo);
if (SessionIdDict.TryAdd(terminalPhoneNo, session))
{

}
}
}

public JT1078TcpSession RemoveSession(string terminalPhoneNo)
{
if (string.IsNullOrEmpty(terminalPhoneNo)) return default;
if (SessionIdDict.TryRemove(terminalPhoneNo, out JT1078TcpSession sessionRemove))
{
logger.LogInformation($">>>{terminalPhoneNo} Session Remove.");
return sessionRemove;
}
else
{
return default;
}
}

public void RemoveSessionByChannel(IChannel channel)
{
var terminalPhoneNos = SessionIdDict.Where(w => w.Value.Channel.Id == channel.Id).Select(s => s.Key).ToList();
if (terminalPhoneNos.Count > 0)
{
foreach (var key in terminalPhoneNos)
{
SessionIdDict.TryRemove(key, out JT1078TcpSession sessionRemove);
}
string nos = string.Join(",", terminalPhoneNos);
logger.LogInformation($">>>{nos} Channel Remove.");
}
}

public IEnumerable<JT1078TcpSession> GetAll()
{
return SessionIdDict.Select(s => s.Value).ToList();
}
}
}


+ 0
- 116
src/JT1078.DotNetty.Core/Session/JT1078UdpSessionManager.cs 查看文件

@@ -1,116 +0,0 @@
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using DotNetty.Transport.Channels;
using Microsoft.Extensions.Options;
using System.Net;
using JT1078.DotNetty.Core.Configurations;
using JT1078.DotNetty.Core.Metadata;

namespace JT1078.DotNetty.Core.Session
{
/// <summary>
/// JT1078 udp会话管理
/// 估计要轮询下
/// </summary>
public class JT1078UdpSessionManager
{
private readonly ILogger<JT1078UdpSessionManager> logger;

public JT1078UdpSessionManager(
ILoggerFactory loggerFactory)
{
logger = loggerFactory.CreateLogger<JT1078UdpSessionManager>();
}

private ConcurrentDictionary<string, JT1078UdpSession> SessionIdDict = new ConcurrentDictionary<string, JT1078UdpSession>(StringComparer.OrdinalIgnoreCase);

public int SessionCount
{
get
{
return SessionIdDict.Count;
}
}

public JT1078UdpSession GetSession(string terminalPhoneNo)
{
if (string.IsNullOrEmpty(terminalPhoneNo))
return default;
if (SessionIdDict.TryGetValue(terminalPhoneNo, out JT1078UdpSession targetSession))
{
return targetSession;
}
else
{
return default;
}
}

public void TryAdd(IChannel channel,EndPoint sender,string terminalPhoneNo)
{
//1.先判断是否在缓存里面
if (SessionIdDict.TryGetValue(terminalPhoneNo, out JT1078UdpSession UdpSession))
{
UdpSession.LastActiveTime=DateTime.Now;
UdpSession.Sender = sender;
UdpSession.Channel = channel;
SessionIdDict.TryUpdate(terminalPhoneNo, UdpSession, UdpSession);
}
else
{
SessionIdDict.TryAdd(terminalPhoneNo, new JT1078UdpSession(channel, sender, terminalPhoneNo));
}
}

public void Heartbeat(string terminalPhoneNo)
{
if (string.IsNullOrEmpty(terminalPhoneNo)) return;
if (SessionIdDict.TryGetValue(terminalPhoneNo, out JT1078UdpSession oldSession))
{
oldSession.LastActiveTime = DateTime.Now;
SessionIdDict.TryUpdate(terminalPhoneNo, oldSession, oldSession);
}
}

public JT1078UdpSession RemoveSession(string terminalPhoneNo)
{
//设备离线可以进行通知
//使用Redis 发布订阅
if (string.IsNullOrEmpty(terminalPhoneNo)) return default;
if (SessionIdDict.TryRemove(terminalPhoneNo, out JT1078UdpSession SessionRemove))
{
logger.LogInformation($">>>{terminalPhoneNo} Session Remove.");
return SessionRemove;
}
else
{
return default;
}
}

public void RemoveSessionByChannel(IChannel channel)
{
//设备离线可以进行通知
//使用Redis 发布订阅
var terminalPhoneNos = SessionIdDict.Where(w => w.Value.Channel.Id == channel.Id).Select(s => s.Key).ToList();
if (terminalPhoneNos.Count > 0)
{
foreach (var key in terminalPhoneNos)
{
SessionIdDict.TryRemove(key, out JT1078UdpSession SessionRemove);
}
string nos = string.Join(",", terminalPhoneNos);
logger.LogInformation($">>>{nos} Channel Remove.");
}
}

public IEnumerable<JT1078UdpSession> GetAll()
{
return SessionIdDict.Select(s => s.Value).ToList();
}
}
}


+ 0
- 32
src/JT1078.DotNetty.Http/Authorization/JT1078AuthorizationDefault.cs 查看文件

@@ -1,32 +0,0 @@
using DotNetty.Codecs.Http;
using JT1078.DotNetty.Core.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Security.Principal;
using System.Text;

namespace JT1078.DotNetty.Http.Authorization
{
class JT1078AuthorizationDefault : IJT1078Authorization
{
public bool Authorization(IFullHttpRequest request, out IPrincipal principal)
{
var uriSpan = request.Uri.AsSpan();
var uriParamStr = uriSpan.Slice(uriSpan.IndexOf('?')+1).ToString().ToLower();
var uriParams = uriParamStr.Split('&');
var tokenParam = uriParams.FirstOrDefault(m => m.Contains("token"));
if (!string.IsNullOrEmpty(tokenParam))
{
principal = new ClaimsPrincipal(new GenericIdentity(tokenParam.Split('=')[1]));
return true;
}
else
{
principal = null;
return false;
}
}
}
}

+ 0
- 183
src/JT1078.DotNetty.Http/Handlers/JT1078HttpServerHandler.cs 查看文件

@@ -1,183 +0,0 @@
using System;
using System.Diagnostics;
using System.Text;
using System.Threading.Tasks;
using DotNetty.Buffers;
using DotNetty.Codecs.Http;
using DotNetty.Codecs.Http.WebSockets;
using DotNetty.Common.Utilities;
using DotNetty.Transport.Channels;
using static DotNetty.Codecs.Http.HttpVersion;
using static DotNetty.Codecs.Http.HttpResponseStatus;
using Microsoft.Extensions.Logging;
using JT1078.DotNetty.Core.Session;
using System.Text.RegularExpressions;
using JT1078.DotNetty.Core.Interfaces;

namespace JT1078.DotNetty.Http.Handlers
{
public sealed class JT1078HttpServerHandler : SimpleChannelInboundHandler<object>
{
const string WebsocketPath = "/jt1078live";
WebSocketServerHandshaker handshaker;
private static readonly AsciiString ServerName = AsciiString.Cached("JT1078Netty");
private static readonly AsciiString DateEntity = HttpHeaderNames.Date;
private static readonly AsciiString ServerEntity = HttpHeaderNames.Server;

private readonly ILogger<JT1078HttpServerHandler> logger;

private readonly JT1078HttpSessionManager jT1078HttpSessionManager;

private readonly IJT1078Authorization iJT1078Authorization;

private readonly IHttpMiddleware httpMiddleware;

public JT1078HttpServerHandler(
JT1078HttpSessionManager jT1078HttpSessionManager,
IJT1078Authorization iJT1078Authorization,
ILoggerFactory loggerFactory,
IHttpMiddleware httpMiddleware = null)
{
this.jT1078HttpSessionManager = jT1078HttpSessionManager;
this.iJT1078Authorization = iJT1078Authorization;
this.httpMiddleware = httpMiddleware;
logger = loggerFactory.CreateLogger<JT1078HttpServerHandler>();
}

public override void ChannelInactive(IChannelHandlerContext context)
{
if (logger.IsEnabled(LogLevel.Information))
{
logger.LogInformation(context.Channel.Id.AsShortText());
}
jT1078HttpSessionManager.RemoveSessionByChannel(context.Channel);
base.ChannelInactive(context);
}

protected override void ChannelRead0(IChannelHandlerContext ctx, object msg)
{
if (msg is IFullHttpRequest request)
{
this.HandleHttpRequest(ctx, request);
}
else if (msg is WebSocketFrame frame)
{
this.HandleWebSocketFrame(ctx, frame);
}
}

public override void ChannelReadComplete(IChannelHandlerContext context) => context.Flush();

void HandleHttpRequest(IChannelHandlerContext ctx, IFullHttpRequest req)
{
// Handle a bad request.
if (!req.Result.IsSuccess)
{
SendHttpResponse(ctx, req, new DefaultFullHttpResponse(Http11, BadRequest));
return;
}
if ("/favicon.ico".Equals(req.Uri))
{
var res = new DefaultFullHttpResponse(Http11, NotFound);
SendHttpResponse(ctx, req, res);
return;
}
if (iJT1078Authorization.Authorization(req, out var principal))
{
if (req.Uri.StartsWith(WebsocketPath))
{
// Handshake
var wsFactory = new WebSocketServerHandshakerFactory(GetWebSocketLocation(req), null, true, 5 * 1024 * 1024);
this.handshaker = wsFactory.NewHandshaker(req);
if (this.handshaker == null)
{
WebSocketServerHandshakerFactory.SendUnsupportedVersionResponse(ctx.Channel);
}
else
{
this.handshaker.HandshakeAsync(ctx.Channel, req);
jT1078HttpSessionManager.TryAdd(principal.Identity.Name, ctx.Channel);
httpMiddleware?.Next(ctx, req, principal);
}
}
else
{
jT1078HttpSessionManager.TryAdd(principal.Identity.Name, ctx.Channel);
httpMiddleware?.Next(ctx, req, principal);
}
}
else {
SendHttpResponse(ctx, req, new DefaultFullHttpResponse(Http11, Unauthorized));
return;
}
}

void HandleWebSocketFrame(IChannelHandlerContext ctx, WebSocketFrame frame)
{
// Check for closing frame
if (frame is CloseWebSocketFrame)
{
this.handshaker.CloseAsync(ctx.Channel, (CloseWebSocketFrame)frame.Retain());
return;
}
if (frame is PingWebSocketFrame)
{
ctx.WriteAsync(new PongWebSocketFrame((IByteBuffer)frame.Content.Retain()));
return;
}
if (frame is TextWebSocketFrame)
{
// Echo the frame
ctx.WriteAsync(frame.Retain());
return;
}
if (frame is BinaryWebSocketFrame)
{
// Echo the frame
ctx.WriteAsync(frame.Retain());
}
}

static void SendHttpResponse(IChannelHandlerContext ctx, IFullHttpRequest req, IFullHttpResponse res)
{
// Generate an error page if response getStatus code is not OK (200).
if (res.Status.Code != 200)
{
res.Headers.Set(ServerEntity, ServerName);
res.Headers.Set(DateEntity, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"));
IByteBuffer buf = Unpooled.CopiedBuffer(Encoding.UTF8.GetBytes(res.Status.ToString()));
res.Content.WriteBytes(buf);
buf.Release();
HttpUtil.SetContentLength(res, res.Content.ReadableBytes);
}
// Send the response and close the connection if necessary.
Task task = ctx.Channel.WriteAndFlushAsync(res);
if (!HttpUtil.IsKeepAlive(req) || res.Status.Code != 200)
{
task.ContinueWith((t, c) => ((IChannelHandlerContext)c).CloseAsync(), ctx, TaskContinuationOptions.ExecuteSynchronously);
}
}

public override void ExceptionCaught(IChannelHandlerContext context, Exception exception)
{
logger.LogError(exception, context.Channel.Id.AsShortText());
context.Channel.WriteAndFlushAsync(new DefaultFullHttpResponse(Http11, InternalServerError));
jT1078HttpSessionManager.RemoveSessionByChannel(context.Channel);
CloseAsync(context);
base.ExceptionCaught(context, exception);
}

public override Task CloseAsync(IChannelHandlerContext context)
{
jT1078HttpSessionManager.RemoveSessionByChannel(context.Channel);
return base.CloseAsync(context);
}

static string GetWebSocketLocation(IFullHttpRequest req)
{
bool result = req.Headers.TryGet(HttpHeaderNames.Host, out ICharSequence value);
string location= value.ToString() + WebsocketPath;
return "ws://" + location;
}
}
}

+ 0
- 30
src/JT1078.DotNetty.Http/JT1078.DotNetty.Http.csproj 查看文件

@@ -1,30 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">

<Import Project="..\Version.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>7.3</LangVersion>
<Copyright>Copyright 2019.</Copyright>
<Authors>SmallChi(Koike)</Authors>
<PackageId>JT1078.DotNetty.Http</PackageId>
<Product>JT1078.DotNetty.Http</Product>
<Description>基于DotNetty实现的JT1078DotNetty的http服务</Description>
<PackageReleaseNotes>基于DotNetty实现的JT1078DotNetty的http服务</PackageReleaseNotes>
<RepositoryUrl>https://github.com/SmallChi/JT1078DotNetty</RepositoryUrl>
<PackageProjectUrl>https://github.com/SmallChi/JT1078DotNetty</PackageProjectUrl>
<licenseUrl>https://github.com/SmallChi/JT1078DotNetty/blob/master/LICENSE</licenseUrl>
<license>https://github.com/SmallChi/JT1078DotNetty/blob/master/LICENSE</license>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<SignAssembly>false</SignAssembly>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<Version>$(JT1078DotNettyPackageVersion)</Version>
</PropertyGroup>

<ItemGroup>
<None Include="..\..\LICENSE" Pack="true" PackagePath="" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\JT1078.DotNetty.Core\JT1078.DotNetty.Core.csproj" />
</ItemGroup>
</Project>

+ 0
- 36
src/JT1078.DotNetty.Http/JT1078HttpBuilderDefault.cs 查看文件

@@ -1,36 +0,0 @@
using JT1078.DotNetty.Core.Interfaces;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using System;
using System.Collections.Generic;
using System.Text;

namespace JT1078.DotNetty.Http
{
class JT1078HttpBuilderDefault : IJT1078HttpBuilder
{
public IJT1078Builder Instance { get; }

public JT1078HttpBuilderDefault(IJT1078Builder builder)
{
Instance = builder;
}

public IJT1078Builder Builder()
{
return Instance;
}

public IJT1078HttpBuilder Replace<T>() where T : IJT1078Authorization
{
Instance.Services.Replace(new ServiceDescriptor(typeof(IJT1078Authorization), typeof(T), ServiceLifetime.Singleton));
return this;
}

public IJT1078HttpBuilder UseHttpMiddleware<T>() where T : IHttpMiddleware
{
Instance.Services.TryAdd(new ServiceDescriptor(typeof(IHttpMiddleware), typeof(T), ServiceLifetime.Singleton));
return this;
}
}
}

+ 0
- 25
src/JT1078.DotNetty.Http/JT1078HttpDotnettyExtensions.cs 查看文件

@@ -1,25 +0,0 @@
using JT1078.DotNetty.Core.Codecs;
using JT1078.DotNetty.Core.Impl;
using JT1078.DotNetty.Core.Interfaces;
using JT1078.DotNetty.Core.Session;
using JT1078.DotNetty.Http.Authorization;
using JT1078.DotNetty.Http.Handlers;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using System.Runtime.CompilerServices;


namespace JT1078.DotNetty.Http
{
public static class JT1078HttpDotnettyExtensions
{
public static IJT1078HttpBuilder AddJT1078HttpHost(this IJT1078Builder builder)
{
builder.Services.TryAddSingleton<JT1078HttpSessionManager>();
builder.Services.TryAddSingleton<IJT1078Authorization, JT1078AuthorizationDefault>();
builder.Services.AddScoped<JT1078HttpServerHandler>();
builder.Services.AddHostedService<JT1078HttpServerHost>();
return new JT1078HttpBuilderDefault(builder);
}
}
}

+ 0
- 99
src/JT1078.DotNetty.Http/JT1078HttpServerHost.cs 查看文件

@@ -1,99 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Codecs;
using DotNetty.Codecs.Http;
using DotNetty.Codecs.Http.Cors;
using DotNetty.Common.Utilities;
using DotNetty.Handlers.Streams;
using DotNetty.Handlers.Timeout;
using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Libuv;
using JT1078.DotNetty.Core.Codecs;
using JT1078.DotNetty.Core.Configurations;
using JT1078.DotNetty.Http.Handlers;
using JT1078.Protocol;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Net;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;

namespace JT1078.DotNetty.Http
{
/// <summary>
/// JT1078 http服务
/// </summary>
internal class JT1078HttpServerHost : IHostedService
{
private readonly JT1078Configuration configuration;
private readonly ILogger<JT1078HttpServerHost> logger;
private DispatcherEventLoopGroup bossGroup;
private WorkerEventLoopGroup workerGroup;
private IChannel bootstrapChannel;
private IByteBufferAllocator serverBufferAllocator;
private readonly IServiceProvider serviceProvider;
public JT1078HttpServerHost(
IServiceProvider serviceProvider,
ILoggerFactory loggerFactory,
IOptions<JT1078Configuration> configurationAccessor)
{
this.serviceProvider = serviceProvider;
configuration = configurationAccessor.Value;
logger=loggerFactory.CreateLogger<JT1078HttpServerHost>();
}

public Task StartAsync(CancellationToken cancellationToken)
{
bossGroup = new DispatcherEventLoopGroup();
workerGroup = new WorkerEventLoopGroup(bossGroup, configuration.EventLoopCount);
serverBufferAllocator = new PooledByteBufferAllocator();
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.Group(bossGroup, workerGroup);
bootstrap.Channel<TcpServerChannel>();
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)
|| RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
bootstrap
.Option(ChannelOption.SoReuseport, true)
.ChildOption(ChannelOption.SoReuseaddr, true);
}
bootstrap
.Option(ChannelOption.SoBacklog, 8192)
.ChildOption(ChannelOption.Allocator, serverBufferAllocator)
.ChildHandler(new ActionChannelInitializer<IChannel>(channel =>
{
IChannelPipeline pipeline = channel.Pipeline;
pipeline.AddLast(new HttpServerCodec());
pipeline.AddLast(new CorsHandler(CorsConfigBuilder
.ForAnyOrigin()
.AllowNullOrigin()
.AllowedRequestMethods(HttpMethod.Get, HttpMethod.Post, HttpMethod.Options, HttpMethod.Delete)
.AllowedRequestHeaders((AsciiString)"origin", (AsciiString)"range", (AsciiString)"accept-encoding", (AsciiString)"referer", (AsciiString)"Cache-Control", (AsciiString)"X-Proxy-Authorization", (AsciiString)"X-Requested-With", (AsciiString)"Content-Type")
.ExposeHeaders((StringCharSequence)"Server", (StringCharSequence)"range", (StringCharSequence)"Content-Length", (StringCharSequence)"Content-Range")
.AllowCredentials()
.Build()));
pipeline.AddLast(new HttpObjectAggregator(int.MaxValue));
using (var scope = serviceProvider.CreateScope())
{
pipeline.AddLast("JT1078HttpServerHandler", scope.ServiceProvider.GetRequiredService<JT1078HttpServerHandler>());
}
}));
logger.LogInformation($"JT1078 Http Server start at {IPAddress.Any}:{configuration.HttpPort}.");
return bootstrap.BindAsync(configuration.HttpPort)
.ContinueWith(i => bootstrapChannel = i.Result);
}

public async Task StopAsync(CancellationToken cancellationToken)
{
await bootstrapChannel.CloseAsync();
var quietPeriod = configuration.QuietPeriodTimeSpan;
var shutdownTimeout = configuration.ShutdownTimeoutTimeSpan;
await workerGroup.ShutdownGracefullyAsync(quietPeriod, shutdownTimeout);
await bossGroup.ShutdownGracefullyAsync(quietPeriod, shutdownTimeout);
}
}
}

+ 0
- 99
src/JT1078.DotNetty.Tcp/Handlers/JT1078TcpConnectionHandler.cs 查看文件

@@ -1,99 +0,0 @@
using DotNetty.Handlers.Timeout;
using DotNetty.Transport.Channels;
using JT1078.DotNetty.Core.Session;
using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks;

namespace JT1078.DotNetty.Tcp.Handlers
{
/// <summary>
/// JT1078服务通道处理程序
/// </summary>
internal class JT1078TcpConnectionHandler : ChannelHandlerAdapter
{
private readonly ILogger<JT1078TcpConnectionHandler> logger;

private readonly JT1078TcpSessionManager SessionManager;

public JT1078TcpConnectionHandler(
JT1078TcpSessionManager sessionManager,
ILoggerFactory loggerFactory)
{
this.SessionManager = sessionManager;
logger = loggerFactory.CreateLogger<JT1078TcpConnectionHandler>();
}

/// <summary>
/// 通道激活
/// </summary>
/// <param name="context"></param>
public override void ChannelActive(IChannelHandlerContext context)
{
string channelId = context.Channel.Id.AsShortText();
if (logger.IsEnabled(LogLevel.Debug))
logger.LogDebug($"<<<{ channelId } Successful client connection to server.");
base.ChannelActive(context);
}

/// <summary>
/// 设备主动断开
/// </summary>
/// <param name="context"></param>
public override void ChannelInactive(IChannelHandlerContext context)
{
string channelId = context.Channel.Id.AsShortText();
if (logger.IsEnabled(LogLevel.Debug))
logger.LogDebug($">>>{ channelId } The client disconnects from the server.");
SessionManager.RemoveSessionByChannel(context.Channel);
base.ChannelInactive(context);
}

/// <summary>
/// 服务器主动断开
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public override Task CloseAsync(IChannelHandlerContext context)
{
string channelId = context.Channel.Id.AsShortText();
if (logger.IsEnabled(LogLevel.Debug))
logger.LogDebug($"<<<{ channelId } The server disconnects from the client.");
SessionManager.RemoveSessionByChannel(context.Channel);
return base.CloseAsync(context);
}

public override void ChannelReadComplete(IChannelHandlerContext context)=> context.Flush();

/// <summary>
/// 超时策略
/// </summary>
/// <param name="context"></param>
/// <param name="evt"></param>
public override void UserEventTriggered(IChannelHandlerContext context, object evt)
{
IdleStateEvent idleStateEvent = evt as IdleStateEvent;
if (idleStateEvent != null)
{
if(idleStateEvent.State== IdleState.ReaderIdle)
{
string channelId = context.Channel.Id.AsShortText();
logger.LogInformation($"{idleStateEvent.State.ToString()}>>>{channelId}");
// 由于808是设备发心跳,如果很久没有上报数据,那么就由服务器主动关闭连接。
SessionManager.RemoveSessionByChannel(context.Channel);
context.CloseAsync();
}
}
base.UserEventTriggered(context, evt);
}

public override void ExceptionCaught(IChannelHandlerContext context, Exception exception)
{
string channelId = context.Channel.Id.AsShortText();
logger.LogError(exception,$"{channelId} {exception.Message}" );
SessionManager.RemoveSessionByChannel(context.Channel);
context.CloseAsync();
}
}
}


+ 0
- 18
src/JT1078.DotNetty.Tcp/Handlers/JT1078TcpMessageProcessorEmptyImpl.cs 查看文件

@@ -1,18 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using JT1078.DotNetty.Core.Interfaces;
using JT1078.DotNetty.Core.Metadata;
using JT1078.Protocol;

namespace JT1078.DotNetty.Tcp.Handlers
{
class JT1078TcpMessageProcessorEmptyImpl : IJT1078TcpMessageHandlers
{
public Task<JT1078Response> Processor(JT1078Request request)
{
return Task.FromResult<JT1078Response>(default);
}
}
}

+ 0
- 69
src/JT1078.DotNetty.Tcp/Handlers/JT1078TcpServerHandler.cs 查看文件

@@ -1,69 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Transport.Channels;
using System;
using Microsoft.Extensions.Logging;
using JT1078.DotNetty.Core.Enums;
using JT1078.DotNetty.Core.Services;
using JT1078.Protocol;
using JT1078.DotNetty.Core.Interfaces;
using JT1078.DotNetty.Core.Session;
using JT1078.DotNetty.Core.Metadata;

namespace JT1078.DotNetty.Tcp.Handlers
{
/// <summary>
/// JT1078 服务端处理程序
/// </summary>
internal class JT1078TcpServerHandler : SimpleChannelInboundHandler<byte[]>
{
private readonly JT1078TcpSessionManager SessionManager;

private readonly JT1078AtomicCounterService AtomicCounterService;

private readonly ILogger<JT1078TcpServerHandler> logger;

private readonly IJT1078TcpMessageHandlers handlers;

public JT1078TcpServerHandler(
IJT1078TcpMessageHandlers handlers,
ILoggerFactory loggerFactory,
JT1078AtomicCounterServiceFactory atomicCounterServiceFactory,
JT1078TcpSessionManager sessionManager)
{
this.handlers = handlers;
this.SessionManager = sessionManager;
this.AtomicCounterService = atomicCounterServiceFactory.Create(JT1078TransportProtocolType.tcp);
logger = loggerFactory.CreateLogger<JT1078TcpServerHandler>();
}


protected override void ChannelRead0(IChannelHandlerContext ctx, byte[] msg)
{
try
{
if (logger.IsEnabled(LogLevel.Trace))
{
logger.LogTrace("accept package success count<<<" + AtomicCounterService.MsgSuccessCount.ToString());
logger.LogTrace("accept msg <<< " + ByteBufferUtil.HexDump(msg));
}
JT1078Package package = JT1078Serializer.Deserialize(msg);
AtomicCounterService.MsgSuccessIncrement();
SessionManager.TryAdd(package.SIM, ctx.Channel);
handlers.Processor(new JT1078Request(package, msg));
if (logger.IsEnabled(LogLevel.Debug))
{
logger.LogDebug("accept package success count<<<" + AtomicCounterService.MsgSuccessCount.ToString());
}
}
catch (Exception ex)
{
AtomicCounterService.MsgFailIncrement();
if (logger.IsEnabled(LogLevel.Error))
{
logger.LogError("accept package fail count<<<" + AtomicCounterService.MsgFailCount.ToString());
logger.LogError(ex, "accept msg<<<" + ByteBufferUtil.HexDump(msg));
}
}
}
}
}

+ 0
- 31
src/JT1078.DotNetty.Tcp/JT1078.DotNetty.Tcp.csproj 查看文件

@@ -1,31 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\Version.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>7.3</LangVersion>
<Copyright>Copyright 2019.</Copyright>
<Authors>SmallChi(Koike)</Authors>
<PackageId>JT1078.DotNetty.Tcp</PackageId>
<Product>JT1078.DotNetty.Tcp</Product>
<Description>基于DotNetty实现的JT1078DotNetty的Tcp服务</Description>
<PackageReleaseNotes>基于DotNetty实现的JT1078DotNetty的Tcp服务</PackageReleaseNotes>
<RepositoryUrl>https://github.com/SmallChi/JT1078DotNetty</RepositoryUrl>
<PackageProjectUrl>https://github.com/SmallChi/JT1078DotNetty</PackageProjectUrl>
<licenseUrl>https://github.com/SmallChi/JT1078DotNetty/blob/master/LICENSE</licenseUrl>
<license>https://github.com/SmallChi/JT1078DotNetty/blob/master/LICENSE</license>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<SignAssembly>false</SignAssembly>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<Version>$(JT1078DotNettyPackageVersion)</Version>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\JT1078.DotNetty.Core\JT1078.DotNetty.Core.csproj" />
</ItemGroup>

<ItemGroup>
<None Include="..\..\LICENSE" Pack="true" PackagePath="" />
</ItemGroup>

</Project>

+ 0
- 30
src/JT1078.DotNetty.Tcp/JT1078TcpBuilderDefault.cs 查看文件

@@ -1,30 +0,0 @@
using JT1078.DotNetty.Core.Interfaces;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using System;
using System.Collections.Generic;
using System.Text;

namespace JT1078.DotNetty.Tcp
{
class JT1078TcpBuilderDefault : IJT1078TcpBuilder
{
public IJT1078Builder Instance { get; }

public JT1078TcpBuilderDefault(IJT1078Builder builder)
{
Instance = builder;
}

public IJT1078Builder Builder()
{
return Instance;
}

public IJT1078TcpBuilder Replace<T>() where T : IJT1078TcpMessageHandlers
{
Instance.Services.Replace(new ServiceDescriptor(typeof(IJT1078TcpMessageHandlers), typeof(T), ServiceLifetime.Singleton));
return this;
}
}
}

+ 0
- 26
src/JT1078.DotNetty.Tcp/JT1078TcpDotnettyExtensions.cs 查看文件

@@ -1,26 +0,0 @@
using JT1078.DotNetty.Core.Codecs;
using JT1078.DotNetty.Core.Interfaces;
using JT1078.DotNetty.Core.Session;
using JT1078.DotNetty.Tcp.Handlers;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("JT1078.DotNetty.Tcp.Test")]

namespace JT1078.DotNetty.Tcp
{
public static class JT1078TcpDotnettyExtensions
{
public static IJT1078TcpBuilder AddJT1078TcpHost(this IJT1078Builder builder)
{
builder.Services.TryAddSingleton<JT1078TcpSessionManager>();
builder.Services.TryAddScoped<JT1078TcpConnectionHandler>();
builder.Services.TryAddScoped<JT1078TcpDecoder>();
builder.Services.TryAddSingleton<IJT1078TcpMessageHandlers, JT1078TcpMessageProcessorEmptyImpl>();
builder.Services.TryAddScoped<JT1078TcpServerHandler>();
builder.Services.AddHostedService<JT1078TcpServerHost>();
return new JT1078TcpBuilderDefault(builder);
}
}
}

+ 0
- 94
src/JT1078.DotNetty.Tcp/JT1078TcpServerHost.cs 查看文件

@@ -1,94 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Codecs;
using DotNetty.Handlers.Timeout;
using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Libuv;
using JT1078.DotNetty.Core.Codecs;
using JT1078.DotNetty.Core.Configurations;
using JT1078.DotNetty.Tcp.Handlers;
using JT1078.Protocol;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Net;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;

namespace JT1078.DotNetty.Tcp
{
/// <summary>
/// JT1078 Tcp网关服务
/// </summary>
internal class JT1078TcpServerHost : IHostedService
{
private readonly IServiceProvider serviceProvider;
private readonly JT1078Configuration configuration;
private readonly ILogger<JT1078TcpServerHost> logger;
private DispatcherEventLoopGroup bossGroup;
private WorkerEventLoopGroup workerGroup;
private IChannel bootstrapChannel;
private IByteBufferAllocator serverBufferAllocator;

public JT1078TcpServerHost(
IServiceProvider provider,
ILoggerFactory loggerFactory,
IOptions<JT1078Configuration> configurationAccessor)
{
serviceProvider = provider;
configuration = configurationAccessor.Value;
logger=loggerFactory.CreateLogger<JT1078TcpServerHost>();
}

public Task StartAsync(CancellationToken cancellationToken)
{
bossGroup = new DispatcherEventLoopGroup();
workerGroup = new WorkerEventLoopGroup(bossGroup, configuration.EventLoopCount);
serverBufferAllocator = new PooledByteBufferAllocator();
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.Group(bossGroup, workerGroup);
bootstrap.Channel<TcpServerChannel>();
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)
|| RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
bootstrap
.Option(ChannelOption.SoReuseport, true)
.ChildOption(ChannelOption.SoReuseaddr, true);
}
bootstrap
.Option(ChannelOption.SoBacklog, configuration.SoBacklog)
.ChildOption(ChannelOption.Allocator, serverBufferAllocator)
.ChildHandler(new ActionChannelInitializer<IChannel>(channel =>
{
IChannelPipeline pipeline = channel.Pipeline;
using (var scope = serviceProvider.CreateScope())
{
channel.Pipeline.AddLast("JT1078TcpBuffer", new DelimiterBasedFrameDecoder(int.MaxValue,true,
Unpooled.CopiedBuffer(JT1078Package.FH_Bytes)));
channel.Pipeline.AddLast("JT1078TcpDecode", scope.ServiceProvider.GetRequiredService<JT1078TcpDecoder>());
channel.Pipeline.AddLast("JT1078SystemIdleState", new IdleStateHandler(
configuration.ReaderIdleTimeSeconds,
configuration.WriterIdleTimeSeconds,
configuration.AllIdleTimeSeconds));
channel.Pipeline.AddLast("JT1078TcpConnection", scope.ServiceProvider.GetRequiredService<JT1078TcpConnectionHandler>());
channel.Pipeline.AddLast("JT1078TcpService", scope.ServiceProvider.GetRequiredService<JT1078TcpServerHandler>());
}
}));
logger.LogInformation($"JT1078 TCP Server start at {IPAddress.Any}:{configuration.TcpPort}.");
return bootstrap.BindAsync(configuration.TcpPort)
.ContinueWith(i => bootstrapChannel = i.Result);
}

public async Task StopAsync(CancellationToken cancellationToken)
{
await bootstrapChannel.CloseAsync();
var quietPeriod = configuration.QuietPeriodTimeSpan;
var shutdownTimeout = configuration.ShutdownTimeoutTimeSpan;
await workerGroup.ShutdownGracefullyAsync(quietPeriod, shutdownTimeout);
await bossGroup.ShutdownGracefullyAsync(quietPeriod, shutdownTimeout);
}
}
}

+ 0
- 13
src/JT1078.DotNetty.Tcp/Properties/PublishProfiles/FolderProfile.pubxml 查看文件

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<PublishProtocol>FileSystem</PublishProtocol>
<Configuration>Release</Configuration>
<Platform>Any CPU</Platform>
<TargetFramework>netstandard2.0</TargetFramework>
<PublishDir>..\..\publish\</PublishDir>
</PropertyGroup>
</Project>

+ 0
- 3106
src/JT1078.DotNetty.TestHosting/Configs/NLog.xsd
文件差異過大導致無法顯示
查看文件


+ 0
- 56
src/JT1078.DotNetty.TestHosting/Configs/nlog.unix.config 查看文件

@@ -1,56 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!--
参考:http://www.cnblogs.com/fuchongjundream/p/3936431.html
autoReload:自动再配置
internalLogFile:可以让NLog把内部的调试和异常信息都写入指定文件里程序没问题了,日志却出了问题。这个该怎么办,到底是哪里不正确了?假如日志本身除了bug该如何解决?这就需要日志排错。把日志的错误信息写入日志。
<nlog throwExceptions="true" />
<nlog internalLogFile="file.txt" />- 设置internalLogFile属性可以让NLog把内部的调试和异常信息都写入指定文件里。
<nlog internalLogLevel="Trace|Debug|Info|Warn|Error|Fatal" /> - 决定内部日志的级别,级别越高,输出的日志信息越简洁。
<nlog internalLogToConsole="false|true" /> - 是否把内部日志输出到标准控制台。
<nlog internalLogToConsoleError="false|true" /> - 是否把内部日志输出到标准错误控制台 (stderr)。
设置throwExceptions属性为“true”可以让NLog不再阻挡这类异常,而是把它们抛给调用者。在部署是这样做可以帮我们快速定位问题。一旦应用程序已经正确配置了,我们建议把throwExceptions的值设为“false”,这样由于日志引发的问题不至于导致应用程序的崩溃。
-->
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xsi:schemaLocation="NLog NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
internalLogFile="wwwroot/logs/internalLog.txt"
internalLogLevel="Debug" >
<variable name="Directory" value="/data/logs/JT1078.Gateway"/>
<targets>
<target name="all" xsi:type="File"
fileName="${Directory}/all/${shortdate}.log"
layout="${date:format=yyyyMMddHHmmss} ${callsite} ${level}:${message} ${onexception:${exception:format=tostring} ${newline} ${stacktrace} ${newline}"/>
<target name="flvencoding" xsi:type="File"
fileName="${Directory}/flvencoding/${shortdate}.log"
layout="${date:format=yyyyMMddHHmmss}:${message}"/>
<target name="JT1078TcpMessageHandlers" xsi:type="File"
fileName="${Directory}/JT1078TcpMessageHandlers/${shortdate}.log"
layout="${date:format=yyyyMMddHHmmss},${message}"/>
<target name="JT1078TcpMessageHandlersHex" xsi:type="File"
fileName="${Directory}/JT1078TcpMessageHandlersHex/${shortdate}.log"
layout="${date:format=yyyyMMddHHmmss},${message}"/>
<target name="FlvEncoder" xsi:type="File"
fileName="${Directory}/FlvEncoder/${shortdate}.log"
layout="${date:format=yyyyMMddHHmmss},${message}"/>
<target name="JT1078TcpConnectionHandler" xsi:type="File"
fileName="${Directory}/JT1078TcpConnectionHandler/${shortdate}.log"
layout="${date:format=yyyyMMddHHmmss},${message}"/>
<target name="console" xsi:type="ColoredConsole"
useDefaultRowHighlightingRules="false"
layout="${date:format=yyyyMMddHHmmss} ${callsite} ${level} ${message} ${onexception:${exception:format=tostring} ${newline} ${stacktrace} ${newline}">
<highlight-row condition="level == LogLevel.Debug" foregroundColor="DarkGray" />
<highlight-row condition="level == LogLevel.Info" foregroundColor="Gray" />
<highlight-row condition="level == LogLevel.Warn" foregroundColor="Yellow" />
<highlight-row condition="level == LogLevel.Error" foregroundColor="Red" />
<highlight-row condition="level == LogLevel.Fatal" foregroundColor="Red" backgroundColor="White" />
</target>
</targets>
<rules>
<logger name="*" minlevel="Error" maxlevel="Fatal" writeTo="all"/>
<logger name="FlvEncoding" minlevel="Debug" maxlevel="Fatal" writeTo="flvencoding"/>
<logger name="JT1078.DotNetty.Tcp.Handlers.JT1078TcpConnectionHandler" minlevel="Debug" maxlevel="Fatal" writeTo="JT1078TcpConnectionHandler,console"/>
<logger name="JT1078TcpMessageHandlers" minlevel="Debug" maxlevel="Fatal" writeTo="JT1078TcpMessageHandlers"/>
<logger name="JT1078TcpMessageHandlersHex" minlevel="Debug" maxlevel="Fatal" writeTo="JT1078TcpMessageHandlersHex"/>
<logger name="FlvEncoder" minlevel="Debug" maxlevel="Fatal" writeTo="FlvEncoder"/>
</rules>
</nlog>

+ 0
- 48
src/JT1078.DotNetty.TestHosting/Configs/nlog.win.config 查看文件

@@ -1,48 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!--
参考:http://www.cnblogs.com/fuchongjundream/p/3936431.html
autoReload:自动再配置
internalLogFile:可以让NLog把内部的调试和异常信息都写入指定文件里程序没问题了,日志却出了问题。这个该怎么办,到底是哪里不正确了?假如日志本身除了bug该如何解决?这就需要日志排错。把日志的错误信息写入日志。
<nlog throwExceptions="true" />
<nlog internalLogFile="file.txt" />- 设置internalLogFile属性可以让NLog把内部的调试和异常信息都写入指定文件里。
<nlog internalLogLevel="Trace|Debug|Info|Warn|Error|Fatal" /> - 决定内部日志的级别,级别越高,输出的日志信息越简洁。
<nlog internalLogToConsole="false|true" /> - 是否把内部日志输出到标准控制台。
<nlog internalLogToConsoleError="false|true" /> - 是否把内部日志输出到标准错误控制台 (stderr)。
设置throwExceptions属性为“true”可以让NLog不再阻挡这类异常,而是把它们抛给调用者。在部署是这样做可以帮我们快速定位问题。一旦应用程序已经正确配置了,我们建议把throwExceptions的值设为“false”,这样由于日志引发的问题不至于导致应用程序的崩溃。
-->
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xsi:schemaLocation="NLog NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
internalLogFile="wwwroot/logs/internalLog.txt"
internalLogLevel="Debug" >
<variable name="Directory" value="${basedir}/wwwroot/logs/JT1078.Gateway"/>
<targets>
<target name="all" xsi:type="File"
fileName="${Directory}/all/${shortdate}.log"
layout="${date:format=yyyyMMddHHmmss} ${callsite} ${level}:${message} ${onexception:${exception:format=tostring} ${newline} ${stacktrace} ${newline}"/>
<target name="JT1078TcpMessageHandlers" xsi:type="File"
fileName="${Directory}/JT1078TcpMessageHandlers/${shortdate}.log"
layout="${date:format=yyyyMMddHHmmss},${message}"/>
<target name="JT1078TcpMessageHandlersHex" xsi:type="File"
fileName="${Directory}/JT1078TcpMessageHandlersHex/${shortdate}.log"
layout="${date:format=yyyyMMddHHmmss},${message}"/>
<target name="JT1078TcpConnectionHandler" xsi:type="File"
fileName="${Directory}/JT1078TcpConnectionHandler/${shortdate}.log"
layout="${date:format=yyyyMMddHHmmss},${message}"/>
<target name="console" xsi:type="ColoredConsole"
useDefaultRowHighlightingRules="false"
layout="${date:format=yyyyMMddHHmmss} ${callsite} ${level} ${message} ${onexception:${exception:format=tostring} ${newline} ${stacktrace} ${newline}">
<highlight-row condition="level == LogLevel.Debug" foregroundColor="DarkGray" />
<highlight-row condition="level == LogLevel.Info" foregroundColor="Gray" />
<highlight-row condition="level == LogLevel.Warn" foregroundColor="Yellow" />
<highlight-row condition="level == LogLevel.Error" foregroundColor="Red" />
<highlight-row condition="level == LogLevel.Fatal" foregroundColor="Red" backgroundColor="White" />
</target>
</targets>
<rules>
<logger name="*" minlevel="Debug" maxlevel="Fatal" writeTo="all,console"/>
<logger name="JT1078.DotNetty.Tcp.Handlers.JT1078TcpConnectionHandler" minlevel="Debug" maxlevel="Fatal" writeTo="JT1078TcpConnectionHandler,console"/>
<logger name="JT1078TcpMessageHandlers" minlevel="Debug" maxlevel="Fatal" writeTo="JT1078TcpMessageHandlers,console"/>
<logger name="JT1078TcpMessageHandlersHex" minlevel="Debug" maxlevel="Fatal" writeTo="JT1078TcpMessageHandlersHex,console"/>
</rules>
</nlog>

+ 0
- 18
src/JT1078.DotNetty.TestHosting/CustomHttpMiddleware.cs 查看文件

@@ -1,18 +0,0 @@
using DotNetty.Codecs.Http;
using DotNetty.Transport.Channels;
using JT1078.DotNetty.Core.Interfaces;
using System;
using System.Collections.Generic;
using System.Security.Principal;
using System.Text;

namespace JT1078.DotNetty.TestHosting
{
public class CustomHttpMiddleware : IHttpMiddleware
{
public void Next(IChannelHandlerContext ctx, IFullHttpRequest req, IPrincipal principal)
{
Console.WriteLine("CustomHttpMiddleware");
}
}
}

+ 0
- 109
src/JT1078.DotNetty.TestHosting/HLS/FFMPEGHLSHostedService.cs 查看文件

@@ -1,109 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Codecs.Http.WebSockets;
using JT1078.DotNetty.Core.Session;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using JT1078.Protocol;
using System.Collections.Concurrent;
using JT1078.Protocol.Enums;
using System.Diagnostics;
using System.IO.Pipes;
using Newtonsoft.Json;
using DotNetty.Common.Utilities;
using DotNetty.Codecs.Http;
using DotNetty.Handlers.Streams;
using DotNetty.Transport.Channels;
using Microsoft.AspNetCore.Hosting;
using System.Net;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Cors;
using Microsoft.Extensions.Configuration;
using Microsoft.AspNetCore.Builder;
using JT1078.DotNetty.TestHosting.HLS;
using Microsoft.Extensions.Logging;

namespace JT1078.DotNetty.TestHosting
{
/// <summary>
///
/// -hls_list_size 10 m3u8内部文件内部保留10个集合
/// -segment_time 10秒切片
/// -hls_wrap 可以让切片文件进行循环 就不会导致产生很多文件了 占用很多空间
/// ./ffmpeg -f dshow -i video="USB2.0 PC CAMERA" -hls_wrap 20 -start_number 0 -hls_list_size 10 -f hls "D:\v\sample.m3u8 -segment_time 10"
/// </summary>
class FFMPEGHLSHostedService : IHostedService
{
private readonly Process process;
private const string FileName= "hls_ch1.m3u8";
private const string DirectoryName = "hlsvideo";
private readonly IWebHost webHost;
public FFMPEGHLSHostedService()
{
string directoryPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, DirectoryName);
if (Directory.Exists(directoryPath))
{
Directory.Delete(directoryPath,true);
Directory.CreateDirectory(directoryPath);
}
else
{
Directory.CreateDirectory(directoryPath);
}
string filePath =$"\"{Path.Combine(directoryPath, FileName)}\"";
process = new Process
{
StartInfo =
{
FileName = @"C:\ffmpeg\bin\ffmpeg.exe",
Arguments = $@"-f dshow -i video={HardwareCamera.CameraName} -vcodec h264 -hls_wrap 10 -start_number 0 -hls_list_size 10 -f hls {filePath} -segment_time 10",
UseShellExecute = false,
CreateNoWindow = true
}
};
webHost= new WebHostBuilder()
.ConfigureLogging((_, factory) =>
{
factory.SetMinimumLevel(LogLevel.Debug);
factory.AddConsole();
})
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,"HLS"));
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
})
.UseKestrel(ksOptions =>
{
ksOptions.ListenAnyIP(5001);
})
.UseWebRoot(AppDomain.CurrentDomain.BaseDirectory)
.UseStartup<Startup>()
.Build();
}

public Task StartAsync(CancellationToken cancellationToken)
{
process.Start();
webHost.RunAsync(cancellationToken);
return Task.CompletedTask;
}

public Task StopAsync(CancellationToken cancellationToken)
{
try
{
process.Kill();
}
catch
{
}
webHost.WaitForShutdownAsync();
return Task.CompletedTask;
}
}
}

+ 0
- 25
src/JT1078.DotNetty.TestHosting/HLS/Startup.cs 查看文件

@@ -1,25 +0,0 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Text;

namespace JT1078.DotNetty.TestHosting.HLS
{
public class Startup
{
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
//mime
//https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/StreamingMediaGuide/DeployingHTTPLiveStreaming/DeployingHTTPLiveStreaming.html
var Provider = new FileExtensionContentTypeProvider();
Provider.Mappings[".m3u8"] = "application/x-mpegURL,vnd.apple.mpegURL";
Provider.Mappings[".ts"] = "video/MP2T";
app.UseStaticFiles(new StaticFileOptions()
{
ContentTypeProvider = Provider
});
}
}
}

+ 0
- 9
src/JT1078.DotNetty.TestHosting/HLS/appsettings.json 查看文件

@@ -1,9 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Debug" //Warning
}
},
"AllowedHosts": "*",
"AllowedOrigins": "*"
}

+ 0
- 25
src/JT1078.DotNetty.TestHosting/HLS/hls.html 查看文件

@@ -1,25 +0,0 @@
<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>hls demo</title>
<script src="hls.min.js"></script>
</head>
<body>
<h6>https://poanchen.github.io/blog/2016/11/17/how-to-play-mp4-video-using-hls</h6>
<video muted="muted" webkit-playsinline="true" autoplay="true" id="player"></video>
<script type="text/javascript">
var video = document.getElementById("player");
var videoSrcHls = "/hlsvideo/hls_ch1.m3u8";
if (Hls.isSupported()) {
var hls = new Hls();
hls.loadSource(videoSrcHls);
hls.attachMedia(video);
hls.on(Hls.Events.MANIFEST_PARSED, function () {
video.play();
});
}
</script>
</body>
</html>

+ 0
- 2
src/JT1078.DotNetty.TestHosting/HLS/hls.min.js
文件差異過大導致無法顯示
查看文件


+ 0
- 134
src/JT1078.DotNetty.TestHosting/HTTPFLV/FFMPEGHTTPFLVHostedService.cs 查看文件

@@ -1,134 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Codecs.Http.WebSockets;
using JT1078.DotNetty.Core.Session;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using JT1078.Protocol;
using System.Collections.Concurrent;
using JT1078.Protocol.Enums;
using System.Diagnostics;
using System.IO.Pipes;
using Newtonsoft.Json;
using DotNetty.Common.Utilities;
using DotNetty.Codecs.Http;
using DotNetty.Handlers.Streams;
using DotNetty.Transport.Channels;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using JT1078.DotNetty.Core.Extensions;

namespace JT1078.DotNetty.TestHosting
{
class FFMPEGHTTPFLVHostedService : IHostedService,IDisposable
{
private readonly Process process;
private readonly NamedPipeServerStream pipeServerOut;
private const string PipeNameOut = "demo1serverout";

private readonly JT1078HttpSessionManager jT1078HttpSessionManager;

/// <summary>
/// 需要缓存flv的第一包数据,当新用户进来先推送第一包的数据
/// </summary>
private byte[] flvFirstPackage;
private ConcurrentDictionary<string, byte> exists = new ConcurrentDictionary<string, byte>();
public FFMPEGHTTPFLVHostedService(JT1078HttpSessionManager jT1078HttpSessionManager)
{
pipeServerOut = new NamedPipeServerStream(PipeNameOut, PipeDirection.In, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous,10240,10240);
process = new Process
{
StartInfo =
{
FileName = @"C:\ffmpeg\bin\ffmpeg.exe",
Arguments = $@"-f dshow -i video={HardwareCamera.CameraName} -c copy -f flv -vcodec h264 -y \\.\pipe\{PipeNameOut}",
UseShellExecute = false,
CreateNoWindow = true
}
};
this.jT1078HttpSessionManager = jT1078HttpSessionManager;
}
public Task StartAsync(CancellationToken cancellationToken)
{
process.Start();
Task.Run(() =>
{
while (true)
{
try
{
Console.WriteLine("IsConnected>>>" + pipeServerOut.IsConnected);
if (pipeServerOut.IsConnected)
{
if (pipeServerOut.CanRead)
{
Span<byte> v1 = new byte[2048];
var length = pipeServerOut.Read(v1);
var realValue = v1.Slice(0, length).ToArray();
if (realValue.Length <= 0) continue;
if (flvFirstPackage == null)
{
flvFirstPackage = realValue;
}
if (jT1078HttpSessionManager.GetAll().Count() > 0)
{
foreach (var session in jT1078HttpSessionManager.GetAll())
{
if (!exists.ContainsKey(session.Channel.Id.AsShortText()))
{
session.SendHttpFirstChunkAsync(flvFirstPackage);
exists.TryAdd(session.Channel.Id.AsShortText(), 0);
}
session.SendHttpOtherChunkAsync(realValue);
}
}
//Console.WriteLine(JsonConvert.SerializeObject(realValue)+"-"+ length.ToString());
}
}
else
{
if (!pipeServerOut.IsConnected)
{
Console.WriteLine("WaitForConnection Star...");
pipeServerOut.WaitForConnectionAsync().Wait(300);
Console.WriteLine("WaitForConnection End...");
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
});
return Task.CompletedTask;
}
public void Dispose()
{
pipeServerOut.Dispose();
}
public Task StopAsync(CancellationToken cancellationToken)
{
try
{
process.Kill();
pipeServerOut.Flush();
pipeServerOut.Close();
}
catch
{


}
return Task.CompletedTask;
}
}
}

+ 0
- 26
src/JT1078.DotNetty.TestHosting/HTTPFLV/flv.html 查看文件

@@ -1,26 +0,0 @@
<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<script src="flv.min.js"></script>
</head>
<body>
<video muted="muted" webkit-playsinline="true" autoplay="true" id="player"></video>
<script>

if (flvjs.isSupported()) {
var player = document.getElementById('player');
var flvPlayer = flvjs.createPlayer({
type: 'flv',
isLive: true,
url: "http://127.0.0.1:1818/demo.flv?token=" + Math.floor((Math.random() * 1000000) + 1)
});
flvPlayer.attachMediaElement(player);
flvPlayer.load();
flvPlayer.play();
}
</script>
</body>
</html>

+ 0
- 7
src/JT1078.DotNetty.TestHosting/HTTPFLV/flv.min.js
文件差異過大導致無法顯示
查看文件


+ 0
- 42
src/JT1078.DotNetty.TestHosting/Handlers/JT1078TcpMessageHandlers.cs 查看文件

@@ -1,42 +0,0 @@
using DotNetty.Buffers;
using JT1078.DotNetty.Core.Interfaces;
using JT1078.DotNetty.Core.Metadata;
using JT1078.DotNetty.TestHosting.JT1078WSFlv;
using JT1078.Protocol;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace JT1078.DotNetty.TestHosting.Handlers
{
public class JT1078TcpMessageHandlers : IJT1078TcpMessageHandlers
{
private readonly ILogger logger;
private readonly ILogger hexLogger;
private readonly JT1078WSFlvDataService jT1078WSFlvDataService;
public JT1078TcpMessageHandlers(
JT1078WSFlvDataService jT1078WSFlvDataServic,
ILoggerFactory loggerFactory)
{
this.jT1078WSFlvDataService = jT1078WSFlvDataServic;
logger = loggerFactory.CreateLogger("JT1078TcpMessageHandlers");
hexLogger = loggerFactory.CreateLogger("JT1078TcpMessageHandlersHex");
}

public Task<JT1078Response> Processor(JT1078Request request)
{
logger.LogInformation(JsonConvert.SerializeObject(request.Package));
//hexLogger.LogInformation($"{request.Package.SIM},{request.Package.Label3.DataType.ToString()},{request.Package.LastFrameInterval},{request.Package.LastIFrameInterval},{request.Package.Timestamp},{request.Package.SN},{request.Package.LogicChannelNumber},{request.Package.Label3.SubpackageType.ToString()},{ByteBufferUtil.HexDump(request.Src)}");
hexLogger.LogInformation($"{request.Package.SIM},{request.Package.SN},{request.Package.LogicChannelNumber},{request.Package.Label3.DataType.ToString()},{request.Package.Label3.SubpackageType.ToString()},{ByteBufferUtil.HexDump(request.Src)}");
var mergePackage = JT1078Serializer.Merge(request.Package);
if (mergePackage != null)
{
jT1078WSFlvDataService.JT1078Packages.Add(mergePackage);
}
return Task.FromResult<JT1078Response>(default);
}
}
}

+ 0
- 25
src/JT1078.DotNetty.TestHosting/Handlers/JT1078UdpMessageHandlers.cs 查看文件

@@ -1,25 +0,0 @@
using JT1078.DotNetty.Core.Interfaces;
using JT1078.DotNetty.Core.Metadata;
using JT1078.Protocol;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.Threading.Tasks;

namespace JT1078.DotNetty.TestHosting.Handlers
{
public class JT1078UdpMessageHandlers : IJT1078UdpMessageHandlers
{
private readonly ILogger<JT1078UdpMessageHandlers> logger;

public JT1078UdpMessageHandlers(ILoggerFactory loggerFactory)
{
logger = loggerFactory.CreateLogger<JT1078UdpMessageHandlers>();
}

public Task<JT1078Response> Processor(JT1078Request request)
{
logger.LogDebug(JsonConvert.SerializeObject(request.Package));
return Task.FromResult<JT1078Response>(default);
}
}
}

+ 0
- 24
src/JT1078.DotNetty.TestHosting/HardwareCamera.cs 查看文件

@@ -1,24 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace JT1078.DotNetty.TestHosting
{
/// <summary>
///
/// .\ffmpeg -list_options true -f dshow -i video = "USB2.0 PC CAMERA"
/// .\ffmpeg -f dshow -i video = "USB2.0 PC CAMERA" -vcodec libx264 "D:\mycamera.flv"
///
/// .\ffmpeg -f dshow -i video = "USB2.0 PC CAMERA" - c copy -f flv -vcodec h264 "rtmp://127.0.0.1/living/streamName"
/// .\ffplay rtmp://127.0.0.1/living/streamName
///
/// .\ffmpeg -f dshow -i video = "USB2.0 PC CAMERA" - c copy -f -y flv -vcodec h264 "pipe://demoserverout"
///
/// ref:https://www.cnblogs.com/lidabo/p/8662955.html
/// </summary>
public static class HardwareCamera
{
public const string CameraName = "\"USB2.0 PC CAMERA\"";
public const string RTMPURL = "rtmp://127.0.0.1/living/streamName";
}
}

+ 0
- 80
src/JT1078.DotNetty.TestHosting/HexExtensions.cs 查看文件

@@ -1,80 +0,0 @@
using System;

namespace JT1078.DotNetty.TestHosting
{
public static partial class BinaryExtensions
{
public static string ToHexString(this byte[] source)
{
return HexUtil.DoHexDump(source, 0, source.Length).ToUpper();
}
/// <summary>
/// 16进制字符串转16进制数组
/// </summary>
/// <param name="hexString"></param>
/// <param name="separator"></param>
/// <returns></returns>
public static byte[] ToHexBytes(this string hexString)
{
hexString = hexString.Replace(" ", "");
byte[] buf = new byte[hexString.Length / 2];
ReadOnlySpan<char> readOnlySpan = hexString.AsSpan();
for (int i = 0; i < hexString.Length; i++)
{
if (i % 2 == 0)
{
buf[i / 2] = Convert.ToByte(readOnlySpan.Slice(i, 2).ToString(), 16);
}
}
return buf;
}
}

public static class HexUtil
{
static readonly char[] HexdumpTable = new char[256 * 4];
static HexUtil()
{
char[] digits = "0123456789ABCDEF".ToCharArray();
for (int i = 0; i < 256; i++)
{
HexdumpTable[i << 1] = digits[(int)((uint)i >> 4 & 0x0F)];
HexdumpTable[(i << 1) + 1] = digits[i & 0x0F];
}
}

public static string DoHexDump(ReadOnlySpan<byte> buffer, int fromIndex, int length)
{
if (length == 0)
{
return "";
}
int endIndex = fromIndex + length;
var buf = new char[length << 1];
int srcIdx = fromIndex;
int dstIdx = 0;
for (; srcIdx < endIndex; srcIdx++, dstIdx += 2)
{
Array.Copy(HexdumpTable, buffer[srcIdx] << 1, buf, dstIdx, 2);
}
return new string(buf);
}

public static string DoHexDump(byte[] array, int fromIndex, int length)
{
if (length == 0)
{
return "";
}
int endIndex = fromIndex + length;
var buf = new char[length << 1];
int srcIdx = fromIndex;
int dstIdx = 0;
for (; srcIdx < endIndex; srcIdx++, dstIdx += 2)
{
Array.Copy(HexdumpTable, (array[srcIdx] & 0xFF) << 1, buf, dstIdx, 2);
}
return new string(buf);
}
}
}

+ 0
- 72
src/JT1078.DotNetty.TestHosting/JT1078.DotNetty.TestHosting.csproj 查看文件

@@ -1,72 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="JT1078.Flv" Version="1.0.0-preview2" />
<PackageReference Include="Microsoft.AspNetCore.Cors" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.2.7" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.0.0" />
<PackageReference Include="NLog.Extensions.Logging" Version="1.6.0" />
</ItemGroup>


<ItemGroup>
<ProjectReference Include="..\JT1078.DotNetty.Http\JT1078.DotNetty.Http.csproj" />
<ProjectReference Include="..\JT1078.DotNetty.Tcp\JT1078.DotNetty.Tcp.csproj" />
<ProjectReference Include="..\JT1078.DotNetty.Udp\JT1078.DotNetty.Udp.csproj" />
</ItemGroup>


<ItemGroup>
<Reference Include="JT1078.Flv">
<HintPath>dll\JT1078.Flv.dll</HintPath>
</Reference>
</ItemGroup>

<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Configs\nlog.unix.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Configs\nlog.win.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Configs\NLog.xsd">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="HLS\appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="HLS\hls.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="HLS\hls.min.js">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="HTTPFLV\flv.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="HTTPFLV\flv.min.js">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="JT1078WSFlv\flv.min.js">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="JT1078WSFlv\index.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>

+ 0
- 17
src/JT1078.DotNetty.TestHosting/JT1078WSFlv/JT1078WSFlvDataService.cs 查看文件

@@ -1,17 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.Concurrent;
using JT1078.Protocol;

namespace JT1078.DotNetty.TestHosting.JT1078WSFlv
{
public class JT1078WSFlvDataService
{
public JT1078WSFlvDataService()
{
JT1078Packages = new BlockingCollection<JT1078Package>();
}
public BlockingCollection<JT1078Package> JT1078Packages { get; set; }
}
}

+ 0
- 105
src/JT1078.DotNetty.TestHosting/JT1078WSFlv/JT1078WSFlvHostedService.cs 查看文件

@@ -1,105 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Codecs.Http.WebSockets;
using JT1078.DotNetty.Core.Session;
using JT1078.DotNetty.Core.Extensions;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using JT1078.Protocol;
using System.Collections.Concurrent;
using JT1078.Protocol.Enums;
using System.Diagnostics;
using System.IO.Pipes;
using Newtonsoft.Json;
using JT1078.DotNetty.TestHosting.JT1078WSFlv;
using JT1078.Flv;
using JT1078.Flv.H264;
using Microsoft.Extensions.Logging;

namespace JT1078.DotNetty.TestHosting
{
/// <summary>
///
/// </summary>
class JT1078WSFlvHostedService : IHostedService
{
private readonly JT1078HttpSessionManager jT1078HttpSessionManager;

private ConcurrentDictionary<string, byte> exists = new ConcurrentDictionary<string, byte>();

private readonly JT1078WSFlvDataService jT1078WSFlvDataService;
private readonly FlvEncoder FlvEncoder;
private readonly ILogger logger;
private readonly ILogger flvEncodingLogger;
public JT1078WSFlvHostedService(
ILoggerFactory loggerFactory,
JT1078WSFlvDataService jT1078WSFlvDataServic,
JT1078HttpSessionManager jT1078HttpSessionManager)
{
logger = loggerFactory.CreateLogger("JT1078WSFlvHostedService");
flvEncodingLogger = loggerFactory.CreateLogger("FlvEncoding");
this.jT1078WSFlvDataService = jT1078WSFlvDataServic;
this.jT1078HttpSessionManager = jT1078HttpSessionManager;
FlvEncoder = new FlvEncoder(loggerFactory);
}

public Task StartAsync(CancellationToken cancellationToken)
{
Task.Run(() =>
{
try
{
Stopwatch stopwatch = new Stopwatch();
foreach (var item in jT1078WSFlvDataService.JT1078Packages.GetConsumingEnumerable())
{
stopwatch.Start();
var flv3 = FlvEncoder.CreateFlvFrame(item);
stopwatch.Stop();
if(flvEncodingLogger.IsEnabled(LogLevel.Debug))
{
long times = stopwatch.ElapsedMilliseconds;
flvEncodingLogger.LogDebug($"flv encoding {times.ToString()}ms");
}
stopwatch.Reset();
if (flv3 == null) continue;
if (jT1078HttpSessionManager.GetAll().Count() > 0)
{
foreach (var session in jT1078HttpSessionManager.GetAll())
{
if (!exists.ContainsKey(session.Channel.Id.AsShortText()))
{
exists.TryAdd(session.Channel.Id.AsShortText(), 0);
string key = item.GetKey();
//ws-flv
//session.SendBinaryWebSocketAsync(FlvEncoder.GetFirstFlvFrame(key, flv3));
//http-flv
session.SendHttpFirstChunkAsync(FlvEncoder.GetFirstFlvFrame(key, flv3));
continue;
}
//ws-flv
//session.SendBinaryWebSocketAsync(flv3);
//http-flv
session.SendHttpOtherChunkAsync(flv3);
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
});
return Task.CompletedTask;
}

public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
}

+ 0
- 7
src/JT1078.DotNetty.TestHosting/JT1078WSFlv/flv.min.js
文件差異過大導致無法顯示
查看文件


+ 0
- 41
src/JT1078.DotNetty.TestHosting/JT1078WSFlv/index.html 查看文件

@@ -1,41 +0,0 @@
<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<script src="flv.min.js"></script>
</head>
<body>
<video muted="muted" webkit-playsinline="true" autoplay="true" id="player"></video>
<script>
if (flvjs.isSupported()) {
var player = document.getElementById('player');
var flvPlayer = flvjs.createPlayer({
type: 'flv',
isLive: true,
url: "ws://127.0.0.1:1818/jt1078live?token=" + Math.floor((Math.random() * 1000000) + 1)
});
flvPlayer.attachMediaElement(player);
flvPlayer.load();
flvPlayer.play();
function componentDidMount() {
this.cleanBuff = setInterval(function () {
let buffered = player.buffered
console.log("start...")
if (buffered.length > 0) {
let end = buffered.end(0)
if (end - player.currentTime > 0.15) {
player.currentTime = end - 0.1;
console.log("exe... start")
}
}
console.log("end...")
}, 3 * 10 * 1000)
};
componentDidMount();
}
</script>
</body>
</html>

+ 0
- 89
src/JT1078.DotNetty.TestHosting/Program.cs 查看文件

@@ -1,89 +0,0 @@
using JT1078.DotNetty.Core;
using JT1078.DotNetty.Tcp;
using JT1078.DotNetty.TestHosting.Handlers;
using JT1078.DotNetty.Udp;
using JT1078.DotNetty.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using NLog.Extensions.Logging;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using JT1078.DotNetty.TestHosting.JT1078WSFlv;

namespace JT1078.DotNetty.TestHosting
{
class Program
{
static Program()
{
Newtonsoft.Json.JsonSerializerSettings setting = new Newtonsoft.Json.JsonSerializerSettings();
JsonConvert.DefaultSettings = new Func<JsonSerializerSettings>(() =>
{
setting.Converters.Add(new StringEnumConverter());
return setting;
});
}
static async Task Main(string[] args)
{
//3031636481E2108801123456781001100000016BB392CA7C02800028002E0000000161E1A2BF0098CFC0EE1E17283407788E39A403FDDBD1D546BFB063013F59AC34C97A021AB96A28A42C08
var serverHostBuilder = new HostBuilder()
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(AppDomain.CurrentDomain.BaseDirectory);
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
})
.ConfigureLogging((context, logging) =>
{
if (Environment.OSVersion.Platform == PlatformID.Unix)
{
NLog.LogManager.LoadConfiguration("Configs/nlog.unix.config");
}
else
{
NLog.LogManager.LoadConfiguration("Configs/nlog.win.config");
}
logging.AddNLog(new NLogProviderOptions { CaptureMessageTemplates = true, CaptureMessageProperties = true });
logging.SetMinimumLevel(LogLevel.Trace);
})
.ConfigureServices((hostContext, services) =>
{
services.AddSingleton<JT1078WSFlvDataService>();
services.AddSingleton<ILoggerFactory, LoggerFactory>();
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>));
services.AddJT1078Core(hostContext.Configuration)
.AddJT1078TcpHost()
.Replace<JT1078TcpMessageHandlers>()
.Builder()
//.AddJT1078UdpHost()
//.Replace<JT1078UdpMessageHandlers>()
// .Builder()
.AddJT1078HttpHost()
//.UseHttpMiddleware<CustomHttpMiddleware>()
//.Builder()
;
//使用ffmpeg工具
//1.success
//services.AddHostedService<FFMPEGRTMPHostedService>();
//2.success
//services.AddHostedService<FFMPEGHTTPFLVHostedService>();
//3.success
//services.AddHostedService<FFMPEGWSFLVPHostedService>();
//4.success
//http://127.0.0.1:5001/HLS/hls.html
//services.AddHostedService<FFMPEGHLSHostedService>();

services.AddHostedService<JT1078WSFlvHostedService>();
});
await serverHostBuilder.RunConsoleAsync();
}
}
}

+ 0
- 59
src/JT1078.DotNetty.TestHosting/RTMP/FFMPEGRTMPHostedService.cs 查看文件

@@ -1,59 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Codecs.Http.WebSockets;
using JT1078.DotNetty.Core.Session;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using JT1078.Protocol;
using System.Collections.Concurrent;
using JT1078.Protocol.Enums;
using System.Diagnostics;

namespace JT1078.DotNetty.TestHosting
{
/// <summary>
/// 1.部署 RTMP 服务器 https://github.com/a1q123456/Harmonic
/// 2.使用ffplay播放器查看 ./ffplay rtmp://127.0.0.1/living/streamName
/// ref:
/// https://stackoverflow.com/questions/32157774/ffmpeg-output-pipeing-to-named-windows-pipe
/// https://mathewsachin.github.io/blog/2017/07/28/ffmpeg-pipe-csharp.html
/// https://csharp.hotexamples.com/examples/-/NamedPipeServerStream/-/php-namedpipeserverstream-class-examples.html
///
/// ffmpeg pipe作为客户端
/// NamedPipeServerStream作为服务端
/// </summary>
class FFMPEGRTMPHostedService : IHostedService
{
private readonly Process process;
public FFMPEGRTMPHostedService()
{
process = new Process
{
StartInfo =
{
FileName = @"C:\ffmpeg\bin\ffmpeg.exe",
Arguments = $@"-f dshow -i video={HardwareCamera.CameraName} -c copy -f flv -vcodec h264 {HardwareCamera.RTMPURL}",
UseShellExecute = false,
CreateNoWindow = true
}
};
}

public Task StartAsync(CancellationToken cancellationToken)
{
process.Start();
return Task.CompletedTask;
}

public Task StopAsync(CancellationToken cancellationToken)
{
process.Kill();
return Task.CompletedTask;
}
}
}

+ 0
- 129
src/JT1078.DotNetty.TestHosting/WSFLV/FFMPEGWSFLVHostedService.cs 查看文件

@@ -1,129 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Codecs.Http.WebSockets;
using JT1078.DotNetty.Core.Session;
using JT1078.DotNetty.Core.Extensions;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using JT1078.Protocol;
using System.Collections.Concurrent;
using JT1078.Protocol.Enums;
using System.Diagnostics;
using System.IO.Pipes;
using Newtonsoft.Json;

namespace JT1078.DotNetty.TestHosting
{
/// <summary>
///
/// </summary>
class FFMPEGWSFLVHostedService : IHostedService,IDisposable
{
private readonly Process process;
private readonly NamedPipeServerStream pipeServerOut;
private const string PipeNameOut = "demo2serverout";
private readonly JT1078HttpSessionManager jT1078HttpSessionManager;
/// <summary>
/// 需要缓存flv的第一包数据,当新用户进来先推送第一包的数据
/// </summary>
private byte[] flvFirstPackage;
private ConcurrentDictionary<string,byte> exists = new ConcurrentDictionary<string, byte>();
public FFMPEGWSFLVHostedService(
JT1078HttpSessionManager jT1078HttpSessionManager)
{
pipeServerOut = new NamedPipeServerStream(PipeNameOut, PipeDirection.In, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous,102400,102400);
process = new Process
{
StartInfo =
{
FileName = @"C:\ffmpeg\bin\ffmpeg.exe",
Arguments = $@"-f dshow -i video={HardwareCamera.CameraName} -c copy -f flv -vcodec h264 -y \\.\pipe\{PipeNameOut}",
UseShellExecute = false,
CreateNoWindow = true,
}
};
this.jT1078HttpSessionManager = jT1078HttpSessionManager;
}

public void Dispose()
{
pipeServerOut.Dispose();
}

public Task StartAsync(CancellationToken cancellationToken)
{
process.Start();
Task.Run(() =>
{
while (true)
{
try
{
Console.WriteLine("IsConnected>>>" + pipeServerOut.IsConnected);
if (pipeServerOut.IsConnected)
{
if (pipeServerOut.CanRead)
{
Span<byte> v1 = new byte[2048];
var length = pipeServerOut.Read(v1);
var realValue = v1.Slice(0, length).ToArray();
if (realValue.Length <= 0) continue;
if (flvFirstPackage == null)
{
flvFirstPackage = realValue;
}
if (jT1078HttpSessionManager.GetAll().Count() > 0)
{
foreach (var session in jT1078HttpSessionManager.GetAll())
{
if (!exists.ContainsKey(session.Channel.Id.AsShortText()))
{
session.SendBinaryWebSocketAsync(flvFirstPackage);
exists.TryAdd(session.Channel.Id.AsShortText(), 0);
}
session.SendBinaryWebSocketAsync(realValue);
}
}
}
}
else
{
if (!pipeServerOut.IsConnected)
{
Console.WriteLine("WaitForConnection Star...");
pipeServerOut.WaitForConnectionAsync().Wait(300);
Console.WriteLine("WaitForConnection End...");
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
});
return Task.CompletedTask;
}

public Task StopAsync(CancellationToken cancellationToken)
{
try
{
process.Kill();
pipeServerOut.Flush();
pipeServerOut.Close();
}
catch
{

}
return Task.CompletedTask;
}
}
}

+ 0
- 7
src/JT1078.DotNetty.TestHosting/WSFLV/flv.min.js
文件差異過大導致無法顯示
查看文件


+ 0
- 26
src/JT1078.DotNetty.TestHosting/WSFLV/index.html 查看文件

@@ -1,26 +0,0 @@
<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<script src="flv.min.js"></script>
</head>
<body>
<video muted="muted" webkit-playsinline="true" autoplay="true" id="player"></video>
<script>
if (flvjs.isSupported()) {
var player = document.getElementById('player');
var flvPlayer = flvjs.createPlayer({
type: 'flv',
isLive: true,
url: "ws://127.0.0.1:1818/jt1078live?token=" + Math.floor((Math.random() * 1000000) + 1)
});
flvPlayer.attachMediaElement(player);
flvPlayer.load();
flvPlayer.play();
}
</script>
</body>
</html>

+ 0
- 23
src/JT1078.DotNetty.TestHosting/appsettings.json 查看文件

@@ -1,23 +0,0 @@
{
"Logging": {
"IncludeScopes": false,
"Debug": {
"LogLevel": {
"Default": "Trace"
}
},
"Console": {
"LogLevel": {
"Default": "Trace"
}
}
},
"JT1078Configuration": {
"TcpPort": 1808,
"UdpPort": 1808,
"HttpPort": 1818,
"RemoteServerOptions": {

}
}
}

+ 0
- 18
src/JT1078.DotNetty.Udp/Handlers/JT1078UdpMessageProcessorEmptyImpl.cs 查看文件

@@ -1,18 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using JT1078.DotNetty.Core.Interfaces;
using JT1078.DotNetty.Core.Metadata;
using JT1078.Protocol;

namespace JT1078.DotNetty.Udp.Handlers
{
class JT1078UdpMessageProcessorEmptyImpl : IJT1078UdpMessageHandlers
{
public Task<JT1078Response> Processor(JT1078Request request)
{
return Task.FromResult<JT1078Response>(default);
}
}
}

+ 0
- 70
src/JT1078.DotNetty.Udp/Handlers/JT1078UdpServerHandler.cs 查看文件

@@ -1,70 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Transport.Channels;
using System;
using Microsoft.Extensions.Logging;
using JT1078.DotNetty.Core.Metadata;
using JT1078.DotNetty.Core.Session;
using JT1078.DotNetty.Core.Services;
using JT1078.DotNetty.Core.Enums;
using JT1078.Protocol;
using JT1078.DotNetty.Core.Interfaces;

namespace JT1078.DotNetty.Udp.Handlers
{
/// <summary>
/// JT1078 Udp服务端处理程序
/// </summary>
internal class JT1078UdpServerHandler : SimpleChannelInboundHandler<JT1078UdpPackage>
{
private readonly ILogger<JT1078UdpServerHandler> logger;

private readonly JT1078UdpSessionManager SessionManager;

private readonly JT1078AtomicCounterService AtomicCounterService;

private readonly IJT1078UdpMessageHandlers handlers;
public JT1078UdpServerHandler(
ILoggerFactory loggerFactory,
JT1078AtomicCounterServiceFactory atomicCounterServiceFactory,
IJT1078UdpMessageHandlers handlers,
JT1078UdpSessionManager sessionManager)
{
this.AtomicCounterService = atomicCounterServiceFactory.Create(JT1078TransportProtocolType.udp);
this.SessionManager = sessionManager;
logger = loggerFactory.CreateLogger<JT1078UdpServerHandler>();
this.handlers = handlers;
}

protected override void ChannelRead0(IChannelHandlerContext ctx, JT1078UdpPackage msg)
{
try
{
if (logger.IsEnabled(LogLevel.Trace))
{
logger.LogTrace("accept package success count<<<" + AtomicCounterService.MsgSuccessCount.ToString());
logger.LogTrace("accept msg <<< " + ByteBufferUtil.HexDump(msg.Buffer));
}
JT1078Package package = JT1078Serializer.Deserialize(msg.Buffer);
AtomicCounterService.MsgSuccessIncrement();
SessionManager.TryAdd(ctx.Channel, msg.Sender, package.SIM);
handlers.Processor(new JT1078Request(package, msg.Buffer));
if (logger.IsEnabled(LogLevel.Debug))
{
logger.LogDebug("accept package success count<<<" + AtomicCounterService.MsgSuccessCount.ToString());
}
}
catch (Exception ex)
{
AtomicCounterService.MsgFailIncrement();
if (logger.IsEnabled(LogLevel.Error))
{
logger.LogError("accept package fail count<<<" + AtomicCounterService.MsgFailCount.ToString());
logger.LogError(ex, "accept msg<<<" + ByteBufferUtil.HexDump(msg.Buffer));
}
}
}

public override void ChannelReadComplete(IChannelHandlerContext context) => context.Flush();

}
}

+ 0
- 29
src/JT1078.DotNetty.Udp/JT1078.DotNetty.Udp.csproj 查看文件

@@ -1,29 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\Version.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>7.3</LangVersion>
<Copyright>Copyright 2019.</Copyright>
<Authors>SmallChi(Koike)</Authors>
<PackageId>JT1078.DotNetty.Udp</PackageId>
<Product>JT1078.DotNetty.Udp</Product>
<Description>基于DotNetty实现的JT1078DotNetty的Udp服务</Description>
<PackageReleaseNotes>基于DotNetty实现的JT1078DotNetty的Udp服务</PackageReleaseNotes>
<RepositoryUrl>https://github.com/SmallChi/JT1078DotNetty</RepositoryUrl>
<PackageProjectUrl>https://github.com/SmallChi/JT1078DotNetty</PackageProjectUrl>
<licenseUrl>https://github.com/SmallChi/JT1078DotNetty/blob/master/LICENSE</licenseUrl>
<license>https://github.com/SmallChi/JT1078DotNetty/blob/master/LICENSE</license>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<SignAssembly>false</SignAssembly>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<Version>$(JT1078DotNettyPackageVersion)</Version>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\JT1078.DotNetty.Core\JT1078.DotNetty.Core.csproj" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\LICENSE" Pack="true" PackagePath="" />
</ItemGroup>
</Project>

+ 0
- 30
src/JT1078.DotNetty.Udp/JT1078UdpBuilderDefault.cs 查看文件

@@ -1,30 +0,0 @@
using JT1078.DotNetty.Core.Interfaces;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using System;
using System.Collections.Generic;
using System.Text;

namespace JT1078.DotNetty.Udp
{
class JT1078UdpBuilderDefault : IJT1078UdpBuilder
{
public IJT1078Builder Instance { get; }

public JT1078UdpBuilderDefault(IJT1078Builder builder)
{
Instance = builder;
}

public IJT1078Builder Builder()
{
return Instance;
}

public IJT1078UdpBuilder Replace<T>() where T : IJT1078UdpMessageHandlers
{
Instance.Services.Replace(new ServiceDescriptor(typeof(IJT1078UdpMessageHandlers), typeof(T), ServiceLifetime.Singleton));
return this;
}
}
}

+ 0
- 26
src/JT1078.DotNetty.Udp/JT1078UdpDotnettyExtensions.cs 查看文件

@@ -1,26 +0,0 @@
using JT1078.DotNetty.Core.Codecs;
using JT1078.DotNetty.Core.Interfaces;
using JT1078.DotNetty.Core.Session;
using JT1078.DotNetty.Udp;
using JT1078.DotNetty.Udp.Handlers;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("JT1078.DotNetty.Udp.Test")]

namespace JT1078.DotNetty.Udp
{
public static class JT1078UdpDotnettyExtensions
{
public static IJT1078UdpBuilder AddJT1078UdpHost(this IJT1078Builder builder)
{
builder.Services.TryAddSingleton<JT1078UdpSessionManager>();
builder.Services.TryAddSingleton<IJT1078UdpMessageHandlers, JT1078UdpMessageProcessorEmptyImpl>();
builder.Services.TryAddScoped<JT1078UdpDecoder>();
builder.Services.TryAddScoped<JT1078UdpServerHandler>();
builder.Services.AddHostedService<JT1078UdpServerHost>();
return new JT1078UdpBuilderDefault(builder);
}
}
}

+ 0
- 76
src/JT1078.DotNetty.Udp/JT1078UdpServerHost.cs 查看文件

@@ -1,76 +0,0 @@
using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Channels.Sockets;
using JT1078.DotNetty.Core.Codecs;
using JT1078.DotNetty.Core.Configurations;
using JT1078.DotNetty.Udp.Handlers;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Net;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;

namespace JT1078.DotNetty.Udp
{
/// <summary>
/// JT1078 Udp网关服务
/// </summary>
internal class JT1078UdpServerHost : IHostedService
{
private readonly IServiceProvider serviceProvider;
private readonly JT1078Configuration configuration;
private readonly ILogger<JT1078UdpServerHost> logger;
private MultithreadEventLoopGroup group;
private IChannel bootstrapChannel;

public JT1078UdpServerHost(
IServiceProvider provider,
ILoggerFactory loggerFactory,
IOptions<JT1078Configuration> jT808ConfigurationAccessor)
{
serviceProvider = provider;
configuration = jT808ConfigurationAccessor.Value;
logger=loggerFactory.CreateLogger<JT1078UdpServerHost>();
}

public Task StartAsync(CancellationToken cancellationToken)
{
group = new MultithreadEventLoopGroup();
Bootstrap bootstrap = new Bootstrap();
bootstrap.Group(group);
bootstrap.Channel<SocketDatagramChannel>();
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)
|| RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
bootstrap
.Option(ChannelOption.SoReuseport, true);
}
bootstrap
.Option(ChannelOption.SoBroadcast, true)
.Handler(new ActionChannelInitializer<IChannel>(channel =>
{
IChannelPipeline pipeline = channel.Pipeline;
using (var scope = serviceProvider.CreateScope())
{
pipeline.AddLast("JT1078UdpDecoder", scope.ServiceProvider.GetRequiredService<JT1078UdpDecoder>());
pipeline.AddLast("JT1078UdpService", scope.ServiceProvider.GetRequiredService<JT1078UdpServerHandler>());
}
}));
logger.LogInformation($"JT1078 Udp Server start at {IPAddress.Any}:{configuration.UdpPort}.");
return bootstrap.BindAsync(configuration.UdpPort)
.ContinueWith(i => bootstrapChannel = i.Result);
}

public async Task StopAsync(CancellationToken cancellationToken)
{
await bootstrapChannel.CloseAsync();
var quietPeriod = configuration.QuietPeriodTimeSpan;
var shutdownTimeout = configuration.ShutdownTimeoutTimeSpan;
await group.ShutdownGracefullyAsync(quietPeriod, shutdownTimeout);
}
}
}

+ 0
- 13
src/JT1078.DotNetty.Udp/Properties/PublishProfiles/FolderProfile.pubxml 查看文件

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<PublishProtocol>FileSystem</PublishProtocol>
<Configuration>Release</Configuration>
<Platform>Any CPU</Platform>
<TargetFramework>netstandard2.0</TargetFramework>
<PublishDir>..\..\publish\</PublishDir>
</PropertyGroup>
</Project>

+ 0
- 54
src/JT1078DotNetty.sln 查看文件

@@ -1,54 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29009.5
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT1078.DotNetty.Core", "JT1078.DotNetty.Core\JT1078.DotNetty.Core.csproj", "{71D35280-24BE-4BF1-AFA4-07DFBC696FA5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT1078.DotNetty.Tcp", "JT1078.DotNetty.Tcp\JT1078.DotNetty.Tcp.csproj", "{C4B4BBEB-4597-469F-B99A-A9F380DDB8FB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT1078.DotNetty.TestHosting", "JT1078.DotNetty.TestHosting\JT1078.DotNetty.TestHosting.csproj", "{DCCA6BB7-C2B5-490A-B43F-C28ABEA922D7}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT1078.DotNetty.Udp", "JT1078.DotNetty.Udp\JT1078.DotNetty.Udp.csproj", "{6405D7FA-3B6E-4545-827E-BA13EB5BB268}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{1C26DF6A-2978-46B7-B921-BB7776CC6EE8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT1078.DotNetty.Http", "JT1078.DotNetty.Http\JT1078.DotNetty.Http.csproj", "{C6B9DB90-8A6C-4285-A03F-C03E2E8DF7CC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{71D35280-24BE-4BF1-AFA4-07DFBC696FA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{71D35280-24BE-4BF1-AFA4-07DFBC696FA5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{71D35280-24BE-4BF1-AFA4-07DFBC696FA5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{71D35280-24BE-4BF1-AFA4-07DFBC696FA5}.Release|Any CPU.Build.0 = Release|Any CPU
{C4B4BBEB-4597-469F-B99A-A9F380DDB8FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C4B4BBEB-4597-469F-B99A-A9F380DDB8FB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C4B4BBEB-4597-469F-B99A-A9F380DDB8FB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C4B4BBEB-4597-469F-B99A-A9F380DDB8FB}.Release|Any CPU.Build.0 = Release|Any CPU
{DCCA6BB7-C2B5-490A-B43F-C28ABEA922D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DCCA6BB7-C2B5-490A-B43F-C28ABEA922D7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DCCA6BB7-C2B5-490A-B43F-C28ABEA922D7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DCCA6BB7-C2B5-490A-B43F-C28ABEA922D7}.Release|Any CPU.Build.0 = Release|Any CPU
{6405D7FA-3B6E-4545-827E-BA13EB5BB268}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6405D7FA-3B6E-4545-827E-BA13EB5BB268}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6405D7FA-3B6E-4545-827E-BA13EB5BB268}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6405D7FA-3B6E-4545-827E-BA13EB5BB268}.Release|Any CPU.Build.0 = Release|Any CPU
{C6B9DB90-8A6C-4285-A03F-C03E2E8DF7CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C6B9DB90-8A6C-4285-A03F-C03E2E8DF7CC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C6B9DB90-8A6C-4285-A03F-C03E2E8DF7CC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C6B9DB90-8A6C-4285-A03F-C03E2E8DF7CC}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{DCCA6BB7-C2B5-490A-B43F-C28ABEA922D7} = {1C26DF6A-2978-46B7-B921-BB7776CC6EE8}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {07ED058A-2CEB-43FD-8478-7EEC7E56F868}
EndGlobalSection
EndGlobal

+ 0
- 5
src/Version.props 查看文件

@@ -1,5 +0,0 @@
<Project>
<PropertyGroup>
<JT1078DotNettyPackageVersion>1.0.0-preview3</JT1078DotNettyPackageVersion>
</PropertyGroup>
</Project>

Loading…
取消
儲存