Exemple #1
0
        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);
        }
Exemple #3
0
        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);
        }
Exemple #4
0
        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);
        }