Make WebSocketClient use ObjectManager

This commit is contained in:
Alessandro Proto 2023-02-12 11:20:02 +01:00
parent f9f56c8063
commit 4143417947
2 changed files with 101 additions and 42 deletions

View file

@ -5,7 +5,6 @@ using KeraLua;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Net.WebSockets; using System.Net.WebSockets;
@ -19,7 +18,7 @@ public class HTTP : IPlugin
private static IGame _game; private static IGame _game;
private static HttpClient _httpClient; private static HttpClient _httpClient;
private static long _requestId; private static long _requestId;
public static readonly HashSet<WebSocketClient> WebSocketConnections = new(); public static readonly HashSet<WebSocketClient.Client> WebSocketConnections = new();
public static readonly string UserAgent = $"Capy64/{Capy64.Version}"; public static readonly string UserAgent = $"Capy64/{Capy64.Version}";
@ -336,14 +335,15 @@ public class HTTP : IPlugin
await task; await task;
var handle = new WebSocketClient(wsClient, requestId); var handle = new WebSocketClient.Client(wsClient, requestId);
WebSocketConnections.Add(handle); WebSocketConnections.Add(handle);
_game.LuaRuntime.QueueEvent("websocket_connect", LK => _game.LuaRuntime.QueueEvent("websocket_connect", LK =>
{ {
LK.PushInteger(requestId); LK.PushInteger(requestId);
handle.Push(LK); ObjectManager.PushObject(LK, handle);
LK.SetMetaTable(WebSocketClient.ObjectType);
return 2; return 2;
}); });

View file

@ -1,4 +1,5 @@
using Capy64.Runtime.Libraries; using Capy64.API;
using Capy64.Runtime.Libraries;
using KeraLua; using KeraLua;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -7,17 +8,72 @@ using System.Threading;
namespace Capy64.Runtime.Objects; namespace Capy64.Runtime.Objects;
public class WebSocketClient public class WebSocketClient : IPlugin
{ {
public const string ObjectType = "WebSocketClient"; public const string ObjectType = "WebSocketClient";
private readonly ClientWebSocket _socket;
private readonly long _requestId; public record Client(ClientWebSocket Socket, long RequestId);
public WebSocketClient(ClientWebSocket socket, long requestId)
public void LuaInit(Lua L)
{ {
_socket = socket; CreateMeta(L);
_requestId = requestId;
} }
public static void CreateMeta(Lua L)
{
L.NewMetaTable(ObjectType);
L.SetFuncs(MetaMethods, 0);
L.NewLibTable(Methods);
L.SetFuncs(Methods, 0);
L.SetField(-2, "__index");
L.Pop(1);
}
internal static LuaRegister[] Methods = new LuaRegister[]
{
new()
{
name = "getRequestID",
function = L_GetRequestId,
},
new()
{
name = "send",
function = L_Send,
},
new()
{
name = "closeAsync",
function = L_CloseAsync,
},
new(),
};
internal static LuaRegister[] MetaMethods = new LuaRegister[]
{
new()
{
name = "__index",
},
new()
{
name = "__gc",
function = L_CloseAsync,
},
new()
{
name = "__close",
function = L_CloseAsync,
},
new()
{
name = "__tostring",
function = LM_ToString,
},
new(),
};
private static readonly Dictionary<string, LuaFunction> functions = new() private static readonly Dictionary<string, LuaFunction> functions = new()
{ {
["getRequestID"] = L_GetRequestId, ["getRequestID"] = L_GetRequestId,
@ -25,41 +81,29 @@ public class WebSocketClient
["closeAsync"] = L_CloseAsync, ["closeAsync"] = L_CloseAsync,
}; };
public void Push(Lua L) public static Client ToObject(Lua L, bool gc = false)
{ {
L.PushObject(this); return ObjectManager.ToObject<Client>(L, 1, gc);
}
if (L.NewMetaTable(ObjectType)) public static Client CheckObject(Lua L, bool gc = false)
{
var obj = ObjectManager.CheckObject<Client>(L, 1, ObjectType, gc);
if (obj is null)
{ {
L.PushString("__index"); L.Error("attempt to use a closed object");
L.NewTable(); return null;
foreach (var pair in functions)
{
L.PushString(pair.Key);
L.PushCFunction(pair.Value);
L.SetTable(-3);
}
L.SetTable(-3);
L.PushString("__close");
L.PushCFunction(L_CloseAsync);
L.SetTable(-3);
L.PushString("__gc");
L.PushCFunction(L_CloseAsync);
L.SetTable(-3);
} }
return obj;
L.SetMetaTable(-2);
} }
private static int L_GetRequestId(IntPtr state) private static int L_GetRequestId(IntPtr state)
{ {
var L = Lua.FromIntPtr(state); var L = Lua.FromIntPtr(state);
var client = L.CheckObject<WebSocketClient>(1, ObjectType, false); var client = CheckObject(L, false);
L.PushInteger(client._requestId); L.PushInteger(client.RequestId);
return 1; return 1;
} }
@ -68,14 +112,14 @@ public class WebSocketClient
{ {
var L = Lua.FromIntPtr(state); var L = Lua.FromIntPtr(state);
var client = L.CheckObject<WebSocketClient>(1, ObjectType, false); var client = CheckObject(L, false);
var data = L.CheckBuffer(2); var data = L.CheckBuffer(2);
if (client is null || client._socket.State == WebSocketState.Closed) if (client is null || client.Socket.State == WebSocketState.Closed)
L.Error("connection is closed"); L.Error("connection is closed");
client._socket.SendAsync(data, WebSocketMessageType.Text, true, CancellationToken.None); client.Socket.SendAsync(data, WebSocketMessageType.Text, true, CancellationToken.None);
return 0; return 0;
} }
@ -84,18 +128,18 @@ public class WebSocketClient
{ {
var L = Lua.FromIntPtr(state); var L = Lua.FromIntPtr(state);
var client = L.CheckObject<WebSocketClient>(1, ObjectType, true); var client = ToObject(L, true);
if (client is null || client._socket.State == WebSocketState.Closed) if (client is null || client.Socket.State == WebSocketState.Closed)
return 0; return 0;
client._socket.CloseAsync(WebSocketCloseStatus.NormalClosure, null, CancellationToken.None) client.Socket.CloseAsync(WebSocketCloseStatus.NormalClosure, null, CancellationToken.None)
.ContinueWith(async task => .ContinueWith(async task =>
{ {
await task; await task;
Capy64.Instance.LuaRuntime.QueueEvent("websocket_close", LK => Capy64.Instance.LuaRuntime.QueueEvent("websocket_close", LK =>
{ {
LK.PushInteger(client._requestId); LK.PushInteger(client.RequestId);
return 1; return 1;
}); });
@ -105,4 +149,19 @@ public class WebSocketClient
return 0; return 0;
} }
private static unsafe int LM_ToString(IntPtr state)
{
var L = Lua.FromIntPtr(state);
var buffer = ToObject(L);
if (buffer is not null)
{
L.PushString("GPUBuffer ({0:X})", (ulong)&buffer);
}
else
{
L.PushString("GPUBuffer (closed)");
}
return 1;
}
} }