Ver a proveniência

1.元旦快乐,有事停写4天

2.去除无用项目
3.调整UDP的会话管理、解码器
4.调整TCP/UDP的统一下发
tags/v1.0.0
SmallChi há 6 anos
ascendente
cometimento
bb53b7c331
62 ficheiros alterados com 0 adições e 4214 eliminações
  1. +0
    -90
      src/JT808.DotNetty.Test/Internal/JT808AtomicCounterServiceTest.cs
  2. +0
    -78
      src/JT808.DotNetty.Test/Internal/JT808SessionPublishingRedisImplTest.cs
  3. +0
    -62
      src/JT808.DotNetty.Test/Internal/JT808SessionServiceDefaultImplTest.cs
  4. +0
    -146
      src/JT808.DotNetty.Test/Internal/JT808SourcePackageChannelServiceTest.cs
  5. +0
    -72
      src/JT808.DotNetty.Test/Internal/JT808SourcePackageDispatcherDefaultImplTest.cs
  6. +0
    -104
      src/JT808.DotNetty.Test/Internal/JT808TransmitAddressFilterServiceTest.cs
  7. +0
    -87
      src/JT808.DotNetty.Test/Internal/JT808UnificationSendServiceDefaultImplTest.cs
  8. +0
    -32
      src/JT808.DotNetty.Test/JT808.DotNetty.Test.csproj
  9. +0
    -39
      src/JT808.DotNetty.Test/JT808DefaultChannelId.cs
  10. +0
    -85
      src/JT808.DotNetty.Test/JT808SessionManagerTest.cs
  11. +0
    -90
      src/JT808.DotNetty.Test/JT808WebAPIServiceTest.cs
  12. +0
    -36
      src/JT808.DotNetty.Test/SeedSession.cs
  13. +0
    -46
      src/JT808.DotNetty.Test/TestBase.cs
  14. +0
    -39
      src/JT808.DotNetty.Test/appsettings.json
  15. +0
    -59
      src/JT808.DotNetty/Codecs/JT808ClientDecoder.cs
  16. +0
    -28
      src/JT808.DotNetty/Codecs/JT808Decoder.cs
  17. +0
    -31
      src/JT808.DotNetty/Codecs/JT808UDPDecoder.cs
  18. +0
    -35
      src/JT808.DotNetty/Configurations/JT808ClientConfiguration.cs
  19. +0
    -54
      src/JT808.DotNetty/Configurations/JT808Configuration.cs
  20. +0
    -16
      src/JT808.DotNetty/Dtos/JT808AtomicCounterDto.cs
  21. +0
    -15
      src/JT808.DotNetty/Dtos/JT808DefaultResultDto.cs
  22. +0
    -35
      src/JT808.DotNetty/Dtos/JT808IPAddressDto.cs
  23. +0
    -24
      src/JT808.DotNetty/Dtos/JT808ResultDto.cs
  24. +0
    -30
      src/JT808.DotNetty/Dtos/JT808SessionInfoDto.cs
  25. +0
    -33
      src/JT808.DotNetty/Dtos/JT808SourcePackageChannelInfoDto.cs
  26. +0
    -15
      src/JT808.DotNetty/Dtos/JT808UnificationSendRequestDto.cs
  27. +0
    -107
      src/JT808.DotNetty/Handlers/JT808ConnectionHandler.cs
  28. +0
    -96
      src/JT808.DotNetty/Handlers/JT808ServerHandler.cs
  29. +0
    -70
      src/JT808.DotNetty/Handlers/JT808SourcePackageDispatcherHandler.cs
  30. +0
    -88
      src/JT808.DotNetty/Handlers/JT808UDPServerHandler.cs
  31. +0
    -82
      src/JT808.DotNetty/Handlers/JT808WebAPIServerHandler.cs
  32. +0
    -12
      src/JT808.DotNetty/Interfaces/IJT808SessionPublishing.cs
  33. +0
    -25
      src/JT808.DotNetty/Interfaces/IJT808SessionService.cs
  34. +0
    -18
      src/JT808.DotNetty/Interfaces/IJT808SourcePackageDispatcher.cs
  35. +0
    -15
      src/JT808.DotNetty/Interfaces/IJT808UnificationSendService.cs
  36. +0
    -48
      src/JT808.DotNetty/Internal/JT808AtomicCounterService.cs
  37. +0
    -16
      src/JT808.DotNetty/Internal/JT808MsgIdDefaultHandler.cs
  38. +0
    -16
      src/JT808.DotNetty/Internal/JT808SessionPublishingEmptyImpl.cs
  39. +0
    -75
      src/JT808.DotNetty/Internal/JT808SessionPublishingRedisImpl.cs
  40. +0
    -77
      src/JT808.DotNetty/Internal/JT808SessionServiceDefaultImpl.cs
  41. +0
    -290
      src/JT808.DotNetty/Internal/JT808SourcePackageChannelService.cs
  42. +0
    -39
      src/JT808.DotNetty/Internal/JT808SourcePackageDispatcherDefaultImpl.cs
  43. +0
    -88
      src/JT808.DotNetty/Internal/JT808TransmitAddressFilterService.cs
  44. +0
    -56
      src/JT808.DotNetty/Internal/JT808UnificationSendServiceDefaultImpl.cs
  45. +0
    -253
      src/JT808.DotNetty/Internal/JT808WebAPIService.cs
  46. +0
    -46
      src/JT808.DotNetty/JT808.DotNetty.csproj
  47. +0
    -418
      src/JT808.DotNetty/JT808.DotNetty.xml
  48. +0
    -13
      src/JT808.DotNetty/JT808Constants.cs
  49. +0
    -58
      src/JT808.DotNetty/JT808DotnettyExtensions.cs
  50. +0
    -160
      src/JT808.DotNetty/JT808MsgIdHandlerBase.cs
  51. +0
    -96
      src/JT808.DotNetty/JT808ServerHost.cs
  52. +0
    -141
      src/JT808.DotNetty/JT808SessionManager.cs
  53. +0
    -77
      src/JT808.DotNetty/JT808SimpleTcpClient.cs
  54. +0
    -82
      src/JT808.DotNetty/JT808UDPServerHost.cs
  55. +0
    -82
      src/JT808.DotNetty/JT808WebAPIServerHost.cs
  56. +0
    -44
      src/JT808.DotNetty/Metadata/JT808AtomicCounter.cs
  57. +0
    -22
      src/JT808.DotNetty/Metadata/JT808HttpRequest.cs
  58. +0
    -22
      src/JT808.DotNetty/Metadata/JT808HttpResponse.cs
  59. +0
    -23
      src/JT808.DotNetty/Metadata/JT808Request.cs
  60. +0
    -27
      src/JT808.DotNetty/Metadata/JT808Response.cs
  61. +0
    -31
      src/JT808.DotNetty/Metadata/JT808Session.cs
  62. +0
    -20
      src/JT808.DotNetty/Metadata/JT808UDPPackage.cs

+ 0
- 90
src/JT808.DotNetty.Test/Internal/JT808AtomicCounterServiceTest.cs Ver ficheiro

@@ -1,90 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Codecs;
using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Libuv;
using JT808.DotNetty.Codecs;
using JT808.DotNetty.Dtos;
using JT808.DotNetty.Metadata;
using JT808.Protocol;
using JT808.Protocol.Extensions;
using JT808.Protocol.MessageBody;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Xunit;

namespace JT808.DotNetty.Test.Internal
{
public class JT808AtomicCounterServiceTest: TestBase
{
private IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6565);

public JT808SimpleTcpClient SimpleTcpClient;

public JT808AtomicCounterServiceTest()
{
SimpleTcpClient = new JT808SimpleTcpClient(endPoint);
}

[Fact]
public void Test1()
{
JT808AtomicCounter jT808AtomicCounter = new JT808AtomicCounter();
JT808AtomicCounter jT808AtomicCounter1 = new JT808AtomicCounter();
Parallel.For(0, 1000, (i) =>
{
jT808AtomicCounter.Increment();
});
Assert.Equal(1000, jT808AtomicCounter.Count);
Parallel.For(0, 1000, (i) =>
{
jT808AtomicCounter1.Increment();
});
Assert.Equal(1000, jT808AtomicCounter1.Count);
}

[Fact]
public void Test2()
{
// 心跳会话包
JT808Package jT808Package1 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789001");
SimpleTcpClient.WriteAsync(JT808Serializer.Serialize(jT808Package1));

// 心跳会话包
JT808Package jT808Package2 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789002");
SimpleTcpClient.WriteAsync(JT808Serializer.Serialize(jT808Package2));

// 心跳会话包
JT808Package jT808Package3 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789003");
SimpleTcpClient.WriteAsync(JT808Serializer.Serialize(jT808Package3));

// 心跳会话包
JT808Package jT808Package4 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789004");
SimpleTcpClient.WriteAsync(JT808Serializer.Serialize(jT808Package4));

// 心跳会话包
JT808Package jT808Package5 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789005");
SimpleTcpClient.WriteAsync(JT808Serializer.Serialize(jT808Package5));

// 异步的需要延时下
Thread.Sleep(1000);

HttpClient httpClient = new HttpClient();
// 调用内置的http服务接收文本信息下发
var result = httpClient.GetAsync("http://127.0.0.1:828/jt808api/GetAtomicCounter").Result;
string content = result.Content.ReadAsStringAsync().Result;
JT808ResultDto<JT808AtomicCounterDto> jt808Result = JsonConvert.DeserializeObject<JT808ResultDto<JT808AtomicCounterDto>>(content);
Assert.Equal(200, jt808Result.Code);
Assert.Equal(5,jt808Result.Data.MsgSuccessCount);
Assert.Equal(0, jt808Result.Data.MsgFailCount);
SimpleTcpClient.Down();
}
}
}

+ 0
- 78
src/JT808.DotNetty.Test/Internal/JT808SessionPublishingRedisImplTest.cs Ver ficheiro

@@ -1,78 +0,0 @@
using JT808.DotNetty.Internal;
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Extensions.DependencyInjection;
using JT808.DotNetty.Configurations;
using Microsoft.Extensions.Options;
using Xunit;
using System.Threading.Tasks;
using System.Threading;
using StackExchange.Redis;

namespace JT808.DotNetty.Test.Internal
{
public class JT808SessionPublishingRedisImplTest: TestBase
{
JT808SessionPublishingRedisImpl jT808SessionPublishingRedisImpl;

public JT808SessionPublishingRedisImplTest()
{
jT808SessionPublishingRedisImpl = new JT808SessionPublishingRedisImpl(
ServiceProvider.GetRequiredService<IOptionsMonitor<JT808Configuration>>());
}

[Fact]
public void Test1()
{
int i = 10000;
Task.Run(() => {
while (i > 0)
{
jT808SessionPublishingRedisImpl.PublishAsync(JT808Constants.SessionOnline, null, Guid.NewGuid().ToString("N"));
jT808SessionPublishingRedisImpl.PublishAsync(JT808Constants.SessionOffline, null, Guid.NewGuid().ToString("N"));
i--;
Thread.Sleep(1000);
}
});
Thread.Sleep(1000);
List<string> SessionOnlines = new List<string>();
ChannelMessageQueue channelMessageQueue= jT808SessionPublishingRedisImpl.Subscriber.Subscribe(JT808Constants.SessionOnline);
channelMessageQueue.OnMessage((msg) => {
SessionOnlines.Add(msg.Message);
});
List<string> SessionOfflines = new List<string>();
ChannelMessageQueue channelMessageQueue1 = jT808SessionPublishingRedisImpl.Subscriber.Subscribe(JT808Constants.SessionOffline);
channelMessageQueue1.OnMessage((msg) => {
SessionOfflines.Add(msg.Message);
});
Thread.Sleep(3000);
}

[Fact]
public void Test2()
{
int i = 100000;
Task.Run(() => {
while (i > 0)
{
jT808SessionPublishingRedisImpl.PublishAsync(JT808Constants.SessionOnline, null, Guid.NewGuid().ToString("N"));
jT808SessionPublishingRedisImpl.PublishAsync(JT808Constants.SessionOffline, null, Guid.NewGuid().ToString("N"));
i--;
Thread.Sleep(1000);
}
});
Thread.Sleep(1000);
List<string> SessionOnlines = new List<string>();
List<string> SessionOfflines = new List<string>();
ChannelMessageQueue channelMessageQueue = jT808SessionPublishingRedisImpl.Subscriber.Subscribe(JT808Constants.SessionOnline);
channelMessageQueue.OnMessage((msg) => {
SessionOnlines.Add(msg.Message);
});
ChannelMessageQueue channelMessageQueue1 = jT808SessionPublishingRedisImpl.Subscriber.Subscribe(JT808Constants.SessionOffline);
channelMessageQueue1.OnMessage((msg) => {
SessionOfflines.Add(msg.Message);
});
}
}
}

+ 0
- 62
src/JT808.DotNetty.Test/Internal/JT808SessionServiceDefaultImplTest.cs Ver ficheiro

@@ -1,62 +0,0 @@
using JT808.DotNetty.Internal;
using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using Microsoft.Extensions.DependencyInjection;
using System.Net;
using JT808.Protocol;
using JT808.Protocol.Extensions;
using System.Threading;
using Xunit;
using JT808.DotNetty.Interfaces;

namespace JT808.DotNetty.Test.Internal
{
public class JT808SessionServiceDefaultImplTest : TestBase
{
static IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6565);

[Fact]
public void Test1()
{
IJT808SessionService jT808SessionServiceDefaultImpl = ServiceProvider.GetService<IJT808SessionService>();
JT808SimpleTcpClient SimpleTcpClient1 = new JT808SimpleTcpClient(endPoint);
JT808SimpleTcpClient SimpleTcpClient2 = new JT808SimpleTcpClient(endPoint);
JT808SimpleTcpClient SimpleTcpClient3 = new JT808SimpleTcpClient(endPoint);
JT808SimpleTcpClient SimpleTcpClient4 = new JT808SimpleTcpClient(endPoint);
JT808SimpleTcpClient SimpleTcpClient5 = new JT808SimpleTcpClient(endPoint);
// 心跳会话包
JT808Package jT808Package1 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789001");
SimpleTcpClient1.WriteAsync(JT808Serializer.Serialize(jT808Package1));

// 心跳会话包
JT808Package jT808Package2 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789002");
SimpleTcpClient2.WriteAsync(JT808Serializer.Serialize(jT808Package2));

// 心跳会话包
JT808Package jT808Package3 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789003");
SimpleTcpClient3.WriteAsync(JT808Serializer.Serialize(jT808Package3));

// 心跳会话包
JT808Package jT808Package4 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789004");
SimpleTcpClient4.WriteAsync(JT808Serializer.Serialize(jT808Package4));

// 心跳会话包
JT808Package jT808Package5 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789005");
SimpleTcpClient5.WriteAsync(JT808Serializer.Serialize(jT808Package5));
Thread.Sleep(1000);
var result = jT808SessionServiceDefaultImpl.GetAll();

var result1 = jT808SessionServiceDefaultImpl.GetAll();

Thread.Sleep(10000);

SimpleTcpClient1.Down();
SimpleTcpClient2.Down();
SimpleTcpClient3.Down();
SimpleTcpClient4.Down();
SimpleTcpClient5.Down();
}
}
}

+ 0
- 146
src/JT808.DotNetty.Test/Internal/JT808SourcePackageChannelServiceTest.cs Ver ficheiro

@@ -1,146 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Codecs;
using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Libuv;
using JT808.DotNetty.Codecs;
using JT808.DotNetty.Configurations;
using JT808.DotNetty.Internal;
using JT808.Protocol;
using JT808.Protocol.Extensions;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Xunit;

namespace JT808.DotNetty.Test.Internal
{
public class JT808SourcePackageChannelServiceTest:TestBase
{
private JT808SourcePackageChannelService jT808SourcePackageChannelService;

private IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6565);

public JT808SimpleTcpClient SimpleTcpClient;

/// <summary>
/// 需要使用 SocketTool 创建tcp服务器
/// </summary>
public JT808SourcePackageChannelServiceTest()
{
SimpleTcpClient = new JT808SimpleTcpClient(endPoint, new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6555));
//作为设备5秒上传
Task.Run(() =>
{
Random random = new Random();
while (true)
{

JT808Package jT808Package = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("12345678900"+ random.Next(0,2).ToString());
SimpleTcpClient.WriteAsync(JT808Serializer.Serialize(jT808Package));
Thread.Sleep(1000);
}
});

// 作为源包转发服务端
DispatcherEventLoopGroup bossGroup = new DispatcherEventLoopGroup();
WorkerEventLoopGroup workerGroup = new WorkerEventLoopGroup(bossGroup, 1);
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.Group(bossGroup, workerGroup);
bootstrap.Channel<TcpServerChannel>();
bootstrap
.ChildHandler(new ActionChannelInitializer<IChannel>(channel =>
{
IChannelPipeline pipeline = channel.Pipeline;
channel.Pipeline.AddLast("jt808Buffer", new DelimiterBasedFrameDecoder(int.MaxValue,
Unpooled.CopiedBuffer(new byte[] { JT808.Protocol.JT808Package.BeginFlag }),
Unpooled.CopiedBuffer(new byte[] { JT808.Protocol.JT808Package.EndFlag })));
channel.Pipeline.AddLast("jt808Decode", new JT808ClientDecoder());
}));
bootstrap.BindAsync(6655);

DispatcherEventLoopGroup bossGroup1 = new DispatcherEventLoopGroup();
WorkerEventLoopGroup workerGroup1 = new WorkerEventLoopGroup(bossGroup1, 1);
ServerBootstrap bootstrap1 = new ServerBootstrap();
bootstrap1.Group(bossGroup1, workerGroup1);
bootstrap1.Channel<TcpServerChannel>();
bootstrap1
.ChildHandler(new ActionChannelInitializer<IChannel>(channel =>
{
IChannelPipeline pipeline = channel.Pipeline;
channel.Pipeline.AddLast("jt808Buffer", new DelimiterBasedFrameDecoder(int.MaxValue,
Unpooled.CopiedBuffer(new byte[] { JT808.Protocol.JT808Package.BeginFlag }),
Unpooled.CopiedBuffer(new byte[] { JT808.Protocol.JT808Package.EndFlag })));
channel.Pipeline.AddLast("jt808Decode", new JT808ClientDecoder());
}));
bootstrap1.BindAsync(6656);
}

[Fact]
public void Test1()
{
//预热
Thread.Sleep(3000);

jT808SourcePackageChannelService = ServiceProvider.GetService<JT808SourcePackageChannelService>();
var result = jT808SourcePackageChannelService.GetAll();

//创建服务
DispatcherEventLoopGroup bossGroup2 = new DispatcherEventLoopGroup();
WorkerEventLoopGroup workerGroup2 = new WorkerEventLoopGroup(bossGroup2, 1);
ServerBootstrap bootstrap2 = new ServerBootstrap();
bootstrap2.Group(bossGroup2, workerGroup2);
bootstrap2.Channel<TcpServerChannel>();
bootstrap2
.ChildHandler(new ActionChannelInitializer<IChannel>(channel =>
{
IChannelPipeline pipeline = channel.Pipeline;
channel.Pipeline.AddLast("jt808Buffer", new DelimiterBasedFrameDecoder(int.MaxValue,
Unpooled.CopiedBuffer(new byte[] { JT808.Protocol.JT808Package.BeginFlag }),
Unpooled.CopiedBuffer(new byte[] { JT808.Protocol.JT808Package.EndFlag })));
channel.Pipeline.AddLast("jt808Decode", new JT808ClientDecoder());
}));
bootstrap2.BindAsync(6522);

//添加服务
var addResult = jT808SourcePackageChannelService.Add(new Dtos.JT808IPAddressDto
{
Host = "127.0.0.1",
Port = 6522
}).Result;

Thread.Sleep(1000);

var result1 = jT808SourcePackageChannelService.GetAll();

//删除
var result2 = jT808SourcePackageChannelService.Remove(new Dtos.JT808IPAddressDto
{
Host = "127.0.0.1",
Port = 6522
}).Result;
//[::ffff:127.0.0.1]:13196
var result3 = jT808SourcePackageChannelService.GetAll();
}

[Fact]
public void Test2()
{
//[::ffff:127.0.0.1]:13196
var str = "[::ffff:127.0.0.1]:13196";
IPAddress.TryParse(str, out IPAddress ip);
var a = ip.MapToIPv4().ToString();

var a1 = str.Replace("[::ffff:", "").Replace("]", "");

}
}
}

+ 0
- 72
src/JT808.DotNetty.Test/Internal/JT808SourcePackageDispatcherDefaultImplTest.cs Ver ficheiro

@@ -1,72 +0,0 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using Xunit;
using JT808.Protocol.Extensions;
using System.Threading;
using DotNetty.Transport.Channels;
using System.Runtime.InteropServices;
using DotNetty.Transport.Libuv;
using DotNetty.Transport.Bootstrapping;
using DotNetty.Buffers;
using DotNetty.Codecs;
using JT808.DotNetty.Codecs;

namespace JT808.DotNetty.Test.Internal
{
public class JT808SourcePackageDispatcherDefaultImplTest: TestBase
{
private IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6565);

public JT808SimpleTcpClient SimpleTcpClient;

public JT808SourcePackageDispatcherDefaultImplTest()
{
SimpleTcpClient = new JT808SimpleTcpClient(endPoint, new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6561));
}

[Fact]
public void Test1()
{
// 作为源包转发服务端
DispatcherEventLoopGroup bossGroup = new DispatcherEventLoopGroup();
WorkerEventLoopGroup workerGroup = new WorkerEventLoopGroup(bossGroup, 1);
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
.ChildHandler(new ActionChannelInitializer<IChannel>(channel =>
{
IChannelPipeline pipeline = channel.Pipeline;
channel.Pipeline.AddLast("jt808Buffer", new DelimiterBasedFrameDecoder(int.MaxValue,
Unpooled.CopiedBuffer(new byte[] { JT808.Protocol.JT808Package.BeginFlag }),
Unpooled.CopiedBuffer(new byte[] { JT808.Protocol.JT808Package.EndFlag })));
channel.Pipeline.AddLast("jt808Decode", new JT808ClientDecoder());
}));
bootstrap.BindAsync(6655);
//作为设备上传
byte[] bytes = "7E 02 00 00 26 12 34 56 78 90 12 00 7D 02 00 00 00 01 00 00 00 02 00 BA 7F 0E 07 E4 F1 1C 00 28 00 3C 00 00 18 10 15 10 10 10 01 04 00 00 00 64 02 02 00 7D 01 13 7E".ToHexBytes();
SimpleTcpClient.WriteAsync(bytes);
Thread.Sleep(10000);
SimpleTcpClient.Down();
}

[Fact]
public void Test2()
{
//原包转发 不下发 - 貔貅
byte[] bytes = "7E 02 00 00 26 12 34 56 78 90 12 00 7D 02 00 00 00 01 00 00 00 02 00 BA 7F 0E 07 E4 F1 1C 00 28 00 3C 00 00 18 10 15 10 10 10 01 04 00 00 00 64 02 02 00 7D 01 13 7E".ToHexBytes();
SimpleTcpClient.WriteAsync(bytes);
Thread.Sleep(3000);
SimpleTcpClient.Down();
}
}
}

+ 0
- 104
src/JT808.DotNetty.Test/Internal/JT808TransmitAddressFilterServiceTest.cs Ver ficheiro

@@ -1,104 +0,0 @@
using JT808.DotNetty.Configurations;
using JT808.DotNetty.Dtos;
using JT808.DotNetty.Internal;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Text;
using Xunit;

namespace JT808.DotNetty.Test.Internal
{
public class JT808TransmitAddressFilterServiceTest
{
private JT808TransmitAddressFilterService jT808TransmitAddressFilterService;

public JT808TransmitAddressFilterServiceTest()
{
var serverHostBuilder = new HostBuilder()
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(AppDomain.CurrentDomain.BaseDirectory);
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
})
.ConfigureServices((hostContext, services) =>
{
services.AddSingleton<ILoggerFactory, LoggerFactory>();
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>));
services.Configure<JT808Configuration>(hostContext.Configuration.GetSection("JT808Configuration"));
services.AddSingleton<JT808TransmitAddressFilterService>();
});
var serviceProvider = serverHostBuilder.Build().Services;
jT808TransmitAddressFilterService = serviceProvider.GetService<JT808TransmitAddressFilterService>();
jT808TransmitAddressFilterService.Add(new Dtos.JT808IPAddressDto
{
Host = "127.0.0.1",
Port = 12345
});
jT808TransmitAddressFilterService.Add(new Dtos.JT808IPAddressDto
{
Host = "127.0.0.1",
Port = 12346
});
jT808TransmitAddressFilterService.Add(new Dtos.JT808IPAddressDto
{
Host = "127.0.0.1",
Port = 12347
});
jT808TransmitAddressFilterService.Add(new Dtos.JT808IPAddressDto
{
Host = "127.0.0.1",
Port = 12348
});
}

[Fact]
public void Test1()
{
Assert.True(jT808TransmitAddressFilterService.ContainsKey(new Dtos.JT808IPAddressDto
{
Host = "127.0.0.1",
Port = 12348
}.EndPoint));
}

[Fact]
public void Test2()
{
var result = jT808TransmitAddressFilterService.GetAll();
}

[Fact]
public void Test3()
{
var ip1 = new Dtos.JT808IPAddressDto
{
Host = "127.0.0.1",
Port = 12349
};
var result1= jT808TransmitAddressFilterService.Add(ip1);
Assert.Equal(JT808ResultCode.Ok, result1.Code);
Assert.True(result1.Data);
var result2 = jT808TransmitAddressFilterService.Remove(ip1);
Assert.Equal(JT808ResultCode.Ok, result2.Code);
Assert.True(result2.Data);
}

[Fact]
public void Test4()
{
var configIp = new Dtos.JT808IPAddressDto
{
Host = "127.0.0.1",
Port = 6561
};
var result2 = jT808TransmitAddressFilterService.Remove(configIp);
Assert.Equal(JT808ResultCode.Ok, result2.Code);
Assert.False(result2.Data);
Assert.Equal("不能删除服务器配置的地址", result2.Message);
}
}
}

+ 0
- 87
src/JT808.DotNetty.Test/Internal/JT808UnificationSendServiceDefaultImplTest.cs Ver ficheiro

@@ -1,87 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Codecs;
using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Libuv;
using JT808.DotNetty.Codecs;
using JT808.DotNetty.Dtos;
using JT808.Protocol;
using JT808.Protocol.Extensions;
using JT808.Protocol.MessageBody;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using Xunit;

namespace JT808.DotNetty.Test.Internal
{
public class JT808UnificationSendServiceDefaultImplTest : TestBase
{
private IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6565);

public JT808SimpleTcpClient SimpleTcpClient;

public JT808UnificationSendServiceDefaultImplTest()
{
SimpleTcpClient = new JT808SimpleTcpClient(endPoint);
}

[Fact]
public void Test1()
{
// 文本信息包
JT808Package jT808Package2 = JT808.Protocol.Enums.JT808MsgId.文本信息下发.Create("123456789012", new JT808_0x8300
{
TextFlag = 5,
TextInfo = "smallchi 518"
});
var data = JT808Serializer.Serialize(jT808Package2);

JT808UnificationSendRequestDto jT808UnificationSendRequestDto = new JT808UnificationSendRequestDto();
jT808UnificationSendRequestDto.TerminalPhoneNo = "123456789012";
jT808UnificationSendRequestDto.Data = data;

HttpClient httpClient = new HttpClient();
// 调用内置的http服务接收文本信息下发
var result = httpClient.PostAsync("http://127.0.0.1:828/jt808api/UnificationSend", new StringContent(JsonConvert.SerializeObject(jT808UnificationSendRequestDto))).Result;
string content = result.Content.ReadAsStringAsync().Result;
JT808ResultDto<bool> jt808Result = JsonConvert.DeserializeObject<JT808ResultDto<bool>>(content);
Assert.Equal(200, jt808Result.Code);
Assert.False(jt808Result.Data);
}

[Fact]
public void Test2()
{
// 心跳会话包
JT808Package jT808Package1 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789012");
SimpleTcpClient.WriteAsync(JT808Serializer.Serialize(jT808Package1));

// 文本信息包
JT808Package jT808Package2 = JT808.Protocol.Enums.JT808MsgId.文本信息下发.Create("123456789012", new JT808_0x8300
{
TextFlag=5,
TextInfo= "smallchi 518"
});
var data = JT808Serializer.Serialize(jT808Package2);

JT808UnificationSendRequestDto jT808UnificationSendRequestDto = new JT808UnificationSendRequestDto();
jT808UnificationSendRequestDto.TerminalPhoneNo = "123456789012";
jT808UnificationSendRequestDto.Data = data;

HttpClient httpClient = new HttpClient();
// 调用内置的http服务接收文本信息下发
var result =httpClient.PostAsync("http://127.0.0.1:828/jt808api/UnificationSend", new StringContent(JsonConvert.SerializeObject(jT808UnificationSendRequestDto))).Result;
string content = result.Content.ReadAsStringAsync().Result;
JT808ResultDto<bool> jt808Result = JsonConvert.DeserializeObject<JT808ResultDto<bool>>(content);
Assert.Equal(200, jt808Result.Code);
Assert.True(jt808Result.Data);
SimpleTcpClient.Down();
}
}
}

+ 0
- 32
src/JT808.DotNetty.Test/JT808.DotNetty.Test.csproj Ver ficheiro

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

<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>

<IsPackable>false</IsPackable>

<LangVersion>7.1</LangVersion>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="2.2.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>

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

<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

+ 0
- 39
src/JT808.DotNetty.Test/JT808DefaultChannelId.cs Ver ficheiro

@@ -1,39 +0,0 @@
using DotNetty.Transport.Channels;
using JT808.DotNetty.Metadata;
using System;
using System.Collections.Generic;
using System.Text;

namespace JT808.DotNetty.Test
{
public class JT808DefaultChannelId : IChannelId
{
private static readonly JT808AtomicCounter jT808AtomicCounter = new JT808AtomicCounter();

private string Id {
get
{
return Guid.NewGuid().ToString("N");
}
}

public string AsLongText()
{
return Id;
}

public string AsShortText()
{
return Id;
}

public int CompareTo(IChannelId other)
{
if(other.AsShortText()== Id)
{
return 1;
}
return 0;
}
}
}

+ 0
- 85
src/JT808.DotNetty.Test/JT808SessionManagerTest.cs Ver ficheiro

@@ -1,85 +0,0 @@
using DotNetty.Transport.Channels.Embedded;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using Xunit;

namespace JT808.DotNetty.Test
{
public class JT808SessionManagerTest: SeedSession
{
[Fact]
public void Test1()
{
var no = "test150";
var channel = new EmbeddedChannel(new JT808DefaultChannelId());
jT808SessionManager.TryAdd(new Metadata.JT808Session(channel, no));
Thread.Sleep(1000);
jT808SessionManager.Heartbeat(no);
}

[Fact]
public void Test2()
{
var no = "test151";
var channel = new EmbeddedChannel(new JT808DefaultChannelId());
jT808SessionManager.TryAdd(new Metadata.JT808Session(channel, no));
var sessionInfo = jT808SessionManager.RemoveSession(no);
Assert.Equal(no, sessionInfo.TerminalPhoneNo);
}

[Fact]
public void Test3()
{
var realSessionInfos = jT808SessionManager.GetAll();
}

[Fact]
public void Test4()
{
var realSessionCount = jT808SessionManager.SessionCount;
}

[Fact]
public void Test5()
{
//转发过来的数据 1:n 一个通道对应多个设备
var no = "test1";
var no1 = "test2";
var no2 = "test3";
var no3 = "test4";
var no4 = "test5";
var channel = new EmbeddedChannel(new JT808DefaultChannelId());
jT808SessionManager.TryAdd(new Metadata.JT808Session(channel, no));
jT808SessionManager.TryAdd(new Metadata.JT808Session(channel, no1));
jT808SessionManager.TryAdd(new Metadata.JT808Session(channel, no2));
jT808SessionManager.TryAdd(new Metadata.JT808Session(channel, no3));
jT808SessionManager.TryAdd(new Metadata.JT808Session(channel, no4));
var removeSession = jT808SessionManager.RemoveSession(no);
Assert.Equal(no, removeSession.TerminalPhoneNo);
Assert.Equal(channel, removeSession.Channel);
Assert.Equal(channel.Id, removeSession.Channel.Id);
}

[Fact]
public void Test6()
{
//转发过来的数据 1:n 一个通道对应多个设备
var no = "test61";
var no1 = "test62";
var no2 = "test63";
var no3 = "test64";
var no4 = "test65";
var channel1 = new EmbeddedChannel(new JT808DefaultChannelId());
var channel2 = new EmbeddedChannel(new JT808DefaultChannelId());
jT808SessionManager.TryAdd(new Metadata.JT808Session(channel1, no));
jT808SessionManager.TryAdd(new Metadata.JT808Session(channel1, no1));
jT808SessionManager.TryAdd(new Metadata.JT808Session(channel1, no2));
jT808SessionManager.TryAdd(new Metadata.JT808Session(channel2, no3));
jT808SessionManager.TryAdd(new Metadata.JT808Session(channel2, no4));
jT808SessionManager.RemoveSessionByChannel(channel1);
}
}
}

+ 0
- 90
src/JT808.DotNetty.Test/JT808WebAPIServiceTest.cs Ver ficheiro

@@ -1,90 +0,0 @@
using JT808.DotNetty.Dtos;
using JT808.Protocol;
using JT808.Protocol.Extensions;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using Xunit;

namespace JT808.DotNetty.Test
{
public class JT808WebAPIServiceTest: TestBase
{
private IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6565);

public JT808SimpleTcpClient SimpleTcpClient;

private HttpClient httpClient;

private const string Url = "http://127.0.0.1:828/jt808api";

private const string sessionRoutePrefix = "Session";

private const int length = 10;

public JT808WebAPIServiceTest()
{
SimpleTcpClient = new JT808SimpleTcpClient(endPoint);
httpClient = new HttpClient();
for (var i = 1; i <= length; i++)
{
// 心跳会话包
JT808Package jT808Package1 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create($"{i.ToString()}");
SimpleTcpClient.WriteAsync(JT808Serializer.Serialize(jT808Package1));
}
Thread.Sleep(300);
}

[Fact]
public void GetAllTest()
{
var result = httpClient.GetAsync($"{Url}/{sessionRoutePrefix}/GetAll").Result;
string content = result.Content.ReadAsStringAsync().Result;
JT808ResultDto<IEnumerable<JT808SessionInfoDto>> jt808Result = JsonConvert.DeserializeObject<JT808ResultDto<IEnumerable<JT808SessionInfoDto>>>(content);
Assert.Equal(200, jt808Result.Code);
Assert.Equal(10,jt808Result.Data.Count());
}

[Fact]
public void RemoveByChannelIdTest()
{
// 心跳会话包
JT808Package jT808Package1 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("99");
SimpleTcpClient.WriteAsync(JT808Serializer.Serialize(jT808Package1));

var result4 = httpClient.PostAsync($"{Url}/{sessionRoutePrefix}/RemoveByChannelId", new StringContent("99")).Result;
string content4 = result4.Content.ReadAsStringAsync().Result;
JT808ResultDto<bool> jt808Result4= JsonConvert.DeserializeObject<JT808ResultDto<bool>>(content4);
Assert.Equal(200, jt808Result4.Code);
Assert.True(jt808Result4.Data);
}


[Fact]
public void RemoveByTerminalPhoneNoTest()
{
// 心跳会话包
JT808Package jT808Package1 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("999");
SimpleTcpClient.WriteAsync(JT808Serializer.Serialize(jT808Package1));


var result4 = httpClient.PostAsync($"{Url}/{sessionRoutePrefix}/RemoveByTerminalPhoneNo", new StringContent("999")).Result;
string content4 = result4.Content.ReadAsStringAsync().Result;
JT808ResultDto<bool> jt808Result4 = JsonConvert.DeserializeObject<JT808ResultDto<bool>>(content4);
Assert.Equal(200, jt808Result4.Code);
Assert.True(jt808Result4.Data);
}


public override void Dispose()
{
base.Dispose();
SimpleTcpClient.Down();
}
}
}

+ 0
- 36
src/JT808.DotNetty.Test/SeedSession.cs Ver ficheiro

@@ -1,36 +0,0 @@
using DotNetty.Transport.Channels.Embedded;
using JT808.DotNetty.Internal;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Text;
using Xunit;

namespace JT808.DotNetty.Test
{
public class SeedSession
{
public JT808SessionManager jT808SessionManager = new JT808SessionManager(
new JT808SessionPublishingEmptyImpl(),
new LoggerFactory());

public SeedSession()
{
for (var i = 0; i < 10; i++)
{
var channel = new EmbeddedChannel(new JT808DefaultChannelId());
jT808SessionManager.TryAdd(new Metadata.JT808Session(channel, i.ToString()));
}
}

[Fact]
public void Init()
{
for (var i = 0; i < 10; i++)
{
var channel = new EmbeddedChannel(new JT808DefaultChannelId());
jT808SessionManager.TryAdd(new Metadata.JT808Session(channel, i.ToString()));
}
}
}
}

+ 0
- 46
src/JT808.DotNetty.Test/TestBase.cs Ver ficheiro

@@ -1,46 +0,0 @@
using JT808.DotNetty.Codecs;
using JT808.DotNetty.Configurations;
using JT808.DotNetty.Handlers;
using JT808.DotNetty.Interfaces;
using JT808.DotNetty.Internal;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Net;
using Xunit;

namespace JT808.DotNetty.Test
{
public class TestBase:IDisposable
{
public static IServiceProvider ServiceProvider;

static TestBase()
{
var serverHostBuilder = new HostBuilder()
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(AppDomain.CurrentDomain.BaseDirectory);
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
})
.ConfigureServices((hostContext, services) =>
{
services.AddSingleton<ILoggerFactory, LoggerFactory>();
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>));
})
.UseJT808Host();
var build = serverHostBuilder.Build();
build.Start();
ServiceProvider = build.Services;

}

public virtual void Dispose()
{
}
}
}

+ 0
- 39
src/JT808.DotNetty.Test/appsettings.json Ver ficheiro

@@ -1,39 +0,0 @@
{
"Logging": {
"IncludeScopes": false,
"Debug": {
"LogLevel": {
"Default": "Trace"
}
},
"Console": {
"LogLevel": {
"Default": "Trace"
}
}
},
"JT808Configuration": {
"Port": 6565,
"SourcePackageDispatcherClientConfigurations": [
{
"Host": "127.0.0.1",
"Port": 6655
},
{
"Host": "127.0.0.1",
"Port": 6656
}
],
"ForwardingRemoteAddress": [
{
"Host": "127.0.0.1",
"Port": 6561
},
{
"Host": "127.0.0.1",
"Port": 6562
}
],
"RedisHost": "127.0.0.1:6379"
}
}

+ 0
- 59
src/JT808.DotNetty/Codecs/JT808ClientDecoder.cs Ver ficheiro

@@ -1,59 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Codecs;
using DotNetty.Transport.Channels;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using JT808.Protocol;
using JT808.DotNetty.Metadata;

namespace JT808.DotNetty.Codecs
{
/// <summary>
/// JT808客户端解码(测试客户端)
/// </summary>
internal class JT808ClientDecoder : ByteToMessageDecoder
{
private static readonly ILogger<JT808ClientDecoder> logger=new LoggerFactory().CreateLogger<JT808ClientDecoder>();

private static readonly JT808AtomicCounter MsgSuccessCounter = new JT808AtomicCounter();

private static readonly JT808AtomicCounter MsgFailCounter = new JT808AtomicCounter();

protected override void Decode(IChannelHandlerContext context, IByteBuffer input, List<object> output)
{
byte[] buffer = new byte[input.Capacity + 2];
try
{
input.ReadBytes(buffer, 1, input.Capacity);
buffer[0] = JT808Package.BeginFlag;
buffer[input.Capacity + 1] = JT808Package.EndFlag;
JT808Package jT808Package = JT808Serializer.Deserialize<JT808Package>(buffer);
MsgSuccessCounter.Increment();
output.Add(jT808Package);
if (logger.IsEnabled(LogLevel.Debug))
{
logger.LogDebug("accept package success count<<<" + MsgSuccessCounter.Count.ToString());
}
}
catch (JT808.Protocol.Exceptions.JT808Exception ex)
{
MsgFailCounter.Increment();
if (logger.IsEnabled(LogLevel.Error))
{
logger.LogError("accept package fail count<<<" + MsgFailCounter.Count.ToString());
logger.LogError(ex, "accept msg<<<" + buffer);
}
}
catch (Exception ex)
{
MsgFailCounter.Increment();
if (logger.IsEnabled(LogLevel.Error))
{
logger.LogError("accept package fail count<<<" + MsgFailCounter.Count.ToString());
logger.LogError(ex, "accept msg<<<" + buffer);
}
}
}
}
}

+ 0
- 28
src/JT808.DotNetty/Codecs/JT808Decoder.cs Ver ficheiro

@@ -1,28 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Codecs;
using DotNetty.Transport.Channels;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Text;
using JT808.Protocol;
using JT808.DotNetty.Internal;
using JT808.DotNetty.Interfaces;

namespace JT808.DotNetty.Codecs
{
/// <summary>
/// JT808解码
/// </summary>
internal class JT808Decoder : ByteToMessageDecoder
{
protected override void Decode(IChannelHandlerContext context, IByteBuffer input, List<object> output)
{
byte[] buffer = new byte[input.Capacity + 2];
input.ReadBytes(buffer, 1, input.Capacity);
buffer[0] = JT808Package.BeginFlag;
buffer[input.Capacity + 1] = JT808Package.EndFlag;
output.Add(buffer);
}
}
}

+ 0
- 31
src/JT808.DotNetty/Codecs/JT808UDPDecoder.cs Ver ficheiro

@@ -1,31 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Codecs;
using DotNetty.Transport.Channels;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Text;
using JT808.Protocol;
using JT808.DotNetty.Internal;
using JT808.DotNetty.Interfaces;
using DotNetty.Transport.Channels.Sockets;
using JT808.DotNetty.Metadata;

namespace JT808.DotNetty.Codecs
{
/// <summary>
/// JT808 UDP解码
/// </summary>
internal class JT808UDPDecoder : MessageToMessageDecoder<DatagramPacket>
{


protected override void Decode(IChannelHandlerContext context, DatagramPacket message, List<object> output)
{
IByteBuffer byteBuffer = message.Content;
byte[] buffer = new byte[byteBuffer.ReadableBytes];
byteBuffer.ReadBytes(buffer);
output.Add(new JT808UDPPackage(buffer, message.Sender));
}
}
}

+ 0
- 35
src/JT808.DotNetty/Configurations/JT808ClientConfiguration.cs Ver ficheiro

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

namespace JT808.DotNetty.Configurations
{
public class JT808ClientConfiguration
{
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);
}
else
{
endPoint = new DnsEndPoint(Host, Port);
}
}
return endPoint;
}
}
}
}

+ 0
- 54
src/JT808.DotNetty/Configurations/JT808Configuration.cs Ver ficheiro

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

namespace JT808.DotNetty.Configurations
{
public class JT808Configuration
{
public int Port { get; set; } = 808;

public int UDPPort { get; set; } = 809;

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;

/// <summary>
/// WebApi服务
/// 默认828端口
/// </summary>
public int WebApiPort { get; set; } = 828;

/// <summary>
/// 源包分发器配置
/// </summary>
public List<JT808ClientConfiguration> SourcePackageDispatcherClientConfigurations { get; set; }

/// <summary>
/// 转发远程地址 (可选项)知道转发的地址有利于提升性能
/// 按照808的消息,有些请求必须要应答,但是转发可以不需要有应答可以节省部分资源包括:
// 1.消息的序列化
// 2.消息的下发
// 都有一定的性能损耗,那么不需要判断写超时 IdleState.WriterIdle
// 就跟神兽貔貅一样。。。
/// </summary>
public List<JT808ClientConfiguration> ForwardingRemoteAddress { get; set; }

public string RedisHost { get; set; }
}
}

+ 0
- 16
src/JT808.DotNetty/Dtos/JT808AtomicCounterDto.cs Ver ficheiro

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

namespace JT808.DotNetty.Dtos
{
/// <summary>
/// 包计数器服务
/// </summary>
public class JT808AtomicCounterDto
{
public long MsgSuccessCount { get; set; }

public long MsgFailCount { get; set; }
}
}

+ 0
- 15
src/JT808.DotNetty/Dtos/JT808DefaultResultDto.cs Ver ficheiro

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

namespace JT808.DotNetty.Dtos
{
public class JT808DefaultResultDto: JT808ResultDto<string>
{
public JT808DefaultResultDto()
{
Data = "Hello,JT808 WebAPI";
Code = JT808ResultCode.Ok;
}
}
}

+ 0
- 35
src/JT808.DotNetty/Dtos/JT808IPAddressDto.cs Ver ficheiro

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

namespace JT808.DotNetty.Dtos
{
public class JT808IPAddressDto
{
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);
}
else
{
endPoint = new DnsEndPoint(Host, Port);
}
}
return endPoint;
}
}
}
}

+ 0
- 24
src/JT808.DotNetty/Dtos/JT808ResultDto.cs Ver ficheiro

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

namespace JT808.DotNetty.Dtos
{
public class JT808ResultDto<T>
{
public string Message { get; set; }

public int Code { get; set; }

public T Data { get; set; }
}

internal class JT808ResultCode
{
public const int Ok = 200;
public const int Empty = 201;
public const int NotFound = 404;
public const int Fail = 400;
public const int Error = 500;
}
}

+ 0
- 30
src/JT808.DotNetty/Dtos/JT808SessionInfoDto.cs Ver ficheiro

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

namespace JT808.DotNetty.Dtos
{
public class JT808SessionInfoDto
{
/// <summary>
/// 通道Id
/// </summary>
public string ChannelId { get; set; }
/// <summary>
/// 最后上线时间
/// </summary>
public DateTime LastActiveTime { get; set; }
/// <summary>
/// 上线时间
/// </summary>
public DateTime StartTime { get; set; }
/// <summary>
/// 终端手机号
/// </summary>
public string TerminalPhoneNo { get; set; }
/// <summary>
/// 远程ip地址
/// </summary>
public string RemoteAddressIP { get; set; }
}
}

+ 0
- 33
src/JT808.DotNetty/Dtos/JT808SourcePackageChannelInfoDto.cs Ver ficheiro

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

namespace JT808.DotNetty.Dtos
{
/// <summary>
/// 原包通道信息
/// </summary>
public class JT808SourcePackageChannelInfoDto
{
/// <summary>
/// 远程地址
/// </summary>
public string RemoteAddress { get; set; }
/// <summary>
/// 本地地址
/// </summary>
public string LocalAddress { get; set; }
/// <summary>
/// 是否注册
/// </summary>
public bool Registered { get; set; }
/// <summary>
/// 是否活动
/// </summary>
public bool Active { get; set; }
/// <summary>
/// 是否打开
/// </summary>
public bool Open { get; set; }
}
}

+ 0
- 15
src/JT808.DotNetty/Dtos/JT808UnificationSendRequestDto.cs Ver ficheiro

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

namespace JT808.DotNetty.Dtos
{
/// <summary>
/// 统一下发请求参数
/// </summary>
public class JT808UnificationSendRequestDto
{
public string TerminalPhoneNo { get; set; }
public byte[] Data { get; set; }
}
}

+ 0
- 107
src/JT808.DotNetty/Handlers/JT808ConnectionHandler.cs Ver ficheiro

@@ -1,107 +0,0 @@
using DotNetty.Handlers.Timeout;
using DotNetty.Transport.Channels;
using JT808.DotNetty.Metadata;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using System.Threading.Tasks;

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

private readonly JT808SessionManager jT808SessionManager;

public JT808ConnectionHandler(
JT808SessionManager jT808SessionManager,
ILoggerFactory loggerFactory)
{
this.jT808SessionManager = jT808SessionManager;
logger = loggerFactory.CreateLogger<JT808ConnectionHandler>();
}

/// <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.");
jT808SessionManager.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.");
jT808SessionManager.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是设备发心跳,如果很久没有上报数据,那么就由服务器主动关闭连接。
jT808SessionManager.RemoveSessionByChannel(context.Channel);
context.CloseAsync();
}
// 按照808的消息,有些请求必须要应答,但是转发可以不需要有应答可以节省部分资源包括:
// 1.消息的序列化
// 2.消息的下发
// 都有一定的性能损耗,那么不需要判断写超时 IdleState.WriterIdle
// 就跟神兽貔貅一样。。。
}
base.UserEventTriggered(context, evt);
}

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


+ 0
- 96
src/JT808.DotNetty/Handlers/JT808ServerHandler.cs Ver ficheiro

@@ -1,96 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Transport.Channels;
using JT808.Protocol;
using System;
using System.Collections.Generic;
using System.Text;
using JT808.DotNetty.Metadata;
using JT808.DotNetty.Internal;
using JT808.DotNetty.Interfaces;
using Microsoft.Extensions.Logging;

namespace JT808.DotNetty.Handlers
{
/// <summary>
/// JT808服务端处理程序
/// </summary>
internal class JT808ServerHandler : SimpleChannelInboundHandler<byte[]>
{
private readonly JT808MsgIdHandlerBase handler;
private readonly JT808SessionManager jT808SessionManager;

private readonly JT808TransmitAddressFilterService jT808TransmitAddressFilterService;

private readonly IJT808SourcePackageDispatcher jT808SourcePackageDispatcher;

private readonly JT808AtomicCounterService jT808AtomicCounterService;

private readonly ILogger<JT808ServerHandler> logger;

public JT808ServerHandler(
ILoggerFactory loggerFactory,
JT808TransmitAddressFilterService jT808TransmitAddressFilterService,
IJT808SourcePackageDispatcher jT808SourcePackageDispatcher,
JT808MsgIdHandlerBase handler,
JT808AtomicCounterService jT808AtomicCounterService,
JT808SessionManager jT808SessionManager)
{
this.jT808TransmitAddressFilterService = jT808TransmitAddressFilterService;
this.handler = handler;
this.jT808SessionManager = jT808SessionManager;
this.jT808SourcePackageDispatcher = jT808SourcePackageDispatcher;
this.jT808AtomicCounterService = jT808AtomicCounterService;
logger = loggerFactory.CreateLogger<JT808ServerHandler>();
}


protected override void ChannelRead0(IChannelHandlerContext ctx, byte[] msg)
{
try
{
jT808SourcePackageDispatcher?.SendAsync(msg);
//解析到头部,然后根据具体的消息Id通过队列去进行消费
//要是一定要解析到数据体可以在JT808MsgIdHandlerBase类中根据具体的消息,
//解析具体的消息体,具体调用JT808Serializer.Deserialize<T>
JT808HeaderPackage jT808HeaderPackage = JT808Serializer.Deserialize<JT808HeaderPackage>(msg);
jT808AtomicCounterService.MsgSuccessIncrement();
if (logger.IsEnabled(LogLevel.Debug))
{
logger.LogDebug("accept package success count<<<" + jT808AtomicCounterService.MsgSuccessCount.ToString());
}
jT808SessionManager.TryAdd(new JT808Session(ctx.Channel, jT808HeaderPackage.Header.TerminalPhoneNo));
Func<JT808Request, JT808Response> handlerFunc;
if (handler.HandlerDict.TryGetValue(jT808HeaderPackage.Header.MsgId, out handlerFunc))
{
JT808Response jT808Response = handlerFunc(new JT808Request(jT808HeaderPackage, msg));
if (jT808Response != null)
{
if (!jT808TransmitAddressFilterService.ContainsKey(ctx.Channel.RemoteAddress))
{
ctx.WriteAndFlushAsync(Unpooled.WrappedBuffer(JT808Serializer.Serialize(jT808Response.Package, jT808Response.MinBufferSize)));
}
}
}
}
catch (JT808.Protocol.Exceptions.JT808Exception ex)
{
jT808AtomicCounterService.MsgFailIncrement();
if (logger.IsEnabled(LogLevel.Error))
{
logger.LogError("accept package fail count<<<" + jT808AtomicCounterService.MsgFailCount.ToString());
logger.LogError(ex, "accept msg<<<" + ByteBufferUtil.HexDump(msg));
}
}
catch (Exception ex)
{
jT808AtomicCounterService.MsgFailIncrement();
if (logger.IsEnabled(LogLevel.Error))
{
logger.LogError("accept package fail count<<<" + jT808AtomicCounterService.MsgFailCount.ToString());
logger.LogError(ex, "accept msg<<<" + ByteBufferUtil.HexDump(msg));
}
}
}
}
}

+ 0
- 70
src/JT808.DotNetty/Handlers/JT808SourcePackageDispatcherHandler.cs Ver ficheiro

@@ -1,70 +0,0 @@
using DotNetty.Transport.Channels;
using JT808.DotNetty.Internal;
using Microsoft.Extensions.Logging;
using Polly;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;

namespace JT808.DotNetty.Handlers
{
internal class JT808SourcePackageDispatcherHandler: ChannelHandlerAdapter
{
private readonly ILogger<JT808SourcePackageDispatcherHandler> logger;

private readonly JT808SourcePackageChannelService jT808SourcePackageChannelService;

public JT808SourcePackageDispatcherHandler(JT808SourcePackageChannelService jT808SourcePackageChannelService)
{
logger= jT808SourcePackageChannelService.LoggerFactory.CreateLogger<JT808SourcePackageDispatcherHandler>();
this.jT808SourcePackageChannelService = jT808SourcePackageChannelService;
}

public override void ChannelInactive(IChannelHandlerContext context)
{
Policy.HandleResult<bool>(context.Channel.Open)
.WaitAndRetryForeverAsync(retryAttempt =>
{
return retryAttempt > 20 ? TimeSpan.FromSeconds(Math.Pow(2, 50)) : TimeSpan.FromSeconds(Math.Pow(2, retryAttempt));//超过重试20次,接近12个小时链接一次
},(exception, timespan, ctx) =>
{
logger.LogError($"Server Disconnection {context.Channel.RemoteAddress.ToString()},Retry Results{exception.Result},Retry Number{timespan},Next Retry Interval(s){ctx.TotalSeconds}");
})
.ExecuteAsync(async () =>
{
try
{
var newChannel = jT808SourcePackageChannelService.channels.FirstOrDefault(m => m.Value == context.Channel);
if (default(KeyValuePair<EndPoint, IChannel>).Equals(newChannel))
{
if(logger.IsEnabled(LogLevel.Debug))
logger.LogDebug($"Server already deleted {context.Channel.RemoteAddress.ToString()} remote server configuration");
return true;
}
var channel = await jT808SourcePackageChannelService.bootstrap.ConnectAsync(context.Channel.RemoteAddress);
jT808SourcePackageChannelService.channels.AddOrUpdate(newChannel.Key, channel, (x, y) => channel);
return channel.Open;
}
catch (Exception ex)
{
logger.LogError(ex,$"Reconnection abnormal:After the server is disconnected {context.Channel.RemoteAddress.ToString()}");
return false;
}
});
}

public override void ChannelRead(IChannelHandlerContext context, object message)
{
if(logger.IsEnabled(LogLevel.Debug))
logger.LogDebug($"The server returns a message {message.ToString()}");
}

public override void ExceptionCaught(IChannelHandlerContext context, Exception exception)
{
logger.LogError(exception, context.Channel.RemoteAddress.ToString());
context.CloseAsync();
}
}
}

+ 0
- 88
src/JT808.DotNetty/Handlers/JT808UDPServerHandler.cs Ver ficheiro

@@ -1,88 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Transport.Channels;
using JT808.Protocol;
using System;
using System.Collections.Generic;
using System.Text;
using JT808.DotNetty.Metadata;
using JT808.DotNetty.Internal;
using JT808.DotNetty.Interfaces;
using Microsoft.Extensions.Logging;
using DotNetty.Transport.Channels.Sockets;

namespace JT808.DotNetty.Handlers
{
/// <summary>
/// JT808 UDP服务端处理程序
/// </summary>
internal class JT808UDPServerHandler : SimpleChannelInboundHandler<JT808UDPPackage>
{
private readonly JT808MsgIdHandlerBase handler;
private readonly JT808SessionManager jT808SessionManager;

private readonly IJT808SourcePackageDispatcher jT808SourcePackageDispatcher;

private readonly JT808AtomicCounterService jT808AtomicCounterService;

private readonly ILogger<JT808UDPServerHandler> logger;

public JT808UDPServerHandler(
ILoggerFactory loggerFactory,
IJT808SourcePackageDispatcher jT808SourcePackageDispatcher,
JT808MsgIdHandlerBase handler,
JT808AtomicCounterService jT808AtomicCounterService,
JT808SessionManager jT808SessionManager)
{
this.handler = handler;
this.jT808SessionManager = jT808SessionManager;
this.jT808SourcePackageDispatcher = jT808SourcePackageDispatcher;
this.jT808AtomicCounterService = jT808AtomicCounterService;
logger = loggerFactory.CreateLogger<JT808UDPServerHandler>();
}

protected override void ChannelRead0(IChannelHandlerContext ctx, JT808UDPPackage msg)
{
try
{
jT808SourcePackageDispatcher?.SendAsync(msg.Buffer);
//解析到头部,然后根据具体的消息Id通过队列去进行消费
//要是一定要解析到数据体可以在JT808MsgIdHandlerBase类中根据具体的消息,
//解析具体的消息体,具体调用JT808Serializer.Deserialize<T>
JT808HeaderPackage jT808HeaderPackage = JT808Serializer.Deserialize<JT808HeaderPackage>(msg.Buffer);
jT808AtomicCounterService.MsgSuccessIncrement();
if (logger.IsEnabled(LogLevel.Debug))
{
logger.LogDebug("accept package success count<<<" + jT808AtomicCounterService.MsgSuccessCount.ToString());
}
Func<JT808Request, JT808Response> handlerFunc;
if (handler.HandlerDict.TryGetValue(jT808HeaderPackage.Header.MsgId, out handlerFunc))
{
JT808Response jT808Response = handlerFunc(new JT808Request(jT808HeaderPackage, msg.Buffer));
if (jT808Response != null)
{
ctx.WriteAndFlushAsync(new DatagramPacket(Unpooled.WrappedBuffer(JT808Serializer.Serialize(jT808Response.Package, jT808Response.MinBufferSize)), msg.Sender));
}
}
}
catch (JT808.Protocol.Exceptions.JT808Exception ex)
{
jT808AtomicCounterService.MsgFailIncrement();
if (logger.IsEnabled(LogLevel.Error))
{
logger.LogError("accept package fail count<<<" + jT808AtomicCounterService.MsgFailCount.ToString());
logger.LogError(ex, "accept msg<<<" + ByteBufferUtil.HexDump(msg.Buffer));
}
}
catch (Exception ex)
{
jT808AtomicCounterService.MsgFailIncrement();
if (logger.IsEnabled(LogLevel.Error))
{
logger.LogError("accept package fail count<<<" + jT808AtomicCounterService.MsgFailCount.ToString());
logger.LogError(ex, "accept msg<<<" + ByteBufferUtil.HexDump(msg.Buffer));
}
}
}
}
}

+ 0
- 82
src/JT808.DotNetty/Handlers/JT808WebAPIServerHandler.cs Ver ficheiro

@@ -1,82 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Codecs.Http;
using DotNetty.Common.Utilities;
using DotNetty.Transport.Channels;
using JT808.DotNetty.Internal;
using JT808.DotNetty.Metadata;
using Microsoft.Extensions.Logging;
using System;
using System.Text;

namespace JT808.DotNetty.Handlers
{
/// <summary>
/// jt808 webapi服务
/// 请求量不大,只支持JSON格式并且只支持post发数据
/// ref: dotnetty HttpServer
/// </summary>
internal class JT808WebAPIServerHandler : SimpleChannelInboundHandler<IFullHttpRequest>
{
private static readonly AsciiString TypeJson = AsciiString.Cached("application/json");
private static readonly AsciiString ServerName = AsciiString.Cached("JT808WebAPINetty");
private static readonly AsciiString ContentTypeEntity = HttpHeaderNames.ContentType;
private static readonly AsciiString DateEntity = HttpHeaderNames.Date;
private static readonly AsciiString ContentLengthEntity = HttpHeaderNames.ContentLength;
private static readonly AsciiString ServerEntity = HttpHeaderNames.Server;
private readonly JT808WebAPIService jT808WebAPIService;
private readonly ILogger<JT808WebAPIServerHandler> logger;

public JT808WebAPIServerHandler(
JT808WebAPIService jT808WebAPIService,
ILoggerFactory loggerFactory)
{
this.jT808WebAPIService = jT808WebAPIService;
logger = loggerFactory.CreateLogger<JT808WebAPIServerHandler>();
}

protected override void ChannelRead0(IChannelHandlerContext ctx, IFullHttpRequest msg)
{
if (logger.IsEnabled(LogLevel.Debug))
{
logger.LogDebug($"Uri:{msg.Uri}");
logger.LogDebug($"Content:{msg.Content.ToString(Encoding.UTF8)}");
}
JT808HttpResponse jT808HttpResponse = null;
if (jT808WebAPIService.HandlerDict.TryGetValue(msg.Uri,out var funcHandler))
{
jT808HttpResponse = funcHandler( new JT808HttpRequest() { Json = msg.Content.ToString(Encoding.UTF8)});
}
else
{
jT808HttpResponse = jT808WebAPIService.NotFoundHttpResponse();
}
if (jT808HttpResponse != null)
{
WriteResponse(ctx, Unpooled.WrappedBuffer(jT808HttpResponse.Data), TypeJson, jT808HttpResponse.Data.Length);
}
}

private void WriteResponse(IChannelHandlerContext ctx, IByteBuffer buf, ICharSequence contentType, int contentLength)
{
// Build the response object.
var response = new DefaultFullHttpResponse(HttpVersion.Http11, HttpResponseStatus.OK, buf, false);
HttpHeaders headers = response.Headers;
headers.Set(ContentTypeEntity, contentType);
headers.Set(ServerEntity, ServerName);
headers.Set(DateEntity, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"));
headers.Set(ContentLengthEntity, contentLength);
// Close the non-keep-alive connection after the write operation is done.
ctx.WriteAndFlushAsync(response);
ctx.CloseAsync();
}

public override void ExceptionCaught(IChannelHandlerContext context, Exception exception)
{
WriteResponse(context, Unpooled.WrappedBuffer(jT808WebAPIService.ErrorHttpResponse(exception).Data), TypeJson, jT808WebAPIService.ErrorHttpResponse(exception).Data.Length);
logger.LogError(exception, exception.Message);
context.CloseAsync();
}

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

+ 0
- 12
src/JT808.DotNetty/Interfaces/IJT808SessionPublishing.cs Ver ficheiro

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

namespace JT808.DotNetty.Interfaces
{
public interface IJT808SessionPublishing
{
Task PublishAsync(string topicName, string key, string value);
}
}

+ 0
- 25
src/JT808.DotNetty/Interfaces/IJT808SessionService.cs Ver ficheiro

@@ -1,25 +0,0 @@
using JT808.DotNetty.Dtos;
using System;
using System.Collections.Generic;
using System.Text;

namespace JT808.DotNetty.Interfaces
{
/// <summary>
/// JT808会话服务
/// </summary>
internal interface IJT808SessionService
{
/// <summary>
/// 获取会话集合
/// </summary>
/// <returns></returns>
JT808ResultDto<List<JT808SessionInfoDto>> GetAll();
/// <summary>
/// 通过设备终端号移除对应会话
/// </summary>
/// <param name="terminalPhoneNo"></param>
/// <returns></returns>
JT808ResultDto<bool> RemoveByTerminalPhoneNo(string terminalPhoneNo);
}
}

+ 0
- 18
src/JT808.DotNetty/Interfaces/IJT808SourcePackageDispatcher.cs Ver ficheiro

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

namespace JT808.DotNetty.Interfaces
{
/// <summary>
/// 源包分发器
/// 自定义源包分发器业务
/// ConfigureServices:
/// services.Replace(new ServiceDescriptor(typeof(IJT808SourcePackageDispatcher),typeof(JT808SourcePackageDispatcherDefaultImpl),ServiceLifetime.Singleton));
/// </summary>
public interface IJT808SourcePackageDispatcher
{
Task SendAsync(byte[] data);
}
}

+ 0
- 15
src/JT808.DotNetty/Interfaces/IJT808UnificationSendService.cs Ver ficheiro

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

namespace JT808.DotNetty.Interfaces
{
/// <summary>
/// JT808统一下发命令
/// </summary>
internal interface IJT808UnificationSendService
{
JT808ResultDto<bool> Send(string terminalPhoneNo, byte[] data);
}
}

+ 0
- 48
src/JT808.DotNetty/Internal/JT808AtomicCounterService.cs Ver ficheiro

@@ -1,48 +0,0 @@
using JT808.DotNetty.Metadata;
using System;
using System.Collections.Generic;
using System.Text;

namespace JT808.DotNetty.Internal
{
/// <summary>
/// 计数包服务
/// </summary>
internal class JT808AtomicCounterService
{
private static readonly JT808AtomicCounter MsgSuccessCounter = new JT808AtomicCounter();

private static readonly JT808AtomicCounter MsgFailCounter = new JT808AtomicCounter();

public JT808AtomicCounterService()
{

}

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
- 16
src/JT808.DotNetty/Internal/JT808MsgIdDefaultHandler.cs Ver ficheiro

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

namespace JT808.DotNetty.Internal
{
/// <summary>
/// 默认消息处理业务实现
/// </summary>
internal class JT808MsgIdDefaultHandler : JT808MsgIdHandlerBase
{
public JT808MsgIdDefaultHandler(JT808SessionManager sessionManager) : base(sessionManager)
{
}
}
}

+ 0
- 16
src/JT808.DotNetty/Internal/JT808SessionPublishingEmptyImpl.cs Ver ficheiro

@@ -1,16 +0,0 @@
using JT808.DotNetty.Interfaces;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace JT808.DotNetty.Internal
{
internal class JT808SessionPublishingEmptyImpl : IJT808SessionPublishing
{
public Task PublishAsync(string topicName, string key, string value)
{
return Task.CompletedTask;
}
}
}

+ 0
- 75
src/JT808.DotNetty/Internal/JT808SessionPublishingRedisImpl.cs Ver ficheiro

@@ -1,75 +0,0 @@
using JT808.DotNetty.Interfaces;
using System;
using System.Threading.Tasks;
using StackExchange.Redis;
using Microsoft.Extensions.Options;
using JT808.DotNetty.Configurations;

namespace JT808.DotNetty.Internal
{
internal class JT808SessionPublishingRedisImpl : IJT808SessionPublishing,IDisposable
{
private IConnectionMultiplexer connectionMultiplexer;

private IOptionsMonitor<JT808Configuration> optionsMonitor;

private string redisHost;

private IDisposable optionsMonitorDisposable;

public JT808SessionPublishingRedisImpl(
IOptionsMonitor<JT808Configuration> optionsMonitor
)
{
this.optionsMonitor = optionsMonitor;
redisHost = optionsMonitor.CurrentValue.RedisHost;
try
{
connectionMultiplexer = ConnectionMultiplexer.Connect(redisHost);
}
catch
{

}
optionsMonitorDisposable= this.optionsMonitor.OnChange((config,str) =>
{
if(config.RedisHost!= redisHost)
{
redisHost = config.RedisHost;
connectionMultiplexer.Close();
try
{
connectionMultiplexer = ConnectionMultiplexer.Connect(redisHost);
}
catch
{
}
}
});
}

public Task PublishAsync(string topicName, string key, string value)
{
if (connectionMultiplexer.IsConnected)
{
Subscriber?.PublishAsync(topicName, value);
}
return Task.CompletedTask;
}

internal ISubscriber Subscriber
{
get
{
return connectionMultiplexer.GetSubscriber();
}
}

public void Dispose()
{
connectionMultiplexer.Close();
optionsMonitorDisposable.Dispose();
}
}
}

+ 0
- 77
src/JT808.DotNetty/Internal/JT808SessionServiceDefaultImpl.cs Ver ficheiro

@@ -1,77 +0,0 @@
using JT808.DotNetty.Dtos;
using JT808.DotNetty.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.CompilerServices;
using Microsoft.Extensions.Options;
using JT808.DotNetty.Configurations;

namespace JT808.DotNetty.Internal
{
internal class JT808SessionServiceDefaultImpl : IJT808SessionService
{
private readonly JT808SessionManager jT808SessionManager;

public JT808SessionServiceDefaultImpl(
JT808SessionManager jT808SessionManager)
{
this.jT808SessionManager = jT808SessionManager;
}

public JT808ResultDto<List<JT808SessionInfoDto>> GetAll()
{
JT808ResultDto<List<JT808SessionInfoDto>> resultDto = new JT808ResultDto<List<JT808SessionInfoDto>>();
try
{
resultDto.Data = jT808SessionManager.GetAll().Select(s => new JT808SessionInfoDto
{
LastActiveTime = s.LastActiveTime,
StartTime = s.StartTime,
TerminalPhoneNo = s.TerminalPhoneNo,
RemoteAddressIP = s.Channel.RemoteAddress.ToString(),
}).ToList();
resultDto.Code = JT808ResultCode.Ok;
}
catch (Exception ex)
{
resultDto.Data = null;
resultDto.Code = JT808ResultCode.Error;
resultDto.Message = Newtonsoft.Json.JsonConvert.SerializeObject(ex);
}
return resultDto;
}

public JT808ResultDto<bool> RemoveByTerminalPhoneNo(string terminalPhoneNo)
{
JT808ResultDto<bool> resultDto = new JT808ResultDto<bool>();
try
{
var session = jT808SessionManager.RemoveSession(terminalPhoneNo);
if (session != null)
{
if(session.Channel.Open)
{
session.Channel.CloseAsync();
}
}
resultDto.Code = JT808ResultCode.Ok;
resultDto.Data = true;
}
catch (AggregateException ex)
{
resultDto.Data = false;
resultDto.Code = 500;
resultDto.Message = Newtonsoft.Json.JsonConvert.SerializeObject(ex);
}
catch (Exception ex)
{
resultDto.Data = false;
resultDto.Code = JT808ResultCode.Error;
resultDto.Message = Newtonsoft.Json.JsonConvert.SerializeObject(ex);
}
return resultDto;
}
}
}

+ 0
- 290
src/JT808.DotNetty/Internal/JT808SourcePackageChannelService.cs Ver ficheiro

@@ -1,290 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Channels.Sockets;
using JT808.DotNetty.Configurations;
using JT808.DotNetty.Dtos;
using JT808.DotNetty.Handlers;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace JT808.DotNetty.Internal
{
/// <summary>
/// 原包分发器通道服务
/// </summary>
internal class JT808SourcePackageChannelService:IDisposable
{
private readonly IOptionsMonitor<JT808Configuration> jT808ConfigurationOptionsMonitor;

internal readonly ConcurrentDictionary<EndPoint, IChannel> channels;

private readonly ILogger<JT808SourcePackageChannelService> logger;

private readonly MultithreadEventLoopGroup group;

internal readonly ILoggerFactory LoggerFactory;

internal readonly Bootstrap bootstrap;

private IDisposable jT808ConfigurationOptionsMonitorDisposable;

public JT808SourcePackageChannelService(
ILoggerFactory loggerFactory,
IOptionsMonitor<JT808Configuration> jT808ConfigurationOptionsMonitor)
{
this.LoggerFactory = loggerFactory;
this.logger = loggerFactory.CreateLogger<JT808SourcePackageChannelService>();
this.channels = new ConcurrentDictionary<EndPoint, IChannel>();
this.jT808ConfigurationOptionsMonitor = jT808ConfigurationOptionsMonitor;
this.group = new MultithreadEventLoopGroup();
this.bootstrap = new Bootstrap();
jT808ConfigurationOptionsMonitorDisposable = jT808ConfigurationOptionsMonitor.OnChange(options =>
{
List<JT808ClientConfiguration> chgRemoteServers = new List<JT808ClientConfiguration>();
if (jT808ConfigurationOptionsMonitor.CurrentValue.SourcePackageDispatcherClientConfigurations != null && jT808ConfigurationOptionsMonitor.CurrentValue.SourcePackageDispatcherClientConfigurations.Count > 0)
{
chgRemoteServers = options.SourcePackageDispatcherClientConfigurations;
}
DelRemoteServsers(chgRemoteServers);
AddRemoteServsers(chgRemoteServers);
});
StartAsync();
}

/// <summary>
/// 下发数据
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public Task SendAsync(byte[] data)
{
foreach (var item in channels)
{
try
{
if (item.Value.Open && item.Value.Active)
{
item.Value.WriteAndFlushAsync(Unpooled.WrappedBuffer(data));
}
else
{
logger.LogInformation($"{item} link closed.");
}
}
catch (AggregateException ex)
{
logger.LogError(ex, $"{item} Send Data Error.");
}
catch (Exception ex)
{
logger.LogError(ex, $"{item} Send Data Error.");
}
}
return Task.CompletedTask;
}

/// <summary>
/// 获取通道信息集合
/// </summary>
/// <returns></returns>
public JT808ResultDto<List<JT808SourcePackageChannelInfoDto>> GetAll()
{
JT808ResultDto<List<JT808SourcePackageChannelInfoDto>> jT808ResultDto = new JT808ResultDto<List<JT808SourcePackageChannelInfoDto>>();
jT808ResultDto.Data = new List<JT808SourcePackageChannelInfoDto>();
jT808ResultDto.Code = JT808ResultCode.Ok;
foreach (var item in channels)
{
JT808SourcePackageChannelInfoDto jT808SourcePackageChannelInfoDto = new JT808SourcePackageChannelInfoDto();
jT808SourcePackageChannelInfoDto.Active = item.Value.Active;
jT808SourcePackageChannelInfoDto.Open = item.Value.Open;
jT808SourcePackageChannelInfoDto.Registered = item.Value.Registered;
jT808SourcePackageChannelInfoDto.LocalAddress = item.Value.LocalAddress.ToString().Replace("[::ffff:", "").Replace("]", "");
jT808SourcePackageChannelInfoDto.RemoteAddress = item.Value.RemoteAddress.ToString().Replace("[::ffff:", "").Replace("]", "");
jT808ResultDto.Data.Add(jT808SourcePackageChannelInfoDto);
}
return jT808ResultDto;
}

/// <summary>
/// 添加地址
/// </summary>
/// <returns></returns>
public async Task<JT808ResultDto<bool>> Add(JT808IPAddressDto jT808IPAddressDto)
{
JT808ResultDto<bool> jT808ResultDto = new JT808ResultDto<bool>();
jT808ResultDto.Code= JT808ResultCode.Ok;
jT808ResultDto.Data = true;
if (!channels.ContainsKey(jT808IPAddressDto.EndPoint))
{
try
{
IChannel clientChannel = await bootstrap.ConnectAsync(jT808IPAddressDto.EndPoint);
channels.TryAdd(jT808IPAddressDto.EndPoint, clientChannel);
}
catch (AggregateException ex)
{
jT808ResultDto.Data = false;
jT808ResultDto.Code = JT808ResultCode.Error;
jT808ResultDto.Message = JsonConvert.SerializeObject(ex);
}
catch (Exception ex)
{
jT808ResultDto.Data = false;
jT808ResultDto.Code= JT808ResultCode.Error;
jT808ResultDto.Message = JsonConvert.SerializeObject(ex);
}
}
return jT808ResultDto;
}

/// <summary>
/// 删除地址
/// </summary>
/// <returns></returns>
public async Task<JT808ResultDto<bool>> Remove(JT808IPAddressDto jT808IPAddressDto)
{
JT808ResultDto<bool> jT808ResultDto = new JT808ResultDto<bool>();
jT808ResultDto.Code = JT808ResultCode.Ok;
jT808ResultDto.Data = true;

if(jT808ConfigurationOptionsMonitor.CurrentValue.SourcePackageDispatcherClientConfigurations!=null &&
jT808ConfigurationOptionsMonitor.CurrentValue.SourcePackageDispatcherClientConfigurations.Any(a=>a.EndPoint.ToString()== jT808IPAddressDto.EndPoint.ToString())
)
{
jT808ResultDto.Data = false;
jT808ResultDto.Message = "不能删除服务器配置的地址";
}
else
{
if (channels.TryRemove(jT808IPAddressDto.EndPoint, out var channel))
{
try
{
await channel.CloseAsync();
}
catch (AggregateException ex)
{
jT808ResultDto.Data = false;
jT808ResultDto.Code = JT808ResultCode.Error;
jT808ResultDto.Message = JsonConvert.SerializeObject(ex);
}
catch (Exception ex)
{
jT808ResultDto.Data = false;
jT808ResultDto.Code = JT808ResultCode.Error;
jT808ResultDto.Message = JsonConvert.SerializeObject(ex);
}
}
}
return jT808ResultDto;
}

private void StartAsync()
{
bootstrap
.Group(group)
.Channel<TcpSocketChannel>()
.Option(ChannelOption.TcpNodelay, true)
.Handler(new ActionChannelInitializer<IChannel>(channel =>
{
channel.Pipeline.AddLast(new JT808SourcePackageDispatcherHandler(this));
}));
if (jT808ConfigurationOptionsMonitor.CurrentValue.SourcePackageDispatcherClientConfigurations != null &&
jT808ConfigurationOptionsMonitor.CurrentValue.SourcePackageDispatcherClientConfigurations.Count > 0)
{
foreach (var item in jT808ConfigurationOptionsMonitor.CurrentValue.SourcePackageDispatcherClientConfigurations)
{
try
{
Task.Run(async () =>
{
IChannel clientChannel = await bootstrap.ConnectAsync(item.EndPoint);
channels.TryAdd(item.EndPoint, clientChannel);
logger.LogInformation($"init remote link {item.EndPoint.ToString()}.");
});
}
catch (Exception ex)
{
logger.LogError(ex, $"there is an exception in sending data {item}.");
}
}
}
}

private Task StopAsync()
{
foreach (var channel in channels)
{
try
{
channel.Value.CloseAsync();
}
catch
{

}
}
group.ShutdownGracefullyAsync(jT808ConfigurationOptionsMonitor.CurrentValue.QuietPeriodTimeSpan, jT808ConfigurationOptionsMonitor.CurrentValue.ShutdownTimeoutTimeSpan);
return Task.CompletedTask;
}

/// <summary>
/// 动态删除远程服务器
/// </summary>
/// <param name="chgRemoteServers"></param>
private void DelRemoteServsers(List<JT808ClientConfiguration> chgRemoteServers)
{
var delChannels = channels.Keys.Except(chgRemoteServers.Select(s => s.EndPoint)).ToList();
foreach (var item in delChannels)
{
try
{
channels.TryRemove(item, out var channel);
channel.CloseAsync();
}
catch
{

}
}
}

/// <summary>
/// 动态添加远程服务器
/// </summary>
/// <param name="bootstrap"></param>
/// <param name="chgRemoteServers"></param>
private async void AddRemoteServsers(List<JT808ClientConfiguration> chgRemoteServers)
{
var addChannels = chgRemoteServers.Select(s => s.EndPoint).Except(channels.Keys).ToList();
foreach (var item in addChannels)
{
try
{
IChannel clientChannel = await bootstrap.ConnectAsync(item);
channels.TryAdd(item, clientChannel);
logger.LogInformation($"link to the remote server after the change {item}.");
}
catch (Exception ex)
{
logger.LogError(ex, $"reconnect the remote server after the exception changes {item}.");
}
}
}

public void Dispose()
{
jT808ConfigurationOptionsMonitorDisposable.Dispose();
StopAsync();
}
}
}

+ 0
- 39
src/JT808.DotNetty/Internal/JT808SourcePackageDispatcherDefaultImpl.cs Ver ficheiro

@@ -1,39 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Channels.Sockets;
using JT808.DotNetty.Configurations;
using JT808.DotNetty.Handlers;
using JT808.DotNetty.Interfaces;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace JT808.DotNetty.Internal
{
/// <summary>
/// 原包分发器默认实现
/// </summary>
internal class JT808SourcePackageDispatcherDefaultImpl : IJT808SourcePackageDispatcher
{
private readonly JT808SourcePackageChannelService jT808SourcePackageChannelService;

public JT808SourcePackageDispatcherDefaultImpl(JT808SourcePackageChannelService jT808SourcePackageChannelService)
{
this.jT808SourcePackageChannelService = jT808SourcePackageChannelService;
}

public async Task SendAsync(byte[] data)
{
await jT808SourcePackageChannelService.SendAsync(data);
}
}
}

+ 0
- 88
src/JT808.DotNetty/Internal/JT808TransmitAddressFilterService.cs Ver ficheiro

@@ -1,88 +0,0 @@
using JT808.DotNetty.Configurations;
using JT808.DotNetty.Dtos;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net;

namespace JT808.DotNetty.Internal
{
/// <summary>
/// JT808转发地址过滤服务
/// 按照808的消息,有些请求必须要应答,但是转发可以不需要有应答可以节省部分资源包括:
// 1.消息的序列化
// 2.消息的下发
// 都有一定的性能损耗,那么不需要判断写超时 IdleState.WriterIdle
// 就跟神兽貔貅一样。。。
/// </summary>
public class JT808TransmitAddressFilterService : IDisposable
{
private readonly IOptionsMonitor<JT808Configuration> jT808ConfigurationOptionsMonitor;

private ConcurrentDictionary<string,int> ForwardingRemoteAddresssDict;

private IDisposable jT808ConfigurationOptionsMonitorDisposable;

public JT808TransmitAddressFilterService(
IOptionsMonitor<JT808Configuration> jT808ConfigurationOptionsMonitor)
{
this.jT808ConfigurationOptionsMonitor = jT808ConfigurationOptionsMonitor;
ForwardingRemoteAddresssDict = new ConcurrentDictionary<string, int>();
InitForwardingRemoteAddress(jT808ConfigurationOptionsMonitor.CurrentValue.ForwardingRemoteAddress);
//OnChange 源码多播委托
jT808ConfigurationOptionsMonitorDisposable = this.jT808ConfigurationOptionsMonitor.OnChange(options =>
{
InitForwardingRemoteAddress(options.ForwardingRemoteAddress);
});
}

private void InitForwardingRemoteAddress(List<JT808ClientConfiguration> jT808ClientConfigurations)
{
if (jT808ClientConfigurations != null && jT808ClientConfigurations.Count > 0)
{
foreach (var item in jT808ClientConfigurations)
{
string host = item.EndPoint.ToString();
ForwardingRemoteAddresssDict.TryAdd(host, 0);
}
}
}

public bool ContainsKey(EndPoint endPoint)
{
return ForwardingRemoteAddresssDict.ContainsKey(endPoint.ToString());
}

public JT808ResultDto<bool> Add(JT808IPAddressDto jT808IPAddressDto)
{
string host = jT808IPAddressDto.EndPoint.ToString();
return new JT808ResultDto<bool>() { Code = JT808ResultCode.Ok, Data = ForwardingRemoteAddresssDict.TryAdd(host,0) };
}

public JT808ResultDto<bool> Remove(JT808IPAddressDto jT808IPAddressDto)
{
string host = jT808IPAddressDto.EndPoint.ToString();
if(jT808ConfigurationOptionsMonitor.CurrentValue.ForwardingRemoteAddress!=null &&
jT808ConfigurationOptionsMonitor.CurrentValue.ForwardingRemoteAddress.Any(w=>w.EndPoint.ToString()== host))
{
return new JT808ResultDto<bool>() { Code = JT808ResultCode.Ok, Data = false,Message="不能删除服务器配置的地址" };
}
else
{
return new JT808ResultDto<bool>() { Code = JT808ResultCode.Ok, Data = ForwardingRemoteAddresssDict.TryRemove(host,out var temp) };
}
}

public JT808ResultDto<List<string>> GetAll()
{
return new JT808ResultDto<List<string>>(){ Code = JT808ResultCode.Ok, Data = ForwardingRemoteAddresssDict.Select(s=>s.Key).ToList() };
}

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

+ 0
- 56
src/JT808.DotNetty/Internal/JT808UnificationSendServiceDefaultImpl.cs Ver ficheiro

@@ -1,56 +0,0 @@
using DotNetty.Buffers;
using JT808.DotNetty.Dtos;
using JT808.DotNetty.Interfaces;
using System;
using System.Collections.Generic;
using System.Text;

namespace JT808.DotNetty.Internal
{
internal class JT808UnificationSendServiceDefaultImpl : IJT808UnificationSendService
{
private readonly JT808SessionManager jT808SessionManager;

public JT808UnificationSendServiceDefaultImpl(JT808SessionManager jT808SessionManager)
{
this.jT808SessionManager = jT808SessionManager;
}

public JT808ResultDto<bool> Send(string terminalPhoneNo, byte[] data)
{
JT808ResultDto<bool> resultDto = new JT808ResultDto<bool>();
try
{
var session = jT808SessionManager.GetSession(terminalPhoneNo);
if (session != null)
{
if (session.Channel.Open)
{
session.Channel.WriteAndFlushAsync(Unpooled.WrappedBuffer(data));
resultDto.Code = JT808ResultCode.Ok;
resultDto.Data = true;
}
else
{
resultDto.Code = JT808ResultCode.Ok;
resultDto.Data = false;
resultDto.Message = "offline";
}
}
else
{
resultDto.Code = JT808ResultCode.Ok;
resultDto.Data = false;
resultDto.Message = "offline";
}
}
catch (Exception ex)
{
resultDto.Data = false;
resultDto.Code = JT808ResultCode.Error;
resultDto.Message = Newtonsoft.Json.JsonConvert.SerializeObject(ex);
}
return resultDto;
}
}
}

+ 0
- 253
src/JT808.DotNetty/Internal/JT808WebAPIService.cs Ver ficheiro

@@ -1,253 +0,0 @@
using JT808.DotNetty.Dtos;
using JT808.DotNetty.Interfaces;
using JT808.DotNetty.Metadata;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Text;

namespace JT808.DotNetty.Internal
{
/// <summary>
/// JT808 WebApi 业务服务
/// </summary>
internal class JT808WebAPIService
{
public Dictionary<string, Func<JT808HttpRequest, JT808HttpResponse>> HandlerDict { get; protected set; }

private const string RouteTablePrefix = "/jt808api";

private const string sessionRoutePrefix = "Session";

private const string sourcePackagePrefix = "SourcePackage";

private const string transmitPrefix = "Transmit";
private readonly IJT808SessionService jT808SessionService;

private readonly IJT808UnificationSendService jT808UnificationSendService;

private readonly JT808AtomicCounterService jT808AtomicCounterService;

private readonly JT808SourcePackageChannelService jT808SourcePackageChannelService;

private readonly JT808TransmitAddressFilterService jT808TransmitAddressFilterService;

/// <summary>
/// 初始化消息处理业务
/// </summary>
public JT808WebAPIService(
JT808AtomicCounterService jT808AtomicCounterService,
JT808SourcePackageChannelService jT808SourcePackageChannelService,
JT808TransmitAddressFilterService jT808TransmitAddressFilterService,
IJT808SessionService jT808SessionService,
IJT808UnificationSendService jT808UnificationSendService)
{
this.jT808AtomicCounterService = jT808AtomicCounterService;
this.jT808SourcePackageChannelService = jT808SourcePackageChannelService;
this.jT808TransmitAddressFilterService = jT808TransmitAddressFilterService;
this.jT808SessionService = jT808SessionService;
this.jT808UnificationSendService = jT808UnificationSendService;
HandlerDict = new Dictionary<string, Func<JT808HttpRequest, JT808HttpResponse>>
{
{$"{RouteTablePrefix}/UnificationSend", UnificationSend},
{$"{RouteTablePrefix}/{sessionRoutePrefix}/GetAll", GetSessionAll},
{$"{RouteTablePrefix}/{sessionRoutePrefix}/RemoveByTerminalPhoneNo", RemoveByTerminalPhoneNo},
{$"{RouteTablePrefix}/GetAtomicCounter", GetAtomicCounter},
{$"{RouteTablePrefix}/{sourcePackagePrefix}/Add", AddSourcePackageAddress},
{$"{RouteTablePrefix}/{sourcePackagePrefix}/Remove", RemoveSourcePackageAddress},
{$"{RouteTablePrefix}/{sourcePackagePrefix}/GetAll", GetSourcePackageAll},
{$"{RouteTablePrefix}/{transmitPrefix}/Add", AddTransmitAddress},
{$"{RouteTablePrefix}/{transmitPrefix}/Remove", RemoveTransmitAddress},
{$"{RouteTablePrefix}/{transmitPrefix}/GetAll", GetTransmitAll},
};
}

/// <summary>
/// 统一下发信息
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public JT808HttpResponse UnificationSend(JT808HttpRequest request)
{
if (string.IsNullOrEmpty(request.Json))
{
return EmptyHttpResponse();
}
JT808UnificationSendRequestDto jT808UnificationSendRequestDto = JsonConvert.DeserializeObject<JT808UnificationSendRequestDto>(request.Json);
var result = jT808UnificationSendService.Send(jT808UnificationSendRequestDto.TerminalPhoneNo, jT808UnificationSendRequestDto.Data);
return CreateJT808HttpResponse(result);
}

/// <summary>
/// 会话服务集合
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public JT808HttpResponse GetSessionAll(JT808HttpRequest request)
{
var result = jT808SessionService.GetAll();
return CreateJT808HttpResponse(result);
}

/// <summary>
/// 会话服务-通过设备终端号移除对应会话
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public JT808HttpResponse RemoveByTerminalPhoneNo(JT808HttpRequest request)
{
if (string.IsNullOrEmpty(request.Json))
{
return EmptyHttpResponse();
}
var result = jT808SessionService.RemoveByTerminalPhoneNo(request.Json);
return CreateJT808HttpResponse(result);
}

/// <summary>
/// 获取包计数器
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public JT808HttpResponse GetAtomicCounter(JT808HttpRequest request)
{
JT808AtomicCounterDto jT808AtomicCounterDto = new JT808AtomicCounterDto();
jT808AtomicCounterDto.MsgFailCount = jT808AtomicCounterService.MsgFailCount;
jT808AtomicCounterDto.MsgSuccessCount = jT808AtomicCounterService.MsgSuccessCount;
return CreateJT808HttpResponse(new JT808ResultDto<JT808AtomicCounterDto>
{
Code=JT808ResultCode.Ok,
Data= jT808AtomicCounterDto
});
}

/// <summary>
/// 添加原包转发地址
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public JT808HttpResponse AddSourcePackageAddress(JT808HttpRequest request)
{
if (string.IsNullOrEmpty(request.Json))
{
return EmptyHttpResponse();
}
JT808IPAddressDto jT808IPAddressDto = JsonConvert.DeserializeObject<JT808IPAddressDto>(request.Json);
return CreateJT808HttpResponse(jT808SourcePackageChannelService.Add(jT808IPAddressDto).Result);
}

/// <summary>
/// 删除原包转发地址(不能删除在网关服务器配置文件配的地址)
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public JT808HttpResponse RemoveSourcePackageAddress(JT808HttpRequest request)
{
if (string.IsNullOrEmpty(request.Json))
{
return EmptyHttpResponse();
}
JT808IPAddressDto jT808IPAddressDto = JsonConvert.DeserializeObject<JT808IPAddressDto>(request.Json);
return CreateJT808HttpResponse(jT808SourcePackageChannelService.Remove(jT808IPAddressDto).Result);
}

/// <summary>
/// 获取原包信息集合
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public JT808HttpResponse GetSourcePackageAll(JT808HttpRequest request)
{
return CreateJT808HttpResponse(jT808SourcePackageChannelService.GetAll());
}

/// <summary>
/// 添加转发过滤地址
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public JT808HttpResponse AddTransmitAddress(JT808HttpRequest request)
{
if (string.IsNullOrEmpty(request.Json))
{
return EmptyHttpResponse();
}
JT808IPAddressDto jT808IPAddressDto = JsonConvert.DeserializeObject<JT808IPAddressDto>(request.Json);
return CreateJT808HttpResponse(jT808TransmitAddressFilterService.Add(jT808IPAddressDto));
}

/// <summary>
/// 删除转发过滤地址(不能删除在网关服务器配置文件配的地址)
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public JT808HttpResponse RemoveTransmitAddress(JT808HttpRequest request)
{
if (string.IsNullOrEmpty(request.Json))
{
return EmptyHttpResponse();
}
JT808IPAddressDto jT808IPAddressDto = JsonConvert.DeserializeObject<JT808IPAddressDto>(request.Json);
return CreateJT808HttpResponse(jT808TransmitAddressFilterService.Remove(jT808IPAddressDto));
}

/// <summary>
/// 获取转发过滤地址信息集合
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public JT808HttpResponse GetTransmitAll(JT808HttpRequest request)
{
return CreateJT808HttpResponse(jT808TransmitAddressFilterService.GetAll());
}

private JT808HttpResponse CreateJT808HttpResponse(dynamic dynamicObject)
{
byte[] data = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(dynamicObject));
return new JT808HttpResponse()
{
Data = data
};
}

public JT808HttpResponse DefaultHttpResponse()
{
byte[] json = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new JT808DefaultResultDto()));
return new JT808HttpResponse(json);
}

public JT808HttpResponse EmptyHttpResponse()
{
byte[] json = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new JT808ResultDto<string>()
{
Code = JT808ResultCode.Empty,
Message ="内容为空",
Data="Content Empty"
}));
return new JT808HttpResponse(json);
}

public JT808HttpResponse NotFoundHttpResponse()
{
byte[] json = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new JT808ResultDto<string>()
{
Code= JT808ResultCode.NotFound,
Message="没有该服务",
Data= "没有该服务"
}));
return new JT808HttpResponse(json);
}

public JT808HttpResponse ErrorHttpResponse(Exception ex)
{
byte[] json = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new JT808ResultDto<string>()
{
Code = JT808ResultCode.Error,
Message = JsonConvert.SerializeObject(ex),
Data= ex.Message
}));
return new JT808HttpResponse(json);
}
}
}

+ 0
- 46
src/JT808.DotNetty/JT808.DotNetty.csproj Ver ficheiro

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

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>latest</LangVersion>
<Copyright>Copyright 2018.</Copyright>
<Authors>SmallChi</Authors>
<PackageId>JT808DotNetty</PackageId>
<Product>JT808DotNetty</Product>
<Description>基于DotNetty封装的JT808DotNetty专注消息业务处理</Description>
<PackageReleaseNotes>基于DotNetty封装的JT808DotNetty专注消息业务处理</PackageReleaseNotes>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<RepositoryUrl>https://github.com/SmallChi/JT808DotNetty</RepositoryUrl>
<PackageProjectUrl>https://github.com/SmallChi/JT808DotNetty</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/SmallChi/JT808DotNetty/blob/master/LICENSE</PackageLicenseUrl>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Version>1.0.0</Version>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile></DocumentationFile>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DocumentationFile>E:\koike\My Project\JT808DotNetty\src\JT808.DotNetty\JT808.DotNetty.xml</DocumentationFile>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="DotNetty.Codecs" Version="0.6.0" />
<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="Microsoft.Extensions.DependencyInjection.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.2.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
<PackageReference Include="Polly" Version="6.1.2" />
<PackageReference Include="StackExchange.Redis" Version="2.0.519" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\JT808.Protocol\src\JT808.Protocol\JT808.Protocol.csproj" />
</ItemGroup>

</Project>

+ 0
- 418
src/JT808.DotNetty/JT808.DotNetty.xml Ver ficheiro

@@ -1,418 +0,0 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>JT808.DotNetty</name>
</assembly>
<members>
<member name="T:JT808.DotNetty.Codecs.JT808ClientDecoder">
<summary>
JT808客户端解码(测试客户端)
</summary>
</member>
<member name="T:JT808.DotNetty.Codecs.JT808Decoder">
<summary>
JT808解码
</summary>
</member>
<member name="P:JT808.DotNetty.Configurations.JT808Configuration.WebApiPort">
<summary>
WebApi服务
默认828端口
</summary>
</member>
<member name="P:JT808.DotNetty.Configurations.JT808Configuration.SourcePackageDispatcherClientConfigurations">
<summary>
源包分发器配置
</summary>
</member>
<!-- 对于成员“P:JT808.DotNetty.Configurations.JT808Configuration.ForwardingRemoteAddress”忽略有格式错误的 XML 注释 -->
<member name="T:JT808.DotNetty.Dtos.JT808AtomicCounterDto">
<summary>
包计数器服务
</summary>
</member>
<member name="P:JT808.DotNetty.Dtos.JT808SessionInfoDto.ChannelId">
<summary>
通道Id
</summary>
</member>
<member name="P:JT808.DotNetty.Dtos.JT808SessionInfoDto.LastActiveTime">
<summary>
最后上线时间
</summary>
</member>
<member name="P:JT808.DotNetty.Dtos.JT808SessionInfoDto.StartTime">
<summary>
上线时间
</summary>
</member>
<member name="P:JT808.DotNetty.Dtos.JT808SessionInfoDto.TerminalPhoneNo">
<summary>
终端手机号
</summary>
</member>
<member name="P:JT808.DotNetty.Dtos.JT808SessionInfoDto.LoaclAddressIP">
<summary>
本地ip地址
</summary>
</member>
<member name="P:JT808.DotNetty.Dtos.JT808SessionInfoDto.WebApiPort">
<summary>
WebApi端口号
</summary>
</member>
<member name="P:JT808.DotNetty.Dtos.JT808SessionInfoDto.RemoteAddressIP">
<summary>
远程ip地址
</summary>
</member>
<member name="T:JT808.DotNetty.Dtos.JT808SourcePackageChannelInfoDto">
<summary>
原包通道信息
</summary>
</member>
<member name="P:JT808.DotNetty.Dtos.JT808SourcePackageChannelInfoDto.RemoteAddress">
<summary>
远程地址
</summary>
</member>
<member name="P:JT808.DotNetty.Dtos.JT808SourcePackageChannelInfoDto.LocalAddress">
<summary>
本地地址
</summary>
</member>
<member name="P:JT808.DotNetty.Dtos.JT808SourcePackageChannelInfoDto.Registered">
<summary>
是否注册
</summary>
</member>
<member name="P:JT808.DotNetty.Dtos.JT808SourcePackageChannelInfoDto.Active">
<summary>
是否活动
</summary>
</member>
<member name="P:JT808.DotNetty.Dtos.JT808SourcePackageChannelInfoDto.Open">
<summary>
是否打开
</summary>
</member>
<member name="T:JT808.DotNetty.Dtos.JT808UnificationSendRequestDto">
<summary>
统一下发请求参数
</summary>
</member>
<member name="M:JT808.DotNetty.Handlers.JT808ConnectionHandler.ChannelActive(DotNetty.Transport.Channels.IChannelHandlerContext)">
<summary>
通道激活
</summary>
<param name="context"></param>
</member>
<member name="M:JT808.DotNetty.Handlers.JT808ConnectionHandler.ChannelInactive(DotNetty.Transport.Channels.IChannelHandlerContext)">
<summary>
设备主动断开
</summary>
<param name="context"></param>
</member>
<member name="M:JT808.DotNetty.Handlers.JT808ConnectionHandler.CloseAsync(DotNetty.Transport.Channels.IChannelHandlerContext)">
<summary>
服务器主动断开
</summary>
<param name="context"></param>
<returns></returns>
</member>
<member name="M:JT808.DotNetty.Handlers.JT808ConnectionHandler.UserEventTriggered(DotNetty.Transport.Channels.IChannelHandlerContext,System.Object)">
<summary>
超时策略
</summary>
<param name="context"></param>
<param name="evt"></param>
</member>
<member name="T:JT808.DotNetty.Handlers.JT808WebAPIServerHandler">
<summary>
jt808 webapi服务
请求量不大,只支持JSON格式并且只支持post发数据
ref: dotnetty HttpServer
</summary>
</member>
<member name="T:JT808.DotNetty.Interfaces.IJT808SessionService">
<summary>
JT808会话服务
</summary>
</member>
<member name="M:JT808.DotNetty.Interfaces.IJT808SessionService.GetAll">
<summary>
获取会话集合
</summary>
<returns></returns>
</member>
<member name="M:JT808.DotNetty.Interfaces.IJT808SessionService.RemoveByChannelId(System.String)">
<summary>
通过通道Id移除对应会话
</summary>
<param name="channelId"></param>
<returns></returns>
</member>
<member name="M:JT808.DotNetty.Interfaces.IJT808SessionService.RemoveByTerminalPhoneNo(System.String)">
<summary>
通过设备终端号移除对应会话
</summary>
<param name="terminalPhoneNo"></param>
<returns></returns>
</member>
<member name="T:JT808.DotNetty.Interfaces.IJT808SourcePackageDispatcher">
<summary>
源包分发器
自定义源包分发器业务
ConfigureServices:
services.Replace(new ServiceDescriptor(typeof(IJT808SourcePackageDispatcher),typeof(JT808SourcePackageDispatcherDefaultImpl),ServiceLifetime.Singleton));
</summary>
</member>
<member name="T:JT808.DotNetty.Interfaces.IJT808UnificationSendService">
<summary>
JT808统一下发命令
</summary>
</member>
<member name="T:JT808.DotNetty.Internal.JT808AtomicCounterService">
<summary>
计数包服务
</summary>
</member>
<member name="T:JT808.DotNetty.Internal.JT808MsgIdDefaultHandler">
<summary>
默认消息处理业务实现
</summary>
</member>
<!-- 对于成员“T:JT808.DotNetty.Internal.JT808RemoteAddressTransmitConfigurationService”忽略有格式错误的 XML 注释 -->
<member name="T:JT808.DotNetty.Internal.JT808SourcePackageChannelService">
<summary>
原包分发器通道服务
</summary>
</member>
<member name="M:JT808.DotNetty.Internal.JT808SourcePackageChannelService.SendAsync(System.Byte[])">
<summary>
下发数据
</summary>
<param name="data"></param>
<returns></returns>
</member>
<member name="M:JT808.DotNetty.Internal.JT808SourcePackageChannelService.GetAll">
<summary>
获取通道信息集合
</summary>
<returns></returns>
</member>
<member name="M:JT808.DotNetty.Internal.JT808SourcePackageChannelService.Add(JT808.DotNetty.Dtos.JT808IPAddressDto)">
<summary>
添加地址
</summary>
<returns></returns>
</member>
<member name="M:JT808.DotNetty.Internal.JT808SourcePackageChannelService.Remove(JT808.DotNetty.Dtos.JT808IPAddressDto)">
<summary>
删除地址
</summary>
<returns></returns>
</member>
<member name="M:JT808.DotNetty.Internal.JT808SourcePackageChannelService.DelRemoteServsers(System.Collections.Generic.List{JT808.DotNetty.Configurations.JT808ClientConfiguration})">
<summary>
动态删除远程服务器
</summary>
<param name="chgRemoteServers"></param>
</member>
<member name="M:JT808.DotNetty.Internal.JT808SourcePackageChannelService.AddRemoteServsers(System.Collections.Generic.List{JT808.DotNetty.Configurations.JT808ClientConfiguration})">
<summary>
动态添加远程服务器
</summary>
<param name="bootstrap"></param>
<param name="chgRemoteServers"></param>
</member>
<member name="T:JT808.DotNetty.Internal.JT808SourcePackageDispatcherDefaultImpl">
<summary>
原包分发器默认实现
</summary>
</member>
<member name="M:JT808.DotNetty.Internal.JT808WebAPIService.#ctor(JT808.DotNetty.Internal.JT808AtomicCounterService,JT808.DotNetty.Internal.JT808SourcePackageChannelService,JT808.DotNetty.Interfaces.IJT808SessionService,JT808.DotNetty.Interfaces.IJT808UnificationSendService)">
<summary>
初始化消息处理业务
</summary>
</member>
<member name="M:JT808.DotNetty.Internal.JT808WebAPIService.UnificationSend(JT808.DotNetty.Metadata.JT808HttpRequest)">
<summary>
统一下发信息
</summary>
<param name="request"></param>
<returns></returns>
</member>
<member name="M:JT808.DotNetty.Internal.JT808WebAPIService.GetSessionAll(JT808.DotNetty.Metadata.JT808HttpRequest)">
<summary>
会话服务集合
</summary>
<param name="request"></param>
<returns></returns>
</member>
<member name="M:JT808.DotNetty.Internal.JT808WebAPIService.RemoveByChannelId(JT808.DotNetty.Metadata.JT808HttpRequest)">
<summary>
会话服务-通过通道Id移除对应会话
</summary>
<param name="request"></param>
<returns></returns>
</member>
<member name="M:JT808.DotNetty.Internal.JT808WebAPIService.RemoveByTerminalPhoneNo(JT808.DotNetty.Metadata.JT808HttpRequest)">
<summary>
会话服务-通过设备终端号移除对应会话
</summary>
<param name="request"></param>
<returns></returns>
</member>
<member name="M:JT808.DotNetty.Internal.JT808WebAPIService.GetAtomicCounter(JT808.DotNetty.Metadata.JT808HttpRequest)">
<summary>
获取包计数器
</summary>
<param name="request"></param>
<returns></returns>
</member>
<member name="M:JT808.DotNetty.Internal.JT808WebAPIService.AddSourcePackageAddress(JT808.DotNetty.Metadata.JT808HttpRequest)">
<summary>
添加原包转发地址
</summary>
<param name="request"></param>
<returns></returns>
</member>
<member name="M:JT808.DotNetty.Internal.JT808WebAPIService.RemoveSourcePackageAddress(JT808.DotNetty.Metadata.JT808HttpRequest)">
<summary>
删除原包转发地址(不能删除在网关服务器配置文件配的地址)
</summary>
<param name="request"></param>
<returns></returns>
</member>
<member name="M:JT808.DotNetty.Internal.JT808WebAPIService.GetSourcePackageAll(JT808.DotNetty.Metadata.JT808HttpRequest)">
<summary>
获取原包信息集合
</summary>
<param name="request"></param>
<returns></returns>
</member>
<member name="T:JT808.DotNetty.JT808MsgIdHandlerBase">
<summary>
抽象消息处理业务
自定义消息处理业务
ConfigureServices:
services.Replace(new ServiceDescriptor(typeof(JT808MsgIdHandlerBase),typeof(JT808MsgIdCustomHandlerImpl),ServiceLifetime.Singleton));
</summary>
</member>
<member name="M:JT808.DotNetty.JT808MsgIdHandlerBase.#ctor(JT808.DotNetty.JT808SessionManager)">
<summary>
初始化消息处理业务
</summary>
</member>
<member name="M:JT808.DotNetty.JT808MsgIdHandlerBase.Msg0x0001(JT808.DotNetty.Metadata.JT808Request)">
<summary>
终端通用应答
</summary>
<param name="reqJT808Package"></param>
<param name="ctx"></param>
<returns></returns>
</member>
<member name="M:JT808.DotNetty.JT808MsgIdHandlerBase.Msg0x0002(JT808.DotNetty.Metadata.JT808Request)">
<summary>
终端心跳
</summary>
<param name="reqJT808Package"></param>
<param name="ctx"></param>
<returns></returns>
</member>
<member name="M:JT808.DotNetty.JT808MsgIdHandlerBase.Msg0x0003(JT808.DotNetty.Metadata.JT808Request)">
<summary>
终端注销
</summary>
<param name="reqJT808Package"></param>
<param name="ctx"></param>
<returns></returns>
</member>
<member name="M:JT808.DotNetty.JT808MsgIdHandlerBase.Msg0x0100(JT808.DotNetty.Metadata.JT808Request)">
<summary>
终端注册
</summary>
<param name="reqJT808Package"></param>
<param name="ctx"></param>
<returns></returns>
</member>
<member name="M:JT808.DotNetty.JT808MsgIdHandlerBase.Msg0x0102(JT808.DotNetty.Metadata.JT808Request)">
<summary>
终端鉴权
</summary>
<param name="reqJT808Package"></param>
<param name="ctx"></param>
<returns></returns>
</member>
<member name="M:JT808.DotNetty.JT808MsgIdHandlerBase.Msg0x0200(JT808.DotNetty.Metadata.JT808Request)">
<summary>
位置信息汇报
</summary>
<param name="reqJT808Package"></param>
<param name="ctx"></param>
<returns></returns>
</member>
<member name="M:JT808.DotNetty.JT808MsgIdHandlerBase.Msg0x0704(JT808.DotNetty.Metadata.JT808Request)">
<summary>
定位数据批量上传
</summary>
<param name="reqJT808Package"></param>
<param name="ctx"></param>
<returns></returns>
</member>
<member name="M:JT808.DotNetty.JT808MsgIdHandlerBase.Msg0x0900(JT808.DotNetty.Metadata.JT808Request)">
<summary>
数据上行透传
</summary>
<param name="reqJT808Package"></param>
<param name="ctx"></param>
<returns></returns>
</member>
<member name="F:JT808.DotNetty.JT808SessionManager.SessionIdDict">
<summary>
Netty生成的sessionID和Session的对应关系
key = seession id
value = Session
</summary>
</member>
<member name="F:JT808.DotNetty.JT808SessionManager.TerminalPhoneNo_SessionId_Dict">
<summary>
终端手机号和netty生成的sessionID的对应关系
key = 终端手机号
value = seession id
</summary>
</member>
<member name="P:JT808.DotNetty.JT808SessionManager.RealSessionCount">
<summary>
获取实际连接数
</summary>
</member>
<member name="P:JT808.DotNetty.JT808SessionManager.RelevanceSessionCount">
<summary>
获取设备相关连的连接数
</summary>
</member>
<member name="T:JT808.DotNetty.JT808WebAPIServerHost">
<summary>
集成一个webapi服务
</summary>
</member>
<member name="T:JT808.DotNetty.Metadata.JT808AtomicCounter">
<summary>
<see cref="!:Grpc.Core.Internal"/>
</summary>
</member>
<member name="P:JT808.DotNetty.Metadata.JT808Response.MinBufferSize">
<summary>
根据实际情况适当调整包的大小
</summary>
</member>
<member name="P:JT808.DotNetty.Metadata.JT808Session.TerminalPhoneNo">
<summary>
终端手机号
</summary>
</member>
</members>
</doc>

+ 0
- 13
src/JT808.DotNetty/JT808Constants.cs Ver ficheiro

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

namespace JT808.DotNetty
{
public static class JT808Constants
{
public const string SessionOnline= "JT808SessionOnline";

public const string SessionOffline = "JT808SessionOffline";
}
}

+ 0
- 58
src/JT808.DotNetty/JT808DotnettyExtensions.cs Ver ficheiro

@@ -1,58 +0,0 @@
using JT808.DotNetty.Codecs;
using JT808.DotNetty.Configurations;
using JT808.DotNetty.Handlers;
using JT808.DotNetty.Interfaces;
using JT808.DotNetty.Internal;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json;
using System;
using System.Reflection;
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("JT808.DotNetty.Test")]
namespace JT808.DotNetty
{
public static class JT808DotnettyExtensions
{
static JT808DotnettyExtensions()
{
JsonSerializerSettings setting = new JsonSerializerSettings();
JsonConvert.DefaultSettings = new Func<JsonSerializerSettings>(() =>
{
//日期类型默认格式化处理
setting.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
setting.DateFormatHandling = Newtonsoft.Json.DateFormatHandling.MicrosoftDateFormat;
setting.DateFormatString = "yyyy-MM-dd HH:mm:ss";
setting.NullValueHandling = NullValueHandling.Include;
return setting;
});
}

public static IHostBuilder UseJT808Host(this IHostBuilder builder)
{
return builder.ConfigureServices((hostContext, services) =>
{
services.Configure<JT808Configuration>(hostContext.Configuration.GetSection("JT808Configuration"));
services.TryAddSingleton<IJT808SessionPublishing, JT808SessionPublishingEmptyImpl>();
services.TryAddSingleton<JT808SessionManager>();
services.TryAddSingleton<JT808AtomicCounterService>();
services.TryAddSingleton<JT808TransmitAddressFilterService>();
services.TryAddSingleton<JT808MsgIdHandlerBase,JT808MsgIdDefaultHandler>();
services.TryAddSingleton<JT808SourcePackageChannelService>();
services.TryAddSingleton<IJT808SourcePackageDispatcher, JT808SourcePackageDispatcherDefaultImpl>();
services.TryAddScoped<JT808ConnectionHandler>();
services.TryAddScoped<JT808Decoder>();
services.TryAddScoped<JT808ServerHandler>();
services.TryAddScoped<JT808UDPServerHandler>();
services.TryAddSingleton<IJT808SessionService, JT808SessionServiceDefaultImpl>();
services.TryAddSingleton<IJT808UnificationSendService, JT808UnificationSendServiceDefaultImpl>();
services.TryAddSingleton<JT808WebAPIService>();
services.TryAddScoped<JT808WebAPIServerHandler>();
services.AddHostedService<JT808ServerHost>();
services.AddHostedService<JT808WebAPIServerHost>();
});
}
}
}

+ 0
- 160
src/JT808.DotNetty/JT808MsgIdHandlerBase.cs Ver ficheiro

@@ -1,160 +0,0 @@
using System;
using System.Collections.Generic;
using JT808.DotNetty.Metadata;
using JT808.Protocol.Enums;
using JT808.Protocol.Extensions;
using JT808.Protocol.MessageBody;

namespace JT808.DotNetty
{
/// <summary>
/// 抽象消息处理业务
/// 自定义消息处理业务
/// 注意:
/// 1.ConfigureServices:
/// services.Replace(new ServiceDescriptor(typeof(JT808MsgIdHandlerBase),typeof(JT808MsgIdCustomHandlerImpl),ServiceLifetime.Singleton));
/// 2.解析具体的消息体,具体消息调用具体的JT808Serializer.Deserialize<T>
/// </summary>
public abstract class JT808MsgIdHandlerBase
{
protected JT808SessionManager sessionManager { get; }
/// <summary>
/// 初始化消息处理业务
/// </summary>
protected JT808MsgIdHandlerBase(JT808SessionManager sessionManager)
{
this.sessionManager = sessionManager;
HandlerDict = new Dictionary<ushort, Func<JT808Request, JT808Response>>
{
{JT808MsgId.终端通用应答.ToUInt16Value(), Msg0x0001},
{JT808MsgId.终端鉴权.ToUInt16Value(), Msg0x0102},
{JT808MsgId.终端心跳.ToUInt16Value(), Msg0x0002},
{JT808MsgId.终端注销.ToUInt16Value(), Msg0x0003},
{JT808MsgId.终端注册.ToUInt16Value(), Msg0x0100},
{JT808MsgId.位置信息汇报.ToUInt16Value(),Msg0x0200 },
{JT808MsgId.定位数据批量上传.ToUInt16Value(),Msg0x0704 },
{JT808MsgId.数据上行透传.ToUInt16Value(),Msg0x0900 }
};
}

public Dictionary<ushort, Func<JT808Request, JT808Response>> HandlerDict { get; protected set; }
/// <summary>
/// 终端通用应答
/// 平台无需回复
/// 实现自己的业务
/// </summary>
/// <param name="reqJT808Package"></param>
/// <param name="ctx"></param>
/// <returns></returns>
public virtual JT808Response Msg0x0001(JT808Request request)
{
return null;
}
/// <summary>
/// 终端心跳
/// </summary>
/// <param name="reqJT808Package"></param>
/// <param name="ctx"></param>
/// <returns></returns>
public virtual JT808Response Msg0x0002(JT808Request request)
{
sessionManager.Heartbeat(request.Package.Header.TerminalPhoneNo);
return new JT808Response(JT808MsgId.平台通用应答.Create(request.Package.Header.TerminalPhoneNo, new JT808_0x8001()
{
MsgId = request.Package.Header.MsgId,
JT808PlatformResult = JT808PlatformResult.成功,
MsgNum = request.Package.Header.MsgNum
}));
}
/// <summary>
/// 终端注销
/// </summary>
/// <param name="reqJT808Package"></param>
/// <param name="ctx"></param>
/// <returns></returns>
public virtual JT808Response Msg0x0003(JT808Request request)
{
return new JT808Response(JT808MsgId.平台通用应答.Create(request.Package.Header.TerminalPhoneNo, new JT808_0x8001()
{
MsgId = request.Package.Header.MsgId,
JT808PlatformResult = JT808PlatformResult.成功,
MsgNum = request.Package.Header.MsgNum
}));
}
/// <summary>
/// 终端注册
/// </summary>
/// <param name="reqJT808Package"></param>
/// <param name="ctx"></param>
/// <returns></returns>
public virtual JT808Response Msg0x0100(JT808Request request)
{
return new JT808Response(JT808MsgId.终端注册应答.Create(request.Package.Header.TerminalPhoneNo, new JT808_0x8100()
{
Code = "J" + request.Package.Header.TerminalPhoneNo,
JT808TerminalRegisterResult = JT808TerminalRegisterResult.成功,
MsgNum = request.Package.Header.MsgNum
}));
}
/// <summary>
/// 终端鉴权
/// </summary>
/// <param name="reqJT808Package"></param>
/// <param name="ctx"></param>
/// <returns></returns>
public virtual JT808Response Msg0x0102(JT808Request request)
{
return new JT808Response(JT808MsgId.平台通用应答.Create(request.Package.Header.TerminalPhoneNo, new JT808_0x8001()
{
MsgId = request.Package.Header.MsgId,
JT808PlatformResult = JT808PlatformResult.成功,
MsgNum = request.Package.Header.MsgNum
}));
}
/// <summary>
/// 位置信息汇报
/// </summary>
/// <param name="reqJT808Package"></param>
/// <param name="ctx"></param>
/// <returns></returns>
public virtual JT808Response Msg0x0200(JT808Request request)
{
return new JT808Response(JT808MsgId.平台通用应答.Create(request.Package.Header.TerminalPhoneNo, new JT808_0x8001()
{
MsgId = request.Package.Header.MsgId,
JT808PlatformResult = JT808PlatformResult.成功,
MsgNum = request.Package.Header.MsgNum
}));
}
/// <summary>
/// 定位数据批量上传
/// </summary>
/// <param name="reqJT808Package"></param>
/// <param name="ctx"></param>
/// <returns></returns>
public virtual JT808Response Msg0x0704(JT808Request request)
{
return new JT808Response(JT808MsgId.平台通用应答.Create(request.Package.Header.TerminalPhoneNo, new JT808_0x8001()
{
MsgId =request.Package.Header.MsgId,
JT808PlatformResult = JT808PlatformResult.成功,
MsgNum = request.Package.Header.MsgNum
}));
}
/// <summary>
/// 数据上行透传
/// </summary>
/// <param name="reqJT808Package"></param>
/// <param name="ctx"></param>
/// <returns></returns>
public virtual JT808Response Msg0x0900(JT808Request request)
{
return new JT808Response(JT808MsgId.平台通用应答.Create(request.Package.Header.TerminalPhoneNo, new JT808_0x8001()
{
MsgId =request.Package.Header.MsgId,
JT808PlatformResult = JT808PlatformResult.成功,
MsgNum = request.Package.Header.MsgNum
}));
}
}
}

+ 0
- 96
src/JT808.DotNetty/JT808ServerHost.cs Ver ficheiro

@@ -1,96 +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 JT808.DotNetty.Codecs;
using JT808.DotNetty.Configurations;
using JT808.DotNetty.Handlers;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

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

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

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("systemIdleState", new IdleStateHandler(
configuration.ReaderIdleTimeSeconds,
configuration.WriterIdleTimeSeconds,
configuration.AllIdleTimeSeconds));
channel.Pipeline.AddLast("jt808Connection", scope.ServiceProvider.GetRequiredService<JT808ConnectionHandler>());
channel.Pipeline.AddLast("jt808Buffer", new DelimiterBasedFrameDecoder(int.MaxValue,
Unpooled.CopiedBuffer(new byte[] { JT808.Protocol.JT808Package.BeginFlag }),
Unpooled.CopiedBuffer(new byte[] { JT808.Protocol.JT808Package.EndFlag })));
channel.Pipeline.AddLast("jt808Decode", scope.ServiceProvider.GetRequiredService<JT808Decoder>());
channel.Pipeline.AddLast("jt808Service", scope.ServiceProvider.GetRequiredService<JT808ServerHandler>());
}
}));
logger.LogInformation($"Server start at {IPAddress.Any}:{configuration.Port}.");
return bootstrap.BindAsync(configuration.Port)
.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
- 141
src/JT808.DotNetty/JT808SessionManager.cs Ver ficheiro

@@ -1,141 +0,0 @@
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using JT808.DotNetty.Metadata;
using DotNetty.Transport.Channels;
using JT808.DotNetty.Interfaces;

namespace JT808.DotNetty
{
/// <summary>
/// JT808会话管理
/// </summary>
public class JT808SessionManager
{
private readonly ILogger<JT808SessionManager> logger;

private readonly IJT808SessionPublishing jT808SessionPublishing;

public JT808SessionManager(
IJT808SessionPublishing jT808SessionPublishing,
ILoggerFactory loggerFactory)
{
this.jT808SessionPublishing = jT808SessionPublishing;
logger = loggerFactory.CreateLogger<JT808SessionManager>();
}

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

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

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

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

public void TryAdd(JT808Session appSession)
{
// 解决了设备号跟通道绑定到一起,不需要用到通道本身的SessionId
// 不管设备下发更改了设备终端号,只要是没有在内存中就当是新的
// 存在的问题:
// 1.原先老的如何销毁
// 2.这时候用的通道是相同的,设备终端是不同的
// 当设备主动或者服务器断开以后,可以释放,这点内存忽略不计,况且更改设备号不是很频繁。
if (SessionIdDict.TryAdd(appSession.TerminalPhoneNo, appSession))
{
//使用场景:
//部标的超长待机设备,不会像正常的设备一样一直连着,可能10几分钟连上了,然后发完就关闭连接,
//这时候想下发数据需要知道设备什么时候上线,在这边做通知最好不过了。
//todo: 有设备关联上来可以进行通知 例如:使用Redis发布订阅
jT808SessionPublishing.PublishAsync(JT808Constants.SessionOnline,null, appSession.TerminalPhoneNo);
}
}

public JT808Session RemoveSession(string terminalPhoneNo)
{
//todo: 设备离线可以进行通知
//todo: 使用Redis 发布订阅
if (string.IsNullOrEmpty(terminalPhoneNo)) return default;
if (!SessionIdDict.TryGetValue(terminalPhoneNo, out JT808Session jT808Session))
{
return default;
}
// 处理转发过来的是数据 这时候通道对设备是1对多关系,需要清理垃圾数据
//1.用当前会话的通道Id找出通过转发过来的其他设备的终端号
var terminalPhoneNos = SessionIdDict.Where(w => w.Value.Channel.Id == jT808Session.Channel.Id).Select(s => s.Key).ToList();
//2.存在则一个个移除
if (terminalPhoneNos.Count > 1)
{
//3.移除包括当前的设备号
foreach (var key in terminalPhoneNos)
{
SessionIdDict.TryRemove(key, out JT808Session jT808SessionRemove);
}
string nos = string.Join(",", terminalPhoneNos);
logger.LogInformation($">>>{terminalPhoneNo}-{nos} 1-n Session Remove.");
jT808SessionPublishing.PublishAsync(JT808Constants.SessionOffline, null, nos);
return jT808Session;
}
else
{
if (SessionIdDict.TryRemove(terminalPhoneNo, out JT808Session jT808SessionRemove))
{
logger.LogInformation($">>>{terminalPhoneNo} Session Remove.");
jT808SessionPublishing.PublishAsync(JT808Constants.SessionOffline, null, terminalPhoneNo);
return jT808SessionRemove;
}
else
{
return default;
}
}
}

internal void RemoveSessionByChannel(IChannel channel)
{
//todo: 设备离线可以进行通知
//todo: 使用Redis 发布订阅
var terminalPhoneNos = SessionIdDict.Where(w => w.Value.Channel.Id == channel.Id).Select(s => s.Key).ToList();
foreach (var key in terminalPhoneNos)
{
SessionIdDict.TryRemove(key, out JT808Session jT808SessionRemove);
}
string nos = string.Join(",", terminalPhoneNos);
logger.LogInformation($">>>{nos} Channel Remove.");
jT808SessionPublishing.PublishAsync(JT808Constants.SessionOffline, null, nos);
}

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


+ 0
- 77
src/JT808.DotNetty/JT808SimpleTcpClient.cs Ver ficheiro

@@ -1,77 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Codecs;
using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Channels.Sockets;
using DotNetty.Transport.Libuv;
using JT808.DotNetty.Codecs;
using JT808.DotNetty.Configurations;
using JT808.DotNetty.Handlers;
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace JT808.DotNetty
{
public class JT808SimpleTcpClient
{
private Bootstrap cb;

private MultithreadEventLoopGroup clientGroup;

private IChannel clientChannel;

private IByteBufferAllocator clientBufferAllocator;

public JT808SimpleTcpClient(EndPoint remoteAddress)
{
clientBufferAllocator = new PooledByteBufferAllocator();
clientGroup = new MultithreadEventLoopGroup(1);
cb = new Bootstrap()
.Group(clientGroup)
.Channel<TcpSocketChannel>()
.Option(ChannelOption.TcpNodelay, true)
.Option(ChannelOption.Allocator, clientBufferAllocator)
.Handler(new ActionChannelInitializer<TcpSocketChannel>(channel =>
{
channel.Pipeline.AddLast("jt808Buffer", new DelimiterBasedFrameDecoder(int.MaxValue,
Unpooled.CopiedBuffer(new byte[] { JT808.Protocol.JT808Package.BeginFlag }),
Unpooled.CopiedBuffer(new byte[] { JT808.Protocol.JT808Package.EndFlag })));
channel.Pipeline.AddLast("jt808Decode", new JT808ClientDecoder());
}));
clientChannel = cb.ConnectAsync(remoteAddress).Result;
}

public JT808SimpleTcpClient(EndPoint remoteAddress, EndPoint localAddress)
{
clientBufferAllocator = new PooledByteBufferAllocator();
clientGroup = new MultithreadEventLoopGroup(1);
cb = new Bootstrap()
.Group(clientGroup)
.Channel<TcpSocketChannel>()
.Option(ChannelOption.TcpNodelay, true)
.Option(ChannelOption.Allocator, clientBufferAllocator)
.Handler(new ActionChannelInitializer<TcpSocketChannel>(channel =>
{
channel.Pipeline.AddLast("jt808Buffer", new DelimiterBasedFrameDecoder(int.MaxValue,
Unpooled.CopiedBuffer(new byte[] { JT808.Protocol.JT808Package.BeginFlag }),
Unpooled.CopiedBuffer(new byte[] { JT808.Protocol.JT808Package.EndFlag })));
channel.Pipeline.AddLast("jt808Decode", new JT808ClientDecoder());
}));
clientChannel = cb.ConnectAsync(remoteAddress, localAddress).Result;
}

public void WriteAsync(byte[] data)
{
clientChannel.WriteAndFlushAsync(Unpooled.WrappedBuffer(data));
}

public void Down()
{
this.clientChannel?.CloseAsync().Wait();
Task.WaitAll(this.clientGroup.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1)));
}
}
}

+ 0
- 82
src/JT808.DotNetty/JT808UDPServerHost.cs Ver ficheiro

@@ -1,82 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Codecs;
using DotNetty.Handlers.Timeout;
using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Channels.Sockets;
using DotNetty.Transport.Libuv;
using JT808.DotNetty.Codecs;
using JT808.DotNetty.Configurations;
using JT808.DotNetty.Handlers;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

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

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

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.SoBacklog, configuration.SoBacklog)
.Handler(new ActionChannelInitializer<IChannel>(channel =>
{
IChannelPipeline pipeline = channel.Pipeline;
using (var scope = serviceProvider.CreateScope())
{
pipeline.AddLast(new JT808UDPDecoder());
pipeline.AddLast("jt808UDPService", scope.ServiceProvider.GetRequiredService<JT808UDPServerHandler>());
}
}));
logger.LogInformation($"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
- 82
src/JT808.DotNetty/JT808WebAPIServerHost.cs Ver ficheiro

@@ -1,82 +0,0 @@
using DotNetty.Codecs.Http;
using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Libuv;
using JT808.DotNetty.Configurations;
using JT808.DotNetty.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 JT808.DotNetty
{
/// <summary>
/// 集成一个webapi服务
/// </summary>
internal class JT808WebAPIServerHost : IHostedService
{
private readonly IServiceProvider serviceProvider;
private readonly JT808Configuration configuration;
private readonly ILogger<JT808WebAPIServerHost> logger;
private DispatcherEventLoopGroup bossGroup;
private WorkerEventLoopGroup workerGroup;
private IChannel bootstrapChannel;

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

public Task StartAsync(CancellationToken cancellationToken)
{
bossGroup = new DispatcherEventLoopGroup();
workerGroup = new WorkerEventLoopGroup(bossGroup, 1);
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)
.ChildHandler(new ActionChannelInitializer<IChannel>(channel =>
{
IChannelPipeline pipeline = channel.Pipeline;
using (var scope = serviceProvider.CreateScope())
{
pipeline.AddLast("http_encoder", new HttpResponseEncoder());
pipeline.AddLast("http_decoder", new HttpRequestDecoder(4096, 8192, 8192, false));
//将多个消息转换为单一的request或者response对象 =>IFullHttpRequest
pipeline.AddLast("http_aggregator", new HttpObjectAggregator(65536));
pipeline.AddLast("http_jt808webapihandler", scope.ServiceProvider.GetRequiredService<JT808WebAPIServerHandler>());
}
}));
logger.LogInformation($"WebAPI Server start at {IPAddress.Any}:{configuration.WebApiPort}.");
return bootstrap.BindAsync(configuration.WebApiPort).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
- 44
src/JT808.DotNetty/Metadata/JT808AtomicCounter.cs Ver ficheiro

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

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

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

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
- 22
src/JT808.DotNetty/Metadata/JT808HttpRequest.cs Ver ficheiro

@@ -1,22 +0,0 @@
using JT808.Protocol;
using System;
using System.Collections.Generic;
using System.Reflection;

namespace JT808.DotNetty.Metadata
{
public class JT808HttpRequest
{
public string Json { get; set; }

public JT808HttpRequest()
{

}

public JT808HttpRequest(string json)
{
Json = json;
}
}
}

+ 0
- 22
src/JT808.DotNetty/Metadata/JT808HttpResponse.cs Ver ficheiro

@@ -1,22 +0,0 @@
using JT808.Protocol;
using System;
using System.Collections.Generic;
using System.Reflection;

namespace JT808.DotNetty.Metadata
{
public class JT808HttpResponse
{
public byte[] Data { get; set; }

public JT808HttpResponse()
{

}

public JT808HttpResponse(byte[] data)
{
this.Data = data;
}
}
}

+ 0
- 23
src/JT808.DotNetty/Metadata/JT808Request.cs Ver ficheiro

@@ -1,23 +0,0 @@
using JT808.Protocol;
using System;
using System.Collections.Generic;
using System.Reflection;

namespace JT808.DotNetty.Metadata
{
public class JT808Request
{
public JT808HeaderPackage Package { get; }

/// <summary>
/// 用于消息发送
/// </summary>
public byte[] OriginalPackage { get;}

public JT808Request(JT808HeaderPackage package, byte[] originalPackage)
{
Package = package;
OriginalPackage = originalPackage;
}
}
}

+ 0
- 27
src/JT808.DotNetty/Metadata/JT808Response.cs Ver ficheiro

@@ -1,27 +0,0 @@
using JT808.Protocol;
using System;
using System.Collections.Generic;
using System.Reflection;

namespace JT808.DotNetty.Metadata
{
public class JT808Response
{
public JT808Package Package { get; set; }
/// <summary>
/// 根据实际情况适当调整包的大小
/// </summary>
public int MinBufferSize { get; set; }

public JT808Response()
{

}

public JT808Response(JT808Package package, int minBufferSize = 1024)
{
Package = package;
MinBufferSize = minBufferSize;
}
}
}

+ 0
- 31
src/JT808.DotNetty/Metadata/JT808Session.cs Ver ficheiro

@@ -1,31 +0,0 @@
using DotNetty.Transport.Channels;
using System;
using System.Collections.Generic;
using System.Text;

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

public JT808Session() { }

/// <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/JT808.DotNetty/Metadata/JT808UDPPackage.cs Ver ficheiro

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

namespace JT808.DotNetty.Metadata
{
internal class JT808UDPPackage
{
public JT808UDPPackage(byte[] buffer, EndPoint sender)
{
Buffer = buffer;
Sender = sender;
}

public byte[] Buffer { get; }

public EndPoint Sender { get; }
}
}

Carregando…
Cancelar
Guardar