mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-01-29 20:34:51 +00:00
When multiple UI applications were connecting using the same token, the actual websocket connection was getting lost, and could eventually be garbage-collected, leading to odd behavior from the UI. This is due to an existing client getting replaced and a reference to it lost. This has now been remedied, with each client getting a unique instance with a unique client ID.
148 lines
4.3 KiB
C#
148 lines
4.3 KiB
C#
using System;
|
|
using System.Text.RegularExpressions;
|
|
using Newtonsoft.Json;
|
|
using Newtonsoft.Json.Linq;
|
|
using PepperDash.Core;
|
|
using PepperDash.Essentials.AppServer.Messengers;
|
|
using PepperDash.Essentials.RoomBridges;
|
|
using Serilog.Events;
|
|
using WebSocketSharp;
|
|
using WebSocketSharp.Server;
|
|
using ErrorEventArgs = WebSocketSharp.ErrorEventArgs;
|
|
|
|
|
|
namespace PepperDash.Essentials.WebSocketServer
|
|
{
|
|
/// <summary>
|
|
/// Represents the behaviour to associate with a UiClient for WebSocket communication
|
|
/// </summary>
|
|
public class UiClient : WebSocketBehavior
|
|
{
|
|
public MobileControlSystemController Controller { get; set; }
|
|
|
|
public string RoomKey { get; set; }
|
|
|
|
public string ClientId
|
|
{
|
|
get; private set;
|
|
}
|
|
|
|
private DateTime _connectionTime;
|
|
|
|
public TimeSpan ConnectedDuration
|
|
{
|
|
get
|
|
{
|
|
if (Context.WebSocket.IsAlive)
|
|
{
|
|
return DateTime.Now - _connectionTime;
|
|
}
|
|
else
|
|
{
|
|
return new TimeSpan(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
public UiClient(string clientId)
|
|
{
|
|
ClientId = clientId;
|
|
}
|
|
|
|
protected override void OnOpen()
|
|
{
|
|
base.OnOpen();
|
|
|
|
var url = Context.WebSocket.Url;
|
|
Debug.LogMessage(LogEventLevel.Verbose, "New WebSocket Connection from: {0}", null, url);
|
|
|
|
var match = Regex.Match(url.AbsoluteUri, "(?:ws|wss):\\/\\/.*(?:\\/mc\\/api\\/ui\\/join\\/)(.*)");
|
|
|
|
if (!match.Success)
|
|
{
|
|
_connectionTime = DateTime.Now;
|
|
return;
|
|
}
|
|
|
|
var clientId = ClientId;
|
|
|
|
if (Controller == null)
|
|
{
|
|
Debug.LogMessage(LogEventLevel.Verbose, "WebSocket UiClient Controller is null");
|
|
_connectionTime = DateTime.Now;
|
|
}
|
|
|
|
var clientJoinedMessage = new MobileControlMessage
|
|
{
|
|
Type = "/system/clientJoined",
|
|
Content = JToken.FromObject(new
|
|
{
|
|
clientId,
|
|
roomKey = RoomKey,
|
|
})
|
|
};
|
|
|
|
Controller.HandleClientMessage(JsonConvert.SerializeObject(clientJoinedMessage));
|
|
|
|
var bridge = Controller.GetRoomBridge(RoomKey);
|
|
|
|
if (bridge == null) return;
|
|
|
|
SendUserCodeToClient(bridge, clientId);
|
|
|
|
bridge.UserCodeChanged -= Bridge_UserCodeChanged;
|
|
bridge.UserCodeChanged += Bridge_UserCodeChanged;
|
|
|
|
// TODO: Future: Check token to see if there's already an open session using that token and reject/close the session
|
|
}
|
|
|
|
private void Bridge_UserCodeChanged(object sender, EventArgs e)
|
|
{
|
|
SendUserCodeToClient((MobileControlEssentialsRoomBridge)sender, ClientId);
|
|
}
|
|
|
|
private void SendUserCodeToClient(MobileControlBridgeBase bridge, string clientId)
|
|
{
|
|
var content = new
|
|
{
|
|
userCode = bridge.UserCode,
|
|
qrUrl = bridge.QrCodeUrl,
|
|
};
|
|
|
|
var message = new MobileControlMessage
|
|
{
|
|
Type = "/system/userCodeChanged",
|
|
ClientId = clientId,
|
|
Content = JToken.FromObject(content)
|
|
};
|
|
|
|
Controller.SendMessageObjectToDirectClient(message);
|
|
}
|
|
|
|
protected override void OnMessage(MessageEventArgs e)
|
|
{
|
|
base.OnMessage(e);
|
|
|
|
if (e.IsText && e.Data.Length > 0 && Controller != null)
|
|
{
|
|
// Forward the message to the controller to be put on the receive queue
|
|
Controller.HandleClientMessage(e.Data);
|
|
}
|
|
}
|
|
|
|
protected override void OnClose(CloseEventArgs e)
|
|
{
|
|
base.OnClose(e);
|
|
|
|
Debug.LogMessage(LogEventLevel.Verbose, "WebSocket UiClient Closing: {0} reason: {1}", null, e.Code, e.Reason);
|
|
}
|
|
|
|
protected override void OnError(ErrorEventArgs e)
|
|
{
|
|
base.OnError(e);
|
|
|
|
Debug.LogMessage(LogEventLevel.Verbose, "WebSocket UiClient Error: {exception} message: {message}", e.Exception, e.Message);
|
|
}
|
|
}
|
|
}
|