Overwrite

Complete Overwrite of the Folder with the free shard. ServUO 57.3 has been added.
This commit is contained in:
Unstable Kitsune
2023-11-28 23:20:26 -05:00
parent 3cd54811de
commit b918192e4e
11608 changed files with 2644205 additions and 47 deletions

View File

@@ -0,0 +1,136 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Net.Sockets;
using Server;
using Server.Network;
using VitaNex.Crypto;
#endregion
namespace VitaNex.Modules.WebSockets
{
public sealed class WebSocketsClientKey : CryptoHashCode
{
public override string Value => base.Value.Replace("-", String.Empty);
public WebSocketsClientKey(string key)
: base(CryptoHashType.SHA1, String.Concat(key, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"))
{ }
public WebSocketsClientKey(GenericReader reader)
: base(reader)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
public sealed class WebSocketsClient : NetState
{
public WebSocketsClientKey Key { get; private set; }
public TcpClient TcpClient { get; private set; }
public bool Connected => TcpClient != null && TcpClient.Connected;
public WebSocketsClient(TcpClient client, MessagePump p)
: base(client.Client, p)
{
TcpClient = client;
}
public WebSocketsClientKey ResolveKey(string key)
{
return Key ?? (Key = new WebSocketsClientKey(key));
}
/*
public override void Dispose(bool flush)
{
base.Dispose(flush);
}
public override void Send(Packet p)
{
base.Send(p);
}
public override string ToString()
{
return base.ToString();
}*/
/*
public override int GetHashCode()
{
return base.GetHashCode();
}
public override bool Equals(object obj)
{
return base.Equals(obj);
}*/
/*
public void Send(Packet p)
{
if (Connected)
{
NetState.Send(p);
}
}
public void Flush()
{
if (Connected)
{
NetState.Flush();
}
}
public override void Dispose()
{
VitaNexCore.TryCatch(() =>
{
if (!Connected)
{
return;
}
WebSockets.Disconnected(this);
NetState.Dispose();
NetState = null;
}, e =>
{
lock (WebSockets.Clients)
{
WebSockets.Clients.Remove(this);
}
WebSockets.CMOptions.ToConsole(e);
});
}*/
}
}

View File

@@ -0,0 +1,87 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
#endregion
namespace VitaNex.Modules.WebSockets
{
public class WebSocketsOptions : CoreModuleOptions
{
[CommandProperty(WebSockets.Access)]
public int Port { get; set; }
[CommandProperty(WebSockets.Access)]
public int MaxConnections { get; set; }
public WebSocketsOptions()
: base(typeof(WebSockets))
{
Port = 2594;
MaxConnections = 1000;
}
public WebSocketsOptions(GenericReader reader)
: base(reader)
{ }
public override void Clear()
{
base.Clear();
Port = 2594;
MaxConnections = 1000;
}
public override void Reset()
{
base.Reset();
Port = 2594;
MaxConnections = 1000;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{
writer.Write(Port);
writer.Write(MaxConnections);
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
{
Port = reader.ReadInt();
MaxConnections = reader.ReadInt();
}
break;
}
}
}
}

View File

@@ -0,0 +1,452 @@
#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;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Reflection;
using System.Text;
using Server;
using Server.Misc;
#endregion
namespace VitaNex.Modules.WebSockets
{
public static partial class WebSockets
{
public const AccessLevel Access = AccessLevel.Administrator;
private static bool _Started;
private static readonly PollTimer _ActivityTimer;
public static TcpListener Listener { get; private set; }
public static List<WebSocketsClient> Clients { get; private set; }
public static event Action<WebSocketsClient> OnConnected;
public static event Action<WebSocketsClient> OnDisconnected;
private static readonly MethodInfo _IsPrivateNetwork = //
typeof(ServerList).GetMethod("IsPrivateNetwork", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
private static void AcquireListener()
{
if (!CMOptions.ModuleEnabled)
{
ReleaseListener();
return;
}
if (Listener != null && ((IPEndPoint)Listener.LocalEndpoint).Port != CMOptions.Port)
{
ReleaseListener();
}
if (Listener == null)
{
var address = NetworkInterface.GetAllNetworkInterfaces()
.Select(adapter => adapter.GetIPProperties())
.Select(
properties => properties.UnicastAddresses.Select(unicast => unicast.Address)
.FirstOrDefault(
ip => !IPAddress.IsLoopback(ip) && ip.AddressFamily != AddressFamily.InterNetworkV6 &&
(_IsPrivateNetwork == null || (bool)_IsPrivateNetwork.Invoke(null, new object[] { ip }))))
.FirstOrDefault() ?? IPAddress.Any;
Listener = new TcpListener(address, CMOptions.Port);
}
if (!Listener.Server.IsBound)
{
Listener.Start(CMOptions.MaxConnections);
CMOptions.ToConsole("Listening: {0}", Listener.LocalEndpoint);
}
_Listening = true;
}
private static void ReleaseListener()
{
if (Listener == null)
{
return;
}
VitaNexCore.TryCatch(
() =>
{
if (Listener.Server.IsBound)
{
Listener.Server.Disconnect(true);
}
});
VitaNexCore.TryCatch(Listener.Stop);
Listener = null;
_Listening = false;
}
private static bool _Listening;
private static void ListenAsync()
{
AcquireListener();
if (Listener == null)
{
return;
}
VitaNexCore.TryCatch(
() => Listener.BeginAcceptTcpClient(
r =>
{
var client = VitaNexCore.TryCatchGet(() => Listener.EndAcceptTcpClient(r), CMOptions.ToConsole);
if (client != null && client.Connected)
{
VitaNexCore.TryCatch(() => Connected(client), CMOptions.ToConsole);
}
ListenAsync();
},
null),
e =>
{
_Listening = false;
CMOptions.ToConsole(e);
});
}
private static void Connected(TcpClient tcp)
{
if (tcp == null)
{
return;
}
VitaNexCore.TryCatch(
() =>
{
if (Listener != null && _Started)
{
Connected(new WebSocketsClient(tcp, Core.MessagePump));
}
else
{
tcp.Close();
}
},
CMOptions.ToConsole);
}
private static void Connected(WebSocketsClient client)
{
lock (Clients)
{
if (!Clients.Contains(client))
{
Clients.Add(client);
}
}
CMOptions.ToConsole("[{0}] Client connected: {1}", Clients.Count, client.Address);
if (OnConnected != null)
{
VitaNexCore.TryCatch(
() => OnConnected(client),
e =>
{
CMOptions.ToConsole(e);
client.Dispose();
Disconnected(client);
});
}
}
private static void Disconnected(WebSocketsClient client)
{
if (OnDisconnected != null)
{
VitaNexCore.TryCatch(() => OnDisconnected(client), CMOptions.ToConsole);
}
lock (Clients)
{
Clients.Remove(client);
}
CMOptions.ToConsole("[{0}] Client disconnected: {1}", Clients.Count, client.Address);
client.Dispose();
}
private static void Encode(string data, out byte[] buffer, out int length)
{
length = Encoding.UTF8.GetByteCount(data);
buffer = new byte[length];
Encoding.UTF8.GetBytes(data, 0, data.Length, buffer, 0);
}
private static void Decode(byte[] src, out string data)
{
data = Encoding.UTF8.GetString(src);
}
private static void Compress(ref byte[] buffer, ref int length)
{
using (MemoryStream inS = new MemoryStream(buffer.Take(length).ToArray()), outS = new MemoryStream())
{
using (var ds = new DeflateStream(outS, CompressionMode.Compress))
{
inS.CopyTo(ds);
outS.Position = 0;
}
buffer = outS.ToArray();
length = buffer.Length;
}
}
private static void Decompress(ref byte[] buffer, ref int length)
{
using (MemoryStream inS = new MemoryStream(buffer.Take(length).ToArray()), outS = new MemoryStream())
{
using (var ds = new DeflateStream(inS, CompressionMode.Decompress))
{
ds.CopyTo(outS);
outS.Position = 0;
}
buffer = outS.ToArray();
length = buffer.Length;
}
}
private static void Send(
WebSocketsClient client,
string data,
bool encode,
bool compress,
Action<WebSocketsClient, byte[]> callback)
{
VitaNexCore.TryCatch(
() =>
{
int len;
byte[] buffer;
if (encode)
{
Encode(data, out buffer, out len);
}
else
{
buffer = data.Select(c => (byte)c).ToArray();
len = buffer.Length;
}
Send(client, buffer, len, compress, callback);
},
CMOptions.ToConsole);
}
private static void Send(
WebSocketsClient client,
byte[] buffer,
int len,
bool compress,
Action<WebSocketsClient, byte[]> callback)
{
var stream = client.TcpClient.GetStream();
if (compress)
{
Compress(ref buffer, ref len);
}
var count = 0;
while (count < len)
{
var block = buffer.Skip(count).Take(client.TcpClient.SendBufferSize).ToArray();
stream.Write(block, 0, block.Length);
count += block.Length;
}
if (callback != null)
{
callback(client, buffer);
}
}
private static void Receive(
WebSocketsClient client,
bool decompress,
bool decode,
Action<WebSocketsClient, string, byte[]> callback)
{
VitaNexCore.TryCatch(
() =>
{
var stream = client.TcpClient.GetStream();
var buffer = new byte[client.TcpClient.ReceiveBufferSize];
var len = buffer.Length;
stream.Read(buffer, 0, buffer.Length);
if (decompress)
{
Decompress(ref buffer, ref len);
}
string data;
if (decode)
{
Decode(buffer, out data);
}
else
{
data = new string(buffer.Select(b => (char)b).ToArray());
}
if (callback != null)
{
callback(client, data, buffer);
}
},
CMOptions.ToConsole);
}
private static void HandleConnection(WebSocketsClient client)
{
VitaNexCore.TryCatch(
() =>
{
if (client.Seeded)
{
return;
}
var headers = new Dictionary<string, string>();
Receive(
client,
false,
true,
(c, d, b) =>
{
if (d.Length == 0)
{
return;
}
var lines = d.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
lines = lines.Take(lines.Length - 1).ToArray();
if (CMOptions.ModuleDebug)
{
CMOptions.ToConsole(lines.Not(String.IsNullOrWhiteSpace).ToArray());
}
lines.ForEach(
line =>
{
line = line.Trim();
var header = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (header.Length == 0)
{
return;
}
var hk = header[0].Replace(":", String.Empty);
if (String.IsNullOrWhiteSpace(hk))
{
return;
}
var hv = header.Length > 1 ? String.Join(" ", header.Skip(1)) : String.Empty;
if (!headers.ContainsKey(hk))
{
headers.Add(hk, hv);
}
else
{
headers[hk] = hv;
}
});
});
if (headers.Count > 0)
{
HandleHttpRequest(client, headers);
}
else
{
throw new Exception("No headers defined for WebSockets client handshake.", new SocketException());
}
},
CMOptions.ToConsole);
}
private static void HandleHttpRequest(WebSocketsClient client, Dictionary<string, string> headers)
{
//var uri = headers["GET"];
//var origin = headers["Origin"];
var key = client.ResolveKey(headers["Sec-WebSocket-Key"]);
var answer = Convert.ToBase64String(Encoding.ASCII.GetBytes(key.Value));
var sendHeaders = new List<string>
{
"HTTP/1.1 101 Switching Protocols", //
"Connection: Upgrade", //
"Sec-WebSocket-Accept: " + answer, //
"Upgrade: websocket" //
};
Send(client, String.Join("\r\n", sendHeaders) + "\r\n\r\n", false, false, (c, d) => client.Start());
if (!CMOptions.ModuleDebug)
{
return;
}
CMOptions.ToConsole("HEADERS>>>\n");
CMOptions.ToConsole(sendHeaders.ToArray());
}
}
}

View File

@@ -0,0 +1,93 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System.Collections.Generic;
using Server;
using Server.Network;
#endregion
namespace VitaNex.Modules.WebSockets
{
[CoreModule("Web Sockets", "1.0.0.1")]
public static partial class WebSockets
{
public static WebSocketsOptions CMOptions { get; private set; }
static WebSockets()
{
CMOptions = new WebSocketsOptions();
EventSink.ServerStarted += () => _Started = true;
Clients = new List<WebSocketsClient>();
OnConnected += HandleConnection;
_ActivityTimer = PollTimer.FromSeconds(
60.0,
() =>
{
if (!_Listening || Listener == null || Listener.Server == null || !Listener.Server.IsBound)
{
_Listening = false;
ListenAsync();
}
Clients.RemoveAll(c => !c.Connected);
},
() => CMOptions.ModuleEnabled && Clients.Count > 0);
NetState.CreatedCallback += ns =>
{
if (ns is WebSocketsClient)
{
var client = (WebSocketsClient)ns;
client.CompressionEnabled = false;
}
};
}
private static void CMInvoke()
{
ListenAsync();
}
private static void CMEnabled()
{
ListenAsync();
}
private static void CMDisabled()
{
ReleaseListener();
}
private static void CMSave()
{ }
private static void CMLoad()
{ }
private static void CMDisposed()
{
if (Listener == null)
{
return;
}
Listener.Stop();
Listener = null;
}
}
}