Improved WS client object

This commit is contained in:
Alessandro Proto 2023-01-27 22:56:57 +01:00
parent bc87363f7c
commit c2aca7a7af
3 changed files with 67 additions and 66 deletions

View file

@ -2,23 +2,6 @@ local http = require("http")
local event = require("event")
local expect = require("expect").expect
local WebSocketHandle = {}
function WebSocketHandle:close()
self:closeAsync()
local _, id
repeat
_, id = event.pull("websocket_close")
until id == self.requestId
end
function WebSocketHandle:receive()
local _, id, par
repeat
_, id, par = event.pull("websocket_message")
until id == self.requestId
return par
end
function http.request(url, body, headers, options)
expect(1, url, "string")
@ -60,12 +43,27 @@ function http.post(url, body, headers, options)
return http.request(url, body, headers, options)
end
local function buildWebsocketHandle(requestId, handle)
handle.requestId = requestId
local metatable = getmetatable(handle) or {}
metatable.__index = WebSocketHandle
local WebSocketHandle
local function buildWebsocketHandle(handle)
if not WebSocketHandle then
WebSocketHandle = getmetatable(handle) or { __index = {} }
function WebSocketHandle.__index:close()
self:closeAsync()
local _, id
repeat
_, id = event.pull("websocket_close")
until id == self:getRequestID()
end
setmetatable(handle, metatable)
function WebSocketHandle.__index:receive()
local _, id, par
repeat
_, id, par = event.pull("websocket_message")
until id == self:getRequestID()
return par
end
end
return handle
end
@ -88,5 +86,5 @@ function http.websocket(url, headers)
return nil, par
end
return buildWebsocketHandle(requestId, par)
return buildWebsocketHandle(par)
end

View file

@ -332,7 +332,7 @@ public class HTTP : IPlugin
await task;
var handle = new WebSocketHandle(wsClient, requestId, _game);
var handle = new WebSocketHandle(wsClient, requestId);
WebSocketConnections.Add(handle);
_game.LuaRuntime.QueueEvent("websocket_connect", LK =>
@ -368,10 +368,11 @@ public class HTTP : IPlugin
if (result.EndOfMessage)
{
var payload = builder.ToString();
_game.LuaRuntime.QueueEvent("websocket_message", LK =>
{
LK.PushInteger(requestId);
LK.PushString(builder.ToString());
LK.PushString(payload);
return 2;
});

View file

@ -2,78 +2,80 @@
using KeraLua;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Capy64.Runtime.Objects.Handlers;
public class WebSocketHandle
{
private ClientWebSocket _client;
private long _requestId;
private static IGame _game;
public WebSocketHandle(ClientWebSocket client, long requestId, IGame game)
public const string ObjectType = "WebSocketClient";
private readonly ClientWebSocket _socket;
private readonly long _requestId;
public WebSocketHandle(ClientWebSocket socket, long requestId)
{
_client = client;
_socket = socket;
_requestId = requestId;
_game = game;
}
private static readonly Dictionary<string, LuaFunction> functions = new()
{
["getRequestID"] = L_GetRequestId,
["send"] = L_Send,
["closeAsync"] = L_CloseAsync,
};
public void Push(Lua L)
{
L.NewTable();
L.PushObject(this);
// metatable
if (L.NewMetaTable(ObjectType))
{
L.PushString("__index");
L.NewTable();
L.PushString("__close");
L.PushCFunction(L_CloseAsync);
L.SetTable(-3);
L.PushString("__gc");
L.PushCFunction(L_CloseAsync);
L.SetTable(-3);
L.SetMetaTable(-2);
foreach (var pair in functions)
{
L.PushString(pair.Key);
L.PushCFunction(pair.Value);
L.SetTable(-3);
}
L.SetTable(-3);
L.PushString("_handle");
L.PushObject(this);
L.PushString("__close");
L.PushCFunction(L_CloseAsync);
L.SetTable(-3);
L.PushString("__gc");
L.PushCFunction(L_CloseAsync);
L.SetTable(-3);
}
private static WebSocketHandle GetHandle(Lua L, bool gc = true)
L.SetMetaTable(-2);
}
private static int L_GetRequestId(IntPtr state)
{
L.CheckType(1, LuaType.Table);
L.PushString("_handle");
L.GetTable(1);
return L.ToObject<WebSocketHandle>(-1, gc);
var L = Lua.FromIntPtr(state);
var client = L.CheckObject<WebSocketHandle>(1, ObjectType, false);
L.PushInteger(client._requestId);
return 1;
}
private static int L_Send(IntPtr state)
{
var L = Lua.FromIntPtr(state);
var client = L.CheckObject<WebSocketHandle>(1, ObjectType, false);
var data = L.CheckBuffer(2);
var h = GetHandle(L, false);
if (h is null || h._client.State == WebSocketState.Closed)
if (client is null || client._socket.State == WebSocketState.Closed)
L.Error("connection is closed");
h._client.SendAsync(data, WebSocketMessageType.Text, true, CancellationToken.None);
client._socket.SendAsync(data, WebSocketMessageType.Text, true, CancellationToken.None);
return 0;
}
@ -82,24 +84,24 @@ public class WebSocketHandle
{
var L = Lua.FromIntPtr(state);
var h = GetHandle(L, true);
var client = L.CheckObject<WebSocketHandle>(1, ObjectType, true);
if (h is null || h._client.State == WebSocketState.Closed)
if (client is null || client._socket.State == WebSocketState.Closed)
return 0;
h._client.CloseAsync(WebSocketCloseStatus.NormalClosure, null, CancellationToken.None)
client._socket.CloseAsync(WebSocketCloseStatus.NormalClosure, null, CancellationToken.None)
.ContinueWith(async task =>
{
await task;
_game.LuaRuntime.QueueEvent("websocket_close", LK =>
Capy64.Instance.LuaRuntime.QueueEvent("websocket_close", LK =>
{
LK.PushInteger(h._requestId);
LK.PushInteger(client._requestId);
return 1;
});
});
HTTP.WebSocketConnections.Remove(h);
HTTP.WebSocketConnections.Remove(client);
return 0;
}