Merge branch 'main' into webSupport
This commit is contained in:
commit
8e79abc243
16 changed files with 56 additions and 629 deletions
|
|
@ -701,10 +701,6 @@ MetalDoor2 0x06C7 (Facing=EastCCW)
|
|||
5988 159 0
|
||||
6060 167 0
|
||||
|
||||
# Blood Moss
|
||||
Static 0x0F7B
|
||||
2678 712 0
|
||||
|
||||
# garbage
|
||||
Static 0x10F0
|
||||
5988 46 22
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Sockets;
|
||||
using Moq;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Tests.Network
|
||||
|
|
@ -11,18 +9,8 @@ namespace Server.Tests.Network
|
|||
public static Span<byte> Compile(this Packet p) =>
|
||||
p.Compile(false, out var length).AsSpan(0, length);
|
||||
|
||||
public static NetState CreateTestNetState()
|
||||
{
|
||||
var socket = new Mock<ISocket>();
|
||||
socket
|
||||
.Setup(s => s.SendAsync(It.IsAny<IList<ArraySegment<byte>>>(), SocketFlags.None))
|
||||
.ReturnsAsync(() => 0);
|
||||
|
||||
socket
|
||||
.Setup(s => s.ReceiveAsync(It.IsAny<IList<ArraySegment<byte>>>(), SocketFlags.None))
|
||||
.ReturnsAsync(() => 0);
|
||||
|
||||
return new NetState(socket.Object);
|
||||
}
|
||||
public static NetState CreateTestNetState() => new(
|
||||
new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ namespace Server.Tests.Network
|
|||
[Fact]
|
||||
public void TestGlobalLightLevel()
|
||||
{
|
||||
byte lightLevel = 5;
|
||||
const byte lightLevel = 5;
|
||||
var expected = new GlobalLightLevel(lightLevel).Compile();
|
||||
|
||||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
|
|
|
|||
|
|
@ -916,8 +916,15 @@ namespace Server
|
|||
else
|
||||
{
|
||||
m_NetState.SendChangeCombatant(m_Combatant.Serial);
|
||||
Timer.StartTimer(ExpireCombatantDelay, ExpireCombatant, out _expireCombatantTimerToken);
|
||||
Timer.StartTimer(TimeSpan.FromSeconds(0.01), 0, CheckCombatTime, out _combatTimerToken);
|
||||
if (!_expireCombatantTimerToken.Running)
|
||||
{
|
||||
Timer.StartTimer(ExpireCombatantDelay, ExpireCombatant, out _expireCombatantTimerToken);
|
||||
}
|
||||
|
||||
if (!_combatTimerToken.Running)
|
||||
{
|
||||
Timer.StartTimer(TimeSpan.FromSeconds(0.01), 0, CheckCombatTime, out _combatTimerToken);
|
||||
}
|
||||
|
||||
if (CanBeHarmful(m_Combatant, false))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Network;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Server.Accounting;
|
||||
|
|
@ -48,7 +49,7 @@ namespace Server.Network
|
|||
private const int MenuCap = 512;
|
||||
private const int PacketPerSecondThreshold = 3000;
|
||||
|
||||
private static NetState[] _polledStates = new NetState[2048];
|
||||
private static GCHandle[] _polledStates = new GCHandle[2048];
|
||||
private static readonly IPollGroup _pollGroup = PollGroup.Create();
|
||||
private static readonly Queue<NetState> FlushPending = new(2048);
|
||||
private static readonly Queue<NetState> FlushedPartials = new(2048);
|
||||
|
|
@ -101,7 +102,7 @@ namespace Server.Network
|
|||
Timer.DelayCall(TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1.5), CheckAllAlive);
|
||||
}
|
||||
|
||||
public NetState(ISocket connection)
|
||||
public NetState(Socket connection)
|
||||
{
|
||||
Connection = connection;
|
||||
Seeded = false;
|
||||
|
|
@ -130,7 +131,7 @@ namespace Server.Network
|
|||
|
||||
try
|
||||
{
|
||||
_pollGroup.Add(this);
|
||||
_pollGroup.Add(connection, _handle);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -171,7 +172,7 @@ namespace Server.Network
|
|||
|
||||
public Pipe<byte> SendPipe { get; }
|
||||
|
||||
public ISocket Connection { get; }
|
||||
public Socket Connection { get; }
|
||||
|
||||
public bool CompressionEnabled { get; set; }
|
||||
|
||||
|
|
@ -885,8 +886,8 @@ namespace Server.Network
|
|||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
_polledStates[i].HandleReceive();
|
||||
_polledStates[i] = null;
|
||||
(_polledStates[i].Target as NetState)?.HandleReceive();
|
||||
_polledStates[i] = default;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1032,7 +1033,7 @@ namespace Server.Network
|
|||
TcpServer.Instances.Remove(this);
|
||||
try
|
||||
{
|
||||
_pollGroup.Remove(this);
|
||||
_pollGroup.Remove(Connection);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,77 +0,0 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2020 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: NetworkSocket.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 <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Server.Network
|
||||
{
|
||||
public class NetworkSocket : ISocket
|
||||
{
|
||||
private readonly Socket _connection;
|
||||
|
||||
public Socket Connection
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _connection;
|
||||
}
|
||||
|
||||
public IntPtr Handle
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _connection.Handle;
|
||||
}
|
||||
|
||||
public EndPoint LocalEndPoint
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _connection.LocalEndPoint;
|
||||
}
|
||||
|
||||
public EndPoint RemoteEndPoint
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _connection.RemoteEndPoint;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public NetworkSocket(Socket connection) => _connection = connection;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Task<int> SendAsync(IList<ArraySegment<byte>> buffers, SocketFlags flags) =>
|
||||
_connection.SendAsync(buffers, flags);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int Send(IList<ArraySegment<byte>> buffers, SocketFlags flags) => _connection.Send(buffers, flags);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Task<int> ReceiveAsync(IList<ArraySegment<byte>> buffers, SocketFlags flags) =>
|
||||
_connection.ReceiveAsync(buffers, flags);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int Receive(IList<ArraySegment<byte>> buffers, SocketFlags flags) =>
|
||||
_connection.Receive(buffers, flags);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Shutdown(SocketShutdown how) => _connection.Shutdown(how);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Close() => _connection.Close();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,206 +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 <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System;
|
||||
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)]
|
||||
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.Sequential)]
|
||||
private struct epoll_event
|
||||
{
|
||||
public epoll_events events;
|
||||
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;
|
||||
|
||||
public EPollGroup()
|
||||
{
|
||||
_epHndle = Core.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 (Core.IsWindows)
|
||||
{
|
||||
Windows.epoll_close(_epHndle);
|
||||
}
|
||||
else
|
||||
{
|
||||
Linux.epoll_close(_epHndle);
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(NetState state)
|
||||
{
|
||||
var ev = new epoll_event
|
||||
{
|
||||
events = epoll_events.EPOLLIN | epoll_events.EPOLLERR
|
||||
};
|
||||
|
||||
ev.data.ptr = (IntPtr)state._handle;
|
||||
|
||||
var rc = Core.IsWindows ?
|
||||
Windows.epoll_ctl(_epHndle, epoll_op.EPOLL_CTL_ADD, (int)state.Connection.Handle, ref ev) :
|
||||
Linux.epoll_ctl(_epHndle, epoll_op.EPOLL_CTL_ADD, (int)state.Connection.Handle, ref ev);
|
||||
|
||||
|
||||
if (rc != 0)
|
||||
{
|
||||
throw new Exception($"epoll_ctl failed with error code {Marshal.GetLastWin32Error()}");
|
||||
}
|
||||
}
|
||||
|
||||
public void Remove(NetState state)
|
||||
{
|
||||
var ev = new epoll_event
|
||||
{
|
||||
events = epoll_events.EPOLLIN | epoll_events.EPOLLERR,
|
||||
};
|
||||
ev.data.ptr = (IntPtr)state._handle;
|
||||
|
||||
var rc = Core.IsWindows ?
|
||||
Windows.epoll_ctl(_epHndle, epoll_op.EPOLL_CTL_DEL, (int)state.Connection.Handle, ref ev) :
|
||||
Linux.epoll_ctl(_epHndle, epoll_op.EPOLL_CTL_DEL, (int)state.Connection.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 NetState[] states)
|
||||
{
|
||||
if (states.Length > _events.Length)
|
||||
{
|
||||
var newLength = Math.Max(states.Length, _events.Length + (_events.Length >> 2));
|
||||
_events = new epoll_event[newLength];
|
||||
}
|
||||
|
||||
var rc = Core.IsWindows ?
|
||||
Windows.epoll_wait(_epHndle, _events, states.Length, 0) :
|
||||
Linux.epoll_wait(_epHndle, _events, states.Length, 0);
|
||||
|
||||
if (rc <= 0)
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
|
||||
for (int i = 0; i < rc; i++)
|
||||
{
|
||||
if (((GCHandle)_events[i].data.ptr).Target is not NetState state)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
states[count++] = state;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,248 +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 <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
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<timespec>());
|
||||
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(NetState state)
|
||||
{
|
||||
var rc = BSD.kevent(
|
||||
_kqueueHndle,
|
||||
state.Connection.Handle,
|
||||
kqueue_filter.READ | kqueue_filter.WRITE,
|
||||
kqueue_flags.ADD | kqueue_flags.CLEAR,
|
||||
udata: (IntPtr)state._handle
|
||||
);
|
||||
|
||||
if (rc != 0)
|
||||
{
|
||||
throw new Exception($"kevent failed with error code {Marshal.GetLastWin32Error()}");
|
||||
}
|
||||
}
|
||||
|
||||
public void Remove(NetState state)
|
||||
{
|
||||
var rc = BSD.kevent(
|
||||
_kqueueHndle,
|
||||
state.Connection.Handle,
|
||||
kqueue_filter.READ | kqueue_filter.WRITE,
|
||||
kqueue_flags.DELETE,
|
||||
udata: (IntPtr)state._handle
|
||||
);
|
||||
|
||||
if (rc != 0)
|
||||
{
|
||||
throw new Exception($"kevent failed with error code {Marshal.GetLastWin32Error()}");
|
||||
}
|
||||
}
|
||||
|
||||
private kevent[] _events = new kevent[2048];
|
||||
|
||||
public int Poll(ref NetState[] states)
|
||||
{
|
||||
if (states.Length > _events.Length)
|
||||
{
|
||||
var newLength = Math.Max(states.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;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
|
||||
for (int i = 0; i < rc; i++)
|
||||
{
|
||||
if (((GCHandle)_events[i].udata).Target is not NetState state)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
states[count++] = state;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,39 +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 <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System;
|
||||
|
||||
namespace Server.Network
|
||||
{
|
||||
public interface IPollGroup : IDisposable
|
||||
{
|
||||
void Add(NetState state);
|
||||
void Remove(NetState state);
|
||||
int Poll(ref NetState[] states);
|
||||
}
|
||||
|
||||
public static class PollGroup
|
||||
{
|
||||
public static IPollGroup Create()
|
||||
{
|
||||
if (Core.IsBSD)
|
||||
{
|
||||
return new KQueuePollGroup();
|
||||
}
|
||||
|
||||
return new EPollGroup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -196,7 +196,7 @@ namespace Server.Network
|
|||
}
|
||||
else
|
||||
{
|
||||
var ns = new NetState(new NetworkSocket(socket));
|
||||
var ns = new NetState(socket);
|
||||
_connectedQueue.Enqueue(ns);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,32 +13,29 @@
|
|||
</PropertyGroup>
|
||||
<Target Name="CleanPub" AfterTargets="Clean">
|
||||
<Message Text="Removing distribution files..." />
|
||||
<Delete Files="..\..\Distribution\zlib.dll" ContinueOnError="true" />
|
||||
<Delete Files="..\..\Distribution\libz.dylib" ContinueOnError="true" />
|
||||
<Delete Files="..\..\Distribution\libz.so" ContinueOnError="true" />
|
||||
<Delete Files="..\..\Distribution\ZLib.Bindings.dll" ContinueOnError="true" />
|
||||
<Delete Files="..\..\Distribution\Microsoft.Toolkit.HighPerformance.dll" ContinueOnError="true" />
|
||||
<Delete Files="..\..\Distribution\Serilog.dll" ContinueOnError="true" />
|
||||
<Delete Files="..\..\Distribution\Serilog.Sinks.Async.dll" ContinueOnError="true" />
|
||||
<Delete Files="..\..\Distribution\Serilog.Sinks.Console.dll" ContinueOnError="true" />
|
||||
<Delete Files="..\..\Distribution\$(AssemblyName)" ContinueOnError="true" />
|
||||
<Delete Files="..\..\Distribution\$(AssemblyName).deps.json" ContinueOnError="true" />
|
||||
<Delete Files="..\..\Distribution\$(AssemblyName).dll" ContinueOnError="true" />
|
||||
<Delete Files="..\..\Distribution\ref\$(AssemblyName).dll" ContinueOnError="true" />
|
||||
<Delete Files="..\..\Distribution\$(AssemblyName).dll.config" ContinueOnError="true" />
|
||||
<Delete Files="..\..\Distribution\$(AssemblyName).exe" ContinueOnError="true" />
|
||||
<Delete Files="..\..\Distribution\$(AssemblyName).deps.json" ContinueOnError="true" />
|
||||
<Delete Files="..\..\Distribution\$(AssemblyName).pdb" ContinueOnError="true" />
|
||||
<Delete Files="..\..\Distribution\$(AssemblyName).runtimeconfig.dev.json" ContinueOnError="true" />
|
||||
<Delete Files="..\..\Distribution\$(AssemblyName).runtimeconfig.json" ContinueOnError="true" />
|
||||
<Delete Files="..\..\Distribution\libz.dylib" ContinueOnError="true" />
|
||||
<Delete Files="..\..\Distribution\libz.so" ContinueOnError="true" />
|
||||
<Delete Files="..\..\Distribution\Microsoft.Toolkit.HighPerformance.dll" ContinueOnError="true" />
|
||||
<Delete Files="..\..\Distribution\PollGroup.dll" ContinueOnError="true" />
|
||||
<Delete Files="..\..\Distribution\ref\$(AssemblyName).dll" ContinueOnError="true" />
|
||||
<Delete Files="..\..\Distribution\Serilog.dll" ContinueOnError="true" />
|
||||
<Delete Files="..\..\Distribution\Serilog.Sinks.Async.dll" ContinueOnError="true" />
|
||||
<Delete Files="..\..\Distribution\Serilog.Sinks.Console.dll" ContinueOnError="true" />
|
||||
<Delete Files="..\..\Distribution\wepoll.dll" ContinueOnError="true" />
|
||||
<Delete Files="..\..\Distribution\ZLib.Bindings.dll" ContinueOnError="true" />
|
||||
<Delete Files="..\..\Distribution\zlib.dll" ContinueOnError="true" />
|
||||
</Target>
|
||||
<ItemGroup Condition="'$(IsWindows)'=='true' OR '$(IsWindows)'==''">
|
||||
<Content Include="wepoll.dll">
|
||||
<CopyToPublishDirectory>Always</CopyToPublishDirectory>
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Toolkit.HighPerformance" Version="7.0.2" />
|
||||
<PackageReference Include="PollGroup" Version="1.1.0" />
|
||||
<PackageReference Include="Zlib.Bindings" Version="1.5.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -93,7 +93,8 @@ namespace Server.Accounting
|
|||
|
||||
_totalGameTime = reader.ReadTimeSpan();
|
||||
|
||||
_email = reader.ReadString();
|
||||
if (version > 1)
|
||||
_email = reader.ReadString();
|
||||
|
||||
Timer.StartTimer(AfterDeserialization);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,8 @@ namespace Server.Compression
|
|||
// bsdtar has a bug and hangs, so we are doing it in two steps.
|
||||
if (Core.IsWindows)
|
||||
{
|
||||
var tempTarArchive = Path.Combine(Core.BaseDirectory, "temp/temp-file.tar");
|
||||
var tempDir = PathUtility.EnsureRandomPath(Path.GetTempPath());
|
||||
var tempTarArchive = Path.Combine(tempDir, "temp-file.tar");
|
||||
|
||||
try
|
||||
{
|
||||
|
|
@ -22,8 +23,8 @@ namespace Server.Compression
|
|||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = _pathToZstd,
|
||||
Arguments = $"-q -d \"{fileNamePath}\" -o \"${tempTarArchive}\""
|
||||
FileName = Path.Combine(_pathToZstd, "zstd.exe"),
|
||||
Arguments = $"-q -d \"{fileNamePath}\" -o \"{tempTarArchive}\""
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -54,11 +55,12 @@ namespace Server.Compression
|
|||
// bsdtar has a bug and hangs, so we are doing it in two steps.
|
||||
if (Core.IsWindows)
|
||||
{
|
||||
var tempTarArchive = Path.Combine(Core.BaseDirectory, "temp/temp-file.tar");
|
||||
var tempDir = PathUtility.EnsureRandomPath(Path.GetTempPath());
|
||||
var tempTarArchive = Path.Combine(tempDir, "temp-file.tar");
|
||||
|
||||
try
|
||||
{
|
||||
if (!TarArchive.CreateFromPaths(paths, relativeTo, tempTarArchive))
|
||||
if (!TarArchive.CreateFromPaths(paths, tempTarArchive, relativeTo))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -83,7 +85,7 @@ namespace Server.Compression
|
|||
}
|
||||
finally
|
||||
{
|
||||
File.Delete(tempTarArchive);
|
||||
Directory.Delete(tempDir, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -68,7 +68,11 @@ namespace Server.Misc
|
|||
{
|
||||
var ns = e.State;
|
||||
|
||||
var ipep = (IPEndPoint)ns.Connection.LocalEndPoint;
|
||||
var ipep = (IPEndPoint)ns.Connection?.LocalEndPoint;
|
||||
if (ipep == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var localAddress = ipep.Address;
|
||||
var localPort = ipep.Port;
|
||||
|
|
@ -76,7 +80,7 @@ namespace Server.Misc
|
|||
if (IsPrivateNetwork(localAddress))
|
||||
{
|
||||
ipep = (IPEndPoint)ns.Connection.RemoteEndPoint;
|
||||
if (!IsPrivateNetwork(ipep.Address) && _publicAddress != null)
|
||||
if (ipep == null || !IsPrivateNetwork(ipep.Address) && _publicAddress != null)
|
||||
{
|
||||
localAddress = _publicAddress;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -314,7 +314,7 @@ namespace Server.Saves
|
|||
foreach (var (rangeStart, sortedBackups) in items)
|
||||
{
|
||||
var backups = sortedBackups.Values;
|
||||
if (backups.Count == 0)
|
||||
if (backups.Count <= minimum)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
@ -380,7 +380,7 @@ namespace Server.Saves
|
|||
|
||||
private static IEnumerable<string> PathsByTimestampName(string path, bool files = false)
|
||||
{
|
||||
var allItems = files ? Directory.GetFiles(path) : Directory.GetDirectories(path);
|
||||
var allItems = files ? Directory.EnumerateFiles(path) : Directory.GetDirectories(path);
|
||||
var items = new SortedDictionary<DateTime, string>(new DescendingComparer<DateTime>());
|
||||
foreach (var item in allItems)
|
||||
{
|
||||
|
|
@ -397,7 +397,9 @@ namespace Server.Saves
|
|||
|
||||
if (TryGetDate(name, out var date))
|
||||
{
|
||||
items.Add(date, item);
|
||||
// Might give wrong results if there is a file that matches:
|
||||
// Example: 2021-09-01, and 2021-09-01-00
|
||||
items[date] = item;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -435,7 +437,6 @@ namespace Server.Saves
|
|||
}
|
||||
catch
|
||||
{
|
||||
logger.Warning($"Path was not in the correct date format: {value}");
|
||||
date = DateTime.MinValue;
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue