From fa8b1e986dfb32f0a609ac8b1b4f5a62c8f87a95 Mon Sep 17 00:00:00 2001 From: Michael Lidgren Date: Tue, 24 Mar 2015 13:26:55 +0100 Subject: [PATCH] First iteration improved multiplatform support --- .../Encryption/NetAESEncryption.cs | 12 - .../Encryption/NetCryptoProviderEncryption.cs | 59 +++++ .../Encryption/NetXteaEncryption.cs | 6 +- Lidgren.Network/Lidgren.Network.csproj | 4 + Lidgren.Network/NetBigInteger.cs | 15 ++ Lidgren.Network/NetBuffer.Read.cs | 10 +- Lidgren.Network/NetClient.cs | 6 +- Lidgren.Network/NetConnection.Handshake.cs | 8 +- Lidgren.Network/NetConnection.cs | 12 +- Lidgren.Network/NetIncomingMessage.cs | 10 +- Lidgren.Network/NetNatIntroduction.cs | 30 ++- Lidgren.Network/NetPeer.Discovery.cs | 19 +- Lidgren.Network/NetPeer.Internal.cs | 58 ++--- Lidgren.Network/NetPeer.LatencySimulation.cs | 22 +- Lidgren.Network/NetPeer.Send.cs | 20 +- Lidgren.Network/NetPeer.cs | 36 +-- Lidgren.Network/NetRandomSeed.cs | 26 +- Lidgren.Network/NetSRP.cs | 37 +-- Lidgren.Network/NetTime.cs | 21 +- Lidgren.Network/NetUPnP.cs | 10 +- Lidgren.Network/NetUtility.cs | 237 ++---------------- Lidgren.Network/Platform/PlatformAndroid.cs | 87 +++++++ .../Platform/PlatformConstrained.cs | 72 ++++++ Lidgren.Network/Platform/PlatformWin32.cs | 156 ++++++++++++ Lidgren.Network/Platform/PlatformWinRT.cs | 102 ++++++++ 25 files changed, 674 insertions(+), 401 deletions(-) create mode 100644 Lidgren.Network/Encryption/NetCryptoProviderEncryption.cs create mode 100644 Lidgren.Network/Platform/PlatformAndroid.cs create mode 100644 Lidgren.Network/Platform/PlatformConstrained.cs create mode 100644 Lidgren.Network/Platform/PlatformWin32.cs create mode 100644 Lidgren.Network/Platform/PlatformWinRT.cs diff --git a/Lidgren.Network/Encryption/NetAESEncryption.cs b/Lidgren.Network/Encryption/NetAESEncryption.cs index bb6eb4d..5ed5582 100644 --- a/Lidgren.Network/Encryption/NetAESEncryption.cs +++ b/Lidgren.Network/Encryption/NetAESEncryption.cs @@ -7,30 +7,18 @@ namespace Lidgren.Network public class NetAESEncryption : NetCryptoProviderBase { public NetAESEncryption(NetPeer peer) -#if UNITY_WEBPLAYER - : base(peer, new RijndaelManaged()) -#else : base(peer, new AesCryptoServiceProvider()) -#endif { } public NetAESEncryption(NetPeer peer, string key) -#if UNITY_WEBPLAYER - : base(peer, new RijndaelManaged()) -#else : base(peer, new AesCryptoServiceProvider()) -#endif { SetKey(key); } public NetAESEncryption(NetPeer peer, byte[] data, int offset, int count) -#if UNITY_WEBPLAYER - : base(peer, new RijndaelManaged()) -#else : base(peer, new AesCryptoServiceProvider()) -#endif { SetKey(data, offset, count); } diff --git a/Lidgren.Network/Encryption/NetCryptoProviderEncryption.cs b/Lidgren.Network/Encryption/NetCryptoProviderEncryption.cs new file mode 100644 index 0000000..d112046 --- /dev/null +++ b/Lidgren.Network/Encryption/NetCryptoProviderEncryption.cs @@ -0,0 +1,59 @@ +using System; +using System.IO; +using System.Security.Cryptography; + +namespace Lidgren.Network +{ + public abstract class NetCryptoProviderEncryption : NetEncryption + { + public NetCryptoProviderEncryption(NetPeer peer) + : base(peer) + { + } + + protected abstract CryptoStream GetEncryptStream(MemoryStream ms); + + protected abstract CryptoStream GetDecryptStream(MemoryStream ms); + + public override bool Encrypt(NetOutgoingMessage msg) + { + int unEncLenBits = msg.LengthBits; + + var ms = new MemoryStream(); + var cs = GetEncryptStream(ms); + cs.Write(msg.m_data, 0, msg.LengthBytes); + cs.Close(); + + // get results + var arr = ms.ToArray(); + ms.Close(); + + msg.EnsureBufferSize((arr.Length + 4) * 8); + msg.LengthBits = 0; // reset write pointer + msg.Write((uint)unEncLenBits); + msg.Write(arr); + msg.LengthBits = (arr.Length + 4) * 8; + + return true; + } + + public override bool Decrypt(NetIncomingMessage msg) + { + int unEncLenBits = (int)msg.ReadUInt32(); + + var ms = new MemoryStream(msg.m_data, 4, msg.LengthBytes - 4); + var cs = GetDecryptStream(ms); + + var result = m_peer.GetStorage(unEncLenBits); + cs.Read(result, 0, NetUtility.BytesToHoldBits(unEncLenBits)); + cs.Close(); + + // TODO: recycle existing msg + + msg.m_data = result; + msg.m_bitLength = unEncLenBits; + + return true; + } + } +} diff --git a/Lidgren.Network/Encryption/NetXteaEncryption.cs b/Lidgren.Network/Encryption/NetXteaEncryption.cs index ed1d0ee..9e6ce4b 100644 --- a/Lidgren.Network/Encryption/NetXteaEncryption.cs +++ b/Lidgren.Network/Encryption/NetXteaEncryption.cs @@ -83,14 +83,14 @@ namespace Lidgren.Network /// String to hash for key /// public NetXtea(NetPeer peer, string key) - : this(peer, NetUtility.CreateSHA1Hash(key), 32) + : this(peer, NetUtility.ComputeSHAHash(Encoding.UTF8.GetBytes(key)), 32) { } public override void SetKey(byte[] data, int offset, int length) { - var key = NetUtility.CreateSHA1Hash(data, offset, length); - NetException.Assert(key.Length == 16); + var key = NetUtility.ComputeSHAHash(data, offset, length); + NetException.Assert(key.Length >= 16); SetKey(key, 0, 16); } diff --git a/Lidgren.Network/Lidgren.Network.csproj b/Lidgren.Network/Lidgren.Network.csproj index 4ee2910..608b942 100644 --- a/Lidgren.Network/Lidgren.Network.csproj +++ b/Lidgren.Network/Lidgren.Network.csproj @@ -136,6 +136,10 @@ + + + + diff --git a/Lidgren.Network/NetBigInteger.cs b/Lidgren.Network/NetBigInteger.cs index 8f57fd7..f9d307b 100644 --- a/Lidgren.Network/NetBigInteger.cs +++ b/Lidgren.Network/NetBigInteger.cs @@ -2334,4 +2334,19 @@ namespace Lidgren.Network return ((word >> (n % 32)) & 1) > 0; } } + +#if WINDOWS_RUNTIME + internal sealed class Stack + { + private System.Collections.Generic.List m_list = new System.Collections.Generic.List(); + public int Count { get { return m_list.Count; } } + public void Push(object item) { m_list.Add(item); } + public object Pop() + { + var item = m_list[m_list.Count - 1]; + m_list.RemoveAt(m_list.Count - 1); + return item; + } + } +#endif } \ No newline at end of file diff --git a/Lidgren.Network/NetBuffer.Read.cs b/Lidgren.Network/NetBuffer.Read.cs index c6ec6a6..84c3e7c 100644 --- a/Lidgren.Network/NetBuffer.Read.cs +++ b/Lidgren.Network/NetBuffer.Read.cs @@ -4,6 +4,10 @@ using System.Text; using System.Reflection; using System.Net; +#if !__NOIPENDPOINT__ +using NetEndPoint = System.Net.IPEndPoint; +#endif + namespace Lidgren.Network { /// @@ -638,14 +642,14 @@ namespace Lidgren.Network /// /// Reads a stored IPv4 endpoint description /// - public IPEndPoint ReadIPEndPoint() + public NetEndPoint ReadIPEndPoint() { byte len = ReadByte(); byte[] addressBytes = ReadBytes(len); int port = (int)ReadUInt16(); - IPAddress address = new IPAddress(addressBytes); - return new IPEndPoint(address, port); + var address = NetUtility.CreateAddressFromBytes(addressBytes); + return new NetEndPoint(address, port); } /// diff --git a/Lidgren.Network/NetClient.cs b/Lidgren.Network/NetClient.cs index 9a08d1a..06b88a4 100644 --- a/Lidgren.Network/NetClient.cs +++ b/Lidgren.Network/NetClient.cs @@ -19,6 +19,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. using System; using System.Net; +#if !__NOIPENDPOINT__ +using NetEndPoint = System.Net.IPEndPoint; +#endif + namespace Lidgren.Network { /// @@ -80,7 +84,7 @@ namespace Lidgren.Network /// The remote endpoint to connect to /// The hail message to pass /// server connection, or null if already connected - public override NetConnection Connect(IPEndPoint remoteEndPoint, NetOutgoingMessage hailMessage) + public override NetConnection Connect(NetEndPoint remoteEndPoint, NetOutgoingMessage hailMessage) { lock (m_connections) { diff --git a/Lidgren.Network/NetConnection.Handshake.cs b/Lidgren.Network/NetConnection.Handshake.cs index 36cbf08..31d37ab 100644 --- a/Lidgren.Network/NetConnection.Handshake.cs +++ b/Lidgren.Network/NetConnection.Handshake.cs @@ -3,6 +3,10 @@ using System.Collections.Generic; using System.Text; using System.Threading; +#if !__NOIPENDPOINT__ +using NetEndPoint = System.Net.IPEndPoint; +#endif + namespace Lidgren.Network { public partial class NetConnection @@ -167,7 +171,7 @@ namespace Lidgren.Network if (onLibraryThread) m_peer.SendLibrary(om, m_remoteEndPoint); else - m_peer.m_unsentUnconnectedMessages.Enqueue(new NetTuple(m_remoteEndPoint, om)); + m_peer.m_unsentUnconnectedMessages.Enqueue(new NetTuple(m_remoteEndPoint, om)); m_lastHandshakeSendTime = now; m_handshakeAttempts++; @@ -189,7 +193,7 @@ namespace Lidgren.Network if (onLibraryThread) m_peer.SendLibrary(om, m_remoteEndPoint); else - m_peer.m_unsentUnconnectedMessages.Enqueue(new NetTuple(m_remoteEndPoint, om)); + m_peer.m_unsentUnconnectedMessages.Enqueue(new NetTuple(m_remoteEndPoint, om)); } private void WriteLocalHail(NetOutgoingMessage om) diff --git a/Lidgren.Network/NetConnection.cs b/Lidgren.Network/NetConnection.cs index 6aa71de..428c231 100644 --- a/Lidgren.Network/NetConnection.cs +++ b/Lidgren.Network/NetConnection.cs @@ -3,6 +3,10 @@ using System.Net; using System.Threading; using System.Diagnostics; +#if !__NOIPENDPOINT__ +using NetEndPoint = System.Net.IPEndPoint; +#endif + namespace Lidgren.Network { /// @@ -18,7 +22,7 @@ namespace Lidgren.Network internal NetPeerConfiguration m_peerConfiguration; internal NetConnectionStatus m_status; internal NetConnectionStatus m_visibleStatus; - internal IPEndPoint m_remoteEndPoint; + internal NetEndPoint m_remoteEndPoint; internal NetSenderChannelBase[] m_sendChannels; internal NetReceiverChannelBase[] m_receiveChannels; internal NetOutgoingMessage m_localHailMessage; @@ -57,7 +61,7 @@ namespace Lidgren.Network /// /// Gets the remote endpoint for the connection /// - public IPEndPoint RemoteEndPoint { get { return m_remoteEndPoint; } } + public NetEndPoint RemoteEndPoint { get { return m_remoteEndPoint; } } /// /// Gets the unique identifier of the remote NetPeer for this connection @@ -78,7 +82,7 @@ namespace Lidgren.Network return 0.025 + (avgRtt * 2.1); // 25 ms + double rtt } - internal NetConnection(NetPeer peer, IPEndPoint remoteEndPoint) + internal NetConnection(NetPeer peer, NetEndPoint remoteEndPoint) { m_peer = peer; m_peerConfiguration = m_peer.Configuration; @@ -97,7 +101,7 @@ namespace Lidgren.Network /// /// Change the internal endpoint to this new one. Used when, during handshake, a switch in port is detected (due to NAT) /// - internal void MutateEndPoint(IPEndPoint endPoint) + internal void MutateEndPoint(NetEndPoint endPoint) { m_remoteEndPoint = endPoint; } diff --git a/Lidgren.Network/NetIncomingMessage.cs b/Lidgren.Network/NetIncomingMessage.cs index 617c0f5..cd9db56 100644 --- a/Lidgren.Network/NetIncomingMessage.cs +++ b/Lidgren.Network/NetIncomingMessage.cs @@ -20,6 +20,10 @@ using System; using System.Net; using System.Diagnostics; +#if !__NOIPENDPOINT__ +using NetEndPoint = System.Net.IPEndPoint; +#endif + namespace Lidgren.Network { /// @@ -29,7 +33,7 @@ namespace Lidgren.Network public sealed class NetIncomingMessage : NetBuffer { internal NetIncomingMessageType m_incomingMessageType; - internal IPEndPoint m_senderEndPoint; + internal NetEndPoint m_senderEndPoint; internal NetConnection m_senderConnection; internal int m_sequenceNumber; internal NetMessageType m_receivedMessageType; @@ -52,9 +56,9 @@ namespace Lidgren.Network public int SequenceChannel { get { return (int)m_receivedMessageType - (int)NetUtility.GetDeliveryMethod(m_receivedMessageType); } } /// - /// IPEndPoint of sender, if any + /// endpoint of sender, if any /// - public IPEndPoint SenderEndPoint { get { return m_senderEndPoint; } } + public NetEndPoint SenderEndPoint { get { return m_senderEndPoint; } } /// /// NetConnection of sender, if any diff --git a/Lidgren.Network/NetNatIntroduction.cs b/Lidgren.Network/NetNatIntroduction.cs index e59067a..d134e14 100644 --- a/Lidgren.Network/NetNatIntroduction.cs +++ b/Lidgren.Network/NetNatIntroduction.cs @@ -3,6 +3,10 @@ using System.Collections.Generic; using System.Net; using System.Threading; +#if !__NOIPENDPOINT__ +using NetEndPoint = System.Net.IPEndPoint; +#endif + namespace Lidgren.Network { public partial class NetPeer @@ -11,10 +15,10 @@ namespace Lidgren.Network /// Send NetIntroduction to hostExternal and clientExternal; introducing client to host /// public void Introduce( - IPEndPoint hostInternal, - IPEndPoint hostExternal, - IPEndPoint clientInternal, - IPEndPoint clientExternal, + NetEndPoint hostInternal, + NetEndPoint hostExternal, + NetEndPoint clientInternal, + NetEndPoint clientExternal, string token) { // send message to client @@ -25,7 +29,7 @@ namespace Lidgren.Network um.Write(hostExternal); um.Write(token); Interlocked.Increment(ref um.m_recyclingCount); - m_unsentUnconnectedMessages.Enqueue(new NetTuple(clientExternal, um)); + m_unsentUnconnectedMessages.Enqueue(new NetTuple(clientExternal, um)); // send message to host um = CreateMessage(10 + token.Length + 1); @@ -35,7 +39,7 @@ namespace Lidgren.Network um.Write(clientExternal); um.Write(token); Interlocked.Increment(ref um.m_recyclingCount); - m_unsentUnconnectedMessages.Enqueue(new NetTuple(hostExternal, um)); + m_unsentUnconnectedMessages.Enqueue(new NetTuple(hostExternal, um)); } /// @@ -49,8 +53,8 @@ namespace Lidgren.Network NetIncomingMessage tmp = SetupReadHelperMessage(ptr, 1000); // never mind length byte hostByte = tmp.ReadByte(); - IPEndPoint remoteInternal = tmp.ReadIPEndPoint(); - IPEndPoint remoteExternal = tmp.ReadIPEndPoint(); + NetEndPoint remoteInternal = tmp.ReadIPEndPoint(); + NetEndPoint remoteExternal = tmp.ReadIPEndPoint(); string token = tmp.ReadString(); bool isHost = (hostByte != 0); @@ -67,7 +71,7 @@ namespace Lidgren.Network punch.Write(hostByte); punch.Write(token); Interlocked.Increment(ref punch.m_recyclingCount); - m_unsentUnconnectedMessages.Enqueue(new NetTuple(remoteInternal, punch)); + m_unsentUnconnectedMessages.Enqueue(new NetTuple(remoteInternal, punch)); LogDebug("NAT punch sent to " + remoteInternal); // send external punch @@ -76,7 +80,7 @@ namespace Lidgren.Network punch.Write(hostByte); punch.Write(token); Interlocked.Increment(ref punch.m_recyclingCount); - m_unsentUnconnectedMessages.Enqueue(new NetTuple(remoteExternal, punch)); + m_unsentUnconnectedMessages.Enqueue(new NetTuple(remoteExternal, punch)); LogDebug("NAT punch sent to " + remoteExternal); } @@ -84,7 +88,7 @@ namespace Lidgren.Network /// /// Called when receiving a NatPunchMessage from a remote endpoint /// - private void HandleNatPunch(int ptr, IPEndPoint senderEndPoint) + private void HandleNatPunch(int ptr, NetEndPoint senderEndPoint) { NetIncomingMessage tmp = SetupReadHelperMessage(ptr, 1000); // never mind length @@ -100,7 +104,7 @@ namespace Lidgren.Network LogDebug("NAT punch received from " + senderEndPoint + " we're client, so we've succeeded - token is " + token); // - // Release punch success to client; enabling him to Connect() to msg.SenderIPEndPoint if token is ok + // Release punch success to client; enabling him to Connect() to msg.Sender if token is ok // NetIncomingMessage punchSuccess = CreateIncomingMessage(NetIncomingMessageType.NatIntroductionSuccess, 10); punchSuccess.m_senderEndPoint = senderEndPoint; @@ -113,7 +117,7 @@ namespace Lidgren.Network punch.Write((byte)0); punch.Write(token); Interlocked.Increment(ref punch.m_recyclingCount); - m_unsentUnconnectedMessages.Enqueue(new NetTuple(senderEndPoint, punch)); + m_unsentUnconnectedMessages.Enqueue(new NetTuple(senderEndPoint, punch)); } } } diff --git a/Lidgren.Network/NetPeer.Discovery.cs b/Lidgren.Network/NetPeer.Discovery.cs index 7786732..d5d3a97 100644 --- a/Lidgren.Network/NetPeer.Discovery.cs +++ b/Lidgren.Network/NetPeer.Discovery.cs @@ -2,6 +2,10 @@ using System.Net; using System.Threading; +#if !__NOIPENDPOINT__ +using NetEndPoint = System.Net.IPEndPoint; +#endif + namespace Lidgren.Network { public partial class NetPeer @@ -14,7 +18,8 @@ namespace Lidgren.Network NetOutgoingMessage um = CreateMessage(0); um.m_messageType = NetMessageType.Discovery; Interlocked.Increment(ref um.m_recyclingCount); - m_unsentUnconnectedMessages.Enqueue(new NetTuple(new IPEndPoint(IPAddress.Broadcast, serverPort), um)); + + m_unsentUnconnectedMessages.Enqueue(new NetTuple(new NetEndPoint(NetUtility.GetBroadcastAddress(), serverPort), um)); } /// @@ -22,28 +27,28 @@ namespace Lidgren.Network /// public bool DiscoverKnownPeer(string host, int serverPort) { - IPAddress address = NetUtility.Resolve(host); + var address = NetUtility.Resolve(host); if (address == null) return false; - DiscoverKnownPeer(new IPEndPoint(address, serverPort)); + DiscoverKnownPeer(new NetEndPoint(address, serverPort)); return true; } /// /// Emit a discovery signal to a single known host /// - public void DiscoverKnownPeer(IPEndPoint endPoint) + public void DiscoverKnownPeer(NetEndPoint endPoint) { NetOutgoingMessage om = CreateMessage(0); om.m_messageType = NetMessageType.Discovery; om.m_recyclingCount = 1; - m_unsentUnconnectedMessages.Enqueue(new NetTuple(endPoint, om)); + m_unsentUnconnectedMessages.Enqueue(new NetTuple(endPoint, om)); } /// /// Send a discovery response message /// - public void SendDiscoveryResponse(NetOutgoingMessage msg, IPEndPoint recipient) + public void SendDiscoveryResponse(NetOutgoingMessage msg, NetEndPoint recipient) { if (recipient == null) throw new ArgumentNullException("recipient"); @@ -58,7 +63,7 @@ namespace Lidgren.Network msg.m_messageType = NetMessageType.DiscoveryResponse; Interlocked.Increment(ref msg.m_recyclingCount); - m_unsentUnconnectedMessages.Enqueue(new NetTuple(recipient, msg)); + m_unsentUnconnectedMessages.Enqueue(new NetTuple(recipient, msg)); } } } diff --git a/Lidgren.Network/NetPeer.Internal.cs b/Lidgren.Network/NetPeer.Internal.cs index bef2440..aa7576a 100644 --- a/Lidgren.Network/NetPeer.Internal.cs +++ b/Lidgren.Network/NetPeer.Internal.cs @@ -1,8 +1,4 @@ -#if !__ANDROID__ && !IOS && !UNITY_WEBPLAYER && !UNITY_ANDROID && !UNITY_IPHONE -#define IS_MAC_AVAILABLE -#endif - -using System; +using System; using System.Net; using System.Threading; using System.Diagnostics; @@ -10,6 +6,10 @@ using System.Security.Cryptography; using System.Net.Sockets; using System.Collections.Generic; +#if !__NOIPENDPOINT__ +using NetEndPoint = System.Net.IPEndPoint; +#endif + namespace Lidgren.Network { public partial class NetPeer @@ -30,9 +30,9 @@ namespace Lidgren.Network internal readonly NetPeerConfiguration m_configuration; private readonly NetQueue m_releasedIncomingMessages; - internal readonly NetQueue> m_unsentUnconnectedMessages; + internal readonly NetQueue> m_unsentUnconnectedMessages; - internal Dictionary m_handshakes; + internal Dictionary m_handshakes; internal readonly NetPeerStatistics m_statistics; internal long m_uniqueIdentifier; @@ -133,7 +133,7 @@ namespace Lidgren.Network m_socket.SendBufferSize = m_configuration.SendBufferSize; m_socket.Blocking = false; - var ep = (EndPoint)new IPEndPoint(m_configuration.LocalAddress, reBind ? m_listenPort : m_configuration.Port); + var ep = (EndPoint)new NetEndPoint(m_configuration.LocalAddress, reBind ? m_listenPort : m_configuration.Port); m_socket.Bind(ep); try @@ -148,7 +148,7 @@ namespace Lidgren.Network // ignore; SIO_UDP_CONNRESET not supported on this platform } - IPEndPoint boundEp = m_socket.LocalEndPoint as IPEndPoint; + var boundEp = m_socket.LocalEndPoint as NetEndPoint; LogDebug("Socket bound to " + boundEp + ": " + m_socket.IsBound); m_listenPort = boundEp.Port; } @@ -179,34 +179,14 @@ namespace Lidgren.Network m_readHelperMessage = new NetIncomingMessage(NetIncomingMessageType.Error); m_readHelperMessage.m_data = m_receiveBuffer; - byte[] macBytes = new byte[8]; - MWCRandom.Instance.NextBytes(macBytes); + byte[] macBytes = NetUtility.GetMacAddressBytes(); -#if IS_MAC_AVAILABLE - try - { - System.Net.NetworkInformation.PhysicalAddress pa = NetUtility.GetMacAddress(); - if (pa != null) - { - macBytes = pa.GetAddressBytes(); - LogVerbose("Mac address is " + NetUtility.ToHexString(macBytes)); - } - else - { - LogWarning("Failed to get Mac address"); - } - } - catch (NotSupportedException) - { - // not supported; lets just keep the random bytes set above - } -#endif - IPEndPoint boundEp = m_socket.LocalEndPoint as IPEndPoint; + var boundEp = m_socket.LocalEndPoint as NetEndPoint; byte[] epBytes = BitConverter.GetBytes(boundEp.GetHashCode()); byte[] combined = new byte[epBytes.Length + macBytes.Length]; Array.Copy(epBytes, 0, combined, 0, epBytes.Length); Array.Copy(macBytes, 0, combined, epBytes.Length, macBytes.Length); - m_uniqueIdentifier = BitConverter.ToInt64(NetUtility.CreateSHA1Hash(combined), 0); + m_uniqueIdentifier = BitConverter.ToInt64(NetUtility.ComputeSHAHash(combined), 0); m_status = NetPeerStatus.Running; } @@ -270,8 +250,8 @@ namespace Lidgren.Network // one final heartbeat, will send stuff and do disconnect Heartbeat(); - Thread.Sleep(10); - + NetUtility.Sleep(10); + lock (m_initializeLock) { try @@ -393,7 +373,7 @@ namespace Lidgren.Network m_executeFlushSendQueue = false; // send unsent unconnected messages - NetTuple unsent; + NetTuple unsent; while (m_unsentUnconnectedMessages.TryDequeue(out unsent)) { NetOutgoingMessage om = unsent.Item2; @@ -458,7 +438,7 @@ namespace Lidgren.Network //LogVerbose("Received " + bytesReceived + " bytes"); - IPEndPoint ipsender = (IPEndPoint)m_senderRemote; + var ipsender = (NetEndPoint)m_senderRemote; if (m_upnp != null && now < m_upnp.m_discoveryResponseDeadline && bytesReceived > 32) { @@ -596,7 +576,7 @@ namespace Lidgren.Network m_executeFlushSendQueue = true; } - internal void HandleIncomingDiscoveryRequest(double now, IPEndPoint senderEndPoint, int ptr, int payloadByteLength) + internal void HandleIncomingDiscoveryRequest(double now, NetEndPoint senderEndPoint, int ptr, int payloadByteLength) { if (m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.DiscoveryRequest)) { @@ -610,7 +590,7 @@ namespace Lidgren.Network } } - internal void HandleIncomingDiscoveryResponse(double now, IPEndPoint senderEndPoint, int ptr, int payloadByteLength) + internal void HandleIncomingDiscoveryResponse(double now, NetEndPoint senderEndPoint, int ptr, int payloadByteLength) { if (m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.DiscoveryResponse)) { @@ -624,7 +604,7 @@ namespace Lidgren.Network } } - private void ReceivedUnconnectedLibraryMessage(double now, IPEndPoint senderEndPoint, NetMessageType tp, int ptr, int payloadByteLength) + private void ReceivedUnconnectedLibraryMessage(double now, NetEndPoint senderEndPoint, NetMessageType tp, int ptr, int payloadByteLength) { NetConnection shake; if (m_handshakes.TryGetValue(senderEndPoint, out shake)) diff --git a/Lidgren.Network/NetPeer.LatencySimulation.cs b/Lidgren.Network/NetPeer.LatencySimulation.cs index 36518af..d93fabe 100644 --- a/Lidgren.Network/NetPeer.LatencySimulation.cs +++ b/Lidgren.Network/NetPeer.LatencySimulation.cs @@ -25,6 +25,10 @@ using System.Net; using System.Net.Sockets; using System.Diagnostics; +#if !__NOIPENDPOINT__ +using NetEndPoint = System.Net.IPEndPoint; +#endif + namespace Lidgren.Network { public partial class NetPeer @@ -37,10 +41,10 @@ namespace Lidgren.Network { public byte[] Data; public double DelayedUntil; - public IPEndPoint Target; + public NetEndPoint Target; } - internal void SendPacket(int numBytes, IPEndPoint target, int numMessages, out bool connectionReset) + internal void SendPacket(int numBytes, NetEndPoint target, int numMessages, out bool connectionReset) { connectionReset = false; @@ -128,13 +132,13 @@ namespace Lidgren.Network catch { } } - internal bool ActuallySendPacket(byte[] data, int numBytes, IPEndPoint target, out bool connectionReset) + internal bool ActuallySendPacket(byte[] data, int numBytes, NetEndPoint target, out bool connectionReset) { connectionReset = false; try { // TODO: refactor this check outta here - if (target.Address == IPAddress.Broadcast) + if (target.Address == NetUtility.GetBroadcastAddress()) { // Some networks do not allow // a global broadcast so we use the BroadcastAddress from the configuration @@ -177,7 +181,7 @@ namespace Lidgren.Network return true; } - internal bool SendMTUPacket(int numBytes, IPEndPoint target) + internal bool SendMTUPacket(int numBytes, NetEndPoint target) { try { @@ -213,7 +217,7 @@ namespace Lidgren.Network return true; } #else - internal bool SendMTUPacket(int numBytes, IPEndPoint target) + internal bool SendMTUPacket(int numBytes, NetEndPoint target) { try { @@ -250,7 +254,7 @@ namespace Lidgren.Network // // Release - just send the packet straight away // - internal void SendPacket(int numBytes, IPEndPoint target, int numMessages, out bool connectionReset) + internal void SendPacket(int numBytes, NetEndPoint target, int numMessages, out bool connectionReset) { #if USE_RELEASE_STATISTICS m_statistics.PacketSent(numBytes, numMessages); @@ -259,7 +263,7 @@ namespace Lidgren.Network try { // TODO: refactor this check outta here - if (target.Address == IPAddress.Broadcast) + if (target.Address == NetUtility.GetBroadcastAddress()) m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true); int bytesSent = m_socket.SendTo(m_sendBuffer, 0, numBytes, SocketFlags.None, target); @@ -288,7 +292,7 @@ namespace Lidgren.Network } finally { - if (target.Address == IPAddress.Broadcast) + if (target.Address == NetUtility.GetBroadcastAddress()) m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, false); } return; diff --git a/Lidgren.Network/NetPeer.Send.cs b/Lidgren.Network/NetPeer.Send.cs index f803b1a..57faef4 100644 --- a/Lidgren.Network/NetPeer.Send.cs +++ b/Lidgren.Network/NetPeer.Send.cs @@ -3,6 +3,10 @@ using System.Collections.Generic; using System.Threading; using System.Net; +#if !__NOIPENDPOINT__ +using NetEndPoint = System.Net.IPEndPoint; +#endif + namespace Lidgren.Network { public partial class NetPeer @@ -153,18 +157,18 @@ namespace Lidgren.Network msg.m_isSent = true; msg.m_messageType = NetMessageType.Unconnected; - IPAddress adr = NetUtility.Resolve(host); + var adr = NetUtility.Resolve(host); if (adr == null) throw new NetException("Failed to resolve " + host); Interlocked.Increment(ref msg.m_recyclingCount); - m_unsentUnconnectedMessages.Enqueue(new NetTuple(new IPEndPoint(adr, port), msg)); + m_unsentUnconnectedMessages.Enqueue(new NetTuple(new NetEndPoint(adr, port), msg)); } /// /// Send a message to an unconnected host /// - public void SendUnconnectedMessage(NetOutgoingMessage msg, IPEndPoint recipient) + public void SendUnconnectedMessage(NetOutgoingMessage msg, NetEndPoint recipient) { if (msg == null) throw new ArgumentNullException("msg"); @@ -179,13 +183,13 @@ namespace Lidgren.Network msg.m_isSent = true; Interlocked.Increment(ref msg.m_recyclingCount); - m_unsentUnconnectedMessages.Enqueue(new NetTuple(recipient, msg)); + m_unsentUnconnectedMessages.Enqueue(new NetTuple(recipient, msg)); } /// /// Send a message to an unconnected host /// - public void SendUnconnectedMessage(NetOutgoingMessage msg, IList recipients) + public void SendUnconnectedMessage(NetOutgoingMessage msg, IList recipients) { if (msg == null) throw new ArgumentNullException("msg"); @@ -202,8 +206,8 @@ namespace Lidgren.Network msg.m_isSent = true; Interlocked.Add(ref msg.m_recyclingCount, recipients.Count); - foreach(IPEndPoint ep in recipients) - m_unsentUnconnectedMessages.Enqueue(new NetTuple(ep, msg)); + foreach (NetEndPoint ep in recipients) + m_unsentUnconnectedMessages.Enqueue(new NetTuple(ep, msg)); } /// @@ -231,7 +235,7 @@ namespace Lidgren.Network im.m_isFragment = false; im.m_receiveTime = NetTime.Now; im.m_senderConnection = null; - im.m_senderEndPoint = m_socket.LocalEndPoint as IPEndPoint; + im.m_senderEndPoint = m_socket.LocalEndPoint as NetEndPoint; NetException.Assert(im.m_bitLength == om.LengthBits); // recycle outgoing message diff --git a/Lidgren.Network/NetPeer.cs b/Lidgren.Network/NetPeer.cs index 69ae45b..8590e8e 100644 --- a/Lidgren.Network/NetPeer.cs +++ b/Lidgren.Network/NetPeer.cs @@ -3,6 +3,10 @@ using System.Threading; using System.Collections.Generic; using System.Net; +#if !__NOIPENDPOINT__ +using NetEndPoint = System.Net.IPEndPoint; +#endif + namespace Lidgren.Network { /// @@ -17,7 +21,7 @@ namespace Lidgren.Network private object m_messageReceivedEventCreationLock = new object(); internal readonly List m_connections; - private readonly Dictionary m_connectionLookup; + private readonly Dictionary m_connectionLookup; private string m_shutdownReason; @@ -113,11 +117,11 @@ namespace Lidgren.Network m_configuration = config; m_statistics = new NetPeerStatistics(this); m_releasedIncomingMessages = new NetQueue(4); - m_unsentUnconnectedMessages = new NetQueue>(2); + m_unsentUnconnectedMessages = new NetQueue>(2); m_connections = new List(); - m_connectionLookup = new Dictionary(); - m_handshakes = new Dictionary(); - m_senderRemote = (EndPoint)new IPEndPoint(IPAddress.Any, 0); + m_connectionLookup = new Dictionary(); + m_handshakes = new Dictionary(); + m_senderRemote = (EndPoint)new NetEndPoint(IPAddress.Any, 0); m_status = NetPeerStatus.NotRunning; m_receivedFragmentGroups = new Dictionary>(); } @@ -156,13 +160,13 @@ namespace Lidgren.Network m_upnp.Discover(this); // allow some time for network thread to start up in case they call Connect() or UPnP calls immediately - Thread.Sleep(50); + NetUtility.Sleep(50); } /// /// Get the connection, if any, for a certain remote endpoint /// - public NetConnection GetConnection(IPEndPoint ep) + public NetConnection GetConnection(NetEndPoint ep) { NetConnection retval; @@ -226,7 +230,7 @@ namespace Lidgren.Network } // send message immediately and recycle it - internal void SendLibrary(NetOutgoingMessage msg, IPEndPoint recipient) + internal void SendLibrary(NetOutgoingMessage msg, NetEndPoint recipient) { VerifyNetworkThread(); NetException.Assert(msg.m_isSent == false); @@ -245,7 +249,7 @@ namespace Lidgren.Network /// public NetConnection Connect(string host, int port) { - return Connect(new IPEndPoint(NetUtility.Resolve(host), port), null); + return Connect(new NetEndPoint(NetUtility.Resolve(host), port), null); } /// @@ -253,13 +257,13 @@ namespace Lidgren.Network /// public NetConnection Connect(string host, int port, NetOutgoingMessage hailMessage) { - return Connect(new IPEndPoint(NetUtility.Resolve(host), port), hailMessage); + return Connect(new NetEndPoint(NetUtility.Resolve(host), port), hailMessage); } /// /// Create a connection to a remote endpoint /// - public NetConnection Connect(IPEndPoint remoteEndPoint) + public NetConnection Connect(NetEndPoint remoteEndPoint) { return Connect(remoteEndPoint, null); } @@ -267,7 +271,7 @@ namespace Lidgren.Network /// /// Create a connection to a remote endpoint /// - public virtual NetConnection Connect(IPEndPoint remoteEndPoint, NetOutgoingMessage hailMessage) + public virtual NetConnection Connect(NetEndPoint remoteEndPoint, NetOutgoingMessage hailMessage) { if (remoteEndPoint == null) throw new ArgumentNullException("remoteEndPoint"); @@ -319,12 +323,8 @@ namespace Lidgren.Network /// /// Send raw bytes; only used for debugging /// -#if DEBUG - public void RawSend(byte[] arr, int offset, int length, IPEndPoint destination) -#else - public void RawSend(byte[] arr, int offset, int length, IPEndPoint destination) -#endif - { + public void RawSend(byte[] arr, int offset, int length, NetEndPoint destination) + { // wrong thread - this miiiight crash with network thread... but what's a boy to do. Array.Copy(arr, offset, m_sendBuffer, 0, length); bool unused; diff --git a/Lidgren.Network/NetRandomSeed.cs b/Lidgren.Network/NetRandomSeed.cs index 78f3b1a..9b868fb 100644 --- a/Lidgren.Network/NetRandomSeed.cs +++ b/Lidgren.Network/NetRandomSeed.cs @@ -28,20 +28,18 @@ namespace Lidgren.Network [CLSCompliant(false)] public static ulong GetUInt64() { -#if !__ANDROID__ && !IOS && !UNITY_WEBPLAYER && !UNITY_ANDROID && !UNITY_IPHONE - ulong seed = (ulong)System.Diagnostics.Stopwatch.GetTimestamp(); - seed ^= (ulong)Environment.WorkingSet; - ulong s2 = (ulong)Interlocked.Increment(ref m_seedIncrement); - s2 |= (((ulong)Guid.NewGuid().GetHashCode()) << 32); - seed ^= s2; -#else - ulong seed = (ulong)Environment.TickCount; - seed |= (((ulong)(new object().GetHashCode())) << 32); - ulong s2 = (ulong)Guid.NewGuid().GetHashCode(); - s2 |= (((ulong)Interlocked.Increment(ref m_seedIncrement)) << 32); - seed ^= s2; -#endif - return seed; + var guidBytes = Guid.NewGuid().ToByteArray(); + ulong seed = + ((ulong)guidBytes[0] << (8 * 0)) | + ((ulong)guidBytes[1] << (8 * 1)) | + ((ulong)guidBytes[2] << (8 * 2)) | + ((ulong)guidBytes[3] << (8 * 3)) | + ((ulong)guidBytes[4] << (8 * 4)) | + ((ulong)guidBytes[5] << (8 * 5)) | + ((ulong)guidBytes[6] << (8 * 6)) | + ((ulong)guidBytes[7] << (8 * 7)); + + return seed ^ NetUtility.GetPlatformSeed(m_seedIncrement); } } } diff --git a/Lidgren.Network/NetSRP.cs b/Lidgren.Network/NetSRP.cs index 4e2f6f0..c6f8d27 100644 --- a/Lidgren.Network/NetSRP.cs +++ b/Lidgren.Network/NetSRP.cs @@ -14,17 +14,7 @@ namespace Lidgren.Network private static readonly NetBigInteger N = new NetBigInteger("0115b8b692e0e045692cf280b436735c77a5a9e8a9e7ed56c965f87db5b2a2ece3", 16); private static readonly NetBigInteger g = NetBigInteger.Two; private static readonly NetBigInteger k = ComputeMultiplier(); - - private static HashAlgorithm GetHashAlgorithm() - { -#if USE_SHA256 - // this does not seem to work as of yet - return SHA256.Create(); -#else - return SHA1.Create(); -#endif - } - + /// /// Compute multiplier (k) /// @@ -36,9 +26,7 @@ namespace Lidgren.Network string ccstr = one + two.PadLeft(one.Length, '0'); byte[] cc = NetUtility.ToByteArray(ccstr); - var sha = GetHashAlgorithm(); - var ccHashed = sha.ComputeHash(cc); - + var ccHashed = NetUtility.ComputeSHAHash(cc); return new NetBigInteger(NetUtility.ToHexString(ccHashed), 16); } @@ -67,17 +55,15 @@ namespace Lidgren.Network /// public static byte[] ComputePrivateKey(string username, string password, byte[] salt) { - var sha = GetHashAlgorithm(); - byte[] tmp = Encoding.UTF8.GetBytes(username + ":" + password); - byte[] innerHash = sha.ComputeHash(tmp); + byte[] innerHash = NetUtility.ComputeSHAHash(tmp); byte[] total = new byte[innerHash.Length + salt.Length]; Buffer.BlockCopy(salt, 0, total, 0, salt.Length); Buffer.BlockCopy(innerHash, 0, total, salt.Length, innerHash.Length); // x ie. H(salt || H(username || ":" || password)) - return new NetBigInteger(NetUtility.ToHexString(sha.ComputeHash(total)), 16).ToByteArrayUnsigned(); + return new NetBigInteger(NetUtility.ToHexString(NetUtility.ComputeSHAHash(total)), 16).ToByteArrayUnsigned(); } /// @@ -93,15 +79,6 @@ namespace Lidgren.Network return serverVerifier.ToByteArrayUnsigned(); } - /// - /// SHA hash data - /// - public static byte[] Hash(byte[] data) - { - var sha = GetHashAlgorithm(); - return sha.ComputeHash(data); - } - /// /// Compute client public ephemeral value (A) /// @@ -144,8 +121,7 @@ namespace Lidgren.Network byte[] cc = NetUtility.ToByteArray(ccstr); - var sha = GetHashAlgorithm(); - var ccHashed = sha.ComputeHash(cc); + var ccHashed = NetUtility.ComputeSHAHash(cc); return new NetBigInteger(NetUtility.ToHexString(ccHashed), 16).ToByteArrayUnsigned(); } @@ -187,8 +163,7 @@ namespace Lidgren.Network /// public static NetXtea CreateEncryption(NetPeer peer, byte[] sessionValue) { - var sha = GetHashAlgorithm(); - var hash = sha.ComputeHash(sessionValue); + var hash = NetUtility.ComputeSHAHash(sessionValue); var key = new byte[16]; for(int i=0;i<16;i++) diff --git a/Lidgren.Network/NetTime.cs b/Lidgren.Network/NetTime.cs index 9e2f59d..57bef62 100644 --- a/Lidgren.Network/NetTime.cs +++ b/Lidgren.Network/NetTime.cs @@ -17,8 +17,6 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR TH USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#define IS_STOPWATCH_AVAILABLE - using System; using System.Collections.Generic; using System.Text; @@ -29,25 +27,8 @@ namespace Lidgren.Network /// /// Time service /// - public static class NetTime + public static partial class NetTime { -#if IS_STOPWATCH_AVAILABLE - private static readonly long s_timeInitialized = Stopwatch.GetTimestamp(); - private static readonly double s_dInvFreq = 1.0 / (double)Stopwatch.Frequency; - - /// - /// Get number of seconds since the application started - /// - public static double Now { get { return (double)(Stopwatch.GetTimestamp() - s_timeInitialized) * s_dInvFreq; } } -#else - private static readonly uint s_timeInitialized = (uint)Environment.TickCount; - - /// - /// Get number of seconds since the application started - /// - public static double Now { get { return (double)((uint)Environment.TickCount - s_timeInitialized) / 1000.0; } } -#endif - /// /// Given seconds it will output a human friendly readable string (milliseconds if less than 60 seconds) /// diff --git a/Lidgren.Network/NetUPnP.cs b/Lidgren.Network/NetUPnP.cs index 8775724..9b44dfa 100644 --- a/Lidgren.Network/NetUPnP.cs +++ b/Lidgren.Network/NetUPnP.cs @@ -5,6 +5,10 @@ using System.Net; using System.Net.Sockets; using System.Threading; +#if !__NOIPENDPOINT__ +using NetEndPoint = System.Net.IPEndPoint; +#endif + namespace Lidgren.Network { /// @@ -73,11 +77,11 @@ namespace Lidgren.Network m_peer.LogDebug("Attempting UPnP discovery"); peer.Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true); - peer.RawSend(arr, 0, arr.Length, new IPEndPoint(IPAddress.Broadcast, 1900)); + peer.RawSend(arr, 0, arr.Length, new NetEndPoint(NetUtility.GetBroadcastAddress(), 1900)); peer.Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, false); // allow some extra time for router to respond - // System.Threading.Thread.Sleep(50); + NetUtility.Sleep(50); m_discoveryResponseDeadline = NetTime.Now + 6.0; // arbitrarily chosen number, router gets 6 seconds to respond m_status = UPnPStatus.Discovering; @@ -182,7 +186,7 @@ namespace Lidgren.Network "AddPortMapping"); m_peer.LogDebug("Sent UPnP port forward request"); - System.Threading.Thread.Sleep(50); + NetUtility.Sleep(50); } catch (Exception ex) { diff --git a/Lidgren.Network/NetUtility.cs b/Lidgren.Network/NetUtility.cs index 4ce9e45..055db86 100644 --- a/Lidgren.Network/NetUtility.cs +++ b/Lidgren.Network/NetUtility.cs @@ -16,17 +16,15 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRA TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#if !__ANDROID__ && !IOS && !UNITY_WEBPLAYER && !UNITY_ANDROID && !UNITY_IPHONE -#define IS_FULL_NET_AVAILABLE + +#if !__NOIPENDPOINT__ +using NetEndPoint = System.Net.IPEndPoint; +using NetAddress = System.Net.IPAddress; #endif using System; using System.Net; -#if IS_FULL_NET_AVAILABLE -using System.Net.NetworkInformation; -#endif - using System.Net.Sockets; using System.Text; using System.Text.RegularExpressions; @@ -38,24 +36,24 @@ namespace Lidgren.Network /// /// Utility methods /// - public static class NetUtility + public static partial class NetUtility { /// /// Resolve endpoint callback /// - public delegate void ResolveEndPointCallback(IPEndPoint endPoint); + public delegate void ResolveEndPointCallback(NetEndPoint endPoint); /// /// Resolve address callback /// - public delegate void ResolveAddressCallback(IPAddress adr); + public delegate void ResolveAddressCallback(NetAddress adr); /// /// Get IPv4 endpoint from notation (xxx.xxx.xxx.xxx) or hostname and port number (asynchronous version) /// public static void ResolveAsync(string ipOrHost, int port, ResolveEndPointCallback callback) { - ResolveAsync(ipOrHost, delegate(IPAddress adr) + ResolveAsync(ipOrHost, delegate(NetAddress adr) { if (adr == null) { @@ -63,7 +61,7 @@ namespace Lidgren.Network } else { - callback(new IPEndPoint(adr, port)); + callback(new NetEndPoint(adr, port)); } }); } @@ -71,10 +69,10 @@ namespace Lidgren.Network /// /// Get IPv4 endpoint from notation (xxx.xxx.xxx.xxx) or hostname and port number /// - public static IPEndPoint Resolve(string ipOrHost, int port) + public static NetEndPoint Resolve(string ipOrHost, int port) { - IPAddress adr = Resolve(ipOrHost); - return new IPEndPoint(adr, port); + var adr = Resolve(ipOrHost); + return new NetEndPoint(adr, port); } /// @@ -87,8 +85,8 @@ namespace Lidgren.Network ipOrHost = ipOrHost.Trim(); - IPAddress ipAddress = null; - if (IPAddress.TryParse(ipOrHost, out ipAddress)) + NetAddress ipAddress = null; + if (NetAddress.TryParse(ipOrHost, out ipAddress)) { if (ipAddress.AddressFamily == AddressFamily.InterNetwork) { @@ -129,7 +127,7 @@ namespace Lidgren.Network } // check each entry for a valid IP address - foreach (IPAddress ipCurrent in entry.AddressList) + foreach (var ipCurrent in entry.AddressList) { if (ipCurrent.AddressFamily == AddressFamily.InterNetwork) { @@ -158,15 +156,15 @@ namespace Lidgren.Network /// /// Get IPv4 address from notation (xxx.xxx.xxx.xxx) or hostname /// - public static IPAddress Resolve(string ipOrHost) + public static NetAddress Resolve(string ipOrHost) { if (string.IsNullOrEmpty(ipOrHost)) throw new ArgumentException("Supplied string must not be empty", "ipOrHost"); ipOrHost = ipOrHost.Trim(); - IPAddress ipAddress = null; - if (IPAddress.TryParse(ipOrHost, out ipAddress)) + NetAddress ipAddress = null; + if (NetAddress.TryParse(ipOrHost, out ipAddress)) { if (ipAddress.AddressFamily == AddressFamily.InterNetwork) return ipAddress; @@ -200,56 +198,6 @@ namespace Lidgren.Network } } -#if IS_FULL_NET_AVAILABLE - - private static NetworkInterface GetNetworkInterface() - { - IPGlobalProperties computerProperties = IPGlobalProperties.GetIPGlobalProperties(); - if (computerProperties == null) - return null; - - NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces(); - if (nics == null || nics.Length < 1) - return null; - - NetworkInterface best = null; - foreach (NetworkInterface adapter in nics) - { - if (adapter.NetworkInterfaceType == NetworkInterfaceType.Loopback || adapter.NetworkInterfaceType == NetworkInterfaceType.Unknown) - continue; - if (!adapter.Supports(NetworkInterfaceComponent.IPv4)) - continue; - if (best == null) - best = adapter; - if (adapter.OperationalStatus != OperationalStatus.Up) - continue; - - // make sure this adapter has any ipv4 addresses - IPInterfaceProperties properties = adapter.GetIPProperties(); - foreach (UnicastIPAddressInformation unicastAddress in properties.UnicastAddresses) - { - if (unicastAddress != null && unicastAddress.Address != null && unicastAddress.Address.AddressFamily == AddressFamily.InterNetwork) - { - // Yes it does, return this network interface. - return adapter; - } - } - } - return best; - } - - /// - /// Returns the physical (MAC) address for the first usable network interface - /// - public static PhysicalAddress GetMacAddress() - { - NetworkInterface ni = GetNetworkInterface(); - if (ni == null) - return null; - return ni.GetPhysicalAddress(); - } -#endif - /// /// Create a hex string from an Int64 value /// @@ -282,123 +230,11 @@ namespace Lidgren.Network } return new string(c); } - - /// - /// Gets the local broadcast address - /// - public static IPAddress GetBroadcastAddress() - { -#if __ANDROID__ - try{ - Android.Net.Wifi.WifiManager wifi = (Android.Net.Wifi.WifiManager)Android.App.Application.Context.GetSystemService(Android.App.Activity.WifiService); - if (wifi.IsWifiEnabled) - { - var dhcp = wifi.DhcpInfo; - - int broadcast = (dhcp.IpAddress & dhcp.Netmask) | ~dhcp.Netmask; - byte[] quads = new byte[4]; - for (int k = 0; k < 4; k++) - { - quads[k] = (byte) ((broadcast >> k * 8) & 0xFF); - } - return new IPAddress(quads); - } - } - catch // Catch Access Denied Errors - { - return IPAddress.Broadcast; - } -#endif -#if IS_FULL_NET_AVAILABLE - try - { - NetworkInterface ni = GetNetworkInterface(); - if (ni == null) - { - return null; - } - IPInterfaceProperties properties = ni.GetIPProperties(); - foreach (UnicastIPAddressInformation unicastAddress in properties.UnicastAddresses) - { - if (unicastAddress != null && unicastAddress.Address != null && unicastAddress.Address.AddressFamily == AddressFamily.InterNetwork) - { - var mask = unicastAddress.IPv4Mask; - byte[] ipAdressBytes = unicastAddress.Address.GetAddressBytes(); - byte[] subnetMaskBytes = mask.GetAddressBytes(); - - if (ipAdressBytes.Length != subnetMaskBytes.Length) - throw new ArgumentException("Lengths of IP address and subnet mask do not match."); - - byte[] broadcastAddress = new byte[ipAdressBytes.Length]; - for (int i = 0; i < broadcastAddress.Length; i++) - { - broadcastAddress[i] = (byte)(ipAdressBytes[i] | (subnetMaskBytes[i] ^ 255)); - } - return new IPAddress(broadcastAddress); - } - } - } - catch // Catch any errors - { - return IPAddress.Broadcast; - } -#endif - return IPAddress.Broadcast; - } - /// - /// Gets my local IPv4 address (not necessarily external) and subnet mask + /// Returns true if the endpoint supplied is on the same subnet as this host /// - public static IPAddress GetMyAddress(out IPAddress mask) - { - mask = null; -#if __ANDROID__ - try - { - Android.Net.Wifi.WifiManager wifi = (Android.Net.Wifi.WifiManager)Android.App.Application.Context.GetSystemService(Android.App.Activity.WifiService); - if (!wifi.IsWifiEnabled) return null; - var dhcp = wifi.DhcpInfo; - - int addr = dhcp.IpAddress; - byte[] quads = new byte[4]; - for (int k = 0; k < 4; k++) - { - quads[k] = (byte) ((addr >> k * 8) & 0xFF); - } - return new IPAddress(quads); - } - catch // Catch Access Denied errors - { - return null; - } - -#endif -#if IS_FULL_NET_AVAILABLE - NetworkInterface ni = GetNetworkInterface(); - if (ni == null) - { - mask = null; - return null; - } - - IPInterfaceProperties properties = ni.GetIPProperties(); - foreach (UnicastIPAddressInformation unicastAddress in properties.UnicastAddresses) - { - if (unicastAddress != null && unicastAddress.Address != null && unicastAddress.Address.AddressFamily == AddressFamily.InterNetwork) - { - mask = unicastAddress.IPv4Mask; - return unicastAddress.Address; - } - } -#endif - return null; - } - - /// - /// Returns true if the IPEndPoint supplied is on the same subnet as this host - /// - public static bool IsLocal(IPEndPoint endPoint) + public static bool IsLocal(NetEndPoint endPoint) { if (endPoint == null) return false; @@ -408,10 +244,10 @@ namespace Lidgren.Network /// /// Returns true if the IPAddress supplied is on the same subnet as this host /// - public static bool IsLocal(IPAddress remote) + public static bool IsLocal(NetAddress remote) { - IPAddress mask; - IPAddress local = GetMyAddress(out mask); + NetAddress mask; + var local = GetMyAddress(out mask); if (mask == null) return false; @@ -602,31 +438,10 @@ namespace Lidgren.Network return bdr.ToString(); } - /// - /// Create a SHA1 digest from a string - /// - public static byte[] CreateSHA1Hash(string key) + public static byte[] ComputeSHAHash(byte[] bytes) { - using (var sha = new SHA1CryptoServiceProvider()) - return sha.ComputeHash(Encoding.UTF8.GetBytes(key)); - } - - /// - /// Create a SHA1 digest from a byte buffer - /// - public static byte[] CreateSHA1Hash(byte[] data) - { - using (var sha = new SHA1CryptoServiceProvider()) - return sha.ComputeHash(data); - } - - /// - /// Create a SHA1 digest from a byte buffer - /// - public static byte[] CreateSHA1Hash(byte[] data, int offset, int count) - { - using (var sha = new SHA1CryptoServiceProvider()) - return sha.ComputeHash(data, offset, count); + // this is defined in the platform specific files + return ComputeSHAHash(bytes, 0, bytes.Length); } } } \ No newline at end of file diff --git a/Lidgren.Network/Platform/PlatformAndroid.cs b/Lidgren.Network/Platform/PlatformAndroid.cs new file mode 100644 index 0000000..e8d378f --- /dev/null +++ b/Lidgren.Network/Platform/PlatformAndroid.cs @@ -0,0 +1,87 @@ +#if __ANDROID__ +using System; +using System.Collections.Generic; +using System.Net; + +namespace Lidgren.Network +{ + public static partial class NetUtility + { + private static byte[] s_randomMacBytes; + + static NetUtility() + { + s_randomMacBytes = new byte[8]; + MWCRandom.Instance.NextBytes(s_randomMacBytes); + } + + [CLSCompliant(false)] + public static ulong GetPlatformSeed(int seedInc) + { + ulong seed = (ulong)Environment.TickCount + (ulong)seedInc; + return seed ^ ((ulong)(new object().GetHashCode()) << 32); + } + + /// + /// Gets my local IPv4 address (not necessarily external) and subnet mask + /// + public static IPAddress GetMyAddress(out IPAddress mask) + { + mask = null; + try + { + Android.Net.Wifi.WifiManager wifi = (Android.Net.Wifi.WifiManager)Android.App.Application.Context.GetSystemService(Android.App.Activity.WifiService); + if (!wifi.IsWifiEnabled) + return null; + + var dhcp = wifi.DhcpInfo; + int addr = dhcp.IpAddress; + byte[] quads = new byte[4]; + for (int k = 0; k < 4; k++) + quads[k] = (byte)((addr >> k * 8) & 0xFF); + return new IPAddress(quads); + } + catch // Catch Access Denied errors + { + return null; + } + } + + public static byte[] GetMacAddressBytes() + { + return s_randomMacBytes; + } + + public static void Sleep(int milliseconds) + { + System.Threading.Thread.Sleep(milliseconds); + } + + public static IPAddress GetBroadcastAddress() + { + return IPAddress.Broadcast; + } + + public static IPAddress CreateAddressFromBytes(byte[] bytes) + { + return new IPAddress(bytes); + } + + private static readonly SHA1 s_sha = SHA1.Create(); + public static byte[] ComputeSHAHash(byte[] bytes, int offset, int count) + { + return s_sha.ComputeHash(bytes, offset, count); + } + } + + public static partial class NetTime + { + private static readonly long s_timeInitialized = Environment.TickCount; + + /// + /// Get number of seconds since the application started + /// + public static double Now { get { return (double)((uint)Environment.TickCount - s_timeInitialized) / 1000.0; } } + } +} +#endif \ No newline at end of file diff --git a/Lidgren.Network/Platform/PlatformConstrained.cs b/Lidgren.Network/Platform/PlatformConstrained.cs new file mode 100644 index 0000000..492b232 --- /dev/null +++ b/Lidgren.Network/Platform/PlatformConstrained.cs @@ -0,0 +1,72 @@ +#if __CONSTRAINED__ +using System; +using System.Collections.Generic; +using System.Net; +using System.Security.Cryptography; + +namespace Lidgren.Network +{ + public static partial class NetUtility + { + private static byte[] s_randomMacBytes; + + static NetUtility() + { + s_randomMacBytes = new byte[8]; + MWCRandom.Instance.NextBytes(s_randomMacBytes); + } + + [CLSCompliant(false)] + public static ulong GetPlatformSeed(int seedInc) + { + ulong seed = (ulong)Environment.TickCount + (ulong)seedInc; + return seed ^ ((ulong)(new object().GetHashCode()) << 32); + } + + /// + /// Gets my local IPv4 address (not necessarily external) and subnet mask + /// + public static IPAddress GetMyAddress(out IPAddress mask) + { + mask = null; + return null; + } + + public static byte[] GetMacAddressBytes() + { + return s_randomMacBytes; + } + + public static IPAddress GetBroadcastAddress() + { + return IPAddress.Broadcast; + } + + public static void Sleep(int milliseconds) + { + System.Threading.Thread.Sleep(milliseconds); + } + + public static IPAddress CreateAddressFromBytes(byte[] bytes) + { + return new IPAddress(bytes); + } + + private static readonly SHA1 s_sha = SHA1.Create(); + public static byte[] ComputeSHAHash(byte[] bytes, int offset, int count) + { + return s_sha.ComputeHash(bytes, offset, count); + } + } + + public static partial class NetTime + { + private static readonly long s_timeInitialized = Environment.TickCount; + + /// + /// Get number of seconds since the application started + /// + public static double Now { get { return (double)((uint)Environment.TickCount - s_timeInitialized) / 1000.0; } } + } +} +#endif diff --git a/Lidgren.Network/Platform/PlatformWin32.cs b/Lidgren.Network/Platform/PlatformWin32.cs new file mode 100644 index 0000000..5ee7250 --- /dev/null +++ b/Lidgren.Network/Platform/PlatformWin32.cs @@ -0,0 +1,156 @@ +#if !__ANDROID__ && !__CONSTRAINED__ && !WINDOWS_RUNTIME +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Net; +using System.Net.NetworkInformation; +using System.Net.Sockets; +using System.Security.Cryptography; + +namespace Lidgren.Network +{ + public static partial class NetUtility + { + private static readonly long s_timeInitialized = Stopwatch.GetTimestamp(); + private static readonly double s_dInvFreq = 1.0 / (double)Stopwatch.Frequency; + + [CLSCompliant(false)] + public static ulong GetPlatformSeed(int seedInc) + { + ulong seed = (ulong)System.Diagnostics.Stopwatch.GetTimestamp(); + return seed ^ ((ulong)Environment.WorkingSet + (ulong)seedInc); + } + + public static double Now { get { return (double)(Stopwatch.GetTimestamp() - s_timeInitialized) * s_dInvFreq; } } + + private static NetworkInterface GetNetworkInterface() + { + var computerProperties = IPGlobalProperties.GetIPGlobalProperties(); + if (computerProperties == null) + return null; + + var nics = NetworkInterface.GetAllNetworkInterfaces(); + if (nics == null || nics.Length < 1) + return null; + + NetworkInterface best = null; + foreach (NetworkInterface adapter in nics) + { + if (adapter.NetworkInterfaceType == NetworkInterfaceType.Loopback || adapter.NetworkInterfaceType == NetworkInterfaceType.Unknown) + continue; + if (!adapter.Supports(NetworkInterfaceComponent.IPv4)) + continue; + if (best == null) + best = adapter; + if (adapter.OperationalStatus != OperationalStatus.Up) + continue; + + // make sure this adapter has any ipv4 addresses + IPInterfaceProperties properties = adapter.GetIPProperties(); + foreach (UnicastIPAddressInformation unicastAddress in properties.UnicastAddresses) + { + if (unicastAddress != null && unicastAddress.Address != null && unicastAddress.Address.AddressFamily == AddressFamily.InterNetwork) + { + // Yes it does, return this network interface. + return adapter; + } + } + } + return best; + } + + /// + /// If available, returns the bytes of the physical (MAC) address for the first usable network interface + /// + public static byte[] GetMacAddressBytes() + { + var ni = GetNetworkInterface(); + if (ni == null) + return null; + return ni.GetPhysicalAddress().GetAddressBytes(); + } + + public static IPAddress GetBroadcastAddress() + { + var ni = GetNetworkInterface(); + if (ni == null) + return null; + + var properties = ni.GetIPProperties(); + foreach (UnicastIPAddressInformation unicastAddress in properties.UnicastAddresses) + { + if (unicastAddress != null && unicastAddress.Address != null && unicastAddress.Address.AddressFamily == AddressFamily.InterNetwork) + { + var mask = unicastAddress.IPv4Mask; + byte[] ipAdressBytes = unicastAddress.Address.GetAddressBytes(); + byte[] subnetMaskBytes = mask.GetAddressBytes(); + + if (ipAdressBytes.Length != subnetMaskBytes.Length) + throw new ArgumentException("Lengths of IP address and subnet mask do not match."); + + byte[] broadcastAddress = new byte[ipAdressBytes.Length]; + for (int i = 0; i < broadcastAddress.Length; i++) + { + broadcastAddress[i] = (byte)(ipAdressBytes[i] | (subnetMaskBytes[i] ^ 255)); + } + return new IPAddress(broadcastAddress); + } + } + return IPAddress.Broadcast; + } + + /// + /// Gets my local IPv4 address (not necessarily external) and subnet mask + /// + public static IPAddress GetMyAddress(out IPAddress mask) + { + var ni = GetNetworkInterface(); + if (ni == null) + { + mask = null; + return null; + } + + IPInterfaceProperties properties = ni.GetIPProperties(); + foreach (UnicastIPAddressInformation unicastAddress in properties.UnicastAddresses) + { + if (unicastAddress != null && unicastAddress.Address != null && unicastAddress.Address.AddressFamily == AddressFamily.InterNetwork) + { + mask = unicastAddress.IPv4Mask; + return unicastAddress.Address; + } + } + + mask = null; + return null; + } + + public static void Sleep(int milliseconds) + { + System.Threading.Thread.Sleep(milliseconds); + } + + public static IPAddress CreateAddressFromBytes(byte[] bytes) + { + return new IPAddress(bytes); + } + + private static readonly SHA256 s_sha = SHA256.Create(); + public static byte[] ComputeSHAHash(byte[] bytes, int offset, int count) + { + return s_sha.ComputeHash(bytes, offset, count); + } + } + + public static partial class NetTime + { + private static readonly long s_timeInitialized = Stopwatch.GetTimestamp(); + private static readonly double s_dInvFreq = 1.0 / (double)Stopwatch.Frequency; + + /// + /// Get number of seconds since the application started + /// + public static double Now { get { return (double)(Stopwatch.GetTimestamp() - s_timeInitialized) * s_dInvFreq; } } + } +} +#endif \ No newline at end of file diff --git a/Lidgren.Network/Platform/PlatformWinRT.cs b/Lidgren.Network/Platform/PlatformWinRT.cs new file mode 100644 index 0000000..d2502ca --- /dev/null +++ b/Lidgren.Network/Platform/PlatformWinRT.cs @@ -0,0 +1,102 @@ +#if WINDOWS_RUNTIME +// +// +// +// Completely broken right now +// +// +// +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.NetworkInformation; +using System.Net.Sockets; +using System.Security.Cryptography; +using System.Threading.Tasks; + +namespace Lidgren.Network +{ + public class NetAddress + { + public static readonly HostName Any = null; + } + + public class NetEndPoint + { + public NetEndPoint(HostName hostname, int port) { HostName = hostname; Port = port; } + public NetEndPoint(HostName hostname, string port) { HostName = hostname; Port = int.Parse(port); } + public NetEndPoint(string hostname, int port) { HostName = (hostname == null) ? null : new HostName(hostname); Port = port; } + public HostName HostName; + public int Port; + public override string ToString() { return string.Format("{0}:{1}", HostName, Port); } + public override int GetHashCode() + { + return HostName.RawName.GetHashCode() + Port; + } + public override bool Equals(object obj) + { + var ep = obj as NetEndPoint; + if (ep == null) return false; + if (Port != ep.Port) return false; + return HostName.RawName.Equals(ep.HostName.RawName); + } + }; + + public static partial class NetUtility + { + [CLSCompliant(false)] + public static ulong GetPlatformSeed(int seedInc) + { + ulong seed = (ulong)Environment.TickCount + (ulong)seedInc; + return seed ^ ((ulong)(new object().GetHashCode()) << 32); + } + + /// + /// Returns the physical (MAC) address for the first usable network interface + /// + public static PhysicalAddress GetMacAddress() + { + throw new NotImplementedException(); + } + + public static IPAddress GetBroadcastAddress() + { + throw new NotImplementedException(); + } + + /// + /// Gets my local IPv4 address (not necessarily external) and subnet mask + /// + public static IPAddress GetMyAddress(out IPAddress mask) + { + throw new NotImplementedException(); + } + + public static void Sleep(int milliseconds) + { + Task.Delay(50).Wait(); + } + + public static NetAddress CreateAddressFromBytes(byte[] bytes) + { + throw new NotImplementedException(); + } + + private static readonly SHA1CryptoServiceProvider s_sha = new SHA1CryptoServiceProvider(); + public static byte[] ComputeSHAHash(byte[] bytes, int offset, int count) + { + return s_sha.ComputeHash(bytes, offset, count); + } + } + + public static partial class NetTime + { + private static readonly long s_timeInitialized = Environment.TickCount; + + /// + /// Get number of seconds since the application started + /// + public static double Now { get { return (double)((uint)Environment.TickCount - s_timeInitialized) / 1000.0; } } + } +} +#endif \ No newline at end of file