private bool BindSocket(Socket socket, IPEndPoint ep, bool reuseAddress, IPv6Mode ipv6Mode) { //Setup socket socket.ReceiveTimeout = 500; socket.SendTimeout = 500; socket.ReceiveBufferSize = NetConstants.SocketBufferSize; socket.SendBufferSize = NetConstants.SocketBufferSize; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { try { socket.IOControl(SioUdpConnreset, new byte[] { 0 }, null); } catch { //ignored } } try { socket.ExclusiveAddressUse = !reuseAddress; socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, reuseAddress); } catch { //Unity with IL2CPP throws an exception here, it doesn't matter in most cases so just ignore it } if (ep.AddressFamily == AddressFamily.InterNetwork || ipv6Mode == IPv6Mode.DualMode) { Ttl = NetConstants.SocketTTL; try { socket.EnableBroadcast = true; } catch (SocketException e) { NetDebug.WriteError($"[B]Broadcast error: {e.SocketErrorCode}"); } if (ipv6Mode == IPv6Mode.DualMode) { try { socket.DualMode = true; } catch (Exception e) { NetDebug.WriteError($"[B]Bind exception (dualmode setting): {e}"); } } else if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { try { socket.DontFragment = true; } catch (SocketException e) { NetDebug.WriteError($"[B]DontFragment error: {e.SocketErrorCode}"); } } } //Bind try { socket.Bind(ep); NetDebug.Write(NetLogLevel.Trace, $"[B]Successfully binded to port: {((IPEndPoint)socket.LocalEndPoint).Port}, AF: {socket.AddressFamily}"); //join multicast if (ep.AddressFamily == AddressFamily.InterNetworkV6) { try { #if !UNITY_2018_3_OR_NEWER socket.SetSocketOption( SocketOptionLevel.IPv6, SocketOptionName.AddMembership, new IPv6MulticastOption(MulticastAddressV6)); #endif } catch (Exception) { // Unity3d throws exception - ignored } } } catch (SocketException bindException) { switch (bindException.SocketErrorCode) { //IPv6 bind fix case SocketError.AddressAlreadyInUse: if (socket.AddressFamily == AddressFamily.InterNetworkV6 && ipv6Mode != IPv6Mode.DualMode) { try { //Set IPv6Only socket.DualMode = false; socket.Bind(ep); } catch (SocketException ex) { //because its fixed in 2018_3 NetDebug.WriteError($"[B]Bind exception: {ex}, errorCode: {ex.SocketErrorCode}"); return(false); } return(true); } break; //hack for iOS (Unity3D) case SocketError.AddressFamilyNotSupported: return(true); } NetDebug.WriteError($"[B]Bind exception: {bindException}, errorCode: {bindException.SocketErrorCode}"); return(false); } return(true); }
private bool BindSocket(Socket socket, IPEndPoint ep, bool reuseAddress, IPv6Mode ipv6Mode) { //Setup socket socket.ReceiveTimeout = 500; socket.SendTimeout = 500; socket.ReceiveBufferSize = NetConstants.SocketBufferSize; socket.SendBufferSize = NetConstants.SocketBufferSize; #if !UNITY || UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN #if NETSTANDARD || NETCOREAPP if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) #endif try { socket.IOControl(SioUdpConnreset, new byte[] { 0 }, null); } catch { //ignored } #endif try { socket.ExclusiveAddressUse = !reuseAddress; socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, reuseAddress); } catch { //Unity with IL2CPP throws an exception here, it doesn't matter in most cases so just ignore it } if (socket.AddressFamily == AddressFamily.InterNetwork) { Ttl = NetConstants.SocketTTL; #if NETSTANDARD || NETCOREAPP if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) #endif try { socket.DontFragment = true; } catch (SocketException e) { NetDebug.WriteError("[B]DontFragment error: {0}", e.SocketErrorCode); } try { socket.EnableBroadcast = true; } catch (SocketException e) { NetDebug.WriteError("[B]Broadcast error: {0}", e.SocketErrorCode); } } else //IPv6 specific { if (ipv6Mode == IPv6Mode.DualMode) { try { //Disable IPv6 only mode socket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, false); } catch (Exception e) { NetDebug.WriteError("[B]Bind exception (dualmode setting): {0}", e.ToString()); } } } //Bind try { socket.Bind(ep); NetDebug.Write(NetLogLevel.Trace, "[B]Successfully binded to port: {0}", ((IPEndPoint)socket.LocalEndPoint).Port); //join multicast if (socket.AddressFamily == AddressFamily.InterNetworkV6) { try { #if !UNITY socket.SetSocketOption( SocketOptionLevel.IPv6, SocketOptionName.AddMembership, new IPv6MulticastOption(MulticastAddressV6)); #endif } catch (Exception) { Console.WriteLine("// Unity3d throws exception - ignored"); } } } catch (SocketException bindException) { switch (bindException.SocketErrorCode) { //IPv6 bind fix case SocketError.AddressAlreadyInUse: if (socket.AddressFamily == AddressFamily.InterNetworkV6 && ipv6Mode != IPv6Mode.DualMode) { try { //Set IPv6Only socket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, true); socket.Bind(ep); } #if UNITY_2018_3_OR_NEWER catch (SocketException ex) { //because its fixed in 2018_3 NetDebug.WriteError("[B]Bind exception: {0}, errorCode: {1}", ex.ToString(), ex.SocketErrorCode); #else catch (SocketException) { #endif return(false); } return(true); } break; //hack for iOS (Unity3D) case SocketError.AddressFamilyNotSupported: return(true); } NetDebug.WriteError("[B]Bind exception: {0}, errorCode: {1}", bindException.ToString(), bindException.SocketErrorCode); return(false); } return(true); }
public bool Bind(IPAddress addressIPv4, IPAddress addressIPv6, int port, bool reuseAddress, IPv6Mode ipv6Mode, bool manualMode) { if (IsActive()) { return(false); } _useNativeSockets = _listener.UseNativeSockets && NativeSocket.IsSupported; bool dualMode = ipv6Mode == IPv6Mode.DualMode && IPv6Support; _udpSocketv4 = new Socket( dualMode ? AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); if (!BindSocket(_udpSocketv4, new IPEndPoint(dualMode ? addressIPv6 : addressIPv4, port), reuseAddress, ipv6Mode)) { return(false); } LocalPort = ((IPEndPoint)_udpSocketv4.LocalEndPoint).Port; #if UNITY_IOS && !UNITY_EDITOR if (_unitySocketFix == null) { var unityFixObj = new GameObject("LiteNetLib_UnitySocketFix"); GameObject.DontDestroyOnLoad(unityFixObj); _unitySocketFix = unityFixObj.AddComponent <UnitySocketFix>(); _unitySocketFix.Socket = this; _unitySocketFix.BindAddrIPv4 = addressIPv4; _unitySocketFix.BindAddrIPv6 = addressIPv6; _unitySocketFix.Reuse = reuseAddress; _unitySocketFix.Port = LocalPort; _unitySocketFix.IPv6 = ipv6Mode; _unitySocketFix.ManualMode = manualMode; } else { _unitySocketFix.Paused = false; } #endif if (dualMode) { _udpSocketv6 = _udpSocketv4; } IsRunning = true; if (!manualMode) { ParameterizedThreadStart ts = ReceiveLogic; if (_useNativeSockets) { ts = NativeReceiveLogic; } _threadv4 = new Thread(ts) { Name = $"SocketThreadv4({LocalPort})", IsBackground = true }; _threadv4.Start(_udpSocketv4); } else { _bufferEndPointv4 = new IPEndPoint(IPAddress.Any, 0); } //Check IPv6 support if (!IPv6Support || ipv6Mode != IPv6Mode.SeparateSocket) { return(true); } _udpSocketv6 = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp); //Use one port for two sockets if (BindSocket(_udpSocketv6, new IPEndPoint(addressIPv6, LocalPort), reuseAddress, ipv6Mode)) { if (manualMode) { _bufferEndPointv6 = new IPEndPoint(IPAddress.IPv6Any, 0); } else { ParameterizedThreadStart ts = ReceiveLogic; if (_useNativeSockets) { ts = NativeReceiveLogic; } _threadv6 = new Thread(ts) { Name = $"SocketThreadv6({LocalPort})", IsBackground = true }; _threadv6.Start(_udpSocketv6); } } return(true); }
public bool Bind(IPAddress addressIPv4, IPAddress addressIPv6, int port, bool reuseAddress, IPv6Mode ipv6Mode) { if (IsActive()) { return(false); } bool dualMode = ipv6Mode == IPv6Mode.DualMode && IPv6Support; _udpSocketv4 = new Socket( dualMode ? AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); if (!BindSocket(_udpSocketv4, new IPEndPoint(dualMode ? addressIPv6 : addressIPv4, port), reuseAddress, ipv6Mode)) { return(false); } #if UNITY_IOS && !UNITY_EDITOR if (_unitySocketFix == null) { var unityFixObj = new GameObject("LiteNetLib_UnitySocketFix"); GameObject.DontDestroyOnLoad(unityFixObj); _unitySocketFix = unityFixObj.AddComponent <UnitySocketFix>(); _unitySocketFix.Socket = this; _unitySocketFix.BindAddrIPv4 = addressIPv4; _unitySocketFix.BindAddrIPv6 = addressIPv6; _unitySocketFix.Reuse = reuseAddress; _unitySocketFix.Port = port; _unitySocketFix.IPv6 = ipv6Mode; } #endif if (dualMode) { _udpSocketv6 = _udpSocketv4; } LocalPort = ((IPEndPoint)_udpSocketv4.LocalEndPoint).Port; IsRunning = true; _threadv4 = new Thread(ReceiveLogic) { Name = "SocketThreadv4(" + LocalPort + ")", IsBackground = true }; _threadv4.Start(_udpSocketv4); //Check IPv6 support if (!IPv6Support || ipv6Mode != IPv6Mode.SeparateSocket) { return(true); } _udpSocketv6 = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp); //Use one port for two sockets if (BindSocket(_udpSocketv6, new IPEndPoint(addressIPv6, LocalPort), reuseAddress, ipv6Mode)) { _threadv6 = new Thread(ReceiveLogic) { Name = "SocketThreadv6(" + LocalPort + ")", IsBackground = true }; _threadv6.Start(_udpSocketv6); } return(true); }