Overwrite
Complete Overwrite of the Folder with the free shard. ServUO 57.3 has been added.
This commit is contained in:
559
Server/Random.cs
Normal file
559
Server/Random.cs
Normal file
@@ -0,0 +1,559 @@
|
||||
#region References
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading;
|
||||
#endregion
|
||||
|
||||
namespace Server
|
||||
{
|
||||
/// <summary>
|
||||
/// Handles random number generation.
|
||||
/// </summary>
|
||||
public static class RandomImpl
|
||||
{
|
||||
private static readonly IRandomImpl _Random;
|
||||
|
||||
static RandomImpl()
|
||||
{
|
||||
if (Core.Unix && Core.Is64Bit && File.Exists("libdrng.so"))
|
||||
{
|
||||
_Random = new RDRand64();
|
||||
}
|
||||
else if (Core.Unix && File.Exists("libdrng.so"))
|
||||
{
|
||||
_Random = new RDRand32();
|
||||
}
|
||||
else if (Core.Unix)
|
||||
{
|
||||
_Random = new SimpleRandom();
|
||||
}
|
||||
else if (Core.Is64Bit && File.Exists("drng64.dll"))
|
||||
{
|
||||
_Random = new RDRand64();
|
||||
}
|
||||
else if (!Core.Is64Bit && File.Exists("drng32.dll"))
|
||||
{
|
||||
_Random = new RDRand32();
|
||||
}
|
||||
else
|
||||
{
|
||||
_Random = new CSPRandom();
|
||||
}
|
||||
|
||||
if (_Random is IHardwareRNG)
|
||||
{
|
||||
if (!((IHardwareRNG)_Random).IsSupported())
|
||||
{
|
||||
_Random = new CSPRandom();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsHardwareRNG { get { return _Random is IHardwareRNG; } }
|
||||
|
||||
public static Type Type { get { return _Random.GetType(); } }
|
||||
|
||||
public static int Next(int c)
|
||||
{
|
||||
return _Random.Next(c);
|
||||
}
|
||||
|
||||
public static bool NextBool()
|
||||
{
|
||||
return _Random.NextBool();
|
||||
}
|
||||
|
||||
public static void NextBytes(byte[] b)
|
||||
{
|
||||
_Random.NextBytes(b);
|
||||
}
|
||||
|
||||
public static double NextDouble()
|
||||
{
|
||||
return _Random.NextDouble();
|
||||
}
|
||||
}
|
||||
|
||||
public interface IRandomImpl
|
||||
{
|
||||
int Next(int c);
|
||||
bool NextBool();
|
||||
void NextBytes(byte[] b);
|
||||
double NextDouble();
|
||||
}
|
||||
|
||||
public interface IHardwareRNG
|
||||
{
|
||||
bool IsSupported();
|
||||
}
|
||||
|
||||
public sealed class SimpleRandom : IRandomImpl
|
||||
{
|
||||
private readonly Random m_Random = new Random();
|
||||
|
||||
public int Next(int c)
|
||||
{
|
||||
if(c <= 0)
|
||||
return 0;
|
||||
|
||||
int r;
|
||||
lock (m_Random)
|
||||
r = m_Random.Next(c);
|
||||
return r;
|
||||
}
|
||||
|
||||
public bool NextBool()
|
||||
{
|
||||
return NextDouble() >= .5;
|
||||
}
|
||||
|
||||
public void NextBytes(byte[] b)
|
||||
{
|
||||
lock (m_Random)
|
||||
m_Random.NextBytes(b);
|
||||
}
|
||||
|
||||
public double NextDouble()
|
||||
{
|
||||
double r;
|
||||
lock (m_Random)
|
||||
r = m_Random.NextDouble();
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class CSPRandom : IRandomImpl
|
||||
{
|
||||
private readonly RNGCryptoServiceProvider _CSP = new RNGCryptoServiceProvider();
|
||||
|
||||
private static int BUFFER_SIZE = 0x4000;
|
||||
private static int LARGE_REQUEST = 0x40;
|
||||
|
||||
private byte[] _Working = new byte[BUFFER_SIZE];
|
||||
private byte[] _Buffer = new byte[BUFFER_SIZE];
|
||||
|
||||
private int _Index;
|
||||
|
||||
private readonly object _sync = new object();
|
||||
private readonly object _syncB = new object();
|
||||
|
||||
public CSPRandom()
|
||||
{
|
||||
_CSP.GetBytes(_Working);
|
||||
ThreadPool.QueueUserWorkItem(Fill);
|
||||
}
|
||||
|
||||
private void CheckSwap(int c)
|
||||
{
|
||||
lock (_sync)
|
||||
{
|
||||
if (_Index + c < BUFFER_SIZE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock (_syncB)
|
||||
{
|
||||
var b = _Working;
|
||||
_Working = _Buffer;
|
||||
_Buffer = b;
|
||||
_Index = 0;
|
||||
}
|
||||
}
|
||||
ThreadPool.QueueUserWorkItem(Fill);
|
||||
}
|
||||
|
||||
private void Fill(object o)
|
||||
{
|
||||
lock (_syncB)
|
||||
lock (_CSP)
|
||||
_CSP.GetBytes(_Buffer);
|
||||
}
|
||||
|
||||
private void _GetBytes(byte[] b)
|
||||
{
|
||||
int c = b.Length;
|
||||
|
||||
CheckSwap(c);
|
||||
|
||||
lock (_sync)
|
||||
{
|
||||
Buffer.BlockCopy(_Working, _Index, b, 0, c);
|
||||
_Index += c;
|
||||
}
|
||||
}
|
||||
|
||||
private void _GetBytes(byte[] b, int offset, int count)
|
||||
{
|
||||
CheckSwap(count);
|
||||
|
||||
lock (_sync)
|
||||
{
|
||||
Buffer.BlockCopy(_Working, _Index, b, offset, count);
|
||||
_Index += count;
|
||||
}
|
||||
}
|
||||
|
||||
public int Next(int c)
|
||||
{
|
||||
return (int)(c * NextDouble());
|
||||
}
|
||||
|
||||
public bool NextBool()
|
||||
{
|
||||
return (NextByte() & 1) == 1;
|
||||
}
|
||||
|
||||
private byte NextByte()
|
||||
{
|
||||
CheckSwap(1);
|
||||
|
||||
lock (_sync)
|
||||
return _Working[_Index++];
|
||||
}
|
||||
|
||||
public void NextBytes(byte[] b)
|
||||
{
|
||||
int c = b.Length;
|
||||
|
||||
if (c >= LARGE_REQUEST)
|
||||
{
|
||||
lock (_CSP)
|
||||
_CSP.GetBytes(b);
|
||||
return;
|
||||
}
|
||||
_GetBytes(b);
|
||||
}
|
||||
|
||||
public unsafe double NextDouble()
|
||||
{
|
||||
var 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;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class RDRand32 : IRandomImpl, IHardwareRNG
|
||||
{
|
||||
internal class SafeNativeMethods
|
||||
{
|
||||
[DllImport("drng32")]
|
||||
internal static extern RDRandError rdrand_32(ref uint rand, bool retry);
|
||||
|
||||
[DllImport("drng32")]
|
||||
internal static extern RDRandError rdrand_get_bytes(int n, byte[] buffer);
|
||||
}
|
||||
|
||||
private static int BUFFER_SIZE = 0x10000;
|
||||
private static int LARGE_REQUEST = 0x40;
|
||||
|
||||
private byte[] _Working = new byte[BUFFER_SIZE];
|
||||
private byte[] _Buffer = new byte[BUFFER_SIZE];
|
||||
|
||||
private int _Index;
|
||||
|
||||
private readonly object _sync = new object();
|
||||
private readonly object _syncB = new object();
|
||||
|
||||
public RDRand32()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
private void CheckSwap(int c)
|
||||
{
|
||||
lock (_sync)
|
||||
{
|
||||
if (_Index + c < BUFFER_SIZE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock (_syncB)
|
||||
{
|
||||
var b = _Working;
|
||||
_Working = _Buffer;
|
||||
_Buffer = b;
|
||||
_Index = 0;
|
||||
}
|
||||
}
|
||||
ThreadPool.QueueUserWorkItem(Fill);
|
||||
}
|
||||
|
||||
private void Fill(object o)
|
||||
{
|
||||
lock (_syncB)
|
||||
SafeNativeMethods.rdrand_get_bytes(BUFFER_SIZE, _Buffer);
|
||||
}
|
||||
|
||||
private void _GetBytes(byte[] b)
|
||||
{
|
||||
int c = b.Length;
|
||||
|
||||
CheckSwap(c);
|
||||
|
||||
lock (_sync)
|
||||
{
|
||||
Buffer.BlockCopy(_Working, _Index, b, 0, c);
|
||||
_Index += c;
|
||||
}
|
||||
}
|
||||
|
||||
private void _GetBytes(byte[] b, int offset, int count)
|
||||
{
|
||||
CheckSwap(count);
|
||||
|
||||
lock (_sync)
|
||||
{
|
||||
Buffer.BlockCopy(_Working, _Index, b, offset, count);
|
||||
_Index += count;
|
||||
}
|
||||
}
|
||||
|
||||
public int Next(int c)
|
||||
{
|
||||
return (int)(c * NextDouble());
|
||||
}
|
||||
|
||||
public bool NextBool()
|
||||
{
|
||||
return (NextByte() & 1) == 1;
|
||||
}
|
||||
|
||||
private byte NextByte()
|
||||
{
|
||||
CheckSwap(1);
|
||||
|
||||
lock (_sync)
|
||||
return _Working[_Index++];
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
var 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;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class RDRand64 : IRandomImpl, IHardwareRNG
|
||||
{
|
||||
internal class SafeNativeMethods
|
||||
{
|
||||
[DllImport("drng64")]
|
||||
internal static extern RDRandError rdrand_64(ref ulong rand, bool retry);
|
||||
|
||||
[DllImport("drng64")]
|
||||
internal static extern RDRandError rdrand_get_bytes(int n, byte[] buffer);
|
||||
}
|
||||
|
||||
private static int BUFFER_SIZE = 0x10000;
|
||||
private static int LARGE_REQUEST = 0x40;
|
||||
|
||||
private byte[] _Working = new byte[BUFFER_SIZE];
|
||||
private byte[] _Buffer = new byte[BUFFER_SIZE];
|
||||
|
||||
private int _Index;
|
||||
|
||||
private readonly object _sync = new object();
|
||||
private readonly object _syncB = new object();
|
||||
|
||||
public RDRand64()
|
||||
{
|
||||
SafeNativeMethods.rdrand_get_bytes(BUFFER_SIZE, _Working);
|
||||
ThreadPool.QueueUserWorkItem(Fill);
|
||||
}
|
||||
|
||||
public bool IsSupported()
|
||||
{
|
||||
ulong r = 0;
|
||||
return SafeNativeMethods.rdrand_64(ref r, true) == RDRandError.Success;
|
||||
}
|
||||
|
||||
private void CheckSwap(int c)
|
||||
{
|
||||
lock (_sync)
|
||||
{
|
||||
if (_Index + c < BUFFER_SIZE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock (_syncB)
|
||||
{
|
||||
var b = _Working;
|
||||
_Working = _Buffer;
|
||||
_Buffer = b;
|
||||
_Index = 0;
|
||||
}
|
||||
}
|
||||
ThreadPool.QueueUserWorkItem(Fill);
|
||||
}
|
||||
|
||||
private void Fill(object o)
|
||||
{
|
||||
lock (_syncB)
|
||||
SafeNativeMethods.rdrand_get_bytes(BUFFER_SIZE, _Buffer);
|
||||
}
|
||||
|
||||
private void _GetBytes(byte[] b)
|
||||
{
|
||||
int c = b.Length;
|
||||
|
||||
CheckSwap(c);
|
||||
|
||||
lock (_sync)
|
||||
{
|
||||
Buffer.BlockCopy(_Working, _Index, b, 0, c);
|
||||
_Index += c;
|
||||
}
|
||||
}
|
||||
|
||||
private void _GetBytes(byte[] b, int offset, int count)
|
||||
{
|
||||
CheckSwap(count);
|
||||
|
||||
lock (_sync)
|
||||
{
|
||||
Buffer.BlockCopy(_Working, _Index, b, offset, count);
|
||||
_Index += count;
|
||||
}
|
||||
}
|
||||
|
||||
public int Next(int c)
|
||||
{
|
||||
return (int)(c * NextDouble());
|
||||
}
|
||||
|
||||
public bool NextBool()
|
||||
{
|
||||
return (NextByte() & 1) == 1;
|
||||
}
|
||||
|
||||
private byte NextByte()
|
||||
{
|
||||
CheckSwap(1);
|
||||
|
||||
lock (_sync)
|
||||
return _Working[_Index++];
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
var 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;
|
||||
}
|
||||
}
|
||||
|
||||
public enum RDRandError
|
||||
{
|
||||
Unknown = -4,
|
||||
Unsupported = -3,
|
||||
Supported = -2,
|
||||
NotReady = -1,
|
||||
|
||||
Failure = 0,
|
||||
|
||||
Success = 1,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user