/// <summary> /// Bind the socket to the local endpoint. /// </summary> /// <param name="localEndpoint"></param> public override void BindSocket(EndPoint localEndpoint) { // Create a new IPv4 UDP Socket. Socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp) { Blocking = true }; // Bind the local endpoint to the socket. Socket.Bind(localEndpoint); LocalEndpoint = Socket.LocalEndPoint; SkaiaLogger.LogMessage(MessageType.Info, $"Bound socket to {localEndpoint.ToString()}"); // Set the connection reset. RawDataReceived = new Action <byte[], SEndPoint>(DispatchRawPacket); NetUtils.SetConnReset(Socket); }
/// <summary> /// Receive data on the socket. This will block the calling method until it finds something to receive. /// </summary> /// <param name="buffer"> The buffer to copy the data onto. </param> /// <param name="length"> The amount of data to copy. </param> /// <param name="sender"> The data's sender. </param> /// <returns> The data received or null if nothing. </returns> public override byte[] Receive(byte[] buffer, int length, out EndPoint sender) { if (!Socket.IsBound) { throw new InvalidOperationException(); } sender = null; try { // Wait indefinitely to receive something on the socket. if (Socket.Poll(-1, SelectMode.SelectRead)) { // Get the length of the packet received. int pcktLength = Socket.ReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref recvEndpoint); // If for some odd reason it's empty, we'll just discard it and return an empty byte array. if (pcktLength > 0) { byte[] data = new byte[pcktLength]; Buffer.BlockCopy(buffer, 0, data, 0, data.Length); sender = recvEndpoint; return(data); } else { return(null); } } } catch (Exception ex) { // This probably happens if the socket isn't bound. SkaiaLogger.LogMessage(MessageType.Error, "Failed to poll and receive on socket.", ex); sender = null; } return(null); }
/// <summary> /// Tries to find a network interface with a valid IPv4 address and returns it. /// </summary> /// <returns> The local machine's IPv4 address if any, 127.0.0.1 on failure. </returns> public static IPAddress GetLocalEndpoint() { List <NetworkInterface> netInterfaces = new List <NetworkInterface>(); try { netInterfaces = NetworkInterface.GetAllNetworkInterfaces() .Where(n => n.Supports(NetworkInterfaceComponent.IPv4) && n.OperationalStatus == OperationalStatus.Up) .ToList(); } catch (NetworkInformationException netEx) { SkaiaLogger.LogMessage(MessageType.Critical, "Cannot get information about the network interfaces on this machine.", netEx); return(null); } if (netInterfaces.Count == 0) { // Well. Umm how can I say it. You ain't playing multiplayer at this point. SkaiaLogger.LogMessage(MessageType.Critical, "Cannot find any operating network interface with IPv4 support, defaulting to 127.0.0.1"); // TODO: Check if we should just fail at this point, dunno if 127.0.0.1 will even work. return(IPAddress.Parse("127.0.0.1")); } IPAddress address = netInterfaces.Select(n => n.GetIPProperties()) .SelectMany(i => i.UnicastAddresses) .Where(u => u.IsDnsEligible) // Just a safety check I suppose. .Select(u => u.Address) .FirstOrDefault(); // Shouldn't ever arrive but you're never sure enough. // TODO: Again maybe check if we should just fail at this point. if (address == null) { return(IPAddress.Parse("127.0.0.1")); } return(address); }