mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 03:30:53 +01:00
Fix IPv6 sockets on Linux.
By removing Q's NativeSockets layer and just using byte[] again. There's no performance loss because byte[] was already the only thing used.
This commit is contained in:
@@ -144,7 +144,7 @@ namespace Lidgren.Network
|
||||
//Avoids allocation on mapping to IPv6
|
||||
private IPEndPoint targetCopy = new IPEndPoint(IPAddress.Any, 0);
|
||||
|
||||
internal bool ActuallySendPacket(ReadOnlySpan<byte> data, int numBytes, NetEndPoint target, out bool connectionReset)
|
||||
internal bool ActuallySendPacket(byte[] data, int numBytes, NetEndPoint target, out bool connectionReset)
|
||||
{
|
||||
connectionReset = false;
|
||||
IPAddress ba = default(IPAddress);
|
||||
@@ -170,7 +170,7 @@ namespace Lidgren.Network
|
||||
targetCopy.Address = target.Address;
|
||||
}
|
||||
|
||||
int bytesSent = m_socket.SendTo(data.Slice( 0, numBytes ), 0, targetCopy);
|
||||
int bytesSent = m_socket.SendTo(data, 0, numBytes, 0, targetCopy);
|
||||
if (numBytes != bytesSent)
|
||||
LogWarning("Failed to send the full " + numBytes + "; only " + bytesSent + " bytes sent in packet!");
|
||||
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
#pragma warning disable 649
|
||||
namespace Lidgren.Network {
|
||||
|
||||
public static partial class NativeSockets {
|
||||
|
||||
[SuppressMessage("ReSharper", "FieldCanBeMadeReadOnly.Local")]
|
||||
[StructLayout(LayoutKind.Sequential, Size = SockAddrStorageSize)]
|
||||
private struct SockAddr {
|
||||
|
||||
public ushort SocketAddressFamily;
|
||||
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "NotAccessedField.Local")]
|
||||
private struct SockAddrIn {
|
||||
|
||||
public ushort SocketAddressFamily;
|
||||
|
||||
public ushort Port;
|
||||
|
||||
public uint InAddr;
|
||||
|
||||
public ulong Zero;
|
||||
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Size = 16)]
|
||||
private struct InAddr6 {
|
||||
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "NotAccessedField.Local")]
|
||||
private struct SockAddrIn6 {
|
||||
|
||||
public ushort SocketAddressFamily;
|
||||
|
||||
public ushort Port;
|
||||
|
||||
public uint FlowInfo;
|
||||
|
||||
public InAddr6 InAddr;
|
||||
|
||||
public uint InScopeId;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,195 +0,0 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Buffers.Binary;
|
||||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace Lidgren.Network
|
||||
{
|
||||
|
||||
public static partial class NativeSockets
|
||||
{
|
||||
|
||||
private const int SockAddrStorageSize = 128; // sockaddr_storage
|
||||
|
||||
private static readonly bool IsWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
|
||||
|
||||
internal static unsafe int _SendTo(int socket, byte* buf, int len, int flags, void* to, int toLen)
|
||||
=> IsWindows
|
||||
? WindowsSockets.SendTo(socket, buf, len, flags, to, toLen)
|
||||
: PosixSockets.SendTo(socket, buf, len, flags, to, toLen);
|
||||
|
||||
internal static unsafe int _RecvFrom(int socket, byte* buf, int len, int flags, void* from, int* fromLen)
|
||||
=> IsWindows
|
||||
? WindowsSockets.RecvFrom(socket, buf, len, flags, from, fromLen)
|
||||
: PosixSockets.RecvFrom(socket, buf, len, flags, from, fromLen);
|
||||
|
||||
public static int GetError(Socket socket)
|
||||
=> (int) socket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Error);
|
||||
|
||||
public static unsafe int SendTo(this Socket socket, ReadOnlySpan<byte> buffer, int flags, IPEndPoint to)
|
||||
{
|
||||
switch (to.AddressFamily)
|
||||
{
|
||||
default:
|
||||
throw new NotImplementedException(to.AddressFamily.ToString());
|
||||
|
||||
case AddressFamily.InterNetwork:
|
||||
{
|
||||
var error = 0;
|
||||
var addrIn = new SockAddrIn();
|
||||
var port = (ushort) to.Port;
|
||||
addrIn.SocketAddressFamily = (ushort) to.AddressFamily;
|
||||
addrIn.Port = BitConverter.IsLittleEndian ? BinaryPrimitives.ReverseEndianness(port) : port;
|
||||
if (!to.Address.TryWriteBytes(MemoryMarshal.AsBytes(MemoryMarshal.CreateSpan(ref addrIn.InAddr, 1)), out _))
|
||||
throw new NotImplementedException("Can't write address.");
|
||||
|
||||
int result;
|
||||
fixed (byte* pBuf = buffer)
|
||||
{
|
||||
result = _SendTo(socket.Handle.ToInt32(), pBuf, buffer.Length, flags, &addrIn, sizeof(SockAddrIn));
|
||||
}
|
||||
|
||||
if (result == -1)
|
||||
{
|
||||
error = GetError(socket);
|
||||
if (error == 0)
|
||||
error = Marshal.GetLastWin32Error();
|
||||
}
|
||||
|
||||
if (result == -1)
|
||||
throw new SocketException(error);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
case AddressFamily.InterNetworkV6:
|
||||
{
|
||||
var error = 0;
|
||||
var addrIn6 = new SockAddrIn6();
|
||||
var port = (ushort) to.Port;
|
||||
addrIn6.SocketAddressFamily = (ushort) to.AddressFamily;
|
||||
addrIn6.Port = BitConverter.IsLittleEndian ? BinaryPrimitives.ReverseEndianness(port) : port;
|
||||
if (!to.Address.TryWriteBytes(MemoryMarshal.AsBytes(MemoryMarshal.CreateSpan(ref addrIn6.InAddr, 1)), out _))
|
||||
throw new NotImplementedException("Can't write address.");
|
||||
|
||||
addrIn6.InScopeId = checked((uint) to.Address.ScopeId);
|
||||
int result;
|
||||
fixed (byte* pBuf = buffer)
|
||||
{
|
||||
result = _SendTo(socket.Handle.ToInt32(), pBuf, buffer.Length, flags, &addrIn6, sizeof(SockAddrIn6));
|
||||
}
|
||||
|
||||
if (result == -1)
|
||||
{
|
||||
error = GetError(socket);
|
||||
if (error == 0)
|
||||
error = Marshal.GetLastWin32Error();
|
||||
}
|
||||
|
||||
if (result == -1)
|
||||
throw new SocketException(error);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static unsafe int ReceiveFrom(this Socket socket, Span<byte> buffer, int flags, out IPEndPoint? from)
|
||||
{
|
||||
var error = 0;
|
||||
int result;
|
||||
var fromSockAddrSize = SockAddrStorageSize;
|
||||
var pFrom = stackalloc byte[SockAddrStorageSize];
|
||||
|
||||
fixed (byte* pBuf = buffer)
|
||||
{
|
||||
result = _RecvFrom(socket.Handle.ToInt32(), pBuf, buffer.Length, flags, pFrom, &fromSockAddrSize);
|
||||
}
|
||||
|
||||
if (result == -1)
|
||||
{
|
||||
error = GetError(socket);
|
||||
if (error == 0)
|
||||
{
|
||||
error = Marshal.GetLastWin32Error();
|
||||
}
|
||||
}
|
||||
|
||||
ReadIp(out from, (SockAddr*) pFrom);
|
||||
|
||||
if (result == -1)
|
||||
{
|
||||
throw new SocketException(error);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static unsafe void ReadIp(out IPEndPoint? from, SockAddr* pFrom)
|
||||
{
|
||||
switch (pFrom->SocketAddressFamily)
|
||||
{
|
||||
default:
|
||||
throw new NotSupportedException(((AddressFamily) pFrom->SocketAddressFamily).ToString());
|
||||
case (ushort) AddressFamily.Unspecified:
|
||||
from = null;
|
||||
break;
|
||||
case (ushort) AddressFamily.InterNetwork:
|
||||
ReadIPv4(out from, (SockAddrIn*) pFrom);
|
||||
break;
|
||||
case (ushort) AddressFamily.InterNetworkV6:
|
||||
ReadIPv6(out from, (SockAddrIn6*) pFrom);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static unsafe void ReadIPv4(out IPEndPoint from, SockAddrIn* addr)
|
||||
{
|
||||
var port = BitConverter.IsLittleEndian ? BinaryPrimitives.ReverseEndianness(addr->Port) : addr->Port;
|
||||
var ip = BitConverter.IsLittleEndian ? BinaryPrimitives.ReverseEndianness(addr->InAddr) : addr->InAddr;
|
||||
|
||||
from = new IPEndPoint(
|
||||
ip,
|
||||
port
|
||||
);
|
||||
}
|
||||
|
||||
private static unsafe void ReadIPv6(out IPEndPoint from, SockAddrIn6* addr)
|
||||
{
|
||||
var port = BitConverter.IsLittleEndian ? BinaryPrimitives.ReverseEndianness(addr->Port) : addr->Port;
|
||||
|
||||
var ip = new IPAddress(MemoryMarshal.AsBytes(MemoryMarshal.CreateReadOnlySpan(ref addr->InAddr, 1)), addr->InScopeId);
|
||||
|
||||
from = new IPEndPoint(ip, port);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal static class PosixSockets
|
||||
{
|
||||
|
||||
[DllImport("libc", EntryPoint = "sendto")]
|
||||
internal static extern unsafe int SendTo(int socket, byte* buf, int len, int flags, void* to, int toLen);
|
||||
|
||||
[DllImport("libc", EntryPoint = "recvfrom")]
|
||||
internal static extern unsafe int RecvFrom(int socket, byte* buf, int len, int flags, void* from, int* fromLen);
|
||||
|
||||
}
|
||||
|
||||
internal static class WindowsSockets
|
||||
{
|
||||
|
||||
[DllImport("ws2_32", EntryPoint = "sendto")]
|
||||
internal static extern unsafe int SendTo(int socket, byte* buf, int len, int flags, void* to, int toLen);
|
||||
|
||||
[DllImport("ws2_32", EntryPoint = "recvfrom")]
|
||||
internal static extern unsafe int RecvFrom(int socket, byte* buf, int len, int flags, void* from, int* fromLen);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user