Overwrite
Complete Overwrite of the Folder with the free shard. ServUO 57.3 has been added.
This commit is contained in:
27
Scripts/SubSystem/VitaNex/Core/Services/WebAPI/Delegates.cs
Normal file
27
Scripts/SubSystem/VitaNex/Core/Services/WebAPI/Delegates.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
#region Header
|
||||
// _,-'/-'/
|
||||
// . __,-; ,'( '/
|
||||
// \. `-.__`-._`:_,-._ _ , . ``
|
||||
// `:-._,------' ` _,`--` -: `_ , ` ,' :
|
||||
// `---..__,,--' (C) 2023 ` -'. -'
|
||||
// # Vita-Nex [http://core.vita-nex.com] #
|
||||
// {o)xxx|===============- # -===============|xxx(o}
|
||||
// # #
|
||||
#endregion
|
||||
|
||||
#region References
|
||||
using System.Net;
|
||||
#endregion
|
||||
|
||||
namespace VitaNex.Web
|
||||
{
|
||||
public delegate void WebAPIContextHandler(WebAPIContext context);
|
||||
|
||||
public delegate void WebAPIClientConnected(WebAPIClient client);
|
||||
|
||||
public delegate void WebAPIClientDisconnected(WebAPIClient client);
|
||||
|
||||
public delegate void WebAPIRequestSend<in T>(HttpWebRequest req, T state);
|
||||
|
||||
public delegate void WebAPIRequestReceive<in T>(HttpWebRequest req, T state, HttpWebResponse res);
|
||||
}
|
||||
411
Scripts/SubSystem/VitaNex/Core/Services/WebAPI/Objects/Client.cs
Normal file
411
Scripts/SubSystem/VitaNex/Core/Services/WebAPI/Objects/Client.cs
Normal file
@@ -0,0 +1,411 @@
|
||||
#region Header
|
||||
// _,-'/-'/
|
||||
// . __,-; ,'( '/
|
||||
// \. `-.__`-._`:_,-._ _ , . ``
|
||||
// `:-._,------' ` _,`--` -: `_ , ` ,' :
|
||||
// `---..__,,--' (C) 2023 ` -'. -'
|
||||
// # Vita-Nex [http://core.vita-nex.com] #
|
||||
// {o)xxx|===============- # -===============|xxx(o}
|
||||
// # #
|
||||
#endregion
|
||||
|
||||
#region References
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
#endregion
|
||||
|
||||
namespace VitaNex.Web
|
||||
{
|
||||
public sealed class WebAPIClient : IDisposable
|
||||
{
|
||||
private static readonly char[] _Separators = { '\r', '\n' };
|
||||
private static readonly byte[] _EmptyBuffer = new byte[0];
|
||||
private static readonly KeyValueString[] _EmptyHeaders = new KeyValueString[0];
|
||||
|
||||
private static IEnumerable<KeyValueString> ParseHeaders(IEnumerable<string> headers)
|
||||
{
|
||||
int i;
|
||||
|
||||
foreach (var h in headers)
|
||||
{
|
||||
i = h.IndexOf(' ');
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
var k = h.Substring(0, i).Trim().TrimEnd(':');
|
||||
var v = h.Substring(i + 1);
|
||||
|
||||
yield return new KeyValueString(k, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public TcpClient Client { get; private set; }
|
||||
public NetworkStream Stream { get; private set; }
|
||||
|
||||
public bool Connected => Client != null && Client.Connected;
|
||||
|
||||
public bool IsDisposed { get; private set; }
|
||||
|
||||
public WebAPIClient(TcpClient client)
|
||||
{
|
||||
Client = client;
|
||||
Stream = Client.GetStream();
|
||||
}
|
||||
|
||||
public void Encode(Encoding enc, string data, out byte[] buffer, out int length)
|
||||
{
|
||||
buffer = enc.GetBytes(data ?? String.Empty);
|
||||
length = buffer.Length;
|
||||
}
|
||||
|
||||
public void Decode(Encoding enc, byte[] buffer, int length, out string data)
|
||||
{
|
||||
if (buffer == null || buffer.Length == 0 || length <= 0)
|
||||
{
|
||||
data = String.Empty;
|
||||
return;
|
||||
}
|
||||
|
||||
data = enc.GetString(buffer, 0, length);
|
||||
}
|
||||
|
||||
public void Compress(ref byte[] buffer, ref int length)
|
||||
{
|
||||
using (var outS = new MemoryStream())
|
||||
{
|
||||
using (var ds = new DeflateStream(outS, CompressionMode.Compress, true))
|
||||
{
|
||||
ds.Write(buffer, 0, length);
|
||||
}
|
||||
|
||||
outS.Position = 0;
|
||||
|
||||
// Recycle the buffer?
|
||||
if (outS.Length <= buffer.Length)
|
||||
{
|
||||
length = outS.Read(buffer, 0, buffer.Length);
|
||||
|
||||
// Heartbleed: Nope; zero-fill the remaining buffer!
|
||||
for (var i = length; i < buffer.Length; i++)
|
||||
{
|
||||
buffer[i] = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer = outS.ToArray();
|
||||
length = buffer.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Decompress(ref byte[] buffer, ref int length)
|
||||
{
|
||||
using (MemoryStream inS = new MemoryStream(buffer, 0, length), outS = new MemoryStream())
|
||||
{
|
||||
using (var ds = new DeflateStream(inS, CompressionMode.Decompress, true))
|
||||
{
|
||||
ds.CopyTo(outS);
|
||||
}
|
||||
|
||||
outS.Position = 0;
|
||||
|
||||
// Recycle the buffer?
|
||||
if (outS.Length <= buffer.Length)
|
||||
{
|
||||
length = outS.Read(buffer, 0, buffer.Length);
|
||||
|
||||
// Heartbleed: Nope; zero-fill the remaining buffer!
|
||||
for (var i = length; i < buffer.Length; i++)
|
||||
{
|
||||
buffer[i] = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer = outS.ToArray();
|
||||
length = buffer.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int Send(bool compress, string data, Encoding enc)
|
||||
{
|
||||
|
||||
Send(compress, data, enc, out var buffer, out var length);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
public void Send(bool compress, string data, Encoding enc, out byte[] buffer, out int length)
|
||||
{
|
||||
Encode(enc, data, out buffer, out length);
|
||||
Send(compress, ref buffer, ref length);
|
||||
}
|
||||
|
||||
public void Send(bool compress, ref byte[] buffer, ref int length)
|
||||
{
|
||||
if (compress)
|
||||
{
|
||||
Compress(ref buffer, ref length);
|
||||
}
|
||||
|
||||
if (buffer.Length > Client.SendBufferSize)
|
||||
{
|
||||
Client.SendBufferSize = Math.Min(1048576, buffer.Length);
|
||||
}
|
||||
|
||||
Stream.Write(buffer, 0, length);
|
||||
|
||||
WebAPI.CSOptions.ToConsole(
|
||||
"Sent {0:#,0} bytes ({1:#,0} bytes/write)",
|
||||
length,
|
||||
Math.Min(length, Client.SendBufferSize));
|
||||
}
|
||||
|
||||
private static bool Sequence(byte b, ref int seq)
|
||||
{
|
||||
switch (b)
|
||||
{
|
||||
case 13:
|
||||
{
|
||||
if (seq % 2 == 0)
|
||||
{
|
||||
++seq;
|
||||
}
|
||||
else
|
||||
{
|
||||
seq = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
{
|
||||
if (seq % 2 == 1)
|
||||
{
|
||||
++seq;
|
||||
}
|
||||
else
|
||||
{
|
||||
seq = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
seq = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return seq > 0;
|
||||
}
|
||||
|
||||
public bool ReceiveHeaders(out KeyValueString[] headers)
|
||||
{
|
||||
headers = _EmptyHeaders;
|
||||
|
||||
var buffer = _EmptyBuffer;
|
||||
var length = 0;
|
||||
|
||||
if (Stream.CanRead)
|
||||
{
|
||||
VitaNexCore.WaitWhile(() => !Stream.DataAvailable, TimeSpan.FromMilliseconds(1000));
|
||||
|
||||
if (Stream.DataAvailable)
|
||||
{
|
||||
buffer = new byte[Client.ReceiveBufferSize];
|
||||
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
int idx = 0, seq = 0;
|
||||
|
||||
while (Stream.DataAvailable)
|
||||
{
|
||||
var r = Stream.ReadByte();
|
||||
|
||||
if (r > -1)
|
||||
{
|
||||
if (++length > WebAPI.CSOptions.MaxReceiveBufferSizeBytes)
|
||||
{
|
||||
throw new InternalBufferOverflowException(
|
||||
String.Format("Received data exceeded {0:#,0} bytes", WebAPI.CSOptions.MaxReceiveBufferSizeBytes));
|
||||
}
|
||||
|
||||
var b = (byte)r;
|
||||
|
||||
buffer[idx++] = b;
|
||||
|
||||
if (Sequence(b, ref seq) && seq >= 4)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (idx >= buffer.Length)
|
||||
{
|
||||
ms.Write(buffer, 0, idx);
|
||||
idx = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (idx > 0)
|
||||
{
|
||||
ms.Write(buffer, 0, idx);
|
||||
}
|
||||
|
||||
buffer = ms.ToArray();
|
||||
length = buffer.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WebAPI.CSOptions.ToConsole(
|
||||
"Received {0:#,0} bytes ({1:#,0} bytes/read)",
|
||||
length,
|
||||
Math.Min(length, Client.ReceiveBufferSize));
|
||||
|
||||
if (length <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var raw = Encoding.ASCII.GetString(buffer, 0, length);
|
||||
|
||||
if (String.IsNullOrWhiteSpace(raw))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var h = raw.Split(_Separators, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if (h.Length == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
headers = ParseHeaders(h).ToArray();
|
||||
|
||||
return headers.Length > 0;
|
||||
}
|
||||
|
||||
public void Receive(bool decompress, Encoding enc, out string content, out byte[] buffer, out int length)
|
||||
{
|
||||
content = String.Empty;
|
||||
buffer = _EmptyBuffer;
|
||||
length = 0;
|
||||
|
||||
if (Stream.CanRead)
|
||||
{
|
||||
VitaNexCore.WaitWhile(() => !Stream.DataAvailable, TimeSpan.FromMilliseconds(1000));
|
||||
|
||||
if (Stream.DataAvailable)
|
||||
{
|
||||
buffer = new byte[Client.ReceiveBufferSize];
|
||||
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
while (Stream.DataAvailable)
|
||||
{
|
||||
length = Stream.Read(buffer, 0, buffer.Length);
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
if (ms.Length + length > WebAPI.CSOptions.MaxReceiveBufferSizeBytes)
|
||||
{
|
||||
throw new InternalBufferOverflowException(
|
||||
String.Format("Received data exceeded {0:#,0} bytes", WebAPI.CSOptions.MaxReceiveBufferSizeBytes));
|
||||
}
|
||||
|
||||
ms.SetLength(ms.Length + length);
|
||||
ms.Write(buffer, 0, length);
|
||||
}
|
||||
}
|
||||
|
||||
buffer = ms.ToArray();
|
||||
length = buffer.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WebAPI.CSOptions.ToConsole(
|
||||
"Received {0:#,0} bytes ({1:#,0} bytes/read)",
|
||||
length,
|
||||
Math.Min(length, Client.ReceiveBufferSize));
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
if (decompress)
|
||||
{
|
||||
Decompress(ref buffer, ref length);
|
||||
}
|
||||
|
||||
Decode(enc, buffer, length, out content);
|
||||
}
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
Close(false);
|
||||
}
|
||||
|
||||
public void Close(bool disconnecting)
|
||||
{
|
||||
if (IsDisposed || !Client.Connected)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
VitaNexCore.TryCatch(
|
||||
() =>
|
||||
{
|
||||
if (!disconnecting)
|
||||
{
|
||||
WebAPI.Disconnect(this);
|
||||
}
|
||||
|
||||
if (Stream != null)
|
||||
{
|
||||
using (Stream)
|
||||
{
|
||||
Stream.Close();
|
||||
}
|
||||
}
|
||||
|
||||
if (Client != null)
|
||||
{
|
||||
Client.Close();
|
||||
}
|
||||
},
|
||||
WebAPI.CSOptions.ToConsole);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (IsDisposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Close(false);
|
||||
|
||||
IsDisposed = true;
|
||||
|
||||
Client = null;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (Client == null || Client.Client == null || Client.Client.RemoteEndPoint == null)
|
||||
{
|
||||
return "?.?.?.?:?";
|
||||
}
|
||||
|
||||
return Client.Client.RemoteEndPoint.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
#region Header
|
||||
// _,-'/-'/
|
||||
// . __,-; ,'( '/
|
||||
// \. `-.__`-._`:_,-._ _ , . ``
|
||||
// `:-._,------' ` _,`--` -: `_ , ` ,' :
|
||||
// `---..__,,--' (C) 2023 ` -'. -'
|
||||
// # Vita-Nex [http://core.vita-nex.com] #
|
||||
// {o)xxx|===============- # -===============|xxx(o}
|
||||
// # #
|
||||
#endregion
|
||||
|
||||
#region References
|
||||
using System;
|
||||
#endregion
|
||||
|
||||
namespace VitaNex.Web
|
||||
{
|
||||
public class WebAPIContext : IDisposable
|
||||
{
|
||||
public WebAPIClient Client { get; private set; }
|
||||
|
||||
public WebAPIMethod Method { get; private set; }
|
||||
public string Uri { get; private set; }
|
||||
|
||||
public WebAPIRequest Request { get; private set; }
|
||||
public WebAPIResponse Response { get; private set; }
|
||||
|
||||
public bool Authorized { get; set; }
|
||||
|
||||
public WebAPIContext(WebAPIClient client, WebAPIMethod method, string uri)
|
||||
{
|
||||
Client = client;
|
||||
|
||||
Method = method;
|
||||
Uri = uri;
|
||||
|
||||
Request = new WebAPIRequest(Client);
|
||||
Response = new WebAPIResponse(Client);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Client = null;
|
||||
|
||||
Method = WebAPIMethod.UNKNOWN;
|
||||
Uri = null;
|
||||
|
||||
Request.Dispose();
|
||||
Request = null;
|
||||
|
||||
Response.Dispose();
|
||||
Response = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#region Header
|
||||
// _,-'/-'/
|
||||
// . __,-; ,'( '/
|
||||
// \. `-.__`-._`:_,-._ _ , . ``
|
||||
// `:-._,------' ` _,`--` -: `_ , ` ,' :
|
||||
// `---..__,,--' (C) 2023 ` -'. -'
|
||||
// # Vita-Nex [http://core.vita-nex.com] #
|
||||
// {o)xxx|===============- # -===============|xxx(o}
|
||||
// # #
|
||||
#endregion
|
||||
|
||||
#region References
|
||||
using System;
|
||||
#endregion
|
||||
|
||||
namespace VitaNex.Web
|
||||
{
|
||||
public class WebAPIHandler
|
||||
{
|
||||
public string Uri { get; private set; }
|
||||
|
||||
public Action<WebAPIContext> Handler { get; set; }
|
||||
|
||||
public WebAPIHandler(string uri, Action<WebAPIContext> handler)
|
||||
{
|
||||
Uri = uri;
|
||||
Handler = handler;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Uri.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
#region Header
|
||||
// _,-'/-'/
|
||||
// . __,-; ,'( '/
|
||||
// \. `-.__`-._`:_,-._ _ , . ``
|
||||
// `:-._,------' ` _,`--` -: `_ , ` ,' :
|
||||
// `---..__,,--' (C) 2023 ` -'. -'
|
||||
// # Vita-Nex [http://core.vita-nex.com] #
|
||||
// {o)xxx|===============- # -===============|xxx(o}
|
||||
// # #
|
||||
#endregion
|
||||
|
||||
#region References
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
#endregion
|
||||
|
||||
namespace VitaNex.Web
|
||||
{
|
||||
public class WebAPIHeaders : IDisposable, IEnumerable<KeyValuePair<string, string>>
|
||||
{
|
||||
private Dictionary<string, string> _Headers;
|
||||
|
||||
public string this[string header]
|
||||
{
|
||||
get => _Headers.GetValue(header);
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
_Headers.Remove(header);
|
||||
}
|
||||
else
|
||||
{
|
||||
_Headers[header] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int Count => _Headers.Count;
|
||||
|
||||
public WebAPIHeaders()
|
||||
{
|
||||
_Headers = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public WebAPIHeaders(IEnumerable<KeyValuePair<string, string>> headers)
|
||||
: this()
|
||||
{
|
||||
foreach (var kv in headers.Ensure())
|
||||
{
|
||||
this[kv.Key] = kv.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_Headers.Clear();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_Headers = null;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Join("\r\n", _Headers.Select(kv => String.Format("{0}: {1}", kv.Key, kv.Value))) + "\r\n\r\n";
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
|
||||
{
|
||||
return _Headers.GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#region Header
|
||||
// _,-'/-'/
|
||||
// . __,-; ,'( '/
|
||||
// \. `-.__`-._`:_,-._ _ , . ``
|
||||
// `:-._,------' ` _,`--` -: `_ , ` ,' :
|
||||
// `---..__,,--' (C) 2023 ` -'. -'
|
||||
// # Vita-Nex [http://core.vita-nex.com] #
|
||||
// {o)xxx|===============- # -===============|xxx(o}
|
||||
// # #
|
||||
#endregion
|
||||
|
||||
namespace VitaNex.Web
|
||||
{
|
||||
public enum WebAPIMethod
|
||||
{
|
||||
UNKNOWN = 0,
|
||||
OPTIONS,
|
||||
GET,
|
||||
HEAD,
|
||||
POST,
|
||||
PUT,
|
||||
DELETE,
|
||||
TRACE,
|
||||
CONNECT
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
#region Header
|
||||
// _,-'/-'/
|
||||
// . __,-; ,'( '/
|
||||
// \. `-.__`-._`:_,-._ _ , . ``
|
||||
// `:-._,------' ` _,`--` -: `_ , ` ,' :
|
||||
// `---..__,,--' (C) 2023 ` -'. -'
|
||||
// # Vita-Nex [http://core.vita-nex.com] #
|
||||
// {o)xxx|===============- # -===============|xxx(o}
|
||||
// # #
|
||||
#endregion
|
||||
|
||||
#region References
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
#endregion
|
||||
|
||||
namespace VitaNex.Web
|
||||
{
|
||||
public class WebAPIQueries : IDisposable, IEnumerable<KeyValuePair<string, string>>
|
||||
{
|
||||
private Dictionary<string, string> _Queries;
|
||||
|
||||
public string this[string query]
|
||||
{
|
||||
get => _Queries.GetValue(query);
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
_Queries.Remove(query);
|
||||
}
|
||||
else
|
||||
{
|
||||
_Queries[query] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int Count => _Queries.Count;
|
||||
|
||||
public WebAPIQueries()
|
||||
{
|
||||
_Queries = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public WebAPIQueries(IEnumerable<KeyValuePair<string, string>> queries)
|
||||
: this()
|
||||
{
|
||||
foreach (var kv in queries.Ensure())
|
||||
{
|
||||
this[kv.Key] = kv.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public WebAPIQueries(string query)
|
||||
: this(WebAPI.DecodeQuery(query))
|
||||
{ }
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_Queries.Clear();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_Queries = null;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return WebAPI.EncodeQuery(_Queries);
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
|
||||
{
|
||||
return _Queries.GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
#region Header
|
||||
// _,-'/-'/
|
||||
// . __,-; ,'( '/
|
||||
// \. `-.__`-._`:_,-._ _ , . ``
|
||||
// `:-._,------' ` _,`--` -: `_ , ` ,' :
|
||||
// `---..__,,--' (C) 2023 ` -'. -'
|
||||
// # Vita-Nex [http://core.vita-nex.com] #
|
||||
// {o)xxx|===============- # -===============|xxx(o}
|
||||
// # #
|
||||
#endregion
|
||||
|
||||
#region References
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
using VitaNex.IO;
|
||||
#endregion
|
||||
|
||||
namespace VitaNex.Web
|
||||
{
|
||||
public class WebAPIRequest : IDisposable
|
||||
{
|
||||
public WebAPIClient Client { get; private set; }
|
||||
|
||||
public WebAPIHeaders Headers { get; private set; }
|
||||
public WebAPIQueries Queries { get; private set; }
|
||||
|
||||
public FileMime ContentType { get; set; }
|
||||
public Encoding Encoding { get; set; }
|
||||
public string Data { get; set; }
|
||||
public int Length { get; set; }
|
||||
|
||||
public WebAPIRequest(WebAPIClient client)
|
||||
{
|
||||
Client = client;
|
||||
|
||||
Headers = new WebAPIHeaders();
|
||||
Queries = new WebAPIQueries();
|
||||
|
||||
ContentType = FileMime.Default;
|
||||
Encoding = Encoding.UTF8;
|
||||
|
||||
Data = String.Empty;
|
||||
Length = 0;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Headers.Dispose();
|
||||
Headers = null;
|
||||
|
||||
Queries.Dispose();
|
||||
Queries = null;
|
||||
|
||||
Encoding = null;
|
||||
|
||||
Data = null;
|
||||
Length = 0;
|
||||
|
||||
Client = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
#region Header
|
||||
// _,-'/-'/
|
||||
// . __,-; ,'( '/
|
||||
// \. `-.__`-._`:_,-._ _ , . ``
|
||||
// `:-._,------' ` _,`--` -: `_ , ` ,' :
|
||||
// `---..__,,--' (C) 2023 ` -'. -'
|
||||
// # Vita-Nex [http://core.vita-nex.com] #
|
||||
// {o)xxx|===============- # -===============|xxx(o}
|
||||
// # #
|
||||
#endregion
|
||||
|
||||
#region References
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
|
||||
using VitaNex.IO;
|
||||
#endregion
|
||||
|
||||
namespace VitaNex.Web
|
||||
{
|
||||
public class WebAPIResponse : IDisposable
|
||||
{
|
||||
public WebAPIClient Client { get; private set; }
|
||||
public WebAPIHeaders Headers { get; private set; }
|
||||
|
||||
public HttpStatusCode Status { get; set; }
|
||||
public FileMime ContentType { get; set; }
|
||||
public Encoding Encoding { get; set; }
|
||||
public object Data { get; set; }
|
||||
|
||||
public bool Compress { get; set; }
|
||||
public bool FreeData { get; set; }
|
||||
|
||||
public string FileName { get; set; }
|
||||
public int Cache { get; set; }
|
||||
|
||||
public WebAPIResponse(WebAPIClient client)
|
||||
{
|
||||
Client = client;
|
||||
|
||||
Headers = new WebAPIHeaders();
|
||||
|
||||
Compress = false;
|
||||
FreeData = true;
|
||||
|
||||
Cache = -1;
|
||||
FileName = String.Empty;
|
||||
Encoding = Encoding.UTF8;
|
||||
|
||||
Status = HttpStatusCode.OK;
|
||||
ContentType = FileMime.Default;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (FreeData && Data is IDisposable)
|
||||
{
|
||||
((IDisposable)Data).Dispose();
|
||||
}
|
||||
|
||||
Data = null;
|
||||
|
||||
Headers.Dispose();
|
||||
Headers = null;
|
||||
|
||||
Cache = -1;
|
||||
FileName = "public.html";
|
||||
Encoding = null;
|
||||
|
||||
Client = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
#region Header
|
||||
// _,-'/-'/
|
||||
// . __,-; ,'( '/
|
||||
// \. `-.__`-._`:_,-._ _ , . ``
|
||||
// `:-._,------' ` _,`--` -: `_ , ` ,' :
|
||||
// `---..__,,--' (C) 2023 ` -'. -'
|
||||
// # Vita-Nex [http://core.vita-nex.com] #
|
||||
// {o)xxx|===============- # -===============|xxx(o}
|
||||
// # #
|
||||
#endregion
|
||||
|
||||
#region References
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Server;
|
||||
#endregion
|
||||
|
||||
namespace VitaNex.Web
|
||||
{
|
||||
public class WebAPIOptions : CoreServiceOptions
|
||||
{
|
||||
public List<string> Whitelist { get; private set; }
|
||||
public List<string> Blacklist { get; private set; }
|
||||
|
||||
[CommandProperty(WebAPI.Access)]
|
||||
public bool UseWhitelist { get; set; }
|
||||
|
||||
[CommandProperty(WebAPI.Access)]
|
||||
public short Port { get; set; }
|
||||
|
||||
[CommandProperty(WebAPI.Access)]
|
||||
public int MaxConnections { get; set; }
|
||||
|
||||
[CommandProperty(WebAPI.Access)]
|
||||
public int MaxSendBufferSize { get; set; }
|
||||
|
||||
[CommandProperty(WebAPI.Access)]
|
||||
public int MaxReceiveBufferSize { get; set; }
|
||||
|
||||
[CommandProperty(WebAPI.Access)]
|
||||
public int MaxSendBufferSizeBytes => MaxSendBufferSize * 1024 * 1024;
|
||||
|
||||
[CommandProperty(WebAPI.Access)]
|
||||
public int MaxReceiveBufferSizeBytes => MaxReceiveBufferSize * 1024 * 1024;
|
||||
|
||||
[CommandProperty(WebAPI.Access)]
|
||||
public bool DirectoryIndex { get; set; }
|
||||
|
||||
[CommandProperty(WebAPI.Access)]
|
||||
public bool WebServer { get; set; }
|
||||
|
||||
public WebAPIOptions()
|
||||
: base(typeof(WebAPI))
|
||||
{
|
||||
Whitelist = new List<string>();
|
||||
Blacklist = new List<string>();
|
||||
|
||||
Port = 2595;
|
||||
MaxConnections = 500;
|
||||
MaxSendBufferSize = 32;
|
||||
MaxReceiveBufferSize = 32;
|
||||
|
||||
UseWhitelist = false;
|
||||
WebServer = true;
|
||||
DirectoryIndex = true;
|
||||
}
|
||||
|
||||
public WebAPIOptions(GenericReader reader)
|
||||
: base(reader)
|
||||
{ }
|
||||
|
||||
public override void Clear()
|
||||
{
|
||||
base.Clear();
|
||||
|
||||
Whitelist.Clear();
|
||||
Blacklist.Clear();
|
||||
|
||||
Port = 80;
|
||||
MaxConnections = 500;
|
||||
MaxSendBufferSize = 32;
|
||||
MaxReceiveBufferSize = 32;
|
||||
|
||||
UseWhitelist = false;
|
||||
WebServer = false;
|
||||
DirectoryIndex = false;
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
|
||||
Whitelist.Clear();
|
||||
Blacklist.Clear();
|
||||
|
||||
Port = 80;
|
||||
MaxConnections = 500;
|
||||
MaxSendBufferSize = 32;
|
||||
MaxReceiveBufferSize = 32;
|
||||
|
||||
UseWhitelist = false;
|
||||
WebServer = false;
|
||||
DirectoryIndex = false;
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
var version = writer.SetVersion(4);
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 4:
|
||||
{
|
||||
writer.Write(WebServer);
|
||||
writer.Write(DirectoryIndex);
|
||||
}
|
||||
goto case 3;
|
||||
case 3:
|
||||
case 2:
|
||||
{
|
||||
writer.Write(MaxSendBufferSize);
|
||||
writer.Write(MaxReceiveBufferSize);
|
||||
}
|
||||
goto case 1;
|
||||
case 1:
|
||||
{
|
||||
writer.WriteList(Whitelist, (w, m) => w.Write(m));
|
||||
writer.WriteList(Blacklist, (w, m) => w.Write(m));
|
||||
|
||||
writer.Write(UseWhitelist);
|
||||
}
|
||||
goto case 0;
|
||||
case 0:
|
||||
{
|
||||
writer.Write(Port);
|
||||
writer.Write(MaxConnections);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
var version = reader.GetVersion();
|
||||
|
||||
if (version < 3)
|
||||
{
|
||||
MaxSendBufferSize = 32;
|
||||
MaxReceiveBufferSize = 32;
|
||||
}
|
||||
|
||||
if (version < 2)
|
||||
{
|
||||
Whitelist = new List<string>();
|
||||
Blacklist = new List<string>();
|
||||
}
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 4:
|
||||
{
|
||||
WebServer = reader.ReadBool();
|
||||
DirectoryIndex = reader.ReadBool();
|
||||
}
|
||||
goto case 3;
|
||||
case 3:
|
||||
case 2:
|
||||
{
|
||||
MaxSendBufferSize = reader.ReadInt();
|
||||
MaxReceiveBufferSize = reader.ReadInt();
|
||||
}
|
||||
goto case 1;
|
||||
case 1:
|
||||
{
|
||||
Whitelist = reader.ReadList(r => r.ReadString(), Whitelist);
|
||||
Blacklist = reader.ReadList(r => r.ReadString(), Blacklist);
|
||||
|
||||
UseWhitelist = reader.ReadBool();
|
||||
}
|
||||
goto case 0;
|
||||
case 0:
|
||||
{
|
||||
Port = reader.ReadShort();
|
||||
MaxConnections = reader.ReadInt();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1371
Scripts/SubSystem/VitaNex/Core/Services/WebAPI/WebAPI.cs
Normal file
1371
Scripts/SubSystem/VitaNex/Core/Services/WebAPI/WebAPI.cs
Normal file
File diff suppressed because it is too large
Load Diff
100
Scripts/SubSystem/VitaNex/Core/Services/WebAPI/WebAPI_Init.cs
Normal file
100
Scripts/SubSystem/VitaNex/Core/Services/WebAPI/WebAPI_Init.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
#region Header
|
||||
// _,-'/-'/
|
||||
// . __,-; ,'( '/
|
||||
// \. `-.__`-._`:_,-._ _ , . ``
|
||||
// `:-._,------' ` _,`--` -: `_ , ` ,' :
|
||||
// `---..__,,--' (C) 2023 ` -'. -'
|
||||
// # Vita-Nex [http://core.vita-nex.com] #
|
||||
// {o)xxx|===============- # -===============|xxx(o}
|
||||
// # #
|
||||
#endregion
|
||||
|
||||
#region References
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
|
||||
using Server;
|
||||
using Server.Misc;
|
||||
#endregion
|
||||
|
||||
namespace VitaNex.Web
|
||||
{
|
||||
[CoreService("Web API", "3.0.0.1")]
|
||||
public static partial class WebAPI
|
||||
{
|
||||
static WebAPI()
|
||||
{
|
||||
CSOptions = new WebAPIOptions();
|
||||
|
||||
Clients = new List<WebAPIClient>();
|
||||
|
||||
Handlers = new Dictionary<string, WebAPIHandler>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
_ActivityTimer = PollTimer.FromSeconds(
|
||||
60.0,
|
||||
() =>
|
||||
{
|
||||
if (!_Listening || Listener == null || Listener.Server == null || !Listener.Server.IsBound)
|
||||
{
|
||||
_Listening = false;
|
||||
ListenerUtility.ListenAsync();
|
||||
}
|
||||
|
||||
Clients.RemoveAll(c => !c.Connected);
|
||||
},
|
||||
() => Clients.Count > 0,
|
||||
false);
|
||||
|
||||
ServicePointManager.SecurityProtocol = (SecurityProtocolType)0x3FC0; // Tls, Tls11, Tls12, Tls13
|
||||
}
|
||||
|
||||
private static void CSConfig()
|
||||
{
|
||||
if (_ServerStarted)
|
||||
{
|
||||
ListenerUtility.ListenAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
EventSink.ServerStarted += () =>
|
||||
{
|
||||
_ServerStarted = true;
|
||||
|
||||
ListenerUtility.ListenAsync();
|
||||
};
|
||||
|
||||
var t = typeof(StatusPage);
|
||||
var f = t.GetField("Enabled", BindingFlags.Public | BindingFlags.Static);
|
||||
|
||||
if (f != null)
|
||||
{
|
||||
f.SetValue(null, false);
|
||||
}
|
||||
}
|
||||
|
||||
private static void CSInvoke()
|
||||
{
|
||||
_ActivityTimer.Start();
|
||||
|
||||
Register("/", HandleRoot);
|
||||
}
|
||||
|
||||
private static void CSDisposed()
|
||||
{
|
||||
Clients.ForEachReverse(c => c.Close());
|
||||
|
||||
_ActivityTimer.Stop();
|
||||
_ActivityTimer = null;
|
||||
|
||||
if (Listener == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Listener.Stop();
|
||||
Listener = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user