From 3e8161d2644a60287b68979c805ea3f5276608bf Mon Sep 17 00:00:00 2001 From: "SmallChi(Koike)" <564952747@qq.com> Date: Mon, 1 Mar 2021 18:06:56 +0800 Subject: [PATCH] =?UTF-8?q?1.=E6=B7=BB=E5=8A=A0SIM=E5=8D=A1=E9=BB=91?= =?UTF-8?q?=E5=90=8D=E5=8D=95=E7=AE=A1=E7=90=86=E5=8F=8A=E5=AF=B9=E5=BA=94?= =?UTF-8?q?=E7=9A=84WebApi=202.=E4=BF=AE=E5=A4=8Dtcp=E4=B8=8B=E5=8F=91?= =?UTF-8?q?=E6=9C=AA=E5=88=A4=E6=96=AD=E8=BF=9E=E6=8E=A5=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E6=98=AF=E5=90=A6=E5=BC=82=E5=B8=B8=E5=AF=BC=E8=87=B4=E7=A8=8B?= =?UTF-8?q?=E5=BA=8F=E5=BC=82=E5=B8=B8=203.=E5=8D=87=E7=BA=A7kafka?= =?UTF-8?q?=E7=89=88=E6=9C=AC=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Configurations/JT808Configuration.cs | 22 ++- .../Extensions/JT808SessionExtensions.cs | 22 ++- .../IJT808SessionProducer.cs | 5 + .../JT808.Gateway.Abstractions.xml | 71 ++++++++ .../JT808GatewayConstants.cs | 12 ++ .../JT808.Gateway.CleintBenchmark.csproj | 2 +- .../JT808.Gateway.ServerBenchmark.csproj | 2 +- .../JT808.Gateway.Kafka.csproj | 2 +- .../JT808.Gateway.NormalHosting.csproj | 4 +- .../JT808.Gateway.NormalHosting/Program.cs | 4 +- .../JT808.Gateway.QueueHosting.csproj | 4 +- .../Services/JT808BlacklistManagerTest.cs | 36 ++++ .../JT808.Gateway.WebApiClientTool.xml | 20 +++ .../JT808HttpClient.cs | 46 +++++ .../JT808MsgIdDefaultWebApiHandler.cs | 118 ++++++++++-- src/JT808.Gateway/JT808.Gateway.xml | 168 +++++++++++++++++- src/JT808.Gateway/JT808GatewayExtensions.cs | 4 + src/JT808.Gateway/JT808TcpServer.cs | 85 ++++++--- .../Services/JT808BlacklistManager.cs | 101 +++++++++++ .../Session/JT808SessionManager.cs | 72 ++++++-- 20 files changed, 727 insertions(+), 73 deletions(-) create mode 100644 src/JT808.Gateway.Tests/JT808.Gateway.Test/Services/JT808BlacklistManagerTest.cs create mode 100644 src/JT808.Gateway/Services/JT808BlacklistManager.cs diff --git a/src/JT808.Gateway.Abstractions/Configurations/JT808Configuration.cs b/src/JT808.Gateway.Abstractions/Configurations/JT808Configuration.cs index 844347a..c8d4b9b 100644 --- a/src/JT808.Gateway.Abstractions/Configurations/JT808Configuration.cs +++ b/src/JT808.Gateway.Abstractions/Configurations/JT808Configuration.cs @@ -4,17 +4,35 @@ using System.Text; namespace JT808.Gateway.Abstractions.Configurations { + /// + /// JT808网关配置 + /// public class JT808Configuration { + /// + /// tcp端口 + /// public int TcpPort { get; set; } = 808; + /// + /// udp端口 + /// public int UdpPort { get; set; } = 808; + /// + /// http webapi端口 + /// public int WebApiPort { get; set; } = 828; /// /// WebApi 默认token 123456 /// public string WebApiToken { get; set; } = "123456"; - public int SoBacklog { get; set; } = 8192; - public int MiniNumBufferSize { get; set; } = 8096; + /// + /// tcp连接能够成功连接上的数量 + /// + public int SoBacklog { get; set; } = 10000; + /// + /// 默认4k + /// + public int MiniNumBufferSize { get; set; } = 4096; /// /// Tcp读超时 /// 默认10分钟检查一次 diff --git a/src/JT808.Gateway.Abstractions/Extensions/JT808SessionExtensions.cs b/src/JT808.Gateway.Abstractions/Extensions/JT808SessionExtensions.cs index 108d50a..f3e5ec4 100644 --- a/src/JT808.Gateway.Abstractions/Extensions/JT808SessionExtensions.cs +++ b/src/JT808.Gateway.Abstractions/Extensions/JT808SessionExtensions.cs @@ -7,31 +7,45 @@ using System.Threading.Tasks; namespace JT808.Gateway.Abstractions { + /// + /// JT808会话扩展 + /// public static class JT808SessionExtensions { + /// + /// 下发消息 + /// + /// + /// public static async void SendAsync(this IJT808Session session,byte[] data) { if (data == null) return; if (session.TransportProtocolType == JT808TransportProtocolType.tcp) { - await session.Client.SendAsync(data, SocketFlags.None); + if (session.Client.Connected) + await session.Client.SendAsync(data, SocketFlags.None); } else { await session.Client.SendToAsync(data, SocketFlags.None, session.RemoteEndPoint); } } - + /// + /// 下发消息 + /// + /// + /// public static void Send(this IJT808Session session, byte[] data) { if (data == null) return; if (session.TransportProtocolType == JT808TransportProtocolType.tcp) { - session.Client.Send(data, SocketFlags.None); + if (session.Client.Connected) + session.Client.Send(data, SocketFlags.None); } else { - session.Client.SendTo(data, SocketFlags.None, session.RemoteEndPoint); + session.Client.SendTo(data, SocketFlags.None, session.RemoteEndPoint); } } } diff --git a/src/JT808.Gateway.Abstractions/IJT808SessionProducer.cs b/src/JT808.Gateway.Abstractions/IJT808SessionProducer.cs index 32000de..12734f5 100644 --- a/src/JT808.Gateway.Abstractions/IJT808SessionProducer.cs +++ b/src/JT808.Gateway.Abstractions/IJT808SessionProducer.cs @@ -8,6 +8,11 @@ namespace JT808.Gateway.Abstractions /// public interface IJT808SessionProducer : IJT808PubSub, IDisposable { + /// + /// + /// + /// + /// void ProduceAsync(string notice,string terminalNo); } } diff --git a/src/JT808.Gateway.Abstractions/JT808.Gateway.Abstractions.xml b/src/JT808.Gateway.Abstractions/JT808.Gateway.Abstractions.xml index 73ac7dd..6dd7f9e 100644 --- a/src/JT808.Gateway.Abstractions/JT808.Gateway.Abstractions.xml +++ b/src/JT808.Gateway.Abstractions/JT808.Gateway.Abstractions.xml @@ -4,11 +4,41 @@ JT808.Gateway.Abstractions + + + JT808网关配置 + + + + + tcp端口 + + + + + udp端口 + + + + + http webapi端口 + + WebApi 默认token 123456 + + + tcp连接能够成功连接上的数量 + + + + + 默认4k + + Tcp读超时 @@ -85,6 +115,25 @@ 传输协议类型 + + + JT808会话扩展 + + + + + 下发消息 + + + + + + + 下发消息 + + + + @@ -129,6 +178,13 @@ 会话通知(在线/离线) + + + + + + + 基于Tcp的会话服务集合 @@ -164,6 +220,21 @@ 会话服务-通过设备终端号查询对应会话 + + + 黑名单添加 + + + + + 黑名单删除 + + + + + 黑名单查询 + + 通用消息处理程序 diff --git a/src/JT808.Gateway.Abstractions/JT808GatewayConstants.cs b/src/JT808.Gateway.Abstractions/JT808GatewayConstants.cs index cefd329..9d507cc 100644 --- a/src/JT808.Gateway.Abstractions/JT808GatewayConstants.cs +++ b/src/JT808.Gateway.Abstractions/JT808GatewayConstants.cs @@ -45,6 +45,18 @@ /// 会话服务-通过设备终端号查询对应会话 /// public static string QueryUdpSessionByTerminalPhoneNo = $"{RouteTablePrefix}/{UdpPrefix}/{SessionPrefix}/QueryUdpSessionByTerminalPhoneNo"; + /// + /// 黑名单添加 + /// + public static string BlacklistAdd = $"{RouteTablePrefix}/Blacklist/Add"; + /// + /// 黑名单删除 + /// + public static string BlacklistRemove = $"{RouteTablePrefix}/Blacklist/Remove"; + /// + /// 黑名单查询 + /// + public static string BlacklistGet = $"{RouteTablePrefix}/Blacklist/Get"; } } } diff --git a/src/JT808.Gateway.Benchmark/JT808.Gateway.CleintBenchmark/JT808.Gateway.CleintBenchmark.csproj b/src/JT808.Gateway.Benchmark/JT808.Gateway.CleintBenchmark/JT808.Gateway.CleintBenchmark.csproj index b385da7..cf86f35 100644 --- a/src/JT808.Gateway.Benchmark/JT808.Gateway.CleintBenchmark/JT808.Gateway.CleintBenchmark.csproj +++ b/src/JT808.Gateway.Benchmark/JT808.Gateway.CleintBenchmark/JT808.Gateway.CleintBenchmark.csproj @@ -20,7 +20,7 @@ - + diff --git a/src/JT808.Gateway.Benchmark/JT808.Gateway.ServerBenchmark/JT808.Gateway.ServerBenchmark.csproj b/src/JT808.Gateway.Benchmark/JT808.Gateway.ServerBenchmark/JT808.Gateway.ServerBenchmark.csproj index 8800082..cd1b6c0 100644 --- a/src/JT808.Gateway.Benchmark/JT808.Gateway.ServerBenchmark/JT808.Gateway.ServerBenchmark.csproj +++ b/src/JT808.Gateway.Benchmark/JT808.Gateway.ServerBenchmark/JT808.Gateway.ServerBenchmark.csproj @@ -9,7 +9,7 @@ - + diff --git a/src/JT808.Gateway.Kafka/JT808.Gateway.Kafka.csproj b/src/JT808.Gateway.Kafka/JT808.Gateway.Kafka.csproj index 5d0c820..d40314f 100644 --- a/src/JT808.Gateway.Kafka/JT808.Gateway.Kafka.csproj +++ b/src/JT808.Gateway.Kafka/JT808.Gateway.Kafka.csproj @@ -21,7 +21,7 @@ $(JT808GatewayPackageVersion) - + diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.NormalHosting/JT808.Gateway.NormalHosting.csproj b/src/JT808.Gateway.Tests/JT808.Gateway.NormalHosting/JT808.Gateway.NormalHosting.csproj index 002aee4..b86821c 100644 --- a/src/JT808.Gateway.Tests/JT808.Gateway.NormalHosting/JT808.Gateway.NormalHosting.csproj +++ b/src/JT808.Gateway.Tests/JT808.Gateway.NormalHosting/JT808.Gateway.NormalHosting.csproj @@ -7,10 +7,10 @@ - + - + diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.NormalHosting/Program.cs b/src/JT808.Gateway.Tests/JT808.Gateway.NormalHosting/Program.cs index f8921fb..7991612 100644 --- a/src/JT808.Gateway.Tests/JT808.Gateway.NormalHosting/Program.cs +++ b/src/JT808.Gateway.Tests/JT808.Gateway.NormalHosting/Program.cs @@ -65,9 +65,9 @@ namespace JT808.Gateway.NormalHosting //方式2:客户端webapi调用 //services.AddJT808WebApiClientTool(hostContext.Configuration); //httpclient客户端调用 - services.AddHostedService(); + //services.AddHostedService(); //客户端测试 依赖AddClient()服务 - services.AddHostedService(); + //services.AddHostedService(); }); await serverHostBuilder.RunConsoleAsync(); diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.QueueHosting/JT808.Gateway.QueueHosting.csproj b/src/JT808.Gateway.Tests/JT808.Gateway.QueueHosting/JT808.Gateway.QueueHosting.csproj index be96215..c6bc73c 100644 --- a/src/JT808.Gateway.Tests/JT808.Gateway.QueueHosting/JT808.Gateway.QueueHosting.csproj +++ b/src/JT808.Gateway.Tests/JT808.Gateway.QueueHosting/JT808.Gateway.QueueHosting.csproj @@ -10,10 +10,10 @@ - + - + diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.Test/Services/JT808BlacklistManagerTest.cs b/src/JT808.Gateway.Tests/JT808.Gateway.Test/Services/JT808BlacklistManagerTest.cs new file mode 100644 index 0000000..8cfd98c --- /dev/null +++ b/src/JT808.Gateway.Tests/JT808.Gateway.Test/Services/JT808BlacklistManagerTest.cs @@ -0,0 +1,36 @@ +using JT808.Gateway.Services; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace JT808.Gateway.Test.Services +{ + public class JT808BlacklistManagerTest + { + [Fact] + public void Test1() + { + JT808BlacklistManager jT808BlacklistManager = new JT808BlacklistManager(); + jT808BlacklistManager.Add("1"); + Assert.True(jT808BlacklistManager.Contains("1")); + jT808BlacklistManager.Add("2"); + Assert.True(jT808BlacklistManager.Contains("2")); + jT808BlacklistManager.Remove("1"); + Assert.False(jT808BlacklistManager.Contains("1")); + } + + [Fact] + public void Test2() + { + JT808BlacklistManager jT808BlacklistManager = new JT808BlacklistManager(); + jT808BlacklistManager.Add("1"); + jT808BlacklistManager.Add("2"); + Assert.True(jT808BlacklistManager.Contains("1")); + Assert.True(jT808BlacklistManager.Contains("2")); + } + } +} diff --git a/src/JT808.Gateway.WebApiClientTool/JT808.Gateway.WebApiClientTool.xml b/src/JT808.Gateway.WebApiClientTool/JT808.Gateway.WebApiClientTool.xml index 5897f16..7c3de3f 100644 --- a/src/JT808.Gateway.WebApiClientTool/JT808.Gateway.WebApiClientTool.xml +++ b/src/JT808.Gateway.WebApiClientTool/JT808.Gateway.WebApiClientTool.xml @@ -67,6 +67,26 @@ + + + SIM卡黑名单服务-将对应SIM号加入黑名单 + + + + + + + SIM卡黑名单服务-将对应SIM号移除黑名单 + + + + + + + SIM卡黑名单服务-获取所有sim的黑名单列表 + + + diff --git a/src/JT808.Gateway.WebApiClientTool/JT808HttpClient.cs b/src/JT808.Gateway.WebApiClientTool/JT808HttpClient.cs index 2b6e609..02873ac 100644 --- a/src/JT808.Gateway.WebApiClientTool/JT808HttpClient.cs +++ b/src/JT808.Gateway.WebApiClientTool/JT808HttpClient.cs @@ -136,5 +136,51 @@ namespace JT808.Gateway.WebApiClientTool var value = await JsonSerializer.DeserializeAsync>(data); return value; } + + /// + /// SIM卡黑名单服务-将对应SIM号加入黑名单 + /// + /// + /// + public async ValueTask> BlacklistAdd(string terminalPhoneNo) + { + var request = new HttpRequestMessage(HttpMethod.Post, JT808GatewayConstants.JT808WebApiRouteTable.BlacklistAdd); + request.Content = new StringContent(terminalPhoneNo); + var response = await HttpClient.SendAsync(request); + response.EnsureSuccessStatusCode(); + var data = await response.Content.ReadAsStreamAsync(); + var value = await JsonSerializer.DeserializeAsync>(data); + return value; + } + + /// + /// SIM卡黑名单服务-将对应SIM号移除黑名单 + /// + /// + /// + public async ValueTask> BlacklistRemove(string terminalPhoneNo) + { + var request = new HttpRequestMessage(HttpMethod.Post, JT808GatewayConstants.JT808WebApiRouteTable.BlacklistRemove); + request.Content = new StringContent(terminalPhoneNo); + var response = await HttpClient.SendAsync(request); + response.EnsureSuccessStatusCode(); + var data = await response.Content.ReadAsStreamAsync(); + var value = await JsonSerializer.DeserializeAsync>(data); + return value; + } + + /// + /// SIM卡黑名单服务-获取所有sim的黑名单列表 + /// + /// + public async ValueTask>> GetBlacklistAll() + { + var request = new HttpRequestMessage(HttpMethod.Post, JT808GatewayConstants.JT808WebApiRouteTable.BlacklistGet); + var response = await HttpClient.SendAsync(request); + response.EnsureSuccessStatusCode(); + var data = await response.Content.ReadAsStreamAsync(); + var value = await JsonSerializer.DeserializeAsync>>(data); + return value; + } } } diff --git a/src/JT808.Gateway/Handlers/JT808MsgIdDefaultWebApiHandler.cs b/src/JT808.Gateway/Handlers/JT808MsgIdDefaultWebApiHandler.cs index 779824e..969bf7a 100644 --- a/src/JT808.Gateway/Handlers/JT808MsgIdDefaultWebApiHandler.cs +++ b/src/JT808.Gateway/Handlers/JT808MsgIdDefaultWebApiHandler.cs @@ -1,5 +1,6 @@ using JT808.Gateway.Abstractions; using JT808.Gateway.Abstractions.Dtos; +using JT808.Gateway.Services; using JT808.Gateway.Session; using JT808.Protocol.Extensions; using System; @@ -15,10 +16,19 @@ namespace JT808.Gateway.Handlers /// public class JT808MsgIdDefaultWebApiHandler : JT808MsgIdHttpHandlerBase { - private JT808SessionManager JT808SessionManager; - public JT808MsgIdDefaultWebApiHandler(JT808SessionManager jT808SessionManager) + private JT808SessionManager SessionManager; + private JT808BlacklistManager BlacklistManager; + /// + /// + /// + /// + /// + public JT808MsgIdDefaultWebApiHandler( + JT808SessionManager jT808SessionManager, + JT808BlacklistManager jT808BlacklistManager) { - this.JT808SessionManager = jT808SessionManager; + this.SessionManager = jT808SessionManager; + this.BlacklistManager = jT808BlacklistManager; InitTcpRoute(); InitUdpRoute(); InitCommontRoute(); @@ -34,7 +44,7 @@ namespace JT808.Gateway.Handlers JT808ResultDto> resultDto = new JT808ResultDto>(); try { - resultDto.Data = JT808SessionManager.GetTcpAll().Select(s => new JT808TcpSessionInfoDto + resultDto.Data = SessionManager.GetTcpAll().Select(s => new JT808TcpSessionInfoDto { LastActiveTime = s.ActiveTime, StartTime = s.StartTime, @@ -66,7 +76,7 @@ namespace JT808.Gateway.Handlers JT808ResultDto resultDto = new JT808ResultDto(); try { - resultDto.Data = JT808SessionManager.GetTcpAll().Where(w => w.TerminalPhoneNo == json).Select(s => new JT808TcpSessionInfoDto + resultDto.Data = SessionManager.GetTcpAll().Where(w => w.TerminalPhoneNo == json).Select(s => new JT808TcpSessionInfoDto { LastActiveTime = s.ActiveTime, StartTime = s.StartTime, @@ -98,7 +108,7 @@ namespace JT808.Gateway.Handlers JT808ResultDto resultDto = new JT808ResultDto(); try { - JT808SessionManager.RemoveByTerminalPhoneNo(json); + SessionManager.RemoveByTerminalPhoneNo(json); resultDto.Code = JT808ResultCode.Ok; resultDto.Data = true; } @@ -127,7 +137,7 @@ namespace JT808.Gateway.Handlers JT808ResultDto> resultDto = new JT808ResultDto>(); try { - resultDto.Data = JT808SessionManager.GetUdpAll().Select(s => new JT808UdpSessionInfoDto + resultDto.Data = SessionManager.GetUdpAll().Select(s => new JT808UdpSessionInfoDto { LastActiveTime = s.ActiveTime, StartTime = s.StartTime, @@ -159,7 +169,7 @@ namespace JT808.Gateway.Handlers JT808ResultDto resultDto = new JT808ResultDto(); try { - resultDto.Data = JT808SessionManager.GetUdpAll().Where(w => w.TerminalPhoneNo == json).Select(s => new JT808UdpSessionInfoDto + resultDto.Data = SessionManager.GetUdpAll().Where(w => w.TerminalPhoneNo == json).Select(s => new JT808UdpSessionInfoDto { LastActiveTime = s.ActiveTime, StartTime = s.StartTime, @@ -191,7 +201,7 @@ namespace JT808.Gateway.Handlers JT808ResultDto resultDto = new JT808ResultDto(); try { - JT808SessionManager.RemoveByTerminalPhoneNo(json); + SessionManager.RemoveByTerminalPhoneNo(json); resultDto.Code = JT808ResultCode.Ok; resultDto.Data = true; } @@ -225,7 +235,7 @@ namespace JT808.Gateway.Handlers try { JT808UnificationSendRequestDto jT808UnificationSendRequestDto = JsonSerializer.Deserialize(json); - resultDto.Data = JT808SessionManager.TrySendByTerminalPhoneNoAsync(jT808UnificationSendRequestDto.TerminalPhoneNo, jT808UnificationSendRequestDto.HexData.ToHexBytes()) + resultDto.Data = SessionManager.TrySendByTerminalPhoneNoAsync(jT808UnificationSendRequestDto.TerminalPhoneNo, jT808UnificationSendRequestDto.HexData.ToHexBytes()) .GetAwaiter() .GetResult(); resultDto.Code = JT808ResultCode.Ok; @@ -239,11 +249,96 @@ namespace JT808.Gateway.Handlers return CreateHttpResponse(resultDto); } + /// + /// 添加sim卡黑名单 + /// + /// + /// + public byte[] BlacklistAdd(string json) + { + if (string.IsNullOrEmpty(json)) + { + return EmptyHttpResponse(); + } + JT808ResultDto resultDto = new JT808ResultDto(); + try + { + BlacklistManager.Add(json); + resultDto.Data = true; + resultDto.Code = JT808ResultCode.Ok; + } + catch (Exception ex) + { + resultDto.Data = false; + resultDto.Code = JT808ResultCode.Error; + resultDto.Message = ex.StackTrace; + } + return CreateHttpResponse(resultDto); + } + + /// + /// 移除sim卡黑名单 + /// + /// + /// + public byte[] BlacklistRemove(string json) + { + if (string.IsNullOrEmpty(json)) + { + return EmptyHttpResponse(); + } + JT808ResultDto resultDto = new JT808ResultDto(); + try + { + BlacklistManager.Remove(json); + resultDto.Data = true; + resultDto.Code = JT808ResultCode.Ok; + } + catch (Exception ex) + { + resultDto.Data = false; + resultDto.Code = JT808ResultCode.Error; + resultDto.Message = ex.StackTrace; + } + return CreateHttpResponse(resultDto); + } + + /// + /// 移除sim卡黑名单 + /// + /// + /// + public byte[] QueryBlacklist(string json) + { + JT808ResultDto> resultDto = new JT808ResultDto>(); + try + { + resultDto.Data = BlacklistManager.GetAll(); + resultDto.Code = JT808ResultCode.Ok; + } + catch (Exception ex) + { + resultDto.Data = null; + resultDto.Code = JT808ResultCode.Error; + resultDto.Message = ex.StackTrace; + } + return CreateHttpResponse(resultDto); + } + + /// + /// + /// protected virtual void InitCommontRoute() { CreateRoute(JT808GatewayConstants.JT808WebApiRouteTable.UnificationSend, UnificationSend); + CreateRoute(JT808GatewayConstants.JT808WebApiRouteTable.BlacklistAdd, BlacklistAdd); + CreateRoute(JT808GatewayConstants.JT808WebApiRouteTable.BlacklistRemove, BlacklistRemove); + CreateRoute(JT808GatewayConstants.JT808WebApiRouteTable.BlacklistGet, QueryBlacklist); } + /// + /// + /// protected virtual void InitTcpRoute() { CreateRoute(JT808GatewayConstants.JT808WebApiRouteTable.SessionTcpGetAll, GetTcpSessionAll); @@ -251,6 +346,9 @@ namespace JT808.Gateway.Handlers CreateRoute(JT808GatewayConstants.JT808WebApiRouteTable.SessionRemoveByTerminalPhoneNo, RemoveSessionByTerminalPhoneNo); } + /// + /// + /// protected virtual void InitUdpRoute() { CreateRoute(JT808GatewayConstants.JT808WebApiRouteTable.SessionUdpGetAll, GetUdpSessionAll); diff --git a/src/JT808.Gateway/JT808.Gateway.xml b/src/JT808.Gateway/JT808.Gateway.xml index 78ce4ae..9301a55 100644 --- a/src/JT808.Gateway/JT808.Gateway.xml +++ b/src/JT808.Gateway/JT808.Gateway.xml @@ -9,6 +9,13 @@ 默认消息处理业务实现 + + + + + + + 会话服务集合 @@ -58,6 +65,47 @@ + + + 添加sim卡黑名单 + + + + + + + 移除sim卡黑名单 + + + + + + + 移除sim卡黑名单 + + + + + + + + + + + + + + + + + + + + + + JT808网关注册扩展 + + 添加808网关 @@ -150,9 +198,14 @@ - + + + 808 tcp服务器 + + + - 使用队列方式 + 初始化服务注册 @@ -161,6 +214,56 @@ + + + + + + + + + + + + + + + + + + + SIM黑名单管理 + + + + + + + + + + 是否包含 + + + + + + + 添加 + + + + + + 移除 + + + + + + 查询所有黑名单 + + @@ -168,6 +271,67 @@ 不支持变态类型:既发TCP和UDP + + + socket连接会话 + + + + + socket绑定的终端SIM连接会话 + + + + + + + + + + + + + + + + + + 获取会话总数量 + + + + + 获取tcp会话数量 + + + + + 获取udp会话数量 + + + + + + + + + + + + + + + + + + + + + + + + + 终端手机号 diff --git a/src/JT808.Gateway/JT808GatewayExtensions.cs b/src/JT808.Gateway/JT808GatewayExtensions.cs index 08ee494..d71d566 100644 --- a/src/JT808.Gateway/JT808GatewayExtensions.cs +++ b/src/JT808.Gateway/JT808GatewayExtensions.cs @@ -17,6 +17,9 @@ using System.Linq; [assembly: InternalsVisibleTo("JT808.Gateway.Test")] namespace JT808.Gateway { + /// + /// JT808网关注册扩展 + /// public static partial class JT808GatewayExtensions { /// @@ -161,6 +164,7 @@ namespace JT808.Gateway private static IJT808GatewayBuilder AddJT808Core(this IJT808GatewayBuilder config) { config.JT808Builder.Services.AddSingleton(); + config.JT808Builder.Services.AddSingleton(); config.JT808Builder.Services.AddSingleton(); config.JT808Builder.Services.AddSingleton(); config.JT808Builder.Services.AddSingleton(); diff --git a/src/JT808.Gateway/JT808TcpServer.cs b/src/JT808.Gateway/JT808TcpServer.cs index 3f52692..93972e4 100644 --- a/src/JT808.Gateway/JT808TcpServer.cs +++ b/src/JT808.Gateway/JT808TcpServer.cs @@ -7,6 +7,7 @@ using System.Threading; using System.Threading.Tasks; using JT808.Gateway.Abstractions; using JT808.Gateway.Abstractions.Configurations; +using JT808.Gateway.Services; using JT808.Gateway.Session; using JT808.Protocol; using JT808.Protocol.Exceptions; @@ -17,6 +18,9 @@ using Microsoft.Extensions.Options; namespace JT808.Gateway { + /// + /// 808 tcp服务器 + /// public class JT808TcpServer : IHostedService { private Socket server; @@ -25,6 +29,8 @@ namespace JT808.Gateway private readonly JT808SessionManager SessionManager; + private readonly JT808BlacklistManager BlacklistManager; + private readonly JT808Serializer Serializer; private readonly JT808MessageHandler MessageHandler; @@ -35,8 +41,10 @@ namespace JT808.Gateway private readonly IOptionsMonitor ConfigurationMonitor; + private long MessageReceiveCounter = 0; + /// - /// 使用队列方式 + /// 初始化服务注册 /// /// /// @@ -45,6 +53,7 @@ namespace JT808.Gateway /// /// /// + /// public JT808TcpServer( IOptionsMonitor configurationMonitor, IJT808MsgProducer msgProducer, @@ -52,13 +61,15 @@ namespace JT808.Gateway JT808MessageHandler messageHandler, IJT808Config jT808Config, ILoggerFactory loggerFactory, - JT808SessionManager jT808SessionManager) + JT808SessionManager jT808SessionManager, + JT808BlacklistManager jT808BlacklistManager) { MessageHandler = messageHandler; MsgProducer = msgProducer; MsgReplyLoggingProducer = msgReplyLoggingProducer; ConfigurationMonitor = configurationMonitor; SessionManager = jT808SessionManager; + BlacklistManager = jT808BlacklistManager; Logger = loggerFactory.CreateLogger(); Serializer = jT808Config.GetSerializer(); InitServer(); @@ -76,7 +87,11 @@ namespace JT808.Gateway server.Bind(IPEndPoint); server.Listen(ConfigurationMonitor.CurrentValue.SoBacklog); } - + /// + /// + /// + /// + /// public Task StartAsync(CancellationToken cancellationToken) { Logger.LogInformation($"JT808 TCP Server start at {IPAddress.Any}:{ConfigurationMonitor.CurrentValue.TcpPort}."); @@ -118,15 +133,20 @@ namespace JT808.Gateway break; } writer.Advance(bytesRead); + FlushResult result = await writer.FlushAsync(session.ReceiveTimeout.Token); + if (result.IsCompleted) + { + break; + } } - catch (OperationCanceledException ex) + catch (OperationCanceledException) { - Logger.LogError($"[Receive Timeout]:{session.Client.RemoteEndPoint},{session.TerminalPhoneNo}"); + Logger.LogError($"[Receive Timeout Or Operation Canceled]:{session.Client.RemoteEndPoint},{session.TerminalPhoneNo}"); break; } catch (System.Net.Sockets.SocketException ex) { - Logger.LogError($"[{ex.SocketErrorCode.ToString()},{ex.Message}]:{session.Client.RemoteEndPoint},{session.TerminalPhoneNo}"); + Logger.LogError($"[{ex.SocketErrorCode},{ex.Message}]:{session.Client.RemoteEndPoint},{session.TerminalPhoneNo}"); break; } #pragma warning disable CA1031 // Do not catch general exception types @@ -136,11 +156,6 @@ namespace JT808.Gateway break; } #pragma warning restore CA1031 // Do not catch general exception types - FlushResult result = await writer.FlushAsync(); - if (result.IsCompleted) - { - break; - } } writer.Complete(); } @@ -161,16 +176,14 @@ namespace JT808.Gateway if (result.IsCanceled) break; if (buffer.Length > 0) { - ReaderBuffer(ref buffer, session, out consumed, out examined); + ReaderBuffer(ref buffer, session, out consumed); } } -#pragma warning disable CA1031 // Do not catch general exception types catch (Exception ex) { Logger.LogError(ex, $"[ReadPipe Error]:{session.Client.RemoteEndPoint},{session.TerminalPhoneNo}"); break; } -#pragma warning restore CA1031 // Do not catch general exception types finally { reader.AdvanceTo(consumed, examined); @@ -178,10 +191,8 @@ namespace JT808.Gateway } reader.Complete(); } - private void ReaderBuffer(ref ReadOnlySequence buffer, JT808TcpSession session, out SequencePosition consumed, out SequencePosition examined) + private void ReaderBuffer(ref ReadOnlySequence buffer, JT808TcpSession session, out SequencePosition consumed) { - consumed = buffer.Start; - examined = buffer.End; SequenceReader seqReader = new SequenceReader(buffer); if (seqReader.TryPeek(out byte beginMark)) { @@ -195,29 +206,43 @@ namespace JT808.Gateway { if (mark == 1) { - ReadOnlySpan contentSpan = ReadOnlySpan.Empty; + byte[] data = null; try { - contentSpan = seqReader.Sequence.Slice(totalConsumed, seqReader.Consumed - totalConsumed).FirstSpan; + data = seqReader.Sequence.Slice(totalConsumed, seqReader.Consumed - totalConsumed).ToArray(); //过滤掉不是808标准包(14) //(头)1+(消息 ID )2+(消息体属性)2+(终端手机号)6+(消息流水号)2+(检验码 )1+(尾)1 - if (contentSpan.Length > 14) + if (data != null && data.Length > 14) { - var package = Serializer.HeaderDeserialize(contentSpan, minBufferSize: 10240); - if (Logger.IsEnabled(LogLevel.Trace)) Logger.LogTrace($"[Accept Hex {session.Client.RemoteEndPoint}-{session.TerminalPhoneNo}]:{package.OriginalData.ToHexString()}"); + var package = Serializer.HeaderDeserialize(data); + if (BlacklistManager.Contains(package.Header.TerminalPhoneNo)) + { + if (Logger.IsEnabled(LogLevel.Warning)) + Logger.LogWarning($"[Blacklist {session.Client.RemoteEndPoint}-{session.TerminalPhoneNo}]:{package.OriginalData.ToHexString()}"); + session.ReceiveTimeout.Cancel(); + break; + } +# if DEBUG + Interlocked.Increment(ref MessageReceiveCounter); + if (Logger.IsEnabled(LogLevel.Trace)) + Logger.LogTrace($"[Accept Hex {session.Client.RemoteEndPoint}-{session.TerminalPhoneNo}]:{package.OriginalData.ToHexString()},Counter:{MessageReceiveCounter}"); +#else + if (Logger.IsEnabled(LogLevel.Trace)) + Logger.LogTrace($"[Accept Hex {session.Client.RemoteEndPoint}-{session.TerminalPhoneNo}]:{package.OriginalData.ToHexString()}"); +#endif SessionManager.TryLink(package.Header.TerminalPhoneNo, session); Processor(session, package); } } catch (NotImplementedException ex) { - Logger.LogError(ex.Message,$"{session.Client.RemoteEndPoint},{session.TerminalPhoneNo}"); + Logger.LogError(ex.Message, $"[ReaderBuffer]:{data?.ToHexString()},{session.Client.RemoteEndPoint},{session.TerminalPhoneNo}"); } catch (JT808Exception ex) { - Logger.LogError($"[HeaderDeserialize ErrorCode]:{ ex.ErrorCode},[ReaderBuffer]:{contentSpan.ToArray().ToHexString()},{session.Client.RemoteEndPoint},{session.TerminalPhoneNo}"); + Logger.LogError($"[HeaderDeserialize ErrorCode]:{ ex.ErrorCode},[ReaderBuffer]:{data?.ToHexString()},{session.Client.RemoteEndPoint},{session.TerminalPhoneNo}"); } - totalConsumed += (seqReader.Consumed - totalConsumed); + totalConsumed += seqReader.Consumed - totalConsumed; if (seqReader.End) break; seqReader.Advance(1); mark = 0; @@ -231,14 +256,14 @@ namespace JT808.Gateway } if (seqReader.Length == totalConsumed) { - examined = consumed = buffer.End; + consumed = buffer.End; } else { consumed = buffer.GetPosition(totalConsumed); } } - private void Processor(in IJT808Session session,in JT808HeaderPackage package) + private void Processor(in IJT808Session session, in JT808HeaderPackage package) { try { @@ -266,6 +291,12 @@ namespace JT808.Gateway Logger.LogError(ex, $"[Processor]:{package.OriginalData.ToHexString()},{session.Client.RemoteEndPoint},{session.TerminalPhoneNo}"); } } + + /// + /// + /// + /// + /// public Task StopAsync(CancellationToken cancellationToken) { Logger.LogInformation("JT808 Tcp Server Stop"); diff --git a/src/JT808.Gateway/Services/JT808BlacklistManager.cs b/src/JT808.Gateway/Services/JT808BlacklistManager.cs new file mode 100644 index 0000000..0a2a3c4 --- /dev/null +++ b/src/JT808.Gateway/Services/JT808BlacklistManager.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Collections.Concurrent; +using System.IO; +using Microsoft.Extensions.Options; +using System.Linq; + +namespace JT808.Gateway.Services +{ + /// + /// SIM黑名单管理 + /// + public class JT808BlacklistManager + { + private ConcurrentDictionary Blacklist; + + private const string BlacklistFileName = "blacklist.ini"; + + private FileSystemWatcher fileSystemWatcher; + + private string FullPath; + + /// + /// + /// + public JT808BlacklistManager() + { + Blacklist = new ConcurrentDictionary(); + FullPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, BlacklistFileName); + if (!File.Exists(FullPath)) + { + File.Create(FullPath).Close(); + } + else + { + Init(FullPath); + } + fileSystemWatcher = new FileSystemWatcher(AppDomain.CurrentDomain.BaseDirectory, BlacklistFileName); + fileSystemWatcher.NotifyFilter = NotifyFilters.LastWrite; + fileSystemWatcher.EnableRaisingEvents = true; + fileSystemWatcher.Changed += (sender, e) => + { + Init(e.FullPath); + }; + } + + private void Init(string fullPath) + { + var values = File.ReadAllLines(fullPath); + foreach (var item in values) + { + if (!string.IsNullOrEmpty(item)) + { + Blacklist.TryAdd(item, 0); + } + } + } + + /// + /// 是否包含 + /// + /// + /// + public bool Contains(string sim) + { + return Blacklist.ContainsKey(sim); + } + + /// + /// 添加 + /// + /// + public void Add(string sim) + { + if(Blacklist.TryAdd(sim, 0)) + { + File.AppendAllLines(FullPath, new List { sim }); + } + } + + /// + /// 移除 + /// + /// + public void Remove(string sim) + { + Blacklist.TryRemove(sim, out _); + File.WriteAllLines(FullPath, Blacklist.Select(s => s.Key).OrderBy(o=>o).ToList()); + } + + /// + /// 查询所有黑名单 + /// + /// + public List GetAll() + { + return Blacklist.Select(s => s.Key).ToList(); + } + } +} diff --git a/src/JT808.Gateway/Session/JT808SessionManager.cs b/src/JT808.Gateway/Session/JT808SessionManager.cs index 47a818f..40438f0 100644 --- a/src/JT808.Gateway/Session/JT808SessionManager.cs +++ b/src/JT808.Gateway/Session/JT808SessionManager.cs @@ -18,27 +18,43 @@ namespace JT808.Gateway.Session public class JT808SessionManager { private readonly ILogger logger; - private readonly IJT808SessionProducer JT808SessionProducer; + private readonly IJT808SessionProducer SessionProducer; + /// + /// socket连接会话 + /// public ConcurrentDictionary Sessions { get; } + /// + /// socket绑定的终端SIM连接会话 + /// public ConcurrentDictionary TerminalPhoneNoSessions { get; } + /// + /// + /// + /// + /// public JT808SessionManager( IJT808SessionProducer jT808SessionProducer, ILoggerFactory loggerFactory ) { - JT808SessionProducer = jT808SessionProducer; + SessionProducer = jT808SessionProducer; Sessions = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); TerminalPhoneNoSessions = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); logger = loggerFactory.CreateLogger(); } - + /// + /// + /// + /// public JT808SessionManager(ILoggerFactory loggerFactory) { Sessions = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); TerminalPhoneNoSessions = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); logger = loggerFactory.CreateLogger(); } - + /// + /// 获取会话总数量 + /// public int TotalSessionCount { get @@ -46,7 +62,9 @@ namespace JT808.Gateway.Session return Sessions.Count; } } - + /// + /// 获取tcp会话数量 + /// public int TcpSessionCount { get @@ -54,7 +72,9 @@ namespace JT808.Gateway.Session return Sessions.Where(w => w.Value.TransportProtocolType == JT808TransportProtocolType.tcp).Count(); } } - + /// + /// 获取udp会话数量 + /// public int UdpSessionCount { get @@ -62,7 +82,11 @@ namespace JT808.Gateway.Session return Sessions.Where(w => w.Value.TransportProtocolType == JT808TransportProtocolType.udp).Count(); } } - + /// + /// + /// + /// + /// internal void TryLink(string terminalPhoneNo, IJT808Session session) { DateTime curretDatetime= DateTime.Now; @@ -74,9 +98,9 @@ namespace JT808.Gateway.Session session.ActiveTime = curretDatetime; TerminalPhoneNoSessions.TryUpdate(terminalPhoneNo, session, cacheSession); //会话通知 - if(JT808SessionProducer != null) + if(SessionProducer != null) { - JT808SessionProducer.ProduceAsync(JT808GatewayConstants.SessionOnline, terminalPhoneNo); + SessionProducer.ProduceAsync(JT808GatewayConstants.SessionOnline, terminalPhoneNo); } } else @@ -91,14 +115,20 @@ namespace JT808.Gateway.Session if (TerminalPhoneNoSessions.TryAdd(terminalPhoneNo, session)) { //会话通知 - if (JT808SessionProducer != null) + if (SessionProducer != null) { - JT808SessionProducer.ProduceAsync(JT808GatewayConstants.SessionOnline, terminalPhoneNo); + SessionProducer.ProduceAsync(JT808GatewayConstants.SessionOnline, terminalPhoneNo); } } } } - + /// + /// + /// + /// + /// + /// + /// public IJT808Session TryLink(string terminalPhoneNo, Socket socket, EndPoint remoteEndPoint) { if (TerminalPhoneNoSessions.TryGetValue(terminalPhoneNo, out IJT808Session currentSession)) @@ -121,13 +151,17 @@ namespace JT808.Gateway.Session //部标的超长待机设备,不会像正常的设备一样一直连着,可能10几分钟连上了,然后发完就关闭连接, //这时候想下发数据需要知道设备什么时候上线,在这边做通知最好不过了。 //有设备关联上来可以进行通知 例如:使用Redis发布订阅 - if (JT808SessionProducer != null) + if (SessionProducer != null) { - JT808SessionProducer.ProduceAsync(JT808GatewayConstants.SessionOnline, terminalPhoneNo); + SessionProducer.ProduceAsync(JT808GatewayConstants.SessionOnline, terminalPhoneNo); } return currentSession; } - + /// + /// + /// + /// + /// internal bool TryAdd(IJT808Session session) { return Sessions.TryAdd(session.SessionID, session); @@ -196,9 +230,9 @@ namespace JT808.Gateway.Session removeSession.Close(); if (logger.IsEnabled(LogLevel.Information)) logger.LogInformation($"[Session Remove]:{terminalPhoneNo}-{tmpTerminalPhoneNo}"); - if (JT808SessionProducer != null) + if (SessionProducer != null) { - JT808SessionProducer.ProduceAsync(JT808GatewayConstants.SessionOffline, tmpTerminalPhoneNo); + SessionProducer.ProduceAsync(JT808GatewayConstants.SessionOffline, tmpTerminalPhoneNo); } } } @@ -216,9 +250,9 @@ namespace JT808.Gateway.Session TerminalPhoneNoSessions.TryRemove(item, out _); } var tmpTerminalPhoneNo = string.Join(",", terminalPhoneNos); - if (JT808SessionProducer != null) + if (SessionProducer != null) { - JT808SessionProducer.ProduceAsync(JT808GatewayConstants.SessionOffline, tmpTerminalPhoneNo); + SessionProducer.ProduceAsync(JT808GatewayConstants.SessionOffline, tmpTerminalPhoneNo); } if (logger.IsEnabled(LogLevel.Information)) logger.LogInformation($"[Session Remove]:{tmpTerminalPhoneNo}");