Fixes publishing

This commit is contained in:
Kamron Batman 2019-10-04 22:02:19 -07:00
parent 6119774dc9
commit 58be0d416c
No known key found for this signature in database
GPG key ID: 5C9DFD15804B6BB8
53 changed files with 981 additions and 1225 deletions

View file

@ -12,6 +12,7 @@ using System.IO;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;
namespace Server
{
@ -26,46 +27,31 @@ namespace Server
{
if (Core.Unix && File.Exists("rdrand.so"))
_Random = new RDRandUnix();
else if (Core.Is64Bit && File.Exists("rdrand64.dll"))
_Random = new RDRand64();
else if (File.Exists("rdrand.dll"))
_Random = new RDRand32();
else
_Random = new CSPRandom();
_Random = new RDRand64();
if (_Random is IHardwareRNG rng && !rng.IsSupported()) _Random = new CSPRandom();
if (_Random == null || _Random is IHardwareRNG rng && !rng.IsSupported())
_Random = new CSPRandom();
}
public static bool IsHardwareRNG => _Random is IHardwareRNG;
public static Type Type => _Random.GetType();
public static int Next(int c)
{
return _Random.Next(c);
}
public static int Next(int c) => _Random.Next(c);
public static bool NextBool()
{
return _Random.NextBool();
}
public static bool NextBool() => _Random.NextBool();
public static void NextBytes(byte[] b)
{
_Random.NextBytes(b);
}
public static void NextBytes(Span<byte> b) => _Random.NextBytes(b);
public static double NextDouble()
{
return _Random.NextDouble();
}
public static double NextDouble() => _Random.NextDouble();
}
public interface IRandomImpl
{
int Next(int c);
bool NextBool();
void NextBytes(byte[] b);
void NextBytes(Span<byte> b);
double NextDouble();
}
@ -74,48 +60,54 @@ namespace Server
bool IsSupported();
}
public sealed class SimpleRandom : IRandomImpl
public abstract class BaseRandom : IRandomImpl
{
private Random m_Random = new Random();
internal abstract void GetBytes(Span<byte> b);
internal abstract void GetBytes(byte[] b, int offset, int count);
public int Next(int c)
public virtual void NextBytes(Span<byte> b) => GetBytes(b);
public virtual int Next(int c) => (int)(c * NextDouble());
public virtual bool NextBool() => (NextByte() & 1) == 1;
public virtual byte NextByte()
{
int r;
lock (m_Random)
byte[] b = new byte[1];
GetBytes(b, 0, 1);
return b[0];
}
public virtual unsafe double NextDouble()
{
byte[] b = new byte[8];
if (BitConverter.IsLittleEndian)
{
r = m_Random.Next(c);
b[7] = 0;
GetBytes(b, 0, 7);
}
else
{
b[0] = 0;
GetBytes(b, 1, 7);
}
return r;
}
public bool NextBool()
{
return NextDouble() >= .5;
}
public void NextBytes(byte[] b)
{
lock (m_Random)
ulong r;
fixed (byte* buf = b)
{
m_Random.NextBytes(b);
}
}
public double NextDouble()
{
double r;
lock (m_Random)
{
r = m_Random.NextDouble();
r = *(ulong*)&buf[0] >> 3;
}
return r;
}
}
/* double: 53 bits of significand precision
* ulong.MaxValue >> 11 = 9007199254740991
* 2^53 = 9007199254740992
*/
public sealed class CSPRandom : IRandomImpl
{
return (double)r / 9007199254740992;
}
}
public sealed class CSPRandom : BaseRandom
{
private static int BUFFER_SIZE = 0x4000;
private static int LARGE_REQUEST = 0x40;
private byte[] _Buffer = new byte[BUFFER_SIZE];
@ -132,63 +124,24 @@ namespace Server
public CSPRandom()
{
_CSP.GetBytes(_Working);
ThreadPool.QueueUserWorkItem(Fill);
Task.Run(Fill);
}
public int Next(int c)
{
return (int)(c * NextDouble());
}
public bool NextBool()
{
return (NextByte() & 1) == 1;
}
public void NextBytes(byte[] b)
public override void NextBytes(Span<byte> b)
{
int c = b.Length;
if (c >= LARGE_REQUEST)
{
lock (_CSP)
{
lock (_sync)
{
_CSP.GetBytes(b);
}
}
return;
}
_GetBytes(b);
}
public unsafe double NextDouble()
{
byte[] b = new byte[8];
if (BitConverter.IsLittleEndian)
{
b[7] = 0;
_GetBytes(b, 0, 7);
}
else
{
b[0] = 0;
_GetBytes(b, 1, 7);
}
ulong r = 0;
fixed (byte* buf = b)
{
r = *(ulong*)&buf[0] >> 3;
}
/* double: 53 bits of significand precision
* ulong.MaxValue >> 11 = 9007199254740991
* 2^53 = 9007199254740992
*/
return (double)r / 9007199254740992;
GetBytes(b);
}
private void CheckSwap(int c)
@ -205,474 +158,91 @@ namespace Server
_filled.Reset();
ThreadPool.QueueUserWorkItem(Fill);
Task.Run(Fill);
}
private void Fill(object o)
private void Fill()
{
lock (_CSP)
{
_CSP.GetBytes(_Buffer);
}
_CSP.GetBytes(_Buffer);
_filled.Set();
}
private void _GetBytes(byte[] b)
internal override void GetBytes(Span<byte> b)
{
int c = b.Length;
lock (_sync)
{
CheckSwap(c);
Buffer.BlockCopy(_Working, _Index, b, 0, c);
_Working.CopyTo(b);
_Index += c;
}
}
private void _GetBytes(byte[] b, int offset, int count)
internal override void GetBytes(byte[] b, int offset, int count)
{
lock (_sync)
{
CheckSwap(count);
Buffer.BlockCopy(_Working, _Index, b, offset, count);
_Index += count;
}
GetBytes(b.AsSpan(offset, count));
}
private byte NextByte()
public override byte NextByte()
{
lock (_sync)
{
CheckSwap(1);
return _Working[_Index++];
}
}
}
public sealed class RDRandUnix : IRandomImpl, IHardwareRNG
{
private static int BUFFER_SIZE = 0x10000;
private static int LARGE_REQUEST = 0x40;
private byte[] _Buffer = new byte[BUFFER_SIZE];
private ManualResetEvent _filled = new ManualResetEvent(false);
private int _Index;
private object _sync = new object();
private byte[] _Working = new byte[BUFFER_SIZE];
public RDRandUnix()
{
SafeNativeMethods.rdrand_get_bytes(BUFFER_SIZE, _Working);
ThreadPool.QueueUserWorkItem(Fill);
}
public bool IsSupported()
{
uint r = 0;
return SafeNativeMethods.rdrand_32(ref r, true) == RDRandError.Success;
}
public int Next(int c)
{
return (int)(c * NextDouble());
}
public bool NextBool()
{
return (NextByte() & 1) == 1;
}
public void NextBytes(byte[] b)
{
int c = b.Length;
if (c >= LARGE_REQUEST)
{
SafeNativeMethods.rdrand_get_bytes(c, b);
return;
}
_GetBytes(b);
}
public unsafe double NextDouble()
{
byte[] b = new byte[8];
if (BitConverter.IsLittleEndian)
{
b[7] = 0;
_GetBytes(b, 0, 7);
}
else
{
b[0] = 0;
_GetBytes(b, 1, 7);
}
ulong r = 0;
fixed (byte* buf = b)
{
r = *(ulong*)&buf[0] >> 3;
}
/* double: 53 bits of significand precision
* ulong.MaxValue >> 11 = 9007199254740991
* 2^53 = 9007199254740992
*/
return (double)r / 9007199254740992;
}
private void CheckSwap(int c)
{
if (_Index + c < BUFFER_SIZE)
return;
_filled.WaitOne();
byte[] b = _Working;
_Working = _Buffer;
_Buffer = b;
_Index = 0;
_filled.Reset();
ThreadPool.QueueUserWorkItem(Fill);
}
private void Fill(object o)
{
SafeNativeMethods.rdrand_get_bytes(BUFFER_SIZE, _Buffer);
_filled.Set();
}
private void _GetBytes(byte[] b)
{
int c = b.Length;
lock (_sync)
{
CheckSwap(c);
Buffer.BlockCopy(_Working, _Index, b, 0, c);
_Index += c;
}
}
private void _GetBytes(byte[] b, int offset, int count)
{
lock (_sync)
{
CheckSwap(count);
Buffer.BlockCopy(_Working, _Index, b, offset, count);
_Index += count;
}
}
private byte NextByte()
{
lock (_sync)
{
CheckSwap(1);
return _Working[_Index++];
}
}
internal class SafeNativeMethods
public sealed class RDRandUnix : BaseRandom, IHardwareRNG
{
[DllImport("rdrand.so")]
internal static extern RDRandError rdrand_32(ref uint rand, bool retry);
[DllImport("rdrand.so")]
internal static extern RDRandError rdrand_get_bytes(int n, byte[] buffer);
}
}
public sealed class RDRand32 : IRandomImpl, IHardwareRNG
{
private static int BUFFER_SIZE = 0x10000;
private static int LARGE_REQUEST = 0x40;
private byte[] _Buffer = new byte[BUFFER_SIZE];
private ManualResetEvent _filled = new ManualResetEvent(false);
private int _Index;
private object _sync = new object();
private byte[] _Working = new byte[BUFFER_SIZE];
public RDRand32()
{
SafeNativeMethods.rdrand_get_bytes(BUFFER_SIZE, _Working);
ThreadPool.QueueUserWorkItem(Fill);
}
internal static extern unsafe RDRandError rdrand_get_bytes(int n, byte* buffer);
public bool IsSupported()
{
uint r = 0;
return SafeNativeMethods.rdrand_32(ref r, true) == RDRandError.Success;
return rdrand_32(ref r, true) == RDRandError.Success;
}
public int Next(int c)
internal override unsafe void GetBytes(Span<byte> b)
{
return (int)(c * NextDouble());
fixed(byte* ptr = b)
rdrand_get_bytes(b.Length, ptr);
}
public bool NextBool()
internal override void GetBytes(byte[] b, int offset, int count)
{
return (NextByte() & 1) == 1;
}
public void NextBytes(byte[] b)
{
int c = b.Length;
if (c >= LARGE_REQUEST)
{
SafeNativeMethods.rdrand_get_bytes(c, b);
return;
}
_GetBytes(b);
}
public unsafe double NextDouble()
{
byte[] b = new byte[8];
if (BitConverter.IsLittleEndian)
{
b[7] = 0;
_GetBytes(b, 0, 7);
}
else
{
b[0] = 0;
_GetBytes(b, 1, 7);
}
ulong r = 0;
fixed (byte* buf = b)
{
r = *(ulong*)&buf[0] >> 3;
}
/* double: 53 bits of significand precision
* ulong.MaxValue >> 11 = 9007199254740991
* 2^53 = 9007199254740992
*/
return (double)r / 9007199254740992;
}
private void CheckSwap(int c)
{
if (_Index + c < BUFFER_SIZE)
return;
_filled.WaitOne();
byte[] b = _Working;
_Working = _Buffer;
_Buffer = b;
_Index = 0;
_filled.Reset();
ThreadPool.QueueUserWorkItem(Fill);
}
private void Fill(object o)
{
SafeNativeMethods.rdrand_get_bytes(BUFFER_SIZE, _Buffer);
_filled.Set();
}
private void _GetBytes(byte[] b)
{
int c = b.Length;
lock (_sync)
{
CheckSwap(c);
Buffer.BlockCopy(_Working, _Index, b, 0, c);
_Index += c;
GetBytes(b.AsSpan().Slice(offset, count));
}
}
private void _GetBytes(byte[] b, int offset, int count)
public sealed class RDRand64 : BaseRandom, IHardwareRNG
{
lock (_sync)
{
CheckSwap(count);
Buffer.BlockCopy(_Working, _Index, b, offset, count);
_Index += count;
}
}
[DllImport("rdrand")]
internal static extern RDRandError rdrand_64(ref ulong rand, bool retry);
private byte NextByte()
{
lock (_sync)
{
CheckSwap(1);
return _Working[_Index++];
}
}
internal class SafeNativeMethods
{
[DllImport("rdrand32")]
internal static extern RDRandError rdrand_32(ref uint rand, bool retry);
[DllImport("rdrand32")]
internal static extern RDRandError rdrand_get_bytes(int n, byte[] buffer);
}
}
public sealed class RDRand64 : IRandomImpl, IHardwareRNG
{
private static int BUFFER_SIZE = 0x10000;
private static int LARGE_REQUEST = 0x40;
private byte[] _Buffer = new byte[BUFFER_SIZE];
private ManualResetEvent _filled = new ManualResetEvent(false);
private int _Index;
private object _sync = new object();
private byte[] _Working = new byte[BUFFER_SIZE];
public RDRand64()
{
SafeNativeMethods.rdrand_get_bytes(BUFFER_SIZE, _Working);
ThreadPool.QueueUserWorkItem(Fill);
}
[DllImport("rdrand")]
internal static extern unsafe RDRandError rdrand_get_bytes(int n, byte* buffer);
public bool IsSupported()
{
ulong r = 0;
return SafeNativeMethods.rdrand_64(ref r, true) == RDRandError.Success;
return rdrand_64(ref r, true) == RDRandError.Success;
}
public int Next(int c)
internal override unsafe void GetBytes(Span<byte> b)
{
return (int)(c * NextDouble());
fixed (byte* ptr = b)
rdrand_get_bytes(b.Length, ptr);
}
public bool NextBool()
internal override void GetBytes(byte[] b, int offset, int count)
{
return (NextByte() & 1) == 1;
}
public void NextBytes(byte[] b)
{
int c = b.Length;
if (c >= LARGE_REQUEST)
{
SafeNativeMethods.rdrand_get_bytes(c, b);
return;
}
_GetBytes(b);
}
public unsafe double NextDouble()
{
byte[] b = new byte[8];
if (BitConverter.IsLittleEndian)
{
b[7] = 0;
_GetBytes(b, 0, 7);
}
else
{
b[0] = 0;
_GetBytes(b, 1, 7);
}
ulong r = 0;
fixed (byte* buf = b)
{
r = *(ulong*)&buf[0] >> 3;
}
/* double: 53 bits of significand precision
* ulong.MaxValue >> 11 = 9007199254740991
* 2^53 = 9007199254740992
*/
return (double)r / 9007199254740992;
}
private void CheckSwap(int c)
{
if (_Index + c < BUFFER_SIZE)
return;
_filled.WaitOne();
byte[] b = _Working;
_Working = _Buffer;
_Buffer = b;
_Index = 0;
_filled.Reset();
ThreadPool.QueueUserWorkItem(Fill);
}
private void Fill(object o)
{
SafeNativeMethods.rdrand_get_bytes(BUFFER_SIZE, _Buffer);
_filled.Set();
}
private void _GetBytes(byte[] b)
{
int c = b.Length;
lock (_sync)
{
CheckSwap(c);
Buffer.BlockCopy(_Working, _Index, b, 0, c);
_Index += c;
}
}
private void _GetBytes(byte[] b, int offset, int count)
{
lock (_sync)
{
CheckSwap(count);
Buffer.BlockCopy(_Working, _Index, b, offset, count);
_Index += count;
}
}
private byte NextByte()
{
lock (_sync)
{
CheckSwap(1);
return _Working[_Index++];
}
}
internal class SafeNativeMethods
{
[DllImport("rdrand64")]
internal static extern RDRandError rdrand_64(ref ulong rand, bool retry);
[DllImport("rdrand64")]
internal static extern RDRandError rdrand_get_bytes(int n, byte[] buffer);
GetBytes(b.AsSpan(offset, count));
}
}
@ -687,4 +257,4 @@ namespace Server
Success = 1
}
}
}