/WindowsApp/WindowsGoodbye/WindowsGoodbyeAuthTask/UDPListener.cs

https://github.com/cqjjjzr/WindowsGoodbye · C# · 92 lines · 85 code · 7 blank · 0 comment · 14 complexity · 2d4de3a9dd4af32b1e65086740cf7fac MD5 · raw file

  1. using System;
  2. using System.Diagnostics;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Net;
  6. using System.Runtime.InteropServices.WindowsRuntime;
  7. using System.Text;
  8. using System.Threading;
  9. using System.Threading.Tasks;
  10. using Windows.Networking;
  11. using Windows.Networking.Sockets;
  12. using Windows.Storage.Streams;
  13. namespace WindowsGoodbyeAuthTask
  14. {
  15. internal static class UDPListener
  16. {
  17. public const int ReadBufferSize = 1024;
  18. public const int DeviceAuthPort = 26819;
  19. public static DatagramSocket DatagramSocket;
  20. public static readonly HostName DeviceMulticastGroupAddress = new HostName("225.67.76.67");
  21. public static async void StartListening()
  22. {
  23. if (DatagramSocket != null)
  24. await DatagramSocket.CancelIOAsync();
  25. DatagramSocket = new DatagramSocket();
  26. DatagramSocket.MessageReceived += async (sender, args) =>
  27. {
  28. await OnReceived(args.GetDataStream(), args.RemoteAddress);
  29. };
  30. await DatagramSocket.BindServiceNameAsync(DeviceAuthPort.ToString());
  31. DatagramSocket.JoinMulticastGroup(DeviceMulticastGroupAddress);
  32. }
  33. public static async void Send(string hostname, byte[] data)
  34. {
  35. await Send(new HostName(hostname), data);
  36. }
  37. public static async Task Send(HostName hostname, byte[] data)
  38. {
  39. using (var stream = (await DatagramSocket.GetOutputStreamAsync(
  40. hostname,
  41. DeviceAuthPort.ToString())).AsStreamForWrite())
  42. {
  43. await stream.WriteAsync(data, 0, data.Length);
  44. await stream.FlushAsync();
  45. }
  46. }
  47. public static async void StopListening()
  48. {
  49. await DatagramSocket.CancelIOAsync();
  50. DatagramSocket.Dispose();
  51. DatagramSocket = null;
  52. }
  53. public static async Task OnReceived(IInputStream dataStream, HostName remoteAddress)
  54. {
  55. IBuffer buffer = new Windows.Storage.Streams.Buffer(ReadBufferSize);
  56. await dataStream.ReadAsync(buffer, ReadBufferSize, InputStreamOptions.None);
  57. dataStream.Dispose();
  58. var info = Encoding.UTF8.GetString(buffer.ToArray());
  59. if (info.StartsWith(WindowsGoodbyeAuthTask.DeviceAlivePrefix) &&
  60. info.Length > WindowsGoodbyeAuthTask.DeviceAlivePrefix.Length)
  61. {
  62. var payload = Convert.FromBase64String(info.Substring(WindowsGoodbyeAuthTask.DeviceAlivePrefix.Length));
  63. if (payload.Length != 16) return;
  64. var guid = new Guid(payload);
  65. var session = WindowsGoodbyeAuthTask.deviceSessions.FirstOrDefault(s => s.DeviceInDb.DeviceId == guid);
  66. if (session != null) session.Status = DeviceStatus.Established;
  67. WindowsGoodbyeAuthTask.findAuth = false;
  68. } else if (info.StartsWith(WindowsGoodbyeAuthTask.AuthResponsePrefix) &&
  69. info.Length > WindowsGoodbyeAuthTask.AuthResponsePrefix.Length)
  70. {
  71. var payload = Convert.FromBase64String(info.Substring(WindowsGoodbyeAuthTask.DeviceAlivePrefix.Length));
  72. if (payload.Length <= 18) return;
  73. var guidBytes = new byte[16];
  74. Array.Copy(payload, guidBytes, 16);
  75. var guid = new Guid(guidBytes);
  76. var session = WindowsGoodbyeAuthTask.deviceSessions.FirstOrDefault(s => s.DeviceInDb.DeviceId == guid);
  77. if (session == null) return;
  78. var resultBytes = new byte[payload.Length - 16];
  79. Array.Copy(payload, 16, resultBytes, 0, resultBytes.Length);
  80. session.ResultBytes = resultBytes;
  81. WindowsGoodbyeAuthTask.AuthResultReceivedEvent.Set();
  82. }
  83. }
  84. }
  85. }