< Summary

Class:WebSocketCommunication
Assembly:WebSocketCommunication
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/KernelCommunication/WebSocketCommunication/WebSocketCommunication.cs
Covered lines:0
Uncovered lines:148
Coverable lines:148
Total lines:253
Line coverage:0% (0 of 148)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
WebSocketCommunication(...)0%2100%
WebSocketCommunication()0%2100%
StartServer(...)0%56700%
InitMessageTypeToBridgeName()0%2100%
ProcessMessages()0%3421800%
Dispose()0%2100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/KernelCommunication/WebSocketCommunication/WebSocketCommunication.cs

#LineLine coverage
 1using System;
 2using System.Collections;
 3using System.Collections.Generic;
 4using System.Net.Sockets;
 5using DCL;
 6using UnityEngine;
 7using WebSocketSharp.Server;
 8
 9public class WebSocketCommunication : IKernelCommunication
 10{
 11    WebSocketServer ws;
 12    private Coroutine updateCoroutine;
 13    private bool requestStop = false;
 14
 015    private Dictionary<string, GameObject> bridgeGameObjects = new Dictionary<string, GameObject>();
 16
 017    public Dictionary<string, string> messageTypeToBridgeName = new Dictionary<string, string>(); // Public to be able t
 18
 19    [System.NonSerialized]
 020    public static Queue<DCLWebSocketService.Message> queuedMessages = new Queue<DCLWebSocketService.Message>();
 21
 22    [System.NonSerialized]
 23    public static volatile bool queuedMessagesDirty;
 24
 025    public bool isServerReady => ws.IsListening;
 26
 27    private string StartServer(int port, int maxPort, bool withSSL)
 28    {
 029        if (port > maxPort)
 30        {
 031            throw new SocketException((int)SocketError.AddressAlreadyInUse);
 32        }
 33        string wssServerUrl;
 034        string wssServiceId = "dcl";
 35        try
 36        {
 037            if (withSSL)
 38            {
 039                wssServerUrl = $"wss://localhost:{port}/";
 040                ws = new WebSocketServer(wssServerUrl)
 41                {
 42                    SslConfiguration =
 43                    {
 44                        ServerCertificate = CertificateUtils.CreateSelfSignedCert(),
 45                        ClientCertificateRequired = false,
 46                        CheckCertificateRevocation = false,
 047                        ClientCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true
 48                    }
 49                };
 050            }
 51            else
 52            {
 053                wssServerUrl = $"ws://localhost:{port}/";
 054                ws = new WebSocketServer(wssServerUrl);
 55            }
 56
 057            ws.AddWebSocketService<DCLWebSocketService>("/" + wssServiceId);
 058            ws.Start();
 059        }
 060        catch (InvalidOperationException e)
 61        {
 062            ws.Stop();
 063            if (withSSL) // Search for available ports only if we're using SSL
 64            {
 065                SocketException se = (SocketException)e.InnerException;
 066                if (se is { SocketErrorCode: SocketError.AddressAlreadyInUse })
 67                {
 068                    return StartServer(port + 1, maxPort, withSSL);
 69                }
 70            }
 071            throw new InvalidOperationException(e.Message, e.InnerException);
 72        }
 73
 074        string wssUrl = wssServerUrl + wssServiceId;
 075        return wssUrl;
 076    }
 77
 078    public WebSocketCommunication(bool withSSL = false)
 79    {
 080        InitMessageTypeToBridgeName();
 81
 082        DCL.DataStore.i.debugConfig.isWssDebugMode = true;
 83
 084        string url = StartServer(5000, 5100, withSSL);
 85
 086        Debug.Log("WebSocket Server URL: " + url);
 87
 088        DataStore.i.wsCommunication.url = url;
 89
 090        DataStore.i.wsCommunication.communicationReady.Set(true);
 91
 092        updateCoroutine = CoroutineStarter.Start(ProcessMessages());
 093    }
 94
 95    private void InitMessageTypeToBridgeName()
 96    {
 97        // Please, use `Bridges` as a bridge name, avoid adding messages here. The system will use `Bridges` as the defa
 098        messageTypeToBridgeName["SetDebug"] = "Main";
 099        messageTypeToBridgeName["SetSceneDebugPanel"] = "Main";
 0100        messageTypeToBridgeName["ShowFPSPanel"] = "Main";
 0101        messageTypeToBridgeName["HideFPSPanel"] = "Main";
 0102        messageTypeToBridgeName["SetEngineDebugPanel"] = "Main";
 0103        messageTypeToBridgeName["SendSceneMessage"] = "Main";
 0104        messageTypeToBridgeName["LoadParcelScenes"] = "Main";
 0105        messageTypeToBridgeName["UnloadScene"] = "Main";
 0106        messageTypeToBridgeName["Reset"] = "Main";
 0107        messageTypeToBridgeName["CreateGlobalScene"] = "Main";
 0108        messageTypeToBridgeName["BuilderReady"] = "Main";
 0109        messageTypeToBridgeName["UpdateParcelScenes"] = "Main";
 0110        messageTypeToBridgeName["LoadProfile"] = "Main";
 0111        messageTypeToBridgeName["AddUserProfileToCatalog"] = "Main";
 0112        messageTypeToBridgeName["AddUserProfilesToCatalog"] = "Main";
 0113        messageTypeToBridgeName["RemoveUserProfilesFromCatalog"] = "Main";
 0114        messageTypeToBridgeName["ActivateRendering"] = "Main";
 0115        messageTypeToBridgeName["DeactivateRendering"] = "Main";
 0116        messageTypeToBridgeName["ForceActivateRendering"] = "Main";
 0117        messageTypeToBridgeName["AddWearablesToCatalog"] = "Main";
 0118        messageTypeToBridgeName["WearablesRequestFailed"] = "Main";
 0119        messageTypeToBridgeName["RemoveWearablesFromCatalog"] = "Main";
 0120        messageTypeToBridgeName["ClearWearableCatalog"] = "Main";
 0121        messageTypeToBridgeName["InitializeFriends"] = "Main";
 0122        messageTypeToBridgeName["UpdateFriendshipStatus"] = "Main";
 0123        messageTypeToBridgeName["UpdateUserPresence"] = "Main";
 0124        messageTypeToBridgeName["FriendNotFound"] = "Main";
 0125        messageTypeToBridgeName["AddMessageToChatWindow"] = "Main";
 0126        messageTypeToBridgeName["UpdateMinimapSceneInformation"] = "Main";
 0127        messageTypeToBridgeName["UpdateHotScenesList"] = "Main";
 0128        messageTypeToBridgeName["SetRenderProfile"] = "Main";
 0129        messageTypeToBridgeName["CrashPayloadRequest"] = "Main";
 0130        messageTypeToBridgeName["SetDisableAssetBundles"] = "Main";
 0131        messageTypeToBridgeName["DumpRendererLockersInfo"] = "Main";
 0132        messageTypeToBridgeName["PublishSceneResult"] = "Main";
 0133        messageTypeToBridgeName["BuilderProjectInfo"] = "Main";
 0134        messageTypeToBridgeName["BuilderInWorldCatalogHeaders"] = "Main";
 0135        messageTypeToBridgeName["RequestedHeaders"] = "Main";
 0136        messageTypeToBridgeName["AddAssets"] = "Main";
 0137        messageTypeToBridgeName["RunPerformanceMeterTool"] = "Main";
 0138        messageTypeToBridgeName["InstantiateBotsAtWorldPos"] = "Main";
 0139        messageTypeToBridgeName["InstantiateBotsAtCoords"] = "Main";
 0140        messageTypeToBridgeName["StartBotsRandomizedMovement"] = "Main";
 0141        messageTypeToBridgeName["StopBotsMovement"] = "Main";
 0142        messageTypeToBridgeName["RemoveBot"] = "Main";
 0143        messageTypeToBridgeName["ClearBots"] = "Main";
 144
 0145        messageTypeToBridgeName["Teleport"] = "CharacterController";
 146
 0147        messageTypeToBridgeName["SetRotation"] = "CameraController";
 148
 0149        messageTypeToBridgeName["ShowNotificationFromJson"] = "HUDController";
 0150        messageTypeToBridgeName["ConfigureHUDElement"] = "HUDController";
 0151        messageTypeToBridgeName["ShowTermsOfServices"] = "HUDController";
 0152        messageTypeToBridgeName["RequestTeleport"] = "HUDController";
 0153        messageTypeToBridgeName["ShowAvatarEditorInSignUp"] = "HUDController";
 0154        messageTypeToBridgeName["SetUserTalking"] = "HUDController";
 0155        messageTypeToBridgeName["SetUsersMuted"] = "HUDController";
 0156        messageTypeToBridgeName["ShowWelcomeNotification"] = "HUDController";
 0157        messageTypeToBridgeName["UpdateBalanceOfMANA"] = "HUDController";
 0158        messageTypeToBridgeName["SetPlayerTalking"] = "HUDController";
 0159        messageTypeToBridgeName["SetVoiceChatEnabledByScene"] = "HUDController";
 0160        messageTypeToBridgeName["TriggerSelfUserExpression"] = "HUDController";
 0161        messageTypeToBridgeName["AirdroppingRequest"] = "HUDController";
 162
 0163        messageTypeToBridgeName["GetMousePosition"] = "BuilderController";
 0164        messageTypeToBridgeName["SelectGizmo"] = "BuilderController";
 0165        messageTypeToBridgeName["ResetObject"] = "BuilderController";
 0166        messageTypeToBridgeName["ZoomDelta"] = "BuilderController";
 0167        messageTypeToBridgeName["SetPlayMode"] = "BuilderController";
 0168        messageTypeToBridgeName["TakeScreenshot"] = "BuilderController";
 0169        messageTypeToBridgeName["ResetBuilderScene"] = "BuilderController";
 0170        messageTypeToBridgeName["SetBuilderCameraPosition"] = "BuilderController";
 0171        messageTypeToBridgeName["SetBuilderCameraRotation"] = "BuilderController";
 0172        messageTypeToBridgeName["ResetBuilderCameraZoom"] = "BuilderController";
 0173        messageTypeToBridgeName["SetGridResolution"] = "BuilderController";
 0174        messageTypeToBridgeName["OnBuilderKeyDown"] = "BuilderController";
 0175        messageTypeToBridgeName["UnloadBuilderScene"] = "BuilderController";
 0176        messageTypeToBridgeName["SetSelectedEntities"] = "BuilderController";
 0177        messageTypeToBridgeName["GetCameraTargetBuilder"] = "BuilderController";
 0178        messageTypeToBridgeName["PreloadFile"] = "BuilderController";
 0179        messageTypeToBridgeName["SetBuilderConfiguration"] = "BuilderController";
 180
 0181        messageTypeToBridgeName["SetTutorialEnabled"] = "TutorialController";
 0182        messageTypeToBridgeName["SetTutorialEnabledForUsersThatAlreadyDidTheTutorial"] = "TutorialController";
 0183    }
 184
 185    IEnumerator ProcessMessages()
 186    {
 0187        var hudControllerGO = GameObject.Find("HUDController");
 0188        var mainGO = GameObject.Find("Main");
 189
 0190        while (!requestStop)
 191        {
 0192            lock (queuedMessages)
 193            {
 0194                if (queuedMessagesDirty)
 195                {
 0196                    while (queuedMessages.Count > 0)
 197                    {
 0198                        DCLWebSocketService.Message msg = queuedMessages.Dequeue();
 199
 0200                        switch (msg.type)
 201                        {
 202                            // Add to this list the messages that are used a lot and you want better performance
 203                            case "SendSceneMessage":
 0204                                DCL.Environment.i.world.sceneController.SendSceneMessage(msg.payload);
 0205                                break;
 206                            case "Reset":
 0207                                DCL.Environment.i.world.sceneController.UnloadAllScenesQueued();
 0208                                break;
 209                            case "SetVoiceChatEnabledByScene":
 0210                                if (int.TryParse(msg.payload, out int value)) // The payload should be `string`, this wi
 211                                {
 0212                                    hudControllerGO.SendMessage(msg.type, value);
 213                                }
 0214                                break;
 215                            case "RunPerformanceMeterTool":
 0216                                if (float.TryParse(msg.payload, out float durationInSeconds)) // The payload should be `
 217                                {
 0218                                    mainGO.SendMessage(msg.type, durationInSeconds);
 219                                }
 0220                                break;
 221                            default:
 0222                                if (!messageTypeToBridgeName.TryGetValue(msg.type, out string bridgeName))
 223                                {
 0224                                    bridgeName = "Bridges"; // Default bridge
 225                                }
 226
 0227                                if (bridgeGameObjects.TryGetValue(bridgeName, out GameObject bridgeObject) == false)
 228                                {
 0229                                    bridgeObject = GameObject.Find(bridgeName);
 0230                                    bridgeGameObjects.Add(bridgeName, bridgeObject);
 231                                }
 232
 0233                                if (bridgeObject != null)
 234                                {
 0235                                    bridgeObject.SendMessage(msg.type, msg.payload);
 236                                }
 237                                break;
 238                        }
 239
 0240                        if (DCLWebSocketService.VERBOSE)
 241                        {
 0242                            Debug.Log(
 243                                "<b><color=#0000FF>WebSocketCommunication</color></b> >>> Got it! passing message of typ
 244                                msg.type);
 245                        }
 246                    }
 247                }
 0248            }
 0249            yield return null;
 250        }
 0251    }
 0252    public void Dispose() { ws.Stop(); }
 253}