parent
05ff3f2ad9
commit
81486772f6
10 changed files with 60 additions and 161 deletions
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -48,7 +48,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 +101,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 +130,7 @@ namespace Server.Network
|
|||
|
||||
try
|
||||
{
|
||||
_pollGroup.Add(this);
|
||||
_pollGroup.Add(connection, _handle);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -171,7 +171,7 @@ namespace Server.Network
|
|||
|
||||
public Pipe<byte> SendPipe { get; }
|
||||
|
||||
public ISocket Connection { get; }
|
||||
public Socket Connection { get; }
|
||||
|
||||
public bool CompressionEnabled { get; set; }
|
||||
|
||||
|
|
@ -885,8 +885,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 +1032,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();
|
||||
}
|
||||
}
|
||||
|
|
@ -14,6 +14,7 @@
|
|||
*************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Server.Network
|
||||
|
|
@ -53,23 +54,20 @@ namespace Server.Network
|
|||
EPOLL_CTL_MOD = 3,
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
[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)]
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 4)]
|
||||
private struct epoll_event
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
|
|
@ -109,10 +107,12 @@ namespace Server.Network
|
|||
}
|
||||
|
||||
private readonly int _epHndle;
|
||||
private readonly bool _isWindows;
|
||||
|
||||
public EPollGroup()
|
||||
{
|
||||
_epHndle = Core.IsWindows ? Windows.epoll_create1(epoll_flags.NONE) : Linux.epoll_create1(epoll_flags.NONE);
|
||||
_isWindows = Core.IsWindows;
|
||||
_epHndle = _isWindows ? Windows.epoll_create1(epoll_flags.NONE) : Linux.epoll_create1(epoll_flags.NONE);
|
||||
|
||||
if (_epHndle == 0)
|
||||
{
|
||||
|
|
@ -122,7 +122,7 @@ namespace Server.Network
|
|||
|
||||
public void Dispose()
|
||||
{
|
||||
if (Core.IsWindows)
|
||||
if (_isWindows)
|
||||
{
|
||||
Windows.epoll_close(_epHndle);
|
||||
}
|
||||
|
|
@ -132,18 +132,18 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public void Add(NetState state)
|
||||
public void Add(Socket socket, GCHandle handle)
|
||||
{
|
||||
var ev = new epoll_event
|
||||
{
|
||||
events = epoll_events.EPOLLIN | epoll_events.EPOLLERR
|
||||
};
|
||||
|
||||
ev.data.ptr = (IntPtr)state._handle;
|
||||
ev.data.ptr = (IntPtr)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);
|
||||
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)
|
||||
|
|
@ -152,17 +152,13 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public void Remove(NetState state)
|
||||
public void Remove(Socket socket)
|
||||
{
|
||||
var ev = new epoll_event
|
||||
{
|
||||
events = epoll_events.EPOLLIN | epoll_events.EPOLLERR,
|
||||
};
|
||||
ev.data.ptr = (IntPtr)state._handle;
|
||||
var ev = new epoll_event { events = epoll_events.EPOLLIN | epoll_events.EPOLLERR };
|
||||
|
||||
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);
|
||||
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)
|
||||
{
|
||||
|
|
@ -172,36 +168,29 @@ namespace Server.Network
|
|||
|
||||
private epoll_event[] _events = new epoll_event[2048];
|
||||
|
||||
public int Poll(ref NetState[] states)
|
||||
public int Poll(ref GCHandle[] handles)
|
||||
{
|
||||
if (states.Length > _events.Length)
|
||||
if (handles.Length > _events.Length)
|
||||
{
|
||||
var newLength = Math.Max(states.Length, _events.Length + (_events.Length >> 2));
|
||||
var newLength = Math.Max(handles.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);
|
||||
var rc = _isWindows ?
|
||||
Windows.epoll_wait(_epHndle, _events, handles.Length, 0) :
|
||||
Linux.epoll_wait(_epHndle, _events, handles.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;
|
||||
handles[i] = (GCHandle)_events[i].data.ptr;
|
||||
}
|
||||
|
||||
return count;
|
||||
return rc;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Server.Network
|
||||
|
|
@ -181,14 +182,14 @@ namespace Server.Network
|
|||
Marshal.FreeHGlobal(_zeroTimeoutPtr);
|
||||
}
|
||||
|
||||
public void Add(NetState state)
|
||||
public void Add(Socket socket, GCHandle handle)
|
||||
{
|
||||
var rc = BSD.kevent(
|
||||
_kqueueHndle,
|
||||
state.Connection.Handle,
|
||||
socket.Handle,
|
||||
kqueue_filter.READ | kqueue_filter.WRITE,
|
||||
kqueue_flags.ADD | kqueue_flags.CLEAR,
|
||||
udata: (IntPtr)state._handle
|
||||
udata: (IntPtr)handle
|
||||
);
|
||||
|
||||
if (rc != 0)
|
||||
|
|
@ -197,14 +198,13 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public void Remove(NetState state)
|
||||
public void Remove(Socket socket)
|
||||
{
|
||||
var rc = BSD.kevent(
|
||||
_kqueueHndle,
|
||||
state.Connection.Handle,
|
||||
socket.Handle,
|
||||
kqueue_filter.READ | kqueue_filter.WRITE,
|
||||
kqueue_flags.DELETE,
|
||||
udata: (IntPtr)state._handle
|
||||
kqueue_flags.DELETE
|
||||
);
|
||||
|
||||
if (rc != 0)
|
||||
|
|
@ -215,11 +215,11 @@ namespace Server.Network
|
|||
|
||||
private kevent[] _events = new kevent[2048];
|
||||
|
||||
public int Poll(ref NetState[] states)
|
||||
public int Poll(ref GCHandle[] handles)
|
||||
{
|
||||
if (states.Length > _events.Length)
|
||||
if (handles.Length > _events.Length)
|
||||
{
|
||||
var newLength = Math.Max(states.Length, _events.Length + (_events.Length >> 2));
|
||||
var newLength = Math.Max(handles.Length, _events.Length + (_events.Length >> 2));
|
||||
_events = new kevent[newLength];
|
||||
}
|
||||
|
||||
|
|
@ -230,19 +230,12 @@ namespace Server.Network
|
|||
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;
|
||||
handles[i] = (GCHandle)_events[i].udata;
|
||||
}
|
||||
|
||||
return count;
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,14 +14,16 @@
|
|||
*************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Server.Network
|
||||
{
|
||||
public interface IPollGroup : IDisposable
|
||||
{
|
||||
void Add(NetState state);
|
||||
void Remove(NetState state);
|
||||
int Poll(ref NetState[] states);
|
||||
void Add(Socket sock, GCHandle handle);
|
||||
void Remove(Socket sock);
|
||||
int Poll(ref GCHandle[] handles);
|
||||
}
|
||||
|
||||
public static class PollGroup
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ namespace Server.Network
|
|||
}
|
||||
else
|
||||
{
|
||||
var ns = new NetState(new NetworkSocket(socket));
|
||||
var ns = new NetState(socket);
|
||||
_connectedQueue.Enqueue(ns);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue