Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 

166 linhas
6.8 KiB

  1. using System;
  2. using System.Buffers;
  3. using System.Collections.Generic;
  4. using System.IO.Pipelines;
  5. using System.Net;
  6. using System.Net.Sockets;
  7. using System.Text;
  8. using System.Threading;
  9. using System.Threading.Tasks;
  10. using JT808.Gateway.Abstractions;
  11. using JT808.Gateway.Abstractions.Configurations;
  12. using JT808.Gateway.Session;
  13. using JT808.Protocol;
  14. using JT808.Protocol.Exceptions;
  15. using JT808.Protocol.Extensions;
  16. using Microsoft.Extensions.Hosting;
  17. using Microsoft.Extensions.Logging;
  18. using Microsoft.Extensions.Options;
  19. namespace JT808.Gateway
  20. {
  21. public class JT808UdpServer : IHostedService
  22. {
  23. private readonly Socket server;
  24. private readonly ILogger Logger;
  25. private readonly JT808SessionManager SessionManager;
  26. private readonly JT808Serializer Serializer;
  27. private readonly IPEndPoint LocalIPEndPoint;
  28. private readonly JT808MessageHandler MessageHandler;
  29. private readonly IJT808MsgProducer MsgProducer;
  30. private readonly IJT808MsgReplyLoggingProducer MsgReplyLoggingProducer;
  31. private readonly IOptionsMonitor<JT808Configuration> ConfigurationMonitor;
  32. public JT808UdpServer(
  33. IOptionsMonitor<JT808Configuration> configurationMonitor,
  34. IJT808MsgProducer msgProducer,
  35. IJT808MsgReplyLoggingProducer msgReplyLoggingProducer,
  36. IJT808Config jT808Config,
  37. ILoggerFactory loggerFactory,
  38. JT808SessionManager jT808SessionManager,
  39. JT808MessageHandler messageHandler)
  40. {
  41. SessionManager = jT808SessionManager;
  42. MsgProducer = msgProducer;
  43. ConfigurationMonitor = configurationMonitor;
  44. MsgReplyLoggingProducer = msgReplyLoggingProducer;
  45. Logger = loggerFactory.CreateLogger<JT808UdpServer>();
  46. Serializer = jT808Config.GetSerializer();
  47. MessageHandler = messageHandler;
  48. LocalIPEndPoint = new System.Net.IPEndPoint(IPAddress.Any, ConfigurationMonitor.CurrentValue.UdpPort);
  49. server = new Socket(LocalIPEndPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
  50. server.Bind(LocalIPEndPoint);
  51. }
  52. public Task StartAsync(CancellationToken cancellationToken)
  53. {
  54. Logger.LogInformation($"JT808 Udp Server start at {IPAddress.Any}:{ConfigurationMonitor.CurrentValue.UdpPort}.");
  55. Task.Factory.StartNew(async() => {
  56. while (!cancellationToken.IsCancellationRequested)
  57. {
  58. var buffer = ArrayPool<byte>.Shared.Rent(ConfigurationMonitor.CurrentValue.MiniNumBufferSize);
  59. try
  60. {
  61. var segment = new ArraySegment<byte>(buffer);
  62. SocketReceiveMessageFromResult result = await server.ReceiveMessageFromAsync(segment, SocketFlags.None, LocalIPEndPoint);
  63. ReaderBuffer(buffer.AsSpan(0, result.ReceivedBytes), server, result);
  64. }
  65. catch(System.ObjectDisposedException ex)
  66. {
  67. //Logger.LogInformation("Socket Received Bytes Close");
  68. }
  69. catch(AggregateException ex)
  70. {
  71. Logger.LogError(ex, "Receive MessageFrom Async");
  72. }
  73. catch (SocketException ex)
  74. {
  75. //Logger.LogWarning(ex, $"Socket Error");
  76. }
  77. catch (Exception ex)
  78. {
  79. Logger.LogError(ex, $"Service Error");
  80. }
  81. finally
  82. {
  83. ArrayPool<byte>.Shared.Return(buffer);
  84. }
  85. }
  86. }, cancellationToken);
  87. return Task.CompletedTask;
  88. }
  89. private void ReaderBuffer(ReadOnlySpan<byte> buffer, Socket socket,SocketReceiveMessageFromResult receiveMessageFromResult)
  90. {
  91. try
  92. {
  93. var package = Serializer.HeaderDeserialize(buffer, minBufferSize: 10240);
  94. if (Logger.IsEnabled(LogLevel.Trace)) Logger.LogTrace($"[Accept Hex {receiveMessageFromResult.RemoteEndPoint}]:{package.OriginalData.ToHexString()}");
  95. var session = SessionManager.TryLink(package.Header.TerminalPhoneNo, socket, receiveMessageFromResult.RemoteEndPoint);
  96. if (Logger.IsEnabled(LogLevel.Information))
  97. {
  98. Logger.LogInformation($"[Connected]:{receiveMessageFromResult.RemoteEndPoint}");
  99. }
  100. Processor(session, package);
  101. }
  102. catch (NotImplementedException ex)
  103. {
  104. Logger.LogError(ex.Message);
  105. }
  106. catch (JT808Exception ex)
  107. {
  108. Logger.LogError($"[HeaderDeserialize ErrorCode]:{ ex.ErrorCode},[ReaderBuffer]:{buffer.ToArray().ToHexString()}");
  109. }
  110. #pragma warning disable CA1031 // Do not catch general exception types
  111. catch (Exception ex)
  112. {
  113. Logger.LogError(ex, $"[ReaderBuffer]:{ buffer.ToArray().ToHexString()}");
  114. }
  115. #pragma warning restore CA1031 // Do not catch general exception types
  116. }
  117. private void Processor(in IJT808Session session, in JT808HeaderPackage package)
  118. {
  119. try
  120. {
  121. MsgProducer?.ProduceAsync(package.Header.TerminalPhoneNo, package.OriginalData);
  122. var downData = MessageHandler.Processor(package);
  123. if (ConfigurationMonitor.CurrentValue.IgnoreMsgIdReply != null && ConfigurationMonitor.CurrentValue.IgnoreMsgIdReply.Count > 0)
  124. {
  125. if (!ConfigurationMonitor.CurrentValue.IgnoreMsgIdReply.Contains(package.Header.MsgId))
  126. {
  127. session.SendAsync(downData);
  128. }
  129. }
  130. else
  131. {
  132. session.SendAsync(downData);
  133. }
  134. if (MsgReplyLoggingProducer != null)
  135. {
  136. if (downData != null)
  137. MsgReplyLoggingProducer.ProduceAsync(package.Header.TerminalPhoneNo, downData);
  138. }
  139. }
  140. catch (Exception ex)
  141. {
  142. Logger.LogError(ex, $"[Processor]:{package.OriginalData.ToHexString()},{session.Client.RemoteEndPoint},{session.TerminalPhoneNo}");
  143. }
  144. }
  145. public Task StopAsync(CancellationToken cancellationToken)
  146. {
  147. Logger.LogInformation("JT808 Udp Server Stop");
  148. if (server?.Connected ?? false)
  149. server.Shutdown(SocketShutdown.Both);
  150. server?.Close();
  151. return Task.CompletedTask;
  152. }
  153. }
  154. }