ExampleForm.cs 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. using System;
  2. using System.IO;
  3. using System.Linq;
  4. using System.Net;
  5. using System.Net.Sockets;
  6. using System.Security.Cryptography;
  7. using System.Text;
  8. using System.Windows.Forms;
  9. namespace UdPunching.ExampleW
  10. {
  11. public partial class ExampleForm : Form
  12. {
  13. private const int ReceiveBufferSize = 1500;
  14. private static readonly IPEndPoint AnyEndPoint = new IPEndPoint(IPAddress.Any, 0);
  15. private IPEndPoint _serverEndPoint;
  16. private RSACryptoServiceProvider _serverRsa;
  17. private SocketAsyncEventArgs _saeRecv;
  18. private Guid _peerId;
  19. private RSACryptoServiceProvider _peerRsa;
  20. private Socket _peerSocket;
  21. public ExampleForm()
  22. {
  23. InitializeComponent();
  24. }
  25. private void ExampleForm_Shown(object sender, EventArgs e)
  26. {
  27. _serverRsa = new RSACryptoServiceProvider();
  28. _serverRsa.FromXmlString(File.ReadAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ServerPublicKey.txt")));
  29. var files = Directory
  30. .GetFiles(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "PrivateKey"))
  31. .Select(Path.GetFileName)
  32. .ToArray();
  33. PeerKetyDropDown.DataSource = files;
  34. }
  35. private void StartButton_Click(object sender, EventArgs e)
  36. {
  37. _serverEndPoint = ServerIEndPointTextBox.Text.ParseToIpEndPointV4();
  38. _peerRsa = new RSACryptoServiceProvider();
  39. var peerPrivateKeyPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "PrivateKey", PeerKetyDropDown.Text);
  40. _peerRsa.FromXmlString(
  41. File.ReadAllText(
  42. peerPrivateKeyPath
  43. )
  44. );
  45. _peerId = new Guid(Path.GetFileNameWithoutExtension(peerPrivateKeyPath));
  46. _peerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
  47. _peerSocket.Bind(AnyEndPoint);
  48. _saeRecv = new SocketAsyncEventArgs();
  49. _saeRecv.SetBuffer(new byte[ReceiveBufferSize], 0, ReceiveBufferSize);
  50. _saeRecv.Completed += _saeRecv_Completed;
  51. BeginRecv();
  52. KeepAliveTimer.Start();
  53. StartButton.Enabled = false;
  54. StopButton.Enabled = true;
  55. SendButton.Enabled = true;
  56. }
  57. private void StopButton_Click(object sender, EventArgs e)
  58. {
  59. KeepAliveTimer.Stop();
  60. _peerSocket.Dispose();
  61. _saeRecv.Dispose();
  62. _peerRsa.Dispose();
  63. StartButton.Enabled = true;
  64. StopButton.Enabled = false;
  65. SendButton.Enabled = false;
  66. }
  67. private void _saeRecv_Completed(object sender, SocketAsyncEventArgs e)
  68. {
  69. if (e.SocketError == SocketError.Success)
  70. {
  71. try
  72. {
  73. ProcessPacket();
  74. if (false == _peerSocket.ReceiveFromAsync(_saeRecv)) _saeRecv_Completed(null, null);
  75. }
  76. catch (Exception exception)
  77. {
  78. Invoke(new Action(() =>
  79. {
  80. StatusLabel.Text = $"ERROR:{exception.Message}";
  81. StopButton_Click(null, null);
  82. }));
  83. }
  84. }
  85. else
  86. {
  87. Invoke(new Action(() =>
  88. {
  89. StatusLabel.Text = $"ERROR:{e.SocketError}";
  90. StopButton_Click(null, null);
  91. }));
  92. }
  93. }
  94. private void ProcessPacket()
  95. {
  96. var peerId = TransferCodec.ReadId(_saeRecv.Buffer);
  97. if (_saeRecv.RemoteEndPoint.IpEndPointEqualsTo(_serverEndPoint))
  98. {
  99. if (BuindInPeerId.Invalid == peerId)
  100. {
  101. Invoke(new Action(() => { StatusLabel.Text = "Server FAILURE"; }));
  102. }
  103. else if (Guid.Empty == peerId)
  104. {
  105. var msgData = TransferCodec.DecodeData(_peerRsa, _saeRecv.Buffer);
  106. var msg = new ExchangeMessage(msgData);
  107. if (msg.Flags.HasFlag(ExchangeMessageFlags.EchoEndPoint))
  108. {
  109. Invoke(new Action(() =>
  110. {
  111. PublicEndPointTextBox.Text = msg.PeerEndPoint.ToString();
  112. }));
  113. }
  114. }
  115. }
  116. else
  117. {
  118. Invoke(new Action(() =>
  119. {
  120. RecvTextBox.Text =
  121. $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} {_saeRecv.RemoteEndPoint}"
  122. + $"{Environment.NewLine} {Encoding.UTF8.GetString(_saeRecv.Buffer, 0, _saeRecv.BytesTransferred)}"
  123. + $"{Environment.NewLine}"
  124. + RecvTextBox.Text;
  125. }));
  126. }
  127. }
  128. private void BeginRecv()
  129. {
  130. _saeRecv.RemoteEndPoint = AnyEndPoint;
  131. if (false == _peerSocket.ReceiveFromAsync(_saeRecv))
  132. {
  133. _saeRecv_Completed(null, _saeRecv);
  134. }
  135. }
  136. private readonly byte[] _buf = new byte[7];// 1flag,1count,1section,4timestamp
  137. private readonly ExchangeMessage _msg = new ExchangeMessage { Flags = ExchangeMessageFlags.PeerKeepAlive };
  138. private void KeepAliveTimer_Tick(object sender, EventArgs e)
  139. {
  140. _msg.PeerTimeStamp = DateTime.Now;
  141. _msg.WriteToBuffer(_buf);
  142. StatusLabel.Text = "Keeping alive...";
  143. var encode = TransferCodec.Encode(_serverRsa, _peerId, _buf);
  144. _peerSocket.SendTo(encode, _serverEndPoint);
  145. }
  146. private void SendButton_Click(object sender, EventArgs e)
  147. {
  148. var to = SendToEndPointTextBox.Text.ParseToIpEndPointV4();
  149. var sent = _peerSocket.SendTo(Encoding.UTF8.GetBytes(SendContentTextBox.Text), to);
  150. }
  151. }
  152. }