Add WebSocket support; wraps BCL ClientWebSocket (squashed PR #2237)

Co-authored-by: David Ackroyd <davidackroydmusic@gmail.com>
This commit is contained in:
David Ackroyd 2020-08-03 04:11:29 +01:00 committed by GitHub
parent 22d78efabd
commit dbcd6b5b68
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 197 additions and 0 deletions

View File

@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
namespace BizHawk.Client.Common
{
public class WebSocketClient
{
private Dictionary<string, ClientWebSocket> activeSockets;
public WebSocketClient()
{
activeSockets = new Dictionary<string, ClientWebSocket>();
}
public string OpenSocket(string url)
{
var ws = new ClientWebSocket();
var id = new Guid().ToString();
ws.ConnectAsync(new Uri(url), CancellationToken.None).Wait();
activeSockets[id] = ws;
return id;
}
public void SendToSocket(string id, string content, bool endOfMessage)
{
var ws = activeSockets[id];
var msg = new ArraySegment<byte>(Encoding.UTF8.GetBytes(content));
ws.SendAsync(msg, WebSocketMessageType.Text, endOfMessage, CancellationToken.None);
}
public string ReceiveFromSocket(string id, int maxRead)
{
var ws = activeSockets[id];
var rcvBytes = new byte[maxRead];
var rcvBuffer = new ArraySegment<byte>(rcvBytes);
var result = ws.ReceiveAsync(rcvBuffer, CancellationToken.None).Result;
string rcvMsg = Encoding.UTF8.GetString(rcvBuffer.Take(result.Count).ToArray());
return rcvMsg;
}
public int GetSocketStatus(string id)
{
var ws = activeSockets[id];
return (int)ws.State;
}
public void CloseSocket(string id, int status, string closeMessage)
{
var ws = activeSockets[id];
ws.CloseAsync((WebSocketCloseStatus)status, closeMessage, CancellationToken.None);
}
}
}

View File

@ -237,6 +237,41 @@ namespace BizHawk.Client.Common
return APIs.Comm.HTTP?.GetUrl;
}
//[LuaMethodExample("local ws = bizsocket.open('wss://echo.websocket.org');")]
//[LuaMethod("websocket_open", "Opens a websocket and returns the id so that it can be retrieved later.")]
//public string OpenSocket(string url)
//{
// return APIs.Comm.WebSocketClient?.OpenSocket(url);
//}
//[LuaMethodExample("local ws = bizsocket.send(ws_id, 'some message', true);")]
//[LuaMethod("websocket_send", "Send a message to a certain websocket id (boolean flag endOfMessage)")]
//public void SendToSocket(string id, string content, bool endOfMessage)
//{
// APIs.Comm.WebSocketClient?.SendToSocket(id, content, endOfMessage);
//}
//[LuaMethodExample("local ws = bizsocket.receive(ws_id, max_read);")]
//[LuaMethod("websocket_receive", "Receive a message from a certain websocket id and a maximum number of bytes to read.")]
//public string ReceiveFromSocket(string id, int maxRead)
//{
// return APIs.Comm.WebSocketClient?.ReceiveFromSocket(id, maxRead);
//}
//[LuaMethodExample("local ws_status = bizsocket.getstatus(ws_id);")]
//[LuaMethod("websocket_getStatus", "Get a websocket's status")]
//public int? GetSocketStatus(string id)
//{
// return APIs.Comm.WebSocketClient?.GetSocketStatus(id);
//}
//[LuaMethodExample("local ws_status = bizsocket.close(ws_id, close_status);")]
//[LuaMethod("websocket_close", "Close a websocket connection with a close status, defined in section 11.7 of the web sockets protocol spec.")]
//public void CloseSocket(string id, int status, string closeMessage)
//{
// APIs.Comm.WebSocketClient?.CloseSocket(id, status, closeMessage);
//}
private void CheckHttp()
{
if (APIs.Comm.HTTP == null)
@ -244,5 +279,13 @@ namespace BizHawk.Client.Common
Log("HTTP was not initialized, please initialize it via the command line");
}
}
//private void CheckWebSocket()
//{
// if (APIs.Comm.WebSocketClient == null)
// {
// Log("WebSocketClient was not initialized");
// }
//}
}
}

View File

@ -0,0 +1,87 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using NLua;
namespace BizHawk.Client.Common.lua.LuaHelperLibs
{
[Description("A library exposing standard .NET string methods")]
public sealed class WebSocketLuaLibrary : LuaLibraryBase
{
private Dictionary<string, ClientWebSocket> activeSockets;
public WebSocketLuaLibrary(Lua lua) : base(lua)
{
activeSockets = new Dictionary<string, ClientWebSocket>();
}
public WebSocketLuaLibrary(Lua lua, Action<string> logOutputCallback) : base(lua, logOutputCallback)
{
activeSockets = new Dictionary<string, ClientWebSocket>();
}
public override string Name => "bizsocket";
[LuaMethodExample("local ws = bizsocket.open('wss://echo.websocket.org');")]
[LuaMethod("open", "Opens a websocket and returns the id so that it can be retrieved later.")]
public string OpenSocket(string url)
{
var ws = new ClientWebSocket();
var id = new Guid().ToString();
ws.ConnectAsync(new Uri(url), CancellationToken.None).Wait();
activeSockets[id] = ws;
return id;
}
[LuaMethodExample("local ws = bizsocket.send(ws_id, 'some message', true);")]
[LuaMethod("send", "Send a message to a certain websocket id (boolean flag endOfMessage)")]
public void SendToSocket(string id, string content, bool endOfMessage)
{
var ws = activeSockets[id];
var msg = new ArraySegment<byte>(Encoding.UTF8.GetBytes(content));
ws.SendAsync(msg, WebSocketMessageType.Text, endOfMessage, CancellationToken.None);
}
[LuaMethodExample("local ws = bizsocket.receive(ws_id, max_read);")]
[LuaMethod("receive", "Receive a message from a certain websocket id and a maximum number of bytes to read.")]
public string ReceiveFromSocket(string id, int maxRead)
{
var ws = activeSockets[id];
var rcvBytes = new byte[maxRead];
var rcvBuffer = new ArraySegment<byte>(rcvBytes);
var result = ws.ReceiveAsync(rcvBuffer, CancellationToken.None).Result;
string rcvMsg = Encoding.UTF8.GetString(rcvBuffer.Take(result.Count).ToArray());
return rcvMsg;
}
[LuaMethodExample("local ws_status = bizsocket.getstatus(ws_id);")]
[LuaMethod("getStatus", "Get a websocket's status")]
public int GetSocketStatus(string id)
{
var ws = activeSockets[id];
return (int)ws.State;
}
[LuaMethodExample("local ws_status = bizsocket.close(ws_id, close_status);")]
[LuaMethod("close", "Close a websocket connection with a close status, defined in section 11.7 of the web sockets protocol spec.")]
public void CloseSocket(string id, int status, string closeMessage)
{
var ws = activeSockets[id];
ws.CloseAsync((WebSocketCloseStatus) status, closeMessage, CancellationToken.None);
}
}
}