/// <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); }
// 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); }
// 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); }
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); } }
/// <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); }
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); }
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); }
/// <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); }
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); } }
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); }
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); }
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); }
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); }
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); } }