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/Logs
|
||||||
/Distribution/Backups
|
/Distribution/Backups
|
||||||
/Distribution/Saves
|
/Distribution/Saves
|
||||||
|
/Distribution/docs
|
||||||
/Distribution/System.IO.Pipelines.dll
|
/Distribution/System.IO.Pipelines.dll
|
||||||
/Distribution/libdrng.dll
|
/Distribution/libdrng.dll
|
||||||
/Distribution/zlib.dll
|
/Distribution/zlib.dll
|
||||||
|
|
@ -12,21 +13,17 @@
|
||||||
/Distribution/System.Runtime.CompilerServices.Unsafe.dll
|
/Distribution/System.Runtime.CompilerServices.Unsafe.dll
|
||||||
|
|
||||||
# LibUv Dependencies
|
# LibUv Dependencies
|
||||||
|
/Distribution/libuv.dylib
|
||||||
/Distribution/libuv.dll
|
/Distribution/libuv.dll
|
||||||
|
/Distribution/libuv.so
|
||||||
/Distribution/Microsoft.AspNetCore.Connections.Abstractions.dll
|
/Distribution/Microsoft.AspNetCore.Connections.Abstractions.dll
|
||||||
/Distribution/Microsoft.AspNetCore.Http.Features.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.Abstractions.dll
|
||||||
/Distribution/Microsoft.Extensions.Configuration.Binder.dll
|
|
||||||
/Distribution/Microsoft.Extensions.Configuration.dll
|
|
||||||
/Distribution/Microsoft.Extensions.DependencyInjection.Abstractions.dll
|
/Distribution/Microsoft.Extensions.DependencyInjection.Abstractions.dll
|
||||||
/Distribution/Microsoft.Extensions.DependencyInjection.dll
|
|
||||||
/Distribution/Microsoft.Extensions.FileProviders.Abstractions.dll
|
/Distribution/Microsoft.Extensions.FileProviders.Abstractions.dll
|
||||||
/Distribution/Microsoft.Extensions.Hosting.Abstractions.dll
|
/Distribution/Microsoft.Extensions.Hosting.Abstractions.dll
|
||||||
/Distribution/Microsoft.Extensions.Logging.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.Options.dll
|
||||||
/Distribution/Microsoft.Extensions.Primitives.dll
|
/Distribution/Microsoft.Extensions.Primitives.dll
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ namespace Server.Misc
|
||||||
if (!Enabled || IsExempt(ourAddress))
|
if (!Enabled || IsExempt(ourAddress))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
List<NetState> netStates = NetState.Instances;
|
List<NetState> netStates = TcpServer.Instances;
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
|
|
@ -50,4 +50,4 @@ namespace Server.Misc
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ namespace Server.Commands.Generic
|
||||||
List<object> list = new List<object>();
|
List<object> list = new List<object>();
|
||||||
List<IPAddress> addresses = new List<IPAddress>();
|
List<IPAddress> addresses = new List<IPAddress>();
|
||||||
|
|
||||||
List<NetState> states = NetState.Instances;
|
List<NetState> states = TcpServer.Instances;
|
||||||
|
|
||||||
for (int i = 0; i < states.Count; ++i)
|
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<object> list = new List<object>();
|
||||||
|
|
||||||
List<NetState> states = NetState.Instances;
|
List<NetState> states = TcpServer.Instances;
|
||||||
|
|
||||||
for (int i = 0; i < states.Count; ++i)
|
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)
|
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;
|
Mobile m = state.Mobile;
|
||||||
|
|
||||||
|
|
@ -743,7 +743,7 @@ namespace Server.Commands
|
||||||
[Description("View some stats about the server.")]
|
[Description("View some stats about the server.")]
|
||||||
public static void Stats_OnCommand(CommandEventArgs e)
|
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("Mobiles: {0}", World.Mobiles.Count);
|
||||||
e.Mobile.SendMessage("Items: {0}", World.Items.Count);
|
e.Mobile.SendMessage("Items: {0}", World.Items.Count);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -212,7 +212,7 @@ namespace Server.Engines.Help
|
||||||
|
|
||||||
bool isStaffOnline = false;
|
bool isStaffOnline = false;
|
||||||
|
|
||||||
foreach (NetState ns in NetState.Instances)
|
foreach (NetState ns in TcpServer.Instances)
|
||||||
{
|
{
|
||||||
Mobile m = ns.Mobile;
|
Mobile m = ns.Mobile;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -133,7 +133,7 @@ namespace Server.Gumps
|
||||||
AddLabel(150, 170, LabelHue, Firewall.List.Count.ToString());
|
AddLabel(150, 170, LabelHue, Firewall.List.Count.ToString());
|
||||||
|
|
||||||
AddLabel(20, 190, LabelHue, "Clients:");
|
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(20, 210, LabelHue, "Mobiles:");
|
||||||
AddLabel(150, 210, LabelHue, World.Mobiles.Count.ToString());
|
AddLabel(150, 210, LabelHue, World.Mobiles.Count.ToString());
|
||||||
|
|
@ -380,7 +380,7 @@ namespace Server.Gumps
|
||||||
{
|
{
|
||||||
if (m_List == null)
|
if (m_List == null)
|
||||||
{
|
{
|
||||||
List<NetState> states = NetState.Instances.ToList();
|
List<NetState> states = TcpServer.Instances;
|
||||||
states.Sort(NetStateComparer.Instance);
|
states.Sort(NetStateComparer.Instance);
|
||||||
|
|
||||||
m_List = states.ToList<object>();
|
m_List = states.ToList<object>();
|
||||||
|
|
@ -1932,7 +1932,7 @@ namespace Server.Gumps
|
||||||
|
|
||||||
if (level > AccessLevel.Player)
|
if (level > AccessLevel.Player)
|
||||||
{
|
{
|
||||||
List<NetState> clients = NetState.Instances;
|
List<NetState> clients = TcpServer.Instances;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
for (int i = 0; i < clients.Count; ++i)
|
for (int i = 0; i < clients.Count; ++i)
|
||||||
|
|
@ -2020,7 +2020,7 @@ namespace Server.Gumps
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
List<NetState> instances = NetState.Instances;
|
List<NetState> instances = TcpServer.Instances;
|
||||||
|
|
||||||
for (int i = 0; i < instances.Count; ++i)
|
for (int i = 0; i < instances.Count; ++i)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,7 @@ namespace Server.Gumps
|
||||||
string filter = string.IsNullOrWhiteSpace(rawFilter) ? null : rawFilter.Trim().ToLower();
|
string filter = string.IsNullOrWhiteSpace(rawFilter) ? null : rawFilter.Trim().ToLower();
|
||||||
|
|
||||||
List<Mobile> list = new List<Mobile>();
|
List<Mobile> list = new List<Mobile>();
|
||||||
List<NetState> states = NetState.Instances;
|
List<NetState> states = TcpServer.Instances;
|
||||||
|
|
||||||
for ( int i = 0; i < states.Count; ++i )
|
for ( int i = 0; i < states.Count; ++i )
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -202,7 +202,7 @@ namespace Server.Misc
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
List<NetState> states = NetState.Instances;
|
List<NetState> states = TcpServer.Instances;
|
||||||
|
|
||||||
op.WriteLine("- Count: {0}", states.Count);
|
op.WriteLine("- Count: {0}", states.Count);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ namespace Server.Misc
|
||||||
|
|
||||||
public static void FoodDecay()
|
public static void FoodDecay()
|
||||||
{
|
{
|
||||||
foreach (NetState state in NetState.Instances)
|
foreach (NetState state in TcpServer.Instances)
|
||||||
{
|
{
|
||||||
HungerDecay(state.Mobile);
|
HungerDecay(state.Mobile);
|
||||||
ThirstDecay(state.Mobile);
|
ThirstDecay(state.Mobile);
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,9 @@ namespace Server
|
||||||
{
|
{
|
||||||
m_LevelOverride = value;
|
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;
|
Mobile m = ns.Mobile;
|
||||||
|
|
||||||
m?.CheckLightLevels(false);
|
m?.CheckLightLevels(false);
|
||||||
|
|
@ -69,12 +69,12 @@ namespace Server
|
||||||
Clock.GetTime(from.Map, from.X, from.Y, out int hours, out int minutes);
|
Clock.GetTime(from.Map, from.X, from.Y, out int hours, out int minutes);
|
||||||
|
|
||||||
/* OSI times:
|
/* OSI times:
|
||||||
*
|
*
|
||||||
* Midnight -> 3:59 AM : Night
|
* Midnight -> 3:59 AM : Night
|
||||||
* 4:00 AM -> 11:59 PM : Day
|
* 4:00 AM -> 11:59 PM : Day
|
||||||
*
|
*
|
||||||
* RunUO times:
|
* RunUO times:
|
||||||
*
|
*
|
||||||
* 10:00 PM -> 11:59 PM : Scale to night
|
* 10:00 PM -> 11:59 PM : Scale to night
|
||||||
* Midnight -> 3:59 AM : Night
|
* Midnight -> 3:59 AM : Night
|
||||||
* 4:00 AM -> 5:59 AM : Scale to day
|
* 4:00 AM -> 5:59 AM : Scale to day
|
||||||
|
|
@ -102,9 +102,9 @@ namespace Server
|
||||||
|
|
||||||
protected override void OnTick()
|
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;
|
Mobile m = ns.Mobile;
|
||||||
|
|
||||||
m?.CheckLightLevels(false);
|
m?.CheckLightLevels(false);
|
||||||
|
|
@ -130,4 +130,4 @@ namespace Server
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ namespace Server.Misc
|
||||||
|
|
||||||
private static void EventSink_Login(LoginEventArgs args)
|
private static void EventSink_Login(LoginEventArgs args)
|
||||||
{
|
{
|
||||||
int userCount = NetState.Instances.Count;
|
int userCount = TcpServer.Instances.Count;
|
||||||
int itemCount = World.Items.Count;
|
int itemCount = World.Items.Count;
|
||||||
int mobileCount = World.Mobiles.Count;
|
int mobileCount = World.Mobiles.Count;
|
||||||
|
|
||||||
|
|
@ -27,4 +27,4 @@ namespace Server.Misc
|
||||||
mobileCount, mobileCount == 1 ? "" : "s");
|
mobileCount, mobileCount == 1 ? "" : "s");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ using Server.Network;
|
||||||
|
|
||||||
namespace Server.Misc
|
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
|
* 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 System.Net;
|
||||||
|
using Server.Network;
|
||||||
|
|
||||||
namespace Server
|
namespace Server
|
||||||
{
|
{
|
||||||
|
|
@ -15,8 +16,7 @@ namespace Server
|
||||||
|
|
||||||
public static void RegisterListeners()
|
public static void RegisterListeners()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < m_ListenerEndPoints.Length; i++)
|
TcpServer.Listeners.AddRange(m_ListenerEndPoints);
|
||||||
Core.MessagePump.AddListener(m_ListenerEndPoints[i]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -316,10 +316,7 @@ namespace Server
|
||||||
|
|
||||||
private static void ProcessDisplayCase(Map map, StaticTile[] tiles, int x, int y)
|
private static void ProcessDisplayCase(Map map, StaticTile[] tiles, int x, int y)
|
||||||
{
|
{
|
||||||
ShopFlags flags = ShopFlags.None;
|
ShopFlags flags = tiles.Aggregate(ShopFlags.None, (current, t) => current | ProcessDisplayedItem(t.ID));
|
||||||
|
|
||||||
for (int i = 0; i < tiles.Length; ++i)
|
|
||||||
flags |= ProcessDisplayedItem(tiles[i].ID);
|
|
||||||
|
|
||||||
if (flags != ShopFlags.None)
|
if (flags != ShopFlags.None)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -263,7 +263,7 @@ namespace Server.Misc
|
||||||
else
|
else
|
||||||
type = 2;
|
type = 2;
|
||||||
|
|
||||||
List<NetState> states = NetState.Instances;
|
List<NetState> states = TcpServer.Instances;
|
||||||
|
|
||||||
Packet weatherPacket = null;
|
Packet weatherPacket = null;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -119,7 +119,7 @@ namespace Server.Misc
|
||||||
|
|
||||||
int index = 0;
|
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;
|
++index;
|
||||||
|
|
||||||
|
|
@ -181,4 +181,4 @@ namespace Server.Misc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,8 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="MailKit" Version="2.4.1" />
|
<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>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ namespace Server.Misc
|
||||||
{
|
{
|
||||||
Mobile from = e.Mobile;
|
Mobile from = e.Mobile;
|
||||||
|
|
||||||
if (from?.AccessLevel < AccessLevel.Counselor)
|
if (from == null || from.AccessLevel < AccessLevel.Counselor)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (HasDisconnected(from))
|
if (HasDisconnected(from))
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ namespace Server
|
||||||
{
|
{
|
||||||
public class AggressorInfo
|
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 Mobile m_Attacker, m_Defender;
|
||||||
private bool m_CanReportMurder;
|
private bool m_CanReportMurder;
|
||||||
private bool m_CriminalAggression;
|
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
|
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;
|
private static TypeCache m_NullCache;
|
||||||
public static Assembly[] Assemblies { get; set; }
|
public static Assembly[] Assemblies { get; set; }
|
||||||
|
|
||||||
|
|
@ -85,10 +85,7 @@ namespace Server
|
||||||
List<Type> types = new List<Type>();
|
List<Type> types = new List<Type>();
|
||||||
if(ignoreCase)
|
if(ignoreCase)
|
||||||
name = name.ToLower();
|
name = name.ToLower();
|
||||||
for (int i = 0; i < Assemblies.Length; i++)
|
for (int i = 0; i < Assemblies.Length; i++) types.AddRange(GetTypeCache(Assemblies[i])[name]);
|
||||||
{
|
|
||||||
types.AddRange(GetTypeCache(Assemblies[i])[name]);
|
|
||||||
}
|
|
||||||
if (types.Count == 0)
|
if (types.Count == 0)
|
||||||
types.AddRange(GetTypeCache(Core.Assembly)[name]);
|
types.AddRange(GetTypeCache(Core.Assembly)[name]);
|
||||||
return types;
|
return types;
|
||||||
|
|
@ -107,15 +104,12 @@ namespace Server
|
||||||
|
|
||||||
public class TypeCache
|
public class TypeCache
|
||||||
{
|
{
|
||||||
private Dictionary<string, int[]> m_NameMap = new Dictionary<string, int[]>();
|
private readonly Dictionary<string, int[]> m_NameMap = new Dictionary<string, int[]>();
|
||||||
private Type[] m_Types;
|
private readonly Type[] m_Types;
|
||||||
public IEnumerable<Type> Types { get => m_Types; }
|
public IEnumerable<Type> Types => m_Types;
|
||||||
public IEnumerable<string> Names { get => m_NameMap.Keys; }
|
public IEnumerable<string> Names => m_NameMap.Keys;
|
||||||
|
|
||||||
public IEnumerable<Type> this[string name]
|
public IEnumerable<Type> this[string name] => m_NameMap.TryGetValue(name, out int[] value) ? value.Select(x => m_Types[x]) : new Type[0];
|
||||||
{
|
|
||||||
get => m_NameMap.TryGetValue(name, out int[] value) ? value.Select(x => m_Types[x]) : new Type[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
public TypeCache(Assembly asm)
|
public TypeCache(Assembly asm)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ namespace Server
|
||||||
|
|
||||||
public struct Body
|
public struct Body
|
||||||
{
|
{
|
||||||
private static BodyType[] m_Types;
|
private static readonly BodyType[] m_Types;
|
||||||
|
|
||||||
static Body()
|
static Body()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ namespace System.Buffers
|
||||||
|
|
||||||
private readonly IMemoryOwner<byte> _memoryOwner;
|
private readonly IMemoryOwner<byte> _memoryOwner;
|
||||||
private MemoryHandle? _memoryHandle;
|
private MemoryHandle? _memoryHandle;
|
||||||
private Memory<byte> _memory;
|
private readonly Memory<byte> _memory;
|
||||||
|
|
||||||
private readonly object _syncObj = new object();
|
private readonly object _syncObj = new object();
|
||||||
private bool _isDisposed;
|
private bool _isDisposed;
|
||||||
|
|
|
||||||
|
|
@ -5,15 +5,7 @@ namespace System.Buffers
|
||||||
{
|
{
|
||||||
public static class SlabMemoryPoolFactory
|
public static class SlabMemoryPoolFactory
|
||||||
{
|
{
|
||||||
public static MemoryPool<byte> Create()
|
public static MemoryPool<byte> Create() => CreateSlabMemoryPool();
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
return new DiagnosticMemoryPool(CreateSlabMemoryPool());
|
|
||||||
#else
|
|
||||||
return CreateSlabMemoryPool();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
public static MemoryPool<byte> CreateSlabMemoryPool() => new SlabMemoryPool();
|
public static MemoryPool<byte> CreateSlabMemoryPool() => new SlabMemoryPool();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ namespace Server.ContextMenus
|
||||||
{
|
{
|
||||||
public class OpenBackpackEntry : ContextMenuEntry
|
public class OpenBackpackEntry : ContextMenuEntry
|
||||||
{
|
{
|
||||||
private Mobile m_Mobile;
|
private readonly Mobile m_Mobile;
|
||||||
|
|
||||||
public OpenBackpackEntry(Mobile m) : base(6145) => m_Mobile = m;
|
public OpenBackpackEntry(Mobile m) : base(6145) => m_Mobile = m;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ namespace Server.ContextMenus
|
||||||
{
|
{
|
||||||
public class PaperdollEntry : ContextMenuEntry
|
public class PaperdollEntry : ContextMenuEntry
|
||||||
{
|
{
|
||||||
private Mobile m_Mobile;
|
private readonly Mobile m_Mobile;
|
||||||
|
|
||||||
public PaperdollEntry(Mobile m) : base(6123, 18) => m_Mobile = m;
|
public PaperdollEntry(Mobile m) : base(6123, 18) => m_Mobile = m;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ namespace Server.Diagnostics
|
||||||
{
|
{
|
||||||
public abstract class BaseProfile
|
public abstract class BaseProfile
|
||||||
{
|
{
|
||||||
private Stopwatch _stopwatch;
|
private readonly Stopwatch _stopwatch;
|
||||||
|
|
||||||
protected BaseProfile(string name)
|
protected BaseProfile(string name)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ namespace Server.Diagnostics
|
||||||
{
|
{
|
||||||
public class GumpProfile : BaseProfile
|
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)
|
public GumpProfile(Type type) : base(type.FullName)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ namespace Server.Diagnostics
|
||||||
|
|
||||||
public class PacketSendProfile : BasePacketProfile
|
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;
|
private long _created;
|
||||||
|
|
||||||
|
|
@ -87,7 +87,7 @@ namespace Server.Diagnostics
|
||||||
|
|
||||||
public class PacketReceiveProfile : BasePacketProfile
|
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)
|
public PacketReceiveProfile(int packetId)
|
||||||
: base($"0x{packetId:X2}")
|
: base($"0x{packetId:X2}")
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ namespace Server.Diagnostics
|
||||||
{
|
{
|
||||||
public class TargetProfile : BaseProfile
|
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)
|
public TargetProfile(Type type)
|
||||||
: base(type.FullName)
|
: base(type.FullName)
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ namespace Server.Diagnostics
|
||||||
{
|
{
|
||||||
public class TimerProfile : BaseProfile
|
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)
|
public TimerProfile(string name)
|
||||||
: base(name)
|
: base(name)
|
||||||
|
|
|
||||||
|
|
@ -196,7 +196,7 @@ namespace Server
|
||||||
|
|
||||||
public class AggressiveActionEventArgs : EventArgs
|
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)
|
private AggressiveActionEventArgs(Mobile aggressed, Mobile aggressor, bool criminal)
|
||||||
{
|
{
|
||||||
|
|
@ -512,7 +512,7 @@ namespace Server
|
||||||
|
|
||||||
public class MovementEventArgs : EventArgs
|
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)
|
public MovementEventArgs(Mobile mobile, Direction dir)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ namespace Server.Guilds
|
||||||
|
|
||||||
public abstract class BaseGuild : ISerializable
|
public abstract class BaseGuild : ISerializable
|
||||||
{
|
{
|
||||||
private BufferWriter m_SaveBuffer;
|
private readonly BufferWriter m_SaveBuffer;
|
||||||
public BufferWriter SaveBuffer => m_SaveBuffer;
|
public BufferWriter SaveBuffer => m_SaveBuffer;
|
||||||
|
|
||||||
private static uint m_NextID = 1;
|
private static uint m_NextID = 1;
|
||||||
|
|
|
||||||
|
|
@ -29,13 +29,13 @@ namespace Server.Gumps
|
||||||
{
|
{
|
||||||
private static uint m_NextSerial = 1;
|
private static uint m_NextSerial = 1;
|
||||||
|
|
||||||
private static byte[] m_BeginLayout = StringToBuffer("{ ");
|
private static readonly byte[] m_BeginLayout = StringToBuffer("{ ");
|
||||||
private static byte[] m_EndLayout = StringToBuffer(" }");
|
private static readonly byte[] m_EndLayout = StringToBuffer(" }");
|
||||||
|
|
||||||
private static byte[] m_NoMove = StringToBuffer("{ nomove }");
|
private static readonly byte[] m_NoMove = StringToBuffer("{ nomove }");
|
||||||
private static byte[] m_NoClose = StringToBuffer("{ noclose }");
|
private static readonly byte[] m_NoClose = StringToBuffer("{ noclose }");
|
||||||
private static byte[] m_NoDispose = StringToBuffer("{ nodispose }");
|
private static readonly byte[] m_NoDispose = StringToBuffer("{ nodispose }");
|
||||||
private static byte[] m_NoResize = StringToBuffer("{ noresize }");
|
private static readonly byte[] m_NoResize = StringToBuffer("{ noresize }");
|
||||||
private bool m_Closable = true;
|
private bool m_Closable = true;
|
||||||
private bool m_Disposable = true;
|
private bool m_Disposable = true;
|
||||||
|
|
||||||
|
|
@ -43,7 +43,7 @@ namespace Server.Gumps
|
||||||
private bool m_Resizable = true;
|
private bool m_Resizable = true;
|
||||||
|
|
||||||
private uint m_Serial;
|
private uint m_Serial;
|
||||||
private List<string> m_Strings;
|
private readonly List<string> m_Strings;
|
||||||
|
|
||||||
internal int m_TextEntries, m_Switches;
|
internal int m_TextEntries, m_Switches;
|
||||||
private int m_X, m_Y;
|
private int m_X, m_Y;
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ namespace Server.Gumps
|
||||||
{
|
{
|
||||||
public class GumpAlphaRegion : GumpEntry
|
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_Width, m_Height;
|
||||||
private int m_X, m_Y;
|
private int m_X, m_Y;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ namespace Server.Gumps
|
||||||
{
|
{
|
||||||
public class GumpBackground : GumpEntry
|
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_GumpID;
|
||||||
private int m_Width, m_Height;
|
private int m_Width, m_Height;
|
||||||
private int m_X, m_Y;
|
private int m_X, m_Y;
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ namespace Server.Gumps
|
||||||
|
|
||||||
public class GumpButton : GumpEntry
|
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_ButtonID;
|
||||||
private int m_ID1, m_ID2;
|
private int m_ID1, m_ID2;
|
||||||
private int m_Param;
|
private int m_Param;
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ namespace Server.Gumps
|
||||||
{
|
{
|
||||||
public class GumpCheck : GumpEntry
|
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 int m_ID1, m_ID2;
|
||||||
private bool m_InitialState;
|
private bool m_InitialState;
|
||||||
private int m_SwitchID;
|
private int m_SwitchID;
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ namespace Server.Gumps
|
||||||
{
|
{
|
||||||
public class GumpGroup : GumpEntry
|
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;
|
private int m_Group;
|
||||||
|
|
||||||
public GumpGroup(int group) => m_Group = group;
|
public GumpGroup(int group) => m_Group = group;
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ namespace Server.Gumps
|
||||||
{
|
{
|
||||||
public class GumpHtml : GumpEntry
|
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 bool m_Background, m_Scrollbar;
|
||||||
private string m_Text;
|
private string m_Text;
|
||||||
private int m_Width, m_Height;
|
private int m_Width, m_Height;
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,9 @@ namespace Server.Gumps
|
||||||
|
|
||||||
public class GumpHtmlLocalized : GumpEntry
|
public class GumpHtmlLocalized : GumpEntry
|
||||||
{
|
{
|
||||||
private static byte[] m_LayoutNamePlain = Gump.StringToBuffer("xmfhtmlgump");
|
private static readonly byte[] m_LayoutNamePlain = Gump.StringToBuffer("xmfhtmlgump");
|
||||||
private static byte[] m_LayoutNameColor = Gump.StringToBuffer("xmfhtmlgumpcolor");
|
private static readonly byte[] m_LayoutNameColor = Gump.StringToBuffer("xmfhtmlgumpcolor");
|
||||||
private static byte[] m_LayoutNameArgs = Gump.StringToBuffer("xmfhtmltok");
|
private static readonly byte[] m_LayoutNameArgs = Gump.StringToBuffer("xmfhtmltok");
|
||||||
private string m_Args;
|
private string m_Args;
|
||||||
private bool m_Background, m_Scrollbar;
|
private bool m_Background, m_Scrollbar;
|
||||||
private int m_Color;
|
private int m_Color;
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,8 @@ namespace Server.Gumps
|
||||||
{
|
{
|
||||||
public class GumpImage : GumpEntry
|
public class GumpImage : GumpEntry
|
||||||
{
|
{
|
||||||
private static byte[] m_LayoutName = Gump.StringToBuffer("gumppic");
|
private static readonly byte[] m_LayoutName = Gump.StringToBuffer("gumppic");
|
||||||
private static byte[] m_HueEquals = Gump.StringToBuffer(" hue=");
|
private static readonly byte[] m_HueEquals = Gump.StringToBuffer(" hue=");
|
||||||
private int m_GumpID;
|
private int m_GumpID;
|
||||||
private int m_Hue;
|
private int m_Hue;
|
||||||
private int m_X, m_Y;
|
private int m_X, m_Y;
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,8 @@ namespace Server.Gumps
|
||||||
{
|
{
|
||||||
public class GumpImageTileButton : GumpEntry
|
public class GumpImageTileButton : GumpEntry
|
||||||
{
|
{
|
||||||
private static byte[] m_LayoutName = Gump.StringToBuffer("buttontileart");
|
private static readonly byte[] m_LayoutName = Gump.StringToBuffer("buttontileart");
|
||||||
private static byte[] m_LayoutTooltip = Gump.StringToBuffer(" }{ tooltip");
|
private static readonly byte[] m_LayoutTooltip = Gump.StringToBuffer(" }{ tooltip");
|
||||||
private int m_ButtonID;
|
private int m_ButtonID;
|
||||||
private int m_Height;
|
private int m_Height;
|
||||||
private int m_Hue;
|
private int m_Hue;
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ namespace Server.Gumps
|
||||||
{
|
{
|
||||||
public class GumpImageTiled : GumpEntry
|
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_GumpID;
|
||||||
private int m_Width, m_Height;
|
private int m_Width, m_Height;
|
||||||
private int m_X, m_Y;
|
private int m_X, m_Y;
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,8 @@ namespace Server.Gumps
|
||||||
{
|
{
|
||||||
public class GumpItem : GumpEntry
|
public class GumpItem : GumpEntry
|
||||||
{
|
{
|
||||||
private static byte[] m_LayoutName = Gump.StringToBuffer("tilepic");
|
private static readonly byte[] m_LayoutName = Gump.StringToBuffer("tilepic");
|
||||||
private static byte[] m_LayoutNameHue = Gump.StringToBuffer("tilepichue");
|
private static readonly byte[] m_LayoutNameHue = Gump.StringToBuffer("tilepichue");
|
||||||
private int m_Hue;
|
private int m_Hue;
|
||||||
private int m_ItemID;
|
private int m_ItemID;
|
||||||
private int m_X, m_Y;
|
private int m_X, m_Y;
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ namespace Server.Gumps
|
||||||
{
|
{
|
||||||
public class GumpItemProperty : GumpEntry
|
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;
|
private uint m_Serial;
|
||||||
|
|
||||||
public GumpItemProperty(uint serial) => m_Serial = serial;
|
public GumpItemProperty(uint serial) => m_Serial = serial;
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ namespace Server.Gumps
|
||||||
{
|
{
|
||||||
public class GumpLabel : GumpEntry
|
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 int m_Hue;
|
||||||
private string m_Text;
|
private string m_Text;
|
||||||
private int m_X, m_Y;
|
private int m_X, m_Y;
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ namespace Server.Gumps
|
||||||
{
|
{
|
||||||
public class GumpLabelCropped : GumpEntry
|
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 int m_Hue;
|
||||||
private string m_Text;
|
private string m_Text;
|
||||||
private int m_Width, m_Height;
|
private int m_Width, m_Height;
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ namespace Server.Gumps
|
||||||
{
|
{
|
||||||
public class GumpPage : GumpEntry
|
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;
|
private int m_Page;
|
||||||
|
|
||||||
public GumpPage(int page) => m_Page = page;
|
public GumpPage(int page) => m_Page = page;
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ namespace Server.Gumps
|
||||||
{
|
{
|
||||||
public class GumpRadio : GumpEntry
|
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 int m_ID1, m_ID2;
|
||||||
private bool m_InitialState;
|
private bool m_InitialState;
|
||||||
private int m_SwitchID;
|
private int m_SwitchID;
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ namespace Server.Gumps
|
||||||
{
|
{
|
||||||
public class GumpTextEntry : GumpEntry
|
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_EntryID;
|
||||||
private int m_Hue;
|
private int m_Hue;
|
||||||
private string m_InitialText;
|
private string m_InitialText;
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ namespace Server.Gumps
|
||||||
{
|
{
|
||||||
public class GumpTextEntryLimited : GumpEntry
|
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_EntryID;
|
||||||
private int m_Hue;
|
private int m_Hue;
|
||||||
private string m_InitialText;
|
private string m_InitialText;
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ namespace Server.Gumps
|
||||||
{
|
{
|
||||||
public class GumpTooltip : GumpEntry
|
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;
|
private int m_Number;
|
||||||
|
|
||||||
public GumpTooltip(int number) => m_Number = number;
|
public GumpTooltip(int number) => m_Number = number;
|
||||||
|
|
|
||||||
|
|
@ -201,13 +201,13 @@ namespace Server
|
||||||
|
|
||||||
public class Item : IHued, IComparable<Item>, ISerializable, ISpawnable, IPropertyListObject
|
public class Item : IHued, IComparable<Item>, ISerializable, ISpawnable, IPropertyListObject
|
||||||
{
|
{
|
||||||
private BufferWriter m_SaveBuffer;
|
private readonly BufferWriter m_SaveBuffer;
|
||||||
public BufferWriter SaveBuffer { get { return m_SaveBuffer; } }
|
public BufferWriter SaveBuffer => m_SaveBuffer;
|
||||||
|
|
||||||
public const int QuestItemHue = 0x4EA; // Hmmmm... "for EA"?
|
public const int QuestItemHue = 0x4EA; // Hmmmm... "for EA"?
|
||||||
public static readonly List<Item> EmptyItems = new List<Item>();
|
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;
|
private static bool _processing;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,8 +36,8 @@ namespace Server.Items
|
||||||
|
|
||||||
public class Container : Item
|
public class Container : Item
|
||||||
{
|
{
|
||||||
private static QueuePool m_QueuePool = new QueuePool(QueueRef<Container>.Generate, preGenerateCount: 2, maxRefrenceRetention: 5);
|
private static readonly QueuePool m_QueuePool = new QueuePool(QueueRef<Container>.Generate, preGenerateCount: 2, maxRefrenceRetention: 5);
|
||||||
private static List<Item> m_FindItemsList = new List<Item>();
|
private static readonly List<Item> m_FindItemsList = new List<Item>();
|
||||||
|
|
||||||
private ContainerData m_ContainerData;
|
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)
|
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)
|
if (IsDecoContainer)
|
||||||
{
|
{
|
||||||
|
|
@ -735,7 +735,7 @@ namespace Server.Items
|
||||||
|
|
||||||
private class GroupComparer : IComparer<Item>
|
private class GroupComparer : IComparer<Item>
|
||||||
{
|
{
|
||||||
private CheckItemGroup m_Grouper;
|
private readonly CheckItemGroup m_Grouper;
|
||||||
|
|
||||||
public GroupComparer(CheckItemGroup grouper) => m_Grouper = grouper;
|
public GroupComparer(CheckItemGroup grouper) => m_Grouper = grouper;
|
||||||
|
|
||||||
|
|
@ -754,8 +754,8 @@ namespace Server.Items
|
||||||
|
|
||||||
private struct ItemStackEntry
|
private struct ItemStackEntry
|
||||||
{
|
{
|
||||||
public Item m_StackItem;
|
public readonly Item m_StackItem;
|
||||||
public Item m_DropItem;
|
public readonly Item m_DropItem;
|
||||||
|
|
||||||
public ItemStackEntry(Item stack, Item drop)
|
public ItemStackEntry(Item stack, Item drop)
|
||||||
{
|
{
|
||||||
|
|
@ -1536,12 +1536,10 @@ namespace Server.Items
|
||||||
{
|
{
|
||||||
var container = queue.Dequeue();
|
var container = queue.Dequeue();
|
||||||
foreach (var item in container.Items)
|
foreach (var item in container.Items)
|
||||||
{
|
|
||||||
if (item is T typedItem && predicate?.Invoke(typedItem) != false)
|
if (item is T typedItem && predicate?.Invoke(typedItem) != false)
|
||||||
items.Add(typedItem);
|
items.Add(typedItem);
|
||||||
else if (recurse && item is Container itemContainer)
|
else if (recurse && item is Container itemContainer)
|
||||||
queue.Enqueue(itemContainer);
|
queue.Enqueue(itemContainer);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
@ -1583,7 +1581,7 @@ namespace Server.Items
|
||||||
|
|
||||||
public class ContainerData
|
public class ContainerData
|
||||||
{
|
{
|
||||||
private static Dictionary<int, ContainerData> m_Table;
|
private static readonly Dictionary<int, ContainerData> m_Table;
|
||||||
|
|
||||||
static ContainerData()
|
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;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Libuv
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||||
{
|
{
|
||||||
interface IAsyncDisposable
|
interface IAsyncDisposable
|
||||||
{
|
{
|
||||||
|
|
@ -4,9 +4,9 @@
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.Extensions.Logging;
|
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);
|
void ConnectionRead(string connectionId, int count);
|
||||||
|
|
||||||
|
|
@ -5,11 +5,11 @@ using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Threading;
|
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 = () => { };
|
private static readonly Action _callbackCompleted = () => { };
|
||||||
|
|
||||||
|
|
@ -53,8 +53,7 @@ namespace Libuv
|
||||||
{
|
{
|
||||||
// There should never be a race between IsCompleted and OnCompleted since both operations
|
// There should never be a race between IsCompleted and OnCompleted since both operations
|
||||||
// should always be on the libuv thread
|
// should always be on the libuv thread
|
||||||
if (ReferenceEquals(_callback, _callbackCompleted))
|
if (ReferenceEquals(_callback, _callbackCompleted)) Debug.Fail($"{typeof(LibuvAwaitable<TRequest>)}.{nameof(OnCompleted)} raced with {nameof(IsCompleted)}, scheduling callback.");
|
||||||
Debug.Fail($"{typeof(LibuvAwaitable<TRequest>)}.{nameof(OnCompleted)} raced with {nameof(IsCompleted)}, scheduling callback.");
|
|
||||||
|
|
||||||
_callback = continuation;
|
_callback = continuation;
|
||||||
}
|
}
|
||||||
|
|
@ -65,7 +64,7 @@ namespace Libuv
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct UvWriteResult
|
internal struct UvWriteResult
|
||||||
{
|
{
|
||||||
public int Status { get; }
|
public int Status { get; }
|
||||||
public UvException Error { get; }
|
public UvException Error { get; }
|
||||||
|
|
@ -8,19 +8,21 @@ using System.IO.Pipelines;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Libuv.Internal;
|
|
||||||
using Microsoft.AspNetCore.Connections;
|
using Microsoft.AspNetCore.Connections;
|
||||||
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
||||||
using Microsoft.Extensions.Logging;
|
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 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 UvStreamHandle _socket;
|
||||||
private readonly CancellationTokenSource _connectionClosedTokenSource = new CancellationTokenSource();
|
private readonly CancellationTokenSource _connectionClosedTokenSource = new CancellationTokenSource();
|
||||||
|
|
@ -243,7 +245,7 @@ namespace Libuv
|
||||||
state._waitForConnectionClosedTcs.TrySetResult(null);
|
state._waitForConnectionClosedTcs.TrySetResult(null);
|
||||||
},
|
},
|
||||||
this,
|
this,
|
||||||
false);
|
preferLocal: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ApplyBackpressureAsync(ValueTask<FlushResult> flushTask)
|
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.
|
// The operation was canceled by the server not the client. No need for additional logs.
|
||||||
return new ConnectionAbortedException(uvError.Message, uvError);
|
return new ConnectionAbortedException(uvError.Message, uvError);
|
||||||
}
|
}
|
||||||
|
else if (LibuvConstants.IsConnectionReset(uvError.StatusCode))
|
||||||
if (LibuvConstants.IsConnectionReset(uvError.StatusCode))
|
|
||||||
{
|
{
|
||||||
// Log connection resets at a lower (Debug) level.
|
// Log connection resets at a lower (Debug) level.
|
||||||
Log.ConnectionReset(ConnectionId);
|
Log.ConnectionReset(ConnectionId);
|
||||||
return new ConnectionResetException(uvError.Message, uvError);
|
return new ConnectionResetException(uvError.Message, uvError);
|
||||||
}
|
}
|
||||||
// This is unexpected.
|
else
|
||||||
Log.ConnectionError(ConnectionId, uvError);
|
{
|
||||||
return new IOException(uvError.Message, uvError);
|
// This is unexpected.
|
||||||
|
Log.ConnectionError(ConnectionId, uvError);
|
||||||
|
return new IOException(uvError.Message, uvError);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CancelConnectionClosedToken()
|
private void CancelConnectionClosedToken()
|
||||||
|
|
@ -7,15 +7,14 @@ using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Libuv.Internal;
|
|
||||||
using Microsoft.AspNetCore.Connections;
|
using Microsoft.AspNetCore.Connections;
|
||||||
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
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 readonly List<ListenerContext> _listeners = new List<ListenerContext>();
|
||||||
private IAsyncEnumerator<LibuvConnection> _acceptEnumerator;
|
private IAsyncEnumerator<LibuvConnection> _acceptEnumerator;
|
||||||
|
|
@ -63,8 +62,7 @@ namespace Libuv
|
||||||
|
|
||||||
var disposeTasks = _listeners.Select(listener => ((IAsyncDisposable)listener).DisposeAsync()).ToArray();
|
var disposeTasks = _listeners.Select(listener => ((IAsyncDisposable)listener).DisposeAsync()).ToArray();
|
||||||
|
|
||||||
if (!await WaitAsync(Task.WhenAll(disposeTasks), TimeSpan.FromSeconds(5)).ConfigureAwait(false))
|
if (!await WaitAsync(Task.WhenAll(disposeTasks), TimeSpan.FromSeconds(5)).ConfigureAwait(false)) Log.LogError(0, null, "Disposing listeners failed");
|
||||||
Log.LogError(0, null, "Disposing listeners failed");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -101,14 +99,9 @@ namespace Libuv
|
||||||
}
|
}
|
||||||
|
|
||||||
Threads.Clear();
|
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: Move thread management to LibuvTransportFactory
|
||||||
// TODO: Split endpoint management from thread management
|
// TODO: Split endpoint management from thread management
|
||||||
|
|
@ -127,7 +120,7 @@ namespace Libuv
|
||||||
}
|
}
|
||||||
else
|
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 pipeMessage = Guid.NewGuid().ToByteArray();
|
||||||
|
|
||||||
var listenerPrimary = new ListenerPrimary(TransportContext);
|
var listenerPrimary = new ListenerPrimary(TransportContext);
|
||||||
|
|
@ -171,7 +164,7 @@ namespace Libuv
|
||||||
while (remainingSlots > 0)
|
while (remainingSlots > 0)
|
||||||
{
|
{
|
||||||
// Calling GetAwaiter().GetResult() is safe because we know the task is completed
|
// 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 the connection is null then the listener was closed
|
||||||
if (connection == null)
|
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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System.Runtime.CompilerServices;
|
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 const int EOF = -4095;
|
||||||
public static readonly int? ECONNRESET = GetECONNRESET();
|
public static readonly int? ECONNRESET = GetECONNRESET();
|
||||||
|
|
@ -22,76 +22,69 @@ namespace Libuv
|
||||||
|
|
||||||
private static int? GetECONNRESET()
|
private static int? GetECONNRESET()
|
||||||
{
|
{
|
||||||
if (Core.IsWindows)
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
return -4077;
|
return -4077;
|
||||||
if (Core.IsLinux)
|
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||||
return -104;
|
return -104;
|
||||||
if (Core.IsDarwin)
|
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) return -54;
|
||||||
return -5;
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int? GetEPIPE()
|
private static int? GetEPIPE()
|
||||||
{
|
{
|
||||||
if (Core.IsWindows)
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
return -4047;
|
return -4047;
|
||||||
if (Core.IsLinux)
|
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||||
return -32;
|
|
||||||
if (Core.IsDarwin)
|
|
||||||
return -32;
|
return -32;
|
||||||
|
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) return -32;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int? GetENOTCONN()
|
private static int? GetENOTCONN()
|
||||||
{
|
{
|
||||||
if (Core.IsWindows)
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
return -4053;
|
return -4053;
|
||||||
if (Core.IsLinux)
|
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||||
return -107;
|
return -107;
|
||||||
if (Core.IsDarwin)
|
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) return -57;
|
||||||
return -57;
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int? GetEINVAL()
|
private static int? GetEINVAL()
|
||||||
{
|
{
|
||||||
if (Core.IsWindows)
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
return -4071;
|
return -4071;
|
||||||
if (Core.IsLinux)
|
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||||
return -22;
|
|
||||||
if (Core.IsDarwin)
|
|
||||||
return -22;
|
return -22;
|
||||||
|
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) return -22;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int? GetEADDRINUSE()
|
private static int? GetEADDRINUSE()
|
||||||
{
|
{
|
||||||
if (Core.IsWindows)
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
return -4091;
|
return -4091;
|
||||||
if (Core.IsLinux)
|
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||||
return -98;
|
return -98;
|
||||||
if (Core.IsDarwin)
|
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) return -48;
|
||||||
return -48;
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int? GetENOTSUP()
|
private static int? GetENOTSUP()
|
||||||
{
|
{
|
||||||
if (Core.IsLinux)
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||||
return -95;
|
return -95;
|
||||||
if (Core.IsDarwin)
|
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) return -45;
|
||||||
return -45;
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int? GetECANCELED()
|
private static int? GetECANCELED()
|
||||||
{
|
{
|
||||||
if (Core.IsWindows)
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
return -4081;
|
return -4081;
|
||||||
if (Core.IsLinux)
|
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||||
return -125;
|
return -125;
|
||||||
if (Core.IsDarwin)
|
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) return -89;
|
||||||
return -89;
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4,11 +4,11 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO.Pipelines;
|
using System.IO.Pipelines;
|
||||||
using System.Threading.Tasks;
|
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 LibuvThread _thread;
|
||||||
private readonly UvStreamHandle _socket;
|
private readonly UvStreamHandle _socket;
|
||||||
|
|
@ -9,13 +9,13 @@ using System.IO.Pipelines;
|
||||||
using System.Runtime.ExceptionServices;
|
using System.Runtime.ExceptionServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Libuv.Internal;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
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
|
// 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
|
// 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 _workSync = new object();
|
||||||
private readonly object _closeHandleSync = new object();
|
private readonly object _closeHandleSync = new object();
|
||||||
private readonly object _startSync = new object();
|
private readonly object _startSync = new object();
|
||||||
private bool _stopImmediate;
|
private bool _stopImmediate = false;
|
||||||
private bool _initCompleted;
|
private bool _initCompleted = false;
|
||||||
private Exception _closeError;
|
private Exception _closeError;
|
||||||
private readonly ILibuvTrace _log;
|
private readonly ILibuvTrace _log;
|
||||||
|
|
||||||
|
|
@ -60,9 +60,9 @@ namespace Libuv
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
// Mark the thread as being as unimportant to keeping the process alive.
|
// 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.
|
// Don't do this for debug builds, so we know if the thread isn't terminating.
|
||||||
_thread.IsBackground = true;
|
_thread.IsBackground = true;
|
||||||
#endif
|
#endif
|
||||||
QueueCloseHandle = PostCloseHandle;
|
QueueCloseHandle = PostCloseHandle;
|
||||||
QueueCloseAsyncHandle = EnqueueCloseHandle;
|
QueueCloseAsyncHandle = EnqueueCloseHandle;
|
||||||
|
|
@ -76,10 +76,6 @@ namespace Libuv
|
||||||
|
|
||||||
public WriteReqPool WriteReqPool { get; }
|
public WriteReqPool WriteReqPool { get; }
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
public List<WeakReference> Requests { get; } = new List<WeakReference>();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public Exception FatalError => _closeError;
|
public Exception FatalError => _closeError;
|
||||||
|
|
||||||
public Action<Action<IntPtr>, IntPtr> QueueCloseHandle { get; }
|
public Action<Action<IntPtr>, IntPtr> QueueCloseHandle { get; }
|
||||||
|
|
@ -129,18 +125,6 @@ namespace Libuv
|
||||||
if (_closeError != null) ExceptionDispatchInfo.Capture(_closeError).Throw();
|
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()
|
private void AllowStop()
|
||||||
{
|
{
|
||||||
_post.Unreference();
|
_post.Unreference();
|
||||||
|
|
@ -320,11 +304,6 @@ namespace Libuv
|
||||||
}
|
}
|
||||||
WriteReqPool.Dispose();
|
WriteReqPool.Dispose();
|
||||||
_threadTcs.SetResult(null);
|
_threadTcs.SetResult(null);
|
||||||
|
|
||||||
#if DEBUG && !INNER_LOOP
|
|
||||||
// Check for handle leaks after disposing everything
|
|
||||||
CheckUvReqLeaks();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -406,8 +385,7 @@ namespace Libuv
|
||||||
return wasWork;
|
return wasWork;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<bool> WaitAsync(Task task, TimeSpan timeout) =>
|
private static async Task<bool> WaitAsync(Task task, TimeSpan timeout) => await Task.WhenAny(task, Task.Delay(timeout)).ConfigureAwait(false) == task;
|
||||||
await Task.WhenAny(task, Task.Delay(timeout)).ConfigureAwait(false) == task;
|
|
||||||
|
|
||||||
public override void Schedule(Action<object> action, object state)
|
public override void Schedule(Action<object> action, object state)
|
||||||
{
|
{
|
||||||
|
|
@ -4,9 +4,9 @@
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.Extensions.Logging;
|
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
|
// ConnectionRead: Reserved: 3
|
||||||
|
|
||||||
|
|
@ -3,9 +3,9 @@
|
||||||
|
|
||||||
using Microsoft.Extensions.Hosting;
|
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; }
|
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;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Libuv.Internal;
|
|
||||||
using Microsoft.AspNetCore.Connections;
|
using Microsoft.AspNetCore.Connections;
|
||||||
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Libuv
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Base class for listeners in Kestrel. Listens for incoming connections
|
/// Base class for listeners in Kestrel. Listens for incoming connections
|
||||||
/// </summary>
|
/// </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
|
// REVIEW: This needs to be bounded and we need a strategy for what to do when the queue is full
|
||||||
private bool _closed;
|
private bool _closed;
|
||||||
|
|
@ -46,13 +46,17 @@ namespace Libuv
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private UvStreamHandle CreateListenSocket()
|
private UvStreamHandle CreateListenSocket()
|
||||||
{
|
{
|
||||||
return EndPoint switch
|
switch (EndPoint)
|
||||||
{
|
{
|
||||||
IPEndPoint _ => ListenTcp(false),
|
case IPEndPoint _:
|
||||||
UnixDomainSocketEndPoint _ => ListenPipe(false),
|
return ListenTcp(useFileHandle: false);
|
||||||
FileHandleEndPoint _ => ListenHandle(),
|
case UnixDomainSocketEndPoint _:
|
||||||
_ => throw new NotSupportedException()
|
return ListenPipe(useFileHandle: false);
|
||||||
};
|
case FileHandleEndPoint _:
|
||||||
|
return ListenHandle();
|
||||||
|
default:
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private UvTcpHandle ListenTcp(bool useFileHandle)
|
private UvTcpHandle ListenTcp(bool useFileHandle)
|
||||||
|
|
@ -62,7 +66,7 @@ namespace Libuv
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
socket.Init(Thread.Loop, Thread.QueueCloseHandle);
|
socket.Init(Thread.Loop, Thread.QueueCloseHandle);
|
||||||
socket.NoDelay(true);
|
socket.NoDelay(TransportContext.Options.NoDelay);
|
||||||
|
|
||||||
if (!useFileHandle)
|
if (!useFileHandle)
|
||||||
{
|
{
|
||||||
|
|
@ -117,9 +121,9 @@ namespace Libuv
|
||||||
case FileHandleType.Auto:
|
case FileHandleType.Auto:
|
||||||
break;
|
break;
|
||||||
case FileHandleType.Tcp:
|
case FileHandleType.Tcp:
|
||||||
return ListenTcp(true);
|
return ListenTcp(useFileHandle: true);
|
||||||
case FileHandleType.Pipe:
|
case FileHandleType.Pipe:
|
||||||
return ListenPipe(true);
|
return ListenPipe(useFileHandle: true);
|
||||||
default:
|
default:
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
}
|
}
|
||||||
|
|
@ -127,7 +131,7 @@ namespace Libuv
|
||||||
UvStreamHandle handle;
|
UvStreamHandle handle;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
handle = ListenTcp(true);
|
handle = ListenTcp(useFileHandle: true);
|
||||||
EndPoint = new FileHandleEndPoint(handleEndPoint.FileHandle, FileHandleType.Tcp);
|
EndPoint = new FileHandleEndPoint(handleEndPoint.FileHandle, FileHandleType.Tcp);
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
@ -136,7 +140,7 @@ namespace Libuv
|
||||||
Log.LogDebug(0, exception, "Listener.ListenHandle");
|
Log.LogDebug(0, exception, "Listener.ListenHandle");
|
||||||
}
|
}
|
||||||
|
|
||||||
handle = ListenPipe(true);
|
handle = ListenPipe(useFileHandle: true);
|
||||||
EndPoint = new FileHandleEndPoint(handleEndPoint.FileHandle, FileHandleType.Pipe);
|
EndPoint = new FileHandleEndPoint(handleEndPoint.FileHandle, FileHandleType.Pipe);
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
@ -9,13 +9,13 @@ using System.Net.Sockets;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Channels;
|
using System.Threading.Channels;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Libuv.Internal;
|
|
||||||
using Microsoft.AspNetCore.Connections;
|
using Microsoft.AspNetCore.Connections;
|
||||||
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
||||||
using Microsoft.Extensions.Logging;
|
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
|
// 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
|
private readonly Channel<LibuvConnection> _acceptQueue = Channel.CreateUnbounded<LibuvConnection>(new UnboundedChannelOptions
|
||||||
|
|
@ -115,7 +115,7 @@ namespace Libuv
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
socket.Init(Thread.Loop, Thread.QueueCloseHandle);
|
socket.Init(Thread.Loop, Thread.QueueCloseHandle);
|
||||||
socket.NoDelay(true);
|
socket.NoDelay(TransportContext.Options.NoDelay);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
|
@ -152,17 +152,14 @@ namespace Libuv
|
||||||
{
|
{
|
||||||
var fileHandleEndPoint = (FileHandleEndPoint)EndPoint;
|
var fileHandleEndPoint = (FileHandleEndPoint)EndPoint;
|
||||||
|
|
||||||
switch (fileHandleEndPoint.FileHandleType)
|
return fileHandleEndPoint.FileHandleType switch
|
||||||
{
|
{
|
||||||
case FileHandleType.Auto:
|
FileHandleType.Auto => throw new InvalidOperationException(
|
||||||
throw new InvalidOperationException("Cannot accept on a non-specific file handle, listen should be performed first.");
|
"Cannot accept on a non-specific file handle, listen should be performed first."),
|
||||||
case FileHandleType.Tcp:
|
FileHandleType.Tcp => (UvStreamHandle)AcceptTcp(),
|
||||||
return AcceptTcp();
|
FileHandleType.Pipe => AcceptPipe(),
|
||||||
case FileHandleType.Pipe:
|
_ => throw new NotSupportedException()
|
||||||
return AcceptPipe();
|
};
|
||||||
default:
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -7,19 +7,16 @@ using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Libuv.Internal;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Server;
|
|
||||||
|
|
||||||
#pragma warning disable 169
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||||
|
|
||||||
namespace Libuv
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A primary listener waits for incoming connections on a specified socket. Incoming
|
/// A primary listener waits for incoming connections on a specified socket. Incoming
|
||||||
/// connections may be passed to a secondary listener to handle.
|
/// connections may be passed to a secondary listener to handle.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ListenerPrimary : Listener
|
internal class ListenerPrimary : Listener
|
||||||
{
|
{
|
||||||
// The list of pipes that can be dispatched to (where we've confirmed the _pipeMessage)
|
// The list of pipes that can be dispatched to (where we've confirmed the _pipeMessage)
|
||||||
private readonly List<UvPipeHandle> _dispatchPipes = new List<UvPipeHandle>();
|
private readonly List<UvPipeHandle> _dispatchPipes = new List<UvPipeHandle>();
|
||||||
|
|
@ -29,7 +26,7 @@ namespace Libuv
|
||||||
private string _pipeName;
|
private string _pipeName;
|
||||||
private byte[] _pipeMessage;
|
private byte[] _pipeMessage;
|
||||||
private IntPtr _fileCompletionInfoPtr;
|
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,
|
// this message is passed to write2 because it must be non-zero-length,
|
||||||
// but it has no other functional significance
|
// but it has no other functional significance
|
||||||
|
|
@ -151,15 +148,17 @@ namespace Libuv
|
||||||
Thread.Loop.Libuv.uv_fileno(handle, ref socket);
|
Thread.Loop.Libuv.uv_fileno(handle, ref socket);
|
||||||
|
|
||||||
if (NtSetInformationFile(socket, out statusBlock, _fileCompletionInfoPtr,
|
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
|
// Replacing IOCP information is only supported on Windows 8.1 or newer
|
||||||
_tryDetachFromIOCP = false;
|
_tryDetachFromIOCP = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct IO_STATUS_BLOCK
|
private struct IO_STATUS_BLOCK
|
||||||
{
|
{
|
||||||
|
#pragma warning disable 169
|
||||||
uint status;
|
uint status;
|
||||||
ulong information;
|
ulong information;
|
||||||
|
#pragma warning restore 169
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct FILE_COMPLETION_INFORMATION
|
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
|
// 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.
|
// 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();
|
dispatchPipe.Dispose();
|
||||||
_bufHandle.Free();
|
_bufHandle.Free();
|
||||||
|
|
@ -6,16 +6,16 @@ using System.Net;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Libuv.Internal;
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Libuv
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A secondary listener is delegated requests from a primary listener via a named pipe or
|
/// A secondary listener is delegated requests from a primary listener via a named pipe or
|
||||||
/// UNIX domain socket.
|
/// UNIX domain socket.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ListenerSecondary : ListenerContext, IAsyncDisposable
|
internal class ListenerSecondary : ListenerContext, IAsyncDisposable
|
||||||
{
|
{
|
||||||
private string _pipeName;
|
private string _pipeName;
|
||||||
private byte[] _pipeMessage;
|
private byte[] _pipeMessage;
|
||||||
|
|
@ -4,14 +4,15 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
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()
|
public LibuvFunctions()
|
||||||
{
|
{
|
||||||
|
IsWindows = PlatformApis.IsWindows;
|
||||||
|
|
||||||
_uv_loop_init = NativeMethods.uv_loop_init;
|
_uv_loop_init = NativeMethods.uv_loop_init;
|
||||||
_uv_loop_close = NativeMethods.uv_loop_close;
|
_uv_loop_close = NativeMethods.uv_loop_close;
|
||||||
_uv_run = NativeMethods.uv_run;
|
_uv_run = NativeMethods.uv_run;
|
||||||
|
|
@ -63,6 +64,8 @@ namespace Libuv.Internal
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public readonly bool IsWindows;
|
||||||
|
|
||||||
public void ThrowIfErrored(int statusCode)
|
public void ThrowIfErrored(int statusCode)
|
||||||
{
|
{
|
||||||
// Note: method is explicitly small so the success case is easily inlined
|
// 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;
|
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)]
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
private UvException GetError(int statusCode) =>
|
private UvException GetError(int statusCode)
|
||||||
new UvException($"Error {statusCode} {err_name(statusCode)} {strerror(statusCode)}", 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)
|
public void loop_init(UvLoopHandle handle)
|
||||||
{
|
{
|
||||||
ThrowIfErrored(_uv_loop_init(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)
|
public void loop_close(UvLoopHandle handle)
|
||||||
{
|
{
|
||||||
handle.Validate(true);
|
handle.Validate(closed: true);
|
||||||
ThrowIfErrored(_uv_loop_close(handle.InternalGetHandle()));
|
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)
|
public void run(UvLoopHandle handle, int mode)
|
||||||
{
|
{
|
||||||
handle.Validate();
|
handle.Validate();
|
||||||
ThrowIfErrored(_uv_run(handle, mode));
|
ThrowIfErrored(_uv_run(handle, mode));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Action<UvLoopHandle> _uv_stop;
|
protected Action<UvLoopHandle> _uv_stop;
|
||||||
public void stop(UvLoopHandle handle)
|
public void stop(UvLoopHandle handle)
|
||||||
{
|
{
|
||||||
handle.Validate();
|
handle.Validate();
|
||||||
_uv_stop(handle);
|
_uv_stop(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Action<UvHandle> _uv_ref;
|
protected Action<UvHandle> _uv_ref;
|
||||||
public void @ref(UvHandle handle)
|
public void @ref(UvHandle handle)
|
||||||
{
|
{
|
||||||
handle.Validate();
|
handle.Validate();
|
||||||
_uv_ref(handle);
|
_uv_ref(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Action<UvHandle> _uv_unref;
|
protected Action<UvHandle> _uv_unref;
|
||||||
public void unref(UvHandle handle)
|
public void unref(UvHandle handle)
|
||||||
{
|
{
|
||||||
handle.Validate();
|
handle.Validate();
|
||||||
|
|
@ -131,8 +138,8 @@ namespace Libuv.Internal
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
public delegate int uv_fileno_func(UvHandle handle, ref IntPtr socket);
|
protected delegate int uv_fileno_func(UvHandle handle, ref IntPtr socket);
|
||||||
public uv_fileno_func _uv_fileno;
|
protected uv_fileno_func _uv_fileno;
|
||||||
public void uv_fileno(UvHandle handle, ref IntPtr socket)
|
public void uv_fileno(UvHandle handle, ref IntPtr socket)
|
||||||
{
|
{
|
||||||
handle.Validate();
|
handle.Validate();
|
||||||
|
|
@ -141,10 +148,10 @@ namespace Libuv.Internal
|
||||||
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
public delegate void uv_close_cb(IntPtr handle);
|
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)
|
public void close(UvHandle handle, uv_close_cb close_cb)
|
||||||
{
|
{
|
||||||
handle.Validate(true);
|
handle.Validate(closed: true);
|
||||||
_uv_close(handle.InternalGetHandle(), close_cb);
|
_uv_close(handle.InternalGetHandle(), close_cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -155,7 +162,7 @@ namespace Libuv.Internal
|
||||||
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
public delegate void uv_async_cb(IntPtr handle);
|
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)
|
public void async_init(UvLoopHandle loop, UvAsyncHandle handle, uv_async_cb cb)
|
||||||
{
|
{
|
||||||
loop.Validate();
|
loop.Validate();
|
||||||
|
|
@ -163,19 +170,19 @@ namespace Libuv.Internal
|
||||||
ThrowIfErrored(_uv_async_init(loop, handle, cb));
|
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)
|
public void async_send(UvAsyncHandle handle)
|
||||||
{
|
{
|
||||||
ThrowIfErrored(_uv_async_send(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)
|
public void unsafe_async_send(IntPtr handle)
|
||||||
{
|
{
|
||||||
ThrowIfErrored(_uv_unsafe_async_send(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)
|
public void tcp_init(UvLoopHandle loop, UvTcpHandle handle)
|
||||||
{
|
{
|
||||||
loop.Validate();
|
loop.Validate();
|
||||||
|
|
@ -183,29 +190,29 @@ namespace Libuv.Internal
|
||||||
ThrowIfErrored(_uv_tcp_init(loop, handle));
|
ThrowIfErrored(_uv_tcp_init(loop, handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
public delegate int uv_tcp_bind_func(UvTcpHandle handle, ref SockAddr addr, int flags);
|
protected delegate int uv_tcp_bind_func(UvTcpHandle handle, ref SockAddr addr, int flags);
|
||||||
public uv_tcp_bind_func _uv_tcp_bind;
|
protected uv_tcp_bind_func _uv_tcp_bind;
|
||||||
public void tcp_bind(UvTcpHandle handle, ref SockAddr addr, int flags)
|
public void tcp_bind(UvTcpHandle handle, ref SockAddr addr, int flags)
|
||||||
{
|
{
|
||||||
handle.Validate();
|
handle.Validate();
|
||||||
ThrowIfErrored(_uv_tcp_bind(handle, ref addr, flags));
|
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)
|
public void tcp_open(UvTcpHandle handle, IntPtr hSocket)
|
||||||
{
|
{
|
||||||
handle.Validate();
|
handle.Validate();
|
||||||
ThrowIfErrored(_uv_tcp_open(handle, hSocket));
|
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)
|
public void tcp_nodelay(UvTcpHandle handle, bool enable)
|
||||||
{
|
{
|
||||||
handle.Validate();
|
handle.Validate();
|
||||||
ThrowIfErrored(_uv_tcp_nodelay(handle, enable ? 1 : 0));
|
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)
|
public void pipe_init(UvLoopHandle loop, UvPipeHandle handle, bool ipc)
|
||||||
{
|
{
|
||||||
loop.Validate();
|
loop.Validate();
|
||||||
|
|
@ -213,14 +220,14 @@ namespace Libuv.Internal
|
||||||
ThrowIfErrored(_uv_pipe_init(loop, handle, ipc ? -1 : 0));
|
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)
|
public void pipe_bind(UvPipeHandle handle, string name)
|
||||||
{
|
{
|
||||||
handle.Validate();
|
handle.Validate();
|
||||||
ThrowIfErrored(_uv_pipe_bind(handle, name));
|
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)
|
public void pipe_open(UvPipeHandle handle, IntPtr hSocket)
|
||||||
{
|
{
|
||||||
handle.Validate();
|
handle.Validate();
|
||||||
|
|
@ -229,14 +236,14 @@ namespace Libuv.Internal
|
||||||
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
public delegate void uv_connection_cb(IntPtr server, int status);
|
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)
|
public void listen(UvStreamHandle handle, int backlog, uv_connection_cb cb)
|
||||||
{
|
{
|
||||||
handle.Validate();
|
handle.Validate();
|
||||||
ThrowIfErrored(_uv_listen(handle, backlog, cb));
|
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)
|
public void accept(UvStreamHandle server, UvStreamHandle client)
|
||||||
{
|
{
|
||||||
server.Validate();
|
server.Validate();
|
||||||
|
|
@ -246,7 +253,7 @@ namespace Libuv.Internal
|
||||||
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
public delegate void uv_connect_cb(IntPtr req, int status);
|
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)
|
public void pipe_connect(UvConnectRequest req, UvPipeHandle handle, string name, uv_connect_cb cb)
|
||||||
{
|
{
|
||||||
req.Validate();
|
req.Validate();
|
||||||
|
|
@ -254,7 +261,7 @@ namespace Libuv.Internal
|
||||||
_uv_pipe_connect(req, handle, name, cb);
|
_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)
|
public int pipe_pending_count(UvPipeHandle handle)
|
||||||
{
|
{
|
||||||
handle.Validate();
|
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);
|
public delegate void uv_alloc_cb(IntPtr server, int suggested_size, out uv_buf_t buf);
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
public delegate void uv_read_cb(IntPtr server, int nread, ref uv_buf_t buf);
|
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)
|
public void read_start(UvStreamHandle handle, uv_alloc_cb alloc_cb, uv_read_cb read_cb)
|
||||||
{
|
{
|
||||||
handle.Validate();
|
handle.Validate();
|
||||||
ThrowIfErrored(_uv_read_start(handle, alloc_cb, read_cb));
|
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)
|
public void read_stop(UvStreamHandle handle)
|
||||||
{
|
{
|
||||||
handle.Validate();
|
handle.Validate();
|
||||||
ThrowIfErrored(_uv_read_stop(handle));
|
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)
|
public int try_write(UvStreamHandle handle, uv_buf_t[] bufs, int nbufs)
|
||||||
{
|
{
|
||||||
handle.Validate();
|
handle.Validate();
|
||||||
|
|
@ -291,8 +298,8 @@ namespace Libuv.Internal
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
public delegate void uv_write_cb(IntPtr req, int status);
|
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);
|
protected 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 uv_write_func _uv_write;
|
||||||
public unsafe void write(UvRequest req, UvStreamHandle handle, uv_buf_t* bufs, int nbufs, uv_write_cb cb)
|
public unsafe void write(UvRequest req, UvStreamHandle handle, uv_buf_t* bufs, int nbufs, uv_write_cb cb)
|
||||||
{
|
{
|
||||||
req.Validate();
|
req.Validate();
|
||||||
|
|
@ -300,8 +307,8 @@ namespace Libuv.Internal
|
||||||
ThrowIfErrored(_uv_write(req, handle, bufs, nbufs, cb));
|
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);
|
protected 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 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)
|
public unsafe void write2(UvRequest req, UvStreamHandle handle, uv_buf_t* bufs, int nbufs, UvStreamHandle sendHandle, uv_write_cb cb)
|
||||||
{
|
{
|
||||||
req.Validate();
|
req.Validate();
|
||||||
|
|
@ -309,38 +316,38 @@ namespace Libuv.Internal
|
||||||
ThrowIfErrored(_uv_write2(req, handle, bufs, nbufs, sendHandle, cb));
|
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)
|
public string err_name(int err)
|
||||||
{
|
{
|
||||||
IntPtr ptr = _uv_err_name(err);
|
IntPtr ptr = _uv_err_name(err);
|
||||||
return ptr == IntPtr.Zero ? null : Marshal.PtrToStringAnsi(ptr);
|
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)
|
public string strerror(int err)
|
||||||
{
|
{
|
||||||
IntPtr ptr = _uv_strerror(err);
|
IntPtr ptr = _uv_strerror(err);
|
||||||
return ptr == IntPtr.Zero ? null : Marshal.PtrToStringAnsi(ptr);
|
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 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 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 int req_size(RequestType reqType) => _uv_req_size(reqType);
|
||||||
|
|
||||||
public delegate int uv_ip4_addr_func(string ip, int port, out SockAddr addr);
|
protected delegate int uv_ip4_addr_func(string ip, int port, out SockAddr addr);
|
||||||
public uv_ip4_addr_func _uv_ip4_addr;
|
protected uv_ip4_addr_func _uv_ip4_addr;
|
||||||
public void ip4_addr(string ip, int port, out SockAddr addr, out UvException error)
|
public void ip4_addr(string ip, int port, out SockAddr addr, out UvException error)
|
||||||
{
|
{
|
||||||
Check(_uv_ip4_addr(ip, port, out addr), out 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);
|
protected delegate int uv_ip6_addr_func(string ip, int port, out SockAddr addr);
|
||||||
public uv_ip6_addr_func _uv_ip6_addr;
|
protected uv_ip6_addr_func _uv_ip6_addr;
|
||||||
public void ip6_addr(string ip, int port, out SockAddr addr, out UvException error)
|
public void ip6_addr(string ip, int port, out SockAddr addr, out UvException error)
|
||||||
{
|
{
|
||||||
Check(_uv_ip6_addr(ip, port, out addr), out error);
|
Check(_uv_ip6_addr(ip, port, out addr), out error);
|
||||||
|
|
@ -348,15 +355,15 @@ namespace Libuv.Internal
|
||||||
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
public delegate void uv_walk_cb(IntPtr handle, IntPtr arg);
|
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)
|
public void walk(UvLoopHandle loop, uv_walk_cb walk_cb, IntPtr arg)
|
||||||
{
|
{
|
||||||
loop.Validate();
|
loop.Validate();
|
||||||
_uv_walk(loop, walk_cb, arg);
|
_uv_walk(loop, walk_cb, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Func<UvLoopHandle, UvTimerHandle, int> _uv_timer_init;
|
protected Func<UvLoopHandle, UvTimerHandle, int> _uv_timer_init;
|
||||||
public void timer_init(UvLoopHandle loop, UvTimerHandle handle)
|
public unsafe void timer_init(UvLoopHandle loop, UvTimerHandle handle)
|
||||||
{
|
{
|
||||||
loop.Validate();
|
loop.Validate();
|
||||||
handle.Validate();
|
handle.Validate();
|
||||||
|
|
@ -365,29 +372,29 @@ namespace Libuv.Internal
|
||||||
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
public delegate void uv_timer_cb(IntPtr handle);
|
public delegate void uv_timer_cb(IntPtr handle);
|
||||||
public Func<UvTimerHandle, uv_timer_cb, long, long, int> _uv_timer_start;
|
protected 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)
|
public unsafe void timer_start(UvTimerHandle handle, uv_timer_cb cb, long timeout, long repeat)
|
||||||
{
|
{
|
||||||
handle.Validate();
|
handle.Validate();
|
||||||
ThrowIfErrored(_uv_timer_start(handle, cb, timeout, repeat));
|
ThrowIfErrored(_uv_timer_start(handle, cb, timeout, repeat));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Func<UvTimerHandle, int> _uv_timer_stop;
|
protected Func<UvTimerHandle, int> _uv_timer_stop;
|
||||||
public void timer_stop(UvTimerHandle handle)
|
public unsafe void timer_stop(UvTimerHandle handle)
|
||||||
{
|
{
|
||||||
handle.Validate();
|
handle.Validate();
|
||||||
ThrowIfErrored(_uv_timer_stop(handle));
|
ThrowIfErrored(_uv_timer_stop(handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Func<UvLoopHandle, long> _uv_now;
|
protected Func<UvLoopHandle, long> _uv_now;
|
||||||
public long now(UvLoopHandle loop)
|
public unsafe long now(UvLoopHandle loop)
|
||||||
{
|
{
|
||||||
loop.Validate();
|
loop.Validate();
|
||||||
return _uv_now(loop);
|
return _uv_now(loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
public delegate int uv_tcp_getsockname_func(UvTcpHandle handle, out SockAddr addr, ref int namelen);
|
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)
|
public void tcp_getsockname(UvTcpHandle handle, out SockAddr addr, ref int namelen)
|
||||||
{
|
{
|
||||||
handle.Validate();
|
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 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)
|
public void tcp_getpeername(UvTcpHandle handle, out SockAddr addr, ref int namelen)
|
||||||
{
|
{
|
||||||
handle.Validate();
|
handle.Validate();
|
||||||
ThrowIfErrored(_uv_tcp_getpeername(handle, out addr, ref namelen));
|
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
|
public struct uv_buf_t
|
||||||
{
|
{
|
||||||
|
|
@ -417,9 +424,9 @@ namespace Libuv.Internal
|
||||||
private readonly IntPtr _field0;
|
private readonly IntPtr _field0;
|
||||||
private readonly IntPtr _field1;
|
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;
|
_field0 = (IntPtr)len;
|
||||||
_field1 = memory;
|
_field1 = memory;
|
||||||
|
|
@ -581,16 +588,16 @@ namespace Libuv.Internal
|
||||||
public static extern int uv_walk(UvLoopHandle loop, uv_walk_cb walk_cb, IntPtr arg);
|
public static extern int uv_walk(UvLoopHandle loop, uv_walk_cb walk_cb, IntPtr arg);
|
||||||
|
|
||||||
[DllImport("libuv", CallingConvention = CallingConvention.Cdecl)]
|
[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)]
|
[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)]
|
[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)]
|
[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)]
|
[DllImport("WS2_32.dll", CallingConvention = CallingConvention.Winapi)]
|
||||||
public static extern unsafe int WSAIoctl(
|
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.Net;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using Server;
|
|
||||||
|
|
||||||
namespace Libuv.Internal
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking
|
||||||
{
|
{
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct SockAddr
|
internal struct SockAddr
|
||||||
{
|
{
|
||||||
// this type represents native memory occupied by sockaddr struct
|
// this type represents native memory occupied by sockaddr struct
|
||||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms740496(v=vs.85).aspx
|
// 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,
|
// 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
|
// the simplest way to reserve the same size in c# is with four nameless long values
|
||||||
private long _field0;
|
private readonly long _field0;
|
||||||
private long _field1;
|
private readonly long _field1;
|
||||||
private long _field2;
|
private readonly long _field2;
|
||||||
private long _field3;
|
private long _field3;
|
||||||
|
|
||||||
public SockAddr(long ignored) => _field0 = _field1 = _field2 = _field3 = 0;
|
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);
|
var port = ((int)(_field0 & 0x00FF0000) >> 8) | (int)((_field0 & 0xFF000000) >> 24);
|
||||||
|
|
||||||
int family = (int)_field0;
|
int family = (int)_field0;
|
||||||
if (Core.IsDarwin)
|
if (PlatformApis.IsDarwin)
|
||||||
// see explanation in example 4
|
// see explanation in example 4
|
||||||
family >>= 8;
|
family >>= 8;
|
||||||
family &= 0xFF;
|
family &= 0xFF;
|
||||||
|
|
||||||
if (family == 2)
|
if (family == 2)
|
||||||
|
{
|
||||||
// AF_INET => IPv4
|
// AF_INET => IPv4
|
||||||
return new IPEndPoint(new IPAddress((_field0 >> 32) & 0xFFFFFFFF), port);
|
return new IPEndPoint(new IPAddress((_field0 >> 32) & 0xFFFFFFFF), port);
|
||||||
|
}
|
||||||
if (IsIPv4MappedToIPv6())
|
else if (IsIPv4MappedToIPv6())
|
||||||
{
|
{
|
||||||
var ipv4bits = (_field2 >> 32) & 0x00000000FFFFFFFF;
|
var ipv4bits = (_field2 >> 32) & 0x00000000FFFFFFFF;
|
||||||
return new IPEndPoint(new IPAddress(ipv4bits), port);
|
return new IPEndPoint(new IPAddress(ipv4bits), port);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
// otherwise IPv6
|
|
||||||
var bytes = new byte[16];
|
|
||||||
fixed (byte* b = bytes)
|
|
||||||
{
|
{
|
||||||
*(long*)b = _field1;
|
// otherwise IPv6
|
||||||
*(long*)(b + 8) = _field2;
|
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
|
public uint ScopeId
|
||||||
|
|
@ -100,8 +102,13 @@ namespace Libuv.Internal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the IPAddress is an IPv4 mapped to IPv6, return the IPv4 representation instead.
|
private bool IsIPv4MappedToIPv6()
|
||||||
// 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;
|
// 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.Diagnostics;
|
||||||
using System.Threading;
|
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 _callback;
|
||||||
private Action<Action<IntPtr>, IntPtr> _queueCloseHandle;
|
private Action<Action<IntPtr>, IntPtr> _queueCloseHandle;
|
||||||
|
|
||||||
|
|
@ -56,7 +56,7 @@ namespace Libuv.Internal
|
||||||
{
|
{
|
||||||
// This can be called from the finalizer.
|
// This can be called from the finalizer.
|
||||||
// Ensure the closure doesn't reference "this".
|
// Ensure the closure doesn't reference "this".
|
||||||
LibuvFunctions uv = _uv;
|
var uv = _uv;
|
||||||
_queueCloseHandle(memory2 => uv.close(memory2, _destroyMemory), memory);
|
_queueCloseHandle(memory2 => uv.close(memory2, _destroyMemory), memory);
|
||||||
uv.unsafe_async_send(memory);
|
uv.unsafe_async_send(memory);
|
||||||
}
|
}
|
||||||
|
|
@ -4,14 +4,14 @@
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Libuv.Internal
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Summary description for UvWriteRequest
|
/// Summary description for UvWriteRequest
|
||||||
/// </summary>
|
/// </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 Action<UvConnectRequest, int, UvException, object> _callback;
|
||||||
private object _state;
|
private object _state;
|
||||||
|
|
@ -3,9 +3,9 @@
|
||||||
|
|
||||||
using System;
|
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;
|
public UvException(string message, int statusCode) : base(message) => StatusCode = statusCode;
|
||||||
|
|
||||||
|
|
@ -5,11 +5,11 @@ using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Threading;
|
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;
|
private Action<Action<IntPtr>, IntPtr> _queueCloseHandle;
|
||||||
|
|
||||||
protected UvHandle(ILibuvTrace logger) : base (logger)
|
protected UvHandle(ILibuvTrace logger) : base (logger)
|
||||||
|
|
@ -28,7 +28,7 @@ namespace Libuv.Internal
|
||||||
|
|
||||||
protected override bool ReleaseHandle()
|
protected override bool ReleaseHandle()
|
||||||
{
|
{
|
||||||
IntPtr memory = handle;
|
var memory = handle;
|
||||||
if (memory != IntPtr.Zero)
|
if (memory != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
handle = IntPtr.Zero;
|
handle = IntPtr.Zero;
|
||||||
|
|
@ -41,7 +41,7 @@ namespace Libuv.Internal
|
||||||
{
|
{
|
||||||
// This can be called from the finalizer.
|
// This can be called from the finalizer.
|
||||||
// Ensure the closure doesn't reference "this".
|
// Ensure the closure doesn't reference "this".
|
||||||
LibuvFunctions uv = _uv;
|
var uv = _uv;
|
||||||
_queueCloseHandle(memory2 => uv.close(memory2, _destroyMemory), memory);
|
_queueCloseHandle(memory2 => uv.close(memory2, _destroyMemory), memory);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -4,9 +4,9 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
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)
|
public UvLoopHandle(ILibuvTrace logger) : base(logger)
|
||||||
{
|
{
|
||||||
|
|
@ -7,12 +7,12 @@ using System.Diagnostics;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace Libuv.Internal
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Summary description for UvMemory
|
/// Summary description for UvMemory
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class UvMemory : SafeHandle
|
internal abstract class UvMemory : SafeHandle
|
||||||
{
|
{
|
||||||
protected LibuvFunctions _uv;
|
protected LibuvFunctions _uv;
|
||||||
protected int _threadId;
|
protected int _threadId;
|
||||||
|
|
@ -66,7 +66,6 @@ namespace Libuv.Internal
|
||||||
{
|
{
|
||||||
Debug.Assert(closed || !IsClosed, "Handle is closed");
|
Debug.Assert(closed || !IsClosed, "Handle is closed");
|
||||||
Debug.Assert(!IsInvalid, "Handle is invalid");
|
Debug.Assert(!IsInvalid, "Handle is invalid");
|
||||||
|
|
||||||
Debug.Assert(_threadId == Thread.CurrentThread.ManagedThreadId, "ThreadId is incorrect");
|
Debug.Assert(_threadId == Thread.CurrentThread.ManagedThreadId, "ThreadId is incorrect");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3,9 +3,9 @@
|
||||||
|
|
||||||
using System;
|
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)
|
public UvPipeHandle(ILibuvTrace logger) : base(logger)
|
||||||
{
|
{
|
||||||
|
|
@ -4,9 +4,9 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
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)
|
protected UvRequest(ILibuvTrace logger) : base(logger, GCHandleType.Normal)
|
||||||
{
|
{
|
||||||
|
|
@ -14,11 +14,6 @@ namespace Libuv.Internal
|
||||||
|
|
||||||
public virtual void Init(LibuvThread thread)
|
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()
|
protected override bool ReleaseHandle()
|
||||||
|
|
@ -29,3 +24,4 @@ namespace Libuv.Internal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5,16 +5,14 @@ using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using Microsoft.Extensions.Logging;
|
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
|
// Ref and out lamda params must be explicitly typed
|
||||||
private static readonly LibuvFunctions.uv_alloc_cb _uv_alloc_cb =
|
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);
|
||||||
(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_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 Action<UvStreamHandle, int, UvException, object> _listenCallback;
|
||||||
private object _listenState;
|
private object _listenState;
|
||||||
|
|
@ -5,9 +5,9 @@ using System;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Runtime.InteropServices;
|
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)
|
public UvTcpHandle(ILibuvTrace logger) : base(logger)
|
||||||
{
|
{
|
||||||
|
|
@ -4,9 +4,9 @@
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.Extensions.Logging;
|
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;
|
private static readonly LibuvFunctions.uv_timer_cb _uv_timer_cb = UvTimerCb;
|
||||||
|
|
||||||
|
|
@ -7,14 +7,14 @@ using System.Collections.Generic;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Libuv.Internal
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Summary description for UvWriteRequest
|
/// Summary description for UvWriteRequest
|
||||||
/// </summary>
|
/// </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;
|
private IntPtr _bufs;
|
||||||
|
|
||||||
|
|
@ -22,9 +22,9 @@ namespace Libuv.Internal
|
||||||
private object _state;
|
private object _state;
|
||||||
private const int BUFFER_COUNT = 4;
|
private const int BUFFER_COUNT = 4;
|
||||||
|
|
||||||
private LibuvAwaitable<UvWriteReq> _awaitable = new LibuvAwaitable<UvWriteReq>();
|
private readonly LibuvAwaitable<UvWriteReq> _awaitable = new LibuvAwaitable<UvWriteReq>();
|
||||||
private List<GCHandle> _pins = new List<GCHandle>(BUFFER_COUNT + 1);
|
private readonly List<GCHandle> _pins = new List<GCHandle>(BUFFER_COUNT + 1);
|
||||||
private List<MemoryHandle> _handles = new List<MemoryHandle>(BUFFER_COUNT + 1);
|
private readonly List<MemoryHandle> _handles = new List<MemoryHandle>(BUFFER_COUNT + 1);
|
||||||
|
|
||||||
public UvWriteReq(ILibuvTrace logger) : base(logger)
|
public UvWriteReq(ILibuvTrace logger) : base(logger)
|
||||||
{
|
{
|
||||||
|
|
@ -76,9 +76,6 @@ namespace Libuv.Internal
|
||||||
nBuffers++;
|
nBuffers++;
|
||||||
|
|
||||||
var pBuffers = (LibuvFunctions.uv_buf_t*)_bufs;
|
var pBuffers = (LibuvFunctions.uv_buf_t*)_bufs;
|
||||||
if (pBuffers == null)
|
|
||||||
throw new NullReferenceException();
|
|
||||||
|
|
||||||
if (nBuffers > BUFFER_COUNT)
|
if (nBuffers > BUFFER_COUNT)
|
||||||
{
|
{
|
||||||
// create and pin buffer array when it's larger than the pre-allocated one
|
// 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);
|
var gcHandle = GCHandle.Alloc(bufArray, GCHandleType.Pinned);
|
||||||
_pins.Add(gcHandle);
|
_pins.Add(gcHandle);
|
||||||
pBuffers = (LibuvFunctions.uv_buf_t*)gcHandle.AddrOfPinnedObject();
|
pBuffers = (LibuvFunctions.uv_buf_t*)gcHandle.AddrOfPinnedObject();
|
||||||
if (pBuffers == null)
|
|
||||||
throw new NullReferenceException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nBuffers == 1)
|
if (nBuffers == 1)
|
||||||
|
|
@ -137,7 +132,7 @@ namespace Libuv.Internal
|
||||||
Action<UvWriteReq, int, UvException, object> callback,
|
Action<UvWriteReq, int, UvException, object> callback,
|
||||||
object state)
|
object state)
|
||||||
{
|
{
|
||||||
WriteArraySegmentInternal(handle, bufs, null, callback, state);
|
WriteArraySegmentInternal(handle, bufs, sendHandle: null, callback: callback, state: state);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Write2(
|
public void Write2(
|
||||||
|
|
@ -154,15 +149,12 @@ namespace Libuv.Internal
|
||||||
UvStreamHandle handle,
|
UvStreamHandle handle,
|
||||||
ArraySegment<ArraySegment<byte>> bufs,
|
ArraySegment<ArraySegment<byte>> bufs,
|
||||||
UvStreamHandle sendHandle,
|
UvStreamHandle sendHandle,
|
||||||
Action<UvWriteReq, int, UvException, object> callback, object state
|
Action<UvWriteReq, int, UvException, object> callback,
|
||||||
)
|
object state)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var pBuffers = (LibuvFunctions.uv_buf_t*)_bufs;
|
var pBuffers = (LibuvFunctions.uv_buf_t*)_bufs;
|
||||||
if (pBuffers == null)
|
|
||||||
throw new NullReferenceException();
|
|
||||||
|
|
||||||
var nBuffers = bufs.Count;
|
var nBuffers = bufs.Count;
|
||||||
if (nBuffers > BUFFER_COUNT)
|
if (nBuffers > BUFFER_COUNT)
|
||||||
{
|
{
|
||||||
|
|
@ -171,14 +163,12 @@ namespace Libuv.Internal
|
||||||
var gcHandle = GCHandle.Alloc(bufArray, GCHandleType.Pinned);
|
var gcHandle = GCHandle.Alloc(bufArray, GCHandleType.Pinned);
|
||||||
_pins.Add(gcHandle);
|
_pins.Add(gcHandle);
|
||||||
pBuffers = (LibuvFunctions.uv_buf_t*)gcHandle.AddrOfPinnedObject();
|
pBuffers = (LibuvFunctions.uv_buf_t*)gcHandle.AddrOfPinnedObject();
|
||||||
if (pBuffers == null)
|
|
||||||
throw new NullReferenceException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var index = 0; index < nBuffers; index++)
|
for (var index = 0; index < nBuffers; index++)
|
||||||
{
|
{
|
||||||
// create and pin each segment being written
|
// 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);
|
var gcHandle = GCHandle.Alloc(buf.Array, GCHandleType.Pinned);
|
||||||
_pins.Add(gcHandle);
|
_pins.Add(gcHandle);
|
||||||
|
|
@ -3,11 +3,11 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
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;
|
private const int _maxPooledWriteReqs = 1024;
|
||||||
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
|
|
||||||
namespace Libuv
|
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Provides programmatic configuration of Libuv transport features.
|
/// Provides programmatic configuration of Libuv transport features.
|
||||||
|
|
@ -19,6 +19,14 @@ namespace Libuv
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public int ThreadCount { get; set; } = ProcessorThreadCount;
|
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>
|
/// <summary>
|
||||||
/// The maximum length of the pending connection queue.
|
/// The maximum length of the pending connection queue.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -39,12 +47,19 @@ namespace Libuv
|
||||||
{
|
{
|
||||||
// Actual core count would be a better number
|
// Actual core count would be a better number
|
||||||
// rather than logical cores which includes hyper-threaded cores.
|
// 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;
|
var threadCount = Environment.ProcessorCount >> 1;
|
||||||
|
|
||||||
// Receive Side Scaling RSS Processor count currently maxes out at 16
|
if (threadCount < 1)
|
||||||
// would be better to check the NIC's current hardware queues; but xplat...
|
// Ensure shifted value is at least one
|
||||||
return threadCount < 1 ? 1 : threadCount > 16 ? 16 : threadCount;
|
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
|
public class KeywordList
|
||||||
{
|
{
|
||||||
private static int[] m_EmptyInts = new int[0];
|
private static readonly int[] m_EmptyInts = new int[0];
|
||||||
private int[] m_Keywords;
|
private int[] m_Keywords;
|
||||||
|
|
||||||
public KeywordList()
|
public KeywordList()
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,9 @@ using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
using Server.Network;
|
using Server.Network;
|
||||||
|
|
||||||
namespace Server
|
namespace Server
|
||||||
|
|
@ -56,7 +59,7 @@ namespace Server
|
||||||
* GetTickCount and GetTickCount64 have poor resolution.
|
* GetTickCount and GetTickCount64 have poor resolution.
|
||||||
* GetTickCount64 is unavailable on Windows XP and Windows Server 2003.
|
* GetTickCount64 is unavailable on Windows XP and Windows Server 2003.
|
||||||
* Stopwatch.GetTimestamp() (QueryPerformanceCounter) is high resolution, but
|
* 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(),
|
* which is why Stopwatch has been used to verify HRT before calling GetTimestamp(),
|
||||||
* enabling the usage of DateTime.UtcNow instead.
|
* enabling the usage of DateTime.UtcNow instead.
|
||||||
*/
|
*/
|
||||||
|
|
@ -80,8 +83,6 @@ namespace Server
|
||||||
|
|
||||||
private static readonly Type[] m_SerialTypeArray = { typeof(Serial) };
|
private static readonly Type[] m_SerialTypeArray = { typeof(Serial) };
|
||||||
|
|
||||||
public static MessagePump MessagePump{ get; set; }
|
|
||||||
|
|
||||||
public static bool Profiling
|
public static bool Profiling
|
||||||
{
|
{
|
||||||
get => m_Profiling;
|
get => m_Profiling;
|
||||||
|
|
@ -265,9 +266,7 @@ namespace Server
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Task.WhenAll(
|
// Close all listeners
|
||||||
MessagePump.Listeners.Select(listener => listener.Dispose())
|
|
||||||
).Wait();
|
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
|
@ -444,9 +443,6 @@ namespace Server
|
||||||
|
|
||||||
AssemblyHandler.Invoke("Initialize");
|
AssemblyHandler.Invoke("Initialize");
|
||||||
|
|
||||||
// Start accepting new connections
|
|
||||||
MessagePump = new MessagePump();
|
|
||||||
|
|
||||||
AssemblyHandler.Invoke("RegisterListeners");
|
AssemblyHandler.Invoke("RegisterListeners");
|
||||||
|
|
||||||
timerThread.Start();
|
timerThread.Start();
|
||||||
|
|
@ -454,10 +450,18 @@ namespace Server
|
||||||
foreach (Map m in Map.AllMaps)
|
foreach (Map m in Map.AllMaps)
|
||||||
m.Tiles.Force();
|
m.Tiles.Force();
|
||||||
|
|
||||||
NetState.Initialize();
|
|
||||||
|
|
||||||
EventSink.InvokeServerStarted();
|
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
|
try
|
||||||
{
|
{
|
||||||
long last = TickCount;
|
long last = TickCount;
|
||||||
|
|
@ -477,7 +481,7 @@ namespace Server
|
||||||
);
|
);
|
||||||
|
|
||||||
Timer.Slice();
|
Timer.Slice();
|
||||||
MessagePump.DoWork();
|
messagePumpService.DoWork();
|
||||||
|
|
||||||
NetState.ProcessDisposedQueue();
|
NetState.ProcessDisposedQueue();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -262,16 +262,17 @@ namespace Server
|
||||||
private static readonly List<Item> _EmptyFixItems = new List<Item>();
|
private static readonly List<Item> _EmptyFixItems = new List<Item>();
|
||||||
private Region m_DefaultRegion;
|
private Region m_DefaultRegion;
|
||||||
|
|
||||||
private int m_FileIndex;
|
private readonly int m_FileIndex;
|
||||||
|
|
||||||
private string m_Name;
|
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 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)
|
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
|
public class ItemListMenu : IMenu
|
||||||
{
|
{
|
||||||
private static int m_NextSerial;
|
private static int m_NextSerial;
|
||||||
private int m_Serial;
|
private readonly int m_Serial;
|
||||||
|
|
||||||
public ItemListMenu(string question, ItemListEntry[] entries)
|
public ItemListMenu(string question, ItemListEntry[] entries)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ namespace Server.Menus.Questions
|
||||||
public class QuestionMenu : IMenu
|
public class QuestionMenu : IMenu
|
||||||
{
|
{
|
||||||
private static int m_NextSerial;
|
private static int m_NextSerial;
|
||||||
private int m_Serial;
|
private readonly int m_Serial;
|
||||||
|
|
||||||
public QuestionMenu(string question, string[] answers)
|
public QuestionMenu(string question, string[] answers)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ namespace Server
|
||||||
|
|
||||||
public class TimedSkillMod : SkillMod
|
public class TimedSkillMod : SkillMod
|
||||||
{
|
{
|
||||||
private DateTime m_Expire;
|
private readonly DateTime m_Expire;
|
||||||
|
|
||||||
public TimedSkillMod(SkillName skill, bool relative, double value, TimeSpan delay)
|
public TimedSkillMod(SkillName skill, bool relative, double value, TimeSpan delay)
|
||||||
: this(skill, relative, value, DateTime.UtcNow + delay)
|
: this(skill, relative, value, DateTime.UtcNow + delay)
|
||||||
|
|
@ -64,21 +64,16 @@ namespace Server
|
||||||
}
|
}
|
||||||
|
|
||||||
public TimedSkillMod(SkillName skill, bool relative, double value, DateTime expire)
|
public TimedSkillMod(SkillName skill, bool relative, double value, DateTime expire)
|
||||||
: base(skill, relative, value)
|
: base(skill, relative, value) =>
|
||||||
{
|
|
||||||
m_Expire = expire;
|
m_Expire = expire;
|
||||||
}
|
|
||||||
|
|
||||||
public override bool CheckCondition()
|
public override bool CheckCondition() => DateTime.UtcNow < m_Expire;
|
||||||
{
|
|
||||||
return DateTime.UtcNow < m_Expire;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class EquippedSkillMod : SkillMod
|
public class EquippedSkillMod : SkillMod
|
||||||
{
|
{
|
||||||
private Item m_Item;
|
private readonly Item m_Item;
|
||||||
private Mobile m_Mobile;
|
private readonly Mobile m_Mobile;
|
||||||
|
|
||||||
public EquippedSkillMod(SkillName skill, bool relative, double value, Item item, Mobile mobile)
|
public EquippedSkillMod(SkillName skill, bool relative, double value, Item item, Mobile mobile)
|
||||||
: base(skill, relative, value)
|
: base(skill, relative, value)
|
||||||
|
|
@ -87,10 +82,7 @@ namespace Server
|
||||||
m_Mobile = mobile;
|
m_Mobile = mobile;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool CheckCondition()
|
public override bool CheckCondition() => !m_Item.Deleted && !m_Mobile.Deleted && m_Item.Parent == m_Mobile;
|
||||||
{
|
|
||||||
return !m_Item.Deleted && !m_Mobile.Deleted && m_Item.Parent == m_Mobile;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DefaultSkillMod : SkillMod
|
public class DefaultSkillMod : SkillMod
|
||||||
|
|
@ -100,10 +92,7 @@ namespace Server
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool CheckCondition()
|
public override bool CheckCondition() => true;
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class SkillMod
|
public abstract class SkillMod
|
||||||
|
|
@ -265,8 +254,8 @@ namespace Server
|
||||||
|
|
||||||
public class StatMod
|
public class StatMod
|
||||||
{
|
{
|
||||||
private DateTime m_Added;
|
private readonly DateTime m_Added;
|
||||||
private TimeSpan m_Duration;
|
private readonly TimeSpan m_Duration;
|
||||||
|
|
||||||
public StatMod(StatType type, string name, int offset, TimeSpan duration)
|
public StatMod(StatType type, string name, int offset, TimeSpan duration)
|
||||||
{
|
{
|
||||||
|
|
@ -296,10 +285,7 @@ namespace Server
|
||||||
|
|
||||||
public class DamageEntry
|
public class DamageEntry
|
||||||
{
|
{
|
||||||
public DamageEntry(Mobile damager)
|
public DamageEntry(Mobile damager) => Damager = damager;
|
||||||
{
|
|
||||||
Damager = damager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Mobile Damager{ get; }
|
public Mobile Damager{ get; }
|
||||||
|
|
||||||
|
|
@ -425,10 +411,8 @@ namespace Server
|
||||||
public class MobileNotConnectedException : Exception
|
public class MobileNotConnectedException : Exception
|
||||||
{
|
{
|
||||||
public MobileNotConnectedException(Mobile source, string message)
|
public MobileNotConnectedException(Mobile source, string message)
|
||||||
: base(message)
|
: base(message) =>
|
||||||
{
|
|
||||||
Source = source.ToString();
|
Source = source.ToString();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Delegates
|
#region Delegates
|
||||||
|
|
@ -460,8 +444,8 @@ namespace Server
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Mobile : IHued, IComparable<Mobile>, ISerializable, ISpawnable, IPropertyListObject
|
public class Mobile : IHued, IComparable<Mobile>, ISerializable, ISpawnable, IPropertyListObject
|
||||||
{
|
{
|
||||||
private BufferWriter m_SaveBuffer;
|
private readonly BufferWriter m_SaveBuffer;
|
||||||
public BufferWriter SaveBuffer { get { return m_SaveBuffer; } }
|
public BufferWriter SaveBuffer => m_SaveBuffer;
|
||||||
|
|
||||||
private const int
|
private const int
|
||||||
WarmodeCatchCount = 4; // Allow four warmode changes in 0.5 seconds, any more will be delay for two seconds
|
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 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],
|
||||||
new Packet[8]
|
new Packet[8]
|
||||||
};
|
};
|
||||||
|
|
||||||
private static List<IEntity> m_MoveList = new List<IEntity>();
|
private static readonly List<IEntity> m_MoveList = new List<IEntity>();
|
||||||
private static List<Mobile> m_MoveClientList = new List<Mobile>();
|
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 readonly List<Mobile> m_Hears = new List<Mobile>();
|
||||||
private static List<IEntity> m_OnSpeech = new List<IEntity>();
|
private static readonly List<IEntity> m_OnSpeech = new List<IEntity>();
|
||||||
|
|
||||||
public static bool m_DefaultShowVisibleDamage, m_DefaultCanSeeVisibleDamage;
|
public static bool m_DefaultShowVisibleDamage, m_DefaultCanSeeVisibleDamage;
|
||||||
|
|
||||||
private static string[] m_AccessLevelNames =
|
private static readonly string[] m_AccessLevelNames =
|
||||||
{
|
{
|
||||||
"a player",
|
"a player",
|
||||||
"a counselor",
|
"a counselor",
|
||||||
|
|
@ -497,7 +481,7 @@ namespace Server
|
||||||
"an owner"
|
"an owner"
|
||||||
};
|
};
|
||||||
|
|
||||||
private static int[] m_InvalidBodies =
|
private static readonly int[] m_InvalidBodies =
|
||||||
{
|
{
|
||||||
32,
|
32,
|
||||||
95,
|
95,
|
||||||
|
|
@ -506,12 +490,12 @@ namespace Server
|
||||||
198
|
198
|
||||||
};
|
};
|
||||||
|
|
||||||
private static Queue<Mobile> m_DeltaQueue = new Queue<Mobile>();
|
private static readonly Queue<Mobile> m_DeltaQueue = new Queue<Mobile>();
|
||||||
private static Queue<Mobile> m_DeltaQueueR = new Queue<Mobile>();
|
private static readonly Queue<Mobile> m_DeltaQueueR = new Queue<Mobile>();
|
||||||
|
|
||||||
private static bool _processing;
|
private static bool _processing;
|
||||||
|
|
||||||
private static string[] m_GuildTypes =
|
private static readonly string[] m_GuildTypes =
|
||||||
{
|
{
|
||||||
"",
|
"",
|
||||||
" (Chaos)",
|
" (Chaos)",
|
||||||
|
|
@ -4367,10 +4351,7 @@ namespace Server
|
||||||
/// <seealso cref="OnDeath" />
|
/// <seealso cref="OnDeath" />
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>True to continue with death, false to override it.</returns>
|
/// <returns>True to continue with death, false to override it.</returns>
|
||||||
public virtual bool OnBeforeDeath()
|
public virtual bool OnBeforeDeath() => true;
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Overridable. Event invoked after the Mobile is <see cref="Kill">killed</see>. Primarily, this method is responsible for
|
/// 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 static Mobile GetDamagerFrom(DamageEntry de) => de?.Damager;
|
||||||
|
|
||||||
public Mobile FindMostRecentDamager(bool allowSelf)
|
public Mobile FindMostRecentDamager(bool allowSelf) => GetDamagerFrom(FindMostRecentDamageEntry(allowSelf));
|
||||||
{
|
|
||||||
return GetDamagerFrom(FindMostRecentDamageEntry(allowSelf));
|
|
||||||
}
|
|
||||||
|
|
||||||
public DamageEntry FindMostRecentDamageEntry(bool allowSelf)
|
public DamageEntry FindMostRecentDamageEntry(bool allowSelf)
|
||||||
{
|
{
|
||||||
|
|
@ -5199,10 +5177,7 @@ namespace Server
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual Mobile GetDamageMaster(Mobile damagee)
|
public virtual Mobile GetDamageMaster(Mobile damagee) => null;
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual DamageEntry RegisterDamage(int amount, Mobile from)
|
public virtual DamageEntry RegisterDamage(int amount, Mobile from)
|
||||||
{
|
{
|
||||||
|
|
@ -5251,10 +5226,7 @@ namespace Server
|
||||||
Damage(amount, null);
|
Damage(amount, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual bool CanBeDamaged()
|
public virtual bool CanBeDamaged() => !m_Blessed;
|
||||||
{
|
|
||||||
return !m_Blessed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual void Damage(int amount, Mobile from)
|
public virtual void Damage(int amount, Mobile from)
|
||||||
{
|
{
|
||||||
|
|
@ -5906,15 +5878,9 @@ namespace Server
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetAccessLevelName(AccessLevel level)
|
public static string GetAccessLevelName(AccessLevel level) => m_AccessLevelNames[(int)level];
|
||||||
{
|
|
||||||
return m_AccessLevelNames[(int)level];
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual bool CanPaperdollBeOpenedBy(Mobile from)
|
public virtual bool CanPaperdollBeOpenedBy(Mobile from) => Body.IsHuman || Body.IsGhost || IsBodyMod;
|
||||||
{
|
|
||||||
return Body.IsHuman || Body.IsGhost || IsBodyMod;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual void GetChildContextMenuEntries(Mobile from, List<ContextMenuEntry> list, Item item)
|
public virtual void GetChildContextMenuEntries(Mobile from, List<ContextMenuEntry> list, Item item)
|
||||||
{
|
{
|
||||||
|
|
@ -6215,10 +6181,7 @@ namespace Server
|
||||||
eable.Free();
|
eable.Free();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Send(Packet p)
|
public bool Send(Packet p) => Send(p, false);
|
||||||
{
|
|
||||||
return Send(p, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Send(Packet p, bool throwOnOffline)
|
public bool Send(Packet p, bool throwOnOffline)
|
||||||
{
|
{
|
||||||
|
|
@ -6254,10 +6217,7 @@ namespace Server
|
||||||
RevealingAction();
|
RevealingAction();
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual bool HandlesOnSpeech(Mobile from)
|
public virtual bool HandlesOnSpeech(Mobile from) => false;
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Overridable. Virtual event invoked when the Mobile hears speech. This event will only be invoked if
|
/// 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;
|
m_Direction = dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual int GetSeason()
|
public virtual int GetSeason() => m_Map?.Season ?? 1;
|
||||||
{
|
|
||||||
return m_Map?.Season ?? 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual int GetPacketFlags()
|
public virtual int GetPacketFlags()
|
||||||
{
|
{
|
||||||
|
|
@ -6505,10 +6462,7 @@ namespace Server
|
||||||
m_AccessLevel > AccessLevel.Player || m.Warmode);
|
m_AccessLevel > AccessLevel.Player || m.Warmode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual bool CanBeRenamedBy(Mobile from)
|
public virtual bool CanBeRenamedBy(Mobile from) => from.AccessLevel >= AccessLevel.GameMaster && from.m_AccessLevel > m_AccessLevel;
|
||||||
{
|
|
||||||
return from.AccessLevel >= AccessLevel.GameMaster && from.m_AccessLevel > m_AccessLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual void OnGuildTitleChange(string oldTitle)
|
public virtual void OnGuildTitleChange(string oldTitle)
|
||||||
{
|
{
|
||||||
|
|
@ -6738,10 +6692,7 @@ namespace Server
|
||||||
|
|
||||||
public bool HasFreeHand() => FindItemOnLayer(Layer.TwoHanded) == null;
|
public bool HasFreeHand() => FindItemOnLayer(Layer.TwoHanded) == null;
|
||||||
|
|
||||||
public virtual IWeapon GetDefaultWeapon()
|
public virtual IWeapon GetDefaultWeapon() => DefaultWeapon;
|
||||||
{
|
|
||||||
return DefaultWeapon;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BankBox FindBankNoCreate()
|
public BankBox FindBankNoCreate()
|
||||||
{
|
{
|
||||||
|
|
@ -6827,21 +6778,13 @@ namespace Server
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual bool CheckLift(Mobile from, Item item, ref LRReason reject)
|
public virtual bool CheckLift(Mobile from, Item item, ref LRReason reject) => true;
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual bool CheckNonlocalLift(Mobile from, Item item)
|
public virtual bool CheckNonlocalLift(Mobile from, Item item) => from == this || from.AccessLevel > AccessLevel && from.AccessLevel >= AccessLevel.GameMaster;
|
||||||
{
|
|
||||||
return from == this || from.AccessLevel > AccessLevel && from.AccessLevel >= AccessLevel.GameMaster;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual bool CheckTrade(Mobile to, Item item, SecureTradeContainer cont, bool message, bool checkItems,
|
public virtual bool CheckTrade(Mobile to, Item item, SecureTradeContainer cont, bool message, bool checkItems,
|
||||||
int plusItems, int plusWeight)
|
int plusItems, int plusWeight) =>
|
||||||
{
|
true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual bool OpenTrade(Mobile from, Item offer = null)
|
public virtual bool OpenTrade(Mobile from, Item offer = null)
|
||||||
{
|
{
|
||||||
|
|
@ -6927,10 +6870,7 @@ namespace Server
|
||||||
/// return base.OnDragLift( item );
|
/// return base.OnDragLift( item );
|
||||||
/// }</code>
|
/// }</code>
|
||||||
/// </example>
|
/// </example>
|
||||||
public virtual bool OnDragLift(Item item)
|
public virtual bool OnDragLift(Item item) => true;
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Overridable. Virtual event invoked when the Mobile attempts to drop <paramref name="item" /> into a
|
/// Overridable. Virtual event invoked when the Mobile attempts to drop <paramref name="item" /> into a
|
||||||
|
|
@ -6940,40 +6880,28 @@ namespace Server
|
||||||
/// .
|
/// .
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>True if the drop is allowed, false if otherwise.</returns>
|
/// <returns>True if the drop is allowed, false if otherwise.</returns>
|
||||||
public virtual bool OnDroppedItemInto(Item item, Container container, Point3D loc)
|
public virtual bool OnDroppedItemInto(Item item, Container container, Point3D loc) => true;
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Overridable. Virtual event invoked when the Mobile attempts to drop <paramref name="item" /> directly onto another
|
/// 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.
|
/// <see cref="Item" />, <paramref name="target" />. This is the case of stacking items.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>True if the drop is allowed, false if otherwise.</returns>
|
/// <returns>True if the drop is allowed, false if otherwise.</returns>
|
||||||
public virtual bool OnDroppedItemOnto(Item item, Item target)
|
public virtual bool OnDroppedItemOnto(Item item, Item target) => true;
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Overridable. Virtual event invoked when the Mobile attempts to drop <paramref name="item" /> into another
|
/// 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" />.
|
/// <see cref="Item" />, <paramref name="target" />. The target item is most likely a <see cref="Container" />.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>True if the drop is allowed, false if otherwise.</returns>
|
/// <returns>True if the drop is allowed, false if otherwise.</returns>
|
||||||
public virtual bool OnDroppedItemToItem(Item item, Item target, Point3D loc)
|
public virtual bool OnDroppedItemToItem(Item item, Item target, Point3D loc) => true;
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Overridable. Virtual event invoked when the Mobile attempts to give <paramref name="item" /> to a Mobile (
|
/// Overridable. Virtual event invoked when the Mobile attempts to give <paramref name="item" /> to a Mobile (
|
||||||
/// <paramref name="target" />).
|
/// <paramref name="target" />).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>True if the drop is allowed, false if otherwise.</returns>
|
/// <returns>True if the drop is allowed, false if otherwise.</returns>
|
||||||
public virtual bool OnDroppedItemToMobile(Item item, Mobile target)
|
public virtual bool OnDroppedItemToMobile(Item item, Mobile target) => true;
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Overridable. Virtual event invoked when the Mobile attempts to drop <paramref name="item" /> to the world at a
|
/// 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>
|
/// </summary>
|
||||||
/// <returns>True if the drop is allowed, false if otherwise.</returns>
|
/// <returns>True if the drop is allowed, false if otherwise.</returns>
|
||||||
public virtual bool OnDroppedItemToWorld(Item item, Point3D location)
|
public virtual bool OnDroppedItemToWorld(Item item, Point3D location) => true;
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Overridable. Virtual event when <paramref name="from" /> successfully uses <paramref name="item" /> while it's on this
|
/// 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)
|
public virtual bool CheckNonlocalDrop(Mobile from, Item item, Item target) => from == this || from.AccessLevel > AccessLevel && from.AccessLevel >= AccessLevel.GameMaster;
|
||||||
{
|
|
||||||
return from == this || from.AccessLevel > AccessLevel && from.AccessLevel >= AccessLevel.GameMaster;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual bool CheckItemUse(Mobile from, Item item)
|
public virtual bool CheckItemUse(Mobile from, Item item) => true;
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Overridable. Virtual event invoked when <paramref name="from" /> successfully lifts <paramref name="item" /> from this
|
/// 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)
|
public virtual bool AllowItemUse(Item item) => true;
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual bool AllowEquipFrom(Mobile mob)
|
public virtual bool AllowEquipFrom(Mobile mob) => mob == this || mob.AccessLevel >= AccessLevel.GameMaster && mob.AccessLevel > AccessLevel;
|
||||||
{
|
|
||||||
return mob == this || mob.AccessLevel >= AccessLevel.GameMaster && mob.AccessLevel > AccessLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual bool EquipItem(Item item)
|
public virtual bool EquipItem(Item item)
|
||||||
{
|
{
|
||||||
|
|
@ -7304,13 +7217,10 @@ namespace Server
|
||||||
|
|
||||||
private class MovementRecord
|
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;
|
public long m_End;
|
||||||
|
|
||||||
private MovementRecord(long end)
|
private MovementRecord(long end) => m_End = end;
|
||||||
{
|
|
||||||
m_End = end;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static MovementRecord NewInstance(long end)
|
public static MovementRecord NewInstance(long end)
|
||||||
{
|
{
|
||||||
|
|
@ -7343,7 +7253,7 @@ namespace Server
|
||||||
|
|
||||||
private class WarmodeTimer : Timer
|
private class WarmodeTimer : Timer
|
||||||
{
|
{
|
||||||
private Mobile m_Mobile;
|
private readonly Mobile m_Mobile;
|
||||||
|
|
||||||
public WarmodeTimer(Mobile m, bool value)
|
public WarmodeTimer(Mobile m, bool value)
|
||||||
: base(WarmodeSpamDelay)
|
: base(WarmodeSpamDelay)
|
||||||
|
|
@ -7365,13 +7275,11 @@ namespace Server
|
||||||
|
|
||||||
private class SimpleTarget : Target
|
private class SimpleTarget : Target
|
||||||
{
|
{
|
||||||
private TargetCallback m_Callback;
|
private readonly TargetCallback m_Callback;
|
||||||
|
|
||||||
public SimpleTarget(int range, TargetFlags flags, bool allowGround, TargetCallback callback)
|
public SimpleTarget(int range, TargetFlags flags, bool allowGround, TargetCallback callback)
|
||||||
: base(range, allowGround, flags)
|
: base(range, allowGround, flags) =>
|
||||||
{
|
|
||||||
m_Callback = callback;
|
m_Callback = callback;
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnTarget(Mobile from, object targeted)
|
protected override void OnTarget(Mobile from, object targeted)
|
||||||
{
|
{
|
||||||
|
|
@ -7381,8 +7289,8 @@ namespace Server
|
||||||
|
|
||||||
private class SimpleStateTarget<T> : Target
|
private class SimpleStateTarget<T> : Target
|
||||||
{
|
{
|
||||||
private TargetStateCallback<T> m_Callback;
|
private readonly TargetStateCallback<T> m_Callback;
|
||||||
private T m_State;
|
private readonly T m_State;
|
||||||
|
|
||||||
public SimpleStateTarget(int range, TargetFlags flags, bool allowGround, TargetStateCallback<T> callback,
|
public SimpleStateTarget(int range, TargetFlags flags, bool allowGround, TargetStateCallback<T> callback,
|
||||||
T state)
|
T state)
|
||||||
|
|
@ -7400,13 +7308,11 @@ namespace Server
|
||||||
|
|
||||||
private class AutoManifestTimer : Timer
|
private class AutoManifestTimer : Timer
|
||||||
{
|
{
|
||||||
private Mobile m_Mobile;
|
private readonly Mobile m_Mobile;
|
||||||
|
|
||||||
public AutoManifestTimer(Mobile m, TimeSpan delay)
|
public AutoManifestTimer(Mobile m, TimeSpan delay)
|
||||||
: base(delay)
|
: base(delay) =>
|
||||||
{
|
|
||||||
m_Mobile = m;
|
m_Mobile = m;
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnTick()
|
protected override void OnTick()
|
||||||
{
|
{
|
||||||
|
|
@ -7419,17 +7325,11 @@ namespace Server
|
||||||
{
|
{
|
||||||
private static LocationComparer m_Instance;
|
private static LocationComparer m_Instance;
|
||||||
|
|
||||||
public LocationComparer(IEntity relativeTo)
|
public LocationComparer(IEntity relativeTo) => RelativeTo = relativeTo;
|
||||||
{
|
|
||||||
RelativeTo = relativeTo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEntity RelativeTo{ get; set; }
|
public IEntity RelativeTo{ get; set; }
|
||||||
|
|
||||||
public int Compare(IEntity x, IEntity y)
|
public int Compare(IEntity x, IEntity y) => GetDistance(x) - GetDistance(y);
|
||||||
{
|
|
||||||
return GetDistance(x) - GetDistance(y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static LocationComparer GetInstance(IEntity relativeTo)
|
public static LocationComparer GetInstance(IEntity relativeTo)
|
||||||
{
|
{
|
||||||
|
|
@ -7454,15 +7354,9 @@ namespace Server
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int IComparable<IEntity>.CompareTo(IEntity other)
|
int IComparable<IEntity>.CompareTo(IEntity other) => other == null ? -1 : Serial.CompareTo(other.Serial);
|
||||||
{
|
|
||||||
return other == null ? -1 : Serial.CompareTo(other.Serial);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int CompareTo(Mobile other)
|
public int CompareTo(Mobile other) => other == null ? -1 : Serial.CompareTo(other.Serial);
|
||||||
{
|
|
||||||
return other == null ? -1 : Serial.CompareTo(other.Serial);
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Handlers
|
#region Handlers
|
||||||
|
|
||||||
|
|
@ -7581,7 +7475,7 @@ namespace Server
|
||||||
|
|
||||||
private class ManaTimer : Timer
|
private class ManaTimer : Timer
|
||||||
{
|
{
|
||||||
private Mobile m_Owner;
|
private readonly Mobile m_Owner;
|
||||||
|
|
||||||
public ManaTimer(Mobile m)
|
public ManaTimer(Mobile m)
|
||||||
: base(GetManaRegenRate(m), GetManaRegenRate(m))
|
: base(GetManaRegenRate(m), GetManaRegenRate(m))
|
||||||
|
|
@ -7601,7 +7495,7 @@ namespace Server
|
||||||
|
|
||||||
private class HitsTimer : Timer
|
private class HitsTimer : Timer
|
||||||
{
|
{
|
||||||
private Mobile m_Owner;
|
private readonly Mobile m_Owner;
|
||||||
|
|
||||||
public HitsTimer(Mobile m)
|
public HitsTimer(Mobile m)
|
||||||
: base(GetHitsRegenRate(m), GetHitsRegenRate(m))
|
: base(GetHitsRegenRate(m), GetHitsRegenRate(m))
|
||||||
|
|
@ -7621,7 +7515,7 @@ namespace Server
|
||||||
|
|
||||||
private class StamTimer : Timer
|
private class StamTimer : Timer
|
||||||
{
|
{
|
||||||
private Mobile m_Owner;
|
private readonly Mobile m_Owner;
|
||||||
|
|
||||||
public StamTimer(Mobile m)
|
public StamTimer(Mobile m)
|
||||||
: base(GetStamRegenRate(m), GetStamRegenRate(m))
|
: base(GetStamRegenRate(m), GetStamRegenRate(m))
|
||||||
|
|
@ -7641,7 +7535,7 @@ namespace Server
|
||||||
|
|
||||||
private class LogoutTimer : Timer
|
private class LogoutTimer : Timer
|
||||||
{
|
{
|
||||||
private Mobile m_Mobile;
|
private readonly Mobile m_Mobile;
|
||||||
|
|
||||||
public LogoutTimer(Mobile m)
|
public LogoutTimer(Mobile m)
|
||||||
: base(TimeSpan.FromDays(1.0))
|
: base(TimeSpan.FromDays(1.0))
|
||||||
|
|
@ -7666,7 +7560,7 @@ namespace Server
|
||||||
|
|
||||||
private class ParalyzedTimer : Timer
|
private class ParalyzedTimer : Timer
|
||||||
{
|
{
|
||||||
private Mobile m_Mobile;
|
private readonly Mobile m_Mobile;
|
||||||
|
|
||||||
public ParalyzedTimer(Mobile m, TimeSpan duration)
|
public ParalyzedTimer(Mobile m, TimeSpan duration)
|
||||||
: base(duration)
|
: base(duration)
|
||||||
|
|
@ -7683,7 +7577,7 @@ namespace Server
|
||||||
|
|
||||||
private class FrozenTimer : Timer
|
private class FrozenTimer : Timer
|
||||||
{
|
{
|
||||||
private Mobile m_Mobile;
|
private readonly Mobile m_Mobile;
|
||||||
|
|
||||||
public FrozenTimer(Mobile m, TimeSpan duration)
|
public FrozenTimer(Mobile m, TimeSpan duration)
|
||||||
: base(duration)
|
: base(duration)
|
||||||
|
|
@ -7700,7 +7594,7 @@ namespace Server
|
||||||
|
|
||||||
private class CombatTimer : Timer
|
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))
|
public CombatTimer(Mobile m) : base(TimeSpan.FromSeconds(0.0), TimeSpan.FromSeconds(0.01))
|
||||||
{
|
{
|
||||||
|
|
@ -7744,7 +7638,7 @@ namespace Server
|
||||||
|
|
||||||
private class ExpireCombatantTimer : Timer
|
private class ExpireCombatantTimer : Timer
|
||||||
{
|
{
|
||||||
private Mobile m_Mobile;
|
private readonly Mobile m_Mobile;
|
||||||
|
|
||||||
public ExpireCombatantTimer(Mobile m)
|
public ExpireCombatantTimer(Mobile m)
|
||||||
: base(TimeSpan.FromMinutes(1.0))
|
: base(TimeSpan.FromMinutes(1.0))
|
||||||
|
|
@ -7763,7 +7657,7 @@ namespace Server
|
||||||
|
|
||||||
private class ExpireCriminalTimer : Timer
|
private class ExpireCriminalTimer : Timer
|
||||||
{
|
{
|
||||||
private Mobile m_Mobile;
|
private readonly Mobile m_Mobile;
|
||||||
|
|
||||||
public ExpireCriminalTimer(Mobile m)
|
public ExpireCriminalTimer(Mobile m)
|
||||||
: base(ExpireCriminalDelay)
|
: base(ExpireCriminalDelay)
|
||||||
|
|
@ -7780,7 +7674,7 @@ namespace Server
|
||||||
|
|
||||||
private class ExpireAggressorsTimer : Timer
|
private class ExpireAggressorsTimer : Timer
|
||||||
{
|
{
|
||||||
private Mobile m_Mobile;
|
private readonly Mobile m_Mobile;
|
||||||
|
|
||||||
public ExpireAggressorsTimer(Mobile m)
|
public ExpireAggressorsTimer(Mobile m)
|
||||||
: base(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(5.0))
|
: base(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(5.0))
|
||||||
|
|
@ -7804,9 +7698,9 @@ namespace Server
|
||||||
|
|
||||||
private class SimplePrompt : Prompt
|
private class SimplePrompt : Prompt
|
||||||
{
|
{
|
||||||
private PromptCallback m_Callback;
|
private readonly PromptCallback m_Callback;
|
||||||
private bool m_CallbackHandlesCancel;
|
private readonly bool m_CallbackHandlesCancel;
|
||||||
private PromptCallback m_CancelCallback;
|
private readonly PromptCallback m_CancelCallback;
|
||||||
|
|
||||||
public SimplePrompt(PromptCallback callback, PromptCallback cancelCallback)
|
public SimplePrompt(PromptCallback callback, PromptCallback cancelCallback)
|
||||||
{
|
{
|
||||||
|
|
@ -7830,9 +7724,7 @@ namespace Server
|
||||||
if (m_CallbackHandlesCancel && m_Callback != null)
|
if (m_CallbackHandlesCancel && m_Callback != null)
|
||||||
m_Callback(from, "");
|
m_Callback(from, "");
|
||||||
else
|
else
|
||||||
{
|
m_CancelCallback?.Invoke(@from, "");
|
||||||
m_CancelCallback?.Invoke(from, "");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -7848,10 +7740,10 @@ namespace Server
|
||||||
|
|
||||||
private class SimpleStatePrompt<T> : Prompt
|
private class SimpleStatePrompt<T> : Prompt
|
||||||
{
|
{
|
||||||
private PromptStateCallback<T> m_Callback;
|
private readonly PromptStateCallback<T> m_Callback;
|
||||||
private PromptStateCallback<T> m_CancelCallback;
|
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)
|
public SimpleStatePrompt(PromptStateCallback<T> callback, PromptStateCallback<T> cancelCallback, T state)
|
||||||
{
|
{
|
||||||
|
|
@ -7962,10 +7854,7 @@ namespace Server
|
||||||
|
|
||||||
#region Get*InRange
|
#region Get*InRange
|
||||||
|
|
||||||
public IPooledEnumerable<Item> GetItemsInRange(int range)
|
public IPooledEnumerable<Item> GetItemsInRange(int range) => GetItemsInRange<Item>(range);
|
||||||
{
|
|
||||||
return GetItemsInRange<Item>(range);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IPooledEnumerable<T> GetItemsInRange<T>(int range) where T : Item
|
public IPooledEnumerable<T> GetItemsInRange<T>(int range) where T : Item
|
||||||
{
|
{
|
||||||
|
|
@ -7987,10 +7876,7 @@ namespace Server
|
||||||
return map.GetObjectsInRange(m_Location, range);
|
return map.GetObjectsInRange(m_Location, range);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IPooledEnumerable<Mobile> GetMobilesInRange(int range)
|
public IPooledEnumerable<Mobile> GetMobilesInRange(int range) => GetMobilesInRange<Mobile>(range);
|
||||||
{
|
|
||||||
return GetMobilesInRange<Mobile>(range);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IPooledEnumerable<T> GetMobilesInRange<T>(int range) where T : Mobile
|
public IPooledEnumerable<T> GetMobilesInRange<T>(int range) where T : Mobile
|
||||||
{
|
{
|
||||||
|
|
@ -8177,10 +8063,7 @@ namespace Server
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasGump<T>() where T : Gump
|
public bool HasGump<T>() where T : Gump => FindGump<T>() != null;
|
||||||
{
|
|
||||||
return FindGump<T>() != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool SendGump(Gump g)
|
public bool SendGump(Gump g)
|
||||||
{
|
{
|
||||||
|
|
@ -8204,15 +8087,9 @@ namespace Server
|
||||||
|
|
||||||
#region Beneficial Checks/Actions
|
#region Beneficial Checks/Actions
|
||||||
|
|
||||||
public virtual bool CanBeBeneficial(Mobile target)
|
public virtual bool CanBeBeneficial(Mobile target) => CanBeBeneficial(target, true, false);
|
||||||
{
|
|
||||||
return CanBeBeneficial(target, true, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual bool CanBeBeneficial(Mobile target, bool message)
|
public virtual bool CanBeBeneficial(Mobile target, bool message) => CanBeBeneficial(target, message, false);
|
||||||
{
|
|
||||||
return CanBeBeneficial(target, message, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual bool CanBeBeneficial(Mobile target, bool message, bool allowDead)
|
public virtual bool CanBeBeneficial(Mobile target, bool message, bool allowDead)
|
||||||
{
|
{
|
||||||
|
|
@ -9001,10 +8878,7 @@ namespace Server
|
||||||
/// <seealso cref="ApplyPoison" />
|
/// <seealso cref="ApplyPoison" />
|
||||||
/// <seealso cref="Poison" />
|
/// <seealso cref="Poison" />
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual bool CheckPoisonImmunity(Mobile from, Poison poison)
|
public virtual bool CheckPoisonImmunity(Mobile from, Poison poison) => false;
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Overridable. Called from <see cref="ApplyPoison" />, this method checks if the Mobile is already poisoned by some
|
/// 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="ApplyPoison" />
|
||||||
/// <seealso cref="Poison" />
|
/// <seealso cref="Poison" />
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual bool CheckHigherPoison(Mobile from, Poison poison)
|
public virtual bool CheckHigherPoison(Mobile from, Poison poison) => m_Poison != null && m_Poison.Level >= poison.Level;
|
||||||
{
|
|
||||||
return m_Poison != null && m_Poison.Level >= poison.Level;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Overridable. Attempts to apply poison to the Mobile. Checks are made such that no
|
/// 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="CurePoison" />
|
||||||
/// <seealso cref="Poison" />
|
/// <seealso cref="Poison" />
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual bool CheckCure(Mobile from)
|
public virtual bool CheckCure(Mobile from) => true;
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Overridable. Virtual event invoked when a call to <see cref="CurePoison" /> succeeded.
|
/// Overridable. Virtual event invoked when a call to <see cref="CurePoison" /> succeeded.
|
||||||
|
|
@ -9166,10 +9034,7 @@ namespace Server
|
||||||
[CommandProperty(AccessLevel.GameMaster)]
|
[CommandProperty(AccessLevel.GameMaster)]
|
||||||
public int FacialHairItemID
|
public int FacialHairItemID
|
||||||
{
|
{
|
||||||
get
|
get => m_FacialHair?.ItemID ?? 0;
|
||||||
{
|
|
||||||
return m_FacialHair?.ItemID ?? 0;
|
|
||||||
}
|
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (m_FacialHair == null && value > 0)
|
if (m_FacialHair == null && value > 0)
|
||||||
|
|
@ -9327,15 +9192,9 @@ namespace Server
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Direction GetDirectionTo(Point2D p)
|
public Direction GetDirectionTo(Point2D p) => GetDirectionTo(p.m_X, p.m_Y);
|
||||||
{
|
|
||||||
return GetDirectionTo(p.m_X, p.m_Y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Direction GetDirectionTo(Point3D p)
|
public Direction GetDirectionTo(Point3D p) => GetDirectionTo(p.m_X, p.m_Y);
|
||||||
{
|
|
||||||
return GetDirectionTo(p.m_X, p.m_Y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Direction GetDirectionTo(IPoint2D p)
|
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