├── .gitattributes
├── Test
├── Program.cs
├── Test.csproj
└── TestWave.cs
├── enet-csharp
├── ENet
│ ├── plugins
│ │ ├── NativeSockets
│ │ │ ├── Unix
│ │ │ │ ├── Shared
│ │ │ │ │ ├── include
│ │ │ │ │ │ ├── iovec.cs
│ │ │ │ │ │ ├── pollfd.cs
│ │ │ │ │ │ ├── PollEvents.cs
│ │ │ │ │ │ └── msghdr.cs
│ │ │ │ │ └── c
│ │ │ │ │ │ ├── iOSSocketPal.cs
│ │ │ │ │ │ └── UnixSocketPal.cs
│ │ │ │ └── Linux
│ │ │ │ │ └── c
│ │ │ │ │ └── LinuxSocketPal.cs
│ │ │ ├── Windows
│ │ │ │ └── include
│ │ │ │ │ └── WSABuffer.cs
│ │ │ ├── Shared
│ │ │ │ └── include
│ │ │ │ │ ├── sockaddr.cs
│ │ │ │ │ ├── sockaddr_storage.cs
│ │ │ │ │ ├── in_addr.cs
│ │ │ │ │ ├── sockaddr_in.cs
│ │ │ │ │ ├── addrinfo.cs
│ │ │ │ │ ├── sockaddr_in6.cs
│ │ │ │ │ ├── WinSock2.cs
│ │ │ │ │ └── sa_family_t.cs
│ │ │ └── SocketPal.cs
│ │ └── Helpers
│ │ │ ├── SpanHelpers.cs
│ │ │ └── XxHash.cs
│ ├── include
│ │ ├── utility.cs
│ │ ├── callback.cs
│ │ ├── time.cs
│ │ ├── list.cs
│ │ ├── win32.cs
│ │ └── protocol.cs
│ ├── define
│ │ └── system.cs
│ └── c
│ │ ├── list.cs
│ │ ├── callback.cs
│ │ ├── packet.cs
│ │ ├── win32.cs
│ │ ├── host.cs
│ │ └── enet.cs
└── enet-csharp.csproj
├── README.md
├── enet-csharp.sln
├── LICENSE
└── .gitignore
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/Test/Program.cs:
--------------------------------------------------------------------------------
1 | namespace enet
2 | {
3 | internal sealed class Program
4 | {
5 | private static void Main()
6 | {
7 | TestWave.Start();
8 | }
9 | }
10 | }
--------------------------------------------------------------------------------
/enet-csharp/ENet/plugins/NativeSockets/Unix/Shared/include/iovec.cs:
--------------------------------------------------------------------------------
1 | #pragma warning disable CS1591
2 | #pragma warning disable CS8981
3 |
4 | // ReSharper disable ALL
5 |
6 | namespace NativeSockets
7 | {
8 | public unsafe struct iovec
9 | {
10 | public void* iov_base;
11 | public nuint iov_len;
12 | }
13 | }
--------------------------------------------------------------------------------
/enet-csharp/ENet/plugins/NativeSockets/Windows/include/WSABuffer.cs:
--------------------------------------------------------------------------------
1 | #pragma warning disable CS1591
2 | #pragma warning disable CS8981
3 |
4 | // ReSharper disable ALL
5 |
6 | namespace NativeSockets
7 | {
8 | public unsafe struct WSABuffer
9 | {
10 | public nuint Length;
11 | public void* Pointer;
12 | }
13 | }
--------------------------------------------------------------------------------
/enet-csharp/ENet/plugins/NativeSockets/Unix/Shared/include/pollfd.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.InteropServices;
2 |
3 | #pragma warning disable CS1591
4 | #pragma warning disable CS8981
5 |
6 | // ReSharper disable ALL
7 |
8 | namespace NativeSockets
9 | {
10 | [StructLayout(LayoutKind.Sequential)]
11 | internal struct pollfd
12 | {
13 | public int fd;
14 | public short events;
15 | public short revents;
16 | }
17 | }
--------------------------------------------------------------------------------
/enet-csharp/ENet/include/utility.cs:
--------------------------------------------------------------------------------
1 | #pragma warning disable CS1591
2 |
3 | // ReSharper disable ALL
4 |
5 | namespace enet
6 | {
7 | public static partial class ENet
8 | {
9 | public static uint ENET_MAX(uint x, uint y) => ((x) > (y) ? (x) : (y));
10 | public static uint ENET_MIN(uint x, uint y) => ((x) < (y) ? (x) : (y));
11 | public static uint ENET_DIFFERENCE(uint x, uint y) => ((x) < (y) ? (y) - (x) : (x) - (y));
12 | }
13 | }
--------------------------------------------------------------------------------
/enet-csharp/ENet/plugins/NativeSockets/Shared/include/sockaddr.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.InteropServices;
2 |
3 | #pragma warning disable CS1591
4 | #pragma warning disable CS8981
5 |
6 | // ReSharper disable ALL
7 |
8 | namespace NativeSockets
9 | {
10 | [StructLayout(LayoutKind.Explicit, Size = 16)]
11 | public unsafe struct sockaddr
12 | {
13 | [FieldOffset(0)] public sa_family_t sa_family;
14 | [FieldOffset(2)] public fixed byte sa_data[14];
15 | }
16 | }
--------------------------------------------------------------------------------
/enet-csharp/ENet/plugins/NativeSockets/Shared/include/sockaddr_storage.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.InteropServices;
2 |
3 | #pragma warning disable CS1591
4 | #pragma warning disable CS8981
5 |
6 | // ReSharper disable ALL
7 |
8 | namespace NativeSockets
9 | {
10 | [StructLayout(LayoutKind.Explicit, Size = 128)]
11 | public struct sockaddr_storage
12 | {
13 | [FieldOffset(0)] public sa_family_t ss_family;
14 | [FieldOffset(8)] public long __ss_align;
15 | }
16 | }
--------------------------------------------------------------------------------
/enet-csharp/ENet/plugins/NativeSockets/Unix/Shared/include/PollEvents.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | #pragma warning disable CS1591
4 | #pragma warning disable CS8981
5 |
6 | // ReSharper disable ALL
7 |
8 | namespace NativeSockets
9 | {
10 | [Flags]
11 | internal enum PollEvents : short
12 | {
13 | POLLIN = 0x0001,
14 | POLLPRI = 0x0002,
15 | POLLOUT = 0x0004,
16 | POLLERR = 0x0008,
17 | POLLHUP = 0x0010,
18 | POLLNVAL = 0x0020
19 | }
20 | }
--------------------------------------------------------------------------------
/enet-csharp/ENet/plugins/NativeSockets/Unix/Shared/include/msghdr.cs:
--------------------------------------------------------------------------------
1 | #pragma warning disable CS1591
2 | #pragma warning disable CS8981
3 |
4 | // ReSharper disable ALL
5 |
6 | namespace NativeSockets
7 | {
8 | public unsafe struct msghdr
9 | {
10 | public void* msg_name;
11 | public nuint msg_namelen;
12 | public iovec* msg_iov;
13 | public int msg_iovlen;
14 | public void* msg_control;
15 | public nuint msg_controllen;
16 | public int msg_flags;
17 | }
18 | }
--------------------------------------------------------------------------------
/enet-csharp/ENet/plugins/NativeSockets/Shared/include/in_addr.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.InteropServices;
2 |
3 | #pragma warning disable CS1591
4 | #pragma warning disable CS8981
5 |
6 | // ReSharper disable ALL
7 |
8 | namespace NativeSockets
9 | {
10 | [StructLayout(LayoutKind.Explicit, Size = 4)]
11 | public unsafe struct in_addr
12 | {
13 | [FieldOffset(0)] public fixed byte S_un_b[4];
14 | [FieldOffset(0)] public fixed ushort S_un_w[2];
15 | [FieldOffset(0)] public uint S_addr;
16 | }
17 | }
--------------------------------------------------------------------------------
/Test/Test.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | disable
7 | enable
8 | true
9 | App
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/enet-csharp/ENet/plugins/NativeSockets/Shared/include/sockaddr_in.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.InteropServices;
2 |
3 | #pragma warning disable CS1591
4 | #pragma warning disable CS8981
5 |
6 | // ReSharper disable ALL
7 |
8 | namespace NativeSockets
9 | {
10 | [StructLayout(LayoutKind.Explicit, Size = 16)]
11 | public unsafe struct sockaddr_in
12 | {
13 | [FieldOffset(0)] public sa_family_t sin_family;
14 | [FieldOffset(2)] public ushort sin_port;
15 | [FieldOffset(4)] public in_addr sin_addr;
16 | [FieldOffset(8)] public fixed byte sin_zero[8];
17 | }
18 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | This project is a pure C# translation of [enet](https://github.com/lsalzman/enet), no binaries.
2 |
3 | Where udp implementation: [NativeSockets](https://github.com/Molth/NativeSockets).
4 |
5 | ## Why?
6 |
7 | The original ENet relies on platform-specific native binaries,
8 |
9 | which poses challenges for cross-platform distribution and deployment.
10 |
11 | This project eliminates that dependency while preserving full compatibility with the original implementation.
12 |
13 | [](https://www.nuget.org/packages/ENet-no_binaries/)
--------------------------------------------------------------------------------
/enet-csharp/ENet/plugins/NativeSockets/Shared/include/addrinfo.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.InteropServices;
2 |
3 | #pragma warning disable CS1591
4 | #pragma warning disable CS8981
5 |
6 | // ReSharper disable ALL
7 |
8 | namespace NativeSockets
9 | {
10 | [StructLayout(LayoutKind.Sequential)]
11 | public unsafe struct addrinfo
12 | {
13 | public int ai_flags;
14 | public int ai_family;
15 | public int ai_socktype;
16 | public int ai_protocol;
17 | public nuint ai_addrlen;
18 | public byte* ai_canonname;
19 | public sockaddr* ai_addr;
20 | public addrinfo* ai_next;
21 | }
22 | }
--------------------------------------------------------------------------------
/enet-csharp/ENet/include/callback.cs:
--------------------------------------------------------------------------------
1 | #pragma warning disable CS1591
2 |
3 | // ReSharper disable ALL
4 |
5 | namespace enet
6 | {
7 | public unsafe struct ENetCallbacks
8 | {
9 | public delegate* managed malloc;
10 | public delegate* managed free;
11 | public delegate* managed no_memory;
12 |
13 | public ENetCallbacks(delegate* managed malloc, delegate* managed free, delegate* managed no_memory)
14 | {
15 | this.malloc = malloc;
16 | this.free = free;
17 | this.no_memory = no_memory;
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/enet-csharp/ENet/plugins/NativeSockets/Shared/include/sockaddr_in6.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.InteropServices;
2 |
3 | #pragma warning disable CS1591
4 | #pragma warning disable CS8981
5 |
6 | // ReSharper disable ALL
7 |
8 | namespace NativeSockets
9 | {
10 | [StructLayout(LayoutKind.Explicit, Size = 28)]
11 | public unsafe struct sockaddr_in6
12 | {
13 | [FieldOffset(0)] public sa_family_t sin6_family;
14 | [FieldOffset(2)] public ushort sin6_port;
15 | [FieldOffset(4)] public uint sin6_flowinfo;
16 | [FieldOffset(8)] public fixed byte sin6_addr[16];
17 | [FieldOffset(24)] public uint sin6_scope_id;
18 | }
19 | }
--------------------------------------------------------------------------------
/enet-csharp/ENet/include/time.cs:
--------------------------------------------------------------------------------
1 | #pragma warning disable CS1591
2 |
3 | // ReSharper disable ALL
4 |
5 | namespace enet
6 | {
7 | public static partial class ENet
8 | {
9 | public const uint ENET_TIME_OVERFLOW = 86400000;
10 |
11 | public static bool ENET_TIME_LESS(uint a, uint b) => ((a) - (b) >= ENET_TIME_OVERFLOW);
12 | public static bool ENET_TIME_GREATER(uint a, uint b) => ((b) - (a) >= ENET_TIME_OVERFLOW);
13 | public static bool ENET_TIME_LESS_EQUAL(uint a, uint b) => (!ENET_TIME_GREATER(a, b));
14 | public static bool ENET_TIME_GREATER_EQUAL(uint a, uint b) => (!ENET_TIME_LESS(a, b));
15 |
16 | public static uint ENET_TIME_DIFFERENCE(uint a, uint b) => ((a) - (b) >= ENET_TIME_OVERFLOW ? (b) - (a) : (a) - (b));
17 | }
18 | }
--------------------------------------------------------------------------------
/enet-csharp/ENet/include/list.cs:
--------------------------------------------------------------------------------
1 | #pragma warning disable CS1591
2 |
3 | // ReSharper disable ALL
4 |
5 | namespace enet
6 | {
7 | public unsafe struct ENetListNode
8 | {
9 | public ENetListNode* next;
10 | public ENetListNode* previous;
11 | }
12 |
13 | public struct ENetList
14 | {
15 | public ENetListNode sentinel;
16 | }
17 |
18 | public static unsafe partial class ENet
19 | {
20 | public static ENetListNode* enet_list_begin(ENetList* list) => ((list)->sentinel.next);
21 | public static ENetListNode* enet_list_end(ENetList* list) => (&(list)->sentinel);
22 |
23 | public static bool enet_list_empty(ENetList* list) => (enet_list_begin(list) == enet_list_end(list));
24 |
25 | public static ENetListNode* enet_list_next(ENetListNode* iterator) => ((iterator)->next);
26 | public static ENetListNode* enet_list_previous(ENetListNode* iterator) => ((iterator)->previous);
27 |
28 | public static void* enet_list_front(ENetList* list) => ((void*)(list)->sentinel.next);
29 | public static void* enet_list_back(ENetList* list) => ((void*)(list)->sentinel.previous);
30 | }
31 | }
--------------------------------------------------------------------------------
/enet-csharp/ENet/plugins/Helpers/SpanHelpers.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // ReSharper disable ALL
6 |
7 | namespace NativeSockets
8 | {
9 | internal static class SpanHelpers
10 | {
11 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
12 | public static bool Compare(ref byte left, ref byte right, nuint byteCount)
13 | {
14 | nuint quotient = byteCount >> 30;
15 | nuint remainder = byteCount & 1073741823;
16 | for (nuint i = 0; i < quotient; ++i)
17 | {
18 | if (!MemoryMarshal.CreateReadOnlySpan(ref left, 1073741824).SequenceEqual(MemoryMarshal.CreateReadOnlySpan(ref right, 1073741824)))
19 | return false;
20 | left = ref Unsafe.AddByteOffset(ref left, new IntPtr(1073741824));
21 | right = ref Unsafe.AddByteOffset(ref right, new IntPtr(1073741824));
22 | }
23 |
24 | return MemoryMarshal.CreateReadOnlySpan(ref left, (int)remainder).SequenceEqual(MemoryMarshal.CreateReadOnlySpan(ref right, (int)remainder));
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/enet-csharp/ENet/define/system.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 |
6 | #pragma warning disable CS1591
7 |
8 | // ReSharper disable ALL
9 |
10 | namespace enet
11 | {
12 | public static unsafe partial class ENet
13 | {
14 | public static void* malloc(nuint size)
15 | {
16 | #if NET6_0_OR_GREATER
17 | return NativeMemory.Alloc((nuint)size);
18 | #else
19 | return (void*)Marshal.AllocHGlobal((nint)size);
20 | #endif
21 | }
22 |
23 | public static void free(void* memory)
24 | {
25 | #if NET6_0_OR_GREATER
26 | NativeMemory.Free(memory);
27 | #else
28 | Marshal.FreeHGlobal((nint)memory);
29 | #endif
30 | }
31 |
32 | public static void memcpy(void* dst, void* src, nuint size) => Unsafe.CopyBlockUnaligned(dst, src, (uint)size);
33 |
34 | public static void memset(void* dst, byte val, nuint size) => Unsafe.InitBlockUnaligned(dst, val, (uint)size);
35 |
36 | public static void abort() => Environment.Exit(-1);
37 |
38 | public static long timeGetTime() => Stopwatch.GetTimestamp() * 1000L / Stopwatch.Frequency;
39 | }
40 | }
--------------------------------------------------------------------------------
/enet-csharp/ENet/plugins/NativeSockets/Shared/include/WinSock2.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Buffers.Binary;
3 | using System.Runtime.CompilerServices;
4 |
5 | #pragma warning disable CS1591
6 |
7 | // ReSharper disable ALL
8 |
9 | namespace NativeSockets
10 | {
11 | public static class WinSock2
12 | {
13 | internal static int ADDRESS_FAMILY_INTER_NETWORK_V4_MAPPED_V6 { get; } = (BitConverter.IsLittleEndian ? -65536 : 65535);
14 |
15 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
16 | public static ushort HOST_TO_NET_16(ushort host) => BitConverter.IsLittleEndian ? BinaryPrimitives.ReverseEndianness(host) : host;
17 |
18 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
19 | public static uint HOST_TO_NET_32(uint host) => BitConverter.IsLittleEndian ? BinaryPrimitives.ReverseEndianness(host) : host;
20 |
21 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
22 | public static ushort NET_TO_HOST_16(ushort network) => BitConverter.IsLittleEndian ? BinaryPrimitives.ReverseEndianness(network) : network;
23 |
24 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
25 | public static uint NET_TO_HOST_32(uint network) => BitConverter.IsLittleEndian ? BinaryPrimitives.ReverseEndianness(network) : network;
26 | }
27 | }
--------------------------------------------------------------------------------
/enet-csharp.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "enet-csharp", "enet-csharp\enet-csharp.csproj", "{E4BCA651-24F7-4E44-9725-B786BF53B2CA}"
4 | EndProject
5 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{88FC4909-A666-4EF6-B96A-5432255B27A0}"
6 | EndProject
7 | Global
8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
9 | Debug|Any CPU = Debug|Any CPU
10 | Release|Any CPU = Release|Any CPU
11 | EndGlobalSection
12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
13 | {E4BCA651-24F7-4E44-9725-B786BF53B2CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
14 | {E4BCA651-24F7-4E44-9725-B786BF53B2CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
15 | {E4BCA651-24F7-4E44-9725-B786BF53B2CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
16 | {E4BCA651-24F7-4E44-9725-B786BF53B2CA}.Release|Any CPU.Build.0 = Release|Any CPU
17 | {88FC4909-A666-4EF6-B96A-5432255B27A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
18 | {88FC4909-A666-4EF6-B96A-5432255B27A0}.Debug|Any CPU.Build.0 = Debug|Any CPU
19 | {88FC4909-A666-4EF6-B96A-5432255B27A0}.Release|Any CPU.ActiveCfg = Release|Any CPU
20 | {88FC4909-A666-4EF6-B96A-5432255B27A0}.Release|Any CPU.Build.0 = Release|Any CPU
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/enet-csharp/ENet/include/win32.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Buffers.Binary;
3 |
4 | #pragma warning disable CS1591
5 |
6 | // ReSharper disable ALL
7 |
8 | namespace enet
9 | {
10 | public static partial class ENet
11 | {
12 | public const nint INVALID_SOCKET = ~0;
13 |
14 | public const nint ENET_SOCKET_NULL = INVALID_SOCKET;
15 |
16 | public static ushort ENET_HOST_TO_NET_16(ushort host) => BitConverter.IsLittleEndian ? BinaryPrimitives.ReverseEndianness(host) : host;
17 |
18 | public static uint ENET_HOST_TO_NET_32(uint host) => BitConverter.IsLittleEndian ? BinaryPrimitives.ReverseEndianness(host) : host;
19 |
20 | public static ushort ENET_NET_TO_HOST_16(ushort network) => BitConverter.IsLittleEndian ? BinaryPrimitives.ReverseEndianness(network) : network;
21 |
22 | public static uint ENET_NET_TO_HOST_32(uint network) => BitConverter.IsLittleEndian ? BinaryPrimitives.ReverseEndianness(network) : network;
23 | }
24 |
25 | public unsafe struct ENetBuffer
26 | {
27 | public nuint dataLength;
28 | public void* data;
29 | }
30 |
31 | public struct ENetSocket
32 | {
33 | public nint handle;
34 | public bool IsIPv4 => !IsIPv6;
35 | public bool IsIPv6;
36 |
37 | public static implicit operator bool(ENetSocket socket) => socket.handle > 0;
38 | public static implicit operator nint(ENetSocket socket) => socket.handle;
39 | }
40 | }
--------------------------------------------------------------------------------
/enet-csharp/ENet/c/list.cs:
--------------------------------------------------------------------------------
1 | #pragma warning disable CS1591
2 |
3 | // ReSharper disable ALL
4 |
5 | namespace enet
6 | {
7 | public static unsafe partial class ENet
8 | {
9 | public static void enet_list_clear(ENetList* list)
10 | {
11 | list->sentinel.next = &list->sentinel;
12 | list->sentinel.previous = &list->sentinel;
13 | }
14 |
15 | public static ENetListNode* enet_list_insert(ENetListNode* position, void* data)
16 | {
17 | ENetListNode* result = (ENetListNode*)data;
18 |
19 | result->previous = position->previous;
20 | result->next = position;
21 |
22 | result->previous->next = result;
23 | position->previous = result;
24 |
25 | return result;
26 | }
27 |
28 | public static void* enet_list_remove(ENetListNode* position)
29 | {
30 | position->previous->next = position->next;
31 | position->next->previous = position->previous;
32 |
33 | return position;
34 | }
35 |
36 | public static ENetListNode* enet_list_move(ENetListNode* position, void* dataFirst, void* dataLast)
37 | {
38 | ENetListNode* first = (ENetListNode*)dataFirst,
39 | last = (ENetListNode*)dataLast;
40 |
41 | first->previous->next = last->next;
42 | last->next->previous = first->previous;
43 |
44 | first->previous = position->previous;
45 | last->next = position;
46 |
47 | first->previous->next = first;
48 | position->previous = last;
49 |
50 | return first;
51 | }
52 |
53 | public static nuint enet_list_size(ENetList* list)
54 | {
55 | nuint size = 0;
56 | ENetListNode* position;
57 |
58 | for (position = enet_list_begin(list);
59 | position != enet_list_end(list);
60 | position = enet_list_next(position))
61 | ++size;
62 |
63 | return size;
64 | }
65 | }
66 | }
--------------------------------------------------------------------------------
/enet-csharp/ENet/plugins/NativeSockets/Shared/include/sa_family_t.cs:
--------------------------------------------------------------------------------
1 | using System.Net.Sockets;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | #pragma warning disable CS1591
6 | #pragma warning disable CS8981
7 |
8 | // ReSharper disable ALL
9 |
10 | namespace NativeSockets
11 | {
12 | [StructLayout(LayoutKind.Explicit, Size = 2)]
13 | public struct sa_family_t
14 | {
15 | [FieldOffset(0)] public byte bsd_len;
16 | [FieldOffset(1)] public byte bsd_family;
17 | [FieldOffset(0)] public ushort family;
18 |
19 | public bool IsIPv4
20 | {
21 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
22 | get => SocketPal.IsBSD ? bsd_family == (int)AddressFamily.InterNetwork : family == (int)AddressFamily.InterNetwork;
23 | }
24 |
25 | public bool IsIPv6
26 | {
27 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
28 | get => SocketPal.IsBSD ? bsd_family == BSDSocketPal.ADDRESS_FAMILY_INTER_NETWORK_V6 : family == SocketPal.ADDRESS_FAMILY_INTER_NETWORK_V6;
29 | }
30 |
31 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
32 | public static sa_family_t FromBSD(ushort value)
33 | {
34 | Unsafe.SkipInit(out sa_family_t result);
35 | result.bsd_len = value == BSDSocketPal.ADDRESS_FAMILY_INTER_NETWORK_V6 ? (byte)28 : (byte)16;
36 | result.bsd_family = (byte)value;
37 | return result;
38 | }
39 |
40 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
41 | public static implicit operator sa_family_t(ushort value)
42 | {
43 | Unsafe.SkipInit(out sa_family_t result);
44 | if (SocketPal.IsBSD)
45 | {
46 | result.bsd_len = value == BSDSocketPal.ADDRESS_FAMILY_INTER_NETWORK_V6 ? (byte)28 : (byte)16;
47 | result.bsd_family = (byte)value;
48 | return result;
49 | }
50 |
51 | result.family = value;
52 | return result;
53 | }
54 | }
55 | }
--------------------------------------------------------------------------------
/enet-csharp/enet-csharp.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0;net8.0;net7.0;net6.0;net5.0;netstandard2.1
5 | enet
6 | disable
7 | enable
8 |
9 | true
10 |
11 | ENet-no_binaries
12 | 1.0.8
13 | Molth Nevin
14 | Hell
15 | ENet reliable UDP networking library
16 | https://github.com/Molth/enet-csharp
17 | MIT
18 | enet;udp;performance;networking
19 |
20 | ./nupkgs
21 | README.md
22 | true
23 |
24 | $(MSBuildThisFileDirectory)../
25 |
26 |
27 |
28 | 9.0
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | true
38 | \
39 | README.md
40 |
41 |
42 |
43 | true
44 | \
45 | LICENSE
46 |
47 |
48 |
49 |
50 | true
51 |
52 |
53 |
54 | false
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/enet-csharp/ENet/c/callback.cs:
--------------------------------------------------------------------------------
1 | #pragma warning disable CS1591
2 | #pragma warning disable CA2211
3 |
4 | // ReSharper disable ALL
5 |
6 | namespace enet
7 | {
8 | public static unsafe partial class ENet
9 | {
10 | public static ENetCallbacks callbacks = new ENetCallbacks(&malloc, &free, &abort);
11 |
12 | ///
13 | /// Initializes ENet globally and supplies user-overridden callbacks. Must be called prior to using any functions in
14 | /// ENet.
15 | /// Do not use if you use this variant. Make sure the
16 | /// structure
17 | /// is zeroed out so that any additional callbacks added in future versions will be properly ignored.
18 | ///
19 | ///
20 | /// the constant should be supplied so ENet knows which version of
21 | /// struct to use
22 | ///
23 | /// user-overridden callbacks where any NULL callbacks will use ENet's defaults
24 | /// 0 on success, < 0 on failure
25 | public static int enet_initialize_with_callbacks(uint version, ENetCallbacks* inits)
26 | {
27 | if (version < ENET_VERSION_CREATE(1, 3, 0))
28 | return -1;
29 |
30 | if (inits->malloc != null || inits->free != null)
31 | {
32 | if (inits->malloc == null || inits->free == null)
33 | return -1;
34 |
35 | callbacks.malloc = inits->malloc;
36 | callbacks.free = inits->free;
37 | }
38 |
39 | if (inits->no_memory != null)
40 | callbacks.no_memory = inits->no_memory;
41 |
42 | return enet_initialize();
43 | }
44 |
45 | ///
46 | /// Gives the linked version of the ENet library.
47 | ///
48 | /// the version number
49 | public static uint enet_linked_version() => ENET_VERSION;
50 |
51 | public static void* enet_malloc(nuint size)
52 | {
53 | void* memory = callbacks.malloc(size);
54 |
55 | if (memory == null)
56 | callbacks.no_memory();
57 |
58 | return memory;
59 | }
60 |
61 | public static void enet_free(void* memory) => callbacks.free(memory);
62 | }
63 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Nevin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 | ---
24 |
25 | enet
26 |
27 | MIT License
28 |
29 | Copyright (c) 2002-2024 Lee Salzman
30 |
31 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
32 |
33 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
34 |
35 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 |
37 | ---
38 |
39 | NanoSockets
40 |
41 | MIT License
42 |
43 | Copyright (c) 2019 Stanislav Denisov (nxrighthere@gmail.com)
44 |
45 | Permission is hereby granted, free of charge, to any person obtaining a copy
46 | of this software and associated documentation files (the "Software"), to deal
47 | in the Software without restriction, including without limitation the rights
48 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
49 | copies of the Software, and to permit persons to whom the Software is
50 | furnished to do so, subject to the following conditions:
51 |
52 | The above copyright notice and this permission notice shall be included in all
53 | copies or substantial portions of the Software.
54 |
55 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
56 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
57 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
58 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
59 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
60 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
61 | SOFTWARE.
--------------------------------------------------------------------------------
/enet-csharp/ENet/plugins/Helpers/XxHash.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 | using System.Security.Cryptography;
5 |
6 | #pragma warning disable CS1591
7 |
8 | // ReSharper disable ALL
9 |
10 | namespace NativeSockets
11 | {
12 | internal static class XxHash
13 | {
14 | public static uint XXHASH_32_SEED { get; }
15 |
16 | static XxHash()
17 | {
18 | Span buffer = stackalloc byte[4];
19 | RandomNumberGenerator.Fill(buffer);
20 | XXHASH_32_SEED = Unsafe.ReadUnaligned(ref MemoryMarshal.GetReference(buffer));
21 | }
22 |
23 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
24 | public static int Hash32(in T obj) where T : unmanaged => Hash32(MemoryMarshal.CreateReadOnlySpan(ref Unsafe.As(ref Unsafe.AsRef(in obj)), Unsafe.SizeOf()), XXHASH_32_SEED);
25 |
26 | public static int Hash32(ReadOnlySpan buffer, uint seed)
27 | {
28 | int length = buffer.Length;
29 | ref byte local1 = ref MemoryMarshal.GetReference(buffer);
30 | uint num1;
31 | if (buffer.Length >= 16)
32 | {
33 | uint num2 = seed + 606290984U;
34 | uint num3 = seed + 2246822519U;
35 | uint num4 = seed;
36 | uint num5 = seed - 2654435761U;
37 | for (; length >= 16; length -= 16)
38 | {
39 | ref byte local2 = ref Unsafe.AddByteOffset(ref local1, new IntPtr(buffer.Length - length));
40 | uint num6 = num2 + Unsafe.ReadUnaligned(ref local2) * 2246822519U;
41 | num2 = (uint)((((int)num6 << 13) | (int)(num6 >> 19)) * -1640531535);
42 | uint num7 = num3 + Unsafe.ReadUnaligned(ref Unsafe.AddByteOffset(ref local2, new IntPtr(4))) * 2246822519U;
43 | num3 = (uint)((((int)num7 << 13) | (int)(num7 >> 19)) * -1640531535);
44 | uint num8 = num4 + Unsafe.ReadUnaligned(ref Unsafe.AddByteOffset(ref local2, new IntPtr(8))) * 2246822519U;
45 | num4 = (uint)((((int)num8 << 13) | (int)(num8 >> 19)) * -1640531535);
46 | uint num9 = num5 + Unsafe.ReadUnaligned(ref Unsafe.AddByteOffset(ref local2, new IntPtr(12))) * 2246822519U;
47 | num5 = (uint)((((int)num9 << 13) | (int)(num9 >> 19)) * -1640531535);
48 | }
49 |
50 | num1 = (uint)((((int)num2 << 1) | (int)(num2 >> 31)) + (((int)num3 << 7) | (int)(num3 >> 25)) + (((int)num4 << 12) | (int)(num4 >> 20)) + (((int)num5 << 18) | (int)(num5 >> 14)) + buffer.Length);
51 | }
52 | else
53 | num1 = (uint)((int)seed + 374761393 + buffer.Length);
54 |
55 | for (; length >= 4; length -= 4)
56 | {
57 | uint num10 = Unsafe.ReadUnaligned(ref Unsafe.AddByteOffset(ref local1, new IntPtr(buffer.Length - length)));
58 | uint num11 = num1 + num10 * 3266489917U;
59 | num1 = (uint)((((int)num11 << 17) | (int)(num11 >> 15)) * 668265263);
60 | }
61 |
62 | ref byte local3 = ref Unsafe.AddByteOffset(ref local1, new IntPtr(buffer.Length - length));
63 | for (int index = 0; index < length; ++index)
64 | {
65 | uint num12 = Unsafe.AddByteOffset(ref local3, new IntPtr(index));
66 | uint num13 = num1 + num12 * 374761393U;
67 | num1 = (uint)((((int)num13 << 11) | (int)(num13 >> 21)) * -1640531535);
68 | }
69 |
70 | #if NET7_0_OR_GREATER
71 | int num14 = ((int)num1 ^ (int)(num1 >> 15)) * -2048144777;
72 | int num15 = (num14 ^ (num14 >>> 13)) * -1028477379;
73 | return num15 ^ (num15 >>> 16);
74 | #else
75 | int num14 = ((int)num1 ^ (int)(num1 >> 15)) * -2048144777;
76 | int num15 = (num14 ^ (int)((uint)num14 >> 13)) * -1028477379;
77 | return num15 ^ (int)((uint)num15 >> 16);
78 | #endif
79 | }
80 | }
81 | }
--------------------------------------------------------------------------------
/enet-csharp/ENet/plugins/NativeSockets/Unix/Shared/c/iOSSocketPal.cs:
--------------------------------------------------------------------------------
1 | using System.Net.Sockets;
2 | using System.Runtime.InteropServices;
3 | using System.Security;
4 |
5 | #pragma warning disable CA1401
6 | #pragma warning disable CS1591
7 | #pragma warning disable CS8981
8 | #pragma warning disable SYSLIB1054
9 |
10 | // ReSharper disable ALL
11 |
12 | namespace NativeSockets
13 | {
14 | [SuppressUnmanagedCodeSecurity]
15 | internal static unsafe class iOSSocketPal
16 | {
17 | private const string NATIVE_LIBRARY = "__Internal";
18 |
19 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
20 | public static extern int getpid();
21 |
22 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
23 | public static extern SocketError bind(int __socketHandle_native, sockaddr* __socketAddress_native, int __socketAddressSize_native);
24 |
25 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
26 | public static extern SocketError getsockname(int __socketHandle_native, sockaddr* __socketAddress_native, int* __socketAddressSize_native);
27 |
28 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
29 | public static extern int socket(int af, int type, int protocol);
30 |
31 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
32 | public static extern int fcntl(int fd, int cmd, int arg);
33 |
34 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
35 | public static extern SocketError setsockopt(int __socketHandle_native, SocketOptionLevel __optionLevel_native, SocketOptionName __optionName_native, int* __optionValue_native, int __optionLength_native);
36 |
37 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
38 | public static extern SocketError getsockopt(int s, int level, int optname, byte* optval, int* optlen);
39 |
40 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
41 | public static extern SocketError connect(int s, sockaddr* name, int namelen);
42 |
43 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
44 | public static extern SocketError close(int __socketHandle_native);
45 |
46 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.StdCall)]
47 | public static extern int send(int __socketHandle_native, byte* __pinnedBuffer_native, int __len_native, SocketFlags __socketFlags_native);
48 |
49 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.StdCall)]
50 | public static extern int recv(int __socketHandle_native, byte* __pinnedBuffer_native, int __len_native, SocketFlags __socketFlags_native);
51 |
52 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
53 | public static extern int sendto(int __socketHandle_native, byte* __pinnedBuffer_native, int __len_native, SocketFlags __socketFlags_native, byte* __socketAddress_native, int __socketAddressSize_native);
54 |
55 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
56 | public static extern int recvfrom(int __socketHandle_native, byte* __pinnedBuffer_native, int __len_native, SocketFlags __socketFlags_native, byte* __socketAddress_native, int* __socketAddressSize_native);
57 |
58 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
59 | public static extern int poll(pollfd* fds, nuint nfds, int timeout);
60 |
61 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
62 | public static extern int inet_pton(int Family, void* pszAddrString, void* pAddrBuf);
63 |
64 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
65 | public static extern int getaddrinfo(byte* pNodeName, byte* pServiceName, addrinfo* pHints, addrinfo** ppResult);
66 |
67 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
68 | public static extern void freeaddrinfo(addrinfo* pAddrInfo);
69 |
70 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
71 | public static extern byte* inet_ntop(int Family, void* pAddr, ref byte pStringBuf, nuint StringBufSize);
72 |
73 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
74 | public static extern int getnameinfo(sockaddr* pSockaddr, int SockaddrLength, ref byte pNodeBuffer, ulong NodeBufferSize, byte* pServiceBuffer, ulong ServiceBufferSize, int Flags);
75 |
76 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
77 | public static extern nint sendmsg(int sockfd, msghdr* msg, int flags);
78 |
79 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
80 | public static extern nint recvmsg(int sockfd, msghdr* msg, int flags);
81 | }
82 | }
--------------------------------------------------------------------------------
/enet-csharp/ENet/include/protocol.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.InteropServices;
2 |
3 | #pragma warning disable CS1591
4 |
5 | // ReSharper disable ALL
6 |
7 | namespace enet
8 | {
9 | public static partial class ENet
10 | {
11 | public const uint ENET_PROTOCOL_MINIMUM_MTU = 576;
12 | public const uint ENET_PROTOCOL_MAXIMUM_MTU = 4096;
13 | public const uint ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS = 32;
14 | public const uint ENET_PROTOCOL_MINIMUM_WINDOW_SIZE = 4096;
15 | public const uint ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE = 65536;
16 | public const uint ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT = 1;
17 | public const uint ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT = 255;
18 | public const uint ENET_PROTOCOL_MAXIMUM_PEER_ID = 0xFFF;
19 | public const uint ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT = 1024 * 1024;
20 | }
21 |
22 | public enum ENetProtocolCommand
23 | {
24 | ENET_PROTOCOL_COMMAND_NONE = 0,
25 | ENET_PROTOCOL_COMMAND_ACKNOWLEDGE = 1,
26 | ENET_PROTOCOL_COMMAND_CONNECT = 2,
27 | ENET_PROTOCOL_COMMAND_VERIFY_CONNECT = 3,
28 | ENET_PROTOCOL_COMMAND_DISCONNECT = 4,
29 | ENET_PROTOCOL_COMMAND_PING = 5,
30 | ENET_PROTOCOL_COMMAND_SEND_RELIABLE = 6,
31 | ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE = 7,
32 | ENET_PROTOCOL_COMMAND_SEND_FRAGMENT = 8,
33 | ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED = 9,
34 | ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT = 10,
35 | ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE = 11,
36 | ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT = 12,
37 | ENET_PROTOCOL_COMMAND_COUNT = 13,
38 |
39 | ENET_PROTOCOL_COMMAND_MASK = 0x0F
40 | }
41 |
42 | public enum ENetProtocolFlag
43 | {
44 | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE = (1 << 7),
45 | ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED = (1 << 6),
46 |
47 | ENET_PROTOCOL_HEADER_FLAG_COMPRESSED = (1 << 14),
48 | ENET_PROTOCOL_HEADER_FLAG_SENT_TIME = (1 << 15),
49 | ENET_PROTOCOL_HEADER_FLAG_MASK = ENET_PROTOCOL_HEADER_FLAG_COMPRESSED | ENET_PROTOCOL_HEADER_FLAG_SENT_TIME,
50 |
51 | ENET_PROTOCOL_HEADER_SESSION_MASK = (3 << 12),
52 | ENET_PROTOCOL_HEADER_SESSION_SHIFT = 12
53 | }
54 |
55 | public struct ENetProtocolHeader
56 | {
57 | public ushort peerID;
58 | public ushort sentTime;
59 | }
60 |
61 | public struct ENetProtocolCommandHeader
62 | {
63 | public byte command;
64 | public byte channelID;
65 | public ushort reliableSequenceNumber;
66 | }
67 |
68 | public struct ENetProtocolAcknowledge
69 | {
70 | public ENetProtocolCommandHeader header;
71 | public ushort receivedReliableSequenceNumber;
72 | public ushort receivedSentTime;
73 | }
74 |
75 | public struct ENetProtocolConnect
76 | {
77 | public ENetProtocolCommandHeader header;
78 | public ushort outgoingPeerID;
79 | public byte incomingSessionID;
80 | public byte outgoingSessionID;
81 | public uint mtu;
82 | public uint windowSize;
83 | public uint channelCount;
84 | public uint incomingBandwidth;
85 | public uint outgoingBandwidth;
86 | public uint packetThrottleInterval;
87 | public uint packetThrottleAcceleration;
88 | public uint packetThrottleDeceleration;
89 | public uint connectID;
90 | public uint data;
91 | }
92 |
93 | public struct ENetProtocolVerifyConnect
94 | {
95 | public ENetProtocolCommandHeader header;
96 | public ushort outgoingPeerID;
97 | public byte incomingSessionID;
98 | public byte outgoingSessionID;
99 | public uint mtu;
100 | public uint windowSize;
101 | public uint channelCount;
102 | public uint incomingBandwidth;
103 | public uint outgoingBandwidth;
104 | public uint packetThrottleInterval;
105 | public uint packetThrottleAcceleration;
106 | public uint packetThrottleDeceleration;
107 | public uint connectID;
108 | }
109 |
110 | public struct ENetProtocolBandwidthLimit
111 | {
112 | public ENetProtocolCommandHeader header;
113 | public uint incomingBandwidth;
114 | public uint outgoingBandwidth;
115 | }
116 |
117 | public struct ENetProtocolThrottleConfigure
118 | {
119 | public ENetProtocolCommandHeader header;
120 | public uint packetThrottleInterval;
121 | public uint packetThrottleAcceleration;
122 | public uint packetThrottleDeceleration;
123 | }
124 |
125 | public struct ENetProtocolDisconnect
126 | {
127 | public ENetProtocolCommandHeader header;
128 | public uint data;
129 | }
130 |
131 | public struct ENetProtocolPing
132 | {
133 | public ENetProtocolCommandHeader header;
134 | }
135 |
136 | public struct ENetProtocolSendReliable
137 | {
138 | public ENetProtocolCommandHeader header;
139 | public ushort dataLength;
140 | }
141 |
142 | public struct ENetProtocolSendUnreliable
143 | {
144 | public ENetProtocolCommandHeader header;
145 | public ushort unreliableSequenceNumber;
146 | public ushort dataLength;
147 | }
148 |
149 | public struct ENetProtocolSendUnsequenced
150 | {
151 | public ENetProtocolCommandHeader header;
152 | public ushort unsequencedGroup;
153 | public ushort dataLength;
154 | }
155 |
156 | public struct ENetProtocolSendFragment
157 | {
158 | public ENetProtocolCommandHeader header;
159 | public ushort startSequenceNumber;
160 | public ushort dataLength;
161 | public uint fragmentCount;
162 | public uint fragmentNumber;
163 | public uint totalLength;
164 | public uint fragmentOffset;
165 | }
166 |
167 | [StructLayout(LayoutKind.Explicit)]
168 | public struct ENetProtocol
169 | {
170 | [FieldOffset(0)] public ENetProtocolCommandHeader header;
171 | [FieldOffset(0)] public ENetProtocolAcknowledge acknowledge;
172 | [FieldOffset(0)] public ENetProtocolConnect connect;
173 | [FieldOffset(0)] public ENetProtocolVerifyConnect verifyConnect;
174 | [FieldOffset(0)] public ENetProtocolDisconnect disconnect;
175 | [FieldOffset(0)] public ENetProtocolPing ping;
176 | [FieldOffset(0)] public ENetProtocolSendReliable sendReliable;
177 | [FieldOffset(0)] public ENetProtocolSendUnreliable sendUnreliable;
178 | [FieldOffset(0)] public ENetProtocolSendUnsequenced sendUnsequenced;
179 | [FieldOffset(0)] public ENetProtocolSendFragment sendFragment;
180 | [FieldOffset(0)] public ENetProtocolBandwidthLimit bandwidthLimit;
181 | [FieldOffset(0)] public ENetProtocolThrottleConfigure throttleConfigure;
182 | }
183 | }
--------------------------------------------------------------------------------
/enet-csharp/ENet/c/packet.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 | using static enet.ENetPacketFlag;
5 |
6 | #pragma warning disable CS1591
7 |
8 | // ReSharper disable ALL
9 |
10 | namespace enet
11 | {
12 | public static unsafe partial class ENet
13 | {
14 | ///
15 | /// Creates a packet that may be sent to a peer.
16 | ///
17 | /// initial contents of the packet's data; the packet's data will remain uninitialized if data is NULL.
18 | /// size of the data allocated for this packet
19 | /// flags for this packet as described for the ENetPacket structure.
20 | /// the packet on success, NULL on failure
21 | public static ENetPacket* enet_packet_create(void* data, nuint dataLength, uint flags)
22 | {
23 | ENetPacket* packet = (ENetPacket*)enet_malloc((nuint)sizeof(ENetPacket));
24 | if (packet == null)
25 | return null;
26 |
27 | if ((flags & (uint)ENET_PACKET_FLAG_NO_ALLOCATE) != 0)
28 | packet->data = (byte*)data;
29 | else if (dataLength <= 0)
30 | packet->data = null;
31 | else
32 | {
33 | packet->data = (byte*)enet_malloc(dataLength);
34 | if (packet->data == null)
35 | {
36 | enet_free(packet);
37 | return null;
38 | }
39 |
40 | if (data != null)
41 | memcpy(packet->data, data, dataLength);
42 | }
43 |
44 | packet->referenceCount = 0;
45 | packet->flags = flags;
46 | packet->dataLength = dataLength;
47 | packet->freeCallback = null;
48 | packet->userData = null;
49 |
50 | return packet;
51 | }
52 |
53 | ///
54 | /// Destroys the packet and deallocates its data.
55 | ///
56 | /// packet to be destroyed
57 | public static void enet_packet_destroy(ENetPacket* packet)
58 | {
59 | if (packet == null)
60 | return;
61 |
62 | if (packet->freeCallback != null)
63 | (packet->freeCallback)(packet);
64 | if (!((packet->flags & (uint)ENET_PACKET_FLAG_NO_ALLOCATE) != 0) &&
65 | packet->data != null)
66 | enet_free(packet->data);
67 | enet_free(packet);
68 | }
69 |
70 | ///
71 | /// Attempts to resize the data in the packet to length specified in the
72 | /// dataLength parameter.
73 | ///
74 | /// packet to resize
75 | /// new size for the packet data
76 | /// 0 on success, < 0 on failure
77 | public static int enet_packet_resize(ENetPacket* packet, nuint dataLength)
78 | {
79 | byte* newData;
80 |
81 | if (dataLength <= packet->dataLength || ((packet->flags & (uint)ENET_PACKET_FLAG_NO_ALLOCATE) != 0))
82 | {
83 | packet->dataLength = dataLength;
84 |
85 | return 0;
86 | }
87 |
88 | newData = (byte*)enet_malloc(dataLength);
89 | if (newData == null)
90 | return -1;
91 |
92 | if (packet->data != null)
93 | {
94 | if (packet->dataLength > 0)
95 | memcpy(newData, packet->data, packet->dataLength);
96 |
97 | enet_free(packet->data);
98 | }
99 |
100 | packet->data = newData;
101 | packet->dataLength = dataLength;
102 |
103 | return 0;
104 | }
105 |
106 | public static ReadOnlySpan crcTable => new uint[256]
107 | {
108 | 0, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
109 | 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
110 | 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
111 | 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
112 | 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
113 | 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
114 | 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
115 | 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
116 | 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
117 | 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
118 | 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
119 | 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
120 | 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
121 | 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
122 | 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
123 | 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
124 | 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
125 | 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
126 | 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
127 | 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
128 | 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
129 | 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
130 | 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
131 | 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
132 | 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x5005713,
133 | 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0xBDBDF21,
134 | 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
135 | 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
136 | 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
137 | 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
138 | 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
139 | 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
140 | };
141 |
142 | public static uint enet_crc32(ENetBuffer* buffers, nuint bufferCount)
143 | {
144 | uint crc = 0xFFFFFFFF;
145 |
146 | while (bufferCount-- > 0)
147 | {
148 | byte* data = (byte*)buffers->data;
149 | byte* dataEnd = &data[buffers->dataLength];
150 |
151 | while (data < dataEnd)
152 | {
153 | crc = (crc >> 8) ^ Unsafe.Add(ref MemoryMarshal.GetReference(crcTable), (int)((crc & 0xFF) ^ *data++));
154 | }
155 |
156 | ++buffers;
157 | }
158 |
159 | return ENET_HOST_TO_NET_32(~ crc);
160 | }
161 | }
162 | }
--------------------------------------------------------------------------------
/enet-csharp/ENet/plugins/NativeSockets/Unix/Shared/c/UnixSocketPal.cs:
--------------------------------------------------------------------------------
1 | #if !NET6_0_OR_GREATER
2 | using System.Collections.Generic;
3 | #endif
4 | using System.Net.Sockets;
5 | using System.Runtime.CompilerServices;
6 | using System.Runtime.InteropServices;
7 | using System.Security;
8 |
9 | #pragma warning disable CA1401
10 | #pragma warning disable CS1591
11 | #pragma warning disable CS8981
12 | #pragma warning disable SYSLIB1054
13 |
14 | // ReSharper disable ALL
15 |
16 | namespace NativeSockets
17 | {
18 | [SuppressUnmanagedCodeSecurity]
19 | internal static unsafe class UnixSocketPal
20 | {
21 | private const string NATIVE_LIBRARY = "libc";
22 |
23 | #if !NET6_0_OR_GREATER
24 | private static readonly Dictionary SocketErrors = new Dictionary
25 | {
26 | { 0, SocketError.Success },
27 | { 1, SocketError.AccessDenied },
28 | { 2, SocketError.AddressNotAvailable },
29 | { 4, SocketError.Interrupted },
30 | { 6, SocketError.HostNotFound },
31 | { 7, SocketError.MessageSize },
32 | { 9, SocketError.OperationAborted },
33 | { 11, SocketError.WouldBlock },
34 | { 12, SocketError.NoBufferSpaceAvailable },
35 | { 13, SocketError.AccessDenied },
36 | { 14, SocketError.Fault },
37 | { 20, SocketError.InvalidArgument },
38 | { 22, SocketError.InvalidArgument },
39 | { 23, SocketError.TooManyOpenSockets },
40 | { 24, SocketError.TooManyOpenSockets },
41 | { 28, SocketError.NoBufferSpaceAvailable },
42 | { 32, SocketError.Shutdown },
43 | { 36, SocketError.InvalidArgument },
44 | { 40, SocketError.AccessDenied },
45 | { 59, SocketError.TooManyOpenSockets },
46 | { 61, SocketError.NoData },
47 | { 63, SocketError.NoBufferSpaceAvailable },
48 | { 67, SocketError.NetworkUnreachable },
49 | { 70, SocketError.ConnectionReset },
50 | { 72, SocketError.NetworkUnreachable },
51 | { 74, SocketError.InvalidArgument },
52 | { 75, SocketError.MessageSize },
53 | { 84, SocketError.InvalidArgument },
54 | { 88, SocketError.NotSocket },
55 | { 89, SocketError.DestinationAddressRequired },
56 | { 90, SocketError.MessageSize },
57 | { 91, SocketError.ProtocolType },
58 | { 92, SocketError.ProtocolOption },
59 | { 93, SocketError.ProtocolNotSupported },
60 | { 94, SocketError.SocketNotSupported },
61 | { 96, SocketError.ProtocolFamilyNotSupported },
62 | { 97, SocketError.AddressFamilyNotSupported },
63 | { 98, SocketError.AddressAlreadyInUse },
64 | { 99, SocketError.AddressNotAvailable },
65 | { 100, SocketError.NetworkDown },
66 | { 101, SocketError.NetworkUnreachable },
67 | { 102, SocketError.NetworkReset },
68 | { 103, SocketError.ConnectionAborted },
69 | { 104, SocketError.ConnectionReset },
70 | { 105, SocketError.NoBufferSpaceAvailable },
71 | { 106, SocketError.IsConnected },
72 | { 107, SocketError.NotConnected },
73 | { 108, SocketError.Disconnecting },
74 | { 110, SocketError.TimedOut },
75 | { 111, SocketError.ConnectionRefused },
76 | { 112, SocketError.HostDown },
77 | { 113, SocketError.HostUnreachable },
78 | { 114, SocketError.AlreadyInProgress },
79 | { 115, SocketError.InProgress }
80 | };
81 | #endif
82 |
83 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
84 | public static SocketError GetLastSocketError()
85 | {
86 | #if NET6_0_OR_GREATER
87 | return (SocketError)Marshal.GetLastPInvokeError();
88 | #else
89 | int errno = Marshal.GetLastWin32Error();
90 | return SocketErrors.TryGetValue(errno, out SocketError error) ? (SocketError)error : (SocketError)errno;
91 | #endif
92 | }
93 |
94 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
95 | public static extern SocketError bind(int __socketHandle_native, sockaddr* __socketAddress_native, int __socketAddressSize_native);
96 |
97 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
98 | public static extern SocketError getsockname(int __socketHandle_native, sockaddr* __socketAddress_native, int* __socketAddressSize_native);
99 |
100 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
101 | public static extern int socket(int af, int type, int protocol);
102 |
103 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
104 | public static extern int fcntl(int fd, int cmd, int arg);
105 |
106 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
107 | public static extern SocketError setsockopt(int __socketHandle_native, SocketOptionLevel __optionLevel_native, SocketOptionName __optionName_native, int* __optionValue_native, int __optionLength_native);
108 |
109 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
110 | public static extern SocketError getsockopt(int s, int level, int optname, byte* optval, int* optlen);
111 |
112 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
113 | public static extern SocketError connect(int s, sockaddr* name, int namelen);
114 |
115 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
116 | public static extern SocketError close(int __socketHandle_native);
117 |
118 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.StdCall)]
119 | public static extern int send(int __socketHandle_native, byte* __pinnedBuffer_native, int __len_native, SocketFlags __socketFlags_native);
120 |
121 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.StdCall)]
122 | public static extern int recv(int __socketHandle_native, byte* __pinnedBuffer_native, int __len_native, SocketFlags __socketFlags_native);
123 |
124 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
125 | public static extern int sendto(int __socketHandle_native, byte* __pinnedBuffer_native, int __len_native, SocketFlags __socketFlags_native, byte* __socketAddress_native, int __socketAddressSize_native);
126 |
127 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
128 | public static extern int recvfrom(int __socketHandle_native, byte* __pinnedBuffer_native, int __len_native, SocketFlags __socketFlags_native, byte* __socketAddress_native, int* __socketAddressSize_native);
129 |
130 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
131 | public static extern int poll(pollfd* fds, nuint nfds, int timeout);
132 |
133 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
134 | public static extern int inet_pton(int Family, void* pszAddrString, void* pAddrBuf);
135 |
136 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
137 | public static extern int getaddrinfo(byte* pNodeName, byte* pServiceName, addrinfo* pHints, addrinfo** ppResult);
138 |
139 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
140 | public static extern void freeaddrinfo(addrinfo* pAddrInfo);
141 |
142 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
143 | public static extern byte* inet_ntop(int Family, void* pAddr, ref byte pStringBuf, nuint StringBufSize);
144 |
145 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
146 | public static extern int getnameinfo(sockaddr* pSockaddr, int SockaddrLength, ref byte pNodeBuffer, ulong NodeBufferSize, byte* pServiceBuffer, ulong ServiceBufferSize, int Flags);
147 |
148 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
149 | public static extern nint sendmsg(int sockfd, msghdr* msg, int flags);
150 |
151 | [DllImport(NATIVE_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
152 | public static extern nint recvmsg(int sockfd, msghdr* msg, int flags);
153 | }
154 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Ww][Ii][Nn]32/
27 | [Aa][Rr][Mm]/
28 | [Aa][Rr][Mm]64/
29 | bld/
30 | [Bb]in/
31 | [Oo]bj/
32 | [Ll]og/
33 | [Ll]ogs/
34 |
35 | # Visual Studio 2015/2017 cache/options directory
36 | .vs/
37 | # Uncomment if you have tasks that create the project's static files in wwwroot
38 | #wwwroot/
39 |
40 | # JetBrains Rider
41 | .idea/
42 | enet-csharp.sln.DotSettings
43 | enet-csharp.sln.DotSettings.user
44 |
45 | # Visual Studio 2017 auto generated files
46 | Generated\ Files/
47 |
48 | # MSTest test Results
49 | [Tt]est[Rr]esult*/
50 | [Bb]uild[Ll]og.*
51 |
52 | # NUnit
53 | *.VisualState.xml
54 | TestResult.xml
55 | nunit-*.xml
56 |
57 | # Build Results of an ATL Project
58 | [Dd]ebugPS/
59 | [Rr]eleasePS/
60 | dlldata.c
61 |
62 | # Benchmark Results
63 | BenchmarkDotNet.Artifacts/
64 |
65 | # .NET Core
66 | project.lock.json
67 | project.fragment.lock.json
68 | artifacts/
69 |
70 | # ASP.NET Scaffolding
71 | ScaffoldingReadMe.txt
72 |
73 | # StyleCop
74 | StyleCopReport.xml
75 |
76 | # Files built by Visual Studio
77 | *_i.c
78 | *_p.c
79 | *_h.h
80 | *.ilk
81 | *.meta
82 | *.obj
83 | *.iobj
84 | *.pch
85 | *.pdb
86 | *.ipdb
87 | *.pgc
88 | *.pgd
89 | *.rsp
90 | *.sbr
91 | *.tlb
92 | *.tli
93 | *.tlh
94 | *.tmp
95 | *.tmp_proj
96 | *_wpftmp.csproj
97 | *.log
98 | *.tlog
99 | *.vspscc
100 | *.vssscc
101 | .builds
102 | *.pidb
103 | *.svclog
104 | *.scc
105 |
106 | # Chutzpah Test files
107 | _Chutzpah*
108 |
109 | # Visual C++ cache files
110 | ipch/
111 | *.aps
112 | *.ncb
113 | *.opendb
114 | *.opensdf
115 | *.sdf
116 | *.cachefile
117 | *.VC.db
118 | *.VC.VC.opendb
119 |
120 | # Visual Studio profiler
121 | *.psess
122 | *.vsp
123 | *.vspx
124 | *.sap
125 |
126 | # Visual Studio Trace Files
127 | *.e2e
128 |
129 | # TFS 2012 Local Workspace
130 | $tf/
131 |
132 | # Guidance Automation Toolkit
133 | *.gpState
134 |
135 | # ReSharper is a .NET coding add-in
136 | _ReSharper*/
137 | *.[Rr]e[Ss]harper
138 | *.DotSettings.user
139 |
140 | # TeamCity is a build add-in
141 | _TeamCity*
142 |
143 | # DotCover is a Code Coverage Tool
144 | *.dotCover
145 |
146 | # AxoCover is a Code Coverage Tool
147 | .axoCover/*
148 | !.axoCover/settings.json
149 |
150 | # Coverlet is a free, cross platform Code Coverage Tool
151 | coverage*.json
152 | coverage*.xml
153 | coverage*.info
154 |
155 | # Visual Studio code coverage results
156 | *.coverage
157 | *.coveragexml
158 |
159 | # NCrunch
160 | _NCrunch_*
161 | .*crunch*.local.xml
162 | nCrunchTemp_*
163 |
164 | # MightyMoose
165 | *.mm.*
166 | AutoTest.Net/
167 |
168 | # Web workbench (sass)
169 | .sass-cache/
170 |
171 | # Installshield output folder
172 | [Ee]xpress/
173 |
174 | # DocProject is a documentation generator add-in
175 | DocProject/buildhelp/
176 | DocProject/Help/*.HxT
177 | DocProject/Help/*.HxC
178 | DocProject/Help/*.hhc
179 | DocProject/Help/*.hhk
180 | DocProject/Help/*.hhp
181 | DocProject/Help/Html2
182 | DocProject/Help/html
183 |
184 | # Click-Once directory
185 | publish/
186 |
187 | # Publish Web Output
188 | *.[Pp]ublish.xml
189 | *.azurePubxml
190 | # Note: Comment the next line if you want to checkin your web deploy settings,
191 | # but database connection strings (with potential passwords) will be unencrypted
192 | *.pubxml
193 | *.publishproj
194 |
195 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
196 | # checkin your Azure Web App publish settings, but sensitive information contained
197 | # in these scripts will be unencrypted
198 | PublishScripts/
199 |
200 | # NuGet Packages
201 | *.nupkg
202 | # NuGet Symbol Packages
203 | *.snupkg
204 | # The packages folder can be ignored because of Package Restore
205 | **/[Pp]ackages/*
206 | # except build/, which is used as an MSBuild target.
207 | !**/[Pp]ackages/build/
208 | # Uncomment if necessary however generally it will be regenerated when needed
209 | #!**/[Pp]ackages/repositories.config
210 | # NuGet v3's project.json files produces more ignorable files
211 | *.nuget.props
212 | *.nuget.targets
213 |
214 | # Microsoft Azure Build Output
215 | csx/
216 | *.build.csdef
217 |
218 | # Microsoft Azure Emulator
219 | ecf/
220 | rcf/
221 |
222 | # Windows Store app package directories and files
223 | AppPackages/
224 | BundleArtifacts/
225 | Package.StoreAssociation.xml
226 | _pkginfo.txt
227 | *.appx
228 | *.appxbundle
229 | *.appxupload
230 |
231 | # Visual Studio cache files
232 | # files ending in .cache can be ignored
233 | *.[Cc]ache
234 | # but keep track of directories ending in .cache
235 | !?*.[Cc]ache/
236 |
237 | # Others
238 | ClientBin/
239 | ~$*
240 | *~
241 | *.dbmdl
242 | *.dbproj.schemaview
243 | *.jfm
244 | *.pfx
245 | *.publishsettings
246 | orleans.codegen.cs
247 |
248 | # Including strong name files can present a security risk
249 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
250 | #*.snk
251 |
252 | # Since there are multiple workflows, uncomment next line to ignore bower_components
253 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
254 | #bower_components/
255 |
256 | # RIA/Silverlight projects
257 | Generated_Code/
258 |
259 | # Backup & report files from converting an old project file
260 | # to a newer Visual Studio version. Backup files are not needed,
261 | # because we have git ;-)
262 | _UpgradeReport_Files/
263 | Backup*/
264 | UpgradeLog*.XML
265 | UpgradeLog*.htm
266 | ServiceFabricBackup/
267 | *.rptproj.bak
268 |
269 | # SQL Server files
270 | *.mdf
271 | *.ldf
272 | *.ndf
273 |
274 | # Business Intelligence projects
275 | *.rdl.data
276 | *.bim.layout
277 | *.bim_*.settings
278 | *.rptproj.rsuser
279 | *- [Bb]ackup.rdl
280 | *- [Bb]ackup ([0-9]).rdl
281 | *- [Bb]ackup ([0-9][0-9]).rdl
282 |
283 | # Microsoft Fakes
284 | FakesAssemblies/
285 |
286 | # GhostDoc plugin setting file
287 | *.GhostDoc.xml
288 |
289 | # Node.js Tools for Visual Studio
290 | .ntvs_analysis.dat
291 | node_modules/
292 |
293 | # Visual Studio 6 build log
294 | *.plg
295 |
296 | # Visual Studio 6 workspace options file
297 | *.opt
298 |
299 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
300 | *.vbw
301 |
302 | # Visual Studio 6 auto-generated project file (contains which files were open etc.)
303 | *.vbp
304 |
305 | # Visual Studio 6 workspace and project file (working project files containing files to include in project)
306 | *.dsw
307 | *.dsp
308 |
309 | # Visual Studio 6 technical files
310 | *.ncb
311 | *.aps
312 |
313 | # Visual Studio LightSwitch build output
314 | **/*.HTMLClient/GeneratedArtifacts
315 | **/*.DesktopClient/GeneratedArtifacts
316 | **/*.DesktopClient/ModelManifest.xml
317 | **/*.Server/GeneratedArtifacts
318 | **/*.Server/ModelManifest.xml
319 | _Pvt_Extensions
320 |
321 | # Paket dependency manager
322 | .paket/paket.exe
323 | paket-files/
324 |
325 | # FAKE - F# Make
326 | .fake/
327 |
328 | # CodeRush personal settings
329 | .cr/personal
330 |
331 | # Python Tools for Visual Studio (PTVS)
332 | __pycache__/
333 | *.pyc
334 |
335 | # Cake - Uncomment if you are using it
336 | # tools/**
337 | # !tools/packages.config
338 |
339 | # Tabs Studio
340 | *.tss
341 |
342 | # Telerik's JustMock configuration file
343 | *.jmconfig
344 |
345 | # BizTalk build output
346 | *.btp.cs
347 | *.btm.cs
348 | *.odx.cs
349 | *.xsd.cs
350 |
351 | # OpenCover UI analysis results
352 | OpenCover/
353 |
354 | # Azure Stream Analytics local run output
355 | ASALocalRun/
356 |
357 | # MSBuild Binary and Structured Log
358 | *.binlog
359 |
360 | # NVidia Nsight GPU debugger configuration file
361 | *.nvuser
362 |
363 | # MFractors (Xamarin productivity tool) working folder
364 | .mfractor/
365 |
366 | # Local History for Visual Studio
367 | .localhistory/
368 |
369 | # Visual Studio History (VSHistory) files
370 | .vshistory/
371 |
372 | # BeatPulse healthcheck temp database
373 | healthchecksdb
374 |
375 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
376 | MigrationBackup/
377 |
378 | # Ionide (cross platform F# VS Code tools) working folder
379 | .ionide/
380 |
381 | # Fody - auto-generated XML schema
382 | FodyWeavers.xsd
383 |
384 | # VS Code files for those working on multiple tools
385 | .vscode/*
386 | !.vscode/settings.json
387 | !.vscode/tasks.json
388 | !.vscode/launch.json
389 | !.vscode/extensions.json
390 | *.code-workspace
391 |
392 | # Local History for Visual Studio Code
393 | .history/
394 |
395 | # Windows Installer files from build outputs
396 | *.cab
397 | *.msi
398 | *.msix
399 | *.msm
400 | *.msp
401 |
402 | # JetBrains Rider
403 | *.sln.iml
404 |
--------------------------------------------------------------------------------
/Test/TestWave.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Security.Cryptography;
3 | using System.Threading;
4 | using static enet.ENet;
5 |
6 | #pragma warning disable CA1806
7 |
8 | // ReSharper disable ALL
9 |
10 | namespace enet
11 | {
12 | public sealed unsafe class TestWave
13 | {
14 | private static bool _running;
15 |
16 | public const int INTERVAL = 1;
17 |
18 | public static void Start()
19 | {
20 | Console.CancelKeyPress += (sender, args) => _running = false;
21 | _running = true;
22 | new Thread(StartServer).Start();
23 | Thread.Sleep(1000);
24 | new Thread(StartClient).Start();
25 | while (true)
26 | Thread.Sleep(1000);
27 | }
28 |
29 | private static void StartServer()
30 | {
31 | enet_initialize();
32 | ENetHost* host = null;
33 | try
34 | {
35 | ENetAddress address = new ENetAddress();
36 | enet_address_set_host_ip(&address, "0.0.0.0");
37 | address.port = 7777;
38 |
39 | byte* hostName = stackalloc byte[1024];
40 | int error = enet_address_get_host(&address, hostName, 1024);
41 |
42 | if (error == 0)
43 | Console.WriteLine(new string((sbyte*)hostName));
44 |
45 | host = enet_host_create(&address, 4095, 0, 0, 0, ENetHostOption.ENET_HOSTOPT_IPV4);
46 |
47 | ENetPeer* peer = null;
48 |
49 | ENetEvent netEvent = new ENetEvent();
50 |
51 | byte* buffer = stackalloc byte[1024];
52 |
53 | while (_running)
54 | {
55 | bool polled = false;
56 | while (!polled)
57 | {
58 | if (enet_host_check_events(host, &netEvent) <= 0)
59 | {
60 | if (enet_host_service(host, &netEvent, 1) <= 0)
61 | break;
62 | polled = true;
63 | }
64 |
65 | switch (netEvent.type)
66 | {
67 | case ENetEventType.ENET_EVENT_TYPE_NONE:
68 | break;
69 | case ENetEventType.ENET_EVENT_TYPE_CONNECT:
70 | peer = netEvent.peer;
71 | Console.WriteLine($"server Connected {peer->address.ToString()}");
72 | break;
73 | case ENetEventType.ENET_EVENT_TYPE_DISCONNECT:
74 | peer = null;
75 | Console.WriteLine("server Disconnected");
76 | break;
77 | case ENetEventType.ENET_EVENT_TYPE_RECEIVE:
78 | enet_peer_send(peer, 0, netEvent.packet);
79 | break;
80 | }
81 | }
82 |
83 | enet_host_flush(host);
84 | Thread.Sleep(INTERVAL);
85 | }
86 | }
87 | finally
88 | {
89 | if (host != null)
90 | enet_host_destroy(host);
91 | enet_deinitialize();
92 | }
93 | }
94 |
95 | private static void StartClient()
96 | {
97 | enet_initialize();
98 | ENetHost* host = null;
99 | try
100 | {
101 | ENetAddress address = new ENetAddress();
102 | enet_address_set_host_ip(&address, "127.0.0.1");
103 | address.port = 7777;
104 |
105 | ENetAddress local = new ENetAddress();
106 | enet_address_set_host_ip(&local, "0.0.0.0");
107 | local.port = 7778;
108 |
109 | host = enet_host_create(&local, 1, 0, 0, 0, ENetHostOption.ENET_HOSTOPT_IPV4);
110 |
111 | ENetPeer* peer = enet_host_connect(host, &address, 0, 0);
112 |
113 | ENetEvent netEvent = new ENetEvent();
114 |
115 | bool connected = false;
116 | byte* buffer = stackalloc byte[2048];
117 | bool sent = false;
118 | bool reached = false;
119 | int count = 0;
120 |
121 | while (_running)
122 | {
123 | bool polled = false;
124 | while (!polled)
125 | {
126 | if (enet_host_check_events(host, &netEvent) <= 0)
127 | {
128 | if (enet_host_service(host, &netEvent, 1) <= 0)
129 | break;
130 | polled = true;
131 | }
132 |
133 | switch (netEvent.type)
134 | {
135 | case ENetEventType.ENET_EVENT_TYPE_NONE:
136 | break;
137 | case ENetEventType.ENET_EVENT_TYPE_CONNECT:
138 | connected = true;
139 | Console.WriteLine($"client Connected {netEvent.peer->address.ToString()}");
140 | break;
141 | case ENetEventType.ENET_EVENT_TYPE_DISCONNECT:
142 | connected = false;
143 | Console.WriteLine("client Disconnected");
144 | break;
145 | case ENetEventType.ENET_EVENT_TYPE_RECEIVE:
146 | sent = false;
147 | if ((int)netEvent.packet->dataLength == count)
148 | {
149 | for (int i = 0; i < count; ++i)
150 | {
151 | if (netEvent.packet->data[i] != buffer[i])
152 | {
153 | Console.ForegroundColor = ConsoleColor.Red;
154 | Console.WriteLine("data not same");
155 | Console.ForegroundColor = ConsoleColor.White;
156 | goto label;
157 | }
158 | }
159 | }
160 | else
161 | {
162 | Console.ForegroundColor = ConsoleColor.Red;
163 | Console.WriteLine($"length not same");
164 | Console.ForegroundColor = ConsoleColor.White;
165 | Console.WriteLine((int)netEvent.packet->dataLength + " " + count);
166 | }
167 |
168 | label:
169 | enet_packet_destroy(netEvent.packet);
170 | break;
171 | }
172 | }
173 |
174 | if (connected && !sent)
175 | {
176 | sent = true;
177 | if (!reached)
178 | {
179 | count++;
180 | if (count == 100)
181 | {
182 | Console.ForegroundColor = ConsoleColor.Cyan;
183 | Console.WriteLine("reached max");
184 | Console.ForegroundColor = ConsoleColor.White;
185 | Thread.Sleep(1000);
186 | reached = true;
187 | }
188 | }
189 | else
190 | {
191 | count--;
192 | if (count == 1)
193 | {
194 | Console.ForegroundColor = ConsoleColor.Cyan;
195 | Console.WriteLine("reached min");
196 | Console.ForegroundColor = ConsoleColor.White;
197 | Thread.Sleep(1000);
198 | reached = false;
199 | }
200 | }
201 |
202 | RandomNumberGenerator.Fill(new Span(buffer, count));
203 | ENetPacket* packet = enet_packet_create(buffer, (nuint)count, (uint)ENetPacketFlag.ENET_PACKET_FLAG_RELIABLE);
204 | enet_peer_send(peer, 0, packet);
205 | }
206 |
207 | enet_host_flush(host);
208 | Thread.Sleep(INTERVAL);
209 | }
210 | }
211 | finally
212 | {
213 | if (host != null)
214 | enet_host_destroy(host);
215 | enet_deinitialize();
216 | }
217 | }
218 | }
219 | }
--------------------------------------------------------------------------------
/enet-csharp/ENet/c/win32.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net.Sockets;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 | using NativeSockets;
6 | using static enet.ENetSocketOption;
7 | using static enet.ENetSocketType;
8 | using static enet.ENetSocketWait;
9 | using static enet.ENetHostOption;
10 | using static NativeSockets.SocketPal;
11 |
12 | #pragma warning disable CA1401
13 | #pragma warning disable CA2101
14 | #pragma warning disable CA2211
15 | #pragma warning disable SYSLIB1054
16 | #pragma warning disable CS1591
17 |
18 | // ReSharper disable ALL
19 |
20 | namespace enet
21 | {
22 | public static unsafe partial class ENet
23 | {
24 | public const int SOCKET_ERROR = -1;
25 |
26 | public static uint timeBase = 0;
27 |
28 | ///
29 | /// Initializes ENet globally. Must be called prior to using any functions in
30 | /// ENet.
31 | ///
32 | /// 0 on success, < 0 on failure
33 | public static int enet_initialize() => (int)Initialize();
34 |
35 | ///
36 | /// Shuts down ENet globally. Should be called when a program that has
37 | /// initialized ENet exits.
38 | ///
39 | public static void enet_deinitialize() => Cleanup();
40 |
41 | public static uint enet_host_random_seed() => (uint)timeGetTime();
42 |
43 | ///
44 | /// the wall-time in milliseconds. Its initial value is unspecified
45 | /// unless otherwise set.
46 | ///
47 | public static uint enet_time_get() => (uint)timeGetTime() - timeBase;
48 |
49 | ///
50 | /// Sets the current wall-time in milliseconds.
51 | ///
52 | public static void enet_time_set(uint newTimeBase) => timeBase = (uint)timeGetTime() - newTimeBase;
53 |
54 | public static int enet_socket_bind(ENetSocket socket, ENetAddress* address)
55 | {
56 | if (address == null)
57 | return socket.IsIPv6 ? (int)Bind6(socket, null) : (int)Bind4(socket, null);
58 |
59 | if (socket.IsIPv6)
60 | {
61 | sockaddr_in6 socketAddress;
62 | socketAddress.sin6_family = (ushort)ADDRESS_FAMILY_INTER_NETWORK_V6;
63 | socketAddress.sin6_port = address->port;
64 | socketAddress.sin6_flowinfo = 0;
65 | memcpy(socketAddress.sin6_addr, &address->host, 16);
66 | socketAddress.sin6_scope_id = address->scopeID;
67 |
68 | return (int)Bind6(socket, &socketAddress);
69 | }
70 | else
71 | {
72 | if (address->IsIPv6)
73 | return -1;
74 |
75 | sockaddr_in socketAddress;
76 | socketAddress.sin_family = (ushort)AddressFamily.InterNetwork;
77 | socketAddress.sin_port = address->port;
78 | Unsafe.WriteUnaligned(&socketAddress.sin_addr, address->address);
79 | memset(socketAddress.sin_zero, 0, 8);
80 |
81 | return (int)Bind4(socket, &socketAddress);
82 | }
83 | }
84 |
85 | public static int enet_socket_get_address(nint socket, ENetAddress* address)
86 | {
87 | sockaddr_in6 socketAddress;
88 | int result = (int)GetName6(socket, &socketAddress);
89 | if (result == 0)
90 | {
91 | memcpy(&address->host, socketAddress.sin6_addr, 16);
92 | address->port = socketAddress.sin6_port;
93 | address->scopeID = socketAddress.sin6_scope_id;
94 | }
95 |
96 | return result;
97 | }
98 |
99 | public static ENetSocket enet_socket_create(ENetSocketType type, ENetHostOption option = 0)
100 | {
101 | if (type == ENET_SOCKET_TYPE_DATAGRAM)
102 | {
103 | bool ipv6 = option == ENET_HOSTOPT_IPV6_ONLY || option == ENET_HOSTOPT_IPV6_DUALMODE;
104 | nint socket = Create(ipv6);
105 | if (socket != ENET_SOCKET_NULL && option == ENET_HOSTOPT_IPV6_DUALMODE && enet_socket_set_option(socket, ENET_SOCKOPT_IPV6_ONLY, 0) < 0)
106 | {
107 | Close(socket);
108 | goto error;
109 | }
110 |
111 | return new ENetSocket { handle = socket, IsIPv6 = ipv6 };
112 | }
113 |
114 | error:
115 | return new ENetSocket { handle = INVALID_SOCKET };
116 | }
117 |
118 | public static int enet_socket_set_option(nint socket, ENetSocketOption option, int value)
119 | {
120 | int result = SOCKET_ERROR;
121 | switch (option)
122 | {
123 | case ENET_SOCKOPT_NONBLOCK:
124 | result = enet_socket_set_nonblocking(socket, value);
125 | break;
126 | case ENET_SOCKOPT_BROADCAST:
127 | result = (int)SetOption(socket, SocketOptionLevel.Socket, SocketOptionName.Broadcast, &value);
128 | break;
129 | case ENET_SOCKOPT_RCVBUF:
130 | result = (int)SetOption(socket, SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, &value);
131 | break;
132 | case ENET_SOCKOPT_SNDBUF:
133 | result = (int)SetOption(socket, SocketOptionLevel.Socket, SocketOptionName.SendBuffer, &value);
134 | break;
135 | case ENET_SOCKOPT_REUSEADDR:
136 | result = (int)SetOption(socket, SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, &value);
137 | break;
138 | case ENET_SOCKOPT_RCVTIMEO:
139 | result = (int)SetOption(socket, SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, &value);
140 | break;
141 | case ENET_SOCKOPT_SNDTIMEO:
142 | result = (int)SetOption(socket, SocketOptionLevel.Socket, SocketOptionName.SendTimeout, &value);
143 | break;
144 | case ENET_SOCKOPT_NODELAY:
145 | result = (int)SetOption(socket, SocketOptionLevel.Socket, SocketOptionName.NoDelay, &value);
146 | break;
147 | case ENET_SOCKOPT_TTL:
148 | result = (int)SetOption(socket, SocketOptionLevel.IP, SocketOptionName.IpTimeToLive, &value);
149 | break;
150 | case ENET_SOCKOPT_IPV6_ONLY:
151 | result = (int)SetOption(socket, SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, &value);
152 | break;
153 | default:
154 | break;
155 | }
156 |
157 | return result == SOCKET_ERROR ? -1 : 0;
158 | }
159 |
160 | public static int enet_socket_set_nonblocking(nint socket, int nonBlocking) => (int)SetBlocking(socket, nonBlocking == 0);
161 |
162 | public static void enet_socket_destroy(ENetSocket* socket)
163 | {
164 | Close(socket->handle);
165 | socket->handle = -1;
166 | }
167 |
168 | public static int enet_socket_send(ENetSocket socket, ENetAddress* address, ENetBuffer* buffers, nuint bufferCount)
169 | {
170 | if (socket.IsIPv6)
171 | {
172 | sockaddr_in6 socketAddress;
173 | socketAddress.sin6_family = (ushort)ADDRESS_FAMILY_INTER_NETWORK_V6;
174 | socketAddress.sin6_port = address->port;
175 | socketAddress.sin6_flowinfo = 0;
176 | memcpy(socketAddress.sin6_addr, &address->host, 16);
177 | socketAddress.sin6_scope_id = address->scopeID;
178 |
179 | return WSASendTo6(socket, (WSABuffer*)buffers, (int)bufferCount, &socketAddress);
180 | }
181 | else
182 | {
183 | if (address->IsIPv6)
184 | return -1;
185 |
186 | sockaddr_in socketAddress;
187 | socketAddress.sin_family = (ushort)AddressFamily.InterNetwork;
188 | socketAddress.sin_port = address->port;
189 | Unsafe.WriteUnaligned(&socketAddress.sin_addr, address->address);
190 | memset(socketAddress.sin_zero, 0, 8);
191 |
192 | return WSASendTo4(socket, (WSABuffer*)buffers, (int)bufferCount, &socketAddress);
193 | }
194 | }
195 |
196 | public static int enet_socket_receive(ENetSocket socket, ENetAddress* address, ENetBuffer* buffers, nuint bufferCount)
197 | {
198 | int result;
199 | if (socket.IsIPv6)
200 | {
201 | sockaddr_in6 socketAddress;
202 | result = WSAReceiveFrom6(socket, (WSABuffer*)buffers, (int)bufferCount, &socketAddress);
203 |
204 | if (result <= 0)
205 | return result;
206 |
207 | memcpy(&address->host, socketAddress.sin6_addr, 16);
208 | address->port = socketAddress.sin6_port;
209 | address->scopeID = socketAddress.sin6_scope_id;
210 | return result;
211 | }
212 | else
213 | {
214 | sockaddr_in socketAddress;
215 | result = WSAReceiveFrom4(socket, (WSABuffer*)buffers, (int)bufferCount, &socketAddress);
216 |
217 | if (result <= 0)
218 | return result;
219 |
220 | memset(address, 0, 8);
221 | Unsafe.WriteUnaligned((byte*)address + 8, WinSock2.ADDRESS_FAMILY_INTER_NETWORK_V4_MAPPED_V6);
222 | Unsafe.WriteUnaligned(&address->address, socketAddress.sin_addr);
223 | address->port = socketAddress.sin_port;
224 | address->scopeID = 0;
225 | return result;
226 | }
227 | }
228 |
229 | public static int enet_socket_wait(nint socket, uint* condition, uint timeout)
230 | {
231 | int error;
232 | bool status;
233 |
234 | if ((*condition & (uint)ENET_SOCKET_WAIT_SEND) != 0)
235 | {
236 | error = (int)Poll(socket, (int)(timeout * 1000), SelectMode.SelectWrite, out status);
237 | if (error == 0)
238 | {
239 | *condition = (uint)ENET_SOCKET_WAIT_NONE;
240 | if (status)
241 | {
242 | *condition |= (uint)ENET_SOCKET_WAIT_SEND;
243 | return 0;
244 | }
245 | }
246 |
247 | return -1;
248 | }
249 |
250 | if ((*condition & (uint)ENET_SOCKET_WAIT_RECEIVE) != 0)
251 | {
252 | error = (int)Poll(socket, (int)(timeout * 1000), SelectMode.SelectRead, out status);
253 | if (error == 0)
254 | {
255 | *condition = (uint)ENET_SOCKET_WAIT_NONE;
256 | if (status)
257 | {
258 | *condition |= (uint)ENET_SOCKET_WAIT_RECEIVE;
259 | return 0;
260 | }
261 | }
262 |
263 | return -1;
264 | }
265 |
266 | return 0;
267 | }
268 |
269 | ///
270 | /// Attempts to parse the printable form of the IP address in the parameter hostName
271 | /// and sets the host field in the address parameter if successful.
272 | ///
273 | /// destination to store the parsed IP address
274 | /// IP address to parse
275 | ///
276 | ///
277 | /// -
278 | /// 0 on success
279 | ///
280 | /// -
281 | /// < 0 on failure
282 | ///
283 | ///
284 | /// the address of the given hostName in address on success
285 | ///
286 | public static int enet_address_set_host_ip(ENetAddress* address, ReadOnlySpan ip)
287 | {
288 | sockaddr_in6 __socketAddress_native;
289 | SocketError error = SetIP6(&__socketAddress_native, ip);
290 | if (error == 0)
291 | {
292 | memcpy(address, __socketAddress_native.sin6_addr, 16);
293 | address->scopeID = __socketAddress_native.sin6_scope_id;
294 | }
295 |
296 | return (int)error;
297 | }
298 |
299 | ///
300 | /// Attempts to resolve the host named by the parameter hostName and sets
301 | /// the host field in the address parameter if successful.
302 | ///
303 | /// destination to store resolved address
304 | /// host name to lookup
305 | ///
306 | ///
307 | /// -
308 | /// 0 on success
309 | ///
310 | /// -
311 | /// < 0 on failure
312 | ///
313 | ///
314 | /// the address of the given hostName in address on success
315 | ///
316 | public static int enet_address_set_host(ENetAddress* address, ReadOnlySpan hostName)
317 | {
318 | sockaddr_in6 __socketAddress_native;
319 | SocketError error = SetHostName6(&__socketAddress_native, hostName);
320 | if (error == 0)
321 | {
322 | memcpy(address, __socketAddress_native.sin6_addr, 16);
323 | address->scopeID = __socketAddress_native.sin6_scope_id;
324 | }
325 |
326 | return (int)error;
327 | }
328 |
329 | ///
330 | /// Gives the printable form of the IP address specified in the address parameter.
331 | ///
332 | /// address printed
333 | /// destination for name, must not be NULL
334 | /// maximum length of hostName.
335 | ///
336 | ///
337 | /// -
338 | /// 0 on success
339 | ///
340 | /// -
341 | /// < 0 on failure
342 | ///
343 | ///
344 | /// the null-terminated name of the host in hostName on success
345 | ///
346 | public static int enet_address_get_host_ip(ENetAddress* address, byte* ip, nuint nameLength)
347 | {
348 | sockaddr_in6 __socketAddress_native;
349 | memcpy(__socketAddress_native.sin6_addr, address, 16);
350 | __socketAddress_native.sin6_scope_id = address->scopeID;
351 |
352 | SocketError error = GetIP6(&__socketAddress_native, MemoryMarshal.CreateSpan(ref *ip, (int)nameLength));
353 |
354 | return (int)error;
355 | }
356 |
357 | ///
358 | /// Attempts to do a reverse lookup of the host field in the address parameter.
359 | ///
360 | /// address used for reverse lookup
361 | /// destination for name, must not be NULL
362 | /// maximum length of hostName.
363 | ///
364 | ///
365 | /// -
366 | /// 0 on success
367 | ///
368 | /// -
369 | /// < 0 on failure
370 | ///
371 | ///
372 | /// the null-terminated name of the host in hostName on success
373 | ///
374 | public static int enet_address_get_host(ENetAddress* address, byte* hostName, nuint nameLength)
375 | {
376 | sockaddr_in6 __socketAddress_native;
377 |
378 | __socketAddress_native.sin6_family = (ushort)ADDRESS_FAMILY_INTER_NETWORK_V6;
379 | __socketAddress_native.sin6_port = address->port;
380 | __socketAddress_native.sin6_flowinfo = 0;
381 | memcpy(__socketAddress_native.sin6_addr, address, 16);
382 | __socketAddress_native.sin6_scope_id = address->scopeID;
383 |
384 | SocketError error = GetHostName6(&__socketAddress_native, MemoryMarshal.CreateSpan(ref *hostName, (int)nameLength));
385 |
386 | return (int)error;
387 | }
388 | }
389 | }
--------------------------------------------------------------------------------
/enet-csharp/ENet/plugins/NativeSockets/SocketPal.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net.Sockets;
3 | using System.Runtime.CompilerServices;
4 |
5 | #pragma warning disable CS1591
6 |
7 | // ReSharper disable ALL
8 |
9 | namespace NativeSockets
10 | {
11 | public static unsafe class SocketPal
12 | {
13 | public static ushort ADDRESS_FAMILY_INTER_NETWORK_V6 { get; }
14 |
15 | public static bool IsWindows => WindowsSocketPal.IsSupported;
16 | public static bool IsLinux => LinuxSocketPal.IsSupported;
17 | public static bool IsBSD => BSDSocketPal.IsSupported;
18 |
19 | private static readonly delegate* managed _GetLastSocketError;
20 | private static readonly delegate* managed _Initialize;
21 | private static readonly delegate* managed _Cleanup;
22 | private static readonly delegate* managed _Create;
23 | private static readonly delegate* managed _Close;
24 | private static readonly delegate* managed _SetDualMode6;
25 | private static readonly delegate* managed _Bind4;
26 | private static readonly delegate* managed _Bind6;
27 | private static readonly delegate* managed _Connect4;
28 | private static readonly delegate* managed _Connect6;
29 | private static readonly delegate* managed _SetOption;
30 | private static readonly delegate* managed _GetOption;
31 | private static readonly delegate* managed _SetBlocking;
32 | private static readonly delegate* managed _Poll;
33 | private static readonly delegate* managed _Send;
34 | private static readonly delegate* managed _SendTo4;
35 | private static readonly delegate* managed _SendTo6;
36 | private static readonly delegate* managed _Receive;
37 | private static readonly delegate* managed _ReceiveFrom4;
38 | private static readonly delegate* managed _ReceiveFrom6;
39 | private static readonly delegate* managed _WSASend;
40 | private static readonly delegate* managed _WSASendTo4;
41 | private static readonly delegate* managed _WSASendTo6;
42 | private static readonly delegate* managed _WSAReceive;
43 | private static readonly delegate* managed _WSAReceiveFrom4;
44 | private static readonly delegate* managed _WSAReceiveFrom6;
45 | private static readonly delegate* managed _GetName4;
46 | private static readonly delegate* managed _GetName6;
47 | private static readonly delegate* managed, SocketError> _SetIP4;
48 | private static readonly delegate* managed, SocketError> _SetIP6;
49 | private static readonly delegate* managed, SocketError> _GetIP4;
50 | private static readonly delegate* managed, SocketError> _GetIP6;
51 | private static readonly delegate* managed, SocketError> _SetHostName4;
52 | private static readonly delegate* managed, SocketError> _SetHostName6;
53 | private static readonly delegate* managed, SocketError> _GetHostName4;
54 | private static readonly delegate* managed, SocketError> _GetHostName6;
55 |
56 | static SocketPal()
57 | {
58 | if (IsWindows)
59 | {
60 | ADDRESS_FAMILY_INTER_NETWORK_V6 = WindowsSocketPal.ADDRESS_FAMILY_INTER_NETWORK_V6;
61 |
62 | _GetLastSocketError = &WindowsSocketPal.GetLastSocketError;
63 | _Initialize = &WindowsSocketPal.Initialize;
64 | _Cleanup = &WindowsSocketPal.Cleanup;
65 | _Create = &WindowsSocketPal.Create;
66 | _Close = &WindowsSocketPal.Close;
67 | _SetDualMode6 = &WindowsSocketPal.SetDualMode6;
68 | _Bind4 = &WindowsSocketPal.Bind4;
69 | _Bind6 = &WindowsSocketPal.Bind6;
70 | _Connect4 = &WindowsSocketPal.Connect4;
71 | _Connect6 = &WindowsSocketPal.Connect6;
72 | _SetOption = &WindowsSocketPal.SetOption;
73 | _GetOption = &WindowsSocketPal.GetOption;
74 | _SetBlocking = &WindowsSocketPal.SetBlocking;
75 | _Poll = &WindowsSocketPal.Poll;
76 | _Send = &WindowsSocketPal.Send;
77 | _SendTo4 = &WindowsSocketPal.SendTo4;
78 | _SendTo6 = &WindowsSocketPal.SendTo6;
79 | _Receive = &WindowsSocketPal.Receive;
80 | _ReceiveFrom4 = &WindowsSocketPal.ReceiveFrom4;
81 | _ReceiveFrom6 = &WindowsSocketPal.ReceiveFrom6;
82 | _WSASend = &WindowsSocketPal.WSASend;
83 | _WSASendTo4 = &WindowsSocketPal.WSASendTo4;
84 | _WSASendTo6 = &WindowsSocketPal.WSASendTo6;
85 | _WSAReceive = &WindowsSocketPal.WSAReceive;
86 | _WSAReceiveFrom4 = &WindowsSocketPal.WSAReceiveFrom4;
87 | _WSAReceiveFrom6 = &WindowsSocketPal.WSAReceiveFrom6;
88 | _GetName4 = &WindowsSocketPal.GetName4;
89 | _GetName6 = &WindowsSocketPal.GetName6;
90 | _SetIP4 = &WindowsSocketPal.SetIP4;
91 | _SetIP6 = &WindowsSocketPal.SetIP6;
92 | _GetIP4 = &WindowsSocketPal.GetIP4;
93 | _GetIP6 = &WindowsSocketPal.GetIP6;
94 | _SetHostName4 = &WindowsSocketPal.SetHostName4;
95 | _SetHostName6 = &WindowsSocketPal.SetHostName6;
96 | _GetHostName4 = &WindowsSocketPal.GetHostName4;
97 | _GetHostName6 = &WindowsSocketPal.GetHostName6;
98 |
99 | return;
100 | }
101 |
102 | if (IsLinux)
103 | {
104 | ADDRESS_FAMILY_INTER_NETWORK_V6 = LinuxSocketPal.ADDRESS_FAMILY_INTER_NETWORK_V6;
105 |
106 | _GetLastSocketError = &LinuxSocketPal.GetLastSocketError;
107 | _Initialize = &LinuxSocketPal.Initialize;
108 | _Cleanup = &LinuxSocketPal.Cleanup;
109 | _Create = &LinuxSocketPal.Create;
110 | _Close = &LinuxSocketPal.Close;
111 | _SetDualMode6 = &LinuxSocketPal.SetDualMode6;
112 | _Bind4 = &LinuxSocketPal.Bind4;
113 | _Bind6 = &LinuxSocketPal.Bind6;
114 | _Connect4 = &LinuxSocketPal.Connect4;
115 | _Connect6 = &LinuxSocketPal.Connect6;
116 | _SetOption = &LinuxSocketPal.SetOption;
117 | _GetOption = &LinuxSocketPal.GetOption;
118 | _SetBlocking = &LinuxSocketPal.SetBlocking;
119 | _Poll = &LinuxSocketPal.Poll;
120 | _Send = &LinuxSocketPal.Send;
121 | _SendTo4 = &LinuxSocketPal.SendTo4;
122 | _SendTo6 = &LinuxSocketPal.SendTo6;
123 | _Receive = &LinuxSocketPal.Receive;
124 | _ReceiveFrom4 = &LinuxSocketPal.ReceiveFrom4;
125 | _ReceiveFrom6 = &LinuxSocketPal.ReceiveFrom6;
126 | _WSASend = &LinuxSocketPal.WSASend;
127 | _WSASendTo4 = &LinuxSocketPal.WSASendTo4;
128 | _WSASendTo6 = &LinuxSocketPal.WSASendTo6;
129 | _WSAReceive = &LinuxSocketPal.WSAReceive;
130 | _WSAReceiveFrom4 = &LinuxSocketPal.WSAReceiveFrom4;
131 | _WSAReceiveFrom6 = &LinuxSocketPal.WSAReceiveFrom6;
132 | _GetName4 = &LinuxSocketPal.GetName4;
133 | _GetName6 = &LinuxSocketPal.GetName6;
134 | _SetIP4 = &LinuxSocketPal.SetIP4;
135 | _SetIP6 = &LinuxSocketPal.SetIP6;
136 | _GetIP4 = &LinuxSocketPal.GetIP4;
137 | _GetIP6 = &LinuxSocketPal.GetIP6;
138 | _SetHostName4 = &LinuxSocketPal.SetHostName4;
139 | _SetHostName6 = &LinuxSocketPal.SetHostName6;
140 | _GetHostName4 = &LinuxSocketPal.GetHostName4;
141 | _GetHostName6 = &LinuxSocketPal.GetHostName6;
142 |
143 | return;
144 | }
145 |
146 | ADDRESS_FAMILY_INTER_NETWORK_V6 = BSDSocketPal.ADDRESS_FAMILY_INTER_NETWORK_V6;
147 |
148 | _GetLastSocketError = &BSDSocketPal.GetLastSocketError;
149 | _Initialize = &BSDSocketPal.Initialize;
150 | _Cleanup = &BSDSocketPal.Cleanup;
151 | _Create = &BSDSocketPal.Create;
152 | _Close = &BSDSocketPal.Close;
153 | _SetDualMode6 = &BSDSocketPal.SetDualMode6;
154 | _Bind4 = &BSDSocketPal.Bind4;
155 | _Bind6 = &BSDSocketPal.Bind6;
156 | _Connect4 = &BSDSocketPal.Connect4;
157 | _Connect6 = &BSDSocketPal.Connect6;
158 | _SetOption = &BSDSocketPal.SetOption;
159 | _GetOption = &BSDSocketPal.GetOption;
160 | _SetBlocking = &BSDSocketPal.SetBlocking;
161 | _Poll = &BSDSocketPal.Poll;
162 | _Send = &BSDSocketPal.Send;
163 | _SendTo4 = &BSDSocketPal.SendTo4;
164 | _SendTo6 = &BSDSocketPal.SendTo6;
165 | _Receive = &BSDSocketPal.Receive;
166 | _ReceiveFrom4 = &BSDSocketPal.ReceiveFrom4;
167 | _ReceiveFrom6 = &BSDSocketPal.ReceiveFrom6;
168 | _WSASend = &BSDSocketPal.WSASend;
169 | _WSASendTo4 = &BSDSocketPal.WSASendTo4;
170 | _WSASendTo6 = &BSDSocketPal.WSASendTo6;
171 | _WSAReceive = &BSDSocketPal.WSAReceive;
172 | _WSAReceiveFrom4 = &BSDSocketPal.WSAReceiveFrom4;
173 | _WSAReceiveFrom6 = &BSDSocketPal.WSAReceiveFrom6;
174 | _GetName4 = &BSDSocketPal.GetName4;
175 | _GetName6 = &BSDSocketPal.GetName6;
176 | _SetIP4 = &BSDSocketPal.SetIP4;
177 | _SetIP6 = &BSDSocketPal.SetIP6;
178 | _GetIP4 = &BSDSocketPal.GetIP4;
179 | _GetIP6 = &BSDSocketPal.GetIP6;
180 | _SetHostName4 = &BSDSocketPal.SetHostName4;
181 | _SetHostName6 = &BSDSocketPal.SetHostName6;
182 | _GetHostName4 = &BSDSocketPal.GetHostName4;
183 | _GetHostName6 = &BSDSocketPal.GetHostName6;
184 | }
185 |
186 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
187 | public static SocketError GetLastSocketError() => _GetLastSocketError();
188 |
189 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
190 | public static SocketError Initialize() => _Initialize();
191 |
192 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
193 | public static SocketError Cleanup() => _Cleanup();
194 |
195 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
196 | public static nint Create(bool ipv6) => _Create(ipv6);
197 |
198 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
199 | public static SocketError Close(nint socket) => _Close(socket);
200 |
201 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
202 | public static SocketError SetDualMode6(nint socket, bool dualMode) => _SetDualMode6(socket, dualMode);
203 |
204 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
205 | public static SocketError Bind4(nint socket, sockaddr_in* socketAddress) => _Bind4(socket, socketAddress);
206 |
207 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
208 | public static SocketError Bind6(nint socket, sockaddr_in6* socketAddress) => _Bind6(socket, socketAddress);
209 |
210 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
211 | public static SocketError Connect4(nint socket, sockaddr_in* socketAddress) => _Connect4(socket, socketAddress);
212 |
213 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
214 | public static SocketError Connect6(nint socket, sockaddr_in6* socketAddress) => _Connect6(socket, socketAddress);
215 |
216 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
217 | public static SocketError SetOption(nint socket, SocketOptionLevel level, SocketOptionName name, int* value, int length = sizeof(int)) => _SetOption(socket, level, name, value, length);
218 |
219 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
220 | public static SocketError GetOption(nint socket, SocketOptionLevel level, SocketOptionName name, int* value, int* length = null) => _GetOption(socket, level, name, value, length);
221 |
222 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
223 | public static SocketError SetBlocking(nint socket, bool blocking) => _SetBlocking(socket, blocking);
224 |
225 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
226 | public static SocketError Poll(nint socket, int microseconds, SelectMode mode, out bool status) => _Poll(socket, microseconds, mode, out status);
227 |
228 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
229 | public static int Send(nint socket, void* buffer, int length) => _Send(socket, buffer, length);
230 |
231 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
232 | public static int SendTo4(nint socket, void* buffer, int length, sockaddr_in* socketAddress) => _SendTo4(socket, buffer, length, socketAddress);
233 |
234 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
235 | public static int SendTo6(nint socket, void* buffer, int length, sockaddr_in6* socketAddress) => _SendTo6(socket, buffer, length, socketAddress);
236 |
237 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
238 | public static int Receive(nint socket, void* buffer, int length) => _Receive(socket, buffer, length);
239 |
240 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
241 | public static int ReceiveFrom4(nint socket, void* buffer, int length, sockaddr_in* socketAddress) => _ReceiveFrom4(socket, buffer, length, socketAddress);
242 |
243 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
244 | public static int ReceiveFrom6(nint socket, void* buffer, int length, sockaddr_in6* socketAddress) => _ReceiveFrom6(socket, buffer, length, socketAddress);
245 |
246 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
247 | public static int WSASend(nint socket, WSABuffer* buffers, int bufferCount) => _WSASend(socket, buffers, bufferCount);
248 |
249 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
250 | public static int WSASendTo4(nint socket, WSABuffer* buffers, int bufferCount, sockaddr_in* socketAddress) => _WSASendTo4(socket, buffers, bufferCount, socketAddress);
251 |
252 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
253 | public static int WSASendTo6(nint socket, WSABuffer* buffers, int bufferCount, sockaddr_in6* socketAddress) => _WSASendTo6(socket, buffers, bufferCount, socketAddress);
254 |
255 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
256 | public static int WSAReceive(nint socket, WSABuffer* buffers, int bufferCount) => _WSAReceive(socket, buffers, bufferCount);
257 |
258 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
259 | public static int WSAReceiveFrom4(nint socket, WSABuffer* buffers, int bufferCount, sockaddr_in* socketAddress) => _WSAReceiveFrom4(socket, buffers, bufferCount, socketAddress);
260 |
261 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
262 | public static int WSAReceiveFrom6(nint socket, WSABuffer* buffers, int bufferCount, sockaddr_in6* socketAddress) => _WSAReceiveFrom6(socket, buffers, bufferCount, socketAddress);
263 |
264 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
265 | public static SocketError GetName4(nint socket, sockaddr_in* socketAddress) => _GetName4(socket, socketAddress);
266 |
267 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
268 | public static SocketError GetName6(nint socket, sockaddr_in6* socketAddress) => _GetName6(socket, socketAddress);
269 |
270 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
271 | public static SocketError SetIP4(sockaddr_in* pAddrBuf, ReadOnlySpan ip) => _SetIP4(pAddrBuf, ip);
272 |
273 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
274 | public static SocketError SetIP6(sockaddr_in6* pAddrBuf, ReadOnlySpan ip) => _SetIP6(pAddrBuf, ip);
275 |
276 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
277 | public static SocketError GetIP4(sockaddr_in* pAddrBuf, Span ip) => _GetIP4(pAddrBuf, ip);
278 |
279 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
280 | public static SocketError GetIP6(sockaddr_in6* pAddrBuf, Span ip) => _GetIP6(pAddrBuf, ip);
281 |
282 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
283 | public static SocketError SetHostName4(sockaddr_in* pAddrBuf, ReadOnlySpan hostName) => _SetHostName4(pAddrBuf, hostName);
284 |
285 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
286 | public static SocketError SetHostName6(sockaddr_in6* pAddrBuf, ReadOnlySpan hostName) => _SetHostName6(pAddrBuf, hostName);
287 |
288 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
289 | public static SocketError GetHostName4(sockaddr_in* socketAddress, Span hostName) => _GetHostName4(socketAddress, hostName);
290 |
291 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
292 | public static SocketError GetHostName6(sockaddr_in6* socketAddress, Span hostName) => _GetHostName6(socketAddress, hostName);
293 | }
294 | }
--------------------------------------------------------------------------------
/enet-csharp/ENet/c/host.cs:
--------------------------------------------------------------------------------
1 | using static enet.ENetSocketOption;
2 | using static enet.ENetSocketType;
3 | using static enet.ENetPeerState;
4 | using static enet.ENetProtocolCommand;
5 | using static enet.ENetProtocolFlag;
6 | using static enet.ENetHostOption;
7 |
8 | #pragma warning disable CS1591
9 |
10 | // ReSharper disable ALL
11 |
12 | namespace enet
13 | {
14 | public static unsafe partial class ENet
15 | {
16 | ///
17 | /// Sends a ping request to an address.
18 | ///
19 | /// host ping the address
20 | /// destination for the ping request
21 | public static int enet_host_ping(ENetHost* host, ENetAddress* address)
22 | {
23 | ENetBuffer buffer;
24 | byte* data = stackalloc byte[1];
25 | buffer.data = data;
26 | buffer.dataLength = 1;
27 | return enet_socket_send(host->socket, address, &buffer, 1) > 0 ? 0 : -1;
28 | }
29 |
30 | ///
31 | /// Creates a host for communicating to peers.
32 | ///
33 | ///
34 | /// The address at which other peers may connect to this host. If NULL, then no peers may connect to
35 | /// the host.
36 | ///
37 | /// The maximum number of peers that should be allocated for the host.
38 | ///
39 | /// The maximum number of channels allowed; if 0, then this is equivalent to
40 | /// ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT
41 | ///
42 | ///
43 | /// Downstream bandwidth of the host in bytes/second; if 0, ENet will assume unlimited
44 | /// bandwidth.
45 | ///
46 | ///
47 | /// Upstream bandwidth of the host in bytes/second; if 0, ENet will assume unlimited
48 | /// bandwidth.
49 | ///
50 | ///
51 | ///
52 | /// -
53 | /// ENET_HOSTOPT_IPV4 (default): IPv4
54 | ///
55 | /// -
56 | /// ENET_HOSTOPT_IPV6_ONLY: IPv6-only
57 | ///
58 | /// -
59 | /// ENET_HOSTOPT_IPV6_DUALMODE: both IPv4 and IPv6
60 | ///
61 | ///
62 | ///
63 | /// The host on success and NULL on failure
64 | ///
65 | /// ENet will strategically drop packets on specific sides of a connection between hosts
66 | /// to ensure the host's bandwidth is not overwhelmed. The bandwidth parameters also determine
67 | /// the window size of a connection which limits the amount of reliable packets that may be in transit
68 | /// at any given time.
69 | ///
70 | public static ENetHost* enet_host_create(ENetAddress* address, nuint peerCount, nuint channelLimit, uint incomingBandwidth, uint outgoingBandwidth, ENetHostOption option = 0)
71 | {
72 | if (option < ENET_HOSTOPT_IPV4 || option > ENET_HOSTOPT_IPV6_DUALMODE)
73 | return null;
74 |
75 | ENetHost* host;
76 | ENetPeer* currentPeer;
77 |
78 | if (peerCount > ENET_PROTOCOL_MAXIMUM_PEER_ID)
79 | return null;
80 |
81 | host = (ENetHost*)enet_malloc((nuint)sizeof(ENetHost));
82 | if (host == null)
83 | return null;
84 |
85 | memset(host, 0, (nuint)sizeof(ENetHost));
86 |
87 | host->peers = (ENetPeer*)enet_malloc(peerCount * (nuint)sizeof(ENetPeer));
88 | if (host->peers == null)
89 | {
90 | enet_free(host);
91 |
92 | return null;
93 | }
94 |
95 | memset(host->peers, 0, peerCount * (nuint)sizeof(ENetPeer));
96 |
97 | host->socket = enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM, option);
98 |
99 | if (host->socket == ENET_SOCKET_NULL || (address != null && enet_socket_bind(host->socket, address) < 0))
100 | {
101 | if (host->socket != ENET_SOCKET_NULL)
102 | enet_socket_destroy(&host->socket);
103 |
104 | enet_free(host->peers);
105 | enet_free(host);
106 |
107 | return null;
108 | }
109 |
110 | enet_socket_set_option(host->socket, ENET_SOCKOPT_NONBLOCK, 1);
111 | enet_socket_set_option(host->socket, ENET_SOCKOPT_BROADCAST, 1);
112 | enet_socket_set_option(host->socket, ENET_SOCKOPT_RCVBUF, (int)ENET_HOST_RECEIVE_BUFFER_SIZE);
113 | enet_socket_set_option(host->socket, ENET_SOCKOPT_SNDBUF, (int)ENET_HOST_SEND_BUFFER_SIZE);
114 |
115 | if (address != null && enet_socket_get_address(host->socket, &host->address) < 0)
116 | host->address = *address;
117 |
118 | if (!(channelLimit != 0) || channelLimit > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT)
119 | channelLimit = (nuint)ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT;
120 | else if (channelLimit < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT)
121 | channelLimit = (nuint)ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT;
122 |
123 | host->randomSeed = (uint)(nuint)host;
124 | host->randomSeed += enet_host_random_seed();
125 | host->randomSeed = (host->randomSeed << 16) | (host->randomSeed >> 16);
126 | host->channelLimit = channelLimit;
127 | host->incomingBandwidth = incomingBandwidth;
128 | host->outgoingBandwidth = outgoingBandwidth;
129 | host->bandwidthThrottleEpoch = 0;
130 | host->recalculateBandwidthLimits = 0;
131 | host->mtu = ENET_HOST_DEFAULT_MTU;
132 | host->peerCount = peerCount;
133 | host->commandCount = 0;
134 | host->bufferCount = 0;
135 | host->checksum = null;
136 | host->receivedAddress.host = ENET_HOST_ANY;
137 | host->receivedAddress.port = 0;
138 | host->receivedAddress.scopeID = 0;
139 | host->receivedData = null;
140 | host->receivedDataLength = 0;
141 |
142 | host->totalSentData = 0;
143 | host->totalSentPackets = 0;
144 | host->totalReceivedData = 0;
145 | host->totalReceivedPackets = 0;
146 | host->totalQueued = 0;
147 |
148 | host->connectedPeers = 0;
149 | host->bandwidthLimitedPeers = 0;
150 | host->duplicatePeers = (nuint)ENET_PROTOCOL_MAXIMUM_PEER_ID;
151 | host->maximumPacketSize = (nuint)ENET_HOST_DEFAULT_MAXIMUM_PACKET_SIZE;
152 | host->maximumWaitingData = (nuint)ENET_HOST_DEFAULT_MAXIMUM_WAITING_DATA;
153 |
154 | host->compressor.context = null;
155 | host->compressor.compress = null;
156 | host->compressor.decompress = null;
157 | host->compressor.destroy = null;
158 |
159 | host->intercept = null;
160 |
161 | enet_list_clear(&host->dispatchQueue);
162 |
163 | for (currentPeer = host->peers;
164 | currentPeer < &host->peers[host->peerCount];
165 | ++currentPeer)
166 | {
167 | currentPeer->host = host;
168 | currentPeer->incomingPeerID = (ushort)(currentPeer - host->peers);
169 | currentPeer->outgoingSessionID = currentPeer->incomingSessionID = 0xFF;
170 | currentPeer->data = null;
171 |
172 | enet_list_clear(¤tPeer->acknowledgements);
173 | enet_list_clear(¤tPeer->sentReliableCommands);
174 | enet_list_clear(¤tPeer->outgoingCommands);
175 | enet_list_clear(¤tPeer->outgoingSendReliableCommands);
176 | enet_list_clear(¤tPeer->dispatchedCommands);
177 |
178 | enet_peer_reset(currentPeer);
179 | }
180 |
181 | return host;
182 | }
183 |
184 | ///
185 | /// Destroys the host and all resources associated with it.
186 | ///
187 | /// pointer to the host to destroy
188 | public static void enet_host_destroy(ENetHost* host)
189 | {
190 | ENetPeer* currentPeer;
191 |
192 | if (host == null)
193 | return;
194 |
195 | enet_socket_destroy(&host->socket);
196 |
197 | for (currentPeer = host->peers;
198 | currentPeer < &host->peers[host->peerCount];
199 | ++currentPeer)
200 | {
201 | enet_peer_reset(currentPeer);
202 | }
203 |
204 | if (host->compressor.context != null && host->compressor.destroy != null)
205 | (host->compressor.destroy)(host->compressor.context);
206 |
207 | enet_free(host->peers);
208 | enet_free(host);
209 | }
210 |
211 | public static uint enet_host_random(ENetHost* host)
212 | {
213 | uint n = (host->randomSeed += 0x6D2B79F5U);
214 | n = (n ^ (n >> 15)) * (n | 1U);
215 | n ^= n + (n ^ (n >> 7)) * (n | 61U);
216 | return n ^ (n >> 14);
217 | }
218 |
219 | ///
220 | /// Initiates a connection to a foreign host.
221 | ///
222 | /// host seeking the connection
223 | /// destination for the connection
224 | /// number of channels to allocate
225 | /// user data supplied to the receiving host
226 | /// a peer representing the foreign host on success, NULL on failure
227 | ///
228 | /// The peer returned will have not completed the connection until enet_host_service()
229 | /// notifies of an ENET_EVENT_TYPE_CONNECT event for the peer.
230 | ///
231 | public static ENetPeer* enet_host_connect(ENetHost* host, ENetAddress* address, nuint channelCount, uint data)
232 | {
233 | ENetPeer* currentPeer;
234 | ENetChannel* channel;
235 | ENetProtocol command;
236 |
237 | if (channelCount < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT)
238 | channelCount = (nuint)ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT;
239 | else if (channelCount > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT)
240 | channelCount = (nuint)ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT;
241 |
242 | for (currentPeer = host->peers;
243 | currentPeer < &host->peers[host->peerCount];
244 | ++currentPeer)
245 | {
246 | if (currentPeer->state == ENET_PEER_STATE_DISCONNECTED)
247 | break;
248 | }
249 |
250 | if (currentPeer >= &host->peers[host->peerCount])
251 | return null;
252 |
253 | currentPeer->channels = (ENetChannel*)enet_malloc(channelCount * (nuint)sizeof(ENetChannel));
254 | if (currentPeer->channels == null)
255 | return null;
256 |
257 | currentPeer->channelCount = channelCount;
258 | currentPeer->state = ENET_PEER_STATE_CONNECTING;
259 | currentPeer->address = *address;
260 | currentPeer->connectID = enet_host_random(host);
261 | currentPeer->mtu = host->mtu;
262 |
263 | if (host->outgoingBandwidth == 0)
264 | currentPeer->windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
265 | else
266 | currentPeer->windowSize = (host->outgoingBandwidth /
267 | ENET_PEER_WINDOW_SIZE_SCALE) *
268 | ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
269 |
270 | if (currentPeer->windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
271 | currentPeer->windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
272 | else if (currentPeer->windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
273 | currentPeer->windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
274 |
275 | for (channel = currentPeer->channels;
276 | channel < ¤tPeer->channels[channelCount];
277 | ++channel)
278 | {
279 | channel->outgoingReliableSequenceNumber = 0;
280 | channel->outgoingUnreliableSequenceNumber = 0;
281 | channel->incomingReliableSequenceNumber = 0;
282 | channel->incomingUnreliableSequenceNumber = 0;
283 |
284 | enet_list_clear(&channel->incomingReliableCommands);
285 | enet_list_clear(&channel->incomingUnreliableCommands);
286 |
287 | channel->usedReliableWindows = 0;
288 | memset(channel->reliableWindows, 0, (nuint)(ENET_PEER_RELIABLE_WINDOWS * sizeof(ushort)));
289 | }
290 |
291 | command.header.command = (byte)((uint)ENET_PROTOCOL_COMMAND_CONNECT | (uint)ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE);
292 | command.header.channelID = 0xFF;
293 | command.connect.outgoingPeerID = ENET_HOST_TO_NET_16(currentPeer->incomingPeerID);
294 | command.connect.incomingSessionID = currentPeer->incomingSessionID;
295 | command.connect.outgoingSessionID = currentPeer->outgoingSessionID;
296 | command.connect.mtu = ENET_HOST_TO_NET_32(currentPeer->mtu);
297 | command.connect.windowSize = ENET_HOST_TO_NET_32(currentPeer->windowSize);
298 | command.connect.channelCount = ENET_HOST_TO_NET_32((uint)channelCount);
299 | command.connect.incomingBandwidth = ENET_HOST_TO_NET_32(host->incomingBandwidth);
300 | command.connect.outgoingBandwidth = ENET_HOST_TO_NET_32(host->outgoingBandwidth);
301 | command.connect.packetThrottleInterval = ENET_HOST_TO_NET_32(currentPeer->packetThrottleInterval);
302 | command.connect.packetThrottleAcceleration = ENET_HOST_TO_NET_32(currentPeer->packetThrottleAcceleration);
303 | command.connect.packetThrottleDeceleration = ENET_HOST_TO_NET_32(currentPeer->packetThrottleDeceleration);
304 | command.connect.connectID = currentPeer->connectID;
305 | command.connect.data = ENET_HOST_TO_NET_32(data);
306 |
307 | enet_peer_queue_outgoing_command(currentPeer, &command, null, 0, 0);
308 |
309 | return currentPeer;
310 | }
311 |
312 | ///
313 | /// Queues a packet to be sent to all peers associated with the host.
314 | ///
315 | /// host on which to broadcast the packet
316 | /// channel on which to broadcast
317 | /// packet to broadcast
318 | public static void enet_host_broadcast(ENetHost* host, byte channelID, ENetPacket* packet)
319 | {
320 | ENetPeer* currentPeer;
321 |
322 | for (currentPeer = host->peers;
323 | currentPeer < &host->peers[host->peerCount];
324 | ++currentPeer)
325 | {
326 | if (currentPeer->state != ENET_PEER_STATE_CONNECTED)
327 | continue;
328 |
329 | enet_peer_send(currentPeer, channelID, packet);
330 | }
331 |
332 | if (packet->referenceCount == 0)
333 | enet_packet_destroy(packet);
334 | }
335 |
336 | ///
337 | /// Sets the packet compressor the host should use to compress and decompress packets.
338 | ///
339 | /// host to enable or disable compression for
340 | /// callbacks for for the packet compressor; if NULL, then compression is disabled
341 | public static void enet_host_compress(ENetHost* host, ENetCompressor* compressor)
342 | {
343 | if (host->compressor.context != null && host->compressor.destroy != null)
344 | (host->compressor.destroy)(host->compressor.context);
345 |
346 | if (compressor != null)
347 | host->compressor = *compressor;
348 | else
349 | host->compressor.context = null;
350 | }
351 |
352 | ///
353 | /// Limits the maximum allowed channels of future incoming connections.
354 | ///
355 | /// host to limit
356 | ///
357 | /// the maximum number of channels allowed; if 0, then this is equivalent to
358 | /// ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT
359 | ///
360 | public static void enet_host_channel_limit(ENetHost* host, nuint channelLimit)
361 | {
362 | if (!(channelLimit != 0) || channelLimit > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT)
363 | channelLimit = (nuint)ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT;
364 | else if (channelLimit < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT)
365 | channelLimit = (nuint)ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT;
366 |
367 | host->channelLimit = channelLimit;
368 | }
369 |
370 | ///
371 | /// Adjusts the bandwidth limits of a host.
372 | ///
373 | /// host to adjust
374 | /// new incoming bandwidth
375 | /// new outgoing bandwidth
376 | ///
377 | /// the incoming and outgoing bandwidth parameters are identical in function to those
378 | /// specified in .
379 | ///
380 | public static void enet_host_bandwidth_limit(ENetHost* host, uint incomingBandwidth, uint outgoingBandwidth)
381 | {
382 | host->incomingBandwidth = incomingBandwidth;
383 | host->outgoingBandwidth = outgoingBandwidth;
384 | host->recalculateBandwidthLimits = 1;
385 | }
386 |
387 | public static void enet_host_bandwidth_throttle(ENetHost* host)
388 | {
389 | uint timeCurrent = enet_time_get(),
390 | elapsedTime = timeCurrent - host->bandwidthThrottleEpoch,
391 | peersRemaining = (uint)host->connectedPeers,
392 | dataTotal = unchecked((uint)(~0)),
393 | bandwidth = unchecked((uint)(~0)),
394 | throttle = 0,
395 | bandwidthLimit = 0;
396 | int needsAdjustment = host->bandwidthLimitedPeers > 0 ? 1 : 0;
397 | ENetPeer* peer;
398 | ENetProtocol command;
399 |
400 | if (elapsedTime < ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL)
401 | return;
402 |
403 | host->bandwidthThrottleEpoch = timeCurrent;
404 |
405 | if (peersRemaining == 0)
406 | return;
407 |
408 | if (host->outgoingBandwidth != 0)
409 | {
410 | dataTotal = 0;
411 | bandwidth = (host->outgoingBandwidth * elapsedTime) / 1000;
412 |
413 | for (peer = host->peers;
414 | peer < &host->peers[host->peerCount];
415 | ++peer)
416 | {
417 | if (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER)
418 | continue;
419 |
420 | dataTotal += peer->outgoingDataTotal;
421 | }
422 | }
423 |
424 | while (peersRemaining > 0 && needsAdjustment != 0)
425 | {
426 | needsAdjustment = 0;
427 |
428 | if (dataTotal <= bandwidth)
429 | throttle = ENET_PEER_PACKET_THROTTLE_SCALE;
430 | else
431 | throttle = (bandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / dataTotal;
432 |
433 | for (peer = host->peers;
434 | peer < &host->peers[host->peerCount];
435 | ++peer)
436 | {
437 | uint peerBandwidth;
438 |
439 | if ((peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) ||
440 | peer->incomingBandwidth == 0 ||
441 | peer->outgoingBandwidthThrottleEpoch == timeCurrent)
442 | continue;
443 |
444 | peerBandwidth = (peer->incomingBandwidth * elapsedTime) / 1000;
445 | if ((throttle * peer->outgoingDataTotal) / ENET_PEER_PACKET_THROTTLE_SCALE <= peerBandwidth)
446 | continue;
447 |
448 | peer->packetThrottleLimit = (peerBandwidth *
449 | ENET_PEER_PACKET_THROTTLE_SCALE) / peer->outgoingDataTotal;
450 |
451 | if (peer->packetThrottleLimit == 0)
452 | peer->packetThrottleLimit = 1;
453 |
454 | if (peer->packetThrottle > peer->packetThrottleLimit)
455 | peer->packetThrottle = peer->packetThrottleLimit;
456 |
457 | peer->outgoingBandwidthThrottleEpoch = timeCurrent;
458 |
459 | peer->incomingDataTotal = 0;
460 | peer->outgoingDataTotal = 0;
461 |
462 | needsAdjustment = 1;
463 | --peersRemaining;
464 | bandwidth -= peerBandwidth;
465 | dataTotal -= peerBandwidth;
466 | }
467 | }
468 |
469 | if (peersRemaining > 0)
470 | {
471 | if (dataTotal <= bandwidth)
472 | throttle = ENET_PEER_PACKET_THROTTLE_SCALE;
473 | else
474 | throttle = (bandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / dataTotal;
475 |
476 | for (peer = host->peers;
477 | peer < &host->peers[host->peerCount];
478 | ++peer)
479 | {
480 | if ((peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) ||
481 | peer->outgoingBandwidthThrottleEpoch == timeCurrent)
482 | continue;
483 |
484 | peer->packetThrottleLimit = throttle;
485 |
486 | if (peer->packetThrottle > peer->packetThrottleLimit)
487 | peer->packetThrottle = peer->packetThrottleLimit;
488 |
489 | peer->incomingDataTotal = 0;
490 | peer->outgoingDataTotal = 0;
491 | }
492 | }
493 |
494 | if ((host->recalculateBandwidthLimits) != 0)
495 | {
496 | host->recalculateBandwidthLimits = 0;
497 |
498 | peersRemaining = (uint)host->connectedPeers;
499 | bandwidth = host->incomingBandwidth;
500 | needsAdjustment = 1;
501 |
502 | if (bandwidth == 0)
503 | bandwidthLimit = 0;
504 | else
505 | {
506 | while (peersRemaining > 0 && needsAdjustment != 0)
507 | {
508 | needsAdjustment = 0;
509 | bandwidthLimit = bandwidth / peersRemaining;
510 |
511 | for (peer = host->peers;
512 | peer < &host->peers[host->peerCount];
513 | ++peer)
514 | {
515 | if ((peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) ||
516 | peer->incomingBandwidthThrottleEpoch == timeCurrent)
517 | continue;
518 |
519 | if (peer->outgoingBandwidth > 0 &&
520 | peer->outgoingBandwidth >= bandwidthLimit)
521 | continue;
522 |
523 | peer->incomingBandwidthThrottleEpoch = timeCurrent;
524 |
525 | needsAdjustment = 1;
526 | --peersRemaining;
527 | bandwidth -= peer->outgoingBandwidth;
528 | }
529 | }
530 | }
531 |
532 | for (peer = host->peers;
533 | peer < &host->peers[host->peerCount];
534 | ++peer)
535 | {
536 | if (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER)
537 | continue;
538 |
539 | command.header.command = (byte)((uint)ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT | (uint)ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE);
540 | command.header.channelID = 0xFF;
541 | command.bandwidthLimit.outgoingBandwidth = ENET_HOST_TO_NET_32(host->outgoingBandwidth);
542 |
543 | if (peer->incomingBandwidthThrottleEpoch == timeCurrent)
544 | command.bandwidthLimit.incomingBandwidth = ENET_HOST_TO_NET_32(peer->outgoingBandwidth);
545 | else
546 | command.bandwidthLimit.incomingBandwidth = ENET_HOST_TO_NET_32(bandwidthLimit);
547 |
548 | enet_peer_queue_outgoing_command(peer, &command, null, 0, 0);
549 | }
550 | }
551 | }
552 | }
553 | }
--------------------------------------------------------------------------------
/enet-csharp/ENet/c/enet.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.CompilerServices;
3 |
4 | #pragma warning disable CS1591
5 |
6 | // ReSharper disable ALL
7 |
8 | namespace enet
9 | {
10 | public static unsafe class ENET_API
11 | {
12 | ///
13 | /// Initializes ENet globally. Must be called prior to using any functions in
14 | /// ENet.
15 | ///
16 | /// 0 on success, < 0 on failure
17 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
18 | public static int enet_initialize() => ENet.enet_initialize();
19 |
20 | ///
21 | /// Initializes ENet globally and supplies user-overridden callbacks. Must be called prior to using any functions in
22 | /// ENet.
23 | /// Do not use if you use this variant. Make sure the
24 | /// structure
25 | /// is zeroed out so that any additional callbacks added in future versions will be properly ignored.
26 | ///
27 | ///
28 | /// the constant should be supplied so ENet knows which version of
29 | /// struct to use
30 | ///
31 | /// user-overridden callbacks where any NULL callbacks will use ENet's defaults
32 | /// 0 on success, < 0 on failure
33 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
34 | public static int enet_initialize_with_callbacks(uint version, ENetCallbacks* inits) => ENet.enet_initialize_with_callbacks(version, inits);
35 |
36 | ///
37 | /// Shuts down ENet globally. Should be called when a program that has
38 | /// initialized ENet exits.
39 | ///
40 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
41 | public static void enet_deinitialize() => ENet.enet_deinitialize();
42 |
43 | ///
44 | /// Gives the linked version of the ENet library.
45 | ///
46 | /// the version number
47 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
48 | public static uint enet_linked_version() => ENet.enet_linked_version();
49 |
50 | ///
51 | /// the wall-time in milliseconds. Its initial value is unspecified
52 | /// unless otherwise set.
53 | ///
54 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
55 | public static uint enet_time_get() => ENet.enet_time_get();
56 |
57 | ///
58 | /// Sets the current wall-time in milliseconds.
59 | ///
60 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
61 | public static void enet_time_set(uint newTimeBase) => ENet.enet_time_set(newTimeBase);
62 |
63 |
64 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
65 | public static ENetSocket enet_socket_create(ENetSocketType type, ENetHostOption option = 0) => ENet.enet_socket_create(type, option);
66 |
67 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
68 | public static int enet_socket_bind(ENetSocket socket, ENetAddress* address) => ENet.enet_socket_bind(socket, address);
69 |
70 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
71 | public static int enet_socket_get_address(nint socket, ENetAddress* address) => ENet.enet_socket_get_address(socket, address);
72 |
73 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
74 | public static int enet_socket_send(ENetSocket socket, ENetAddress* address, ENetBuffer* buffers, nuint bufferCount) => ENet.enet_socket_send(socket, address, buffers, bufferCount);
75 |
76 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
77 | public static int enet_socket_receive(ENetSocket socket, ENetAddress* address, ENetBuffer* buffers, nuint bufferCount) => ENet.enet_socket_receive(socket, address, buffers, bufferCount);
78 |
79 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
80 | public static int enet_socket_wait(nint socket, uint* condition, uint timeout) => ENet.enet_socket_wait(socket, condition, timeout);
81 |
82 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
83 | public static int enet_socket_set_option(nint socket, ENetSocketOption option, int value) => ENet.enet_socket_set_option(socket, option, value);
84 |
85 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
86 | public static void enet_socket_destroy(ENetSocket* socket) => ENet.enet_socket_destroy(socket);
87 |
88 | ///
89 | /// Attempts to parse the printable form of the IP address in the parameter hostName
90 | /// and sets the host field in the address parameter if successful.
91 | ///
92 | /// destination to store the parsed IP address
93 | /// IP address to parse
94 | ///
95 | ///
96 | /// -
97 | /// 0 on success
98 | ///
99 | /// -
100 | /// < 0 on failure
101 | ///
102 | ///
103 | /// the address of the given hostName in address on success
104 | ///
105 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
106 | public static int enet_address_set_host_ip(ENetAddress* address, ReadOnlySpan ip) => ENet.enet_address_set_host_ip(address, ip);
107 |
108 | ///
109 | /// Attempts to resolve the host named by the parameter hostName and sets
110 | /// the host field in the address parameter if successful.
111 | ///
112 | /// destination to store resolved address
113 | /// host name to lookup
114 | ///
115 | ///
116 | /// -
117 | /// 0 on success
118 | ///
119 | /// -
120 | /// < 0 on failure
121 | ///
122 | ///
123 | /// the address of the given hostName in address on success
124 | ///
125 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
126 | public static int enet_address_set_host(ENetAddress* address, ReadOnlySpan hostName) => ENet.enet_address_set_host(address, hostName);
127 |
128 | ///
129 | /// Gives the printable form of the IP address specified in the address parameter.
130 | ///
131 | /// address printed
132 | /// destination for name, must not be NULL
133 | /// maximum length of hostName.
134 | ///
135 | ///
136 | /// -
137 | /// 0 on success
138 | ///
139 | /// -
140 | /// < 0 on failure
141 | ///
142 | ///
143 | /// the null-terminated name of the host in hostName on success
144 | ///
145 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
146 | public static int enet_address_get_host_ip(ENetAddress* address, byte* ip, nuint nameLength) => ENet.enet_address_get_host_ip(address, ip, nameLength);
147 |
148 | ///
149 | /// Attempts to do a reverse lookup of the host field in the address parameter.
150 | ///
151 | /// address used for reverse lookup
152 | /// destination for name, must not be NULL
153 | /// maximum length of hostName.
154 | ///
155 | ///
156 | /// -
157 | /// 0 on success
158 | ///
159 | /// -
160 | /// < 0 on failure
161 | ///
162 | ///
163 | /// the null-terminated name of the host in hostName on success
164 | ///
165 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
166 | public static int enet_address_get_host(ENetAddress* address, byte* hostName, nuint nameLength) => ENet.enet_address_get_host(address, hostName, nameLength);
167 |
168 | ///
169 | /// Creates a packet that may be sent to a peer.
170 | ///
171 | /// initial contents of the packet's data; the packet's data will remain uninitialized if data is NULL.
172 | /// size of the data allocated for this packet
173 | /// flags for this packet as described for the ENetPacket structure.
174 | /// the packet on success, NULL on failure
175 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
176 | public static ENetPacket* enet_packet_create(void* data, nuint dataLength, uint flags) => ENet.enet_packet_create(data, dataLength, flags);
177 |
178 | ///
179 | /// Destroys the packet and deallocates its data.
180 | ///
181 | /// packet to be destroyed
182 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
183 | public static void enet_packet_destroy(ENetPacket* packet) => ENet.enet_packet_destroy(packet);
184 |
185 | ///
186 | /// Attempts to resize the data in the packet to length specified in the
187 | /// dataLength parameter.
188 | ///
189 | /// packet to resize
190 | /// new size for the packet data
191 | /// 0 on success, < 0 on failure
192 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
193 | public static int enet_packet_resize(ENetPacket* packet, nuint dataLength) => ENet.enet_packet_resize(packet, dataLength);
194 |
195 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
196 | public static uint enet_crc32(ENetBuffer* buffers, nuint bufferCount) => ENet.enet_crc32(buffers, bufferCount);
197 |
198 | ///
199 | /// Sends a ping request to an address.
200 | ///
201 | /// host ping the address
202 | /// destination for the ping request
203 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
204 | public static int enet_host_ping(ENetHost* host, ENetAddress* address) => ENet.enet_host_ping(host, address);
205 |
206 | ///
207 | /// Creates a host for communicating to peers.
208 | ///
209 | ///
210 | /// The address at which other peers may connect to this host. If NULL, then no peers may connect to
211 | /// the host.
212 | ///
213 | /// The maximum number of peers that should be allocated for the host.
214 | ///
215 | /// The maximum number of channels allowed; if 0, then this is equivalent to
216 | /// ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT
217 | ///
218 | ///
219 | /// Downstream bandwidth of the host in bytes/second; if 0, ENet will assume unlimited
220 | /// bandwidth.
221 | ///
222 | ///
223 | /// Upstream bandwidth of the host in bytes/second; if 0, ENet will assume unlimited
224 | /// bandwidth.
225 | ///
226 | ///
227 | ///
228 | /// -
229 | /// ENET_HOSTOPT_IPV4 (default): IPv4
230 | ///
231 | /// -
232 | /// ENET_HOSTOPT_IPV6_ONLY: IPv6-only
233 | ///
234 | /// -
235 | /// ENET_HOSTOPT_IPV6_DUALMODE: both IPv4 and IPv6
236 | ///
237 | ///
238 | ///
239 | /// The host on success and NULL on failure
240 | ///
241 | /// ENet will strategically drop packets on specific sides of a connection between hosts
242 | /// to ensure the host's bandwidth is not overwhelmed. The bandwidth parameters also determine
243 | /// the window size of a connection which limits the amount of reliable packets that may be in transit
244 | /// at any given time.
245 | ///
246 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
247 | public static ENetHost* enet_host_create(ENetAddress* address, nuint peerCount, nuint channelLimit, uint incomingBandwidth, uint outgoingBandwidth, ENetHostOption option = 0) => ENet.enet_host_create(address, peerCount, channelLimit, incomingBandwidth, outgoingBandwidth, option);
248 |
249 | ///
250 | /// Destroys the host and all resources associated with it.
251 | ///
252 | /// pointer to the host to destroy
253 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
254 | public static void enet_host_destroy(ENetHost* host) => ENet.enet_host_destroy(host);
255 |
256 | ///
257 | /// Initiates a connection to a foreign host.
258 | ///
259 | /// host seeking the connection
260 | /// destination for the connection
261 | /// number of channels to allocate
262 | /// user data supplied to the receiving host
263 | /// a peer representing the foreign host on success, NULL on failure
264 | ///
265 | /// The peer returned will have not completed the connection until enet_host_service()
266 | /// notifies of an ENET_EVENT_TYPE_CONNECT event for the peer.
267 | ///
268 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
269 | public static ENetPeer* enet_host_connect(ENetHost* host, ENetAddress* address, nuint channelCount, uint data) => ENet.enet_host_connect(host, address, channelCount, data);
270 |
271 | ///
272 | /// Checks for any queued events on the host and dispatches one if available.
273 | ///
274 | /// host to check for events
275 | /// an event structure where event details will be placed if available
276 | ///
277 | ///
278 | /// -
279 | /// > 0 if an event was dispatched
280 | ///
281 | /// -
282 | /// 0 if no events are available
283 | ///
284 | /// -
285 | /// < 0 on failure
286 | ///
287 | ///
288 | ///
289 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
290 | public static int enet_host_check_events(ENetHost* host, ENetEvent* @event) => ENet.enet_host_check_events(host, @event);
291 |
292 | ///
293 | /// Waits for events on the host specified and shuttles packets between
294 | /// the host and its peers.
295 | ///
296 | /// host to service
297 | ///
298 | /// an event structure where event details will be placed if one occurs
299 | /// if event == NULL then no events will be delivered
300 | ///
301 | /// number of milliseconds that ENet should wait for events
302 | ///
303 | ///
304 | /// -
305 | /// > 0 if an event occurred within the specified time limit
306 | ///
307 | /// -
308 | /// 0 if no event occurred
309 | ///
310 | /// -
311 | /// < 0 on failure
312 | ///
313 | ///
314 | ///
315 | ///
316 | /// enet_host_service should be called fairly regularly for adequate performance
317 | ///
318 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
319 | public static int enet_host_service(ENetHost* host, ENetEvent* @event, uint timeout) => ENet.enet_host_service(host, @event, timeout);
320 |
321 | ///
322 | /// Sends any queued packets on the host specified to its designated peers.
323 | ///
324 | /// host to flush
325 | ///
326 | /// This function need only be used in circumstances where one wishes to send queued packets earlier than in a call to
327 | /// enet_host_service().
328 | ///
329 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
330 | public static void enet_host_flush(ENetHost* host) => ENet.enet_host_flush(host);
331 |
332 | ///
333 | /// Queues a packet to be sent to all peers associated with the host.
334 | ///
335 | /// host on which to broadcast the packet
336 | /// channel on which to broadcast
337 | /// packet to broadcast
338 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
339 | public static void enet_host_broadcast(ENetHost* host, byte channelID, ENetPacket* packet) => ENet.enet_host_broadcast(host, channelID, packet);
340 |
341 | ///
342 | /// Sets the packet compressor the host should use to compress and decompress packets.
343 | ///
344 | /// host to enable or disable compression for
345 | /// callbacks for for the packet compressor; if NULL, then compression is disabled
346 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
347 | public static void enet_host_compress(ENetHost* host, ENetCompressor* compressor) => ENet.enet_host_compress(host, compressor);
348 |
349 | ///
350 | /// Limits the maximum allowed channels of future incoming connections.
351 | ///
352 | /// host to limit
353 | ///
354 | /// the maximum number of channels allowed; if 0, then this is equivalent to
355 | /// ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT
356 | ///
357 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
358 | public static void enet_host_channel_limit(ENetHost* host, nuint channelLimit) => ENet.enet_host_channel_limit(host, channelLimit);
359 |
360 | ///
361 | /// Adjusts the bandwidth limits of a host.
362 | ///
363 | /// host to adjust
364 | /// new incoming bandwidth
365 | /// new outgoing bandwidth
366 | ///
367 | /// the incoming and outgoing bandwidth parameters are identical in function to those
368 | /// specified in .
369 | ///
370 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
371 | public static void enet_host_bandwidth_limit(ENetHost* host, uint incomingBandwidth, uint outgoingBandwidth) => ENet.enet_host_bandwidth_limit(host, incomingBandwidth, outgoingBandwidth);
372 |
373 | ///
374 | /// Queues a packet to be sent.
375 | ///
376 | ///
377 | /// On success, ENet will assume ownership of the packet, and so enet_packet_destroy
378 | /// should not be called on it thereafter. On failure, the caller still must destroy
379 | /// the packet on its own as ENet has not queued the packet. The caller can also
380 | /// check the packet's referenceCount field after sending to check if ENet queued
381 | /// the packet and thus incremented the referenceCount.
382 | ///
383 | /// destination for the packet
384 | /// channel on which to send
385 | /// packet to send
386 | ///
387 | ///
388 | /// -
389 | /// 0 on success
390 | ///
391 | /// -
392 | /// < 0 on failure
393 | ///
394 | ///
395 | ///
396 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
397 | public static int enet_peer_send(ENetPeer* peer, byte channelID, ENetPacket* packet) => ENet.enet_peer_send(peer, channelID, packet);
398 |
399 | ///
400 | /// Attempts to dequeue any incoming queued packet.
401 | ///
402 | /// peer to dequeue packets from
403 | /// holds the channel ID of the channel the packet was received on success
404 | /// a pointer to the packet, or NULL if there are no available incoming queued packets
405 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
406 | public static ENetPacket* enet_peer_receive(ENetPeer* peer, byte* channelID) => ENet.enet_peer_receive(peer, channelID);
407 |
408 | ///
409 | /// Sends a ping request to a peer.
410 | ///
411 | /// destination for the ping request
412 | ///
413 | /// ping requests factor into the mean round trip time as designated by the
414 | /// roundTripTime field in the ENetPeer structure. ENet automatically pings all connected
415 | /// peers at regular intervals, however, this function may be called to ensure more
416 | /// frequent ping requests.
417 | ///
418 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
419 | public static void enet_peer_ping(ENetPeer* peer) => ENet.enet_peer_ping(peer);
420 |
421 | ///
422 | /// Sets the interval at which pings will be sent to a peer.
423 | ///
424 | ///
425 | /// Pings are used both to monitor the liveness of the connection and also to dynamically
426 | /// adjust the throttle during periods of low traffic so that the throttle has reasonable
427 | /// responsiveness during traffic spikes.
428 | ///
429 | /// the peer to adjust
430 | /// the interval at which to send pings; defaults to ENET_PEER_PING_INTERVAL if 0
431 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
432 | public static void enet_peer_ping_interval(ENetPeer* peer, uint pingInterval) => ENet.enet_peer_ping_interval(peer, pingInterval);
433 |
434 | ///
435 | /// Sets the timeout parameters for a peer.
436 | ///
437 | ///
438 | /// The timeout parameter control how and when a peer will timeout from a failure to acknowledge
439 | /// reliable traffic. Timeout values use an exponential backoff mechanism, where if a reliable
440 | /// packet is not acknowledge within some multiple of the average RTT plus a variance tolerance,
441 | /// the timeout will be doubled until it reaches a set limit. If the timeout is thus at this
442 | /// limit and reliable packets have been sent but not acknowledged within a certain minimum time
443 | /// period, the peer will be disconnected. Alternatively, if reliable packets have been sent
444 | /// but not acknowledged for a certain maximum time period, the peer will be disconnected regardless
445 | /// of the current timeout limit value.
446 | ///
447 | /// the peer to adjust
448 | /// the timeout limit; defaults to ENET_PEER_TIMEOUT_LIMIT if 0
449 | /// the timeout minimum; defaults to ENET_PEER_TIMEOUT_MINIMUM if 0
450 | /// the timeout maximum; defaults to ENET_PEER_TIMEOUT_MAXIMUM if 0
451 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
452 | public static void enet_peer_timeout(ENetPeer* peer, uint timeoutLimit, uint timeoutMinimum, uint timeoutMaximum) => ENet.enet_peer_timeout(peer, timeoutLimit, timeoutMinimum, timeoutMaximum);
453 |
454 | ///
455 | /// Forcefully disconnects a peer.
456 | ///
457 | /// peer to forcefully disconnect
458 | ///
459 | /// The foreign host represented by the peer is not notified of the disconnection and will timeout
460 | /// on its connection to the local host.
461 | ///
462 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
463 | public static void enet_peer_reset(ENetPeer* peer) => ENet.enet_peer_reset(peer);
464 |
465 | ///
466 | /// Request a disconnection from a peer.
467 | ///
468 | /// peer to request a disconnection
469 | /// data describing the disconnection
470 | ///
471 | /// An ENET_EVENT_DISCONNECT event will be generated by enet_host_service()
472 | /// once the disconnection is complete.
473 | ///
474 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
475 | public static void enet_peer_disconnect(ENetPeer* peer, uint data) => ENet.enet_peer_disconnect(peer, data);
476 |
477 | ///
478 | /// Force an immediate disconnection from a peer.
479 | ///
480 | /// peer to disconnect
481 | /// data describing the disconnection
482 | ///
483 | /// No ENET_EVENT_DISCONNECT event will be generated. The foreign peer is not
484 | /// guaranteed to receive the disconnect notification, and is reset immediately upon
485 | /// return from this function.
486 | ///
487 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
488 | public static void enet_peer_disconnect_now(ENetPeer* peer, uint data) => ENet.enet_peer_disconnect_now(peer, data);
489 |
490 | ///
491 | /// Request a disconnection from a peer, but only after all queued outgoing packets are sent.
492 | ///
493 | /// peer to request a disconnection
494 | /// data describing the disconnection
495 | ///
496 | /// An ENET_EVENT_DISCONNECT event will be generated by enet_host_service()
497 | /// once the disconnection is complete.
498 | ///
499 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
500 | public static void enet_peer_disconnect_later(ENetPeer* peer, uint data) => ENet.enet_peer_disconnect_later(peer, data);
501 |
502 | ///
503 | /// Configures throttle parameter for a peer.
504 | ///
505 | ///
506 | /// Unreliable packets are dropped by ENet in response to the varying conditions
507 | /// of the Internet connection to the peer. The throttle represents a probability
508 | /// that an unreliable packet should not be dropped and thus sent by ENet to the peer.
509 | /// The lowest mean round trip time from the sending of a reliable packet to the
510 | /// receipt of its acknowledgement is measured over an amount of time specified by
511 | /// the interval parameter in milliseconds. If a measured round trip time happens to
512 | /// be significantly less than the mean round trip time measured over the interval,
513 | /// then the throttle probability is increased to allow more traffic by an amount
514 | /// specified in the acceleration parameter, which is a ratio to the ENET_PEER_PACKET_THROTTLE_SCALE
515 | /// constant. If a measured round trip time happens to be significantly greater than
516 | /// the mean round trip time measured over the interval, then the throttle probability
517 | /// is decreased to limit traffic by an amount specified in the deceleration parameter, which
518 | /// is a ratio to the ENET_PEER_PACKET_THROTTLE_SCALE constant. When the throttle has
519 | /// a value of ENET_PEER_PACKET_THROTTLE_SCALE, no unreliable packets are dropped by
520 | /// ENet, and so 100% of all unreliable packets will be sent. When the throttle has a
521 | /// value of 0, all unreliable packets are dropped by ENet, and so 0% of all unreliable
522 | /// packets will be sent. Intermediate values for the throttle represent intermediate
523 | /// probabilities between 0% and 100% of unreliable packets being sent. The bandwidth
524 | /// limits of the local and foreign hosts are taken into account to determine a
525 | /// sensible limit for the throttle probability above which it should not raise even in
526 | /// the best of conditions.
527 | ///
528 | /// peer to configure
529 | ///
530 | /// interval, in milliseconds, over which to measure lowest mean RTT; the default value is
531 | /// ENET_PEER_PACKET_THROTTLE_INTERVAL.
532 | ///
533 | /// rate at which to increase the throttle probability as mean RTT declines
534 | /// rate at which to decrease the throttle probability as mean RTT increases
535 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
536 | public static void enet_peer_throttle_configure(ENetPeer* peer, uint interval, uint acceleration, uint deceleration) => ENet.enet_peer_throttle_configure(peer, interval, acceleration, deceleration);
537 | }
538 | }
--------------------------------------------------------------------------------
/enet-csharp/ENet/plugins/NativeSockets/Unix/Linux/c/LinuxSocketPal.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net.Sockets;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 | using System.Security;
6 | using System.Text;
7 | using static NativeSockets.UnixSocketPal;
8 |
9 | #pragma warning disable CA1401
10 | #pragma warning disable CS1591
11 | #pragma warning disable CS8981
12 | #pragma warning disable SYSLIB1054
13 |
14 | // ReSharper disable ALL
15 |
16 | namespace NativeSockets
17 | {
18 | [SuppressUnmanagedCodeSecurity]
19 | public static unsafe class LinuxSocketPal
20 | {
21 | public const ushort ADDRESS_FAMILY_INTER_NETWORK_V6 = 10;
22 |
23 | public static bool IsSupported { get; } = RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
24 |
25 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
26 | public static SocketError GetLastSocketError() => UnixSocketPal.GetLastSocketError();
27 |
28 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
29 | public static SocketError Initialize() => SocketError.Success;
30 |
31 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
32 | public static SocketError Cleanup() => SocketError.Success;
33 |
34 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
35 | public static nint Create(bool ipv6)
36 | {
37 | int family = ipv6 ? ADDRESS_FAMILY_INTER_NETWORK_V6 : (int)AddressFamily.InterNetwork;
38 | nint _socket = socket(family, (int)SocketType.Dgram, 0);
39 | return _socket;
40 | }
41 |
42 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
43 | public static SocketError Close(nint socket)
44 | {
45 | SocketError errorCode = close((int)socket);
46 | return errorCode;
47 | }
48 |
49 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
50 | public static SocketError SetDualMode6(nint socket, bool dualMode)
51 | {
52 | int optionValue = dualMode ? 0 : 1;
53 | SocketError errorCode = SetOption(socket, SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, &optionValue);
54 | return errorCode;
55 | }
56 |
57 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
58 | public static SocketError Bind4(nint socket, sockaddr_in* socketAddress)
59 | {
60 | sockaddr_in __socketAddress_native;
61 | if (socketAddress == null)
62 | {
63 | __socketAddress_native = new sockaddr_in();
64 | __socketAddress_native.sin_family = (ushort)AddressFamily.InterNetwork;
65 | SetIP4(&__socketAddress_native, "0.0.0.0");
66 | }
67 | else
68 | {
69 | __socketAddress_native = *socketAddress;
70 | __socketAddress_native.sin_port = WinSock2.HOST_TO_NET_16(socketAddress->sin_port);
71 | }
72 |
73 | SocketError errorCode = bind((int)socket, (sockaddr*)&__socketAddress_native, sizeof(sockaddr_in));
74 | return errorCode;
75 | }
76 |
77 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
78 | public static SocketError Bind6(nint socket, sockaddr_in6* socketAddress)
79 | {
80 | sockaddr_in6 __socketAddress_native;
81 | if (socketAddress == null)
82 | {
83 | __socketAddress_native = new sockaddr_in6();
84 | __socketAddress_native.sin6_family = ADDRESS_FAMILY_INTER_NETWORK_V6;
85 | SetIP6(&__socketAddress_native, "::");
86 | }
87 | else
88 | {
89 | __socketAddress_native = *socketAddress;
90 | __socketAddress_native.sin6_port = WinSock2.HOST_TO_NET_16(socketAddress->sin6_port);
91 | }
92 |
93 | SocketError errorCode = bind((int)socket, (sockaddr*)&__socketAddress_native, sizeof(sockaddr_in6));
94 | return errorCode;
95 | }
96 |
97 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
98 | public static SocketError Connect4(nint socket, sockaddr_in* socketAddress)
99 | {
100 | sockaddr_in __socketAddress_native = *socketAddress;
101 | __socketAddress_native.sin_port = WinSock2.HOST_TO_NET_16(socketAddress->sin_port);
102 |
103 | SocketError errorCode = connect((int)socket, (sockaddr*)&__socketAddress_native, sizeof(sockaddr_in));
104 | return errorCode;
105 | }
106 |
107 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
108 | public static SocketError Connect6(nint socket, sockaddr_in6* socketAddress)
109 | {
110 | sockaddr_in6 __socketAddress_native = *socketAddress;
111 | __socketAddress_native.sin6_port = WinSock2.HOST_TO_NET_16(socketAddress->sin6_port);
112 |
113 | SocketError errorCode = connect((int)socket, (sockaddr*)&__socketAddress_native, sizeof(sockaddr_in6));
114 | return errorCode;
115 | }
116 |
117 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
118 | public static SocketError SetOption(nint socket, SocketOptionLevel optionLevel, SocketOptionName optionName, int* optionValue, int optionLength = sizeof(int))
119 | {
120 | SocketError errorCode = setsockopt((int)socket, optionLevel, optionName, optionValue, optionLength);
121 | return errorCode == SocketError.SocketError ? GetLastSocketError() : SocketError.Success;
122 | }
123 |
124 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
125 | public static SocketError GetOption(nint socket, SocketOptionLevel level, SocketOptionName optionName, int* optionValue, int* optionLength = null)
126 | {
127 | int num = sizeof(int);
128 | if (optionLength == null)
129 | optionLength = #
130 |
131 | SocketError errorCode = getsockopt((int)socket, (int)level, (int)optionName, (byte*)optionValue, optionLength);
132 | return errorCode == SocketError.SocketError ? GetLastSocketError() : SocketError.Success;
133 | }
134 |
135 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
136 | public static SocketError SetBlocking(nint socket, bool shouldBlock)
137 | {
138 | int flags = fcntl((int)socket, 3, 0);
139 | if (flags == -1)
140 | return GetLastSocketError();
141 |
142 | flags = shouldBlock ? flags & ~2048 : flags | 2048;
143 | if (fcntl((int)socket, 4, flags) == -1)
144 | return GetLastSocketError();
145 |
146 | return SocketError.Success;
147 | }
148 |
149 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
150 | public static SocketError Poll(nint socket, int microseconds, SelectMode mode, out bool status)
151 | {
152 | PollEvents inEvent = 0;
153 | switch (mode)
154 | {
155 | case SelectMode.SelectRead:
156 | inEvent = PollEvents.POLLIN;
157 | break;
158 | case SelectMode.SelectWrite:
159 | inEvent = PollEvents.POLLOUT;
160 | break;
161 | case SelectMode.SelectError:
162 | inEvent = PollEvents.POLLPRI;
163 | break;
164 | }
165 |
166 | int milliseconds = microseconds == -1 ? -1 : microseconds / 1000;
167 |
168 | pollfd fd;
169 | fd.fd = (int)socket;
170 | fd.events = (short)inEvent;
171 | fd.revents = 0;
172 |
173 | int errno = poll(&fd, 1, milliseconds);
174 | if (errno == -1)
175 | {
176 | status = false;
177 | return GetLastSocketError();
178 | }
179 |
180 | PollEvents outEvents = (PollEvents)fd.revents;
181 | switch (mode)
182 | {
183 | case SelectMode.SelectRead:
184 | status = (outEvents & (PollEvents.POLLIN | PollEvents.POLLHUP)) != 0;
185 | break;
186 | case SelectMode.SelectWrite:
187 | status = (outEvents & PollEvents.POLLOUT) != 0;
188 | break;
189 | case SelectMode.SelectError:
190 | status = (outEvents & (PollEvents.POLLERR | PollEvents.POLLPRI)) != 0;
191 | break;
192 | default:
193 | status = false;
194 | break;
195 | }
196 |
197 | return SocketError.Success;
198 | }
199 |
200 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
201 | public static int Send(nint socket, void* buffer, int length)
202 | {
203 | int num = send((int)socket, (byte*)buffer, length, SocketFlags.None);
204 | return num;
205 | }
206 |
207 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
208 | public static int SendTo4(nint socket, void* buffer, int length, sockaddr_in* socketAddress)
209 | {
210 | if (socketAddress != null)
211 | {
212 | sockaddr_in __socketAddress_native = *socketAddress;
213 | __socketAddress_native.sin_port = WinSock2.HOST_TO_NET_16(socketAddress->sin_port);
214 | return sendto((int)socket, (byte*)buffer, length, SocketFlags.None, (byte*)&__socketAddress_native, sizeof(sockaddr_in));
215 | }
216 |
217 | int num = send((int)socket, (byte*)buffer, length, SocketFlags.None);
218 | return num;
219 | }
220 |
221 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
222 | public static int SendTo6(nint socket, void* buffer, int length, sockaddr_in6* socketAddress)
223 | {
224 | if (socketAddress != null)
225 | {
226 | sockaddr_in6 __socketAddress_native = *socketAddress;
227 | __socketAddress_native.sin6_port = WinSock2.HOST_TO_NET_16(socketAddress->sin6_port);
228 | return sendto((int)socket, (byte*)buffer, length, SocketFlags.None, (byte*)&__socketAddress_native, sizeof(sockaddr_in6));
229 | }
230 |
231 | int num = send((int)socket, (byte*)buffer, length, SocketFlags.None);
232 | return num;
233 | }
234 |
235 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
236 | public static int Receive(nint socket, void* buffer, int length)
237 | {
238 | int num = recv((int)socket, (byte*)buffer, length, SocketFlags.None);
239 | return num;
240 | }
241 |
242 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
243 | public static int ReceiveFrom4(nint socket, void* buffer, int length, sockaddr_in* socketAddress)
244 | {
245 | sockaddr_storage addressStorage = new sockaddr_storage();
246 | int socketAddressSize = sizeof(sockaddr_storage);
247 |
248 | int num = recvfrom((int)socket, (byte*)buffer, length, SocketFlags.None, (byte*)&addressStorage, &socketAddressSize);
249 |
250 | if (num > 0 && socketAddress != null)
251 | {
252 | sockaddr_in* __socketAddress_native = (sockaddr_in*)&addressStorage;
253 | *socketAddress = *__socketAddress_native;
254 | socketAddress->sin_port = WinSock2.NET_TO_HOST_16(__socketAddress_native->sin_port);
255 | }
256 |
257 | return num;
258 | }
259 |
260 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
261 | public static int ReceiveFrom6(nint socket, void* buffer, int length, sockaddr_in6* socketAddress)
262 | {
263 | sockaddr_storage addressStorage = new sockaddr_storage();
264 | int socketAddressSize = sizeof(sockaddr_storage);
265 |
266 | int num = recvfrom((int)socket, (byte*)buffer, length, SocketFlags.None, (byte*)&addressStorage, &socketAddressSize);
267 |
268 | if (num > 0 && socketAddress != null)
269 | {
270 | socketAddress->sin6_family.family = ADDRESS_FAMILY_INTER_NETWORK_V6;
271 | if (addressStorage.ss_family.family == (int)AddressFamily.InterNetwork)
272 | {
273 | sockaddr_in* __socketAddress_native = (sockaddr_in*)&addressStorage;
274 | Unsafe.InitBlockUnaligned(socketAddress->sin6_addr, 0, 8);
275 | Unsafe.WriteUnaligned(socketAddress->sin6_addr + 8, WinSock2.ADDRESS_FAMILY_INTER_NETWORK_V4_MAPPED_V6);
276 | Unsafe.WriteUnaligned(socketAddress->sin6_addr + 12, __socketAddress_native->sin_addr);
277 | socketAddress->sin6_port = WinSock2.NET_TO_HOST_16(__socketAddress_native->sin_port);
278 | socketAddress->sin6_scope_id = 0;
279 | }
280 | else if (addressStorage.ss_family.family == (int)ADDRESS_FAMILY_INTER_NETWORK_V6)
281 | {
282 | sockaddr_in6* __socketAddress_native = (sockaddr_in6*)&addressStorage;
283 | Unsafe.CopyBlockUnaligned(socketAddress->sin6_addr, __socketAddress_native->sin6_addr, 20);
284 | socketAddress->sin6_port = WinSock2.NET_TO_HOST_16(__socketAddress_native->sin6_port);
285 | }
286 | }
287 |
288 | return num;
289 | }
290 |
291 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
292 | public static int WSASend(nint socket, WSABuffer* buffers, int bufferCount)
293 | {
294 | iovec* msg_iov = stackalloc iovec[bufferCount];
295 | for (int i = 0; i < bufferCount; ++i)
296 | {
297 | msg_iov[i].iov_base = buffers[i].Pointer;
298 | msg_iov[i].iov_len = buffers[i].Length;
299 | }
300 |
301 | msghdr msg;
302 | msg.msg_name = null;
303 | msg.msg_namelen = 0;
304 | msg.msg_iov = msg_iov;
305 | msg.msg_iovlen = bufferCount;
306 | msg.msg_control = null;
307 | msg.msg_controllen = 0;
308 | msg.msg_flags = 0;
309 |
310 | int num = (int)sendmsg((int)socket, &msg, 0);
311 | return num;
312 | }
313 |
314 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
315 | public static int WSASendTo4(nint socket, WSABuffer* buffers, int bufferCount, sockaddr_in* socketAddress)
316 | {
317 | iovec* msg_iov = stackalloc iovec[bufferCount];
318 | for (int i = 0; i < bufferCount; ++i)
319 | {
320 | msg_iov[i].iov_base = buffers[i].Pointer;
321 | msg_iov[i].iov_len = buffers[i].Length;
322 | }
323 |
324 | sockaddr_in __socketAddress_native;
325 |
326 | msghdr msg;
327 | msg.msg_iov = msg_iov;
328 | msg.msg_iovlen = bufferCount;
329 | msg.msg_control = null;
330 | msg.msg_controllen = 0;
331 | msg.msg_flags = 0;
332 |
333 | if (socketAddress != null)
334 | {
335 | __socketAddress_native = *socketAddress;
336 | __socketAddress_native.sin_port = WinSock2.HOST_TO_NET_16(socketAddress->sin_port);
337 |
338 | msg.msg_name = &__socketAddress_native;
339 | msg.msg_namelen = 16;
340 | }
341 | else
342 | {
343 | msg.msg_name = null;
344 | msg.msg_namelen = 0;
345 | }
346 |
347 | int num = (int)sendmsg((int)socket, &msg, 0);
348 | return num;
349 | }
350 |
351 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
352 | public static int WSASendTo6(nint socket, WSABuffer* buffers, int bufferCount, sockaddr_in6* socketAddress)
353 | {
354 | iovec* msg_iov = stackalloc iovec[bufferCount];
355 | for (int i = 0; i < bufferCount; ++i)
356 | {
357 | msg_iov[i].iov_base = buffers[i].Pointer;
358 | msg_iov[i].iov_len = buffers[i].Length;
359 | }
360 |
361 | sockaddr_in6 __socketAddress_native;
362 |
363 | msghdr msg;
364 | msg.msg_iov = msg_iov;
365 | msg.msg_iovlen = bufferCount;
366 | msg.msg_control = null;
367 | msg.msg_controllen = 0;
368 | msg.msg_flags = 0;
369 |
370 | if (socketAddress != null)
371 | {
372 | __socketAddress_native = *socketAddress;
373 | __socketAddress_native.sin6_port = WinSock2.HOST_TO_NET_16(socketAddress->sin6_port);
374 |
375 | msg.msg_name = &__socketAddress_native;
376 | msg.msg_namelen = 28;
377 | }
378 | else
379 | {
380 | msg.msg_name = null;
381 | msg.msg_namelen = 0;
382 | }
383 |
384 | int num = (int)sendmsg((int)socket, &msg, 0);
385 | return num;
386 | }
387 |
388 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
389 | public static int WSAReceive(nint socket, WSABuffer* buffers, int bufferCount)
390 | {
391 | iovec* msg_iov = stackalloc iovec[bufferCount];
392 | for (int i = 0; i < bufferCount; ++i)
393 | {
394 | msg_iov[i].iov_base = buffers[i].Pointer;
395 | msg_iov[i].iov_len = buffers[i].Length;
396 | }
397 |
398 | msghdr msg;
399 | msg.msg_name = null;
400 | msg.msg_namelen = 0;
401 | msg.msg_iov = msg_iov;
402 | msg.msg_iovlen = bufferCount;
403 | msg.msg_control = null;
404 | msg.msg_controllen = 0;
405 | msg.msg_flags = 0;
406 |
407 | int num = (int)recvmsg((int)socket, &msg, 0);
408 |
409 | if (msg.msg_flags != 0)
410 | return -1;
411 |
412 | return num;
413 | }
414 |
415 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
416 | public static int WSAReceiveFrom4(nint socket, WSABuffer* buffers, int bufferCount, sockaddr_in* socketAddress)
417 | {
418 | iovec* msg_iov = stackalloc iovec[bufferCount];
419 | for (int i = 0; i < bufferCount; ++i)
420 | {
421 | msg_iov[i].iov_base = buffers[i].Pointer;
422 | msg_iov[i].iov_len = buffers[i].Length;
423 | }
424 |
425 | sockaddr_storage addressStorage = new sockaddr_storage();
426 |
427 | msghdr msg;
428 | msg.msg_name = &addressStorage;
429 | msg.msg_namelen = (nuint)sizeof(sockaddr_storage);
430 | msg.msg_iov = msg_iov;
431 | msg.msg_iovlen = bufferCount;
432 | msg.msg_control = null;
433 | msg.msg_controllen = 0;
434 | msg.msg_flags = 0;
435 |
436 | int num = (int)recvmsg((int)socket, &msg, 0);
437 |
438 | if (msg.msg_flags != 0)
439 | return -1;
440 |
441 | if (num > 0 && socketAddress != null)
442 | {
443 | sockaddr_in* __socketAddress_native = (sockaddr_in*)&addressStorage;
444 | *socketAddress = *__socketAddress_native;
445 | socketAddress->sin_port = WinSock2.NET_TO_HOST_16(__socketAddress_native->sin_port);
446 | }
447 |
448 | return num;
449 | }
450 |
451 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
452 | public static int WSAReceiveFrom6(nint socket, WSABuffer* buffers, int bufferCount, sockaddr_in6* socketAddress)
453 | {
454 | iovec* msg_iov = stackalloc iovec[bufferCount];
455 | for (int i = 0; i < bufferCount; ++i)
456 | {
457 | msg_iov[i].iov_base = buffers[i].Pointer;
458 | msg_iov[i].iov_len = buffers[i].Length;
459 | }
460 |
461 | sockaddr_storage addressStorage = new sockaddr_storage();
462 |
463 | msghdr msg;
464 | msg.msg_name = &addressStorage;
465 | msg.msg_namelen = (nuint)sizeof(sockaddr_storage);
466 | msg.msg_iov = msg_iov;
467 | msg.msg_iovlen = bufferCount;
468 | msg.msg_control = null;
469 | msg.msg_controllen = 0;
470 | msg.msg_flags = 0;
471 |
472 | int num = (int)recvmsg((int)socket, &msg, 0);
473 |
474 | if (msg.msg_flags != 0)
475 | return -1;
476 |
477 | if (num > 0 && socketAddress != null)
478 | {
479 | socketAddress->sin6_family.family = ADDRESS_FAMILY_INTER_NETWORK_V6;
480 | if (addressStorage.ss_family.family == (int)AddressFamily.InterNetwork)
481 | {
482 | sockaddr_in* __socketAddress_native = (sockaddr_in*)&addressStorage;
483 | Unsafe.InitBlockUnaligned(socketAddress->sin6_addr, 0, 8);
484 | Unsafe.WriteUnaligned(socketAddress->sin6_addr + 8, WinSock2.ADDRESS_FAMILY_INTER_NETWORK_V4_MAPPED_V6);
485 | Unsafe.WriteUnaligned(socketAddress->sin6_addr + 12, __socketAddress_native->sin_addr);
486 | socketAddress->sin6_port = WinSock2.NET_TO_HOST_16(__socketAddress_native->sin_port);
487 | socketAddress->sin6_scope_id = 0;
488 | }
489 | else if (addressStorage.ss_family.family == (int)ADDRESS_FAMILY_INTER_NETWORK_V6)
490 | {
491 | sockaddr_in6* __socketAddress_native = (sockaddr_in6*)&addressStorage;
492 | Unsafe.CopyBlockUnaligned(socketAddress->sin6_addr, __socketAddress_native->sin6_addr, 20);
493 | socketAddress->sin6_port = WinSock2.NET_TO_HOST_16(__socketAddress_native->sin6_port);
494 | }
495 | }
496 |
497 | return num;
498 | }
499 |
500 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
501 | public static SocketError GetName4(nint socket, sockaddr_in* socketAddress)
502 | {
503 | sockaddr_storage addressStorage = new sockaddr_storage();
504 | int socketAddressSize = sizeof(sockaddr_storage);
505 | SocketError errorCode = getsockname((int)socket, (sockaddr*)&addressStorage, &socketAddressSize);
506 | if (errorCode == SocketError.Success)
507 | {
508 | socketAddress->sin_family = addressStorage.ss_family;
509 | sockaddr_in* __socketAddress_native = (sockaddr_in*)&addressStorage;
510 | *socketAddress = *__socketAddress_native;
511 | socketAddress->sin_port = WinSock2.NET_TO_HOST_16(__socketAddress_native->sin_port);
512 | }
513 |
514 | return errorCode;
515 | }
516 |
517 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
518 | public static SocketError GetName6(nint socket, sockaddr_in6* socketAddress)
519 | {
520 | sockaddr_storage addressStorage = new sockaddr_storage();
521 | int socketAddressSize = sizeof(sockaddr_storage);
522 | SocketError errorCode = getsockname((int)socket, (sockaddr*)&addressStorage, &socketAddressSize);
523 | if (errorCode == SocketError.Success)
524 | {
525 | socketAddress->sin6_family = addressStorage.ss_family;
526 | if (addressStorage.ss_family.family == (int)AddressFamily.InterNetwork)
527 | {
528 | sockaddr_in* __socketAddress_native = (sockaddr_in*)&addressStorage;
529 | Unsafe.InitBlockUnaligned(socketAddress->sin6_addr, 0, 8);
530 | Unsafe.WriteUnaligned(socketAddress->sin6_addr + 8, WinSock2.ADDRESS_FAMILY_INTER_NETWORK_V4_MAPPED_V6);
531 | Unsafe.WriteUnaligned(socketAddress->sin6_addr + 12, __socketAddress_native->sin_addr);
532 | socketAddress->sin6_port = WinSock2.NET_TO_HOST_16(__socketAddress_native->sin_port);
533 | }
534 | else if (addressStorage.ss_family.family == (int)ADDRESS_FAMILY_INTER_NETWORK_V6)
535 | {
536 | sockaddr_in6* __socketAddress_native = (sockaddr_in6*)&addressStorage;
537 | Unsafe.CopyBlockUnaligned(socketAddress->sin6_addr, __socketAddress_native->sin6_addr, 16);
538 | socketAddress->sin6_port = WinSock2.NET_TO_HOST_16(__socketAddress_native->sin6_port);
539 | }
540 | }
541 |
542 | return errorCode;
543 | }
544 |
545 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
546 | public static SocketError SetIP4(sockaddr_in* socketAddress, ReadOnlySpan ip)
547 | {
548 | void* pAddrBuf = &socketAddress->sin_addr;
549 |
550 | int byteCount = Encoding.ASCII.GetByteCount(ip);
551 | Span buffer = stackalloc byte[byteCount + 1];
552 | Encoding.ASCII.GetBytes(ip, buffer);
553 | buffer[byteCount] = 0;
554 |
555 | int addressFamily = (int)AddressFamily.InterNetwork;
556 |
557 | int error = inet_pton(addressFamily, Unsafe.AsPointer(ref MemoryMarshal.GetReference(buffer)), pAddrBuf);
558 |
559 | switch (error)
560 | {
561 | case 1:
562 | return SocketError.Success;
563 | case 0:
564 | return SocketError.InvalidArgument;
565 | default:
566 | return SocketError.Fault;
567 | }
568 | }
569 |
570 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
571 | public static SocketError SetIP6(sockaddr_in6* socketAddress, ReadOnlySpan ip)
572 | {
573 | void* pAddrBuf = socketAddress->sin6_addr;
574 |
575 | int byteCount = Encoding.ASCII.GetByteCount(ip);
576 | Span buffer = stackalloc byte[byteCount + 1];
577 | Encoding.ASCII.GetBytes(ip, buffer);
578 | buffer[byteCount] = 0;
579 |
580 | int addressFamily = (int)ADDRESS_FAMILY_INTER_NETWORK_V6;
581 | if (ip.IndexOf(':') < 0)
582 | {
583 | addressFamily = (int)AddressFamily.InterNetwork;
584 | Unsafe.InitBlockUnaligned(pAddrBuf, 0, 8);
585 | Unsafe.WriteUnaligned((byte*)pAddrBuf + 8, WinSock2.ADDRESS_FAMILY_INTER_NETWORK_V4_MAPPED_V6);
586 | pAddrBuf = (byte*)pAddrBuf + 12;
587 | }
588 |
589 | int error = inet_pton(addressFamily, Unsafe.AsPointer(ref MemoryMarshal.GetReference(buffer)), pAddrBuf);
590 |
591 | switch (error)
592 | {
593 | case 1:
594 | return SocketError.Success;
595 | case 0:
596 | return SocketError.InvalidArgument;
597 | default:
598 | return SocketError.Fault;
599 | }
600 | }
601 |
602 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
603 | public static SocketError GetIP4(sockaddr_in* socketAddress, Span buffer)
604 | {
605 | void* pAddrBuf = &socketAddress->sin_addr;
606 |
607 | if (inet_ntop((int)AddressFamily.InterNetwork, pAddrBuf, ref MemoryMarshal.GetReference(buffer), (nuint)buffer.Length) == null)
608 | return SocketError.Fault;
609 |
610 | return SocketError.Success;
611 | }
612 |
613 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
614 | public static SocketError GetIP6(sockaddr_in6* socketAddress, Span buffer)
615 | {
616 | void* pAddrBuf = socketAddress->sin6_addr;
617 |
618 | ref int reference = ref Unsafe.AsRef(pAddrBuf);
619 | if (Unsafe.Add(ref reference, 2) == WinSock2.ADDRESS_FAMILY_INTER_NETWORK_V4_MAPPED_V6 && reference == 0 && Unsafe.Add(ref reference, 1) == 0)
620 | {
621 | if (inet_ntop((int)AddressFamily.InterNetwork, (byte*)pAddrBuf + 12, ref MemoryMarshal.GetReference(buffer), (nuint)buffer.Length) == null)
622 | return SocketError.Fault;
623 | }
624 | else if (inet_ntop((int)ADDRESS_FAMILY_INTER_NETWORK_V6, pAddrBuf, ref MemoryMarshal.GetReference(buffer), (nuint)buffer.Length) == null)
625 | {
626 | return SocketError.Fault;
627 | }
628 |
629 | return SocketError.Success;
630 | }
631 |
632 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
633 | public static SocketError SetHostName4(sockaddr_in* socketAddress, ReadOnlySpan hostName)
634 | {
635 | void* pAddrBuf = &socketAddress->sin_addr;
636 |
637 | int byteCount = Encoding.ASCII.GetByteCount(hostName);
638 | Span buffer = stackalloc byte[byteCount + 1];
639 | Encoding.ASCII.GetBytes(hostName, buffer);
640 | buffer[byteCount] = 0;
641 |
642 | addrinfo addressInfo = new addrinfo();
643 | addrinfo* hint, results = null;
644 |
645 | if (getaddrinfo((byte*)Unsafe.AsPointer(ref MemoryMarshal.GetReference(buffer)), null, &addressInfo, &results) != 0)
646 | return SocketError.Fault;
647 |
648 | for (hint = results; hint != null; hint = hint->ai_next)
649 | {
650 | if (hint->ai_addr != null && hint->ai_addrlen >= (nuint)sizeof(sockaddr_in))
651 | {
652 | if (hint->ai_family == (int)AddressFamily.InterNetwork)
653 | {
654 | sockaddr_in* __socketAddress_native = (sockaddr_in*)hint->ai_addr;
655 |
656 | *socketAddress = *__socketAddress_native;
657 | socketAddress->sin_port = WinSock2.NET_TO_HOST_16(__socketAddress_native->sin_port);
658 |
659 | freeaddrinfo(results);
660 |
661 | return 0;
662 | }
663 | }
664 | }
665 |
666 | if (results != null)
667 | freeaddrinfo(results);
668 |
669 | const int addressFamily = (int)AddressFamily.InterNetwork;
670 |
671 | int error = inet_pton(addressFamily, Unsafe.AsPointer(ref MemoryMarshal.GetReference(buffer)), pAddrBuf);
672 |
673 | switch (error)
674 | {
675 | case 1:
676 | return SocketError.Success;
677 | case 0:
678 | return SocketError.InvalidArgument;
679 | default:
680 | return SocketError.Fault;
681 | }
682 | }
683 |
684 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
685 | public static SocketError SetHostName6(sockaddr_in6* socketAddress, ReadOnlySpan hostName)
686 | {
687 | void* pAddrBuf = socketAddress->sin6_addr;
688 |
689 | int byteCount = Encoding.ASCII.GetByteCount(hostName);
690 | Span buffer = stackalloc byte[byteCount + 1];
691 | Encoding.ASCII.GetBytes(hostName, buffer);
692 | buffer[byteCount] = 0;
693 |
694 | addrinfo addressInfo = new addrinfo();
695 | addrinfo* hint, results = null;
696 |
697 | if (getaddrinfo((byte*)Unsafe.AsPointer(ref MemoryMarshal.GetReference(buffer)), null, &addressInfo, &results) != 0)
698 | return SocketError.Fault;
699 |
700 | for (hint = results; hint != null; hint = hint->ai_next)
701 | {
702 | if (hint->ai_addr != null && hint->ai_addrlen >= (nuint)sizeof(sockaddr_in))
703 | {
704 | if (hint->ai_family == (int)AddressFamily.InterNetwork)
705 | {
706 | sockaddr_in* __socketAddress_native = (sockaddr_in*)hint->ai_addr;
707 |
708 | Unsafe.InitBlockUnaligned(pAddrBuf, 0, 8);
709 | Unsafe.WriteUnaligned((byte*)pAddrBuf + 8, WinSock2.ADDRESS_FAMILY_INTER_NETWORK_V4_MAPPED_V6);
710 | Unsafe.WriteUnaligned((byte*)pAddrBuf + 12, __socketAddress_native->sin_addr.S_addr);
711 |
712 | freeaddrinfo(results);
713 |
714 | return 0;
715 | }
716 |
717 | if (hint->ai_family == (int)ADDRESS_FAMILY_INTER_NETWORK_V6)
718 | {
719 | sockaddr_in6* __socketAddress_native = (sockaddr_in6*)hint->ai_addr;
720 |
721 | Unsafe.CopyBlockUnaligned(pAddrBuf, __socketAddress_native->sin6_addr, 16);
722 |
723 | freeaddrinfo(results);
724 |
725 | return 0;
726 | }
727 | }
728 | }
729 |
730 | if (results != null)
731 | freeaddrinfo(results);
732 |
733 | int addressFamily = (int)ADDRESS_FAMILY_INTER_NETWORK_V6;
734 | if (buffer.IndexOf((byte)':') == -1)
735 | {
736 | addressFamily = (int)AddressFamily.InterNetwork;
737 | Unsafe.InitBlockUnaligned(pAddrBuf, 0, 8);
738 | Unsafe.WriteUnaligned((byte*)pAddrBuf + 8, WinSock2.ADDRESS_FAMILY_INTER_NETWORK_V4_MAPPED_V6);
739 | pAddrBuf = (byte*)pAddrBuf + 12;
740 | }
741 |
742 | int error = inet_pton(addressFamily, Unsafe.AsPointer(ref MemoryMarshal.GetReference(buffer)), pAddrBuf);
743 |
744 | switch (error)
745 | {
746 | case 1:
747 | return SocketError.Success;
748 | case 0:
749 | return SocketError.InvalidArgument;
750 | default:
751 | return SocketError.Fault;
752 | }
753 | }
754 |
755 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
756 | public static SocketError GetHostName4(sockaddr_in* socketAddress, Span buffer)
757 | {
758 | sockaddr_in __socketAddress_native = *socketAddress;
759 |
760 | __socketAddress_native.sin_port = WinSock2.HOST_TO_NET_16(socketAddress->sin_port);
761 |
762 | int error = getnameinfo((sockaddr*)&__socketAddress_native, sizeof(sockaddr_in), ref MemoryMarshal.GetReference(buffer), (ulong)buffer.Length, null, 0, 0x4);
763 |
764 | if (error == 0)
765 | {
766 | if (Unsafe.AsPointer(ref MemoryMarshal.GetReference(buffer)) != null && buffer.Length > 0 && buffer.IndexOf((byte)'\0') < 0)
767 | return SocketError.Fault;
768 |
769 | return SocketError.Success;
770 | }
771 |
772 | if (error != 0x2AF9L)
773 | return SocketError.Fault;
774 |
775 | return GetIP4(socketAddress, buffer);
776 | }
777 |
778 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
779 | public static SocketError GetHostName6(sockaddr_in6* socketAddress, Span buffer)
780 | {
781 | sockaddr_in6 __socketAddress_native = *socketAddress;
782 |
783 | __socketAddress_native.sin6_port = WinSock2.HOST_TO_NET_16(socketAddress->sin6_port);
784 |
785 | int error = getnameinfo((sockaddr*)&__socketAddress_native, sizeof(sockaddr_in6), ref MemoryMarshal.GetReference(buffer), (ulong)buffer.Length, null, 0, 0x4);
786 |
787 | if (error == 0)
788 | {
789 | if (Unsafe.AsPointer(ref MemoryMarshal.GetReference(buffer)) != null && buffer.Length > 0 && buffer.IndexOf((byte)'\0') < 0)
790 | return SocketError.Fault;
791 |
792 | return SocketError.Success;
793 | }
794 |
795 | if (error != 0x2AF9L)
796 | return SocketError.Fault;
797 |
798 | return GetIP6(socketAddress, buffer);
799 | }
800 | }
801 | }
--------------------------------------------------------------------------------