Ejemplo n.º 1
0
        /// <summary>
        /// Resolves a host name or IP address to an <see cref="IPHostEntry"/> instance.
        /// </summary>
        /// <param name="hostNameOrAddress">The host name or IP address to resolve.</param>
        /// <returns>An <see cref="IPHostEntry"/> instance that contains address information about the host specified in
        /// hostNameOrAddress.
        /// </returns>
        /// <remarks>
        /// <para>The GetHostEntry method queries a DNS server for the IP address that is associated with a host name or IP address.</para>
        /// <para>When an empty string is passed as the host name, this method returns the IPv4 addresses of the local host.</para>
        /// </remarks>
        public static IPHostEntry GetHostEntry(string hostNameOrAddress)
        {
            NativeSocket.getaddrinfo(hostNameOrAddress, out string canonicalName, out byte[][] addresses);

            int addressesCount = addresses.Length;

            IPAddress[] ipAddresses = new IPAddress[addressesCount];
            IPHostEntry ipHostEntry = new();

            for (int i = 0; i < addressesCount; i++)
            {
                byte[] address = addresses[i];

                AddressFamily family = (AddressFamily)((address[1] << 8) | address[0]);

                if (family == AddressFamily.InterNetwork)
                {
                    uint ipAddr = (uint)((address[7] << 24) | (address[6] << 16) | (address[5] << 8) | (address[4]));

                    ipAddresses[i] = new IPAddress(ipAddr);
                }
                else
                {
                    throw new NotImplementedException();
                }
            }

            ipHostEntry.hostName    = canonicalName;
            ipHostEntry.addressList = ipAddresses;

            return(ipHostEntry);
        }
Ejemplo n.º 2
0
        // ReSharper disable once TooManyArguments
        private IntPtr OnWSAOpenSocket(
            AddressFamily addressFamily,
            SocketType type,
            ProtocolType protocol,
            IntPtr protocolInfo,
            int groupId,
            short flags,
            bool isUnicode)
        {
            var socket = isUnicode
                ? NativeSocket.WSAOpenSocketW(addressFamily, type, protocol, protocolInfo, groupId, flags)
                : NativeSocket.WSAOpenSocketA(addressFamily, type, protocol, protocolInfo, groupId, flags);

            if (socket != IntPtr.Zero)
            {
                lock (SocketLookupTable)
                {
                    if (!SocketLookupTable.ContainsKey(socket))
                    {
                        DebugMessage(
                            nameof(OnWSAOpenSocket),
                            socket,
                            "New socket created."
                            );
                        SocketLookupTable.Add(socket, false);
                    }
                }
            }

            return(socket);
        }
Ejemplo n.º 3
0
        // ReSharper disable once TooManyArguments
        private void DebugMessage(string scope, IntPtr?socket, string message, params object[] args)
        {
            var lastError = NativeSocket.WSAGetLastError();

            try
            {
                var space = Math.Max(20 - scope.Length, 0);

                message = string.Format(
                    "{0:s} - #{4:D8} [`{1}`] {2}{3}",
                    DateTime.UtcNow,
                    scope,
                    new string(' ', space),
                    args?.Length > 0 ? string.Format(message, args) : message,
                    socket?.ToInt64() ?? 0
                    );

#if DEBUG
                try
                {
                    Debug.WriteLine(message);
                    Console.WriteLine(message);
                }
                catch
                {
                    // ignored
                }
#endif

                try
                {
                    if (string.IsNullOrWhiteSpace(LogPath))
                    {
                        return;
                    }

                    File.AppendAllText(LogPath, message + Environment.NewLine);
                }
                catch
                {
                    // ignored
                }
            }
            catch
            {
                // ignored
            }

            NativeSocket.WSASetLastError(lastError);
        }
Ejemplo n.º 4
0
        private void NativeReceiveLogic(object state)
        {
            Socket socket       = (Socket)state;
            IntPtr socketHandle = socket.Handle;

            byte[] addrBuffer = new byte[socket.AddressFamily == AddressFamily.InterNetwork
                ? NativeSocket.IPv4AddrSize
                : NativeSocket.IPv6AddrSize];

            int        addrSize = addrBuffer.Length;
            IPEndPoint endPoint = null;
            NetPacket  packet   = _listener.NetPacketPool.GetPacket(NetConstants.MaxPacketSize);

            while (IsActive())
            {
                //Reading data
                packet.Size = NativeSocket.RecvFrom(socketHandle, packet.RawData, NetConstants.MaxPacketSize, addrBuffer, ref addrSize);
                if (packet.Size == 0)
                {
                    return;
                }
                if (packet.Size == -1)
                {
                    SocketError errorCode = NativeSocket.GetSocketError();
                    if (errorCode == SocketError.WouldBlock || errorCode == SocketError.TimedOut) //Linux timeout EAGAIN
                    {
                        continue;
                    }
                    if (ProcessError(new SocketException((int)errorCode), endPoint))
                    {
                        return;
                    }
                    continue;
                }

                NativeAddr nativeAddr = new NativeAddr(addrBuffer, addrSize);
                if (!_nativeAddrMap.TryGetValue(nativeAddr, out endPoint))
                {
                    endPoint = new NativeEndPoint(addrBuffer);
                }

                //All ok!
                //NetDebug.WriteForce($"[R]Received data from {endPoint}, result: {packet.Size}");
                _listener.OnMessageReceived(packet, 0, endPoint);
                packet = _listener.NetPacketPool.GetPacket(NetConstants.MaxPacketSize);
            }
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Resolves a host name or IP address to an <see cref="IPHostEntry"/> instance.
        /// </summary>
        /// <param name="hostNameOrAddress">The host name or IP address to resolve.</param>
        /// <returns>An <see cref="IPHostEntry"/> instance that contains address information about the host specified in
        /// hostNameOrAddress.
        /// </returns>
        /// <remarks>
        /// <para>The GetHostEntry method queries a DNS server for the IP address that is associated with a host name or IP address.</para>
        /// <para>When an empty string is passed as the host name, this method returns the IPv4 addresses of the local host.</para>
        /// </remarks>
        public static IPHostEntry GetHostEntry(string hostNameOrAddress)
        {
            //Do we need to try to pase this as an Address????
            string canonicalName;

            byte[][] addresses;

            NativeSocket.getaddrinfo(hostNameOrAddress, out canonicalName, out addresses);

            int cAddresses = addresses.Length;

            IPAddress[] ipAddresses = new IPAddress[cAddresses];
            IPHostEntry ipHostEntry = new IPHostEntry();

            for (int i = 0; i < cAddresses; i++)
            {
                byte[] address = addresses[i];

                SocketAddress sockAddress = new SocketAddress(address);

                AddressFamily family;

                //if(SystemInfo.IsBigEndian)
                ////{
                //    family = (AddressFamily)((address[0] << 8) | address[1]);
                //}
                //else
                {
                    family = (AddressFamily)((address[1] << 8) | address[0]);
                }
                //port address[2-3]

                if (family == AddressFamily.InterNetwork)
                {
                    //This only works with IPv4 addresses

                    uint ipAddr = (uint)((address[7] << 24) | (address[6] << 16) | (address[5] << 8) | (address[4]));

                    ipAddresses[i] = new IPAddress((long)ipAddr);
                }
            }

            ipHostEntry.hostName    = canonicalName;
            ipHostEntry.addressList = ipAddresses;

            return(ipHostEntry);
        }
Ejemplo n.º 6
0
        private SocketError OnCloseSocket(IntPtr socket)
        {
            var result = NativeSocket.CloseSocket(socket);

            if (socket != IntPtr.Zero && (result == SocketError.Success || result == SocketError.WouldBlock))
            {
                lock (SocketLookupTable)
                {
                    if (SocketLookupTable.ContainsKey(socket))
                    {
                        DebugMessage(
                            nameof(OnCloseSocket),
                            socket,
                            "Socket destroyed."
                            );
                        SocketLookupTable.Remove(socket);
                    }
                }
            }

            return(result);
        }
Ejemplo n.º 7
0
        private IntPtr OnOpenSocket(AddressFamily addressFamily, SocketType type, ProtocolType protocol)
        {
            var socket = NativeSocket.OpenSocket(addressFamily, type, protocol);

            if (socket != IntPtr.Zero)
            {
                lock (SocketLookupTable)
                {
                    if (!SocketLookupTable.ContainsKey(socket))
                    {
                        DebugMessage(
                            nameof(OnOpenSocket),
                            socket,
                            "New socket created."
                            );
                        SocketLookupTable.Add(socket, false);
                    }
                }
            }

            return(socket);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Resolves a host name or IP address to an <see cref="IPHostEntry"/> instance.
        /// </summary>
        /// <param name="hostNameOrAddress">The host name or IP address to resolve.</param>
        /// <returns>An <see cref="IPHostEntry"/> instance that contains address information about the host specified in
        /// hostNameOrAddress.
        /// </returns>
        /// <remarks>
        /// <para>The GetHostEntry method queries a DNS server for the IP address that is associated with a host name or IP address.</para>
        /// <para>When an empty string is passed as the host name, this method returns the IPv4 addresses of the local host.</para>
        /// </remarks>
        public static IPHostEntry GetHostEntry(string hostNameOrAddress)
        {
            //Do we need to try to pase this as an Address????
            string canonicalName;

            byte[][] addresses;

            NativeSocket.getaddrinfo(hostNameOrAddress, out canonicalName, out addresses);

            int cAddresses = addresses.Length;

            IPAddress[] ipAddresses = new IPAddress[cAddresses];
            IPHostEntry ipHostEntry = new IPHostEntry();

            for (int i = 0; i < cAddresses; i++)
            {
                ipAddresses[i] = new IPAddress(addresses[i]);
            }

            ipHostEntry.hostName    = canonicalName;
            ipHostEntry.addressList = ipAddresses;

            return(ipHostEntry);
        }
Ejemplo n.º 9
0
        public int SendTo(byte[] data, int offset, int size, IPEndPoint remoteEndPoint, ref SocketError errorCode)
        {
            if (!IsActive())
            {
                return(0);
            }
            try
            {
                var socket = _udpSocketv4;
                if (remoteEndPoint.AddressFamily == AddressFamily.InterNetworkV6 && IPv6Support)
                {
                    socket = _udpSocketv6;
                    if (socket == null)
                    {
                        return(0);
                    }
                }

                int result;
                if (_useNativeSockets)
                {
                    byte[] socketAddress;

                    if (remoteEndPoint is NativeEndPoint nep)
                    {
                        socketAddress = nep.NativeAddress;
                    }
                    else //Convert endpoint to raw
                    {
                        if (_endPointBuffer == null)
                        {
                            _endPointBuffer = new byte[NativeSocket.IPv6AddrSize];
                        }
                        socketAddress = _endPointBuffer;

                        bool  ipv4          = remoteEndPoint.AddressFamily == AddressFamily.InterNetwork;
                        short addressFamily = NativeSocket.GetNativeAddressFamily(remoteEndPoint);

                        socketAddress[0] = (byte)(addressFamily);
                        socketAddress[1] = (byte)(addressFamily >> 8);
                        socketAddress[2] = (byte)(remoteEndPoint.Port >> 8);
                        socketAddress[3] = (byte)(remoteEndPoint.Port);

                        if (ipv4)
                        {
#pragma warning disable 618
                            long addr = remoteEndPoint.Address.Address;
#pragma warning restore 618
                            socketAddress[4] = (byte)(addr);
                            socketAddress[5] = (byte)(addr >> 8);
                            socketAddress[6] = (byte)(addr >> 16);
                            socketAddress[7] = (byte)(addr >> 24);
                        }
                        else
                        {
#if NETCOREAPP || NETSTANDARD2_1 || NETSTANDARD2_1_OR_GREATER
                            remoteEndPoint.Address.TryWriteBytes(new Span <byte>(socketAddress, 8, 16), out _);
#else
                            byte[] addrBytes = remoteEndPoint.Address.GetAddressBytes();
                            Buffer.BlockCopy(addrBytes, 0, socketAddress, 8, 16);
#endif
                        }
                    }

#if LITENETLIB_UNSAFE
                    unsafe
                    {
                        fixed(byte *dataWithOffset = &data[offset])
                        {
                            result = NativeSocket.SendTo(socket.Handle, dataWithOffset, size, socketAddress, socketAddress.Length);
                        }
                    }
#else
                    if (offset > 0)
                    {
                        if (_sendToBuffer == null)
                        {
                            _sendToBuffer = new byte[NetConstants.MaxPacketSize];
                        }
                        Buffer.BlockCopy(data, offset, _sendToBuffer, 0, size);
                        data = _sendToBuffer;
                    }
                    result = NativeSocket.SendTo(socket.Handle, data, size, socketAddress, socketAddress.Length);
#endif
                    if (result == -1)
                    {
                        throw NativeSocket.GetSocketException();
                    }
                }
                else
                {
                    result = socket.SendTo(data, offset, size, SocketFlags.None, remoteEndPoint);
                }
                //NetDebug.WriteForce("[S]Send packet to {0}, result: {1}", remoteEndPoint, result);
                return(result);
            }
            catch (SocketException ex)
            {
                switch (ex.SocketErrorCode)
                {
                case SocketError.NoBufferSpaceAvailable:
                case SocketError.Interrupted:
                    return(0);

                case SocketError.MessageSize:     //do nothing
                    break;

                default:
                    NetDebug.WriteError($"[S] {ex}");
                    break;
                }
                errorCode = ex.SocketErrorCode;
                return(-1);
            }
            catch (Exception ex)
            {
                NetDebug.WriteError($"[S] {ex}");
                return(-1);
            }
        }
Ejemplo n.º 10
0
        private SocketError OnConnect(IntPtr socket, IntPtr address, int addressSize)
        {
            var socketAddress = GetSocketAddress(address);

            DebugMessage(
                nameof(OnConnect),
                socket,
                "Connecting to `{0}:{1}` ...",
                socketAddress?.Address?.IPAddress,
                socketAddress?.Port
                );

            var bindResult = BindSocketByAddress(socket, socketAddress);

            DebugMessage(
                nameof(OnConnect),
                socket,
                "Binding `{0}:{1}` to interface resulted in a `{2}` response. [WSALastError = `{3}`]",
                socketAddress?.Address?.IPAddress,
                socketAddress?.Port,
                bindResult,
                NativeSocket.WSAGetLastError()
                );

            if (bindResult != SocketError.Success)
            {
                if (bindResult != SocketError.SocketError)
                {
                    DebugMessage(
                        nameof(OnConnect),
                        socket,
                        NativeSocket.WSAGetLastError().ToString()
                        );
                }

                DebugMessage(
                    nameof(OnConnect),
                    socket,
                    "Connecting to `{0}:{1}` rejected.",
                    socketAddress?.Address?.IPAddress,
                    socketAddress?.Port
                    );

                return(SocketError.SocketError);
            }

            var returnValue = NativeSocket.Connect(socket, address, addressSize);

            DebugMessage(
                nameof(OnConnect),
                socket,
                "Connecting to `{0}:{1}` resulted in a `{2}` response. [WSALastError = `{3}`]",
                socketAddress?.Address?.IPAddress,
                socketAddress?.Port,
                returnValue,
                NativeSocket.WSAGetLastError()
                );

            //if (returnValue == SocketError.SocketError && Socket.WSAGetLastError() == SocketError.Success)
            //{
            //    returnValue = SocketError.Success;
            //}

            return(returnValue);
        }
Ejemplo n.º 11
0
        private SocketError OnBind(IntPtr socket, IntPtr address, int addressSize)
        {
            var socketAddress = GetSocketAddress(address);

            DebugMessage(
                nameof(OnBind),
                socket,
                "Binding to `{0}:{1}` ...",
                socketAddress?.Address?.IPAddress,
                socketAddress?.Port
                );

            SocketError bindResult;

            if (IsInternalAddress(socket, socketAddress))
            {
                bindResult = NativeSocket.Bind(socket, address, addressSize);
            }
            else
            {
                var networkInterface = GetNetworkInterface();
                var interfaceAddress = GetInterfaceAddress(networkInterface, socketAddress?.AddressFamily, true);

                if (socketAddress?.Address == null || networkInterface == null || interfaceAddress == null)
                {
                    DebugMessage(
                        nameof(OnBind),
                        socket,
                        "Binding to `{0}:{1}` rejected due to lack of a valid interface address.",
                        socketAddress?.Address?.IPAddress,
                        socketAddress?.Port
                        );

                    return(SocketError.SocketError);
                }


                if (interfaceAddress.AddressFamily == AddressFamily.InterNetwork &&
                    !interfaceAddress.Equals(socketAddress.Address.IPAddress))
                {
                    var bindIn = new SocketAddressIn
                    {
                        Address = new AddressIn {
                            IPAddress = interfaceAddress
                        },
                        AddressFamily = interfaceAddress.AddressFamily,
                        Port          = socketAddress.Port
                    };

                    DebugMessage(
                        nameof(OnBind),
                        socket,
                        "Binding to `{0}:{1}` replaced by a binding request to `{2}:{3}`.",
                        socketAddress.Address.IPAddress,
                        socketAddress.Port,
                        bindIn.Address.IPAddress,
                        bindIn.Port
                        );

                    MarkSocketAsBinded(socket);

                    socketAddress = bindIn;

                    bindResult = NativeSocket.Bind(socket, ref bindIn, Marshal.SizeOf(bindIn));
                }
                else if (interfaceAddress.AddressFamily == AddressFamily.InterNetworkV6 &&
                         !interfaceAddress.Equals(socketAddress.Address.IPAddress))
                {
                    var scopeId  = (uint?)networkInterface.GetIPProperties()?.GetIPv6Properties()?.Index ?? 0;
                    var flowInfo = (socketAddress as SocketAddressIn6?)?.FlowInfo ?? 0;

                    var bindIn6 = new SocketAddressIn6
                    {
                        Address = new AddressIn6 {
                            IPAddress = interfaceAddress
                        },
                        AddressFamily = interfaceAddress.AddressFamily,
                        Port          = socketAddress.Port, // Assign a random port
                        ScopeId       = scopeId,
                        FlowInfo      = flowInfo
                    };

                    DebugMessage(
                        nameof(OnBind),
                        socket,
                        "Binding to `{0}:{1}` replaced by a binding request to `{2}:{3}`.",
                        socketAddress.Address.IPAddress,
                        socketAddress.Port,
                        bindIn6.Address.IPAddress,
                        bindIn6.Port
                        );

                    MarkSocketAsBinded(socket);

                    socketAddress = bindIn6;

                    bindResult = NativeSocket.Bind(socket, ref bindIn6, Marshal.SizeOf(bindIn6));
                }
                else
                {
                    bindResult = NativeSocket.Bind(socket, address, addressSize);
                }
            }

            DebugMessage(
                nameof(OnBind),
                socket,
                "Binding to `{0}:{1}` resulted in a `{2}` response. [WSALastError = `{3}`]",
                socketAddress?.Address?.IPAddress,
                socketAddress?.Port,
                bindResult,
                NativeSocket.WSAGetLastError()
                );

            return(bindResult);
        }
Ejemplo n.º 12
0
        private SocketError BindSocketByAddress(IntPtr socket, ISocketAddress socketAddress)
        {
            if (IsSpecialAddress(socket, socketAddress))
            {
                return(SocketError.Success);
            }

            if (IsSocketMarkedAsBinded(socket))
            {
                DebugMessage(
                    nameof(BindSocketByAddress),
                    socket,
                    "Binding to interface skipped as the socket should be already binded."
                    );

                return(SocketError.Success);
            }

            var networkInterface = GetNetworkInterface();
            var interfaceAddress = GetInterfaceAddress(networkInterface, socketAddress.AddressFamily, false);

            if (networkInterface == null || interfaceAddress == null)
            {
                DebugMessage(
                    nameof(BindSocketByAddress),
                    socket,
                    "Binding for the `{0}:{1}` rejected due to lack of a valid interface address.",
                    socketAddress.Address?.IPAddress,
                    socketAddress.Port
                    );

                return(SocketError.SocketError);
            }

            if (interfaceAddress.AddressFamily == AddressFamily.InterNetwork)
            {
                var bindIn = new SocketAddressIn
                {
                    Address = new AddressIn {
                        IPAddress = interfaceAddress
                    },
                    AddressFamily = interfaceAddress.AddressFamily,
                    Port          = 0 // Assign a random port
                };

                DebugMessage(
                    nameof(BindSocketByAddress),
                    socket,
                    "Binding to `{0}:{1}` ...",
                    bindIn.Address?.IPAddress,
                    bindIn.Port
                    );

                MarkSocketAsBinded(socket);

                return(NativeSocket.Bind(socket, ref bindIn, Marshal.SizeOf(bindIn)));
            }

            if (interfaceAddress.AddressFamily == AddressFamily.InterNetworkV6)
            {
                var scopeId  = (uint?)networkInterface.GetIPProperties()?.GetIPv6Properties()?.Index ?? 0;
                var flowInfo = (socketAddress as SocketAddressIn6?)?.FlowInfo ?? 0;

                var bindIn6 = new SocketAddressIn6
                {
                    Address = new AddressIn6 {
                        IPAddress = interfaceAddress
                    },
                    AddressFamily = interfaceAddress.AddressFamily,
                    Port          = 0, // Assign a random port
                    ScopeId       = scopeId,
                    FlowInfo      = flowInfo
                };

                DebugMessage(
                    nameof(BindSocketByAddress),
                    socket,
                    "Binding to `{0}:{1}` ...",
                    bindIn6.Address?.IPAddress,
                    bindIn6.Port
                    );

                MarkSocketAsBinded(socket);

                return(NativeSocket.Bind(socket, ref bindIn6, Marshal.SizeOf(bindIn6)));
            }

            DebugMessage(
                nameof(BindSocketByAddress),
                socket,
                "Binding to interface skipped due an unsupported interface address family of `{0}`.",
                interfaceAddress.AddressFamily
                );

            return(SocketError.Success);
        }
Ejemplo n.º 13
0
        internal int SendRaw(byte[] message, int start, int length, IPEndPoint remoteEndPoint)
        {
            if (!IsRunning)
            {
                return(0);
            }

            NetPacket expandedPacket = null;

            if (_extraPacketLayer != null)
            {
                expandedPacket = PoolGetPacket(length + _extraPacketLayer.ExtraPacketSizeForLayer);
                Buffer.BlockCopy(message, start, expandedPacket.RawData, 0, length);
                start = 0;
                _extraPacketLayer.ProcessOutBoundPacket(ref remoteEndPoint, ref expandedPacket.RawData, ref start, ref length);
                message = expandedPacket.RawData;
            }

            var socket = _udpSocketv4;

            if (remoteEndPoint.AddressFamily == AddressFamily.InterNetworkV6 && IPv6Support)
            {
                socket = _udpSocketv6;
                if (socket == null)
                {
                    return(0);
                }
            }

            int result;

            try
            {
                if (UseNativeSockets)
                {
                    byte[] socketAddress;

                    if (remoteEndPoint is NativeEndPoint nep)
                    {
                        socketAddress = nep.NativeAddress;
                    }
                    else //Convert endpoint to raw
                    {
                        if (_endPointBuffer == null)
                        {
                            _endPointBuffer = new byte[NativeSocket.IPv6AddrSize];
                        }
                        socketAddress = _endPointBuffer;

                        bool  ipv4          = remoteEndPoint.AddressFamily == AddressFamily.InterNetwork;
                        short addressFamily = NativeSocket.GetNativeAddressFamily(remoteEndPoint);

                        socketAddress[0] = (byte)(addressFamily);
                        socketAddress[1] = (byte)(addressFamily >> 8);
                        socketAddress[2] = (byte)(remoteEndPoint.Port >> 8);
                        socketAddress[3] = (byte)(remoteEndPoint.Port);

                        if (ipv4)
                        {
#pragma warning disable 618
                            long addr = remoteEndPoint.Address.Address;
#pragma warning restore 618
                            socketAddress[4] = (byte)(addr);
                            socketAddress[5] = (byte)(addr >> 8);
                            socketAddress[6] = (byte)(addr >> 16);
                            socketAddress[7] = (byte)(addr >> 24);
                        }
                        else
                        {
#if NETCOREAPP || NETSTANDARD2_1 || NETSTANDARD2_1_OR_GREATER
                            remoteEndPoint.Address.TryWriteBytes(new Span <byte>(socketAddress, 8, 16), out _);
#else
                            byte[] addrBytes = remoteEndPoint.Address.GetAddressBytes();
                            Buffer.BlockCopy(addrBytes, 0, socketAddress, 8, 16);
#endif
                        }
                    }

#if LITENETLIB_UNSAFE
                    unsafe
                    {
                        fixed(byte *dataWithOffset = &message[start])
                        {
                            result =
                                NativeSocket.SendTo(socket.Handle, dataWithOffset, length, socketAddress, socketAddress.Length);
                        }
                    }
#else
                    if (start > 0)
                    {
                        if (_sendToBuffer == null)
                        {
                            _sendToBuffer = new byte[NetConstants.MaxPacketSize];
                        }
                        Buffer.BlockCopy(message, start, _sendToBuffer, 0, length);
                        message = _sendToBuffer;
                    }

                    result = NativeSocket.SendTo(socket.Handle, message, length, socketAddress, socketAddress.Length);
#endif
                    if (result == -1)
                    {
                        throw NativeSocket.GetSocketException();
                    }
                }
                else
                {
                    result = socket.SendTo(message, start, length, SocketFlags.None, remoteEndPoint);
                }
                //NetDebug.WriteForce("[S]Send packet to {0}, result: {1}", remoteEndPoint, result);
            }
            catch (SocketException ex)
            {
                switch (ex.SocketErrorCode)
                {
                case SocketError.NoBufferSpaceAvailable:
                case SocketError.Interrupted:
                    return(0);

                case SocketError.MessageSize:
                    NetDebug.Write(NetLogLevel.Trace, "[SRD] 10040, datalen: {0}", length);
                    return(0);

                case SocketError.HostUnreachable:
                case SocketError.NetworkUnreachable:
                    if (DisconnectOnUnreachable && TryGetPeer(remoteEndPoint, out var fromPeer))
                    {
                        DisconnectPeerForce(
                            fromPeer,
                            ex.SocketErrorCode == SocketError.HostUnreachable
                                    ? DisconnectReason.HostUnreachable
                                    : DisconnectReason.NetworkUnreachable,
                            ex.SocketErrorCode,
                            null);
                    }

                    CreateEvent(NetEvent.EType.Error, remoteEndPoint: remoteEndPoint, errorCode: ex.SocketErrorCode);
                    return(-1);

                default:
                    NetDebug.WriteError($"[S] {ex}");
                    return(-1);
                }
            }
            catch (Exception ex)
            {
                NetDebug.WriteError($"[S] {ex}");
                return(0);
            }
            finally
            {
                if (expandedPacket != null)
                {
                    PoolRecycle(expandedPacket);
                }
            }

            if (result <= 0)
            {
                return(0);
            }

            if (EnableStatistics)
            {
                Statistics.IncrementPacketsSent();
                Statistics.AddBytesSent(length);
            }

            return(result);
        }
Ejemplo n.º 14
0
        private void NativeReceiveLogic(object state)
        {
            Socket socket       = (Socket)state;
            IntPtr socketHandle = socket.Handle;

            byte[] addrBuffer = new byte[socket.AddressFamily == AddressFamily.InterNetwork
                ? NativeSocket.IPv4AddrSize
                : NativeSocket.IPv6AddrSize];

            int             addrSize  = addrBuffer.Length;
            IPEndPoint      endPoint  = null;
            NativeTimeValue timeValue = new NativeTimeValue
            {
                Seconds      = (int)(ReceivePollingTime / 1000000L),
                Microseconds = (int)(ReceivePollingTime % 1000000L)
            };
            var pollHandle = new IntPtr[2];

            while (IsActive())
            {
                NetPacket packet;

                //Reading data
                try
                {
                    if (socket.Available == 0)
                    {
                        pollHandle[0] = (IntPtr)1;
                        pollHandle[1] = socketHandle;
                        if (NativeSocket.Poll(pollHandle, ref timeValue) == -1)
                        {
                            throw new SocketException((int)NativeSocket.GetSocketError());
                        }
                        if ((int)pollHandle[0] == 0 || pollHandle[1] != socketHandle)
                        {
                            continue;
                        }
                    }
                    packet      = _listener.NetPacketPool.GetPacket(NetConstants.MaxPacketSize);
                    packet.Size = NativeSocket.RecvFrom(socketHandle, packet.RawData, NetConstants.MaxPacketSize, addrBuffer, ref addrSize);
                    if (packet.Size == -1)
                    {
                        throw new SocketException((int)NativeSocket.GetSocketError());
                    }

                    NativeAddr nativeAddr = new NativeAddr(addrBuffer, addrSize);
                    if (!_nativeAddrMap.TryGetValue(nativeAddr, out endPoint))
                    {
                        endPoint = new NativeEndPoint(addrBuffer);
                    }
                }
                catch (SocketException ex)
                {
                    if (ProcessError(ex, endPoint))
                    {
                        return;
                    }
                    continue;
                }
                catch (ObjectDisposedException)
                {
                    return;
                }

                //All ok!
                //NetDebug.Write(NetLogLevel.Trace, "[R]Received data from {0}, result: {1}", endPoint.ToString(), packet.Size);
                _listener.OnMessageReceived(packet, 0, endPoint);
            }
        }