Switches to Kestrel (#102)
This commit is contained in:
parent
70fddfebde
commit
2c0d97cd36
141 changed files with 1040 additions and 1679 deletions
11
.gitignore
vendored
11
.gitignore
vendored
|
|
@ -4,6 +4,7 @@
|
|||
/Distribution/Logs
|
||||
/Distribution/Backups
|
||||
/Distribution/Saves
|
||||
/Distribution/docs
|
||||
/Distribution/System.IO.Pipelines.dll
|
||||
/Distribution/libdrng.dll
|
||||
/Distribution/zlib.dll
|
||||
|
|
@ -12,21 +13,17 @@
|
|||
/Distribution/System.Runtime.CompilerServices.Unsafe.dll
|
||||
|
||||
# LibUv Dependencies
|
||||
/Distribution/libuv.dylib
|
||||
/Distribution/libuv.dll
|
||||
/Distribution/libuv.so
|
||||
/Distribution/Microsoft.AspNetCore.Connections.Abstractions.dll
|
||||
/Distribution/Microsoft.AspNetCore.Http.Features.dll
|
||||
/Distribution/Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.dll
|
||||
/Distribution/Microsoft.Extensions.Configuration.Abstractions.dll
|
||||
/Distribution/Microsoft.Extensions.Configuration.Binder.dll
|
||||
/Distribution/Microsoft.Extensions.Configuration.dll
|
||||
/Distribution/Microsoft.Extensions.DependencyInjection.Abstractions.dll
|
||||
/Distribution/Microsoft.Extensions.DependencyInjection.dll
|
||||
/Distribution/Microsoft.Extensions.FileProviders.Abstractions.dll
|
||||
/Distribution/Microsoft.Extensions.Hosting.Abstractions.dll
|
||||
/Distribution/Microsoft.Extensions.Logging.Abstractions.dll
|
||||
/Distribution/Microsoft.Extensions.Logging.Configuration.dll
|
||||
/Distribution/Microsoft.Extensions.Logging.Console.dll
|
||||
/Distribution/Microsoft.Extensions.Logging.dll
|
||||
/Distribution/Microsoft.Extensions.Options.ConfigurationExtensions.dll
|
||||
/Distribution/Microsoft.Extensions.Options.dll
|
||||
/Distribution/Microsoft.Extensions.Primitives.dll
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ namespace Server.Misc
|
|||
if (!Enabled || IsExempt(ourAddress))
|
||||
return true;
|
||||
|
||||
List<NetState> netStates = NetState.Instances;
|
||||
List<NetState> netStates = TcpServer.Instances;
|
||||
|
||||
int count = 0;
|
||||
|
||||
|
|
@ -50,4 +50,4 @@ namespace Server.Misc
|
|||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ namespace Server.Commands.Generic
|
|||
List<object> list = new List<object>();
|
||||
List<IPAddress> addresses = new List<IPAddress>();
|
||||
|
||||
List<NetState> states = NetState.Instances;
|
||||
List<NetState> states = TcpServer.Instances;
|
||||
|
||||
for (int i = 0; i < states.Count; ++i)
|
||||
{
|
||||
|
|
@ -60,4 +60,4 @@ namespace Server.Commands.Generic
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ namespace Server.Commands.Generic
|
|||
|
||||
List<object> list = new List<object>();
|
||||
|
||||
List<NetState> states = NetState.Instances;
|
||||
List<NetState> states = TcpServer.Instances;
|
||||
|
||||
for (int i = 0; i < states.Count; ++i)
|
||||
{
|
||||
|
|
@ -61,4 +61,4 @@ namespace Server.Commands.Generic
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -671,7 +671,7 @@ namespace Server.Commands
|
|||
|
||||
public static void BroadcastMessage(AccessLevel ac, int hue, string message)
|
||||
{
|
||||
foreach (NetState state in NetState.Instances)
|
||||
foreach (NetState state in TcpServer.Instances)
|
||||
{
|
||||
Mobile m = state.Mobile;
|
||||
|
||||
|
|
@ -743,7 +743,7 @@ namespace Server.Commands
|
|||
[Description("View some stats about the server.")]
|
||||
public static void Stats_OnCommand(CommandEventArgs e)
|
||||
{
|
||||
e.Mobile.SendMessage("Open Connections: {0}", NetState.Instances.Count);
|
||||
e.Mobile.SendMessage("Open Connections: {0}", TcpServer.Instances.Count);
|
||||
e.Mobile.SendMessage("Mobiles: {0}", World.Mobiles.Count);
|
||||
e.Mobile.SendMessage("Items: {0}", World.Items.Count);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ namespace Server.Engines.Help
|
|||
|
||||
bool isStaffOnline = false;
|
||||
|
||||
foreach (NetState ns in NetState.Instances)
|
||||
foreach (NetState ns in TcpServer.Instances)
|
||||
{
|
||||
Mobile m = ns.Mobile;
|
||||
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ namespace Server.Gumps
|
|||
AddLabel(150, 170, LabelHue, Firewall.List.Count.ToString());
|
||||
|
||||
AddLabel(20, 190, LabelHue, "Clients:");
|
||||
AddLabel(150, 190, LabelHue, NetState.Instances.Count.ToString());
|
||||
AddLabel(150, 190, LabelHue, TcpServer.Instances.Count.ToString());
|
||||
|
||||
AddLabel(20, 210, LabelHue, "Mobiles:");
|
||||
AddLabel(150, 210, LabelHue, World.Mobiles.Count.ToString());
|
||||
|
|
@ -380,7 +380,7 @@ namespace Server.Gumps
|
|||
{
|
||||
if (m_List == null)
|
||||
{
|
||||
List<NetState> states = NetState.Instances.ToList();
|
||||
List<NetState> states = TcpServer.Instances;
|
||||
states.Sort(NetStateComparer.Instance);
|
||||
|
||||
m_List = states.ToList<object>();
|
||||
|
|
@ -1932,7 +1932,7 @@ namespace Server.Gumps
|
|||
|
||||
if (level > AccessLevel.Player)
|
||||
{
|
||||
List<NetState> clients = NetState.Instances;
|
||||
List<NetState> clients = TcpServer.Instances;
|
||||
int count = 0;
|
||||
|
||||
for (int i = 0; i < clients.Count; ++i)
|
||||
|
|
@ -2020,7 +2020,7 @@ namespace Server.Gumps
|
|||
}
|
||||
else
|
||||
{
|
||||
List<NetState> instances = NetState.Instances;
|
||||
List<NetState> instances = TcpServer.Instances;
|
||||
|
||||
for (int i = 0; i < instances.Count; ++i)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ namespace Server.Gumps
|
|||
string filter = string.IsNullOrWhiteSpace(rawFilter) ? null : rawFilter.Trim().ToLower();
|
||||
|
||||
List<Mobile> list = new List<Mobile>();
|
||||
List<NetState> states = NetState.Instances;
|
||||
List<NetState> states = TcpServer.Instances;
|
||||
|
||||
for ( int i = 0; i < states.Count; ++i )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -202,7 +202,7 @@ namespace Server.Misc
|
|||
|
||||
try
|
||||
{
|
||||
List<NetState> states = NetState.Instances;
|
||||
List<NetState> states = TcpServer.Instances;
|
||||
|
||||
op.WriteLine("- Count: {0}", states.Count);
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ namespace Server.Misc
|
|||
|
||||
public static void FoodDecay()
|
||||
{
|
||||
foreach (NetState state in NetState.Instances)
|
||||
foreach (NetState state in TcpServer.Instances)
|
||||
{
|
||||
HungerDecay(state.Mobile);
|
||||
ThirstDecay(state.Mobile);
|
||||
|
|
|
|||
|
|
@ -20,9 +20,9 @@ namespace Server
|
|||
{
|
||||
m_LevelOverride = value;
|
||||
|
||||
for (int i = 0; i < NetState.Instances.Count; ++i)
|
||||
for (int i = 0; i < TcpServer.Instances.Count; ++i)
|
||||
{
|
||||
NetState ns = NetState.Instances[i];
|
||||
NetState ns = TcpServer.Instances[i];
|
||||
Mobile m = ns.Mobile;
|
||||
|
||||
m?.CheckLightLevels(false);
|
||||
|
|
@ -69,12 +69,12 @@ namespace Server
|
|||
Clock.GetTime(from.Map, from.X, from.Y, out int hours, out int minutes);
|
||||
|
||||
/* OSI times:
|
||||
*
|
||||
*
|
||||
* Midnight -> 3:59 AM : Night
|
||||
* 4:00 AM -> 11:59 PM : Day
|
||||
*
|
||||
*
|
||||
* RunUO times:
|
||||
*
|
||||
*
|
||||
* 10:00 PM -> 11:59 PM : Scale to night
|
||||
* Midnight -> 3:59 AM : Night
|
||||
* 4:00 AM -> 5:59 AM : Scale to day
|
||||
|
|
@ -102,9 +102,9 @@ namespace Server
|
|||
|
||||
protected override void OnTick()
|
||||
{
|
||||
for (int i = 0; i < NetState.Instances.Count; ++i)
|
||||
for (int i = 0; i < TcpServer.Instances.Count; ++i)
|
||||
{
|
||||
NetState ns = NetState.Instances[i];
|
||||
NetState ns = TcpServer.Instances[i];
|
||||
Mobile m = ns.Mobile;
|
||||
|
||||
m?.CheckLightLevels(false);
|
||||
|
|
@ -130,4 +130,4 @@ namespace Server
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ namespace Server.Misc
|
|||
|
||||
private static void EventSink_Login(LoginEventArgs args)
|
||||
{
|
||||
int userCount = NetState.Instances.Count;
|
||||
int userCount = TcpServer.Instances.Count;
|
||||
int itemCount = World.Items.Count;
|
||||
int mobileCount = World.Mobiles.Count;
|
||||
|
||||
|
|
@ -27,4 +27,4 @@ namespace Server.Misc
|
|||
mobileCount, mobileCount == 1 ? "" : "s");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ using Server.Network;
|
|||
|
||||
namespace Server.Misc
|
||||
{
|
||||
public class ServerList
|
||||
public static class ServerList
|
||||
{
|
||||
/*
|
||||
* The default setting for Address, a value of 'null', will use your local IP address. If all of your local IP addresses
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System.Net;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server
|
||||
{
|
||||
|
|
@ -15,8 +16,7 @@ namespace Server
|
|||
|
||||
public static void RegisterListeners()
|
||||
{
|
||||
for (int i = 0; i < m_ListenerEndPoints.Length; i++)
|
||||
Core.MessagePump.AddListener(m_ListenerEndPoints[i]);
|
||||
TcpServer.Listeners.AddRange(m_ListenerEndPoints);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -316,10 +316,7 @@ namespace Server
|
|||
|
||||
private static void ProcessDisplayCase(Map map, StaticTile[] tiles, int x, int y)
|
||||
{
|
||||
ShopFlags flags = ShopFlags.None;
|
||||
|
||||
for (int i = 0; i < tiles.Length; ++i)
|
||||
flags |= ProcessDisplayedItem(tiles[i].ID);
|
||||
ShopFlags flags = tiles.Aggregate(ShopFlags.None, (current, t) => current | ProcessDisplayedItem(t.ID));
|
||||
|
||||
if (flags != ShopFlags.None)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -263,7 +263,7 @@ namespace Server.Misc
|
|||
else
|
||||
type = 2;
|
||||
|
||||
List<NetState> states = NetState.Instances;
|
||||
List<NetState> states = TcpServer.Instances;
|
||||
|
||||
Packet weatherPacket = null;
|
||||
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ namespace Server.Misc
|
|||
|
||||
int index = 0;
|
||||
|
||||
foreach (Mobile m in NetState.Instances.Where(state => state.Mobile != null).Select(state => state.Mobile))
|
||||
foreach (Mobile m in TcpServer.Instances.Where(state => state.Mobile != null).Select(state => state.Mobile))
|
||||
{
|
||||
++index;
|
||||
|
||||
|
|
@ -181,4 +181,4 @@ namespace Server.Misc
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MailKit" Version="2.4.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Connections.Abstractions" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Connections.Abstractions" Version="3.1.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.1.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="3.1.3" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ namespace Server.Misc
|
|||
{
|
||||
Mobile from = e.Mobile;
|
||||
|
||||
if (from?.AccessLevel < AccessLevel.Counselor)
|
||||
if (from == null || from.AccessLevel < AccessLevel.Counselor)
|
||||
return;
|
||||
|
||||
if (HasDisconnected(from))
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ namespace Server
|
|||
{
|
||||
public class AggressorInfo
|
||||
{
|
||||
private static Queue<AggressorInfo> m_Pool = new Queue<AggressorInfo>();
|
||||
private static readonly Queue<AggressorInfo> m_Pool = new Queue<AggressorInfo>();
|
||||
private Mobile m_Attacker, m_Defender;
|
||||
private bool m_CanReportMurder;
|
||||
private bool m_CriminalAggression;
|
||||
|
|
|
|||
|
|
@ -1,108 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.AspNetCore.Hosting
|
||||
{
|
||||
/// <summary>
|
||||
/// Allows consumers to perform cleanup during a graceful shutdown.
|
||||
/// </summary>
|
||||
internal class ApplicationLifetime : IHostApplicationLifetime
|
||||
{
|
||||
private readonly CancellationTokenSource _startedSource = new CancellationTokenSource();
|
||||
private readonly CancellationTokenSource _stoppingSource = new CancellationTokenSource();
|
||||
private readonly CancellationTokenSource _stoppedSource = new CancellationTokenSource();
|
||||
private readonly ILogger<ApplicationLifetime> _logger;
|
||||
|
||||
public ApplicationLifetime(ILogger<ApplicationLifetime> logger) => _logger = logger;
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when the application host has fully started and is about to wait
|
||||
/// for a graceful shutdown.
|
||||
/// </summary>
|
||||
public CancellationToken ApplicationStarted => _startedSource.Token;
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when the application host is performing a graceful shutdown.
|
||||
/// Request may still be in flight. Shutdown will block until this event completes.
|
||||
/// </summary>
|
||||
public CancellationToken ApplicationStopping => _stoppingSource.Token;
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when the application host is performing a graceful shutdown.
|
||||
/// All requests should be complete at this point. Shutdown will block
|
||||
/// until this event completes.
|
||||
/// </summary>
|
||||
public CancellationToken ApplicationStopped => _stoppedSource.Token;
|
||||
|
||||
/// <summary>
|
||||
/// Signals the ApplicationStopping event and blocks until it completes.
|
||||
/// </summary>
|
||||
public void StopApplication()
|
||||
{
|
||||
// Lock on CTS to synchronize multiple calls to StopApplication. This guarantees that the first call
|
||||
// to StopApplication and its callbacks run to completion before subsequent calls to StopApplication,
|
||||
// which will no-op since the first call already requested cancellation, get a chance to execute.
|
||||
lock (_stoppingSource)
|
||||
{
|
||||
try
|
||||
{
|
||||
ExecuteHandlers(_stoppingSource);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
/* _logger.ApplicationError(LoggerEventIds.ApplicationStoppingException,
|
||||
"An error occurred stopping the application",
|
||||
ex);*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Signals the ApplicationStarted event and blocks until it completes.
|
||||
/// </summary>
|
||||
public void NotifyStarted()
|
||||
{
|
||||
try
|
||||
{
|
||||
ExecuteHandlers(_startedSource);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
/* _logger.ApplicationError(LoggerEventIds.ApplicationStartupException,
|
||||
"An error occurred starting the application",
|
||||
ex);*/
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Signals the ApplicationStopped event and blocks until it completes.
|
||||
/// </summary>
|
||||
public void NotifyStopped()
|
||||
{
|
||||
try
|
||||
{
|
||||
ExecuteHandlers(_stoppedSource);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
/* _logger.ApplicationError(LoggerEventIds.ApplicationStoppedException,
|
||||
"An error occurred stopping the application",
|
||||
ex);*/
|
||||
}
|
||||
}
|
||||
|
||||
private void ExecuteHandlers(CancellationTokenSource cancel)
|
||||
{
|
||||
// Noop if this is already cancelled
|
||||
if (cancel.IsCancellationRequested) return;
|
||||
|
||||
// Run the cancellation token callbacks
|
||||
cancel.Cancel(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
|
@ -29,7 +29,7 @@ namespace Server
|
|||
{
|
||||
public static class AssemblyHandler
|
||||
{
|
||||
private static Dictionary<Assembly, TypeCache> m_TypeCaches = new Dictionary<Assembly, TypeCache>();
|
||||
private static readonly Dictionary<Assembly, TypeCache> m_TypeCaches = new Dictionary<Assembly, TypeCache>();
|
||||
private static TypeCache m_NullCache;
|
||||
public static Assembly[] Assemblies { get; set; }
|
||||
|
||||
|
|
@ -85,10 +85,7 @@ namespace Server
|
|||
List<Type> types = new List<Type>();
|
||||
if(ignoreCase)
|
||||
name = name.ToLower();
|
||||
for (int i = 0; i < Assemblies.Length; i++)
|
||||
{
|
||||
types.AddRange(GetTypeCache(Assemblies[i])[name]);
|
||||
}
|
||||
for (int i = 0; i < Assemblies.Length; i++) types.AddRange(GetTypeCache(Assemblies[i])[name]);
|
||||
if (types.Count == 0)
|
||||
types.AddRange(GetTypeCache(Core.Assembly)[name]);
|
||||
return types;
|
||||
|
|
@ -107,15 +104,12 @@ namespace Server
|
|||
|
||||
public class TypeCache
|
||||
{
|
||||
private Dictionary<string, int[]> m_NameMap = new Dictionary<string, int[]>();
|
||||
private Type[] m_Types;
|
||||
public IEnumerable<Type> Types { get => m_Types; }
|
||||
public IEnumerable<string> Names { get => m_NameMap.Keys; }
|
||||
private readonly Dictionary<string, int[]> m_NameMap = new Dictionary<string, int[]>();
|
||||
private readonly Type[] m_Types;
|
||||
public IEnumerable<Type> Types => m_Types;
|
||||
public IEnumerable<string> Names => m_NameMap.Keys;
|
||||
|
||||
public IEnumerable<Type> this[string name]
|
||||
{
|
||||
get => m_NameMap.TryGetValue(name, out int[] value) ? value.Select(x => m_Types[x]) : new Type[0];
|
||||
}
|
||||
public IEnumerable<Type> this[string name] => m_NameMap.TryGetValue(name, out int[] value) ? value.Select(x => m_Types[x]) : new Type[0];
|
||||
|
||||
public TypeCache(Assembly asm)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ namespace Server
|
|||
|
||||
public struct Body
|
||||
{
|
||||
private static BodyType[] m_Types;
|
||||
private static readonly BodyType[] m_Types;
|
||||
|
||||
static Body()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ namespace System.Buffers
|
|||
|
||||
private readonly IMemoryOwner<byte> _memoryOwner;
|
||||
private MemoryHandle? _memoryHandle;
|
||||
private Memory<byte> _memory;
|
||||
private readonly Memory<byte> _memory;
|
||||
|
||||
private readonly object _syncObj = new object();
|
||||
private bool _isDisposed;
|
||||
|
|
|
|||
|
|
@ -5,15 +5,7 @@ namespace System.Buffers
|
|||
{
|
||||
public static class SlabMemoryPoolFactory
|
||||
{
|
||||
public static MemoryPool<byte> Create()
|
||||
{
|
||||
#if DEBUG
|
||||
return new DiagnosticMemoryPool(CreateSlabMemoryPool());
|
||||
#else
|
||||
return CreateSlabMemoryPool();
|
||||
#endif
|
||||
}
|
||||
|
||||
public static MemoryPool<byte> Create() => CreateSlabMemoryPool();
|
||||
public static MemoryPool<byte> CreateSlabMemoryPool() => new SlabMemoryPool();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ namespace Server.ContextMenus
|
|||
{
|
||||
public class OpenBackpackEntry : ContextMenuEntry
|
||||
{
|
||||
private Mobile m_Mobile;
|
||||
private readonly Mobile m_Mobile;
|
||||
|
||||
public OpenBackpackEntry(Mobile m) : base(6145) => m_Mobile = m;
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ namespace Server.ContextMenus
|
|||
{
|
||||
public class PaperdollEntry : ContextMenuEntry
|
||||
{
|
||||
private Mobile m_Mobile;
|
||||
private readonly Mobile m_Mobile;
|
||||
|
||||
public PaperdollEntry(Mobile m) : base(6123, 18) => m_Mobile = m;
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ namespace Server.Diagnostics
|
|||
{
|
||||
public abstract class BaseProfile
|
||||
{
|
||||
private Stopwatch _stopwatch;
|
||||
private readonly Stopwatch _stopwatch;
|
||||
|
||||
protected BaseProfile(string name)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ namespace Server.Diagnostics
|
|||
{
|
||||
public class GumpProfile : BaseProfile
|
||||
{
|
||||
private static Dictionary<Type, GumpProfile> _profiles = new Dictionary<Type, GumpProfile>();
|
||||
private static readonly Dictionary<Type, GumpProfile> _profiles = new Dictionary<Type, GumpProfile>();
|
||||
|
||||
public GumpProfile(Type type) : base(type.FullName)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ namespace Server.Diagnostics
|
|||
|
||||
public class PacketSendProfile : BasePacketProfile
|
||||
{
|
||||
private static Dictionary<Type, PacketSendProfile> _profiles = new Dictionary<Type, PacketSendProfile>();
|
||||
private static readonly Dictionary<Type, PacketSendProfile> _profiles = new Dictionary<Type, PacketSendProfile>();
|
||||
|
||||
private long _created;
|
||||
|
||||
|
|
@ -87,7 +87,7 @@ namespace Server.Diagnostics
|
|||
|
||||
public class PacketReceiveProfile : BasePacketProfile
|
||||
{
|
||||
private static Dictionary<int, PacketReceiveProfile> _profiles = new Dictionary<int, PacketReceiveProfile>();
|
||||
private static readonly Dictionary<int, PacketReceiveProfile> _profiles = new Dictionary<int, PacketReceiveProfile>();
|
||||
|
||||
public PacketReceiveProfile(int packetId)
|
||||
: base($"0x{packetId:X2}")
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ namespace Server.Diagnostics
|
|||
{
|
||||
public class TargetProfile : BaseProfile
|
||||
{
|
||||
private static Dictionary<Type, TargetProfile> _profiles = new Dictionary<Type, TargetProfile>();
|
||||
private static readonly Dictionary<Type, TargetProfile> _profiles = new Dictionary<Type, TargetProfile>();
|
||||
|
||||
public TargetProfile(Type type)
|
||||
: base(type.FullName)
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ namespace Server.Diagnostics
|
|||
{
|
||||
public class TimerProfile : BaseProfile
|
||||
{
|
||||
private static Dictionary<string, TimerProfile> _profiles = new Dictionary<string, TimerProfile>();
|
||||
private static readonly Dictionary<string, TimerProfile> _profiles = new Dictionary<string, TimerProfile>();
|
||||
|
||||
public TimerProfile(string name)
|
||||
: base(name)
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ namespace Server
|
|||
|
||||
public class AggressiveActionEventArgs : EventArgs
|
||||
{
|
||||
private static Queue<AggressiveActionEventArgs> m_Pool = new Queue<AggressiveActionEventArgs>();
|
||||
private static readonly Queue<AggressiveActionEventArgs> m_Pool = new Queue<AggressiveActionEventArgs>();
|
||||
|
||||
private AggressiveActionEventArgs(Mobile aggressed, Mobile aggressor, bool criminal)
|
||||
{
|
||||
|
|
@ -512,7 +512,7 @@ namespace Server
|
|||
|
||||
public class MovementEventArgs : EventArgs
|
||||
{
|
||||
private static Queue<MovementEventArgs> m_Pool = new Queue<MovementEventArgs>();
|
||||
private static readonly Queue<MovementEventArgs> m_Pool = new Queue<MovementEventArgs>();
|
||||
|
||||
public MovementEventArgs(Mobile mobile, Direction dir)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ namespace Server.Guilds
|
|||
|
||||
public abstract class BaseGuild : ISerializable
|
||||
{
|
||||
private BufferWriter m_SaveBuffer;
|
||||
private readonly BufferWriter m_SaveBuffer;
|
||||
public BufferWriter SaveBuffer => m_SaveBuffer;
|
||||
|
||||
private static uint m_NextID = 1;
|
||||
|
|
|
|||
|
|
@ -29,13 +29,13 @@ namespace Server.Gumps
|
|||
{
|
||||
private static uint m_NextSerial = 1;
|
||||
|
||||
private static byte[] m_BeginLayout = StringToBuffer("{ ");
|
||||
private static byte[] m_EndLayout = StringToBuffer(" }");
|
||||
private static readonly byte[] m_BeginLayout = StringToBuffer("{ ");
|
||||
private static readonly byte[] m_EndLayout = StringToBuffer(" }");
|
||||
|
||||
private static byte[] m_NoMove = StringToBuffer("{ nomove }");
|
||||
private static byte[] m_NoClose = StringToBuffer("{ noclose }");
|
||||
private static byte[] m_NoDispose = StringToBuffer("{ nodispose }");
|
||||
private static byte[] m_NoResize = StringToBuffer("{ noresize }");
|
||||
private static readonly byte[] m_NoMove = StringToBuffer("{ nomove }");
|
||||
private static readonly byte[] m_NoClose = StringToBuffer("{ noclose }");
|
||||
private static readonly byte[] m_NoDispose = StringToBuffer("{ nodispose }");
|
||||
private static readonly byte[] m_NoResize = StringToBuffer("{ noresize }");
|
||||
private bool m_Closable = true;
|
||||
private bool m_Disposable = true;
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ namespace Server.Gumps
|
|||
private bool m_Resizable = true;
|
||||
|
||||
private uint m_Serial;
|
||||
private List<string> m_Strings;
|
||||
private readonly List<string> m_Strings;
|
||||
|
||||
internal int m_TextEntries, m_Switches;
|
||||
private int m_X, m_Y;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ namespace Server.Gumps
|
|||
{
|
||||
public class GumpAlphaRegion : GumpEntry
|
||||
{
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer("checkertrans");
|
||||
private static readonly byte[] m_LayoutName = Gump.StringToBuffer("checkertrans");
|
||||
private int m_Width, m_Height;
|
||||
private int m_X, m_Y;
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ namespace Server.Gumps
|
|||
{
|
||||
public class GumpBackground : GumpEntry
|
||||
{
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer("resizepic");
|
||||
private static readonly byte[] m_LayoutName = Gump.StringToBuffer("resizepic");
|
||||
private int m_GumpID;
|
||||
private int m_Width, m_Height;
|
||||
private int m_X, m_Y;
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ namespace Server.Gumps
|
|||
|
||||
public class GumpButton : GumpEntry
|
||||
{
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer("button");
|
||||
private static readonly byte[] m_LayoutName = Gump.StringToBuffer("button");
|
||||
private int m_ButtonID;
|
||||
private int m_ID1, m_ID2;
|
||||
private int m_Param;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ namespace Server.Gumps
|
|||
{
|
||||
public class GumpCheck : GumpEntry
|
||||
{
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer("checkbox");
|
||||
private static readonly byte[] m_LayoutName = Gump.StringToBuffer("checkbox");
|
||||
private int m_ID1, m_ID2;
|
||||
private bool m_InitialState;
|
||||
private int m_SwitchID;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ namespace Server.Gumps
|
|||
{
|
||||
public class GumpGroup : GumpEntry
|
||||
{
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer("group");
|
||||
private static readonly byte[] m_LayoutName = Gump.StringToBuffer("group");
|
||||
private int m_Group;
|
||||
|
||||
public GumpGroup(int group) => m_Group = group;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ namespace Server.Gumps
|
|||
{
|
||||
public class GumpHtml : GumpEntry
|
||||
{
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer("htmlgump");
|
||||
private static readonly byte[] m_LayoutName = Gump.StringToBuffer("htmlgump");
|
||||
private bool m_Background, m_Scrollbar;
|
||||
private string m_Text;
|
||||
private int m_Width, m_Height;
|
||||
|
|
|
|||
|
|
@ -31,9 +31,9 @@ namespace Server.Gumps
|
|||
|
||||
public class GumpHtmlLocalized : GumpEntry
|
||||
{
|
||||
private static byte[] m_LayoutNamePlain = Gump.StringToBuffer("xmfhtmlgump");
|
||||
private static byte[] m_LayoutNameColor = Gump.StringToBuffer("xmfhtmlgumpcolor");
|
||||
private static byte[] m_LayoutNameArgs = Gump.StringToBuffer("xmfhtmltok");
|
||||
private static readonly byte[] m_LayoutNamePlain = Gump.StringToBuffer("xmfhtmlgump");
|
||||
private static readonly byte[] m_LayoutNameColor = Gump.StringToBuffer("xmfhtmlgumpcolor");
|
||||
private static readonly byte[] m_LayoutNameArgs = Gump.StringToBuffer("xmfhtmltok");
|
||||
private string m_Args;
|
||||
private bool m_Background, m_Scrollbar;
|
||||
private int m_Color;
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ namespace Server.Gumps
|
|||
{
|
||||
public class GumpImage : GumpEntry
|
||||
{
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer("gumppic");
|
||||
private static byte[] m_HueEquals = Gump.StringToBuffer(" hue=");
|
||||
private static readonly byte[] m_LayoutName = Gump.StringToBuffer("gumppic");
|
||||
private static readonly byte[] m_HueEquals = Gump.StringToBuffer(" hue=");
|
||||
private int m_GumpID;
|
||||
private int m_Hue;
|
||||
private int m_X, m_Y;
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ namespace Server.Gumps
|
|||
{
|
||||
public class GumpImageTileButton : GumpEntry
|
||||
{
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer("buttontileart");
|
||||
private static byte[] m_LayoutTooltip = Gump.StringToBuffer(" }{ tooltip");
|
||||
private static readonly byte[] m_LayoutName = Gump.StringToBuffer("buttontileart");
|
||||
private static readonly byte[] m_LayoutTooltip = Gump.StringToBuffer(" }{ tooltip");
|
||||
private int m_ButtonID;
|
||||
private int m_Height;
|
||||
private int m_Hue;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ namespace Server.Gumps
|
|||
{
|
||||
public class GumpImageTiled : GumpEntry
|
||||
{
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer("gumppictiled");
|
||||
private static readonly byte[] m_LayoutName = Gump.StringToBuffer("gumppictiled");
|
||||
private int m_GumpID;
|
||||
private int m_Width, m_Height;
|
||||
private int m_X, m_Y;
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ namespace Server.Gumps
|
|||
{
|
||||
public class GumpItem : GumpEntry
|
||||
{
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer("tilepic");
|
||||
private static byte[] m_LayoutNameHue = Gump.StringToBuffer("tilepichue");
|
||||
private static readonly byte[] m_LayoutName = Gump.StringToBuffer("tilepic");
|
||||
private static readonly byte[] m_LayoutNameHue = Gump.StringToBuffer("tilepichue");
|
||||
private int m_Hue;
|
||||
private int m_ItemID;
|
||||
private int m_X, m_Y;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ namespace Server.Gumps
|
|||
{
|
||||
public class GumpItemProperty : GumpEntry
|
||||
{
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer("itemproperty");
|
||||
private static readonly byte[] m_LayoutName = Gump.StringToBuffer("itemproperty");
|
||||
private uint m_Serial;
|
||||
|
||||
public GumpItemProperty(uint serial) => m_Serial = serial;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ namespace Server.Gumps
|
|||
{
|
||||
public class GumpLabel : GumpEntry
|
||||
{
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer("text");
|
||||
private static readonly byte[] m_LayoutName = Gump.StringToBuffer("text");
|
||||
private int m_Hue;
|
||||
private string m_Text;
|
||||
private int m_X, m_Y;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ namespace Server.Gumps
|
|||
{
|
||||
public class GumpLabelCropped : GumpEntry
|
||||
{
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer("croppedtext");
|
||||
private static readonly byte[] m_LayoutName = Gump.StringToBuffer("croppedtext");
|
||||
private int m_Hue;
|
||||
private string m_Text;
|
||||
private int m_Width, m_Height;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ namespace Server.Gumps
|
|||
{
|
||||
public class GumpPage : GumpEntry
|
||||
{
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer("page");
|
||||
private static readonly byte[] m_LayoutName = Gump.StringToBuffer("page");
|
||||
private int m_Page;
|
||||
|
||||
public GumpPage(int page) => m_Page = page;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ namespace Server.Gumps
|
|||
{
|
||||
public class GumpRadio : GumpEntry
|
||||
{
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer("radio");
|
||||
private static readonly byte[] m_LayoutName = Gump.StringToBuffer("radio");
|
||||
private int m_ID1, m_ID2;
|
||||
private bool m_InitialState;
|
||||
private int m_SwitchID;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ namespace Server.Gumps
|
|||
{
|
||||
public class GumpTextEntry : GumpEntry
|
||||
{
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer("textentry");
|
||||
private static readonly byte[] m_LayoutName = Gump.StringToBuffer("textentry");
|
||||
private int m_EntryID;
|
||||
private int m_Hue;
|
||||
private string m_InitialText;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ namespace Server.Gumps
|
|||
{
|
||||
public class GumpTextEntryLimited : GumpEntry
|
||||
{
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer("textentrylimited");
|
||||
private static readonly byte[] m_LayoutName = Gump.StringToBuffer("textentrylimited");
|
||||
private int m_EntryID;
|
||||
private int m_Hue;
|
||||
private string m_InitialText;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ namespace Server.Gumps
|
|||
{
|
||||
public class GumpTooltip : GumpEntry
|
||||
{
|
||||
private static byte[] m_LayoutName = Gump.StringToBuffer("tooltip");
|
||||
private static readonly byte[] m_LayoutName = Gump.StringToBuffer("tooltip");
|
||||
private int m_Number;
|
||||
|
||||
public GumpTooltip(int number) => m_Number = number;
|
||||
|
|
|
|||
|
|
@ -201,13 +201,13 @@ namespace Server
|
|||
|
||||
public class Item : IHued, IComparable<Item>, ISerializable, ISpawnable, IPropertyListObject
|
||||
{
|
||||
private BufferWriter m_SaveBuffer;
|
||||
public BufferWriter SaveBuffer { get { return m_SaveBuffer; } }
|
||||
private readonly BufferWriter m_SaveBuffer;
|
||||
public BufferWriter SaveBuffer => m_SaveBuffer;
|
||||
|
||||
public const int QuestItemHue = 0x4EA; // Hmmmm... "for EA"?
|
||||
public static readonly List<Item> EmptyItems = new List<Item>();
|
||||
|
||||
private static List<Item> m_DeltaQueue = new List<Item>();
|
||||
private static readonly List<Item> m_DeltaQueue = new List<Item>();
|
||||
|
||||
private static bool _processing;
|
||||
|
||||
|
|
|
|||
|
|
@ -36,8 +36,8 @@ namespace Server.Items
|
|||
|
||||
public class Container : Item
|
||||
{
|
||||
private static QueuePool m_QueuePool = new QueuePool(QueueRef<Container>.Generate, preGenerateCount: 2, maxRefrenceRetention: 5);
|
||||
private static List<Item> m_FindItemsList = new List<Item>();
|
||||
private static readonly QueuePool m_QueuePool = new QueuePool(QueueRef<Container>.Generate, preGenerateCount: 2, maxRefrenceRetention: 5);
|
||||
private static readonly List<Item> m_FindItemsList = new List<Item>();
|
||||
|
||||
private ContainerData m_ContainerData;
|
||||
|
||||
|
|
@ -200,7 +200,7 @@ namespace Server.Items
|
|||
|
||||
public virtual bool CheckHold(Mobile m, Item item, bool message, bool checkItems, int plusItems, int plusWeight)
|
||||
{
|
||||
if (m?.AccessLevel < AccessLevel.GameMaster)
|
||||
if (m == null || m.AccessLevel < AccessLevel.GameMaster)
|
||||
{
|
||||
if (IsDecoContainer)
|
||||
{
|
||||
|
|
@ -735,7 +735,7 @@ namespace Server.Items
|
|||
|
||||
private class GroupComparer : IComparer<Item>
|
||||
{
|
||||
private CheckItemGroup m_Grouper;
|
||||
private readonly CheckItemGroup m_Grouper;
|
||||
|
||||
public GroupComparer(CheckItemGroup grouper) => m_Grouper = grouper;
|
||||
|
||||
|
|
@ -754,8 +754,8 @@ namespace Server.Items
|
|||
|
||||
private struct ItemStackEntry
|
||||
{
|
||||
public Item m_StackItem;
|
||||
public Item m_DropItem;
|
||||
public readonly Item m_StackItem;
|
||||
public readonly Item m_DropItem;
|
||||
|
||||
public ItemStackEntry(Item stack, Item drop)
|
||||
{
|
||||
|
|
@ -1536,12 +1536,10 @@ namespace Server.Items
|
|||
{
|
||||
var container = queue.Dequeue();
|
||||
foreach (var item in container.Items)
|
||||
{
|
||||
if (item is T typedItem && predicate?.Invoke(typedItem) != false)
|
||||
items.Add(typedItem);
|
||||
else if (recurse && item is Container itemContainer)
|
||||
queue.Enqueue(itemContainer);
|
||||
}
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
|
@ -1583,7 +1581,7 @@ namespace Server.Items
|
|||
|
||||
public class ContainerData
|
||||
{
|
||||
private static Dictionary<int, ContainerData> m_Table;
|
||||
private static readonly Dictionary<int, ContainerData> m_Table;
|
||||
|
||||
static ContainerData()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,43 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace Microsoft.AspNetCore.Connections
|
||||
{
|
||||
public static class CorrelationIdGenerator
|
||||
{
|
||||
// Base32 encoding - in ascii sort order for easy text based sorting
|
||||
private static readonly char[] s_encode32Chars = "0123456789ABCDEFGHIJKLMNOPQRSTUV".ToCharArray();
|
||||
|
||||
// Seed the _lastConnectionId for this application instance with
|
||||
// the number of 100-nanosecond intervals that have elapsed since 12:00:00 midnight, January 1, 0001
|
||||
// for a roughly increasing _lastId over restarts
|
||||
private static long _lastId = DateTime.UtcNow.Ticks;
|
||||
|
||||
public static string GetNextId() => GenerateId(Interlocked.Increment(ref _lastId));
|
||||
|
||||
private static string GenerateId(long id)
|
||||
{
|
||||
return string.Create(13, id, (buffer, value) =>
|
||||
{
|
||||
char[] encode32Chars = s_encode32Chars;
|
||||
|
||||
buffer[12] = encode32Chars[value & 31];
|
||||
buffer[11] = encode32Chars[(value >> 5) & 31];
|
||||
buffer[10] = encode32Chars[(value >> 10) & 31];
|
||||
buffer[9] = encode32Chars[(value >> 15) & 31];
|
||||
buffer[8] = encode32Chars[(value >> 20) & 31];
|
||||
buffer[7] = encode32Chars[(value >> 25) & 31];
|
||||
buffer[6] = encode32Chars[(value >> 30) & 31];
|
||||
buffer[5] = encode32Chars[(value >> 35) & 31];
|
||||
buffer[4] = encode32Chars[(value >> 40) & 31];
|
||||
buffer[3] = encode32Chars[(value >> 45) & 31];
|
||||
buffer[2] = encode32Chars[(value >> 50) & 31];
|
||||
buffer[1] = encode32Chars[(value >> 55) & 31];
|
||||
buffer[0] = encode32Chars[(value >> 60) & 31];
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Libuv
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||
{
|
||||
interface IAsyncDisposable
|
||||
{
|
||||
|
|
@ -4,9 +4,9 @@
|
|||
using System;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Libuv
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||
{
|
||||
public interface ILibuvTrace : ILogger
|
||||
internal interface ILibuvTrace : ILogger
|
||||
{
|
||||
void ConnectionRead(string connectionId, int count);
|
||||
|
||||
|
|
@ -5,11 +5,11 @@ using System;
|
|||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using Libuv.Internal;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
||||
|
||||
namespace Libuv
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||
{
|
||||
public class LibuvAwaitable<TRequest> : ICriticalNotifyCompletion where TRequest : UvRequest
|
||||
internal class LibuvAwaitable<TRequest> : ICriticalNotifyCompletion where TRequest : UvRequest
|
||||
{
|
||||
private static readonly Action _callbackCompleted = () => { };
|
||||
|
||||
|
|
@ -53,8 +53,7 @@ namespace Libuv
|
|||
{
|
||||
// There should never be a race between IsCompleted and OnCompleted since both operations
|
||||
// should always be on the libuv thread
|
||||
if (ReferenceEquals(_callback, _callbackCompleted))
|
||||
Debug.Fail($"{typeof(LibuvAwaitable<TRequest>)}.{nameof(OnCompleted)} raced with {nameof(IsCompleted)}, scheduling callback.");
|
||||
if (ReferenceEquals(_callback, _callbackCompleted)) Debug.Fail($"{typeof(LibuvAwaitable<TRequest>)}.{nameof(OnCompleted)} raced with {nameof(IsCompleted)}, scheduling callback.");
|
||||
|
||||
_callback = continuation;
|
||||
}
|
||||
|
|
@ -65,7 +64,7 @@ namespace Libuv
|
|||
}
|
||||
}
|
||||
|
||||
public struct UvWriteResult
|
||||
internal struct UvWriteResult
|
||||
{
|
||||
public int Status { get; }
|
||||
public UvException Error { get; }
|
||||
|
|
@ -8,19 +8,21 @@ using System.IO.Pipelines;
|
|||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Libuv.Internal;
|
||||
using Microsoft.AspNetCore.Connections;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Libuv
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||
{
|
||||
public partial class LibuvConnection : TransportConnection
|
||||
internal partial class LibuvConnection : TransportConnection
|
||||
{
|
||||
private static readonly int MinAllocBufferSize = SlabMemoryPool.BlockSize / 2;
|
||||
|
||||
private static readonly Action<UvStreamHandle, int, object> _readCallback = ReadCallback;
|
||||
private static readonly Action<UvStreamHandle, int, object> _readCallback =
|
||||
(handle, status, state) => ReadCallback(handle, status, state);
|
||||
|
||||
private static readonly Func<UvStreamHandle, int, object, LibuvFunctions.uv_buf_t> _allocCallback = AllocCallback;
|
||||
private static readonly Func<UvStreamHandle, int, object, LibuvFunctions.uv_buf_t> _allocCallback =
|
||||
(handle, suggestedSize, state) => AllocCallback(handle, suggestedSize, state);
|
||||
|
||||
private readonly UvStreamHandle _socket;
|
||||
private readonly CancellationTokenSource _connectionClosedTokenSource = new CancellationTokenSource();
|
||||
|
|
@ -243,7 +245,7 @@ namespace Libuv
|
|||
state._waitForConnectionClosedTcs.TrySetResult(null);
|
||||
},
|
||||
this,
|
||||
false);
|
||||
preferLocal: false);
|
||||
}
|
||||
|
||||
private async Task ApplyBackpressureAsync(ValueTask<FlushResult> flushTask)
|
||||
|
|
@ -282,16 +284,18 @@ namespace Libuv
|
|||
// The operation was canceled by the server not the client. No need for additional logs.
|
||||
return new ConnectionAbortedException(uvError.Message, uvError);
|
||||
}
|
||||
|
||||
if (LibuvConstants.IsConnectionReset(uvError.StatusCode))
|
||||
else if (LibuvConstants.IsConnectionReset(uvError.StatusCode))
|
||||
{
|
||||
// Log connection resets at a lower (Debug) level.
|
||||
Log.ConnectionReset(ConnectionId);
|
||||
return new ConnectionResetException(uvError.Message, uvError);
|
||||
}
|
||||
// This is unexpected.
|
||||
Log.ConnectionError(ConnectionId, uvError);
|
||||
return new IOException(uvError.Message, uvError);
|
||||
else
|
||||
{
|
||||
// This is unexpected.
|
||||
Log.ConnectionError(ConnectionId, uvError);
|
||||
return new IOException(uvError.Message, uvError);
|
||||
}
|
||||
}
|
||||
|
||||
private void CancelConnectionClosedToken()
|
||||
|
|
@ -7,15 +7,14 @@ using System.Linq;
|
|||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Libuv.Internal;
|
||||
using Microsoft.AspNetCore.Connections;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Server;
|
||||
|
||||
namespace Libuv
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||
{
|
||||
public class LibuvConnectionListener : IConnectionListener
|
||||
internal class LibuvConnectionListener : IConnectionListener
|
||||
{
|
||||
private readonly List<ListenerContext> _listeners = new List<ListenerContext>();
|
||||
private IAsyncEnumerator<LibuvConnection> _acceptEnumerator;
|
||||
|
|
@ -63,8 +62,7 @@ namespace Libuv
|
|||
|
||||
var disposeTasks = _listeners.Select(listener => ((IAsyncDisposable)listener).DisposeAsync()).ToArray();
|
||||
|
||||
if (!await WaitAsync(Task.WhenAll(disposeTasks), TimeSpan.FromSeconds(5)).ConfigureAwait(false))
|
||||
Log.LogError(0, null, "Disposing listeners failed");
|
||||
if (!await WaitAsync(Task.WhenAll(disposeTasks), TimeSpan.FromSeconds(5)).ConfigureAwait(false)) Log.LogError(0, null, "Disposing listeners failed");
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -101,14 +99,9 @@ namespace Libuv
|
|||
}
|
||||
|
||||
Threads.Clear();
|
||||
#if DEBUG && !INNER_LOOP
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
#endif
|
||||
}
|
||||
|
||||
public async Task BindAsync()
|
||||
internal async Task BindAsync()
|
||||
{
|
||||
// TODO: Move thread management to LibuvTransportFactory
|
||||
// TODO: Split endpoint management from thread management
|
||||
|
|
@ -127,7 +120,7 @@ namespace Libuv
|
|||
}
|
||||
else
|
||||
{
|
||||
var pipeName = (Core.IsWindows ? @"\\.\pipe\kestrel_" : "/tmp/kestrel_") + Guid.NewGuid().ToString("n");
|
||||
var pipeName = (Libuv.IsWindows ? @"\\.\pipe\kestrel_" : "/tmp/kestrel_") + Guid.NewGuid().ToString("n");
|
||||
var pipeMessage = Guid.NewGuid().ToByteArray();
|
||||
|
||||
var listenerPrimary = new ListenerPrimary(TransportContext);
|
||||
|
|
@ -171,7 +164,7 @@ namespace Libuv
|
|||
while (remainingSlots > 0)
|
||||
{
|
||||
// Calling GetAwaiter().GetResult() is safe because we know the task is completed
|
||||
var (connection, slot) = (await Task.WhenAny(slots)).GetAwaiter().GetResult();
|
||||
(var connection, var slot) = (await Task.WhenAny(slots)).GetAwaiter().GetResult();
|
||||
|
||||
// If the connection is null then the listener was closed
|
||||
if (connection == null)
|
||||
|
|
@ -2,11 +2,11 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
using Server;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Libuv
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||
{
|
||||
public static class LibuvConstants
|
||||
internal static class LibuvConstants
|
||||
{
|
||||
public const int EOF = -4095;
|
||||
public static readonly int? ECONNRESET = GetECONNRESET();
|
||||
|
|
@ -22,76 +22,69 @@ namespace Libuv
|
|||
|
||||
private static int? GetECONNRESET()
|
||||
{
|
||||
if (Core.IsWindows)
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
return -4077;
|
||||
if (Core.IsLinux)
|
||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
return -104;
|
||||
if (Core.IsDarwin)
|
||||
return -5;
|
||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) return -54;
|
||||
return null;
|
||||
}
|
||||
|
||||
private static int? GetEPIPE()
|
||||
{
|
||||
if (Core.IsWindows)
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
return -4047;
|
||||
if (Core.IsLinux)
|
||||
return -32;
|
||||
if (Core.IsDarwin)
|
||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
return -32;
|
||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) return -32;
|
||||
return null;
|
||||
}
|
||||
|
||||
private static int? GetENOTCONN()
|
||||
{
|
||||
if (Core.IsWindows)
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
return -4053;
|
||||
if (Core.IsLinux)
|
||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
return -107;
|
||||
if (Core.IsDarwin)
|
||||
return -57;
|
||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) return -57;
|
||||
return null;
|
||||
}
|
||||
|
||||
private static int? GetEINVAL()
|
||||
{
|
||||
if (Core.IsWindows)
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
return -4071;
|
||||
if (Core.IsLinux)
|
||||
return -22;
|
||||
if (Core.IsDarwin)
|
||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
return -22;
|
||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) return -22;
|
||||
return null;
|
||||
}
|
||||
|
||||
private static int? GetEADDRINUSE()
|
||||
{
|
||||
if (Core.IsWindows)
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
return -4091;
|
||||
if (Core.IsLinux)
|
||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
return -98;
|
||||
if (Core.IsDarwin)
|
||||
return -48;
|
||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) return -48;
|
||||
return null;
|
||||
}
|
||||
|
||||
private static int? GetENOTSUP()
|
||||
{
|
||||
if (Core.IsLinux)
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
return -95;
|
||||
if (Core.IsDarwin)
|
||||
return -45;
|
||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) return -45;
|
||||
return null;
|
||||
}
|
||||
|
||||
private static int? GetECANCELED()
|
||||
{
|
||||
if (Core.IsWindows)
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
return -4081;
|
||||
if (Core.IsLinux)
|
||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
return -125;
|
||||
if (Core.IsDarwin)
|
||||
return -89;
|
||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) return -89;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -4,11 +4,11 @@
|
|||
using System;
|
||||
using System.IO.Pipelines;
|
||||
using System.Threading.Tasks;
|
||||
using Libuv.Internal;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
||||
|
||||
namespace Libuv
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||
{
|
||||
public class LibuvOutputConsumer
|
||||
internal class LibuvOutputConsumer
|
||||
{
|
||||
private readonly LibuvThread _thread;
|
||||
private readonly UvStreamHandle _socket;
|
||||
|
|
@ -9,13 +9,13 @@ using System.IO.Pipelines;
|
|||
using System.Runtime.ExceptionServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Libuv.Internal;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Libuv
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||
{
|
||||
public class LibuvThread : PipeScheduler
|
||||
internal class LibuvThread : PipeScheduler
|
||||
{
|
||||
// maximum times the work queues swapped and are processed in a single pass
|
||||
// as completing a task may immediately have write data to put on the network
|
||||
|
|
@ -35,8 +35,8 @@ namespace Libuv
|
|||
private readonly object _workSync = new object();
|
||||
private readonly object _closeHandleSync = new object();
|
||||
private readonly object _startSync = new object();
|
||||
private bool _stopImmediate;
|
||||
private bool _initCompleted;
|
||||
private bool _stopImmediate = false;
|
||||
private bool _initCompleted = false;
|
||||
private Exception _closeError;
|
||||
private readonly ILibuvTrace _log;
|
||||
|
||||
|
|
@ -60,9 +60,9 @@ namespace Libuv
|
|||
#endif
|
||||
|
||||
#if !DEBUG
|
||||
// Mark the thread as being as unimportant to keeping the process alive.
|
||||
// Don't do this for debug builds, so we know if the thread isn't terminating.
|
||||
_thread.IsBackground = true;
|
||||
// Mark the thread as being as unimportant to keeping the process alive.
|
||||
// Don't do this for debug builds, so we know if the thread isn't terminating.
|
||||
_thread.IsBackground = true;
|
||||
#endif
|
||||
QueueCloseHandle = PostCloseHandle;
|
||||
QueueCloseAsyncHandle = EnqueueCloseHandle;
|
||||
|
|
@ -76,10 +76,6 @@ namespace Libuv
|
|||
|
||||
public WriteReqPool WriteReqPool { get; }
|
||||
|
||||
#if DEBUG
|
||||
public List<WeakReference> Requests { get; } = new List<WeakReference>();
|
||||
#endif
|
||||
|
||||
public Exception FatalError => _closeError;
|
||||
|
||||
public Action<Action<IntPtr>, IntPtr> QueueCloseHandle { get; }
|
||||
|
|
@ -129,18 +125,6 @@ namespace Libuv
|
|||
if (_closeError != null) ExceptionDispatchInfo.Capture(_closeError).Throw();
|
||||
}
|
||||
|
||||
#if DEBUG && !INNER_LOOP
|
||||
private void CheckUvReqLeaks()
|
||||
{
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
||||
// Detect leaks in UvRequest objects
|
||||
foreach (var request in Requests) Debug.Assert(request.Target == null, $"{request.Target?.GetType()} object is still alive.");
|
||||
}
|
||||
#endif
|
||||
|
||||
private void AllowStop()
|
||||
{
|
||||
_post.Unreference();
|
||||
|
|
@ -320,11 +304,6 @@ namespace Libuv
|
|||
}
|
||||
WriteReqPool.Dispose();
|
||||
_threadTcs.SetResult(null);
|
||||
|
||||
#if DEBUG && !INNER_LOOP
|
||||
// Check for handle leaks after disposing everything
|
||||
CheckUvReqLeaks();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -406,8 +385,7 @@ namespace Libuv
|
|||
return wasWork;
|
||||
}
|
||||
|
||||
private static async Task<bool> WaitAsync(Task task, TimeSpan timeout) =>
|
||||
await Task.WhenAny(task, Task.Delay(timeout)).ConfigureAwait(false) == task;
|
||||
private static async Task<bool> WaitAsync(Task task, TimeSpan timeout) => await Task.WhenAny(task, Task.Delay(timeout)).ConfigureAwait(false) == task;
|
||||
|
||||
public override void Schedule(Action<object> action, object state)
|
||||
{
|
||||
|
|
@ -4,9 +4,9 @@
|
|||
using System;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Libuv
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||
{
|
||||
public class LibuvTrace : ILibuvTrace
|
||||
internal class LibuvTrace : ILibuvTrace
|
||||
{
|
||||
// ConnectionRead: Reserved: 3
|
||||
|
||||
|
|
@ -3,9 +3,9 @@
|
|||
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace Libuv
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||
{
|
||||
public class LibuvTransportContext
|
||||
internal class LibuvTransportContext
|
||||
{
|
||||
public LibuvTransportOptions Options { get; set; }
|
||||
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Connections;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||
{
|
||||
internal class LibuvTransportFactory : IConnectionListenerFactory
|
||||
{
|
||||
private readonly LibuvTransportContext _baseTransportContext;
|
||||
|
||||
public LibuvTransportFactory(
|
||||
IOptions<LibuvTransportOptions> options,
|
||||
IHostApplicationLifetime applicationLifetime,
|
||||
ILoggerFactory loggerFactory)
|
||||
{
|
||||
if (options == null) throw new ArgumentNullException(nameof(options));
|
||||
if (applicationLifetime == null) throw new ArgumentNullException(nameof(applicationLifetime));
|
||||
if (loggerFactory == null) throw new ArgumentNullException(nameof(loggerFactory));
|
||||
|
||||
var logger = loggerFactory.CreateLogger("Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv");
|
||||
var trace = new LibuvTrace(logger);
|
||||
|
||||
var threadCount = options.Value.ThreadCount;
|
||||
|
||||
if (threadCount <= 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(threadCount),
|
||||
threadCount,
|
||||
"ThreadCount must be positive.");
|
||||
|
||||
if (!LibuvConstants.ECONNRESET.HasValue) trace.LogWarning("Unable to determine ECONNRESET value on this platform.");
|
||||
|
||||
if (!LibuvConstants.EADDRINUSE.HasValue) trace.LogWarning("Unable to determine EADDRINUSE value on this platform.");
|
||||
|
||||
_baseTransportContext = new LibuvTransportContext
|
||||
{
|
||||
Options = options.Value,
|
||||
AppLifetime = applicationLifetime,
|
||||
Log = trace,
|
||||
};
|
||||
}
|
||||
|
||||
public async ValueTask<IConnectionListener> BindAsync(EndPoint endpoint, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var transportContext = new LibuvTransportContext
|
||||
{
|
||||
Options = _baseTransportContext.Options,
|
||||
AppLifetime = _baseTransportContext.AppLifetime,
|
||||
Log = _baseTransportContext.Log
|
||||
};
|
||||
|
||||
var transport = new LibuvConnectionListener(transportContext, endpoint);
|
||||
await transport.BindAsync();
|
||||
return transport;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,16 +5,16 @@ using System;
|
|||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading.Tasks;
|
||||
using Libuv.Internal;
|
||||
using Microsoft.AspNetCore.Connections;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Libuv
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for listeners in Kestrel. Listens for incoming connections
|
||||
/// </summary>
|
||||
public class Listener : ListenerContext, IAsyncDisposable
|
||||
internal class Listener : ListenerContext, IAsyncDisposable
|
||||
{
|
||||
// REVIEW: This needs to be bounded and we need a strategy for what to do when the queue is full
|
||||
private bool _closed;
|
||||
|
|
@ -46,13 +46,17 @@ namespace Libuv
|
|||
/// </summary>
|
||||
private UvStreamHandle CreateListenSocket()
|
||||
{
|
||||
return EndPoint switch
|
||||
switch (EndPoint)
|
||||
{
|
||||
IPEndPoint _ => ListenTcp(false),
|
||||
UnixDomainSocketEndPoint _ => ListenPipe(false),
|
||||
FileHandleEndPoint _ => ListenHandle(),
|
||||
_ => throw new NotSupportedException()
|
||||
};
|
||||
case IPEndPoint _:
|
||||
return ListenTcp(useFileHandle: false);
|
||||
case UnixDomainSocketEndPoint _:
|
||||
return ListenPipe(useFileHandle: false);
|
||||
case FileHandleEndPoint _:
|
||||
return ListenHandle();
|
||||
default:
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
|
||||
private UvTcpHandle ListenTcp(bool useFileHandle)
|
||||
|
|
@ -62,7 +66,7 @@ namespace Libuv
|
|||
try
|
||||
{
|
||||
socket.Init(Thread.Loop, Thread.QueueCloseHandle);
|
||||
socket.NoDelay(true);
|
||||
socket.NoDelay(TransportContext.Options.NoDelay);
|
||||
|
||||
if (!useFileHandle)
|
||||
{
|
||||
|
|
@ -117,9 +121,9 @@ namespace Libuv
|
|||
case FileHandleType.Auto:
|
||||
break;
|
||||
case FileHandleType.Tcp:
|
||||
return ListenTcp(true);
|
||||
return ListenTcp(useFileHandle: true);
|
||||
case FileHandleType.Pipe:
|
||||
return ListenPipe(true);
|
||||
return ListenPipe(useFileHandle: true);
|
||||
default:
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
|
@ -127,7 +131,7 @@ namespace Libuv
|
|||
UvStreamHandle handle;
|
||||
try
|
||||
{
|
||||
handle = ListenTcp(true);
|
||||
handle = ListenTcp(useFileHandle: true);
|
||||
EndPoint = new FileHandleEndPoint(handleEndPoint.FileHandle, FileHandleType.Tcp);
|
||||
return handle;
|
||||
}
|
||||
|
|
@ -136,7 +140,7 @@ namespace Libuv
|
|||
Log.LogDebug(0, exception, "Listener.ListenHandle");
|
||||
}
|
||||
|
||||
handle = ListenPipe(true);
|
||||
handle = ListenPipe(useFileHandle: true);
|
||||
EndPoint = new FileHandleEndPoint(handleEndPoint.FileHandle, FileHandleType.Pipe);
|
||||
return handle;
|
||||
}
|
||||
|
|
@ -9,13 +9,13 @@ using System.Net.Sockets;
|
|||
using System.Threading;
|
||||
using System.Threading.Channels;
|
||||
using System.Threading.Tasks;
|
||||
using Libuv.Internal;
|
||||
using Microsoft.AspNetCore.Connections;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Libuv
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||
{
|
||||
public class ListenerContext
|
||||
internal class ListenerContext
|
||||
{
|
||||
// Single reader, single writer queue since all writes happen from the uv thread and reads happen sequentially
|
||||
private readonly Channel<LibuvConnection> _acceptQueue = Channel.CreateUnbounded<LibuvConnection>(new UnboundedChannelOptions
|
||||
|
|
@ -115,7 +115,7 @@ namespace Libuv
|
|||
try
|
||||
{
|
||||
socket.Init(Thread.Loop, Thread.QueueCloseHandle);
|
||||
socket.NoDelay(true);
|
||||
socket.NoDelay(TransportContext.Options.NoDelay);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
|
@ -152,17 +152,14 @@ namespace Libuv
|
|||
{
|
||||
var fileHandleEndPoint = (FileHandleEndPoint)EndPoint;
|
||||
|
||||
switch (fileHandleEndPoint.FileHandleType)
|
||||
return fileHandleEndPoint.FileHandleType switch
|
||||
{
|
||||
case FileHandleType.Auto:
|
||||
throw new InvalidOperationException("Cannot accept on a non-specific file handle, listen should be performed first.");
|
||||
case FileHandleType.Tcp:
|
||||
return AcceptTcp();
|
||||
case FileHandleType.Pipe:
|
||||
return AcceptPipe();
|
||||
default:
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
FileHandleType.Auto => throw new InvalidOperationException(
|
||||
"Cannot accept on a non-specific file handle, listen should be performed first."),
|
||||
FileHandleType.Tcp => (UvStreamHandle)AcceptTcp(),
|
||||
FileHandleType.Pipe => AcceptPipe(),
|
||||
_ => throw new NotSupportedException()
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,19 +7,16 @@ using System.IO;
|
|||
using System.Net;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using Libuv.Internal;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Server;
|
||||
|
||||
#pragma warning disable 169
|
||||
|
||||
namespace Libuv
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// A primary listener waits for incoming connections on a specified socket. Incoming
|
||||
/// connections may be passed to a secondary listener to handle.
|
||||
/// </summary>
|
||||
public class ListenerPrimary : Listener
|
||||
internal class ListenerPrimary : Listener
|
||||
{
|
||||
// The list of pipes that can be dispatched to (where we've confirmed the _pipeMessage)
|
||||
private readonly List<UvPipeHandle> _dispatchPipes = new List<UvPipeHandle>();
|
||||
|
|
@ -29,7 +26,7 @@ namespace Libuv
|
|||
private string _pipeName;
|
||||
private byte[] _pipeMessage;
|
||||
private IntPtr _fileCompletionInfoPtr;
|
||||
private bool _tryDetachFromIOCP = Core.IsWindows;
|
||||
private bool _tryDetachFromIOCP = PlatformApis.IsWindows;
|
||||
|
||||
// this message is passed to write2 because it must be non-zero-length,
|
||||
// but it has no other functional significance
|
||||
|
|
@ -151,15 +148,17 @@ namespace Libuv
|
|||
Thread.Loop.Libuv.uv_fileno(handle, ref socket);
|
||||
|
||||
if (NtSetInformationFile(socket, out statusBlock, _fileCompletionInfoPtr,
|
||||
(uint)Marshal.SizeOf<FILE_COMPLETION_INFORMATION>(), FileReplaceCompletionInformation) == STATUS_INVALID_INFO_CLASS)
|
||||
(uint)Marshal.SizeOf<FILE_COMPLETION_INFORMATION>(), FileReplaceCompletionInformation) == STATUS_INVALID_INFO_CLASS)
|
||||
// Replacing IOCP information is only supported on Windows 8.1 or newer
|
||||
_tryDetachFromIOCP = false;
|
||||
}
|
||||
|
||||
private struct IO_STATUS_BLOCK
|
||||
{
|
||||
#pragma warning disable 169
|
||||
uint status;
|
||||
ulong information;
|
||||
#pragma warning restore 169
|
||||
}
|
||||
|
||||
private struct FILE_COMPLETION_INFORMATION
|
||||
|
|
@ -219,7 +218,7 @@ namespace Libuv
|
|||
{
|
||||
// This is an unexpected immediate termination of the dispatch pipe most likely caused by an
|
||||
// external process scanning the pipe, so don't we don't log it too severely.
|
||||
// https://github.com/aspnet/AspNetCore/issues/4741
|
||||
// https://github.com/dotnet/aspnetcore/issues/4741
|
||||
|
||||
dispatchPipe.Dispose();
|
||||
_bufHandle.Free();
|
||||
|
|
@ -6,16 +6,16 @@ using System.Net;
|
|||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Libuv.Internal;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Libuv
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// A secondary listener is delegated requests from a primary listener via a named pipe or
|
||||
/// UNIX domain socket.
|
||||
/// </summary>
|
||||
public class ListenerSecondary : ListenerContext, IAsyncDisposable
|
||||
internal class ListenerSecondary : ListenerContext, IAsyncDisposable
|
||||
{
|
||||
private string _pipeName;
|
||||
private byte[] _pipeMessage;
|
||||
|
|
@ -4,14 +4,15 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Server;
|
||||
|
||||
namespace Libuv.Internal
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking
|
||||
{
|
||||
public class LibuvFunctions
|
||||
internal class LibuvFunctions
|
||||
{
|
||||
public LibuvFunctions()
|
||||
{
|
||||
IsWindows = PlatformApis.IsWindows;
|
||||
|
||||
_uv_loop_init = NativeMethods.uv_loop_init;
|
||||
_uv_loop_close = NativeMethods.uv_loop_close;
|
||||
_uv_run = NativeMethods.uv_run;
|
||||
|
|
@ -63,6 +64,8 @@ namespace Libuv.Internal
|
|||
{
|
||||
}
|
||||
|
||||
public readonly bool IsWindows;
|
||||
|
||||
public void ThrowIfErrored(int statusCode)
|
||||
{
|
||||
// Note: method is explicitly small so the success case is easily inlined
|
||||
|
|
@ -83,47 +86,51 @@ namespace Libuv.Internal
|
|||
error = statusCode < 0 ? GetError(statusCode) : null;
|
||||
}
|
||||
|
||||
// Note: method marked as NoInlining so it doesn't bloat either of the two preceding functions
|
||||
// Check and ThrowError and alter their jit heuristics.
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private UvException GetError(int statusCode) =>
|
||||
new UvException($"Error {statusCode} {err_name(statusCode)} {strerror(statusCode)}", statusCode);
|
||||
private UvException GetError(int statusCode)
|
||||
{
|
||||
// Note: method marked as NoInlining so it doesn't bloat either of the two preceding functions
|
||||
// Check and ThrowError and alter their jit heuristics.
|
||||
var errorName = err_name(statusCode);
|
||||
var errorDescription = strerror(statusCode);
|
||||
return new UvException("Error " + statusCode + " " + errorName + " " + errorDescription, statusCode);
|
||||
}
|
||||
|
||||
public Func<UvLoopHandle, int> _uv_loop_init;
|
||||
protected Func<UvLoopHandle, int> _uv_loop_init;
|
||||
public void loop_init(UvLoopHandle handle)
|
||||
{
|
||||
ThrowIfErrored(_uv_loop_init(handle));
|
||||
}
|
||||
|
||||
public Func<IntPtr, int> _uv_loop_close;
|
||||
protected Func<IntPtr, int> _uv_loop_close;
|
||||
public void loop_close(UvLoopHandle handle)
|
||||
{
|
||||
handle.Validate(true);
|
||||
handle.Validate(closed: true);
|
||||
ThrowIfErrored(_uv_loop_close(handle.InternalGetHandle()));
|
||||
}
|
||||
|
||||
public Func<UvLoopHandle, int, int> _uv_run;
|
||||
protected Func<UvLoopHandle, int, int> _uv_run;
|
||||
public void run(UvLoopHandle handle, int mode)
|
||||
{
|
||||
handle.Validate();
|
||||
ThrowIfErrored(_uv_run(handle, mode));
|
||||
}
|
||||
|
||||
public Action<UvLoopHandle> _uv_stop;
|
||||
protected Action<UvLoopHandle> _uv_stop;
|
||||
public void stop(UvLoopHandle handle)
|
||||
{
|
||||
handle.Validate();
|
||||
_uv_stop(handle);
|
||||
}
|
||||
|
||||
public Action<UvHandle> _uv_ref;
|
||||
protected Action<UvHandle> _uv_ref;
|
||||
public void @ref(UvHandle handle)
|
||||
{
|
||||
handle.Validate();
|
||||
_uv_ref(handle);
|
||||
}
|
||||
|
||||
public Action<UvHandle> _uv_unref;
|
||||
protected Action<UvHandle> _uv_unref;
|
||||
public void unref(UvHandle handle)
|
||||
{
|
||||
handle.Validate();
|
||||
|
|
@ -131,8 +138,8 @@ namespace Libuv.Internal
|
|||
}
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate int uv_fileno_func(UvHandle handle, ref IntPtr socket);
|
||||
public uv_fileno_func _uv_fileno;
|
||||
protected delegate int uv_fileno_func(UvHandle handle, ref IntPtr socket);
|
||||
protected uv_fileno_func _uv_fileno;
|
||||
public void uv_fileno(UvHandle handle, ref IntPtr socket)
|
||||
{
|
||||
handle.Validate();
|
||||
|
|
@ -141,10 +148,10 @@ namespace Libuv.Internal
|
|||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate void uv_close_cb(IntPtr handle);
|
||||
public Action<IntPtr, uv_close_cb> _uv_close;
|
||||
protected Action<IntPtr, uv_close_cb> _uv_close;
|
||||
public void close(UvHandle handle, uv_close_cb close_cb)
|
||||
{
|
||||
handle.Validate(true);
|
||||
handle.Validate(closed: true);
|
||||
_uv_close(handle.InternalGetHandle(), close_cb);
|
||||
}
|
||||
|
||||
|
|
@ -155,7 +162,7 @@ namespace Libuv.Internal
|
|||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate void uv_async_cb(IntPtr handle);
|
||||
public Func<UvLoopHandle, UvAsyncHandle, uv_async_cb, int> _uv_async_init;
|
||||
protected Func<UvLoopHandle, UvAsyncHandle, uv_async_cb, int> _uv_async_init;
|
||||
public void async_init(UvLoopHandle loop, UvAsyncHandle handle, uv_async_cb cb)
|
||||
{
|
||||
loop.Validate();
|
||||
|
|
@ -163,19 +170,19 @@ namespace Libuv.Internal
|
|||
ThrowIfErrored(_uv_async_init(loop, handle, cb));
|
||||
}
|
||||
|
||||
public Func<UvAsyncHandle, int> _uv_async_send;
|
||||
protected Func<UvAsyncHandle, int> _uv_async_send;
|
||||
public void async_send(UvAsyncHandle handle)
|
||||
{
|
||||
ThrowIfErrored(_uv_async_send(handle));
|
||||
}
|
||||
|
||||
public Func<IntPtr, int> _uv_unsafe_async_send;
|
||||
protected Func<IntPtr, int> _uv_unsafe_async_send;
|
||||
public void unsafe_async_send(IntPtr handle)
|
||||
{
|
||||
ThrowIfErrored(_uv_unsafe_async_send(handle));
|
||||
}
|
||||
|
||||
public Func<UvLoopHandle, UvTcpHandle, int> _uv_tcp_init;
|
||||
protected Func<UvLoopHandle, UvTcpHandle, int> _uv_tcp_init;
|
||||
public void tcp_init(UvLoopHandle loop, UvTcpHandle handle)
|
||||
{
|
||||
loop.Validate();
|
||||
|
|
@ -183,29 +190,29 @@ namespace Libuv.Internal
|
|||
ThrowIfErrored(_uv_tcp_init(loop, handle));
|
||||
}
|
||||
|
||||
public delegate int uv_tcp_bind_func(UvTcpHandle handle, ref SockAddr addr, int flags);
|
||||
public uv_tcp_bind_func _uv_tcp_bind;
|
||||
protected delegate int uv_tcp_bind_func(UvTcpHandle handle, ref SockAddr addr, int flags);
|
||||
protected uv_tcp_bind_func _uv_tcp_bind;
|
||||
public void tcp_bind(UvTcpHandle handle, ref SockAddr addr, int flags)
|
||||
{
|
||||
handle.Validate();
|
||||
ThrowIfErrored(_uv_tcp_bind(handle, ref addr, flags));
|
||||
}
|
||||
|
||||
public Func<UvTcpHandle, IntPtr, int> _uv_tcp_open;
|
||||
protected Func<UvTcpHandle, IntPtr, int> _uv_tcp_open;
|
||||
public void tcp_open(UvTcpHandle handle, IntPtr hSocket)
|
||||
{
|
||||
handle.Validate();
|
||||
ThrowIfErrored(_uv_tcp_open(handle, hSocket));
|
||||
}
|
||||
|
||||
public Func<UvTcpHandle, int, int> _uv_tcp_nodelay;
|
||||
protected Func<UvTcpHandle, int, int> _uv_tcp_nodelay;
|
||||
public void tcp_nodelay(UvTcpHandle handle, bool enable)
|
||||
{
|
||||
handle.Validate();
|
||||
ThrowIfErrored(_uv_tcp_nodelay(handle, enable ? 1 : 0));
|
||||
}
|
||||
|
||||
public Func<UvLoopHandle, UvPipeHandle, int, int> _uv_pipe_init;
|
||||
protected Func<UvLoopHandle, UvPipeHandle, int, int> _uv_pipe_init;
|
||||
public void pipe_init(UvLoopHandle loop, UvPipeHandle handle, bool ipc)
|
||||
{
|
||||
loop.Validate();
|
||||
|
|
@ -213,14 +220,14 @@ namespace Libuv.Internal
|
|||
ThrowIfErrored(_uv_pipe_init(loop, handle, ipc ? -1 : 0));
|
||||
}
|
||||
|
||||
public Func<UvPipeHandle, string, int> _uv_pipe_bind;
|
||||
protected Func<UvPipeHandle, string, int> _uv_pipe_bind;
|
||||
public void pipe_bind(UvPipeHandle handle, string name)
|
||||
{
|
||||
handle.Validate();
|
||||
ThrowIfErrored(_uv_pipe_bind(handle, name));
|
||||
}
|
||||
|
||||
public Func<UvPipeHandle, IntPtr, int> _uv_pipe_open;
|
||||
protected Func<UvPipeHandle, IntPtr, int> _uv_pipe_open;
|
||||
public void pipe_open(UvPipeHandle handle, IntPtr hSocket)
|
||||
{
|
||||
handle.Validate();
|
||||
|
|
@ -229,14 +236,14 @@ namespace Libuv.Internal
|
|||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate void uv_connection_cb(IntPtr server, int status);
|
||||
public Func<UvStreamHandle, int, uv_connection_cb, int> _uv_listen;
|
||||
protected Func<UvStreamHandle, int, uv_connection_cb, int> _uv_listen;
|
||||
public void listen(UvStreamHandle handle, int backlog, uv_connection_cb cb)
|
||||
{
|
||||
handle.Validate();
|
||||
ThrowIfErrored(_uv_listen(handle, backlog, cb));
|
||||
}
|
||||
|
||||
public Func<UvStreamHandle, UvStreamHandle, int> _uv_accept;
|
||||
protected Func<UvStreamHandle, UvStreamHandle, int> _uv_accept;
|
||||
public void accept(UvStreamHandle server, UvStreamHandle client)
|
||||
{
|
||||
server.Validate();
|
||||
|
|
@ -246,7 +253,7 @@ namespace Libuv.Internal
|
|||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate void uv_connect_cb(IntPtr req, int status);
|
||||
public Action<UvConnectRequest, UvPipeHandle, string, uv_connect_cb> _uv_pipe_connect;
|
||||
protected Action<UvConnectRequest, UvPipeHandle, string, uv_connect_cb> _uv_pipe_connect;
|
||||
public void pipe_connect(UvConnectRequest req, UvPipeHandle handle, string name, uv_connect_cb cb)
|
||||
{
|
||||
req.Validate();
|
||||
|
|
@ -254,7 +261,7 @@ namespace Libuv.Internal
|
|||
_uv_pipe_connect(req, handle, name, cb);
|
||||
}
|
||||
|
||||
public Func<UvPipeHandle, int> _uv_pipe_pending_count;
|
||||
protected Func<UvPipeHandle, int> _uv_pipe_pending_count;
|
||||
public int pipe_pending_count(UvPipeHandle handle)
|
||||
{
|
||||
handle.Validate();
|
||||
|
|
@ -265,21 +272,21 @@ namespace Libuv.Internal
|
|||
public delegate void uv_alloc_cb(IntPtr server, int suggested_size, out uv_buf_t buf);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate void uv_read_cb(IntPtr server, int nread, ref uv_buf_t buf);
|
||||
public Func<UvStreamHandle, uv_alloc_cb, uv_read_cb, int> _uv_read_start;
|
||||
protected Func<UvStreamHandle, uv_alloc_cb, uv_read_cb, int> _uv_read_start;
|
||||
public void read_start(UvStreamHandle handle, uv_alloc_cb alloc_cb, uv_read_cb read_cb)
|
||||
{
|
||||
handle.Validate();
|
||||
ThrowIfErrored(_uv_read_start(handle, alloc_cb, read_cb));
|
||||
}
|
||||
|
||||
public Func<UvStreamHandle, int> _uv_read_stop;
|
||||
protected Func<UvStreamHandle, int> _uv_read_stop;
|
||||
public void read_stop(UvStreamHandle handle)
|
||||
{
|
||||
handle.Validate();
|
||||
ThrowIfErrored(_uv_read_stop(handle));
|
||||
}
|
||||
|
||||
public Func<UvStreamHandle, uv_buf_t[], int, int> _uv_try_write;
|
||||
protected Func<UvStreamHandle, uv_buf_t[], int, int> _uv_try_write;
|
||||
public int try_write(UvStreamHandle handle, uv_buf_t[] bufs, int nbufs)
|
||||
{
|
||||
handle.Validate();
|
||||
|
|
@ -291,8 +298,8 @@ namespace Libuv.Internal
|
|||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate void uv_write_cb(IntPtr req, int status);
|
||||
|
||||
public unsafe delegate int uv_write_func(UvRequest req, UvStreamHandle handle, uv_buf_t* bufs, int nbufs, uv_write_cb cb);
|
||||
public uv_write_func _uv_write;
|
||||
protected unsafe delegate int uv_write_func(UvRequest req, UvStreamHandle handle, uv_buf_t* bufs, int nbufs, uv_write_cb cb);
|
||||
protected uv_write_func _uv_write;
|
||||
public unsafe void write(UvRequest req, UvStreamHandle handle, uv_buf_t* bufs, int nbufs, uv_write_cb cb)
|
||||
{
|
||||
req.Validate();
|
||||
|
|
@ -300,8 +307,8 @@ namespace Libuv.Internal
|
|||
ThrowIfErrored(_uv_write(req, handle, bufs, nbufs, cb));
|
||||
}
|
||||
|
||||
public unsafe delegate int uv_write2_func(UvRequest req, UvStreamHandle handle, uv_buf_t* bufs, int nbufs, UvStreamHandle sendHandle, uv_write_cb cb);
|
||||
public uv_write2_func _uv_write2;
|
||||
protected unsafe delegate int uv_write2_func(UvRequest req, UvStreamHandle handle, uv_buf_t* bufs, int nbufs, UvStreamHandle sendHandle, uv_write_cb cb);
|
||||
protected uv_write2_func _uv_write2;
|
||||
public unsafe void write2(UvRequest req, UvStreamHandle handle, uv_buf_t* bufs, int nbufs, UvStreamHandle sendHandle, uv_write_cb cb)
|
||||
{
|
||||
req.Validate();
|
||||
|
|
@ -309,38 +316,38 @@ namespace Libuv.Internal
|
|||
ThrowIfErrored(_uv_write2(req, handle, bufs, nbufs, sendHandle, cb));
|
||||
}
|
||||
|
||||
public Func<int, IntPtr> _uv_err_name;
|
||||
protected Func<int, IntPtr> _uv_err_name;
|
||||
public string err_name(int err)
|
||||
{
|
||||
IntPtr ptr = _uv_err_name(err);
|
||||
return ptr == IntPtr.Zero ? null : Marshal.PtrToStringAnsi(ptr);
|
||||
}
|
||||
|
||||
public Func<int, IntPtr> _uv_strerror;
|
||||
protected Func<int, IntPtr> _uv_strerror;
|
||||
public string strerror(int err)
|
||||
{
|
||||
IntPtr ptr = _uv_strerror(err);
|
||||
return ptr == IntPtr.Zero ? null : Marshal.PtrToStringAnsi(ptr);
|
||||
}
|
||||
|
||||
public Func<int> _uv_loop_size;
|
||||
protected Func<int> _uv_loop_size;
|
||||
public int loop_size() => _uv_loop_size();
|
||||
|
||||
public Func<HandleType, int> _uv_handle_size;
|
||||
protected Func<HandleType, int> _uv_handle_size;
|
||||
public int handle_size(HandleType handleType) => _uv_handle_size(handleType);
|
||||
|
||||
public Func<RequestType, int> _uv_req_size;
|
||||
protected Func<RequestType, int> _uv_req_size;
|
||||
public int req_size(RequestType reqType) => _uv_req_size(reqType);
|
||||
|
||||
public delegate int uv_ip4_addr_func(string ip, int port, out SockAddr addr);
|
||||
public uv_ip4_addr_func _uv_ip4_addr;
|
||||
protected delegate int uv_ip4_addr_func(string ip, int port, out SockAddr addr);
|
||||
protected uv_ip4_addr_func _uv_ip4_addr;
|
||||
public void ip4_addr(string ip, int port, out SockAddr addr, out UvException error)
|
||||
{
|
||||
Check(_uv_ip4_addr(ip, port, out addr), out error);
|
||||
}
|
||||
|
||||
public delegate int uv_ip6_addr_func(string ip, int port, out SockAddr addr);
|
||||
public uv_ip6_addr_func _uv_ip6_addr;
|
||||
protected delegate int uv_ip6_addr_func(string ip, int port, out SockAddr addr);
|
||||
protected uv_ip6_addr_func _uv_ip6_addr;
|
||||
public void ip6_addr(string ip, int port, out SockAddr addr, out UvException error)
|
||||
{
|
||||
Check(_uv_ip6_addr(ip, port, out addr), out error);
|
||||
|
|
@ -348,15 +355,15 @@ namespace Libuv.Internal
|
|||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate void uv_walk_cb(IntPtr handle, IntPtr arg);
|
||||
public Func<UvLoopHandle, uv_walk_cb, IntPtr, int> _uv_walk;
|
||||
protected Func<UvLoopHandle, uv_walk_cb, IntPtr, int> _uv_walk;
|
||||
public void walk(UvLoopHandle loop, uv_walk_cb walk_cb, IntPtr arg)
|
||||
{
|
||||
loop.Validate();
|
||||
_uv_walk(loop, walk_cb, arg);
|
||||
}
|
||||
|
||||
public Func<UvLoopHandle, UvTimerHandle, int> _uv_timer_init;
|
||||
public void timer_init(UvLoopHandle loop, UvTimerHandle handle)
|
||||
protected Func<UvLoopHandle, UvTimerHandle, int> _uv_timer_init;
|
||||
public unsafe void timer_init(UvLoopHandle loop, UvTimerHandle handle)
|
||||
{
|
||||
loop.Validate();
|
||||
handle.Validate();
|
||||
|
|
@ -365,29 +372,29 @@ namespace Libuv.Internal
|
|||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate void uv_timer_cb(IntPtr handle);
|
||||
public Func<UvTimerHandle, uv_timer_cb, long, long, int> _uv_timer_start;
|
||||
public void timer_start(UvTimerHandle handle, uv_timer_cb cb, long timeout, long repeat)
|
||||
protected Func<UvTimerHandle, uv_timer_cb, long, long, int> _uv_timer_start;
|
||||
public unsafe void timer_start(UvTimerHandle handle, uv_timer_cb cb, long timeout, long repeat)
|
||||
{
|
||||
handle.Validate();
|
||||
ThrowIfErrored(_uv_timer_start(handle, cb, timeout, repeat));
|
||||
}
|
||||
|
||||
public Func<UvTimerHandle, int> _uv_timer_stop;
|
||||
public void timer_stop(UvTimerHandle handle)
|
||||
protected Func<UvTimerHandle, int> _uv_timer_stop;
|
||||
public unsafe void timer_stop(UvTimerHandle handle)
|
||||
{
|
||||
handle.Validate();
|
||||
ThrowIfErrored(_uv_timer_stop(handle));
|
||||
}
|
||||
|
||||
public Func<UvLoopHandle, long> _uv_now;
|
||||
public long now(UvLoopHandle loop)
|
||||
protected Func<UvLoopHandle, long> _uv_now;
|
||||
public unsafe long now(UvLoopHandle loop)
|
||||
{
|
||||
loop.Validate();
|
||||
return _uv_now(loop);
|
||||
}
|
||||
|
||||
public delegate int uv_tcp_getsockname_func(UvTcpHandle handle, out SockAddr addr, ref int namelen);
|
||||
public uv_tcp_getsockname_func _uv_tcp_getsockname;
|
||||
protected uv_tcp_getsockname_func _uv_tcp_getsockname;
|
||||
public void tcp_getsockname(UvTcpHandle handle, out SockAddr addr, ref int namelen)
|
||||
{
|
||||
handle.Validate();
|
||||
|
|
@ -395,14 +402,14 @@ namespace Libuv.Internal
|
|||
}
|
||||
|
||||
public delegate int uv_tcp_getpeername_func(UvTcpHandle handle, out SockAddr addr, ref int namelen);
|
||||
public uv_tcp_getpeername_func _uv_tcp_getpeername;
|
||||
protected uv_tcp_getpeername_func _uv_tcp_getpeername;
|
||||
public void tcp_getpeername(UvTcpHandle handle, out SockAddr addr, ref int namelen)
|
||||
{
|
||||
handle.Validate();
|
||||
ThrowIfErrored(_uv_tcp_getpeername(handle, out addr, ref namelen));
|
||||
}
|
||||
|
||||
public uv_buf_t buf_init(IntPtr memory, int len) => new uv_buf_t(memory, len, Core.IsWindows);
|
||||
public uv_buf_t buf_init(IntPtr memory, int len) => new uv_buf_t(memory, len, IsWindows);
|
||||
|
||||
public struct uv_buf_t
|
||||
{
|
||||
|
|
@ -417,9 +424,9 @@ namespace Libuv.Internal
|
|||
private readonly IntPtr _field0;
|
||||
private readonly IntPtr _field1;
|
||||
|
||||
public uv_buf_t(IntPtr memory, int len, bool windows)
|
||||
public uv_buf_t(IntPtr memory, int len, bool IsWindows)
|
||||
{
|
||||
if (windows)
|
||||
if (IsWindows)
|
||||
{
|
||||
_field0 = (IntPtr)len;
|
||||
_field1 = memory;
|
||||
|
|
@ -581,16 +588,16 @@ namespace Libuv.Internal
|
|||
public static extern int uv_walk(UvLoopHandle loop, uv_walk_cb walk_cb, IntPtr arg);
|
||||
|
||||
[DllImport("libuv", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern int uv_timer_init(UvLoopHandle loop, UvTimerHandle handle);
|
||||
public static extern unsafe int uv_timer_init(UvLoopHandle loop, UvTimerHandle handle);
|
||||
|
||||
[DllImport("libuv", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern int uv_timer_start(UvTimerHandle handle, uv_timer_cb cb, long timeout, long repeat);
|
||||
public static extern unsafe int uv_timer_start(UvTimerHandle handle, uv_timer_cb cb, long timeout, long repeat);
|
||||
|
||||
[DllImport("libuv", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern int uv_timer_stop(UvTimerHandle handle);
|
||||
public static extern unsafe int uv_timer_stop(UvTimerHandle handle);
|
||||
|
||||
[DllImport("libuv", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern long uv_now(UvLoopHandle loop);
|
||||
public static extern unsafe long uv_now(UvLoopHandle loop);
|
||||
|
||||
[DllImport("WS2_32.dll", CallingConvention = CallingConvention.Winapi)]
|
||||
public static extern unsafe int WSAIoctl(
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking
|
||||
{
|
||||
internal static class PlatformApis
|
||||
{
|
||||
public static bool IsWindows { get; } = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
|
||||
|
||||
public static bool IsDarwin { get; } = RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static long VolatileRead(ref long value) => IntPtr.Size == 8 ? Volatile.Read(ref value) : Interlocked.Read(ref value);
|
||||
}
|
||||
}
|
||||
|
|
@ -3,20 +3,19 @@
|
|||
|
||||
using System.Net;
|
||||
using System.Runtime.InteropServices;
|
||||
using Server;
|
||||
|
||||
namespace Libuv.Internal
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct SockAddr
|
||||
internal struct SockAddr
|
||||
{
|
||||
// this type represents native memory occupied by sockaddr struct
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms740496(v=vs.85).aspx
|
||||
// although the c/c++ header defines it as a 2-byte short followed by a 14-byte array,
|
||||
// the simplest way to reserve the same size in c# is with four nameless long values
|
||||
private long _field0;
|
||||
private long _field1;
|
||||
private long _field2;
|
||||
private readonly long _field0;
|
||||
private readonly long _field1;
|
||||
private readonly long _field2;
|
||||
private long _field3;
|
||||
|
||||
public SockAddr(long ignored) => _field0 = _field1 = _field2 = _field3 = 0;
|
||||
|
|
@ -64,30 +63,33 @@ namespace Libuv.Internal
|
|||
var port = ((int)(_field0 & 0x00FF0000) >> 8) | (int)((_field0 & 0xFF000000) >> 24);
|
||||
|
||||
int family = (int)_field0;
|
||||
if (Core.IsDarwin)
|
||||
if (PlatformApis.IsDarwin)
|
||||
// see explanation in example 4
|
||||
family >>= 8;
|
||||
family &= 0xFF;
|
||||
|
||||
if (family == 2)
|
||||
{
|
||||
// AF_INET => IPv4
|
||||
return new IPEndPoint(new IPAddress((_field0 >> 32) & 0xFFFFFFFF), port);
|
||||
|
||||
if (IsIPv4MappedToIPv6())
|
||||
}
|
||||
else if (IsIPv4MappedToIPv6())
|
||||
{
|
||||
var ipv4bits = (_field2 >> 32) & 0x00000000FFFFFFFF;
|
||||
return new IPEndPoint(new IPAddress(ipv4bits), port);
|
||||
}
|
||||
|
||||
// otherwise IPv6
|
||||
var bytes = new byte[16];
|
||||
fixed (byte* b = bytes)
|
||||
else
|
||||
{
|
||||
*(long*)b = _field1;
|
||||
*(long*)(b + 8) = _field2;
|
||||
}
|
||||
// otherwise IPv6
|
||||
var bytes = new byte[16];
|
||||
fixed (byte* b = bytes)
|
||||
{
|
||||
*(long*)b = _field1;
|
||||
*(long*)(b + 8) = _field2;
|
||||
}
|
||||
|
||||
return new IPEndPoint(new IPAddress(bytes, ScopeId), port);
|
||||
return new IPEndPoint(new IPAddress(bytes, ScopeId), port);
|
||||
}
|
||||
}
|
||||
|
||||
public uint ScopeId
|
||||
|
|
@ -100,8 +102,13 @@ namespace Libuv.Internal
|
|||
}
|
||||
}
|
||||
|
||||
// If the IPAddress is an IPv4 mapped to IPv6, return the IPv4 representation instead.
|
||||
// For example [::FFFF:127.0.0.1] will be transform to IPAddress of 127.0.0.1
|
||||
private bool IsIPv4MappedToIPv6() => _field1 == 0 && (_field2 & 0xFFFFFFFF) == 0xFFFF0000;
|
||||
private bool IsIPv4MappedToIPv6()
|
||||
{
|
||||
// If the IPAddress is an IPv4 mapped to IPv6, return the IPv4 representation instead.
|
||||
// For example [::FFFF:127.0.0.1] will be transform to IPAddress of 127.0.0.1
|
||||
if (_field1 != 0) return false;
|
||||
|
||||
return (_field2 & 0xFFFFFFFF) == 0xFFFF0000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,13 +5,13 @@ using System;
|
|||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
|
||||
namespace Libuv.Internal
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking
|
||||
{
|
||||
public class UvAsyncHandle : UvHandle
|
||||
internal class UvAsyncHandle : UvHandle
|
||||
{
|
||||
private static readonly LibuvFunctions.uv_close_cb _destroyMemory = handle => DestroyMemory(handle);
|
||||
private static readonly LibuvFunctions.uv_close_cb _destroyMemory = (handle) => DestroyMemory(handle);
|
||||
|
||||
private static readonly LibuvFunctions.uv_async_cb _uv_async_cb = handle => AsyncCb(handle);
|
||||
private static readonly LibuvFunctions.uv_async_cb _uv_async_cb = (handle) => AsyncCb(handle);
|
||||
private Action _callback;
|
||||
private Action<Action<IntPtr>, IntPtr> _queueCloseHandle;
|
||||
|
||||
|
|
@ -56,7 +56,7 @@ namespace Libuv.Internal
|
|||
{
|
||||
// This can be called from the finalizer.
|
||||
// Ensure the closure doesn't reference "this".
|
||||
LibuvFunctions uv = _uv;
|
||||
var uv = _uv;
|
||||
_queueCloseHandle(memory2 => uv.close(memory2, _destroyMemory), memory);
|
||||
uv.unsafe_async_send(memory);
|
||||
}
|
||||
|
|
@ -4,14 +4,14 @@
|
|||
using System;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Libuv.Internal
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for UvWriteRequest
|
||||
/// </summary>
|
||||
public class UvConnectRequest : UvRequest
|
||||
internal class UvConnectRequest : UvRequest
|
||||
{
|
||||
private static readonly LibuvFunctions.uv_connect_cb _uv_connect_cb = UvConnectCb;
|
||||
private static readonly LibuvFunctions.uv_connect_cb _uv_connect_cb = (req, status) => UvConnectCb(req, status);
|
||||
|
||||
private Action<UvConnectRequest, int, UvException, object> _callback;
|
||||
private object _state;
|
||||
|
|
@ -3,9 +3,9 @@
|
|||
|
||||
using System;
|
||||
|
||||
namespace Libuv.Internal
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking
|
||||
{
|
||||
public class UvException : Exception
|
||||
internal class UvException : Exception
|
||||
{
|
||||
public UvException(string message, int statusCode) : base(message) => StatusCode = statusCode;
|
||||
|
||||
|
|
@ -5,11 +5,11 @@ using System;
|
|||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
|
||||
namespace Libuv.Internal
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking
|
||||
{
|
||||
public abstract class UvHandle : UvMemory
|
||||
internal abstract class UvHandle : UvMemory
|
||||
{
|
||||
private static readonly LibuvFunctions.uv_close_cb _destroyMemory = DestroyMemory;
|
||||
private static readonly LibuvFunctions.uv_close_cb _destroyMemory = (handle) => DestroyMemory(handle);
|
||||
private Action<Action<IntPtr>, IntPtr> _queueCloseHandle;
|
||||
|
||||
protected UvHandle(ILibuvTrace logger) : base (logger)
|
||||
|
|
@ -28,7 +28,7 @@ namespace Libuv.Internal
|
|||
|
||||
protected override bool ReleaseHandle()
|
||||
{
|
||||
IntPtr memory = handle;
|
||||
var memory = handle;
|
||||
if (memory != IntPtr.Zero)
|
||||
{
|
||||
handle = IntPtr.Zero;
|
||||
|
|
@ -41,7 +41,7 @@ namespace Libuv.Internal
|
|||
{
|
||||
// This can be called from the finalizer.
|
||||
// Ensure the closure doesn't reference "this".
|
||||
LibuvFunctions uv = _uv;
|
||||
var uv = _uv;
|
||||
_queueCloseHandle(memory2 => uv.close(memory2, _destroyMemory), memory);
|
||||
}
|
||||
else
|
||||
|
|
@ -4,9 +4,9 @@
|
|||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace Libuv.Internal
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking
|
||||
{
|
||||
public class UvLoopHandle : UvMemory
|
||||
internal class UvLoopHandle : UvMemory
|
||||
{
|
||||
public UvLoopHandle(ILibuvTrace logger) : base(logger)
|
||||
{
|
||||
|
|
@ -7,12 +7,12 @@ using System.Diagnostics;
|
|||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace Libuv.Internal
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for UvMemory
|
||||
/// </summary>
|
||||
public abstract class UvMemory : SafeHandle
|
||||
internal abstract class UvMemory : SafeHandle
|
||||
{
|
||||
protected LibuvFunctions _uv;
|
||||
protected int _threadId;
|
||||
|
|
@ -66,7 +66,6 @@ namespace Libuv.Internal
|
|||
{
|
||||
Debug.Assert(closed || !IsClosed, "Handle is closed");
|
||||
Debug.Assert(!IsInvalid, "Handle is invalid");
|
||||
|
||||
Debug.Assert(_threadId == Thread.CurrentThread.ManagedThreadId, "ThreadId is incorrect");
|
||||
}
|
||||
|
||||
|
|
@ -3,9 +3,9 @@
|
|||
|
||||
using System;
|
||||
|
||||
namespace Libuv.Internal
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking
|
||||
{
|
||||
public class UvPipeHandle : UvStreamHandle
|
||||
internal class UvPipeHandle : UvStreamHandle
|
||||
{
|
||||
public UvPipeHandle(ILibuvTrace logger) : base(logger)
|
||||
{
|
||||
|
|
@ -4,9 +4,9 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Libuv.Internal
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking
|
||||
{
|
||||
public class UvRequest : UvMemory
|
||||
internal class UvRequest : UvMemory
|
||||
{
|
||||
protected UvRequest(ILibuvTrace logger) : base(logger, GCHandleType.Normal)
|
||||
{
|
||||
|
|
@ -14,11 +14,6 @@ namespace Libuv.Internal
|
|||
|
||||
public virtual void Init(LibuvThread thread)
|
||||
{
|
||||
#if DEBUG
|
||||
// Store weak handles to all UvRequest objects so we can do leak detection
|
||||
// while running tests
|
||||
thread.Requests.Add(new WeakReference(this));
|
||||
#endif
|
||||
}
|
||||
|
||||
protected override bool ReleaseHandle()
|
||||
|
|
@ -29,3 +24,4 @@ namespace Libuv.Internal
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5,16 +5,14 @@ using System;
|
|||
using System.Runtime.InteropServices;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Libuv.Internal
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking
|
||||
{
|
||||
public abstract class UvStreamHandle : UvHandle
|
||||
internal abstract class UvStreamHandle : UvHandle
|
||||
{
|
||||
private static readonly LibuvFunctions.uv_connection_cb _uv_connection_cb = UvConnectionCb;
|
||||
private static readonly LibuvFunctions.uv_connection_cb _uv_connection_cb = (handle, status) => UvConnectionCb(handle, status);
|
||||
// Ref and out lamda params must be explicitly typed
|
||||
private static readonly LibuvFunctions.uv_alloc_cb _uv_alloc_cb =
|
||||
(IntPtr handle, int suggested_size, out LibuvFunctions.uv_buf_t buf) => UvAllocCb(handle, suggested_size, out buf);
|
||||
private static readonly LibuvFunctions.uv_read_cb _uv_read_cb =
|
||||
(IntPtr handle, int status, ref LibuvFunctions.uv_buf_t buf) => UvReadCb(handle, status, ref buf);
|
||||
private static readonly LibuvFunctions.uv_alloc_cb _uv_alloc_cb = (IntPtr handle, int suggested_size, out LibuvFunctions.uv_buf_t buf) => UvAllocCb(handle, suggested_size, out buf);
|
||||
private static readonly LibuvFunctions.uv_read_cb _uv_read_cb = (IntPtr handle, int status, ref LibuvFunctions.uv_buf_t buf) => UvReadCb(handle, status, ref buf);
|
||||
|
||||
private Action<UvStreamHandle, int, UvException, object> _listenCallback;
|
||||
private object _listenState;
|
||||
|
|
@ -5,9 +5,9 @@ using System;
|
|||
using System.Net;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Libuv.Internal
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking
|
||||
{
|
||||
public class UvTcpHandle : UvStreamHandle
|
||||
internal class UvTcpHandle : UvStreamHandle
|
||||
{
|
||||
public UvTcpHandle(ILibuvTrace logger) : base(logger)
|
||||
{
|
||||
|
|
@ -4,9 +4,9 @@
|
|||
using System;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Libuv.Internal
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking
|
||||
{
|
||||
public class UvTimerHandle : UvHandle
|
||||
internal class UvTimerHandle : UvHandle
|
||||
{
|
||||
private static readonly LibuvFunctions.uv_timer_cb _uv_timer_cb = UvTimerCb;
|
||||
|
||||
|
|
@ -7,14 +7,14 @@ using System.Collections.Generic;
|
|||
using System.Runtime.InteropServices;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Libuv.Internal
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for UvWriteRequest
|
||||
/// </summary>
|
||||
public class UvWriteReq : UvRequest
|
||||
internal class UvWriteReq : UvRequest
|
||||
{
|
||||
private static readonly LibuvFunctions.uv_write_cb _uv_write_cb = (ptr, status) => UvWriteCb(ptr, status);
|
||||
private static readonly LibuvFunctions.uv_write_cb _uv_write_cb = (IntPtr ptr, int status) => UvWriteCb(ptr, status);
|
||||
|
||||
private IntPtr _bufs;
|
||||
|
||||
|
|
@ -22,9 +22,9 @@ namespace Libuv.Internal
|
|||
private object _state;
|
||||
private const int BUFFER_COUNT = 4;
|
||||
|
||||
private LibuvAwaitable<UvWriteReq> _awaitable = new LibuvAwaitable<UvWriteReq>();
|
||||
private List<GCHandle> _pins = new List<GCHandle>(BUFFER_COUNT + 1);
|
||||
private List<MemoryHandle> _handles = new List<MemoryHandle>(BUFFER_COUNT + 1);
|
||||
private readonly LibuvAwaitable<UvWriteReq> _awaitable = new LibuvAwaitable<UvWriteReq>();
|
||||
private readonly List<GCHandle> _pins = new List<GCHandle>(BUFFER_COUNT + 1);
|
||||
private readonly List<MemoryHandle> _handles = new List<MemoryHandle>(BUFFER_COUNT + 1);
|
||||
|
||||
public UvWriteReq(ILibuvTrace logger) : base(logger)
|
||||
{
|
||||
|
|
@ -76,9 +76,6 @@ namespace Libuv.Internal
|
|||
nBuffers++;
|
||||
|
||||
var pBuffers = (LibuvFunctions.uv_buf_t*)_bufs;
|
||||
if (pBuffers == null)
|
||||
throw new NullReferenceException();
|
||||
|
||||
if (nBuffers > BUFFER_COUNT)
|
||||
{
|
||||
// create and pin buffer array when it's larger than the pre-allocated one
|
||||
|
|
@ -86,8 +83,6 @@ namespace Libuv.Internal
|
|||
var gcHandle = GCHandle.Alloc(bufArray, GCHandleType.Pinned);
|
||||
_pins.Add(gcHandle);
|
||||
pBuffers = (LibuvFunctions.uv_buf_t*)gcHandle.AddrOfPinnedObject();
|
||||
if (pBuffers == null)
|
||||
throw new NullReferenceException();
|
||||
}
|
||||
|
||||
if (nBuffers == 1)
|
||||
|
|
@ -137,7 +132,7 @@ namespace Libuv.Internal
|
|||
Action<UvWriteReq, int, UvException, object> callback,
|
||||
object state)
|
||||
{
|
||||
WriteArraySegmentInternal(handle, bufs, null, callback, state);
|
||||
WriteArraySegmentInternal(handle, bufs, sendHandle: null, callback: callback, state: state);
|
||||
}
|
||||
|
||||
public void Write2(
|
||||
|
|
@ -154,15 +149,12 @@ namespace Libuv.Internal
|
|||
UvStreamHandle handle,
|
||||
ArraySegment<ArraySegment<byte>> bufs,
|
||||
UvStreamHandle sendHandle,
|
||||
Action<UvWriteReq, int, UvException, object> callback, object state
|
||||
)
|
||||
Action<UvWriteReq, int, UvException, object> callback,
|
||||
object state)
|
||||
{
|
||||
try
|
||||
{
|
||||
var pBuffers = (LibuvFunctions.uv_buf_t*)_bufs;
|
||||
if (pBuffers == null)
|
||||
throw new NullReferenceException();
|
||||
|
||||
var nBuffers = bufs.Count;
|
||||
if (nBuffers > BUFFER_COUNT)
|
||||
{
|
||||
|
|
@ -171,14 +163,12 @@ namespace Libuv.Internal
|
|||
var gcHandle = GCHandle.Alloc(bufArray, GCHandleType.Pinned);
|
||||
_pins.Add(gcHandle);
|
||||
pBuffers = (LibuvFunctions.uv_buf_t*)gcHandle.AddrOfPinnedObject();
|
||||
if (pBuffers == null)
|
||||
throw new NullReferenceException();
|
||||
}
|
||||
|
||||
for (var index = 0; index < nBuffers; index++)
|
||||
{
|
||||
// create and pin each segment being written
|
||||
var buf = bufs.Array?[bufs.Offset + index] ?? throw new Exception("buffs.Array is null");
|
||||
var buf = bufs.Array[bufs.Offset + index];
|
||||
|
||||
var gcHandle = GCHandle.Alloc(buf.Array, GCHandleType.Pinned);
|
||||
_pins.Add(gcHandle);
|
||||
|
|
@ -3,11 +3,11 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Libuv.Internal;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
||||
|
||||
namespace Libuv
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||
{
|
||||
public class WriteReqPool
|
||||
internal class WriteReqPool
|
||||
{
|
||||
private const int _maxPooledWriteReqs = 1024;
|
||||
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
using System;
|
||||
using System.Buffers;
|
||||
|
||||
namespace Libuv
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides programmatic configuration of Libuv transport features.
|
||||
|
|
@ -19,6 +19,14 @@ namespace Libuv
|
|||
/// </remarks>
|
||||
public int ThreadCount { get; set; } = ProcessorThreadCount;
|
||||
|
||||
/// <summary>
|
||||
/// Set to false to enable Nagle's algorithm for all connections.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Defaults to true.
|
||||
/// </remarks>
|
||||
public bool NoDelay { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum length of the pending connection queue.
|
||||
/// </summary>
|
||||
|
|
@ -39,12 +47,19 @@ namespace Libuv
|
|||
{
|
||||
// Actual core count would be a better number
|
||||
// rather than logical cores which includes hyper-threaded cores.
|
||||
// Divide by 2 for hyper-threading, and good defaults (still need threads for the game thread).
|
||||
// Divide by 2 for hyper-threading, and good defaults (still need threads to do webserving).
|
||||
var threadCount = Environment.ProcessorCount >> 1;
|
||||
|
||||
// Receive Side Scaling RSS Processor count currently maxes out at 16
|
||||
// would be better to check the NIC's current hardware queues; but xplat...
|
||||
return threadCount < 1 ? 1 : threadCount > 16 ? 16 : threadCount;
|
||||
if (threadCount < 1)
|
||||
// Ensure shifted value is at least one
|
||||
return 1;
|
||||
|
||||
if (threadCount > 16)
|
||||
// Receive Side Scaling RSS Processor count currently maxes out at 16
|
||||
// would be better to check the NIC's current hardware queues; but xplat...
|
||||
return 16;
|
||||
|
||||
return threadCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Connections;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNetCore.Hosting
|
||||
{
|
||||
public static class WebHostBuilderLibuvExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Specify Libuv as the transport to be used by Kestrel.
|
||||
/// </summary>
|
||||
/// <param name="hostBuilder">
|
||||
/// The Microsoft.AspNetCore.Hosting.IWebHostBuilder to configure.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The Microsoft.AspNetCore.Hosting.IWebHostBuilder.
|
||||
/// </returns>
|
||||
public static IWebHostBuilder UseLibuv(this IWebHostBuilder hostBuilder)
|
||||
{
|
||||
return hostBuilder.ConfigureServices(services =>
|
||||
{
|
||||
services.AddSingleton<IConnectionListenerFactory, LibuvTransportFactory>();
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specify Libuv as the transport to be used by Kestrel.
|
||||
/// </summary>
|
||||
/// <param name="hostBuilder">
|
||||
/// The Microsoft.AspNetCore.Hosting.IWebHostBuilder to configure.
|
||||
/// </param>
|
||||
/// <param name="configureOptions">
|
||||
/// A callback to configure Libuv options.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The Microsoft.AspNetCore.Hosting.IWebHostBuilder.
|
||||
/// </returns>
|
||||
public static IWebHostBuilder UseLibuv(this IWebHostBuilder hostBuilder, Action<LibuvTransportOptions> configureOptions)
|
||||
{
|
||||
return hostBuilder.UseLibuv().ConfigureServices(services =>
|
||||
{
|
||||
services.Configure(configureOptions);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Pipelines;
|
||||
using System.Threading;
|
||||
using Microsoft.AspNetCore.Connections.Features;
|
||||
|
||||
namespace Microsoft.AspNetCore.Connections
|
||||
{
|
||||
public partial class TransportConnection : IConnectionIdFeature,
|
||||
IConnectionTransportFeature,
|
||||
IConnectionItemsFeature,
|
||||
IMemoryPoolFeature,
|
||||
IConnectionLifetimeFeature
|
||||
{
|
||||
// NOTE: When feature interfaces are added to or removed from this TransportConnection class implementation,
|
||||
// then the list of `features` in the generated code project MUST also be updated.
|
||||
// See also: tools/CodeGenerator/TransportConnectionFeatureCollection.cs
|
||||
|
||||
MemoryPool<byte> IMemoryPoolFeature.MemoryPool => MemoryPool;
|
||||
|
||||
IDuplexPipe IConnectionTransportFeature.Transport
|
||||
{
|
||||
get => Transport;
|
||||
set => Transport = value;
|
||||
}
|
||||
|
||||
IDictionary<object, object> IConnectionItemsFeature.Items
|
||||
{
|
||||
get => Items;
|
||||
set => Items = value;
|
||||
}
|
||||
|
||||
CancellationToken IConnectionLifetimeFeature.ConnectionClosed
|
||||
{
|
||||
get => ConnectionClosed;
|
||||
set => ConnectionClosed = value;
|
||||
}
|
||||
|
||||
void IConnectionLifetimeFeature.Abort() => Abort(new ConnectionAbortedException("The connection was aborted by the application via IConnectionLifetimeFeature.Abort()."));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,248 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Microsoft.AspNetCore.Connections.Features;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
|
||||
namespace Microsoft.AspNetCore.Connections
|
||||
{
|
||||
public partial class TransportConnection : IFeatureCollection
|
||||
{
|
||||
private static readonly Type IConnectionIdFeatureType = typeof(IConnectionIdFeature);
|
||||
private static readonly Type IConnectionTransportFeatureType = typeof(IConnectionTransportFeature);
|
||||
private static readonly Type IConnectionItemsFeatureType = typeof(IConnectionItemsFeature);
|
||||
private static readonly Type IMemoryPoolFeatureType = typeof(IMemoryPoolFeature);
|
||||
private static readonly Type IConnectionLifetimeFeatureType = typeof(IConnectionLifetimeFeature);
|
||||
|
||||
private object _currentIConnectionIdFeature;
|
||||
private object _currentIConnectionTransportFeature;
|
||||
private object _currentIConnectionItemsFeature;
|
||||
private object _currentIMemoryPoolFeature;
|
||||
private object _currentIConnectionLifetimeFeature;
|
||||
|
||||
private int _featureRevision;
|
||||
|
||||
private List<KeyValuePair<Type, object>> MaybeExtra;
|
||||
|
||||
private void FastReset()
|
||||
{
|
||||
_currentIConnectionIdFeature = this;
|
||||
_currentIConnectionTransportFeature = this;
|
||||
_currentIConnectionItemsFeature = this;
|
||||
_currentIMemoryPoolFeature = this;
|
||||
_currentIConnectionLifetimeFeature = this;
|
||||
|
||||
}
|
||||
|
||||
// Internal for testing
|
||||
internal void ResetFeatureCollection()
|
||||
{
|
||||
FastReset();
|
||||
MaybeExtra?.Clear();
|
||||
_featureRevision++;
|
||||
}
|
||||
|
||||
private object ExtraFeatureGet(Type key)
|
||||
{
|
||||
if (MaybeExtra == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
for (var i = 0; i < MaybeExtra.Count; i++)
|
||||
{
|
||||
var kv = MaybeExtra[i];
|
||||
if (kv.Key == key)
|
||||
{
|
||||
return kv.Value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void ExtraFeatureSet(Type key, object value)
|
||||
{
|
||||
if (MaybeExtra == null)
|
||||
{
|
||||
MaybeExtra = new List<KeyValuePair<Type, object>>(2);
|
||||
}
|
||||
|
||||
for (var i = 0; i < MaybeExtra.Count; i++)
|
||||
{
|
||||
if (MaybeExtra[i].Key == key)
|
||||
{
|
||||
MaybeExtra[i] = new KeyValuePair<Type, object>(key, value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
MaybeExtra.Add(new KeyValuePair<Type, object>(key, value));
|
||||
}
|
||||
|
||||
bool IFeatureCollection.IsReadOnly => false;
|
||||
|
||||
int IFeatureCollection.Revision => _featureRevision;
|
||||
|
||||
object IFeatureCollection.this[Type key]
|
||||
{
|
||||
get
|
||||
{
|
||||
object feature = null;
|
||||
if (key == IConnectionIdFeatureType)
|
||||
{
|
||||
feature = _currentIConnectionIdFeature;
|
||||
}
|
||||
else if (key == IConnectionTransportFeatureType)
|
||||
{
|
||||
feature = _currentIConnectionTransportFeature;
|
||||
}
|
||||
else if (key == IConnectionItemsFeatureType)
|
||||
{
|
||||
feature = _currentIConnectionItemsFeature;
|
||||
}
|
||||
else if (key == IMemoryPoolFeatureType)
|
||||
{
|
||||
feature = _currentIMemoryPoolFeature;
|
||||
}
|
||||
else if (key == IConnectionLifetimeFeatureType)
|
||||
{
|
||||
feature = _currentIConnectionLifetimeFeature;
|
||||
}
|
||||
else if (MaybeExtra != null)
|
||||
{
|
||||
feature = ExtraFeatureGet(key);
|
||||
}
|
||||
|
||||
return feature;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_featureRevision++;
|
||||
|
||||
if (key == IConnectionIdFeatureType)
|
||||
{
|
||||
_currentIConnectionIdFeature = value;
|
||||
}
|
||||
else if (key == IConnectionTransportFeatureType)
|
||||
{
|
||||
_currentIConnectionTransportFeature = value;
|
||||
}
|
||||
else if (key == IConnectionItemsFeatureType)
|
||||
{
|
||||
_currentIConnectionItemsFeature = value;
|
||||
}
|
||||
else if (key == IMemoryPoolFeatureType)
|
||||
{
|
||||
_currentIMemoryPoolFeature = value;
|
||||
}
|
||||
else if (key == IConnectionLifetimeFeatureType)
|
||||
{
|
||||
_currentIConnectionLifetimeFeature = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
ExtraFeatureSet(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TFeature IFeatureCollection.Get<TFeature>()
|
||||
{
|
||||
TFeature feature = default;
|
||||
if (typeof(TFeature) == typeof(IConnectionIdFeature))
|
||||
{
|
||||
feature = (TFeature)_currentIConnectionIdFeature;
|
||||
}
|
||||
else if (typeof(TFeature) == typeof(IConnectionTransportFeature))
|
||||
{
|
||||
feature = (TFeature)_currentIConnectionTransportFeature;
|
||||
}
|
||||
else if (typeof(TFeature) == typeof(IConnectionItemsFeature))
|
||||
{
|
||||
feature = (TFeature)_currentIConnectionItemsFeature;
|
||||
}
|
||||
else if (typeof(TFeature) == typeof(IMemoryPoolFeature))
|
||||
{
|
||||
feature = (TFeature)_currentIMemoryPoolFeature;
|
||||
}
|
||||
else if (typeof(TFeature) == typeof(IConnectionLifetimeFeature))
|
||||
{
|
||||
feature = (TFeature)_currentIConnectionLifetimeFeature;
|
||||
}
|
||||
else if (MaybeExtra != null)
|
||||
{
|
||||
feature = (TFeature)(ExtraFeatureGet(typeof(TFeature)));
|
||||
}
|
||||
|
||||
return feature;
|
||||
}
|
||||
|
||||
void IFeatureCollection.Set<TFeature>(TFeature feature)
|
||||
{
|
||||
_featureRevision++;
|
||||
if (typeof(TFeature) == typeof(IConnectionIdFeature))
|
||||
{
|
||||
_currentIConnectionIdFeature = feature;
|
||||
}
|
||||
else if (typeof(TFeature) == typeof(IConnectionTransportFeature))
|
||||
{
|
||||
_currentIConnectionTransportFeature = feature;
|
||||
}
|
||||
else if (typeof(TFeature) == typeof(IConnectionItemsFeature))
|
||||
{
|
||||
_currentIConnectionItemsFeature = feature;
|
||||
}
|
||||
else if (typeof(TFeature) == typeof(IMemoryPoolFeature))
|
||||
{
|
||||
_currentIMemoryPoolFeature = feature;
|
||||
}
|
||||
else if (typeof(TFeature) == typeof(IConnectionLifetimeFeature))
|
||||
{
|
||||
_currentIConnectionLifetimeFeature = feature;
|
||||
}
|
||||
else
|
||||
{
|
||||
ExtraFeatureSet(typeof(TFeature), feature);
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<KeyValuePair<Type, object>> FastEnumerable()
|
||||
{
|
||||
if (_currentIConnectionIdFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(IConnectionIdFeatureType, _currentIConnectionIdFeature);
|
||||
}
|
||||
if (_currentIConnectionTransportFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(IConnectionTransportFeatureType, _currentIConnectionTransportFeature);
|
||||
}
|
||||
if (_currentIConnectionItemsFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(IConnectionItemsFeatureType, _currentIConnectionItemsFeature);
|
||||
}
|
||||
if (_currentIMemoryPoolFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(IMemoryPoolFeatureType, _currentIMemoryPoolFeature);
|
||||
}
|
||||
if (_currentIConnectionLifetimeFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(IConnectionLifetimeFeatureType, _currentIConnectionLifetimeFeature);
|
||||
}
|
||||
|
||||
if (MaybeExtra != null)
|
||||
{
|
||||
foreach (var item in MaybeExtra)
|
||||
{
|
||||
yield return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator<KeyValuePair<Type, object>> IEnumerable<KeyValuePair<Type, object>>.GetEnumerator() => FastEnumerable().GetEnumerator();
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => FastEnumerable().GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Pipelines;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
|
||||
namespace Microsoft.AspNetCore.Connections
|
||||
{
|
||||
public abstract partial class TransportConnection : ConnectionContext
|
||||
{
|
||||
private IDictionary<object, object> _items;
|
||||
private string _connectionId;
|
||||
|
||||
public TransportConnection()
|
||||
{
|
||||
FastReset();
|
||||
}
|
||||
|
||||
public override EndPoint LocalEndPoint { get; set; }
|
||||
public override EndPoint RemoteEndPoint { get; set; }
|
||||
|
||||
public override string ConnectionId
|
||||
{
|
||||
get => _connectionId ??= CorrelationIdGenerator.GetNextId();
|
||||
set => _connectionId = value;
|
||||
}
|
||||
|
||||
public override IFeatureCollection Features => this;
|
||||
|
||||
public virtual MemoryPool<byte> MemoryPool { get; }
|
||||
|
||||
public override IDuplexPipe Transport { get; set; }
|
||||
|
||||
public IDuplexPipe Application { get; set; }
|
||||
|
||||
public override IDictionary<object, object> Items
|
||||
{
|
||||
get => _items ??= new ConnectionItems();
|
||||
set => _items = value;
|
||||
}
|
||||
|
||||
public override CancellationToken ConnectionClosed { get; set; }
|
||||
|
||||
// DO NOT remove this override to ConnectionContext.Abort. Doing so would cause
|
||||
// any TransportConnection that does not override Abort or calls base.Abort
|
||||
// to stack overflow when IConnectionLifetimeFeature.Abort() is called.
|
||||
// That said, all derived types should override this method should override
|
||||
// this implementation of Abort because canceling pending output reads is not
|
||||
// sufficient to abort the connection if there is backpressure.
|
||||
public override void Abort(ConnectionAbortedException abortReason)
|
||||
{
|
||||
Application.Input.CancelPendingRead();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -22,7 +22,7 @@ namespace Server
|
|||
{
|
||||
public class KeywordList
|
||||
{
|
||||
private static int[] m_EmptyInts = new int[0];
|
||||
private static readonly int[] m_EmptyInts = new int[0];
|
||||
private int[] m_Keywords;
|
||||
|
||||
public KeywordList()
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@ using System.Runtime.InteropServices;
|
|||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server
|
||||
|
|
@ -56,7 +59,7 @@ namespace Server
|
|||
* GetTickCount and GetTickCount64 have poor resolution.
|
||||
* GetTickCount64 is unavailable on Windows XP and Windows Server 2003.
|
||||
* Stopwatch.GetTimestamp() (QueryPerformanceCounter) is high resolution, but
|
||||
* somewhat expensive to call because of its defference to DateTime.Now,
|
||||
* somewhat expensive to call because of its difference to DateTime.Now,
|
||||
* which is why Stopwatch has been used to verify HRT before calling GetTimestamp(),
|
||||
* enabling the usage of DateTime.UtcNow instead.
|
||||
*/
|
||||
|
|
@ -80,8 +83,6 @@ namespace Server
|
|||
|
||||
private static readonly Type[] m_SerialTypeArray = { typeof(Serial) };
|
||||
|
||||
public static MessagePump MessagePump{ get; set; }
|
||||
|
||||
public static bool Profiling
|
||||
{
|
||||
get => m_Profiling;
|
||||
|
|
@ -265,9 +266,7 @@ namespace Server
|
|||
{
|
||||
try
|
||||
{
|
||||
Task.WhenAll(
|
||||
MessagePump.Listeners.Select(listener => listener.Dispose())
|
||||
).Wait();
|
||||
// Close all listeners
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
|
@ -444,9 +443,6 @@ namespace Server
|
|||
|
||||
AssemblyHandler.Invoke("Initialize");
|
||||
|
||||
// Start accepting new connections
|
||||
MessagePump = new MessagePump();
|
||||
|
||||
AssemblyHandler.Invoke("RegisterListeners");
|
||||
|
||||
timerThread.Start();
|
||||
|
|
@ -454,10 +450,18 @@ namespace Server
|
|||
foreach (Map m in Map.AllMaps)
|
||||
m.Tiles.Force();
|
||||
|
||||
NetState.Initialize();
|
||||
|
||||
EventSink.InvokeServerStarted();
|
||||
|
||||
// Start net socket server
|
||||
var host = TcpServer.CreateWebHostBuilder(new string[0]).Build();
|
||||
var life = host.Services.GetRequiredService<IHostApplicationLifetime>();
|
||||
life.ApplicationStopping.Register(() => { Kill(); });
|
||||
|
||||
host.Run();
|
||||
}
|
||||
|
||||
public static void RunEventLoop(IMessagePumpService messagePumpService)
|
||||
{
|
||||
try
|
||||
{
|
||||
long last = TickCount;
|
||||
|
|
@ -477,7 +481,7 @@ namespace Server
|
|||
);
|
||||
|
||||
Timer.Slice();
|
||||
MessagePump.DoWork();
|
||||
messagePumpService.DoWork();
|
||||
|
||||
NetState.ProcessDisposedQueue();
|
||||
|
||||
|
|
|
|||
|
|
@ -262,16 +262,17 @@ namespace Server
|
|||
private static readonly List<Item> _EmptyFixItems = new List<Item>();
|
||||
private Region m_DefaultRegion;
|
||||
|
||||
private int m_FileIndex;
|
||||
private readonly int m_FileIndex;
|
||||
|
||||
private string m_Name;
|
||||
private Sector[][] m_Sectors;
|
||||
private readonly Sector[][] m_Sectors;
|
||||
|
||||
private int m_SectorsWidth, m_SectorsHeight;
|
||||
private readonly int m_SectorsWidth;
|
||||
private readonly int m_SectorsHeight;
|
||||
|
||||
private TileMatrix m_Tiles;
|
||||
|
||||
private object tileLock = new object();
|
||||
private readonly object tileLock = new object();
|
||||
|
||||
public Map(int mapID, int mapIndex, int fileIndex, int width, int height, int season, string name, MapRules rules)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ namespace Server.Menus.ItemLists
|
|||
public class ItemListMenu : IMenu
|
||||
{
|
||||
private static int m_NextSerial;
|
||||
private int m_Serial;
|
||||
private readonly int m_Serial;
|
||||
|
||||
public ItemListMenu(string question, ItemListEntry[] entries)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ namespace Server.Menus.Questions
|
|||
public class QuestionMenu : IMenu
|
||||
{
|
||||
private static int m_NextSerial;
|
||||
private int m_Serial;
|
||||
private readonly int m_Serial;
|
||||
|
||||
public QuestionMenu(string question, string[] answers)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ namespace Server
|
|||
|
||||
public class TimedSkillMod : SkillMod
|
||||
{
|
||||
private DateTime m_Expire;
|
||||
private readonly DateTime m_Expire;
|
||||
|
||||
public TimedSkillMod(SkillName skill, bool relative, double value, TimeSpan delay)
|
||||
: this(skill, relative, value, DateTime.UtcNow + delay)
|
||||
|
|
@ -64,21 +64,16 @@ namespace Server
|
|||
}
|
||||
|
||||
public TimedSkillMod(SkillName skill, bool relative, double value, DateTime expire)
|
||||
: base(skill, relative, value)
|
||||
{
|
||||
: base(skill, relative, value) =>
|
||||
m_Expire = expire;
|
||||
}
|
||||
|
||||
public override bool CheckCondition()
|
||||
{
|
||||
return DateTime.UtcNow < m_Expire;
|
||||
}
|
||||
public override bool CheckCondition() => DateTime.UtcNow < m_Expire;
|
||||
}
|
||||
|
||||
public class EquippedSkillMod : SkillMod
|
||||
{
|
||||
private Item m_Item;
|
||||
private Mobile m_Mobile;
|
||||
private readonly Item m_Item;
|
||||
private readonly Mobile m_Mobile;
|
||||
|
||||
public EquippedSkillMod(SkillName skill, bool relative, double value, Item item, Mobile mobile)
|
||||
: base(skill, relative, value)
|
||||
|
|
@ -87,10 +82,7 @@ namespace Server
|
|||
m_Mobile = mobile;
|
||||
}
|
||||
|
||||
public override bool CheckCondition()
|
||||
{
|
||||
return !m_Item.Deleted && !m_Mobile.Deleted && m_Item.Parent == m_Mobile;
|
||||
}
|
||||
public override bool CheckCondition() => !m_Item.Deleted && !m_Mobile.Deleted && m_Item.Parent == m_Mobile;
|
||||
}
|
||||
|
||||
public class DefaultSkillMod : SkillMod
|
||||
|
|
@ -100,10 +92,7 @@ namespace Server
|
|||
{
|
||||
}
|
||||
|
||||
public override bool CheckCondition()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public override bool CheckCondition() => true;
|
||||
}
|
||||
|
||||
public abstract class SkillMod
|
||||
|
|
@ -265,8 +254,8 @@ namespace Server
|
|||
|
||||
public class StatMod
|
||||
{
|
||||
private DateTime m_Added;
|
||||
private TimeSpan m_Duration;
|
||||
private readonly DateTime m_Added;
|
||||
private readonly TimeSpan m_Duration;
|
||||
|
||||
public StatMod(StatType type, string name, int offset, TimeSpan duration)
|
||||
{
|
||||
|
|
@ -296,10 +285,7 @@ namespace Server
|
|||
|
||||
public class DamageEntry
|
||||
{
|
||||
public DamageEntry(Mobile damager)
|
||||
{
|
||||
Damager = damager;
|
||||
}
|
||||
public DamageEntry(Mobile damager) => Damager = damager;
|
||||
|
||||
public Mobile Damager{ get; }
|
||||
|
||||
|
|
@ -425,10 +411,8 @@ namespace Server
|
|||
public class MobileNotConnectedException : Exception
|
||||
{
|
||||
public MobileNotConnectedException(Mobile source, string message)
|
||||
: base(message)
|
||||
{
|
||||
: base(message) =>
|
||||
Source = source.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
#region Delegates
|
||||
|
|
@ -460,8 +444,8 @@ namespace Server
|
|||
/// </summary>
|
||||
public class Mobile : IHued, IComparable<Mobile>, ISerializable, ISpawnable, IPropertyListObject
|
||||
{
|
||||
private BufferWriter m_SaveBuffer;
|
||||
public BufferWriter SaveBuffer { get { return m_SaveBuffer; } }
|
||||
private readonly BufferWriter m_SaveBuffer;
|
||||
public BufferWriter SaveBuffer => m_SaveBuffer;
|
||||
|
||||
private const int
|
||||
WarmodeCatchCount = 4; // Allow four warmode changes in 0.5 seconds, any more will be delay for two seconds
|
||||
|
|
@ -470,23 +454,23 @@ namespace Server
|
|||
private static readonly TimeSpan WarmodeSpamDelay = TimeSpan.FromSeconds(Core.SE ? 4.0 : 2.0);
|
||||
|
||||
|
||||
private static Packet[][] m_MovingPacketCache = new Packet[][]
|
||||
private static readonly Packet[][] m_MovingPacketCache = new Packet[][]
|
||||
{
|
||||
new Packet[8],
|
||||
new Packet[8]
|
||||
};
|
||||
|
||||
private static List<IEntity> m_MoveList = new List<IEntity>();
|
||||
private static List<Mobile> m_MoveClientList = new List<Mobile>();
|
||||
private static readonly List<IEntity> m_MoveList = new List<IEntity>();
|
||||
private static readonly List<Mobile> m_MoveClientList = new List<Mobile>();
|
||||
|
||||
private static object m_GhostMutateContext = new object();
|
||||
private static readonly object m_GhostMutateContext = new object();
|
||||
|
||||
private static List<Mobile> m_Hears = new List<Mobile>();
|
||||
private static List<IEntity> m_OnSpeech = new List<IEntity>();
|
||||
private static readonly List<Mobile> m_Hears = new List<Mobile>();
|
||||
private static readonly List<IEntity> m_OnSpeech = new List<IEntity>();
|
||||
|
||||
public static bool m_DefaultShowVisibleDamage, m_DefaultCanSeeVisibleDamage;
|
||||
|
||||
private static string[] m_AccessLevelNames =
|
||||
private static readonly string[] m_AccessLevelNames =
|
||||
{
|
||||
"a player",
|
||||
"a counselor",
|
||||
|
|
@ -497,7 +481,7 @@ namespace Server
|
|||
"an owner"
|
||||
};
|
||||
|
||||
private static int[] m_InvalidBodies =
|
||||
private static readonly int[] m_InvalidBodies =
|
||||
{
|
||||
32,
|
||||
95,
|
||||
|
|
@ -506,12 +490,12 @@ namespace Server
|
|||
198
|
||||
};
|
||||
|
||||
private static Queue<Mobile> m_DeltaQueue = new Queue<Mobile>();
|
||||
private static Queue<Mobile> m_DeltaQueueR = new Queue<Mobile>();
|
||||
private static readonly Queue<Mobile> m_DeltaQueue = new Queue<Mobile>();
|
||||
private static readonly Queue<Mobile> m_DeltaQueueR = new Queue<Mobile>();
|
||||
|
||||
private static bool _processing;
|
||||
|
||||
private static string[] m_GuildTypes =
|
||||
private static readonly string[] m_GuildTypes =
|
||||
{
|
||||
"",
|
||||
" (Chaos)",
|
||||
|
|
@ -4367,10 +4351,7 @@ namespace Server
|
|||
/// <seealso cref="OnDeath" />
|
||||
/// </summary>
|
||||
/// <returns>True to continue with death, false to override it.</returns>
|
||||
public virtual bool OnBeforeDeath()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public virtual bool OnBeforeDeath() => true;
|
||||
|
||||
/// <summary>
|
||||
/// Overridable. Event invoked after the Mobile is <see cref="Kill">killed</see>. Primarily, this method is responsible for
|
||||
|
|
@ -5089,10 +5070,7 @@ namespace Server
|
|||
|
||||
public static Mobile GetDamagerFrom(DamageEntry de) => de?.Damager;
|
||||
|
||||
public Mobile FindMostRecentDamager(bool allowSelf)
|
||||
{
|
||||
return GetDamagerFrom(FindMostRecentDamageEntry(allowSelf));
|
||||
}
|
||||
public Mobile FindMostRecentDamager(bool allowSelf) => GetDamagerFrom(FindMostRecentDamageEntry(allowSelf));
|
||||
|
||||
public DamageEntry FindMostRecentDamageEntry(bool allowSelf)
|
||||
{
|
||||
|
|
@ -5199,10 +5177,7 @@ namespace Server
|
|||
return null;
|
||||
}
|
||||
|
||||
public virtual Mobile GetDamageMaster(Mobile damagee)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
public virtual Mobile GetDamageMaster(Mobile damagee) => null;
|
||||
|
||||
public virtual DamageEntry RegisterDamage(int amount, Mobile from)
|
||||
{
|
||||
|
|
@ -5251,10 +5226,7 @@ namespace Server
|
|||
Damage(amount, null);
|
||||
}
|
||||
|
||||
public virtual bool CanBeDamaged()
|
||||
{
|
||||
return !m_Blessed;
|
||||
}
|
||||
public virtual bool CanBeDamaged() => !m_Blessed;
|
||||
|
||||
public virtual void Damage(int amount, Mobile from)
|
||||
{
|
||||
|
|
@ -5906,15 +5878,9 @@ namespace Server
|
|||
}
|
||||
}
|
||||
|
||||
public static string GetAccessLevelName(AccessLevel level)
|
||||
{
|
||||
return m_AccessLevelNames[(int)level];
|
||||
}
|
||||
public static string GetAccessLevelName(AccessLevel level) => m_AccessLevelNames[(int)level];
|
||||
|
||||
public virtual bool CanPaperdollBeOpenedBy(Mobile from)
|
||||
{
|
||||
return Body.IsHuman || Body.IsGhost || IsBodyMod;
|
||||
}
|
||||
public virtual bool CanPaperdollBeOpenedBy(Mobile from) => Body.IsHuman || Body.IsGhost || IsBodyMod;
|
||||
|
||||
public virtual void GetChildContextMenuEntries(Mobile from, List<ContextMenuEntry> list, Item item)
|
||||
{
|
||||
|
|
@ -6215,10 +6181,7 @@ namespace Server
|
|||
eable.Free();
|
||||
}
|
||||
|
||||
public bool Send(Packet p)
|
||||
{
|
||||
return Send(p, false);
|
||||
}
|
||||
public bool Send(Packet p) => Send(p, false);
|
||||
|
||||
public bool Send(Packet p, bool throwOnOffline)
|
||||
{
|
||||
|
|
@ -6254,10 +6217,7 @@ namespace Server
|
|||
RevealingAction();
|
||||
}
|
||||
|
||||
public virtual bool HandlesOnSpeech(Mobile from)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
public virtual bool HandlesOnSpeech(Mobile from) => false;
|
||||
|
||||
/// <summary>
|
||||
/// Overridable. Virtual event invoked when the Mobile hears speech. This event will only be invoked if
|
||||
|
|
@ -6337,10 +6297,7 @@ namespace Server
|
|||
m_Direction = dir;
|
||||
}
|
||||
|
||||
public virtual int GetSeason()
|
||||
{
|
||||
return m_Map?.Season ?? 1;
|
||||
}
|
||||
public virtual int GetSeason() => m_Map?.Season ?? 1;
|
||||
|
||||
public virtual int GetPacketFlags()
|
||||
{
|
||||
|
|
@ -6505,10 +6462,7 @@ namespace Server
|
|||
m_AccessLevel > AccessLevel.Player || m.Warmode);
|
||||
}
|
||||
|
||||
public virtual bool CanBeRenamedBy(Mobile from)
|
||||
{
|
||||
return from.AccessLevel >= AccessLevel.GameMaster && from.m_AccessLevel > m_AccessLevel;
|
||||
}
|
||||
public virtual bool CanBeRenamedBy(Mobile from) => from.AccessLevel >= AccessLevel.GameMaster && from.m_AccessLevel > m_AccessLevel;
|
||||
|
||||
public virtual void OnGuildTitleChange(string oldTitle)
|
||||
{
|
||||
|
|
@ -6738,10 +6692,7 @@ namespace Server
|
|||
|
||||
public bool HasFreeHand() => FindItemOnLayer(Layer.TwoHanded) == null;
|
||||
|
||||
public virtual IWeapon GetDefaultWeapon()
|
||||
{
|
||||
return DefaultWeapon;
|
||||
}
|
||||
public virtual IWeapon GetDefaultWeapon() => DefaultWeapon;
|
||||
|
||||
public BankBox FindBankNoCreate()
|
||||
{
|
||||
|
|
@ -6827,21 +6778,13 @@ namespace Server
|
|||
return true;
|
||||
}
|
||||
|
||||
public virtual bool CheckLift(Mobile from, Item item, ref LRReason reject)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public virtual bool CheckLift(Mobile from, Item item, ref LRReason reject) => true;
|
||||
|
||||
public virtual bool CheckNonlocalLift(Mobile from, Item item)
|
||||
{
|
||||
return from == this || from.AccessLevel > AccessLevel && from.AccessLevel >= AccessLevel.GameMaster;
|
||||
}
|
||||
public virtual bool CheckNonlocalLift(Mobile from, Item item) => from == this || from.AccessLevel > AccessLevel && from.AccessLevel >= AccessLevel.GameMaster;
|
||||
|
||||
public virtual bool CheckTrade(Mobile to, Item item, SecureTradeContainer cont, bool message, bool checkItems,
|
||||
int plusItems, int plusWeight)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
int plusItems, int plusWeight) =>
|
||||
true;
|
||||
|
||||
public virtual bool OpenTrade(Mobile from, Item offer = null)
|
||||
{
|
||||
|
|
@ -6927,10 +6870,7 @@ namespace Server
|
|||
/// return base.OnDragLift( item );
|
||||
/// }</code>
|
||||
/// </example>
|
||||
public virtual bool OnDragLift(Item item)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public virtual bool OnDragLift(Item item) => true;
|
||||
|
||||
/// <summary>
|
||||
/// Overridable. Virtual event invoked when the Mobile attempts to drop <paramref name="item" /> into a
|
||||
|
|
@ -6940,40 +6880,28 @@ namespace Server
|
|||
/// .
|
||||
/// </summary>
|
||||
/// <returns>True if the drop is allowed, false if otherwise.</returns>
|
||||
public virtual bool OnDroppedItemInto(Item item, Container container, Point3D loc)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public virtual bool OnDroppedItemInto(Item item, Container container, Point3D loc) => true;
|
||||
|
||||
/// <summary>
|
||||
/// Overridable. Virtual event invoked when the Mobile attempts to drop <paramref name="item" /> directly onto another
|
||||
/// <see cref="Item" />, <paramref name="target" />. This is the case of stacking items.
|
||||
/// </summary>
|
||||
/// <returns>True if the drop is allowed, false if otherwise.</returns>
|
||||
public virtual bool OnDroppedItemOnto(Item item, Item target)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public virtual bool OnDroppedItemOnto(Item item, Item target) => true;
|
||||
|
||||
/// <summary>
|
||||
/// Overridable. Virtual event invoked when the Mobile attempts to drop <paramref name="item" /> into another
|
||||
/// <see cref="Item" />, <paramref name="target" />. The target item is most likely a <see cref="Container" />.
|
||||
/// </summary>
|
||||
/// <returns>True if the drop is allowed, false if otherwise.</returns>
|
||||
public virtual bool OnDroppedItemToItem(Item item, Item target, Point3D loc)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public virtual bool OnDroppedItemToItem(Item item, Item target, Point3D loc) => true;
|
||||
|
||||
/// <summary>
|
||||
/// Overridable. Virtual event invoked when the Mobile attempts to give <paramref name="item" /> to a Mobile (
|
||||
/// <paramref name="target" />).
|
||||
/// </summary>
|
||||
/// <returns>True if the drop is allowed, false if otherwise.</returns>
|
||||
public virtual bool OnDroppedItemToMobile(Item item, Mobile target)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public virtual bool OnDroppedItemToMobile(Item item, Mobile target) => true;
|
||||
|
||||
/// <summary>
|
||||
/// Overridable. Virtual event invoked when the Mobile attempts to drop <paramref name="item" /> to the world at a
|
||||
|
|
@ -6983,10 +6911,7 @@ namespace Server
|
|||
/// .
|
||||
/// </summary>
|
||||
/// <returns>True if the drop is allowed, false if otherwise.</returns>
|
||||
public virtual bool OnDroppedItemToWorld(Item item, Point3D location)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public virtual bool OnDroppedItemToWorld(Item item, Point3D location) => true;
|
||||
|
||||
/// <summary>
|
||||
/// Overridable. Virtual event when <paramref name="from" /> successfully uses <paramref name="item" /> while it's on this
|
||||
|
|
@ -6997,15 +6922,9 @@ namespace Server
|
|||
{
|
||||
}
|
||||
|
||||
public virtual bool CheckNonlocalDrop(Mobile from, Item item, Item target)
|
||||
{
|
||||
return from == this || from.AccessLevel > AccessLevel && from.AccessLevel >= AccessLevel.GameMaster;
|
||||
}
|
||||
public virtual bool CheckNonlocalDrop(Mobile from, Item item, Item target) => from == this || from.AccessLevel > AccessLevel && from.AccessLevel >= AccessLevel.GameMaster;
|
||||
|
||||
public virtual bool CheckItemUse(Mobile from, Item item)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public virtual bool CheckItemUse(Mobile from, Item item) => true;
|
||||
|
||||
/// <summary>
|
||||
/// Overridable. Virtual event invoked when <paramref name="from" /> successfully lifts <paramref name="item" /> from this
|
||||
|
|
@ -7016,15 +6935,9 @@ namespace Server
|
|||
{
|
||||
}
|
||||
|
||||
public virtual bool AllowItemUse(Item item)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public virtual bool AllowItemUse(Item item) => true;
|
||||
|
||||
public virtual bool AllowEquipFrom(Mobile mob)
|
||||
{
|
||||
return mob == this || mob.AccessLevel >= AccessLevel.GameMaster && mob.AccessLevel > AccessLevel;
|
||||
}
|
||||
public virtual bool AllowEquipFrom(Mobile mob) => mob == this || mob.AccessLevel >= AccessLevel.GameMaster && mob.AccessLevel > AccessLevel;
|
||||
|
||||
public virtual bool EquipItem(Item item)
|
||||
{
|
||||
|
|
@ -7304,13 +7217,10 @@ namespace Server
|
|||
|
||||
private class MovementRecord
|
||||
{
|
||||
private static Queue<MovementRecord> m_InstancePool = new Queue<MovementRecord>();
|
||||
private static readonly Queue<MovementRecord> m_InstancePool = new Queue<MovementRecord>();
|
||||
public long m_End;
|
||||
|
||||
private MovementRecord(long end)
|
||||
{
|
||||
m_End = end;
|
||||
}
|
||||
private MovementRecord(long end) => m_End = end;
|
||||
|
||||
public static MovementRecord NewInstance(long end)
|
||||
{
|
||||
|
|
@ -7343,7 +7253,7 @@ namespace Server
|
|||
|
||||
private class WarmodeTimer : Timer
|
||||
{
|
||||
private Mobile m_Mobile;
|
||||
private readonly Mobile m_Mobile;
|
||||
|
||||
public WarmodeTimer(Mobile m, bool value)
|
||||
: base(WarmodeSpamDelay)
|
||||
|
|
@ -7365,13 +7275,11 @@ namespace Server
|
|||
|
||||
private class SimpleTarget : Target
|
||||
{
|
||||
private TargetCallback m_Callback;
|
||||
private readonly TargetCallback m_Callback;
|
||||
|
||||
public SimpleTarget(int range, TargetFlags flags, bool allowGround, TargetCallback callback)
|
||||
: base(range, allowGround, flags)
|
||||
{
|
||||
: base(range, allowGround, flags) =>
|
||||
m_Callback = callback;
|
||||
}
|
||||
|
||||
protected override void OnTarget(Mobile from, object targeted)
|
||||
{
|
||||
|
|
@ -7381,8 +7289,8 @@ namespace Server
|
|||
|
||||
private class SimpleStateTarget<T> : Target
|
||||
{
|
||||
private TargetStateCallback<T> m_Callback;
|
||||
private T m_State;
|
||||
private readonly TargetStateCallback<T> m_Callback;
|
||||
private readonly T m_State;
|
||||
|
||||
public SimpleStateTarget(int range, TargetFlags flags, bool allowGround, TargetStateCallback<T> callback,
|
||||
T state)
|
||||
|
|
@ -7400,13 +7308,11 @@ namespace Server
|
|||
|
||||
private class AutoManifestTimer : Timer
|
||||
{
|
||||
private Mobile m_Mobile;
|
||||
private readonly Mobile m_Mobile;
|
||||
|
||||
public AutoManifestTimer(Mobile m, TimeSpan delay)
|
||||
: base(delay)
|
||||
{
|
||||
: base(delay) =>
|
||||
m_Mobile = m;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
|
|
@ -7419,17 +7325,11 @@ namespace Server
|
|||
{
|
||||
private static LocationComparer m_Instance;
|
||||
|
||||
public LocationComparer(IEntity relativeTo)
|
||||
{
|
||||
RelativeTo = relativeTo;
|
||||
}
|
||||
public LocationComparer(IEntity relativeTo) => RelativeTo = relativeTo;
|
||||
|
||||
public IEntity RelativeTo{ get; set; }
|
||||
|
||||
public int Compare(IEntity x, IEntity y)
|
||||
{
|
||||
return GetDistance(x) - GetDistance(y);
|
||||
}
|
||||
public int Compare(IEntity x, IEntity y) => GetDistance(x) - GetDistance(y);
|
||||
|
||||
public static LocationComparer GetInstance(IEntity relativeTo)
|
||||
{
|
||||
|
|
@ -7454,15 +7354,9 @@ namespace Server
|
|||
}
|
||||
}
|
||||
|
||||
int IComparable<IEntity>.CompareTo(IEntity other)
|
||||
{
|
||||
return other == null ? -1 : Serial.CompareTo(other.Serial);
|
||||
}
|
||||
int IComparable<IEntity>.CompareTo(IEntity other) => other == null ? -1 : Serial.CompareTo(other.Serial);
|
||||
|
||||
public int CompareTo(Mobile other)
|
||||
{
|
||||
return other == null ? -1 : Serial.CompareTo(other.Serial);
|
||||
}
|
||||
public int CompareTo(Mobile other) => other == null ? -1 : Serial.CompareTo(other.Serial);
|
||||
|
||||
#region Handlers
|
||||
|
||||
|
|
@ -7581,7 +7475,7 @@ namespace Server
|
|||
|
||||
private class ManaTimer : Timer
|
||||
{
|
||||
private Mobile m_Owner;
|
||||
private readonly Mobile m_Owner;
|
||||
|
||||
public ManaTimer(Mobile m)
|
||||
: base(GetManaRegenRate(m), GetManaRegenRate(m))
|
||||
|
|
@ -7601,7 +7495,7 @@ namespace Server
|
|||
|
||||
private class HitsTimer : Timer
|
||||
{
|
||||
private Mobile m_Owner;
|
||||
private readonly Mobile m_Owner;
|
||||
|
||||
public HitsTimer(Mobile m)
|
||||
: base(GetHitsRegenRate(m), GetHitsRegenRate(m))
|
||||
|
|
@ -7621,7 +7515,7 @@ namespace Server
|
|||
|
||||
private class StamTimer : Timer
|
||||
{
|
||||
private Mobile m_Owner;
|
||||
private readonly Mobile m_Owner;
|
||||
|
||||
public StamTimer(Mobile m)
|
||||
: base(GetStamRegenRate(m), GetStamRegenRate(m))
|
||||
|
|
@ -7641,7 +7535,7 @@ namespace Server
|
|||
|
||||
private class LogoutTimer : Timer
|
||||
{
|
||||
private Mobile m_Mobile;
|
||||
private readonly Mobile m_Mobile;
|
||||
|
||||
public LogoutTimer(Mobile m)
|
||||
: base(TimeSpan.FromDays(1.0))
|
||||
|
|
@ -7666,7 +7560,7 @@ namespace Server
|
|||
|
||||
private class ParalyzedTimer : Timer
|
||||
{
|
||||
private Mobile m_Mobile;
|
||||
private readonly Mobile m_Mobile;
|
||||
|
||||
public ParalyzedTimer(Mobile m, TimeSpan duration)
|
||||
: base(duration)
|
||||
|
|
@ -7683,7 +7577,7 @@ namespace Server
|
|||
|
||||
private class FrozenTimer : Timer
|
||||
{
|
||||
private Mobile m_Mobile;
|
||||
private readonly Mobile m_Mobile;
|
||||
|
||||
public FrozenTimer(Mobile m, TimeSpan duration)
|
||||
: base(duration)
|
||||
|
|
@ -7700,7 +7594,7 @@ namespace Server
|
|||
|
||||
private class CombatTimer : Timer
|
||||
{
|
||||
private Mobile m_Mobile;
|
||||
private readonly Mobile m_Mobile;
|
||||
|
||||
public CombatTimer(Mobile m) : base(TimeSpan.FromSeconds(0.0), TimeSpan.FromSeconds(0.01))
|
||||
{
|
||||
|
|
@ -7744,7 +7638,7 @@ namespace Server
|
|||
|
||||
private class ExpireCombatantTimer : Timer
|
||||
{
|
||||
private Mobile m_Mobile;
|
||||
private readonly Mobile m_Mobile;
|
||||
|
||||
public ExpireCombatantTimer(Mobile m)
|
||||
: base(TimeSpan.FromMinutes(1.0))
|
||||
|
|
@ -7763,7 +7657,7 @@ namespace Server
|
|||
|
||||
private class ExpireCriminalTimer : Timer
|
||||
{
|
||||
private Mobile m_Mobile;
|
||||
private readonly Mobile m_Mobile;
|
||||
|
||||
public ExpireCriminalTimer(Mobile m)
|
||||
: base(ExpireCriminalDelay)
|
||||
|
|
@ -7780,7 +7674,7 @@ namespace Server
|
|||
|
||||
private class ExpireAggressorsTimer : Timer
|
||||
{
|
||||
private Mobile m_Mobile;
|
||||
private readonly Mobile m_Mobile;
|
||||
|
||||
public ExpireAggressorsTimer(Mobile m)
|
||||
: base(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(5.0))
|
||||
|
|
@ -7804,9 +7698,9 @@ namespace Server
|
|||
|
||||
private class SimplePrompt : Prompt
|
||||
{
|
||||
private PromptCallback m_Callback;
|
||||
private bool m_CallbackHandlesCancel;
|
||||
private PromptCallback m_CancelCallback;
|
||||
private readonly PromptCallback m_Callback;
|
||||
private readonly bool m_CallbackHandlesCancel;
|
||||
private readonly PromptCallback m_CancelCallback;
|
||||
|
||||
public SimplePrompt(PromptCallback callback, PromptCallback cancelCallback)
|
||||
{
|
||||
|
|
@ -7830,9 +7724,7 @@ namespace Server
|
|||
if (m_CallbackHandlesCancel && m_Callback != null)
|
||||
m_Callback(from, "");
|
||||
else
|
||||
{
|
||||
m_CancelCallback?.Invoke(from, "");
|
||||
}
|
||||
m_CancelCallback?.Invoke(@from, "");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7848,10 +7740,10 @@ namespace Server
|
|||
|
||||
private class SimpleStatePrompt<T> : Prompt
|
||||
{
|
||||
private PromptStateCallback<T> m_Callback;
|
||||
private PromptStateCallback<T> m_CancelCallback;
|
||||
private readonly PromptStateCallback<T> m_Callback;
|
||||
private readonly PromptStateCallback<T> m_CancelCallback;
|
||||
|
||||
private T m_State;
|
||||
private readonly T m_State;
|
||||
|
||||
public SimpleStatePrompt(PromptStateCallback<T> callback, PromptStateCallback<T> cancelCallback, T state)
|
||||
{
|
||||
|
|
@ -7962,10 +7854,7 @@ namespace Server
|
|||
|
||||
#region Get*InRange
|
||||
|
||||
public IPooledEnumerable<Item> GetItemsInRange(int range)
|
||||
{
|
||||
return GetItemsInRange<Item>(range);
|
||||
}
|
||||
public IPooledEnumerable<Item> GetItemsInRange(int range) => GetItemsInRange<Item>(range);
|
||||
|
||||
public IPooledEnumerable<T> GetItemsInRange<T>(int range) where T : Item
|
||||
{
|
||||
|
|
@ -7987,10 +7876,7 @@ namespace Server
|
|||
return map.GetObjectsInRange(m_Location, range);
|
||||
}
|
||||
|
||||
public IPooledEnumerable<Mobile> GetMobilesInRange(int range)
|
||||
{
|
||||
return GetMobilesInRange<Mobile>(range);
|
||||
}
|
||||
public IPooledEnumerable<Mobile> GetMobilesInRange(int range) => GetMobilesInRange<Mobile>(range);
|
||||
|
||||
public IPooledEnumerable<T> GetMobilesInRange<T>(int range) where T : Mobile
|
||||
{
|
||||
|
|
@ -8177,10 +8063,7 @@ namespace Server
|
|||
return true;
|
||||
}
|
||||
|
||||
public bool HasGump<T>() where T : Gump
|
||||
{
|
||||
return FindGump<T>() != null;
|
||||
}
|
||||
public bool HasGump<T>() where T : Gump => FindGump<T>() != null;
|
||||
|
||||
public bool SendGump(Gump g)
|
||||
{
|
||||
|
|
@ -8204,15 +8087,9 @@ namespace Server
|
|||
|
||||
#region Beneficial Checks/Actions
|
||||
|
||||
public virtual bool CanBeBeneficial(Mobile target)
|
||||
{
|
||||
return CanBeBeneficial(target, true, false);
|
||||
}
|
||||
public virtual bool CanBeBeneficial(Mobile target) => CanBeBeneficial(target, true, false);
|
||||
|
||||
public virtual bool CanBeBeneficial(Mobile target, bool message)
|
||||
{
|
||||
return CanBeBeneficial(target, message, false);
|
||||
}
|
||||
public virtual bool CanBeBeneficial(Mobile target, bool message) => CanBeBeneficial(target, message, false);
|
||||
|
||||
public virtual bool CanBeBeneficial(Mobile target, bool message, bool allowDead)
|
||||
{
|
||||
|
|
@ -9001,10 +8878,7 @@ namespace Server
|
|||
/// <seealso cref="ApplyPoison" />
|
||||
/// <seealso cref="Poison" />
|
||||
/// </summary>
|
||||
public virtual bool CheckPoisonImmunity(Mobile from, Poison poison)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
public virtual bool CheckPoisonImmunity(Mobile from, Poison poison) => false;
|
||||
|
||||
/// <summary>
|
||||
/// Overridable. Called from <see cref="ApplyPoison" />, this method checks if the Mobile is already poisoned by some
|
||||
|
|
@ -9014,10 +8888,7 @@ namespace Server
|
|||
/// <seealso cref="ApplyPoison" />
|
||||
/// <seealso cref="Poison" />
|
||||
/// </summary>
|
||||
public virtual bool CheckHigherPoison(Mobile from, Poison poison)
|
||||
{
|
||||
return m_Poison != null && m_Poison.Level >= poison.Level;
|
||||
}
|
||||
public virtual bool CheckHigherPoison(Mobile from, Poison poison) => m_Poison != null && m_Poison.Level >= poison.Level;
|
||||
|
||||
/// <summary>
|
||||
/// Overridable. Attempts to apply poison to the Mobile. Checks are made such that no
|
||||
|
|
@ -9090,10 +8961,7 @@ namespace Server
|
|||
/// <seealso cref="CurePoison" />
|
||||
/// <seealso cref="Poison" />
|
||||
/// </summary>
|
||||
public virtual bool CheckCure(Mobile from)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public virtual bool CheckCure(Mobile from) => true;
|
||||
|
||||
/// <summary>
|
||||
/// Overridable. Virtual event invoked when a call to <see cref="CurePoison" /> succeeded.
|
||||
|
|
@ -9166,10 +9034,7 @@ namespace Server
|
|||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public int FacialHairItemID
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_FacialHair?.ItemID ?? 0;
|
||||
}
|
||||
get => m_FacialHair?.ItemID ?? 0;
|
||||
set
|
||||
{
|
||||
if (m_FacialHair == null && value > 0)
|
||||
|
|
@ -9327,15 +9192,9 @@ namespace Server
|
|||
return ret;
|
||||
}
|
||||
|
||||
public Direction GetDirectionTo(Point2D p)
|
||||
{
|
||||
return GetDirectionTo(p.m_X, p.m_Y);
|
||||
}
|
||||
public Direction GetDirectionTo(Point2D p) => GetDirectionTo(p.m_X, p.m_Y);
|
||||
|
||||
public Direction GetDirectionTo(Point3D p)
|
||||
{
|
||||
return GetDirectionTo(p.m_X, p.m_Y);
|
||||
}
|
||||
public Direction GetDirectionTo(Point3D p) => GetDirectionTo(p.m_X, p.m_Y);
|
||||
|
||||
public Direction GetDirectionTo(IPoint2D p)
|
||||
{
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue