fix: Cleans up core code (#1187)

**Only one functional change**
* Fixes a bug in LogFactory where `Warning` is being logged as `Information`

Non-functional changes:
* Updates/Fixes copyright headers
* Removes namespace scopes for core files.

View with [whitespace off](https://github.com/modernuo/ModernUO/pull/1187/files?w=1).
This commit is contained in:
Kamron Batman 2022-10-10 21:47:08 -07:00 committed by GitHub
parent 0138d40bda
commit f268d5d4e2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
262 changed files with 28527 additions and 28646 deletions

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2021 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: DumpNetStates.cs *
* *
@ -15,25 +15,24 @@
using System.IO;
namespace Server.Network
namespace Server.Network;
public static class DumpNetStates
{
public static class DumpNetStates
public static void Initialize()
{
public static void Initialize()
CommandSystem.Register("DumpNetStates", AccessLevel.Administrator, DumpNetStatesCommand);
}
public static void DumpNetStatesCommand(CommandEventArgs args)
{
using var file = new StreamWriter("netstatedump.csv");
file.WriteLine("NetState, RecvTask, SendTask, ProtocolState, ParserState");
foreach (var ns in TcpServer.Instances)
{
CommandSystem.Register("DumpNetStates", AccessLevel.Administrator, DumpNetStatesCommand);
}
public static void DumpNetStatesCommand(CommandEventArgs args)
{
using var file = new StreamWriter("netstatedump.csv");
file.WriteLine("NetState, RecvTask, SendTask, ProtocolState, ParserState");
foreach (var ns in TcpServer.Instances)
{
file.WriteLine($"{ns}, {ns._protocolState}, {ns._parserState}");
}
file.WriteLine($"{ns}, {ns._protocolState}, {ns._parserState}");
}
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: NetState.ClientVersion.cs *
* *
@ -15,98 +15,97 @@
using System.Runtime.CompilerServices;
namespace Server.Network
namespace Server.Network;
public partial class NetState
{
public partial class NetState
public ProtocolChanges ProtocolChanges { get; set; }
public ClientFlags Flags { get; set; }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool HasFlag(ClientFlags flag) => (Flags & flag) != 0;
public ClientVersion Version
{
public ProtocolChanges ProtocolChanges { get; set; }
public ClientFlags Flags { get; set; }
get => _version;
set => ProtocolChanges = ProtocolChangesByVersion(_version = value);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool HasFlag(ClientFlags flag) => (Flags & flag) != 0;
public ClientVersion Version
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ProtocolChanges ProtocolChangesByVersion(ClientVersion version) =>
version switch
{
get => _version;
set => ProtocolChanges = ProtocolChangesByVersion(_version = value);
}
var v when v >= ClientVersion.Version70610 => ProtocolChanges.Version70610,
var v when v >= ClientVersion.Version70500 => ProtocolChanges.Version70500,
var v when v >= ClientVersion.Version704565 => ProtocolChanges.Version704565,
var v when v >= ClientVersion.Version70331 => ProtocolChanges.Version70331,
var v when v >= ClientVersion.Version70300 => ProtocolChanges.Version70300,
var v when v >= ClientVersion.Version70160 => ProtocolChanges.Version70160,
var v when v >= ClientVersion.Version70130 => ProtocolChanges.Version70130,
var v when v >= ClientVersion.Version7090 => ProtocolChanges.Version7090,
var v when v >= ClientVersion.Version7000 => ProtocolChanges.Version7000,
var v when v >= ClientVersion.Version60142 => ProtocolChanges.Version60142,
var v when v >= ClientVersion.Version6017 => ProtocolChanges.Version6017,
var v when v >= ClientVersion.Version6000 => ProtocolChanges.Version6000,
var v when v >= ClientVersion.Version502b => ProtocolChanges.Version502b,
var v when v >= ClientVersion.Version500a => ProtocolChanges.Version500a,
var v when v >= ClientVersion.Version407a => ProtocolChanges.Version407a,
var v when v >= ClientVersion.Version400a => ProtocolChanges.Version400a,
_ => ProtocolChanges.None
};
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ProtocolChanges ProtocolChangesByVersion(ClientVersion version) =>
version switch
{
var v when v >= ClientVersion.Version70610 => ProtocolChanges.Version70610,
var v when v >= ClientVersion.Version70500 => ProtocolChanges.Version70500,
var v when v >= ClientVersion.Version704565 => ProtocolChanges.Version704565,
var v when v >= ClientVersion.Version70331 => ProtocolChanges.Version70331,
var v when v >= ClientVersion.Version70300 => ProtocolChanges.Version70300,
var v when v >= ClientVersion.Version70160 => ProtocolChanges.Version70160,
var v when v >= ClientVersion.Version70130 => ProtocolChanges.Version70130,
var v when v >= ClientVersion.Version7090 => ProtocolChanges.Version7090,
var v when v >= ClientVersion.Version7000 => ProtocolChanges.Version7000,
var v when v >= ClientVersion.Version60142 => ProtocolChanges.Version60142,
var v when v >= ClientVersion.Version6017 => ProtocolChanges.Version6017,
var v when v >= ClientVersion.Version6000 => ProtocolChanges.Version6000,
var v when v >= ClientVersion.Version502b => ProtocolChanges.Version502b,
var v when v >= ClientVersion.Version500a => ProtocolChanges.Version500a,
var v when v >= ClientVersion.Version407a => ProtocolChanges.Version407a,
var v when v >= ClientVersion.Version400a => ProtocolChanges.Version400a,
_ => ProtocolChanges.None
};
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool HasProtocolChanges(ProtocolChanges changes) => (ProtocolChanges & changes) != 0;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool HasProtocolChanges(ProtocolChanges changes) => (ProtocolChanges & changes) != 0;
public bool NewSpellbook => HasProtocolChanges(ProtocolChanges.NewSpellbook);
public bool DamagePacket => HasProtocolChanges(ProtocolChanges.DamagePacket);
public bool Unpack => HasProtocolChanges(ProtocolChanges.Unpack);
public bool BuffIcon => HasProtocolChanges(ProtocolChanges.BuffIcon);
public bool NewHaven => HasProtocolChanges(ProtocolChanges.NewHaven);
public bool ContainerGridLines => HasProtocolChanges(ProtocolChanges.ContainerGridLines);
public bool ExtendedSupportedFeatures => HasProtocolChanges(ProtocolChanges.ExtendedSupportedFeatures);
public bool StygianAbyss => HasProtocolChanges(ProtocolChanges.StygianAbyss);
public bool HighSeas => HasProtocolChanges(ProtocolChanges.HighSeas);
public bool NewCharacterList => HasProtocolChanges(ProtocolChanges.NewCharacterList);
public bool NewCharacterCreation => HasProtocolChanges(ProtocolChanges.NewCharacterCreation);
public bool ExtendedStatus => HasProtocolChanges(ProtocolChanges.ExtendedStatus);
public bool NewMobileIncoming => HasProtocolChanges(ProtocolChanges.NewMobileIncoming);
public bool NewSecureTrading => HasProtocolChanges(ProtocolChanges.NewSecureTrading);
public bool NewSpellbook => HasProtocolChanges(ProtocolChanges.NewSpellbook);
public bool DamagePacket => HasProtocolChanges(ProtocolChanges.DamagePacket);
public bool Unpack => HasProtocolChanges(ProtocolChanges.Unpack);
public bool BuffIcon => HasProtocolChanges(ProtocolChanges.BuffIcon);
public bool NewHaven => HasProtocolChanges(ProtocolChanges.NewHaven);
public bool ContainerGridLines => HasProtocolChanges(ProtocolChanges.ContainerGridLines);
public bool ExtendedSupportedFeatures => HasProtocolChanges(ProtocolChanges.ExtendedSupportedFeatures);
public bool StygianAbyss => HasProtocolChanges(ProtocolChanges.StygianAbyss);
public bool HighSeas => HasProtocolChanges(ProtocolChanges.HighSeas);
public bool NewCharacterList => HasProtocolChanges(ProtocolChanges.NewCharacterList);
public bool NewCharacterCreation => HasProtocolChanges(ProtocolChanges.NewCharacterCreation);
public bool ExtendedStatus => HasProtocolChanges(ProtocolChanges.ExtendedStatus);
public bool NewMobileIncoming => HasProtocolChanges(ProtocolChanges.NewMobileIncoming);
public bool NewSecureTrading => HasProtocolChanges(ProtocolChanges.NewSecureTrading);
public bool IsUOTDClient =>
(Flags & ClientFlags.UOTD) != 0 || _version?.Type == ClientType.UOTD;
public bool IsUOTDClient =>
(Flags & ClientFlags.UOTD) != 0 || _version?.Type == ClientType.UOTD;
public bool IsSAClient => _version?.Type == ClientType.SA;
public bool IsSAClient => _version?.Type == ClientType.SA;
private ExpansionInfo m_Expansion;
private ExpansionInfo m_Expansion;
public ExpansionInfo ExpansionInfo
public ExpansionInfo ExpansionInfo
{
get
{
get
if (m_Expansion == null)
{
if (m_Expansion == null)
for (var i = ExpansionInfo.Table.Length - 1; i >= 0; i--)
{
for (var i = ExpansionInfo.Table.Length - 1; i >= 0; i--)
var info = ExpansionInfo.Table[i];
if (info.RequiredClient != null && Version >= info.RequiredClient || (Flags & info.ClientFlags) != 0)
{
var info = ExpansionInfo.Table[i];
if (info.RequiredClient != null && Version >= info.RequiredClient || (Flags & info.ClientFlags) != 0)
{
m_Expansion = info;
break;
}
m_Expansion = info;
break;
}
m_Expansion ??= ExpansionInfo.GetInfo(Expansion.None);
}
return m_Expansion;
m_Expansion ??= ExpansionInfo.GetInfo(Expansion.None);
}
return m_Expansion;
}
public bool SupportsExpansion(ExpansionInfo info, bool checkCoreExpansion = true) =>
info != null && (!checkCoreExpansion || (int)Core.Expansion >= info.ID) && ExpansionInfo.ID >= info.ID;
public bool SupportsExpansion(Expansion ex, bool checkCoreExpansion = true) =>
SupportsExpansion(ExpansionInfo.GetInfo(ex), checkCoreExpansion);
}
public bool SupportsExpansion(ExpansionInfo info, bool checkCoreExpansion = true) =>
info != null && (!checkCoreExpansion || (int)Core.Expansion >= info.ID) && ExpansionInfo.ID >= info.ID;
public bool SupportsExpansion(Expansion ex, bool checkCoreExpansion = true) =>
SupportsExpansion(ExpansionInfo.GetInfo(ex), checkCoreExpansion);
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: NetState.Fastwalk.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: NetState.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: ProtocolChanges.cs *
* *
@ -15,44 +15,43 @@
using System;
namespace Server.Network
{
[Flags]
public enum ProtocolChanges
{
None = 0x00000000,
NewSpellbook = 0x00000001,
DamagePacket = 0x00000002,
Unpack = 0x00000004,
BuffIcon = 0x00000008,
NewHaven = 0x00000010,
ContainerGridLines = 0x00000020,
ExtendedSupportedFeatures = 0x00000040,
StygianAbyss = 0x00000080,
HighSeas = 0x00000100,
NewCharacterList = 0x00000200,
NewCharacterCreation = 0x00000400,
ExtendedStatus = 0x00000800,
NewMobileIncoming = 0x00001000,
NewSecureTrading = 0x00002000,
UltimaStore = 0x00004000,
EndlessJourney = 0x00008000,
namespace Server.Network;
Version400a = NewSpellbook,
Version407a = Version400a | DamagePacket,
Version500a = Version407a | Unpack,
Version502b = Version500a | BuffIcon,
Version6000 = Version502b | NewHaven,
Version6017 = Version6000 | ContainerGridLines,
Version60142 = Version6017 | ExtendedSupportedFeatures,
Version7000 = Version60142 | StygianAbyss,
Version7090 = Version7000 | HighSeas,
Version70130 = Version7090 | NewCharacterList,
Version70160 = Version70130 | NewCharacterCreation,
Version70300 = Version70160 | ExtendedStatus,
Version70331 = Version70300 | NewMobileIncoming,
Version704565 = Version70331 | NewSecureTrading,
Version70500 = Version704565 | UltimaStore,
Version70610 = Version70500 | EndlessJourney
}
[Flags]
public enum ProtocolChanges
{
None = 0x00000000,
NewSpellbook = 0x00000001,
DamagePacket = 0x00000002,
Unpack = 0x00000004,
BuffIcon = 0x00000008,
NewHaven = 0x00000010,
ContainerGridLines = 0x00000020,
ExtendedSupportedFeatures = 0x00000040,
StygianAbyss = 0x00000080,
HighSeas = 0x00000100,
NewCharacterList = 0x00000200,
NewCharacterCreation = 0x00000400,
ExtendedStatus = 0x00000800,
NewMobileIncoming = 0x00001000,
NewSecureTrading = 0x00002000,
UltimaStore = 0x00004000,
EndlessJourney = 0x00008000,
Version400a = NewSpellbook,
Version407a = Version400a | DamagePacket,
Version500a = Version407a | Unpack,
Version502b = Version500a | BuffIcon,
Version6000 = Version502b | NewHaven,
Version6017 = Version6000 | ContainerGridLines,
Version60142 = Version6017 | ExtendedSupportedFeatures,
Version7000 = Version60142 | StygianAbyss,
Version7090 = Version7000 | HighSeas,
Version70130 = Version7090 | NewCharacterList,
Version70160 = Version70130 | NewCharacterCreation,
Version70300 = Version70160 | ExtendedStatus,
Version70331 = Version70300 | NewMobileIncoming,
Version704565 = Version70331 | NewSecureTrading,
Version70500 = Version704565 | UltimaStore,
Version70610 = Version70500 | EndlessJourney
}

View file

@ -1,114 +1,90 @@
using System;
using System.Buffers;
namespace Server.Network
namespace Server.Network;
/// <summary>
/// Handles outgoing packet compression for the network.
/// </summary>
public static class NetworkCompression
{
/// <summary>
/// Handles outgoing packet compression for the network.
/// </summary>
public static class NetworkCompression
private const int CountIndex = 0;
private const int ValueIndex = 1;
// UO packets may not exceed 64kb in length
public const int BufferSize = 0x10000;
// Optimal compression ratio is 2 / 8; worst compression ratio is 11 / 8
private const int MinimalCodeLength = 2;
private const int MaximalCodeLength = 11;
// Fixed overhead, in bits, per compression call
private const int TerminalCodeLength = 4;
// If our input exceeds this length, we cannot possibly compress it within the buffer
private const int DefiniteOverflow = (BufferSize * 8 - TerminalCodeLength) / MinimalCodeLength;
private static readonly int[] _huffmanTable =
{
private const int CountIndex = 0;
private const int ValueIndex = 1;
0x2, 0x000, 0x5, 0x01F, 0x6, 0x022, 0x7, 0x034, 0x7, 0x075, 0x6, 0x028, 0x6, 0x03B, 0x7, 0x032,
0x8, 0x0E0, 0x8, 0x062, 0x7, 0x056, 0x8, 0x079, 0x9, 0x19D, 0x8, 0x097, 0x6, 0x02A, 0x7, 0x057,
0x8, 0x071, 0x8, 0x05B, 0x9, 0x1CC, 0x8, 0x0A7, 0x7, 0x025, 0x7, 0x04F, 0x8, 0x066, 0x8, 0x07D,
0x9, 0x191, 0x9, 0x1CE, 0x7, 0x03F, 0x9, 0x090, 0x8, 0x059, 0x8, 0x07B, 0x8, 0x091, 0x8, 0x0C6,
0x6, 0x02D, 0x9, 0x186, 0x8, 0x06F, 0x9, 0x093, 0xA, 0x1CC, 0x8, 0x05A, 0xA, 0x1AE, 0xA, 0x1C0,
0x9, 0x148, 0x9, 0x14A, 0x9, 0x082, 0xA, 0x19F, 0x9, 0x171, 0x9, 0x120, 0x9, 0x0E7, 0xA, 0x1F3,
0x9, 0x14B, 0x9, 0x100, 0x9, 0x190, 0x6, 0x013, 0x9, 0x161, 0x9, 0x125, 0x9, 0x133, 0x9, 0x195,
0x9, 0x173, 0x9, 0x1CA, 0x9, 0x086, 0x9, 0x1E9, 0x9, 0x0DB, 0x9, 0x1EC, 0x9, 0x08B, 0x9, 0x085,
0x5, 0x00A, 0x8, 0x096, 0x8, 0x09C, 0x9, 0x1C3, 0x9, 0x19C, 0x9, 0x08F, 0x9, 0x18F, 0x9, 0x091,
0x9, 0x087, 0x9, 0x0C6, 0x9, 0x177, 0x9, 0x089, 0x9, 0x0D6, 0x9, 0x08C, 0x9, 0x1EE, 0x9, 0x1EB,
0x9, 0x084, 0x9, 0x164, 0x9, 0x175, 0x9, 0x1CD, 0x8, 0x05E, 0x9, 0x088, 0x9, 0x12B, 0x9, 0x172,
0x9, 0x10A, 0x9, 0x08D, 0x9, 0x13A, 0x9, 0x11C, 0xA, 0x1E1, 0xA, 0x1E0, 0x9, 0x187, 0xA, 0x1DC,
0xA, 0x1DF, 0x7, 0x074, 0x9, 0x19F, 0x8, 0x08D, 0x8, 0x0E4, 0x7, 0x079, 0x9, 0x0EA, 0x9, 0x0E1,
0x8, 0x040, 0x7, 0x041, 0x9, 0x10B, 0x9, 0x0B0, 0x8, 0x06A, 0x8, 0x0C1, 0x7, 0x071, 0x7, 0x078,
0x8, 0x0B1, 0x9, 0x14C, 0x7, 0x043, 0x8, 0x076, 0x7, 0x066, 0x7, 0x04D, 0x9, 0x08A, 0x6, 0x02F,
0x8, 0x0C9, 0x9, 0x0CE, 0x9, 0x149, 0x9, 0x160, 0xA, 0x1BA, 0xA, 0x19E, 0xA, 0x39F, 0x9, 0x0E5,
0x9, 0x194, 0x9, 0x184, 0x9, 0x126, 0x7, 0x030, 0x8, 0x06C, 0x9, 0x121, 0x9, 0x1E8, 0xA, 0x1C1,
0xA, 0x11D, 0xA, 0x163, 0xA, 0x385, 0xA, 0x3DB, 0xA, 0x17D, 0xA, 0x106, 0xA, 0x397, 0xA, 0x24E,
0x7, 0x02E, 0x8, 0x098, 0xA, 0x33C, 0xA, 0x32E, 0xA, 0x1E9, 0x9, 0x0BF, 0xA, 0x3DF, 0xA, 0x1DD,
0xA, 0x32D, 0xA, 0x2ED, 0xA, 0x30B, 0xA, 0x107, 0xA, 0x2E8, 0xA, 0x3DE, 0xA, 0x125, 0xA, 0x1E8,
0x9, 0x0E9, 0xA, 0x1CD, 0xA, 0x1B5, 0x9, 0x165, 0xA, 0x232, 0xA, 0x2E1, 0xB, 0x3AE, 0xB, 0x3C6,
0xB, 0x3E2, 0xA, 0x205, 0xA, 0x29A, 0xA, 0x248, 0xA, 0x2CD, 0xA, 0x23B, 0xB, 0x3C5, 0xA, 0x251,
0xA, 0x2E9, 0xA, 0x252, 0x9, 0x1EA, 0xB, 0x3A0, 0xB, 0x391, 0xA, 0x23C, 0xB, 0x392, 0xB, 0x3D5,
0xA, 0x233, 0xA, 0x2CC, 0xB, 0x390, 0xA, 0x1BB, 0xB, 0x3A1, 0xB, 0x3C4, 0xA, 0x211, 0xA, 0x203,
0x9, 0x12A, 0xA, 0x231, 0xB, 0x3E0, 0xA, 0x29B, 0xB, 0x3D7, 0xA, 0x202, 0xB, 0x3AD, 0xA, 0x213,
0xA, 0x253, 0xA, 0x32C, 0xA, 0x23D, 0xA, 0x23F, 0xA, 0x32F, 0xA, 0x11C, 0xA, 0x384, 0xA, 0x31C,
0xA, 0x17C, 0xA, 0x30A, 0xA, 0x2E0, 0xA, 0x276, 0xA, 0x250, 0xB, 0x3E3, 0xA, 0x396, 0xA, 0x18F,
0xA, 0x204, 0xA, 0x206, 0xA, 0x230, 0xA, 0x265, 0xA, 0x212, 0xA, 0x23E, 0xB, 0x3AC, 0xB, 0x393,
0xB, 0x3E1, 0xA, 0x1DE, 0xB, 0x3D6, 0xA, 0x31D, 0xB, 0x3E5, 0xB, 0x3E4, 0xA, 0x207, 0xB, 0x3C7,
0xA, 0x277, 0xB, 0x3D4, 0x8, 0x0C0, 0xA, 0x162, 0xA, 0x3DA, 0xA, 0x124, 0xA, 0x1B4, 0xA, 0x264,
0xA, 0x33D, 0xA, 0x1D1, 0xA, 0x1AF, 0xA, 0x39E, 0xA, 0x24F, 0xB, 0x373, 0xA, 0x249, 0xB, 0x372,
0x9, 0x167, 0xA, 0x210, 0xA, 0x23A, 0xA, 0x1B8, 0xB, 0x3AF, 0xA, 0x18E, 0xA, 0x2EC, 0x7, 0x062,
0x4, 0x00D
};
// UO packets may not exceed 64kb in length
public const int BufferSize = 0x10000;
public static void Compress(ReadOnlySpan<byte> input, CircularBuffer<byte> output, out int length)
{
length = Compress(input, output);
}
// Optimal compression ratio is 2 / 8; worst compression ratio is 11 / 8
private const int MinimalCodeLength = 2;
private const int MaximalCodeLength = 11;
// Fixed overhead, in bits, per compression call
private const int TerminalCodeLength = 4;
// If our input exceeds this length, we cannot possibly compress it within the buffer
private const int DefiniteOverflow = (BufferSize * 8 - TerminalCodeLength) / MinimalCodeLength;
private static readonly int[] _huffmanTable =
public static int Compress(ReadOnlySpan<byte> input, CircularBuffer<byte> output)
{
if (input.Length > DefiniteOverflow)
{
0x2, 0x000, 0x5, 0x01F, 0x6, 0x022, 0x7, 0x034, 0x7, 0x075, 0x6, 0x028, 0x6, 0x03B, 0x7, 0x032,
0x8, 0x0E0, 0x8, 0x062, 0x7, 0x056, 0x8, 0x079, 0x9, 0x19D, 0x8, 0x097, 0x6, 0x02A, 0x7, 0x057,
0x8, 0x071, 0x8, 0x05B, 0x9, 0x1CC, 0x8, 0x0A7, 0x7, 0x025, 0x7, 0x04F, 0x8, 0x066, 0x8, 0x07D,
0x9, 0x191, 0x9, 0x1CE, 0x7, 0x03F, 0x9, 0x090, 0x8, 0x059, 0x8, 0x07B, 0x8, 0x091, 0x8, 0x0C6,
0x6, 0x02D, 0x9, 0x186, 0x8, 0x06F, 0x9, 0x093, 0xA, 0x1CC, 0x8, 0x05A, 0xA, 0x1AE, 0xA, 0x1C0,
0x9, 0x148, 0x9, 0x14A, 0x9, 0x082, 0xA, 0x19F, 0x9, 0x171, 0x9, 0x120, 0x9, 0x0E7, 0xA, 0x1F3,
0x9, 0x14B, 0x9, 0x100, 0x9, 0x190, 0x6, 0x013, 0x9, 0x161, 0x9, 0x125, 0x9, 0x133, 0x9, 0x195,
0x9, 0x173, 0x9, 0x1CA, 0x9, 0x086, 0x9, 0x1E9, 0x9, 0x0DB, 0x9, 0x1EC, 0x9, 0x08B, 0x9, 0x085,
0x5, 0x00A, 0x8, 0x096, 0x8, 0x09C, 0x9, 0x1C3, 0x9, 0x19C, 0x9, 0x08F, 0x9, 0x18F, 0x9, 0x091,
0x9, 0x087, 0x9, 0x0C6, 0x9, 0x177, 0x9, 0x089, 0x9, 0x0D6, 0x9, 0x08C, 0x9, 0x1EE, 0x9, 0x1EB,
0x9, 0x084, 0x9, 0x164, 0x9, 0x175, 0x9, 0x1CD, 0x8, 0x05E, 0x9, 0x088, 0x9, 0x12B, 0x9, 0x172,
0x9, 0x10A, 0x9, 0x08D, 0x9, 0x13A, 0x9, 0x11C, 0xA, 0x1E1, 0xA, 0x1E0, 0x9, 0x187, 0xA, 0x1DC,
0xA, 0x1DF, 0x7, 0x074, 0x9, 0x19F, 0x8, 0x08D, 0x8, 0x0E4, 0x7, 0x079, 0x9, 0x0EA, 0x9, 0x0E1,
0x8, 0x040, 0x7, 0x041, 0x9, 0x10B, 0x9, 0x0B0, 0x8, 0x06A, 0x8, 0x0C1, 0x7, 0x071, 0x7, 0x078,
0x8, 0x0B1, 0x9, 0x14C, 0x7, 0x043, 0x8, 0x076, 0x7, 0x066, 0x7, 0x04D, 0x9, 0x08A, 0x6, 0x02F,
0x8, 0x0C9, 0x9, 0x0CE, 0x9, 0x149, 0x9, 0x160, 0xA, 0x1BA, 0xA, 0x19E, 0xA, 0x39F, 0x9, 0x0E5,
0x9, 0x194, 0x9, 0x184, 0x9, 0x126, 0x7, 0x030, 0x8, 0x06C, 0x9, 0x121, 0x9, 0x1E8, 0xA, 0x1C1,
0xA, 0x11D, 0xA, 0x163, 0xA, 0x385, 0xA, 0x3DB, 0xA, 0x17D, 0xA, 0x106, 0xA, 0x397, 0xA, 0x24E,
0x7, 0x02E, 0x8, 0x098, 0xA, 0x33C, 0xA, 0x32E, 0xA, 0x1E9, 0x9, 0x0BF, 0xA, 0x3DF, 0xA, 0x1DD,
0xA, 0x32D, 0xA, 0x2ED, 0xA, 0x30B, 0xA, 0x107, 0xA, 0x2E8, 0xA, 0x3DE, 0xA, 0x125, 0xA, 0x1E8,
0x9, 0x0E9, 0xA, 0x1CD, 0xA, 0x1B5, 0x9, 0x165, 0xA, 0x232, 0xA, 0x2E1, 0xB, 0x3AE, 0xB, 0x3C6,
0xB, 0x3E2, 0xA, 0x205, 0xA, 0x29A, 0xA, 0x248, 0xA, 0x2CD, 0xA, 0x23B, 0xB, 0x3C5, 0xA, 0x251,
0xA, 0x2E9, 0xA, 0x252, 0x9, 0x1EA, 0xB, 0x3A0, 0xB, 0x391, 0xA, 0x23C, 0xB, 0x392, 0xB, 0x3D5,
0xA, 0x233, 0xA, 0x2CC, 0xB, 0x390, 0xA, 0x1BB, 0xB, 0x3A1, 0xB, 0x3C4, 0xA, 0x211, 0xA, 0x203,
0x9, 0x12A, 0xA, 0x231, 0xB, 0x3E0, 0xA, 0x29B, 0xB, 0x3D7, 0xA, 0x202, 0xB, 0x3AD, 0xA, 0x213,
0xA, 0x253, 0xA, 0x32C, 0xA, 0x23D, 0xA, 0x23F, 0xA, 0x32F, 0xA, 0x11C, 0xA, 0x384, 0xA, 0x31C,
0xA, 0x17C, 0xA, 0x30A, 0xA, 0x2E0, 0xA, 0x276, 0xA, 0x250, 0xB, 0x3E3, 0xA, 0x396, 0xA, 0x18F,
0xA, 0x204, 0xA, 0x206, 0xA, 0x230, 0xA, 0x265, 0xA, 0x212, 0xA, 0x23E, 0xB, 0x3AC, 0xB, 0x393,
0xB, 0x3E1, 0xA, 0x1DE, 0xB, 0x3D6, 0xA, 0x31D, 0xB, 0x3E5, 0xB, 0x3E4, 0xA, 0x207, 0xB, 0x3C7,
0xA, 0x277, 0xB, 0x3D4, 0x8, 0x0C0, 0xA, 0x162, 0xA, 0x3DA, 0xA, 0x124, 0xA, 0x1B4, 0xA, 0x264,
0xA, 0x33D, 0xA, 0x1D1, 0xA, 0x1AF, 0xA, 0x39E, 0xA, 0x24F, 0xB, 0x373, 0xA, 0x249, 0xB, 0x372,
0x9, 0x167, 0xA, 0x210, 0xA, 0x23A, 0xA, 0x1B8, 0xB, 0x3AF, 0xA, 0x18E, 0xA, 0x2EC, 0x7, 0x062,
0x4, 0x00D
};
public static void Compress(ReadOnlySpan<byte> input, CircularBuffer<byte> output, out int length)
{
length = Compress(input, output);
return 0;
}
public static int Compress(ReadOnlySpan<byte> input, CircularBuffer<byte> output)
int bitCount = 0;
int bitValue = 0;
int inputIdx = 0;
int outputIdx = 0;
while (inputIdx < input.Length)
{
if (input.Length > DefiniteOverflow)
{
return 0;
}
int i = input[inputIdx++] << 1;
int bitCount = 0;
int bitValue = 0;
int inputIdx = 0;
int outputIdx = 0;
while (inputIdx < input.Length)
{
int i = input[inputIdx++] << 1;
bitCount += _huffmanTable[i];
bitValue = (bitValue << _huffmanTable[i]) | _huffmanTable[i + 1];
while (bitCount >= 8)
{
bitCount -= 8;
if (output.Length < outputIdx + 1)
{
return 0;
}
output[outputIdx++] = (byte)(bitValue >> bitCount);
}
}
// terminal code
bitCount += _huffmanTable[0x200];
bitValue = (bitValue << _huffmanTable[0x200]) | _huffmanTable[0x201];
// align on byte boundary
if ((bitCount & 7) != 0)
{
bitValue <<= 8 - (bitCount & 7);
bitCount += 8 - (bitCount & 7);
}
bitCount += _huffmanTable[i];
bitValue = (bitValue << _huffmanTable[i]) | _huffmanTable[i + 1];
while (bitCount >= 8)
{
@ -121,53 +97,53 @@ namespace Server.Network
output[outputIdx++] = (byte)(bitValue >> bitCount);
}
return outputIdx;
}
public static int Compress(CircularBuffer<byte> input, CircularBuffer<byte> output)
// terminal code
bitCount += _huffmanTable[0x200];
bitValue = (bitValue << _huffmanTable[0x200]) | _huffmanTable[0x201];
// align on byte boundary
if ((bitCount & 7) != 0)
{
if (input.Length > DefiniteOverflow)
bitValue <<= 8 - (bitCount & 7);
bitCount += 8 - (bitCount & 7);
}
while (bitCount >= 8)
{
bitCount -= 8;
if (output.Length < outputIdx + 1)
{
return 0;
}
int bitCount = 0;
int bitValue = 0;
output[outputIdx++] = (byte)(bitValue >> bitCount);
}
int inputIdx = 0;
int outputIdx = 0;
return outputIdx;
}
while (inputIdx < input.Length)
{
int i = input[inputIdx++] << 1;
public static int Compress(CircularBuffer<byte> input, CircularBuffer<byte> output)
{
if (input.Length > DefiniteOverflow)
{
return 0;
}
bitCount += _huffmanTable[i];
bitValue = (bitValue << _huffmanTable[i]) | _huffmanTable[i + 1];
int bitCount = 0;
int bitValue = 0;
while (bitCount >= 8)
{
bitCount -= 8;
int inputIdx = 0;
int outputIdx = 0;
if (output.Length < outputIdx + 1)
{
return 0;
}
while (inputIdx < input.Length)
{
int i = input[inputIdx++] << 1;
output[outputIdx++] = (byte)(bitValue >> bitCount);
}
}
// terminal code
bitCount += _huffmanTable[0x200];
bitValue = (bitValue << _huffmanTable[0x200]) | _huffmanTable[0x201];
// align on byte boundary
if ((bitCount & 7) != 0)
{
bitValue <<= 8 - (bitCount & 7);
bitCount += 8 - (bitCount & 7);
}
bitCount += _huffmanTable[i];
bitValue = (bitValue << _huffmanTable[i]) | _huffmanTable[i + 1];
while (bitCount >= 8)
{
@ -180,53 +156,53 @@ namespace Server.Network
output[outputIdx++] = (byte)(bitValue >> bitCount);
}
return outputIdx;
}
public static int Compress(ReadOnlySpan<byte> input, Span<byte> output)
// terminal code
bitCount += _huffmanTable[0x200];
bitValue = (bitValue << _huffmanTable[0x200]) | _huffmanTable[0x201];
// align on byte boundary
if ((bitCount & 7) != 0)
{
if (input.Length > DefiniteOverflow)
bitValue <<= 8 - (bitCount & 7);
bitCount += 8 - (bitCount & 7);
}
while (bitCount >= 8)
{
bitCount -= 8;
if (output.Length < outputIdx + 1)
{
return 0;
}
int bitCount = 0;
int bitValue = 0;
output[outputIdx++] = (byte)(bitValue >> bitCount);
}
int inputIdx = 0;
int outputIdx = 0;
return outputIdx;
}
while (inputIdx < input.Length)
{
int i = input[inputIdx++] << 1;
public static int Compress(ReadOnlySpan<byte> input, Span<byte> output)
{
if (input.Length > DefiniteOverflow)
{
return 0;
}
bitCount += _huffmanTable[i];
bitValue = (bitValue << _huffmanTable[i]) | _huffmanTable[i + 1];
int bitCount = 0;
int bitValue = 0;
while (bitCount >= 8)
{
bitCount -= 8;
int inputIdx = 0;
int outputIdx = 0;
if (output.Length < outputIdx + 1)
{
return 0;
}
while (inputIdx < input.Length)
{
int i = input[inputIdx++] << 1;
output[outputIdx++] = (byte)(bitValue >> bitCount);
}
}
// terminal code
bitCount += _huffmanTable[0x200];
bitValue = (bitValue << _huffmanTable[0x200]) | _huffmanTable[0x201];
// align on byte boundary
if ((bitCount & 7) != 0)
{
bitValue <<= 8 - (bitCount & 7);
bitCount += 8 - (bitCount & 7);
}
bitCount += _huffmanTable[i];
bitValue = (bitValue << _huffmanTable[i]) | _huffmanTable[i + 1];
while (bitCount >= 8)
{
@ -239,8 +215,31 @@ namespace Server.Network
output[outputIdx++] = (byte)(bitValue >> bitCount);
}
return outputIdx;
}
// terminal code
bitCount += _huffmanTable[0x200];
bitValue = (bitValue << _huffmanTable[0x200]) | _huffmanTable[0x201];
// align on byte boundary
if ((bitCount & 7) != 0)
{
bitValue <<= 8 - (bitCount & 7);
bitCount += 8 - (bitCount & 7);
}
while (bitCount >= 8)
{
bitCount -= 8;
if (output.Length < outputIdx + 1)
{
return 0;
}
output[outputIdx++] = (byte)(bitValue >> bitCount);
}
return outputIdx;
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: PacketUtilities.cs *
* *
@ -18,51 +18,50 @@ using System.Buffers;
using System.IO;
using System.Runtime.CompilerServices;
namespace Server.Network
namespace Server.Network;
public static class PacketUtilities
{
public static class PacketUtilities
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void WritePacketLength(this ref CircularBufferWriter writer)
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void WritePacketLength(this ref CircularBufferWriter writer)
{
var length = writer.Position;
writer.Seek(1, SeekOrigin.Begin);
writer.Write((ushort)length);
writer.Seek(length, SeekOrigin.Begin);
}
var length = writer.Position;
writer.Seek(1, SeekOrigin.Begin);
writer.Write((ushort)length);
writer.Seek(length, SeekOrigin.Begin);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void WritePacketLength(this ref SpanWriter writer)
{
writer.Seek(1, SeekOrigin.Begin);
writer.Write((ushort)writer.BytesWritten);
writer.Seek(0, SeekOrigin.End);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void WritePacketLength(this ref SpanWriter writer)
{
writer.Seek(1, SeekOrigin.Begin);
writer.Write((ushort)writer.BytesWritten);
writer.Seek(0, SeekOrigin.End);
}
// If LOCAL INIT is off, then stack/heap allocations have garbage data
// Initializes the first byte (Packet ID) so it can be used as a flag.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<byte> InitializePacket(this Span<byte> buffer)
{
// If LOCAL INIT is off, then stack/heap allocations have garbage data
// Initializes the first byte (Packet ID) so it can be used as a flag.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<byte> InitializePacket(this Span<byte> buffer)
{
#if NO_LOCAL_INIT
if (buffer != null)
{
buffer[0] = 0;
}
#endif
return buffer;
}
return buffer;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<byte> InitializePackets(this Span<byte> buffer, int width)
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<byte> InitializePackets(this Span<byte> buffer, int width)
{
#if NO_LOCAL_INIT
for (var i = 0; i < buffer.Length; i += width)
{
buffer[i] = 0;
}
#endif
return buffer;
}
return buffer;
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: IncomingAccountPackets.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: IncomingEntityPackets.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: IncomingHousePackets.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: IncomingItemPackets.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2021 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: IncomingMessagePackets.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: IncomingMobilePackets.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: IncomingMovementPackets.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: IncomingPlayerPackets.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: IncomingTargetingPackets.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: IncomingVendorPackets.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: OutgoingAccountPackets.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: OutgoingCombatPackets.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: OutgoingContainerPackets.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: OutgoingDamagePackets.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: OutgoingEffectPackets.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: OutgoingEntityPackets.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: OutgoingEquipmentPackets.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: OutgoingItemPackets.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: OutgoingLightPackets.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: OutgoingMapPackets.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: OutgoingMessagePackets.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: OutgoingMobilePackets.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: OutgoingMovementPackets.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: OutgoingPlayerPackets.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: OutgoingSecureTradePackets.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: OutgoingTargetPackets.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: OutgoingVendorBuyPackets.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: OutgoingVendorSellPackets.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: Pipe.cs *
* *
@ -17,489 +17,488 @@ using System;
using System.Runtime.CompilerServices;
using System.Threading;
namespace Server.Network
namespace Server.Network;
public interface IPipeTask<T> : INotifyCompletion
{
public interface IPipeTask<T> : INotifyCompletion
public IPipeTask<T> GetAwaiter();
public bool IsCompleted { get; }
public T GetResult();
}
public class Pipe<T>
{
public struct Result
{
public IPipeTask<T> GetAwaiter();
public ArraySegment<T>[] Buffer { get; }
public bool IsClosed { get; set; }
public bool IsCompleted { get; }
public T GetResult();
}
public class Pipe<T>
{
public struct Result
public int Length
{
public ArraySegment<T>[] Buffer { get; }
public bool IsClosed { get; set; }
public int Length
get
{
get
var length = 0;
for (int i = 0; i < Buffer.Length; i++)
{
var length = 0;
for (int i = 0; i < Buffer.Length; i++)
{
length += Buffer[i].Count;
}
return length;
length += Buffer[i].Count;
}
return length;
}
}
public void CopyFrom(ReadOnlySpan<T> bytes)
{
var remaining = bytes.Length;
var offset = 0;
if (remaining == 0)
{
return;
}
public void CopyFrom(ReadOnlySpan<T> bytes)
for (int i = 0; i < 2; i++)
{
var remaining = bytes.Length;
var offset = 0;
var buffer = Buffer[i];
var sz = Math.Min(remaining, buffer.Count);
bytes.Slice(offset, sz).CopyTo(buffer);
remaining -= sz;
offset += sz;
if (remaining == 0)
{
return;
}
for (int i = 0; i < 2; i++)
{
var buffer = Buffer[i];
var sz = Math.Min(remaining, buffer.Count);
bytes.Slice(offset, sz).CopyTo(buffer);
remaining -= sz;
offset += sz;
if (remaining == 0)
{
return;
}
}
throw new OutOfMemoryException();
}
public Result(int segments)
{
IsClosed = false;
Buffer = new ArraySegment<T>[segments];
}
throw new OutOfMemoryException();
}
public class PipeWriter : IPipeTask<Result>
public Result(int segments)
{
private readonly Pipe<T> _pipe;
IsClosed = false;
Buffer = new ArraySegment<T>[segments];
}
}
private Result _result = new(2);
public class PipeWriter : IPipeTask<Result>
{
private readonly Pipe<T> _pipe;
internal PipeWriter(Pipe<T> pipe) => _pipe = pipe;
private Result _result = new(2);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint GetAvailable()
internal PipeWriter(Pipe<T> pipe) => _pipe = pipe;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint GetAvailable()
{
var read = _pipe._readIdx;
var write = _pipe._writeIdx;
if (read <= write)
{
var read = _pipe._readIdx;
var write = _pipe._writeIdx;
if (read <= write)
if (read == 0)
{
if (read == 0)
{
return _pipe.Size - write - 1;
}
return _pipe.Size - write + (read - 1);
return _pipe.Size - write - 1;
}
return read - write - 1;
return _pipe.Size - write + (read - 1);
}
public Result TryGetMemory()
return read - write - 1;
}
public Result TryGetMemory()
{
var read = _pipe._readIdx;
var write = _pipe._writeIdx;
_result.IsClosed = _pipe._closed;
if (read <= write)
{
var read = _pipe._readIdx;
var write = _pipe._writeIdx;
var readZero = read == 0;
var sz = _pipe.Size - write - (readZero ? 1 : 0);
_result.IsClosed = _pipe._closed;
_result.Buffer[0] = sz == 0 ? ArraySegment<T>.Empty : new ArraySegment<T>(_pipe._buffer, (int)write, (int)sz);
_result.Buffer[1] = readZero ? ArraySegment<T>.Empty : new ArraySegment<T>(_pipe._buffer, 0, (int)read - 1);
}
else
{
var sz = read - write - 1;
if (read <= write)
{
var readZero = read == 0;
var sz = _pipe.Size - write - (readZero ? 1 : 0);
_result.Buffer[0] = sz == 0 ? ArraySegment<T>.Empty : new ArraySegment<T>(_pipe._buffer, (int)write, (int)sz);
_result.Buffer[1] = readZero ? ArraySegment<T>.Empty : new ArraySegment<T>(_pipe._buffer, 0, (int)read - 1);
}
else
{
var sz = read - write - 1;
_result.Buffer[0] = sz == 0 ? ArraySegment<T>.Empty : new ArraySegment<T>(_pipe._buffer, (int)write, (int)sz);
_result.Buffer[1] = ArraySegment<T>.Empty;
}
return _result;
_result.Buffer[0] = sz == 0 ? ArraySegment<T>.Empty : new ArraySegment<T>(_pipe._buffer, (int)write, (int)sz);
_result.Buffer[1] = ArraySegment<T>.Empty;
}
public IPipeTask<Result> GetMemory()
{
if (_pipe._writeAwaitBeginning)
{
throw new Exception("Double await on writer");
}
return _result;
}
return this;
public IPipeTask<Result> GetMemory()
{
if (_pipe._writeAwaitBeginning)
{
throw new Exception("Double await on writer");
}
public void Advance(uint count)
return this;
}
public void Advance(uint count)
{
var read = _pipe._readIdx;
var write = _pipe._writeIdx;
if (count == 0)
{
var read = _pipe._readIdx;
var write = _pipe._writeIdx;
return;
}
if (count == 0)
{
return;
}
if (count > _pipe.Size - 1)
{
throw new InvalidOperationException();
}
if (count > _pipe.Size - 1)
if (read <= write)
{
if (count > read + _pipe.Size - write - 1)
{
throw new InvalidOperationException();
}
if (read <= write)
var sz = Math.Min(count, _pipe.Size - write);
write += sz;
if (write > _pipe.Size - 1)
{
if (count > read + _pipe.Size - write - 1)
write = 0;
}
count -= sz;
if (count > 0)
{
if (count >= read)
{
throw new InvalidOperationException();
}
var sz = Math.Min(count, _pipe.Size - write);
write += sz;
if (write > _pipe.Size - 1)
{
write = 0;
}
count -= sz;
if (count > 0)
{
if (count >= read)
{
throw new InvalidOperationException();
}
write = count;
}
write = count;
}
else
{
if (count > read - write - 1)
{
throw new InvalidOperationException();
}
write += count;
}
// It's never valid to advance the write pointer to become equal to
// the read pointer. Check that here.
if (write == read)
{
throw new InvalidOperationException("Write index equals read index after advance");
}
_pipe._writeIdx = write;
}
public void Close()
else
{
_pipe._closed = true;
var waiting = _pipe._readAwaitBeginning;
if (!waiting)
if (count > read - write - 1)
{
return;
throw new InvalidOperationException();
}
Action continuation;
do
{
continuation = _pipe._readContinuation;
} while (continuation == null);
_pipe._readContinuation = null;
_pipe._readAwaitBeginning = false;
ThreadPool.UnsafeQueueUserWorkItem(_ => continuation(), true);
write += count;
}
public void Flush()
// It's never valid to advance the write pointer to become equal to
// the read pointer. Check that here.
if (write == read)
{
if (_pipe._readIdx == _pipe._writeIdx)
{
return;
}
var waiting = _pipe._readAwaitBeginning;
if (!waiting)
{
return;
}
Action continuation;
do
{
continuation = _pipe._readContinuation;
} while (continuation == null);
_pipe._readContinuation = null;
_pipe._readAwaitBeginning = false;
ThreadPool.UnsafeQueueUserWorkItem(_ => continuation(), true);
throw new InvalidOperationException("Write index equals read index after advance");
}
#region Awaitable
// The following makes it possible to await the writer. Do not use any of this directly.
public IPipeTask<Result> GetAwaiter() => this;
public bool IsCompleted
{
get
{
if (GetAvailable() > 0)
{
return true;
}
if (_pipe._closed)
{
return true;
}
_pipe._writeAwaitBeginning = true;
return false;
}
}
public Result GetResult() => TryGetMemory();
public void OnCompleted(Action continuation) => _pipe._writeContinuation = continuation;
#endregion
_pipe._writeIdx = write;
}
public class PipeReader : IPipeTask<Result>
public void Close()
{
private readonly Pipe<T> _pipe;
_pipe._closed = true;
private Result _result = new(2);
var waiting = _pipe._readAwaitBeginning;
internal PipeReader(Pipe<T> pipe) => _pipe = pipe;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint GetAvailable()
if (!waiting)
{
var read = _pipe._readIdx;
var write = _pipe._writeIdx;
if (read <= write)
{
return write - read;
}
return write + _pipe.Size - read;
return;
}
public Result TryRead()
Action continuation;
do
{
var read = _pipe._readIdx;
var write = _pipe._writeIdx;
continuation = _pipe._readContinuation;
} while (continuation == null);
_result.IsClosed = _pipe._closed;
_pipe._readContinuation = null;
_pipe._readAwaitBeginning = false;
if (read <= write)
{
_result.Buffer[0] = write - read == 0 ? ArraySegment<T>.Empty : new ArraySegment<T>(_pipe._buffer, (int)read, (int)(write - read));
_result.Buffer[1] = ArraySegment<T>.Empty;
}
else
{
_result.Buffer[0] = _pipe.Size - read == 0 ? ArraySegment<T>.Empty : new ArraySegment<T>(_pipe._buffer, (int)read, (int)(_pipe.Size - read));
_result.Buffer[1] = write == 0 ? ArraySegment<T>.Empty : new ArraySegment<T>(_pipe._buffer, 0, (int)write);
}
return _result;
}
public IPipeTask<Result> Read()
{
if (_pipe._readAwaitBeginning)
{
throw new Exception("Double await on reader");
}
return this;
}
public void Advance(uint count)
{
var read = _pipe._readIdx;
var write = _pipe._writeIdx;
if (read <= write)
{
if (count > write - read)
{
throw new InvalidOperationException();
}
read += count;
}
else
{
var sz = Math.Min(count, _pipe.Size - read);
read += sz;
if (read > _pipe.Size - 1)
{
read = 0;
}
count -= sz;
if (count > 0)
{
if (count > write)
{
throw new InvalidOperationException();
}
read = count;
}
}
_pipe._readIdx = read;
}
public void Commit()
{
if (_pipe._readIdx == ((_pipe._writeIdx + 1) & (_pipe.Size - 1)))
{
return;
}
var waiting = _pipe._writeAwaitBeginning;
if (!waiting)
{
return;
}
Action continuation;
do
{
continuation = _pipe._writeContinuation;
} while (continuation == null);
_pipe._writeContinuation = null;
_pipe._writeAwaitBeginning = false;
ThreadPool.UnsafeQueueUserWorkItem(_ => continuation(), true);
}
public void Close()
{
_pipe._closed = true;
var waiting = _pipe._writeAwaitBeginning;
if (!waiting)
{
return;
}
Action continuation;
do
{
continuation = _pipe._writeContinuation;
} while (continuation == null);
_pipe._writeContinuation = null;
_pipe._writeAwaitBeginning = false;
ThreadPool.UnsafeQueueUserWorkItem(_ => continuation(), true);
}
#region Awaitable
// The following makes it possible to await the reader. Do not use any of this directly.
public IPipeTask<Result> GetAwaiter() => this;
public bool IsCompleted
{
get
{
if (GetAvailable() > 0)
{
return true;
}
if (_pipe._closed)
{
return true;
}
_pipe._readAwaitBeginning = true;
return false;
}
}
public Result GetResult() => TryRead();
public void OnCompleted(Action continuation) => _pipe._readContinuation = continuation;
#endregion
ThreadPool.UnsafeQueueUserWorkItem(_ => continuation(), true);
}
private readonly T[] _buffer;
private volatile uint _writeIdx;
private volatile uint _readIdx;
private bool _closed;
public PipeWriter Writer { get; }
public PipeReader Reader { get; }
public uint Size => (uint)_buffer.Length;
public Pipe(T[] buf)
public void Flush()
{
// Test if the buffer is a power of two
if (buf.Length == 0 || (buf.Length & (buf.Length - 1)) != 0)
if (_pipe._readIdx == _pipe._writeIdx)
{
throw new ArgumentOutOfRangeException(nameof(buf), "Pipe buffers must have a length that is a power of two");
return;
}
_buffer = buf;
_writeIdx = 0;
_readIdx = 0;
_closed = false;
var waiting = _pipe._readAwaitBeginning;
Writer = new PipeWriter(this);
Reader = new PipeReader(this);
if (!waiting)
{
return;
}
Action continuation;
do
{
continuation = _pipe._readContinuation;
} while (continuation == null);
_pipe._readContinuation = null;
_pipe._readAwaitBeginning = false;
ThreadPool.UnsafeQueueUserWorkItem(_ => continuation(), true);
}
#region Awaitable
private volatile bool _readAwaitBeginning;
private volatile Action _readContinuation;
private volatile bool _writeAwaitBeginning;
private volatile Action _writeContinuation;
// The following makes it possible to await the writer. Do not use any of this directly.
public IPipeTask<Result> GetAwaiter() => this;
public bool IsCompleted
{
get
{
if (GetAvailable() > 0)
{
return true;
}
if (_pipe._closed)
{
return true;
}
_pipe._writeAwaitBeginning = true;
return false;
}
}
public Result GetResult() => TryGetMemory();
public void OnCompleted(Action continuation) => _pipe._writeContinuation = continuation;
#endregion
}
public class PipeReader : IPipeTask<Result>
{
private readonly Pipe<T> _pipe;
private Result _result = new(2);
internal PipeReader(Pipe<T> pipe) => _pipe = pipe;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint GetAvailable()
{
var read = _pipe._readIdx;
var write = _pipe._writeIdx;
if (read <= write)
{
return write - read;
}
return write + _pipe.Size - read;
}
public Result TryRead()
{
var read = _pipe._readIdx;
var write = _pipe._writeIdx;
_result.IsClosed = _pipe._closed;
if (read <= write)
{
_result.Buffer[0] = write - read == 0 ? ArraySegment<T>.Empty : new ArraySegment<T>(_pipe._buffer, (int)read, (int)(write - read));
_result.Buffer[1] = ArraySegment<T>.Empty;
}
else
{
_result.Buffer[0] = _pipe.Size - read == 0 ? ArraySegment<T>.Empty : new ArraySegment<T>(_pipe._buffer, (int)read, (int)(_pipe.Size - read));
_result.Buffer[1] = write == 0 ? ArraySegment<T>.Empty : new ArraySegment<T>(_pipe._buffer, 0, (int)write);
}
return _result;
}
public IPipeTask<Result> Read()
{
if (_pipe._readAwaitBeginning)
{
throw new Exception("Double await on reader");
}
return this;
}
public void Advance(uint count)
{
var read = _pipe._readIdx;
var write = _pipe._writeIdx;
if (read <= write)
{
if (count > write - read)
{
throw new InvalidOperationException();
}
read += count;
}
else
{
var sz = Math.Min(count, _pipe.Size - read);
read += sz;
if (read > _pipe.Size - 1)
{
read = 0;
}
count -= sz;
if (count > 0)
{
if (count > write)
{
throw new InvalidOperationException();
}
read = count;
}
}
_pipe._readIdx = read;
}
public void Commit()
{
if (_pipe._readIdx == ((_pipe._writeIdx + 1) & (_pipe.Size - 1)))
{
return;
}
var waiting = _pipe._writeAwaitBeginning;
if (!waiting)
{
return;
}
Action continuation;
do
{
continuation = _pipe._writeContinuation;
} while (continuation == null);
_pipe._writeContinuation = null;
_pipe._writeAwaitBeginning = false;
ThreadPool.UnsafeQueueUserWorkItem(_ => continuation(), true);
}
public void Close()
{
_pipe._closed = true;
var waiting = _pipe._writeAwaitBeginning;
if (!waiting)
{
return;
}
Action continuation;
do
{
continuation = _pipe._writeContinuation;
} while (continuation == null);
_pipe._writeContinuation = null;
_pipe._writeAwaitBeginning = false;
ThreadPool.UnsafeQueueUserWorkItem(_ => continuation(), true);
}
#region Awaitable
// The following makes it possible to await the reader. Do not use any of this directly.
public IPipeTask<Result> GetAwaiter() => this;
public bool IsCompleted
{
get
{
if (GetAvailable() > 0)
{
return true;
}
if (_pipe._closed)
{
return true;
}
_pipe._readAwaitBeginning = true;
return false;
}
}
public Result GetResult() => TryRead();
public void OnCompleted(Action continuation) => _pipe._readContinuation = continuation;
#endregion
}
private readonly T[] _buffer;
private volatile uint _writeIdx;
private volatile uint _readIdx;
private bool _closed;
public PipeWriter Writer { get; }
public PipeReader Reader { get; }
public uint Size => (uint)_buffer.Length;
public Pipe(T[] buf)
{
// Test if the buffer is a power of two
if (buf.Length == 0 || (buf.Length & (buf.Length - 1)) != 0)
{
throw new ArgumentOutOfRangeException(nameof(buf), "Pipe buffers must have a length that is a power of two");
}
_buffer = buf;
_writeIdx = 0;
_readIdx = 0;
_closed = false;
Writer = new PipeWriter(this);
Reader = new PipeReader(this);
}
#region Awaitable
private volatile bool _readAwaitBeginning;
private volatile Action _readContinuation;
private volatile bool _writeAwaitBeginning;
private volatile Action _writeContinuation;
#endregion
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: ServerInfo.cs *
* *
@ -17,44 +17,43 @@ using System;
using System.Buffers.Binary;
using System.Net;
namespace Server.Network
namespace Server.Network;
public sealed class ServerInfo
{
public sealed class ServerInfo
private readonly IPEndPoint m_Address;
public ServerInfo(string name, int fullPercent, TimeZoneInfo tz, IPEndPoint address)
{
private readonly IPEndPoint m_Address;
public ServerInfo(string name, int fullPercent, TimeZoneInfo tz, IPEndPoint address)
{
Name = name;
FullPercent = fullPercent;
TimeZone = tz.GetUtcOffset(DateTime.Now).Hours;
Address = address;
}
public string Name { get; set; }
public int FullPercent { get; set; }
public int TimeZone { get; set; }
public IPEndPoint Address
{
get => m_Address;
init
{
m_Address = value;
Span<byte> integer = stackalloc byte[4];
value.Address.MapToIPv4().TryWriteBytes(integer, out var bytesWritten);
if (bytesWritten != 4)
{
throw new InvalidOperationException("IP Address could not be serialized to an integer");
}
RawAddress = BinaryPrimitives.ReadUInt32LittleEndian(integer);
}
}
// UO doesn't support IPv6 servers
public uint RawAddress { get; private set; }
Name = name;
FullPercent = fullPercent;
TimeZone = tz.GetUtcOffset(DateTime.Now).Hours;
Address = address;
}
public string Name { get; set; }
public int FullPercent { get; set; }
public int TimeZone { get; set; }
public IPEndPoint Address
{
get => m_Address;
init
{
m_Address = value;
Span<byte> integer = stackalloc byte[4];
value.Address.MapToIPv4().TryWriteBytes(integer, out var bytesWritten);
if (bytesWritten != 4)
{
throw new InvalidOperationException("IP Address could not be serialized to an integer");
}
RawAddress = BinaryPrimitives.ReadUInt32LittleEndian(integer);
}
}
// UO doesn't support IPv6 servers
public uint RawAddress { get; private set; }
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: TcpServer.cs *
* *
@ -21,188 +21,187 @@ using System.Net.NetworkInformation;
using System.Net.Sockets;
using Server.Logging;
namespace Server.Network
namespace Server.Network;
public static class TcpServer
{
public static class TcpServer
private static readonly ILogger logger = LogFactory.GetLogger(typeof(TcpServer));
private const int MaxConnectionsPerLoop = 250;
// Sanity. 256 * 1024 * 4096 = ~1.3GB of ram
public static int MaxConnections { get; set; } = 4096;
private const long _listenerErrorMessageDelay = 10000; // 10 seconds
private static long _nextMaximumSocketsReachedMessage;
// AccountLoginReject BadComm
private static readonly byte[] _socketRejected = { 0x82, 0xFF };
public static IPEndPoint[] ListeningAddresses { get; private set; }
public static Socket[] Listeners { get; private set; }
public static HashSet<NetState> Instances { get; } = new(2048);
private static readonly ConcurrentQueue<NetState> _connectedQueue = new();
public static void Configure()
{
private static readonly ILogger logger = LogFactory.GetLogger(typeof(TcpServer));
MaxConnections = ServerConfiguration.GetOrUpdateSetting("tcpServer.maxConnections", MaxConnections);
}
private const int MaxConnectionsPerLoop = 250;
public static void Start()
{
HashSet<IPEndPoint> listeningAddresses = new HashSet<IPEndPoint>();
List<Socket> listeners = new List<Socket>();
// Sanity. 256 * 1024 * 4096 = ~1.3GB of ram
public static int MaxConnections { get; set; } = 4096;
private const long _listenerErrorMessageDelay = 10000; // 10 seconds
private static long _nextMaximumSocketsReachedMessage;
// AccountLoginReject BadComm
private static readonly byte[] _socketRejected = { 0x82, 0xFF };
public static IPEndPoint[] ListeningAddresses { get; private set; }
public static Socket[] Listeners { get; private set; }
public static HashSet<NetState> Instances { get; } = new(2048);
private static readonly ConcurrentQueue<NetState> _connectedQueue = new();
public static void Configure()
foreach (var ipep in ServerConfiguration.Listeners)
{
MaxConnections = ServerConfiguration.GetOrUpdateSetting("tcpServer.maxConnections", MaxConnections);
}
public static void Start()
{
HashSet<IPEndPoint> listeningAddresses = new HashSet<IPEndPoint>();
List<Socket> listeners = new List<Socket>();
foreach (var ipep in ServerConfiguration.Listeners)
var listener = CreateListener(ipep);
if (listener == null)
{
var listener = CreateListener(ipep);
if (listener == null)
{
continue;
}
if (ipep.Address.Equals(IPAddress.Any) || ipep.Address.Equals(IPAddress.IPv6Any))
{
listeningAddresses.UnionWith(GetListeningAddresses(ipep));
}
else
{
listeningAddresses.Add(ipep);
}
listeners.Add(listener);
listener.BeginAcceptingSockets();
continue;
}
foreach (var ipep in listeningAddresses)
if (ipep.Address.Equals(IPAddress.Any) || ipep.Address.Equals(IPAddress.IPv6Any))
{
logger.Information("Listening: {Address}:{Port}", ipep.Address, ipep.Port);
listeningAddresses.UnionWith(GetListeningAddresses(ipep));
}
else
{
listeningAddresses.Add(ipep);
}
ListeningAddresses = listeningAddresses.ToArray();
Listeners = listeners.ToArray();
listeners.Add(listener);
listener.BeginAcceptingSockets();
}
public static void Shutdown()
foreach (var ipep in listeningAddresses)
{
foreach (var listener in Listeners)
logger.Information("Listening: {Address}:{Port}", ipep.Address, ipep.Port);
}
ListeningAddresses = listeningAddresses.ToArray();
Listeners = listeners.ToArray();
}
public static void Shutdown()
{
foreach (var listener in Listeners)
{
listener.Close();
}
}
public static IEnumerable<IPEndPoint> GetListeningAddresses(IPEndPoint ipep) =>
NetworkInterface.GetAllNetworkInterfaces().SelectMany(adapter =>
adapter.GetIPProperties().UnicastAddresses
.Where(uip => ipep.AddressFamily == uip.Address.AddressFamily)
.Select(uip => new IPEndPoint(uip.Address, ipep.Port))
);
public static Socket CreateListener(IPEndPoint ipep)
{
var listener = new Socket(ipep.AddressFamily, SocketType.Stream, ProtocolType.Tcp)
{
LingerState = new LingerOption(false, 0),
ExclusiveAddressUse = true,
NoDelay = true
};
try
{
listener.Bind(ipep);
listener.Listen(32);
return listener;
}
catch (SocketException se)
{
// WSAEADDRINUSE
if (se.ErrorCode == 10048)
{
listener.Close();
logger.Warning("Listener: {Address}:{Port}: Failed (In Use)", ipep.Address, ipep.Port);
}
// WSAEADDRNOTAVAIL
else if (se.ErrorCode == 10049)
{
logger.Warning("Listener {Address}:{Port}: Failed (Unavailable)", ipep.Address, ipep.Port);
}
else
{
logger.Warning(se, "Listener Exception:");
}
}
public static IEnumerable<IPEndPoint> GetListeningAddresses(IPEndPoint ipep) =>
NetworkInterface.GetAllNetworkInterfaces().SelectMany(adapter =>
adapter.GetIPProperties().UnicastAddresses
.Where(uip => ipep.AddressFamily == uip.Address.AddressFamily)
.Select(uip => new IPEndPoint(uip.Address, ipep.Port))
);
return null;
}
public static Socket CreateListener(IPEndPoint ipep)
public static void Slice()
{
int count = 0;
while (++count <= MaxConnectionsPerLoop && _connectedQueue.TryDequeue(out var ns))
{
var listener = new Socket(ipep.AddressFamily, SocketType.Stream, ProtocolType.Tcp)
{
LingerState = new LingerOption(false, 0),
ExclusiveAddressUse = true,
NoDelay = true
};
Instances.Add(ns);
ns.LogInfo($"Connected. [{Instances.Count} Online]");
}
}
private static async void BeginAcceptingSockets(this Socket listener)
{
while (true)
{
try
{
listener.Bind(ipep);
listener.Listen(32);
return listener;
}
catch (SocketException se)
{
// WSAEADDRINUSE
if (se.ErrorCode == 10048)
var socket = await listener.AcceptAsync();
var rejected = false;
if (Instances.Count >= MaxConnections)
{
logger.Warning("Listener: {Address}:{Port}: Failed (In Use)", ipep.Address, ipep.Port);
}
// WSAEADDRNOTAVAIL
else if (se.ErrorCode == 10049)
{
logger.Warning("Listener {Address}:{Port}: Failed (Unavailable)", ipep.Address, ipep.Port);
}
else
{
logger.Warning(se, "Listener Exception:");
}
}
rejected = true;
return null;
}
var ticks = Core.TickCount;
public static void Slice()
{
int count = 0;
while (++count <= MaxConnectionsPerLoop && _connectedQueue.TryDequeue(out var ns))
{
Instances.Add(ns);
ns.LogInfo($"Connected. [{Instances.Count} Online]");
}
}
private static async void BeginAcceptingSockets(this Socket listener)
{
while (true)
{
try
{
var socket = await listener.AcceptAsync();
var rejected = false;
if (Instances.Count >= MaxConnections)
if (_nextMaximumSocketsReachedMessage <= ticks)
{
rejected = true;
var ticks = Core.TickCount;
if (_nextMaximumSocketsReachedMessage <= ticks)
{
if (socket.RemoteEndPoint is IPEndPoint ipep)
{
var ip = ipep.Address.ToString();
logger.Warning("Listener {Address}: Failed (Maximum connections reached)", ip);
NetState.TraceDisconnect("Maximum connections reached.", ip);
}
_nextMaximumSocketsReachedMessage = ticks + _listenerErrorMessageDelay;
}
}
var args = new SocketConnectEventArgs(socket);
EventSink.InvokeSocketConnect(args);
if (!args.AllowConnection)
{
rejected = true;
if (socket.RemoteEndPoint is IPEndPoint ipep)
{
var ip = ipep.Address.ToString();
NetState.TraceDisconnect("Rejected by socket event handler", ip);
logger.Warning("Listener {Address}: Failed (Maximum connections reached)", ip);
NetState.TraceDisconnect("Maximum connections reached.", ip);
}
}
if (rejected)
{
socket.Send(_socketRejected, SocketFlags.None);
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
else
{
var ns = new NetState(socket);
_connectedQueue.Enqueue(ns);
_nextMaximumSocketsReachedMessage = ticks + _listenerErrorMessageDelay;
}
}
catch
var args = new SocketConnectEventArgs(socket);
EventSink.InvokeSocketConnect(args);
if (!args.AllowConnection)
{
// ignored
rejected = true;
if (socket.RemoteEndPoint is IPEndPoint ipep)
{
var ip = ipep.Address.ToString();
NetState.TraceDisconnect("Rejected by socket event handler", ip);
}
}
if (rejected)
{
socket.Send(_socketRejected, SocketFlags.None);
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
else
{
var ns = new NetState(socket);
_connectedQueue.Enqueue(ns);
}
}
catch
{
// ignored
}
}
}