using System; using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; using System.Security.Cryptography; using System.Text; using System.Windows.Forms; namespace UdPunching.ExampleW { public partial class ExampleForm : Form { private const int ReceiveBufferSize = 1500; private static readonly IPEndPoint AnyEndPoint = new IPEndPoint(IPAddress.Any, 0); private IPEndPoint _serverEndPoint; private RSACryptoServiceProvider _serverRsa; private SocketAsyncEventArgs _saeRecv; private Guid _peerId; private RSACryptoServiceProvider _peerRsa; private Socket _peerSocket; public ExampleForm() { InitializeComponent(); } private void ExampleForm_Shown(object sender, EventArgs e) { _serverRsa = new RSACryptoServiceProvider(); _serverRsa.FromXmlString(File.ReadAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ServerPublicKey.txt"))); var files = Directory .GetFiles(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "PrivateKey")) .Select(Path.GetFileName) .ToArray(); PeerKetyDropDown.DataSource = files; } private void StartButton_Click(object sender, EventArgs e) { _serverEndPoint = ServerIEndPointTextBox.Text.ParseToIpEndPointV4(); _peerRsa = new RSACryptoServiceProvider(); var peerPrivateKeyPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "PrivateKey", PeerKetyDropDown.Text); _peerRsa.FromXmlString( File.ReadAllText( peerPrivateKeyPath ) ); _peerId = new Guid(Path.GetFileNameWithoutExtension(peerPrivateKeyPath)); _peerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); _peerSocket.Bind(AnyEndPoint); _saeRecv = new SocketAsyncEventArgs(); _saeRecv.SetBuffer(new byte[ReceiveBufferSize], 0, ReceiveBufferSize); _saeRecv.Completed += _saeRecv_Completed; BeginRecv(); KeepAliveTimer.Start(); StartButton.Enabled = false; StopButton.Enabled = true; SendButton.Enabled = true; } private void StopButton_Click(object sender, EventArgs e) { KeepAliveTimer.Stop(); _peerSocket.Dispose(); _saeRecv.Dispose(); _peerRsa.Dispose(); StartButton.Enabled = true; StopButton.Enabled = false; SendButton.Enabled = false; } private void _saeRecv_Completed(object sender, SocketAsyncEventArgs e) { if (e.SocketError == SocketError.Success) { try { ProcessPacket(); if (false == _peerSocket.ReceiveFromAsync(_saeRecv)) _saeRecv_Completed(null, null); } catch (Exception exception) { Invoke(new Action(() => { StatusLabel.Text = $"ERROR:{exception.Message}"; StopButton_Click(null, null); })); } } else { Invoke(new Action(() => { StatusLabel.Text = $"ERROR:{e.SocketError}"; StopButton_Click(null, null); })); } } private void ProcessPacket() { var peerId = TransferCodec.ReadId(_saeRecv.Buffer); if (_saeRecv.RemoteEndPoint.IpEndPointEqualsTo(_serverEndPoint)) { if (BuindInPeerId.Invalid == peerId) { Invoke(new Action(() => { StatusLabel.Text = "Server FAILURE"; })); } else if (Guid.Empty == peerId) { var msgData = TransferCodec.DecodeData(_peerRsa, _saeRecv.Buffer); var msg = new ExchangeMessage(msgData); if (msg.Flags.HasFlag(ExchangeMessageFlags.EchoEndPoint)) { Invoke(new Action(() => { PublicEndPointTextBox.Text = msg.PeerEndPoint.ToString(); })); } } } else { Invoke(new Action(() => { RecvTextBox.Text = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} {_saeRecv.RemoteEndPoint}" + $"{Environment.NewLine} {Encoding.UTF8.GetString(_saeRecv.Buffer, 0, _saeRecv.BytesTransferred)}" + $"{Environment.NewLine}" + RecvTextBox.Text; })); } } private void BeginRecv() { _saeRecv.RemoteEndPoint = AnyEndPoint; if (false == _peerSocket.ReceiveFromAsync(_saeRecv)) { _saeRecv_Completed(null, _saeRecv); } } private readonly byte[] _buf = new byte[7];// 1flag,1count,1section,4timestamp private readonly ExchangeMessage _msg = new ExchangeMessage { Flags = ExchangeMessageFlags.PeerKeepAlive }; private void KeepAliveTimer_Tick(object sender, EventArgs e) { _msg.PeerTimeStamp = DateTime.Now; _msg.WriteToBuffer(_buf); StatusLabel.Text = "Keeping alive..."; var encode = TransferCodec.Encode(_serverRsa, _peerId, _buf); _peerSocket.SendTo(encode, _serverEndPoint); } private void SendButton_Click(object sender, EventArgs e) { var to = SendToEndPointTextBox.Text.ParseToIpEndPointV4(); var sent = _peerSocket.SendTo(Encoding.UTF8.GetBytes(SendContentTextBox.Text), to); } } }