From 507eba34a8894729d0b23d3d52a0b9b22c84666f Mon Sep 17 00:00:00 2001
From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com>
Date: Sat, 9 Oct 2021 13:52:53 -0700
Subject: [PATCH] fix: Replaces PollGroup with nuget (#823)
---
.../Server/Network/PollGroup/EPollGroup.cs | 197 --------------
.../Network/PollGroup/KQueuePollGroup.cs | 241 ------------------
.../Server/Network/PollGroup/PollGroup.cs | 41 ---
Projects/Server/Server.csproj | 29 +--
Projects/Server/wepoll.dll | Bin 21504 -> 0 bytes
5 files changed, 13 insertions(+), 495 deletions(-)
delete mode 100755 Projects/Server/Network/PollGroup/EPollGroup.cs
delete mode 100644 Projects/Server/Network/PollGroup/KQueuePollGroup.cs
delete mode 100644 Projects/Server/Network/PollGroup/PollGroup.cs
delete mode 100644 Projects/Server/wepoll.dll
diff --git a/Projects/Server/Network/PollGroup/EPollGroup.cs b/Projects/Server/Network/PollGroup/EPollGroup.cs
deleted file mode 100755
index bc51526e8..000000000
--- a/Projects/Server/Network/PollGroup/EPollGroup.cs
+++ /dev/null
@@ -1,197 +0,0 @@
-/*************************************************************************
- * ModernUO *
- * Copyright 2019-2021 - ModernUO Development Team *
- * Email: hi@modernuo.com *
- * File: EPollGroup.cs *
- * *
- * This program is free software: you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation, either version 3 of the License, or *
- * (at your option) any later version. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see . *
- *************************************************************************/
-
-using System;
-using System.Net.Sockets;
-using System.Runtime.InteropServices;
-
-namespace Server.Network
-{
- public sealed class EPollGroup : IPollGroup
- {
- [Flags]
- private enum epoll_flags
- {
- NONE = 0,
- CLOEXEC = 0x02000000,
- NONBLOCK = 0x04000,
- }
-
- [Flags]
- private enum epoll_events : uint
- {
- EPOLLIN = 0x001,
- EPOLLPRI = 0x002,
- EPOLLOUT = 0x004,
- EPOLLRDNORM = 0x040,
- EPOLLRDBAND = 0x080,
- EPOLLWRNORM = 0x100,
- EPOLLWRBAND = 0x200,
- EPOLLMSG = 0x400,
- EPOLLERR = 0x008,
- EPOLLHUP = 0x010,
- EPOLLRDHUP = 0x2000,
- EPOLLONESHOT = 1 << 30,
- EPOLLET = unchecked((uint)(1 << 31))
- }
-
- private enum epoll_op
- {
- EPOLL_CTL_ADD = 1,
- EPOLL_CTL_DEL = 2,
- EPOLL_CTL_MOD = 3,
- }
-
- [StructLayout(LayoutKind.Explicit, Size = 8)]
- private struct epoll_data
- {
- [FieldOffset(0)]
- public int fd;
- [FieldOffset(0)]
- public IntPtr ptr;
- [FieldOffset(0)]
- public uint u32;
- [FieldOffset(0)]
- public ulong u64;
- }
-
- [StructLayout(LayoutKind.Explicit, Pack = 4)]
- private struct epoll_event
- {
- [FieldOffset(0)]
- public epoll_events events;
- [FieldOffset(4)]
- public epoll_data data;
- }
-
- private static class Windows
- {
- [DllImport("wepoll.dll", SetLastError = true)]
- public static extern int epoll_create1(epoll_flags flags);
-
- [DllImport("wepoll.dll", SetLastError = true)]
- public static extern int epoll_close(int epfd);
-
- [DllImport("wepoll.dll", SetLastError = true)]
- public static extern int epoll_ctl(int epfd, epoll_op op, int fd, ref epoll_event ee);
-
- [DllImport("wepoll.dll", SetLastError = true)]
- public static extern int epoll_wait(int epfd, [In, Out] epoll_event[] ee, int maxevents, int timeout);
- }
-
- private static class Linux
- {
- [DllImport("libc", SetLastError = true)]
- public static extern int epoll_create1(epoll_flags flags);
-
- [DllImport("libc", SetLastError = true)]
- public static extern int epoll_close(int epfd);
-
- [DllImport("libc", SetLastError = true)]
- public static extern int epoll_ctl(int epfd, epoll_op op, int fd, ref epoll_event ee);
-
- [DllImport("libc", SetLastError = true)]
- public static extern int epoll_wait(int epfd, [In, Out] epoll_event[] ee, int maxevents, int timeout);
- }
-
- private readonly int _epHndle;
- private readonly bool _isWindows;
-
- public EPollGroup()
- {
- _isWindows = Core.IsWindows;
- _epHndle = _isWindows ? Windows.epoll_create1(epoll_flags.NONE) : Linux.epoll_create1(epoll_flags.NONE);
-
- if (_epHndle == 0)
- {
- throw new Exception("Unable to initialize poll group");
- }
- }
-
- public void Dispose()
- {
- if (_isWindows)
- {
- Windows.epoll_close(_epHndle);
- }
- else
- {
- Linux.epoll_close(_epHndle);
- }
- }
-
- public void Add(Socket socket, GCHandle handle)
- {
- var ev = new epoll_event
- {
- events = epoll_events.EPOLLIN | epoll_events.EPOLLERR
- };
-
- ev.data.ptr = (IntPtr)handle;
-
- var rc = _isWindows ?
- Windows.epoll_ctl(_epHndle, epoll_op.EPOLL_CTL_ADD, (int)socket.Handle, ref ev) :
- Linux.epoll_ctl(_epHndle, epoll_op.EPOLL_CTL_ADD, (int)socket.Handle, ref ev);
-
-
- if (rc != 0)
- {
- throw new Exception($"epoll_ctl failed with error code {Marshal.GetLastWin32Error()}");
- }
- }
-
- public void Remove(Socket socket)
- {
- var ev = new epoll_event { events = epoll_events.EPOLLIN | epoll_events.EPOLLERR };
-
- var rc = _isWindows ?
- Windows.epoll_ctl(_epHndle, epoll_op.EPOLL_CTL_DEL, (int)socket.Handle, ref ev) :
- Linux.epoll_ctl(_epHndle, epoll_op.EPOLL_CTL_DEL, (int)socket.Handle, ref ev);
-
- if (rc != 0)
- {
- throw new Exception($"epoll_ctl failed with error code {Marshal.GetLastWin32Error()}");
- }
- }
-
- private epoll_event[] _events = new epoll_event[2048];
-
- public int Poll(ref GCHandle[] handles)
- {
- if (handles.Length > _events.Length)
- {
- var newLength = Math.Max(handles.Length, _events.Length + (_events.Length >> 2));
- _events = new epoll_event[newLength];
- }
-
- var rc = _isWindows ?
- Windows.epoll_wait(_epHndle, _events, handles.Length, 0) :
- Linux.epoll_wait(_epHndle, _events, handles.Length, 0);
-
- if (rc <= 0)
- {
- return rc;
- }
-
- for (int i = 0; i < rc; i++)
- {
- handles[i] = (GCHandle)_events[i].data.ptr;
- }
-
- return rc;
- }
-
- }
-}
diff --git a/Projects/Server/Network/PollGroup/KQueuePollGroup.cs b/Projects/Server/Network/PollGroup/KQueuePollGroup.cs
deleted file mode 100644
index 278e88406..000000000
--- a/Projects/Server/Network/PollGroup/KQueuePollGroup.cs
+++ /dev/null
@@ -1,241 +0,0 @@
-/*************************************************************************
- * ModernUO *
- * Copyright 2019-2021 - ModernUO Development Team *
- * Email: hi@modernuo.com *
- * File: KQueuePollGroup.cs *
- * *
- * This program is free software: you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation, either version 3 of the License, or *
- * (at your option) any later version. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see . *
- *************************************************************************/
-
-using System;
-using System.IO;
-using System.Net.Sockets;
-using System.Runtime.InteropServices;
-
-namespace Server.Network
-{
- public class KQueuePollGroup : IPollGroup
- {
- [StructLayout(LayoutKind.Sequential)]
- private struct kevent
- {
- public IntPtr ident;
- public kqueue_filter filter;
- public kqueue_flags flags;
- public kqueue_fflags fflags;
- public IntPtr data;
- public IntPtr udata;
- }
-
- [Flags]
- private enum kqueue_filter : short
- {
- READ = -1,
- WRITE = -2,
- AIO = -3,
- VNODE = -4,
- PROC = -5,
- SIGNAL = -6,
- TIMER = -7,
- MACHPORT = -8,
- FS = -9,
- USER = -10,
- UNUSED = -11,
- VM = -12,
- EXCEPT = -15
- }
-
- [Flags]
- private enum kqueue_flags : ushort
- {
- ADD = 0x0001,
- DELETE = 0x0002,
- ENABLE = 0x0004,
- DISABLE = 0x0008,
- ONESHOT = 0x0010,
- CLEAR = 0x0020,
- RECEIPT = 0x0040,
- DISPATCH = 0x0080,
- UDATA_SPECIFIC = 0x0100,
- DISPATCH2 = (DISPATCH | UDATA_SPECIFIC),
- VANISHED = 0x0200,
- SYSFLAGS = 0xF000,
- FLAG0 = 0x1000,
- FLAG1 = 0x2000,
- EOF = 0x8000,
- ERROR = 0x4000
- }
-
- [Flags]
- private enum kqueue_fflags : uint
- {
- TRIGGER = 0x01000000,
- FFNOP = 0x00000000,
- FFAND = 0x40000000,
- FFOR = 0x80000000,
- FFCOPY = 0xc0000000,
- FFCTRLMASK = 0xc0000000,
- FFFLAGSMASK = 0x00ffffff,
- LOWAT = 0x00000001,
- DELETE = 0x00000001,
- WRITE = 0x00000002,
- EXTEND = 0x00000004,
- ATTRIB = 0x00000008,
- LINK = 0x00000010,
- RENAME = 0x00000020,
- REVOKE = 0x00000040,
- NONE = 0x00000080,
- }
-
- [StructLayout(LayoutKind.Sequential)]
- struct timespec
- {
- public long tv_sec;
- public long tv_nsec;
-
- public timespec(long sec, long nsec)
- {
- tv_sec = sec;
- tv_nsec = nsec;
- }
- }
-
- private static readonly kevent[] _singleEvent = new kevent[1];
- private static readonly IntPtr _zeroTimeoutPtr;
- // ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
- private static readonly timespec _zeroTimeout;
-
- static KQueuePollGroup()
- {
- _zeroTimeout = new timespec(0, 0);
- _zeroTimeoutPtr = Marshal.AllocHGlobal(Marshal.SizeOf());
- Marshal.StructureToPtr(_zeroTimeout, _zeroTimeoutPtr, false);
- }
-
- private static class BSD
- {
- [DllImport ("libc", SetLastError = true)]
- public static extern int close (int fd);
-
- [DllImport("libc", SetLastError = true)]
- public static extern int kqueue();
-
- [DllImport("libc", SetLastError = true)]
- public static extern int kevent(int kq, kevent[] changelist, int nchanges, [In, Out] kevent[] eventlist, int nevents, IntPtr timeout);
-
- public static int kevent(
- int kq,
- IntPtr ident,
- kqueue_filter filter,
- kqueue_flags flags,
- kqueue_fflags fflags = 0,
- IntPtr data = default,
- IntPtr udata = default
- )
- {
- _singleEvent[0] = new kevent
- {
- ident = ident,
- filter = filter,
- flags = flags,
- fflags = fflags,
- data = data,
- udata = udata
- };
-
- var rc = kevent(kq, _singleEvent, 1, null, 0, _zeroTimeoutPtr);
- if (rc != 0)
- {
- throw new Exception($"kqueue failed to {flags} with error code {Marshal.GetLastWin32Error()}");
- }
-
- if (_singleEvent[0].flags.HasFlag(kqueue_flags.ERROR))
- {
- throw new IOException($"kqueue failed to {flags} with error {_singleEvent[0].data}");
- }
-
- return rc;
- }
- }
-
- private readonly int _kqueueHndle;
-
- public KQueuePollGroup()
- {
- _kqueueHndle = BSD.kqueue();
-
- if (_kqueueHndle == 0)
- {
- throw new Exception("Unable to initialize poll group");
- }
- }
-
- public void Dispose()
- {
- BSD.close(_kqueueHndle);
- Marshal.FreeHGlobal(_zeroTimeoutPtr);
- }
-
- public void Add(Socket socket, GCHandle handle)
- {
- var rc = BSD.kevent(
- _kqueueHndle,
- socket.Handle,
- kqueue_filter.READ | kqueue_filter.WRITE,
- kqueue_flags.ADD | kqueue_flags.CLEAR,
- udata: (IntPtr)handle
- );
-
- if (rc != 0)
- {
- throw new Exception($"kevent failed with error code {Marshal.GetLastWin32Error()}");
- }
- }
-
- public void Remove(Socket socket)
- {
- var rc = BSD.kevent(
- _kqueueHndle,
- socket.Handle,
- kqueue_filter.READ | kqueue_filter.WRITE,
- kqueue_flags.DELETE
- );
-
- if (rc != 0)
- {
- throw new Exception($"kevent failed with error code {Marshal.GetLastWin32Error()}");
- }
- }
-
- private kevent[] _events = new kevent[2048];
-
- public int Poll(ref GCHandle[] handles)
- {
- if (handles.Length > _events.Length)
- {
- var newLength = Math.Max(handles.Length, _events.Length + (_events.Length >> 2));
- _events = new kevent[newLength];
- }
-
- var rc = BSD.kevent(_kqueueHndle, null, 0, _events, _events.Length, _zeroTimeoutPtr);
-
- if (rc <= 0)
- {
- return rc;
- }
-
- for (int i = 0; i < rc; i++)
- {
- handles[i] = (GCHandle)_events[i].udata;
- }
-
- return rc;
- }
- }
-}
diff --git a/Projects/Server/Network/PollGroup/PollGroup.cs b/Projects/Server/Network/PollGroup/PollGroup.cs
deleted file mode 100644
index 0fa4fa875..000000000
--- a/Projects/Server/Network/PollGroup/PollGroup.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-/*************************************************************************
- * ModernUO *
- * Copyright 2019-2021 - ModernUO Development Team *
- * Email: hi@modernuo.com *
- * File: PollGroup.cs *
- * *
- * This program is free software: you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation, either version 3 of the License, or *
- * (at your option) any later version. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see . *
- *************************************************************************/
-
-using System;
-using System.Net.Sockets;
-using System.Runtime.InteropServices;
-
-namespace Server.Network
-{
- public interface IPollGroup : IDisposable
- {
- void Add(Socket sock, GCHandle handle);
- void Remove(Socket sock);
- int Poll(ref GCHandle[] handles);
- }
-
- public static class PollGroup
- {
- public static IPollGroup Create()
- {
- if (Core.IsBSD)
- {
- return new KQueuePollGroup();
- }
-
- return new EPollGroup();
- }
- }
-}
diff --git a/Projects/Server/Server.csproj b/Projects/Server/Server.csproj
index a0d4042b7..031478398 100755
--- a/Projects/Server/Server.csproj
+++ b/Projects/Server/Server.csproj
@@ -13,32 +13,29 @@
-
-
-
-
-
-
-
-
+
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
- Always
- Always
-
-
+
diff --git a/Projects/Server/wepoll.dll b/Projects/Server/wepoll.dll
deleted file mode 100644
index f9383691d3ce8f8c96fb244c0d4908fe4bbbd484..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 21504
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