using System; using System.IO; using System.Net; using System.Net.Sockets; using System.Security.Cryptography; using System.Threading; namespace UdPunching { internal static class PeerProgram { private static RSACryptoServiceProvider _serverRsa; private static RSACryptoServiceProvider _peerRsa; private static IPEndPoint _serverEndPoint; private static int packetSeq; private static Socket _peerSocket; private static void ProcessPacket(SocketAsyncEventArgs sae) { ++packetSeq; Console.WriteLine($"Incoming packet#{packetSeq:0,000,000} from {sae.RemoteEndPoint}, BytesTransferred {sae.BytesTransferred}"); var peerId = TransferCodec.ReadId(sae.Buffer); Console.WriteLine($"Incoming packet#{packetSeq:0,000,000} peer id {peerId}"); if (sae.RemoteEndPoint.IpEndPointEqualsTo(_serverEndPoint)) { if (TransferCodec.InvalidPeerId == peerId) { Console.WriteLine($"Incoming packet#{packetSeq:0,000,000} Server FAILURE"); } else if (Guid.Empty == peerId) { var msgData = TransferCodec.DecodeData(_peerRsa, sae.Buffer); Console.WriteLine($"Incoming packet#{packetSeq:0,000,000} data length {msgData.Length}"); var msg = new ExchangeMessage(msgData); Console.WriteLine($"Incoming packet#{packetSeq:0,000,000} flag {msg.Flags}"); if (msg.Flags.HasFlag(ExchangeMessageFlags.EchoEndPoint)) Console.WriteLine($"Incoming packet#{packetSeq:0,000,000} **** echo endpoint {msg.PeerEndPoint}"); } //TODO: handle server message } else { //TODO: handle peers message } } private static void DeadLoopKeepAlive() { var buf = new byte[7];// 1flag,1count,1section,4timestamp var msg = new ExchangeMessage(); msg.Flags = ExchangeMessageFlags.PeerKeepAlive; while (true) { msg.PeerTimeStamp = DateTime.Now; msg.WriteToBuffer(buf); var encode = TransferCodec.Encode(_serverRsa, Properties.Settings.Default.PeerId, buf); Console.WriteLine($"Sending packet KeepAlive {msg.PeerTimeStamp}"); _peerSocket.SendTo(encode, _serverEndPoint); Thread.Sleep(1000); } } private static void Main(string[] args) { Console.WriteLine("Init..."); _serverRsa = new RSACryptoServiceProvider(); _serverRsa.FromXmlString(File.ReadAllText("ServerPublicKey.txt")); _peerRsa = new RSACryptoServiceProvider(); _peerRsa.FromXmlString(File.ReadAllText("PeerPrivateKey.txt")); _serverEndPoint = new IPEndPoint(IPAddress.Parse(Properties.Settings.Default.Host), Properties.Settings.Default.Port); _peerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); _peerSocket.Bind(new IPEndPoint(IPAddress.Any, 0)); Console.WriteLine($"Peer Bind on {_peerSocket.LocalEndPoint}"); const int receiveBufferSize = 1500; var sae = new SocketAsyncEventArgs(); sae.SetBuffer(new byte[receiveBufferSize], 0, receiveBufferSize); sae.RemoteEndPoint = new IPEndPoint(IPAddress.Any, 0); Console.WriteLine($"Receive buffer:{receiveBufferSize}"); void SaeOnCompleted(object sender, SocketAsyncEventArgs e) { if (e.SocketError == SocketError.Success) { try { ProcessPacket(sae); } catch (Exception exception) { Console.WriteLine(exception); } } else { Console.WriteLine($"ERROR:{e.SocketError}"); } sae.RemoteEndPoint = new IPEndPoint(IPAddress.Any, 0); if (false == _peerSocket.ReceiveFromAsync(sae)) SaeOnCompleted(null, null); } sae.Completed += SaeOnCompleted; if (false == _peerSocket.ReceiveFromAsync(sae)) { SaeOnCompleted(null, null); } DeadLoopKeepAlive(); } } }