b1525 - Added IPv6 support
This commit is contained in:
		
							parent
							
								
									256e2370a3
								
							
						
					
					
						commit
						fdd4c7bac7
					
				
					 8 changed files with 275 additions and 197 deletions
				
			
		|  | @ -70,7 +70,8 @@ namespace SRMultiplayer | ||||||
|                         !assembly.GetName().Name.Contains("Logger") && !assembly.GetName().Name.Contains("Mono.") && !assembly.GetName().Name.Contains("Harmony") && |                         !assembly.GetName().Name.Contains("Logger") && !assembly.GetName().Name.Contains("Mono.") && !assembly.GetName().Name.Contains("Harmony") && | ||||||
|                         !assembly.GetName().Name.Equals("SRML") && !assembly.GetName().Name.Equals("SRML.Editor") && !assembly.GetName().Name.Equals("Newtonsoft.Json") && |                         !assembly.GetName().Name.Equals("SRML") && !assembly.GetName().Name.Equals("SRML.Editor") && !assembly.GetName().Name.Equals("Newtonsoft.Json") && | ||||||
|                         !assembly.GetName().Name.Equals("INIFileParser") && !assembly.GetName().Name.Equals("SRMultiplayer") && !assembly.GetName().Name.Contains("Microsoft.") && |                         !assembly.GetName().Name.Equals("INIFileParser") && !assembly.GetName().Name.Equals("SRMultiplayer") && !assembly.GetName().Name.Contains("Microsoft.") && | ||||||
|                         !assembly.GetName().Name.Equals("SRMP") && !assembly.GetName().Name.Equals("XGamingRuntime") && !Globals.UserData.IgnoredMods.Contains(assembly.GetName().Name)) |                         !assembly.GetName().Name.Equals("SRMP") && !assembly.GetName().Name.Equals("XGamingRuntime") && !assembly.GetName().Name.Contains("MonoMod.Utils.")  | ||||||
|  |                         && !Globals.UserData.IgnoredMods.Contains(assembly.GetName().Name)) | ||||||
|                     { |                     { | ||||||
|                         mods.Add(assembly.GetName().Name); |                         mods.Add(assembly.GetName().Name); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|  | @ -123,7 +123,7 @@ namespace Lidgren.Network | ||||||
| 					mutex.WaitOne(); | 					mutex.WaitOne(); | ||||||
| 
 | 
 | ||||||
| 					if (m_socket == null) | 					if (m_socket == null) | ||||||
| 						m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); | 						m_socket = new Socket(m_configuration.LocalAddress.AddressFamily, SocketType.Dgram, ProtocolType.Udp); | ||||||
| 
 | 
 | ||||||
| 					if (reBind) | 					if (reBind) | ||||||
| 						m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, (int)1); | 						m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, (int)1); | ||||||
|  | @ -132,7 +132,19 @@ namespace Lidgren.Network | ||||||
| 					m_socket.SendBufferSize = m_configuration.SendBufferSize; | 					m_socket.SendBufferSize = m_configuration.SendBufferSize; | ||||||
| 					m_socket.Blocking = false; | 					m_socket.Blocking = false; | ||||||
| 
 | 
 | ||||||
| 					var ep = (EndPoint)new NetEndPoint(m_configuration.LocalAddress, reBind ? m_listenPort : m_configuration.Port); |                     if (m_configuration.DualStack) | ||||||
|  |                     { | ||||||
|  |                         if (m_configuration.LocalAddress.AddressFamily != AddressFamily.InterNetworkV6) | ||||||
|  |                         { | ||||||
|  |                             LogWarning("Configuration specifies Dual Stack but does not use IPv6 local address; Dual stack will not work."); | ||||||
|  |                         } | ||||||
|  |                         else | ||||||
|  |                         { | ||||||
|  |                             m_socket.DualMode = true; | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  | 
 | ||||||
|  |                     var ep = (EndPoint)new NetEndPoint(m_configuration.LocalAddress, reBind ? m_listenPort : m_configuration.Port); | ||||||
| 					m_socket.Bind(ep); | 					m_socket.Bind(ep); | ||||||
| 
 | 
 | ||||||
| 					try | 					try | ||||||
|  | @ -412,172 +424,175 @@ namespace Lidgren.Network | ||||||
| 			// update now | 			// update now | ||||||
| 			now = NetTime.Now; | 			now = NetTime.Now; | ||||||
| 
 | 
 | ||||||
| 			do |             try | ||||||
|  |             { | ||||||
|  | 		        do | ||||||
|  |                 { | ||||||
|  |                     ReceiveSocketData(now); | ||||||
|  |                 } while (m_socket.Available > 0); | ||||||
|  |             } | ||||||
|  |             catch (SocketException sx) | ||||||
|  |             { | ||||||
|  |                 switch (sx.SocketErrorCode) | ||||||
|  |                 { | ||||||
|  |                     case SocketError.ConnectionReset: | ||||||
|  |                         // connection reset by peer, aka connection forcibly closed aka "ICMP port unreachable" | ||||||
|  |                         // we should shut down the connection; but m_senderRemote seemingly cannot be trusted, so which connection should we shut down?! | ||||||
|  |                         // So, what to do? | ||||||
|  |                         LogWarning("ConnectionReset"); | ||||||
|  |                         return; | ||||||
|  | 
 | ||||||
|  |                     case SocketError.NotConnected: | ||||||
|  |                         // socket is unbound; try to rebind it (happens on mobile when process goes to sleep) | ||||||
|  |                         BindSocket(true); | ||||||
|  |                         return; | ||||||
|  | 
 | ||||||
|  |                     default: | ||||||
|  |                         LogWarning("Socket exception: " + sx.ToString()); | ||||||
|  |                         return; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  |         private void ReceiveSocketData(double now) | ||||||
|  |         { | ||||||
|  |             int bytesReceived = m_socket.ReceiveFrom(m_receiveBuffer, 0, m_receiveBuffer.Length, SocketFlags.None, ref m_senderRemote); | ||||||
|  | 
 | ||||||
|  | 			if (bytesReceived < NetConstants.HeaderByteSize) | ||||||
|  | 				return; | ||||||
|  | 
 | ||||||
|  | 			//LogVerbose("Received " + bytesReceived + " bytes"); | ||||||
|  | 
 | ||||||
|  | 			var ipsender = (NetEndPoint)m_senderRemote; | ||||||
|  | 
 | ||||||
|  | 			if (m_upnp != null && now < m_upnp.m_discoveryResponseDeadline && bytesReceived > 32) | ||||||
| 			{ | 			{ | ||||||
| 				int bytesReceived = 0; | 				// is this an UPnP response? | ||||||
| 				try | 				string resp = System.Text.Encoding.UTF8.GetString(m_receiveBuffer, 0, bytesReceived); | ||||||
|  | 				if (resp.Contains("upnp:rootdevice") || resp.Contains("UPnP/1.0")) | ||||||
| 				{ | 				{ | ||||||
| 					bytesReceived = m_socket.ReceiveFrom(m_receiveBuffer, 0, m_receiveBuffer.Length, SocketFlags.None, ref m_senderRemote); |  | ||||||
| 				} |  | ||||||
| 				catch (SocketException sx) |  | ||||||
| 				{ |  | ||||||
| 					switch (sx.SocketErrorCode) |  | ||||||
| 					{ |  | ||||||
| 						case SocketError.ConnectionReset: |  | ||||||
| 							// connection reset by peer, aka connection forcibly closed aka "ICMP port unreachable" |  | ||||||
| 							// we should shut down the connection; but m_senderRemote seemingly cannot be trusted, so which connection should we shut down?! |  | ||||||
| 							// So, what to do? |  | ||||||
| 							LogWarning("ConnectionReset"); |  | ||||||
| 							return; |  | ||||||
| 
 |  | ||||||
| 						case SocketError.NotConnected: |  | ||||||
| 							// socket is unbound; try to rebind it (happens on mobile when process goes to sleep) |  | ||||||
| 							BindSocket(true); |  | ||||||
| 							return; |  | ||||||
| 
 |  | ||||||
| 						default: |  | ||||||
| 							LogWarning("Socket exception: " + sx.ToString()); |  | ||||||
| 							return; |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				if (bytesReceived < NetConstants.HeaderByteSize) |  | ||||||
| 					return; |  | ||||||
| 
 |  | ||||||
| 				//LogVerbose("Received " + bytesReceived + " bytes"); |  | ||||||
| 
 |  | ||||||
| 				var ipsender = (NetEndPoint)m_senderRemote; |  | ||||||
| 
 |  | ||||||
| 				if (m_upnp != null && now < m_upnp.m_discoveryResponseDeadline && bytesReceived > 32) |  | ||||||
| 				{ |  | ||||||
| 					// is this an UPnP response? |  | ||||||
| 					string resp = System.Text.Encoding.UTF8.GetString(m_receiveBuffer, 0, bytesReceived); |  | ||||||
| 					if (resp.Contains("upnp:rootdevice") || resp.Contains("UPnP/1.0")) |  | ||||||
| 					{ |  | ||||||
| 						try |  | ||||||
| 						{ |  | ||||||
| 							resp = resp.Substring(resp.ToLower().IndexOf("location:") + 9); |  | ||||||
| 							resp = resp.Substring(0, resp.IndexOf("\r")).Trim(); |  | ||||||
| 							m_upnp.ExtractServiceUrl(resp); |  | ||||||
| 							return; |  | ||||||
| 						} |  | ||||||
| 						catch (Exception ex) |  | ||||||
| 						{ |  | ||||||
| 							LogDebug("Failed to parse UPnP response: " + ex.ToString()); |  | ||||||
| 
 |  | ||||||
| 							// don't try to parse this packet further |  | ||||||
| 							return; |  | ||||||
| 						} |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				NetConnection sender = null; |  | ||||||
| 				m_connectionLookup.TryGetValue(ipsender, out sender); |  | ||||||
| 
 |  | ||||||
| 				// |  | ||||||
| 				// parse packet into messages |  | ||||||
| 				// |  | ||||||
| 				int numMessages = 0; |  | ||||||
| 				int numFragments = 0; |  | ||||||
| 				int ptr = 0; |  | ||||||
| 				while ((bytesReceived - ptr) >= NetConstants.HeaderByteSize) |  | ||||||
| 				{ |  | ||||||
| 					// decode header |  | ||||||
| 					//  8 bits - NetMessageType |  | ||||||
| 					//  1 bit  - Fragment? |  | ||||||
| 					// 15 bits - Sequence number |  | ||||||
| 					// 16 bits - Payload length in bits |  | ||||||
| 
 |  | ||||||
| 					numMessages++; |  | ||||||
| 
 |  | ||||||
| 					NetMessageType tp = (NetMessageType)m_receiveBuffer[ptr++]; |  | ||||||
| 
 |  | ||||||
| 					byte low = m_receiveBuffer[ptr++]; |  | ||||||
| 					byte high = m_receiveBuffer[ptr++]; |  | ||||||
| 
 |  | ||||||
| 					bool isFragment = ((low & 1) == 1); |  | ||||||
| 					ushort sequenceNumber = (ushort)((low >> 1) | (((int)high) << 7)); |  | ||||||
| 
 |  | ||||||
| 					if (isFragment) |  | ||||||
| 						numFragments++; |  | ||||||
| 
 |  | ||||||
| 					ushort payloadBitLength = (ushort)(m_receiveBuffer[ptr++] | (m_receiveBuffer[ptr++] << 8)); |  | ||||||
| 					int payloadByteLength = NetUtility.BytesToHoldBits(payloadBitLength); |  | ||||||
| 
 |  | ||||||
| 					if (bytesReceived - ptr < payloadByteLength) |  | ||||||
| 					{ |  | ||||||
| 						LogWarning("Malformed packet; stated payload length " + payloadByteLength + ", remaining bytes " + (bytesReceived - ptr)); |  | ||||||
| 						return; |  | ||||||
| 					} |  | ||||||
| 
 |  | ||||||
| 					if (tp >= NetMessageType.Unused1 && tp <= NetMessageType.Unused29) |  | ||||||
| 					{ |  | ||||||
| 						ThrowOrLog("Unexpected NetMessageType: " + tp); |  | ||||||
| 						return; |  | ||||||
| 					} |  | ||||||
| 
 |  | ||||||
| 					try | 					try | ||||||
| 					{ | 					{ | ||||||
| 						if (tp >= NetMessageType.LibraryError) | 						resp = resp.Substring(resp.ToLower().IndexOf("location:") + 9); | ||||||
| 						{ | 						resp = resp.Substring(0, resp.IndexOf("\r")).Trim(); | ||||||
| 							if (sender != null) | 						m_upnp.ExtractServiceUrl(resp); | ||||||
| 								sender.ReceivedLibraryMessage(tp, ptr, payloadByteLength); | 						return; | ||||||
| 							else |  | ||||||
| 								ReceivedUnconnectedLibraryMessage(now, ipsender, tp, ptr, payloadByteLength); |  | ||||||
| 						} |  | ||||||
| 						else |  | ||||||
| 						{ |  | ||||||
| 							if (sender == null && !m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.UnconnectedData)) |  | ||||||
| 								return; // dropping unconnected message since it's not enabled |  | ||||||
| 
 |  | ||||||
| 							NetIncomingMessage msg = CreateIncomingMessage(NetIncomingMessageType.Data, payloadByteLength); |  | ||||||
| 							msg.m_isFragment = isFragment; |  | ||||||
| 							msg.m_receiveTime = now; |  | ||||||
| 							msg.m_sequenceNumber = sequenceNumber; |  | ||||||
| 							msg.m_receivedMessageType = tp; |  | ||||||
| 							msg.m_senderConnection = sender; |  | ||||||
| 							msg.m_senderEndPoint = ipsender; |  | ||||||
| 							msg.m_bitLength = payloadBitLength; |  | ||||||
| 
 |  | ||||||
| 							Buffer.BlockCopy(m_receiveBuffer, ptr, msg.m_data, 0, payloadByteLength); |  | ||||||
| 							if (sender != null) |  | ||||||
| 							{ |  | ||||||
| 								if (tp == NetMessageType.Unconnected) |  | ||||||
| 								{ |  | ||||||
| 									// We're connected; but we can still send unconnected messages to this peer |  | ||||||
| 									msg.m_incomingMessageType = NetIncomingMessageType.UnconnectedData; |  | ||||||
| 									ReleaseMessage(msg); |  | ||||||
| 								} |  | ||||||
| 								else |  | ||||||
| 								{ |  | ||||||
| 									// connected application (non-library) message |  | ||||||
| 									sender.ReceivedMessage(msg); |  | ||||||
| 								} |  | ||||||
| 							} |  | ||||||
| 							else |  | ||||||
| 							{ |  | ||||||
| 								// at this point we know the message type is enabled |  | ||||||
| 								// unconnected application (non-library) message |  | ||||||
| 								msg.m_incomingMessageType = NetIncomingMessageType.UnconnectedData; |  | ||||||
| 								ReleaseMessage(msg); |  | ||||||
| 							} |  | ||||||
| 						} |  | ||||||
| 					} | 					} | ||||||
| 					catch (Exception ex) | 					catch (Exception ex) | ||||||
| 					{ | 					{ | ||||||
| 						LogError("Packet parsing error: " + ex.Message + " from " + ipsender); | 						LogDebug("Failed to parse UPnP response: " + ex.ToString()); | ||||||
|  | 
 | ||||||
|  | 						// don't try to parse this packet further | ||||||
|  | 						return; | ||||||
| 					} | 					} | ||||||
| 					ptr += payloadByteLength; | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			NetConnection sender = null; | ||||||
|  | 			m_connectionLookup.TryGetValue(ipsender, out sender); | ||||||
|  | 
 | ||||||
|  | 			// | ||||||
|  | 			// parse packet into messages | ||||||
|  | 			// | ||||||
|  | 			int numMessages = 0; | ||||||
|  | 			int numFragments = 0; | ||||||
|  | 			int ptr = 0; | ||||||
|  | 			while ((bytesReceived - ptr) >= NetConstants.HeaderByteSize) | ||||||
|  | 			{ | ||||||
|  | 				// decode header | ||||||
|  | 				//  8 bits - NetMessageType | ||||||
|  | 				//  1 bit  - Fragment? | ||||||
|  | 				// 15 bits - Sequence number | ||||||
|  | 				// 16 bits - Payload length in bits | ||||||
|  | 
 | ||||||
|  | 				numMessages++; | ||||||
|  | 
 | ||||||
|  | 				NetMessageType tp = (NetMessageType)m_receiveBuffer[ptr++]; | ||||||
|  | 
 | ||||||
|  | 				byte low = m_receiveBuffer[ptr++]; | ||||||
|  | 				byte high = m_receiveBuffer[ptr++]; | ||||||
|  | 
 | ||||||
|  | 				bool isFragment = ((low & 1) == 1); | ||||||
|  | 				ushort sequenceNumber = (ushort)((low >> 1) | (((int)high) << 7)); | ||||||
|  | 
 | ||||||
|  | 				if (isFragment) | ||||||
|  | 					numFragments++; | ||||||
|  | 
 | ||||||
|  | 				ushort payloadBitLength = (ushort)(m_receiveBuffer[ptr++] | (m_receiveBuffer[ptr++] << 8)); | ||||||
|  | 				int payloadByteLength = NetUtility.BytesToHoldBits(payloadBitLength); | ||||||
|  | 
 | ||||||
|  | 				if (bytesReceived - ptr < payloadByteLength) | ||||||
|  | 				{ | ||||||
|  | 					LogWarning("Malformed packet; stated payload length " + payloadByteLength + ", remaining bytes " + (bytesReceived - ptr)); | ||||||
|  | 					return; | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				m_statistics.PacketReceived(bytesReceived, numMessages, numFragments); | 				if (tp >= NetMessageType.Unused1 && tp <= NetMessageType.Unused29) | ||||||
| 				if (sender != null) | 				{ | ||||||
| 					sender.m_statistics.PacketReceived(bytesReceived, numMessages, numFragments); | 					ThrowOrLog("Unexpected NetMessageType: " + tp); | ||||||
|  | 					return; | ||||||
|  | 				} | ||||||
| 
 | 
 | ||||||
| 			} while (m_socket.Available > 0); | 				try | ||||||
| 		} | 				{ | ||||||
|  | 					if (tp >= NetMessageType.LibraryError) | ||||||
|  | 					{ | ||||||
|  | 						if (sender != null) | ||||||
|  | 							sender.ReceivedLibraryMessage(tp, ptr, payloadByteLength); | ||||||
|  | 						else | ||||||
|  | 							ReceivedUnconnectedLibraryMessage(now, ipsender, tp, ptr, payloadByteLength); | ||||||
|  | 					} | ||||||
|  | 					else | ||||||
|  | 					{ | ||||||
|  | 						if (sender == null && !m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.UnconnectedData)) | ||||||
|  | 							return; // dropping unconnected message since it's not enabled | ||||||
| 
 | 
 | ||||||
| 		/// <summary> | 						NetIncomingMessage msg = CreateIncomingMessage(NetIncomingMessageType.Data, payloadByteLength); | ||||||
|  | 						msg.m_isFragment = isFragment; | ||||||
|  | 						msg.m_receiveTime = now; | ||||||
|  | 						msg.m_sequenceNumber = sequenceNumber; | ||||||
|  | 						msg.m_receivedMessageType = tp; | ||||||
|  | 						msg.m_senderConnection = sender; | ||||||
|  | 						msg.m_senderEndPoint = ipsender; | ||||||
|  | 						msg.m_bitLength = payloadBitLength; | ||||||
|  | 
 | ||||||
|  | 						Buffer.BlockCopy(m_receiveBuffer, ptr, msg.m_data, 0, payloadByteLength); | ||||||
|  | 						if (sender != null) | ||||||
|  | 						{ | ||||||
|  | 							if (tp == NetMessageType.Unconnected) | ||||||
|  | 							{ | ||||||
|  | 								// We're connected; but we can still send unconnected messages to this peer | ||||||
|  | 								msg.m_incomingMessageType = NetIncomingMessageType.UnconnectedData; | ||||||
|  | 								ReleaseMessage(msg); | ||||||
|  | 							} | ||||||
|  | 							else | ||||||
|  | 							{ | ||||||
|  | 								// connected application (non-library) message | ||||||
|  | 								sender.ReceivedMessage(msg); | ||||||
|  | 							} | ||||||
|  | 						} | ||||||
|  | 						else | ||||||
|  | 						{ | ||||||
|  | 							// at this point we know the message type is enabled | ||||||
|  | 							// unconnected application (non-library) message | ||||||
|  | 							msg.m_incomingMessageType = NetIncomingMessageType.UnconnectedData; | ||||||
|  | 							ReleaseMessage(msg); | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 				catch (Exception ex) | ||||||
|  | 				{ | ||||||
|  | 					LogError("Packet parsing error: " + ex.Message + " from " + ipsender); | ||||||
|  | 				} | ||||||
|  | 				ptr += payloadByteLength; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			m_statistics.PacketReceived(bytesReceived, numMessages, numFragments); | ||||||
|  | 			if (sender != null) | ||||||
|  | 				sender.m_statistics.PacketReceived(bytesReceived, numMessages, numFragments); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
| 		/// If NetPeerConfiguration.AutoFlushSendQueue() is false; you need to call this to send all messages queued using SendMessage() | 		/// If NetPeerConfiguration.AutoFlushSendQueue() is false; you need to call this to send all messages queued using SendMessage() | ||||||
| 		/// </summary> | 		/// </summary> | ||||||
| 		public void FlushSendQueue() | 		public void FlushSendQueue() | ||||||
|  | @ -686,7 +701,7 @@ namespace Lidgren.Network | ||||||
| 				case NetMessageType.Connect: | 				case NetMessageType.Connect: | ||||||
| 					if (m_configuration.AcceptIncomingConnections == false) | 					if (m_configuration.AcceptIncomingConnections == false) | ||||||
| 					{ | 					{ | ||||||
| 						LogWarning(m_configuration.AppIdentifier + " Received Connect, but we're not accepting incoming connections!"); | 						LogWarning("Received Connect, but we're not accepting incoming connections!"); | ||||||
| 						return; | 						return; | ||||||
| 					} | 					} | ||||||
| 					// handle connect | 					// handle connect | ||||||
|  |  | ||||||
|  | @ -132,6 +132,9 @@ namespace Lidgren.Network | ||||||
| 			catch { } | 			catch { } | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  |         //Avoids allocation on mapping to IPv6 | ||||||
|  |         private IPEndPoint targetCopy = new IPEndPoint(IPAddress.Any, 0); | ||||||
|  | 
 | ||||||
| 		internal bool ActuallySendPacket(byte[] data, int numBytes, NetEndPoint target, out bool connectionReset) | 		internal bool ActuallySendPacket(byte[] data, int numBytes, NetEndPoint target, out bool connectionReset) | ||||||
| 		{ | 		{ | ||||||
| 			connectionReset = false; | 			connectionReset = false; | ||||||
|  | @ -140,17 +143,25 @@ namespace Lidgren.Network | ||||||
| 			{ | 			{ | ||||||
| 				ba = NetUtility.GetCachedBroadcastAddress(); | 				ba = NetUtility.GetCachedBroadcastAddress(); | ||||||
| 
 | 
 | ||||||
| 				// TODO: refactor this check outta here |                 // TODO: refactor this check outta here | ||||||
| 				if (target.Address.Equals(ba)) |                 if (target.Address.Equals(ba)) | ||||||
| 				{ |                 { | ||||||
| 					// Some networks do not allow  |                     // Some networks do not allow  | ||||||
| 					// a global broadcast so we use the BroadcastAddress from the configuration |                     // a global broadcast so we use the BroadcastAddress from the configuration | ||||||
| 					// this can be resolved to a local broadcast addresss e.g 192.168.x.255                     |                     // this can be resolved to a local broadcast addresss e.g 192.168.x.255                     | ||||||
| 					target.Address = m_configuration.BroadcastAddress; |                     targetCopy.Address = m_configuration.BroadcastAddress; | ||||||
| 					m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true); |                     targetCopy.Port = target.Port; | ||||||
| 				} |                     m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true); | ||||||
|  |                 } | ||||||
|  |                 else if(m_configuration.DualStack && m_configuration.LocalAddress.AddressFamily == AddressFamily.InterNetworkV6) | ||||||
|  |                     NetUtility.CopyEndpoint(target, targetCopy); //Maps to IPv6 for Dual Mode | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  | 	                targetCopy.Port = target.Port; | ||||||
|  | 	                targetCopy.Address = target.Address; | ||||||
|  |                 } | ||||||
| 
 | 
 | ||||||
| 				int bytesSent = m_socket.SendTo(data, 0, numBytes, SocketFlags.None, target); |                 int bytesSent = m_socket.SendTo(data, 0, numBytes, SocketFlags.None, targetCopy); | ||||||
| 				if (numBytes != bytesSent) | 				if (numBytes != bytesSent) | ||||||
| 					LogWarning("Failed to send the full " + numBytes + "; only " + bytesSent + " bytes sent in packet!"); | 					LogWarning("Failed to send the full " + numBytes + "; only " + bytesSent + " bytes sent in packet!"); | ||||||
| 
 | 
 | ||||||
|  | @ -178,7 +189,7 @@ namespace Lidgren.Network | ||||||
| 			} | 			} | ||||||
| 			finally | 			finally | ||||||
| 			{ | 			{ | ||||||
| 				if (target.Address == ba) | 				if (target.Address.Equals(ba)) | ||||||
| 					m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, false); | 					m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, false); | ||||||
| 			} | 			} | ||||||
| 			return true; | 			return true; | ||||||
|  |  | ||||||
|  | @ -2,7 +2,7 @@ | ||||||
| using System.Threading; | using System.Threading; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.Net; | using System.Net; | ||||||
| 
 | using System.Net.Sockets; | ||||||
| #if !__NOIPENDPOINT__ | #if !__NOIPENDPOINT__ | ||||||
| using NetEndPoint = System.Net.IPEndPoint; | using NetEndPoint = System.Net.IPEndPoint; | ||||||
| #endif | #endif | ||||||
|  | @ -121,7 +121,14 @@ namespace Lidgren.Network | ||||||
| 			m_connections = new List<NetConnection>(); | 			m_connections = new List<NetConnection>(); | ||||||
| 			m_connectionLookup = new Dictionary<NetEndPoint, NetConnection>(); | 			m_connectionLookup = new Dictionary<NetEndPoint, NetConnection>(); | ||||||
| 			m_handshakes = new Dictionary<NetEndPoint, NetConnection>(); | 			m_handshakes = new Dictionary<NetEndPoint, NetConnection>(); | ||||||
| 			m_senderRemote = (EndPoint)new NetEndPoint(IPAddress.Any, 0); |             if (m_configuration.LocalAddress.AddressFamily == AddressFamily.InterNetworkV6) | ||||||
|  |             { | ||||||
|  |                 m_senderRemote = (EndPoint)new IPEndPoint(IPAddress.IPv6Any, 0); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 m_senderRemote = (EndPoint)new IPEndPoint(IPAddress.Any, 0); | ||||||
|  |             } | ||||||
| 			m_status = NetPeerStatus.NotRunning; | 			m_status = NetPeerStatus.NotRunning; | ||||||
| 			m_receivedFragmentGroups = new Dictionary<NetConnection, Dictionary<int, ReceivedFragmentGroup>>(); | 			m_receivedFragmentGroups = new Dictionary<NetConnection, Dictionary<int, ReceivedFragmentGroup>>(); | ||||||
| 		} | 		} | ||||||
|  | @ -303,6 +310,8 @@ namespace Lidgren.Network | ||||||
| 		{ | 		{ | ||||||
| 			if (remoteEndPoint == null) | 			if (remoteEndPoint == null) | ||||||
| 				throw new ArgumentNullException("remoteEndPoint"); | 				throw new ArgumentNullException("remoteEndPoint"); | ||||||
|  |             if(m_configuration.DualStack) | ||||||
|  |                 remoteEndPoint = NetUtility.MapToIPv6(remoteEndPoint); | ||||||
| 
 | 
 | ||||||
| 			lock (m_connections) | 			lock (m_connections) | ||||||
| 			{ | 			{ | ||||||
|  |  | ||||||
|  | @ -48,6 +48,8 @@ namespace Lidgren.Network | ||||||
| 		private string m_networkThreadName; | 		private string m_networkThreadName; | ||||||
| 		private IPAddress m_localAddress; | 		private IPAddress m_localAddress; | ||||||
| 		private IPAddress m_broadcastAddress; | 		private IPAddress m_broadcastAddress; | ||||||
|  |         private bool m_dualStack; | ||||||
|  | 
 | ||||||
| 		internal bool m_acceptIncomingConnections; | 		internal bool m_acceptIncomingConnections; | ||||||
| 		internal int m_maximumConnections; | 		internal int m_maximumConnections; | ||||||
| 		internal int m_defaultOutgoingMessageCapacity; | 		internal int m_defaultOutgoingMessageCapacity; | ||||||
|  | @ -341,10 +343,26 @@ namespace Lidgren.Network | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		/// <summary> |         /// <summary> | ||||||
| 		/// Gets or sets the local broadcast address to use when broadcasting |         /// Gets or sets a value indicating whether the library should use IPv6 dual stack mode. | ||||||
| 		/// </summary> |         /// If you enable this you should make sure that the <see cref="LocalAddress"/> is an IPv6 address. | ||||||
| 		public IPAddress BroadcastAddress |         /// Cannot be changed once NetPeer is initialized. | ||||||
|  |         /// </summary> | ||||||
|  |         public bool DualStack | ||||||
|  |         { | ||||||
|  |             get { return m_dualStack;  } | ||||||
|  |             set | ||||||
|  |             { | ||||||
|  |                 if (m_isLocked) | ||||||
|  |                     throw new NetException(c_isLockedMessage); | ||||||
|  |                 m_dualStack = value; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Gets or sets the local broadcast address to use when broadcasting | ||||||
|  |         /// </summary> | ||||||
|  |         public IPAddress BroadcastAddress | ||||||
| 		{ | 		{ | ||||||
| 			get { return m_broadcastAddress; } | 			get { return m_broadcastAddress; } | ||||||
| 			set | 			set | ||||||
|  |  | ||||||
|  | @ -98,7 +98,7 @@ namespace Lidgren.Network | ||||||
| 			NetAddress ipAddress = null; | 			NetAddress ipAddress = null; | ||||||
| 			if (NetAddress.TryParse(ipOrHost, out ipAddress)) | 			if (NetAddress.TryParse(ipOrHost, out ipAddress)) | ||||||
| 			{ | 			{ | ||||||
| 				if (ipAddress.AddressFamily == AddressFamily.InterNetwork) | 				if (ipAddress.AddressFamily == AddressFamily.InterNetwork || ipAddress.AddressFamily == AddressFamily.InterNetworkV6) | ||||||
| 				{ | 				{ | ||||||
| 					callback(ipAddress); | 					callback(ipAddress); | ||||||
| 					return; | 					return; | ||||||
|  | @ -139,7 +139,7 @@ namespace Lidgren.Network | ||||||
| 					// check each entry for a valid IP address | 					// check each entry for a valid IP address | ||||||
| 					foreach (var ipCurrent in entry.AddressList) | 					foreach (var ipCurrent in entry.AddressList) | ||||||
| 					{ | 					{ | ||||||
| 						if (ipCurrent.AddressFamily == AddressFamily.InterNetwork) | 						if (ipCurrent.AddressFamily == AddressFamily.InterNetwork || ipCurrent.AddressFamily == AddressFamily.InterNetworkV6) | ||||||
| 						{ | 						{ | ||||||
| 							callback(ipCurrent); | 							callback(ipCurrent); | ||||||
| 							return; | 							return; | ||||||
|  | @ -163,7 +163,7 @@ namespace Lidgren.Network | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		/// <summary> |         /// <summary> | ||||||
| 		/// Get IPv4 address from notation (xxx.xxx.xxx.xxx) or hostname | 		/// Get IPv4 address from notation (xxx.xxx.xxx.xxx) or hostname | ||||||
| 		/// </summary> | 		/// </summary> | ||||||
| 		public static NetAddress Resolve(string ipOrHost) | 		public static NetAddress Resolve(string ipOrHost) | ||||||
|  | @ -176,9 +176,9 @@ namespace Lidgren.Network | ||||||
| 			NetAddress ipAddress = null; | 			NetAddress ipAddress = null; | ||||||
| 			if (NetAddress.TryParse(ipOrHost, out ipAddress)) | 			if (NetAddress.TryParse(ipOrHost, out ipAddress)) | ||||||
| 			{ | 			{ | ||||||
| 				if (ipAddress.AddressFamily == AddressFamily.InterNetwork) | 				if (ipAddress.AddressFamily == AddressFamily.InterNetwork || ipAddress.AddressFamily == AddressFamily.InterNetworkV6) | ||||||
| 					return ipAddress; | 					return ipAddress; | ||||||
| 				throw new ArgumentException("This method will not currently resolve other than ipv4 addresses"); | 				throw new ArgumentException("This method will not currently resolve other than IPv4 or IPv6 addresses"); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			// ok must be a host name | 			// ok must be a host name | ||||||
|  | @ -189,7 +189,7 @@ namespace Lidgren.Network | ||||||
| 					return null; | 					return null; | ||||||
| 				foreach (var address in addresses) | 				foreach (var address in addresses) | ||||||
| 				{ | 				{ | ||||||
| 					if (address.AddressFamily == AddressFamily.InterNetwork) | 					if (address.AddressFamily == AddressFamily.InterNetwork || address.AddressFamily == AddressFamily.InterNetworkV6) | ||||||
| 						return address; | 						return address; | ||||||
| 				} | 				} | ||||||
| 				return null; | 				return null; | ||||||
|  | @ -465,5 +465,29 @@ namespace Lidgren.Network | ||||||
| 			// this is defined in the platform specific files | 			// this is defined in the platform specific files | ||||||
| 			return ComputeSHAHash(bytes, 0, bytes.Length); | 			return ComputeSHAHash(bytes, 0, bytes.Length); | ||||||
| 		} | 		} | ||||||
| 	} | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Copies from <paramref name="src"/> to <paramref name="dst"/>. Maps to an IPv6 address | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="src">Source.</param> | ||||||
|  |         /// <param name="dst">Destination.</param> | ||||||
|  |         internal static void CopyEndpoint(IPEndPoint src, IPEndPoint dst) | ||||||
|  |         { | ||||||
|  |             dst.Port = src.Port; | ||||||
|  |             if (src.AddressFamily == AddressFamily.InterNetwork) | ||||||
|  |                 dst.Address = src.Address.MapToIPv6(); | ||||||
|  |             else | ||||||
|  |                 dst.Address = src.Address; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Maps the IPEndPoint object to an IPv6 address. Has allocation | ||||||
|  |         /// </summary> | ||||||
|  |         internal static IPEndPoint MapToIPv6(IPEndPoint endPoint) | ||||||
|  |         { | ||||||
|  |             if (endPoint.AddressFamily == AddressFamily.InterNetwork) | ||||||
|  |                 return new IPEndPoint(endPoint.Address.MapToIPv6(), endPoint.Port); | ||||||
|  |             return endPoint; | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | @ -15,7 +15,7 @@ using System.Resources; | ||||||
| [assembly: AssemblyCulture("")] | [assembly: AssemblyCulture("")] | ||||||
| 
 | 
 | ||||||
| // Version informationr( | // Version informationr( | ||||||
| [assembly: AssemblyVersion("0.0.0.1524")] | [assembly: AssemblyVersion("0.0.0.1525")] | ||||||
| [assembly: AssemblyFileVersion("0.0.0.1524")] | [assembly: AssemblyFileVersion("0.0.0.1525")] | ||||||
| [assembly: NeutralResourcesLanguageAttribute( "en-US" )] | [assembly: NeutralResourcesLanguageAttribute( "en-US" )] | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| { | { | ||||||
| 	"id": "srmp", | 	"id": "srmp", | ||||||
| 	"name": "Slime Rancher Multiplayer", | 	"name": "Slime Rancher Multiplayer", | ||||||
| 	"version": "0.0.1524", | 	"version": "0.0.1525", | ||||||
| 	"author": "SatyPardus", | 	"author": "SatyPardus", | ||||||
| 	"dependencies": [ | 	"dependencies": [ | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Saty
						Saty