< 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:166
Coverable lines:166
Total lines:279
Line coverage:0% (0 of 166)
Covered branches:0
Total branches:0

Metrics

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

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    public static DCLWebSocketService service;
 12
 13    [System.NonSerialized]
 014    public static Queue<DCLWebSocketService.Message> queuedMessages = new Queue<DCLWebSocketService.Message>();
 15
 16    [System.NonSerialized]
 17    public static volatile bool queuedMessagesDirty;
 18
 019    private Dictionary<string, GameObject> bridgeGameObjects = new Dictionary<string, GameObject>();
 20
 021    public Dictionary<string, string> messageTypeToBridgeName = new Dictionary<string, string>(); // Public to be able t
 22    private bool requestStop = false;
 23    private Coroutine updateCoroutine;
 24
 25    WebSocketServer ws;
 26
 027    public WebSocketCommunication(bool withSSL = false, int startPort = 7666, int endPort = 7800)
 28    {
 029        InitMessageTypeToBridgeName();
 30
 031        DCL.DataStore.i.debugConfig.isWssDebugMode = true;
 32
 033        string url = StartServer(startPort, endPort, withSSL);
 34
 035        Debug.Log("WebSocket Server URL: " + url);
 36
 037        DataStore.i.wsCommunication.url = url;
 38
 039        DataStore.i.wsCommunication.communicationReady.Set(true);
 40
 041        updateCoroutine = CoroutineStarter.Start(ProcessMessages());
 042    }
 43
 044    public bool isServerReady => ws.IsListening;
 045    public void Dispose() { ws.Stop(); }
 46    public static event Action<DCLWebSocketService> OnWebSocketServiceAdded;
 47
 48    private string StartServer(int port, int maxPort, bool withSSL)
 49    {
 050        if (port > maxPort)
 51        {
 052            throw new SocketException((int)SocketError.AddressAlreadyInUse);
 53        }
 54        string wssServerUrl;
 055        string wssServiceId = "dcl";
 56        try
 57        {
 058            if (withSSL)
 59            {
 060                wssServerUrl = $"wss://localhost:{port}/";
 061                ws = new WebSocketServer(wssServerUrl)
 62                {
 63                    SslConfiguration =
 64                    {
 65                        ServerCertificate = CertificateUtils.CreateSelfSignedCert(),
 66                        ClientCertificateRequired = false,
 67                        CheckCertificateRevocation = false,
 068                        ClientCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true,
 69                        EnabledSslProtocols = System.Security.Authentication.SslProtocols.Tls12
 70                    },
 71                    KeepClean = false
 72                };
 073            }
 74            else
 75            {
 076                wssServerUrl = $"ws://localhost:{port}/";
 077                ws = new WebSocketServer(wssServerUrl);
 78            }
 79
 080            ws.AddWebSocketService("/" + wssServiceId, () =>
 81            {
 082                service = new DCLWebSocketService();
 083                OnWebSocketServiceAdded?.Invoke(service);
 084                return service;
 85            });
 086            ws.Start();
 087        }
 088        catch (InvalidOperationException e)
 89        {
 090            ws.Stop();
 091            if (withSSL) // Search for available ports only if we're using SSL
 92            {
 093                SocketException se = (SocketException)e.InnerException;
 094                if (se is { SocketErrorCode: SocketError.AddressAlreadyInUse })
 95                {
 096                    return StartServer(port + 1, maxPort, withSSL);
 97                }
 98            }
 099            throw new InvalidOperationException(e.Message, e.InnerException);
 100        }
 101
 0102        string wssUrl = wssServerUrl + wssServiceId;
 0103        return wssUrl;
 0104    }
 105
 106    private void InitMessageTypeToBridgeName()
 107    {
 108        // Please, use `Bridges` as a bridge name, avoid adding messages here. The system will use `Bridges` as the defa
 0109        messageTypeToBridgeName["SetDebug"] = "Main";
 0110        messageTypeToBridgeName["SetSceneDebugPanel"] = "Main";
 0111        messageTypeToBridgeName["ShowFPSPanel"] = "Main";
 0112        messageTypeToBridgeName["HideFPSPanel"] = "Main";
 0113        messageTypeToBridgeName["SetEngineDebugPanel"] = "Main";
 0114        messageTypeToBridgeName["SendSceneMessage"] = "Main";
 0115        messageTypeToBridgeName["LoadParcelScenes"] = "Main";
 0116        messageTypeToBridgeName["UnloadScene"] = "Main";
 0117        messageTypeToBridgeName["Reset"] = "Main";
 0118        messageTypeToBridgeName["CreateGlobalScene"] = "Main";
 0119        messageTypeToBridgeName["BuilderReady"] = "Main";
 0120        messageTypeToBridgeName["UpdateParcelScenes"] = "Main";
 0121        messageTypeToBridgeName["LoadProfile"] = "Main";
 0122        messageTypeToBridgeName["AddUserProfileToCatalog"] = "Main";
 0123        messageTypeToBridgeName["AddUserProfilesToCatalog"] = "Main";
 0124        messageTypeToBridgeName["RemoveUserProfilesFromCatalog"] = "Main";
 0125        messageTypeToBridgeName["ActivateRendering"] = "Main";
 0126        messageTypeToBridgeName["DeactivateRendering"] = "Main";
 0127        messageTypeToBridgeName["ForceActivateRendering"] = "Main";
 0128        messageTypeToBridgeName["AddWearablesToCatalog"] = "Main";
 0129        messageTypeToBridgeName["WearablesRequestFailed"] = "Main";
 0130        messageTypeToBridgeName["RemoveWearablesFromCatalog"] = "Main";
 0131        messageTypeToBridgeName["ClearWearableCatalog"] = "Main";
 0132        messageTypeToBridgeName["InitializeFriends"] = "Main";
 0133        messageTypeToBridgeName["UpdateFriendshipStatus"] = "Main";
 0134        messageTypeToBridgeName["UpdateUserPresence"] = "Main";
 0135        messageTypeToBridgeName["FriendNotFound"] = "Main";
 0136        messageTypeToBridgeName["AddMessageToChatWindow"] = "Main";
 0137        messageTypeToBridgeName["UpdateMinimapSceneInformation"] = "Main";
 0138        messageTypeToBridgeName["UpdateHotScenesList"] = "Main";
 0139        messageTypeToBridgeName["SetRenderProfile"] = "Main";
 0140        messageTypeToBridgeName["CrashPayloadRequest"] = "Main";
 0141        messageTypeToBridgeName["SetDisableAssetBundles"] = "Main";
 0142        messageTypeToBridgeName["DumpRendererLockersInfo"] = "Main";
 0143        messageTypeToBridgeName["PublishSceneResult"] = "Main";
 0144        messageTypeToBridgeName["BuilderProjectInfo"] = "Main";
 0145        messageTypeToBridgeName["BuilderInWorldCatalogHeaders"] = "Main";
 0146        messageTypeToBridgeName["RequestedHeaders"] = "Main";
 0147        messageTypeToBridgeName["AddAssets"] = "Main";
 0148        messageTypeToBridgeName["RunPerformanceMeterTool"] = "Main";
 0149        messageTypeToBridgeName["InstantiateBotsAtWorldPos"] = "Main";
 0150        messageTypeToBridgeName["InstantiateBotsAtCoords"] = "Main";
 0151        messageTypeToBridgeName["StartBotsRandomizedMovement"] = "Main";
 0152        messageTypeToBridgeName["StopBotsMovement"] = "Main";
 0153        messageTypeToBridgeName["RemoveBot"] = "Main";
 0154        messageTypeToBridgeName["ClearBots"] = "Main";
 0155        messageTypeToBridgeName["ToggleSceneBoundingBoxes"] = "Main";
 0156        messageTypeToBridgeName["TogglePreviewMenu"] = "Main";
 0157        messageTypeToBridgeName["ToggleSceneSpawnPoints"] = "Main";
 0158        messageTypeToBridgeName["AddFriendsWithDirectMessages"] = "Main";
 0159        messageTypeToBridgeName["AddFriends"] = "Main";
 0160        messageTypeToBridgeName["AddFriendRequests"] = "Main";
 0161        messageTypeToBridgeName["UpdateTotalUnseenMessagesByUser"] = "Main";
 0162        messageTypeToBridgeName["UpdateTotalFriendRequests"] = "Main";
 0163        messageTypeToBridgeName["UpdateTotalFriends"] = "Main";
 0164        messageTypeToBridgeName["InitializeChat"] = "Main";
 0165        messageTypeToBridgeName["AddChatMessages"] = "Main";
 0166        messageTypeToBridgeName["UpdateTotalUnseenMessages"] = "Main";
 0167        messageTypeToBridgeName["UpdateUserUnseenMessages"] = "Main";
 0168        messageTypeToBridgeName["UpdateHomeScene"] = "Main";
 169
 0170        messageTypeToBridgeName["Teleport"] = "CharacterController";
 171
 0172        messageTypeToBridgeName["SetRotation"] = "CameraController";
 173
 0174        messageTypeToBridgeName["ShowNotificationFromJson"] = "HUDController";
 0175        messageTypeToBridgeName["ConfigureHUDElement"] = "HUDController";
 0176        messageTypeToBridgeName["ShowTermsOfServices"] = "HUDController";
 0177        messageTypeToBridgeName["RequestTeleport"] = "HUDController";
 0178        messageTypeToBridgeName["ShowAvatarEditorInSignUp"] = "HUDController";
 0179        messageTypeToBridgeName["SetUserTalking"] = "HUDController";
 0180        messageTypeToBridgeName["SetUsersMuted"] = "HUDController";
 0181        messageTypeToBridgeName["ShowWelcomeNotification"] = "HUDController";
 0182        messageTypeToBridgeName["UpdateBalanceOfMANA"] = "HUDController";
 0183        messageTypeToBridgeName["SetPlayerTalking"] = "HUDController";
 0184        messageTypeToBridgeName["SetVoiceChatEnabledByScene"] = "HUDController";
 0185        messageTypeToBridgeName["TriggerSelfUserExpression"] = "HUDController";
 0186        messageTypeToBridgeName["AirdroppingRequest"] = "HUDController";
 187
 0188        messageTypeToBridgeName["GetMousePosition"] = "BuilderController";
 0189        messageTypeToBridgeName["SelectGizmo"] = "BuilderController";
 0190        messageTypeToBridgeName["ResetObject"] = "BuilderController";
 0191        messageTypeToBridgeName["ZoomDelta"] = "BuilderController";
 0192        messageTypeToBridgeName["SetPlayMode"] = "BuilderController";
 0193        messageTypeToBridgeName["TakeScreenshot"] = "BuilderController";
 0194        messageTypeToBridgeName["ResetBuilderScene"] = "BuilderController";
 0195        messageTypeToBridgeName["SetBuilderCameraPosition"] = "BuilderController";
 0196        messageTypeToBridgeName["SetBuilderCameraRotation"] = "BuilderController";
 0197        messageTypeToBridgeName["ResetBuilderCameraZoom"] = "BuilderController";
 0198        messageTypeToBridgeName["SetGridResolution"] = "BuilderController";
 0199        messageTypeToBridgeName["OnBuilderKeyDown"] = "BuilderController";
 0200        messageTypeToBridgeName["UnloadBuilderScene"] = "BuilderController";
 0201        messageTypeToBridgeName["SetSelectedEntities"] = "BuilderController";
 0202        messageTypeToBridgeName["GetCameraTargetBuilder"] = "BuilderController";
 0203        messageTypeToBridgeName["PreloadFile"] = "BuilderController";
 0204        messageTypeToBridgeName["SetBuilderConfiguration"] = "BuilderController";
 205
 0206        messageTypeToBridgeName["SetTutorialEnabled"] = "TutorialController";
 0207        messageTypeToBridgeName["SetTutorialEnabledForUsersThatAlreadyDidTheTutorial"] = "TutorialController";
 208
 0209        messageTypeToBridgeName["VoiceChatStatus"] = "VoiceChatController";
 0210    }
 211
 212    IEnumerator ProcessMessages()
 213    {
 0214        var hudControllerGO = GameObject.Find("HUDController");
 0215        var mainGO = GameObject.Find("Main");
 216
 0217        while (!requestStop)
 218        {
 0219            lock (queuedMessages)
 220            {
 0221                if (queuedMessagesDirty)
 222                {
 0223                    while (queuedMessages.Count > 0)
 224                    {
 0225                        DCLWebSocketService.Message msg = queuedMessages.Dequeue();
 226
 0227                        switch (msg.type)
 228                        {
 229                            // Add to this list the messages that are used a lot and you want better performance
 230                            case "SendSceneMessage":
 0231                                DCL.Environment.i.world.sceneController.SendSceneMessage(msg.payload);
 0232                                break;
 233                            case "Reset":
 0234                                DCL.Environment.i.world.sceneController.UnloadAllScenesQueued();
 0235                                break;
 236                            case "SetVoiceChatEnabledByScene":
 0237                                if (int.TryParse(msg.payload, out int value)) // The payload should be `string`, this wi
 238                                {
 0239                                    hudControllerGO.SendMessage(msg.type, value);
 240                                }
 0241                                break;
 242                            case "RunPerformanceMeterTool":
 0243                                if (float.TryParse(msg.payload, out float durationInSeconds)) // The payload should be `
 244                                {
 0245                                    mainGO.SendMessage(msg.type, durationInSeconds);
 246                                }
 0247                                break;
 248                            default:
 0249                                if (!messageTypeToBridgeName.TryGetValue(msg.type, out string bridgeName))
 250                                {
 0251                                    bridgeName = "Bridges"; // Default bridge
 252                                }
 253
 0254                                if (bridgeGameObjects.TryGetValue(bridgeName, out GameObject bridgeObject) == false)
 255                                {
 0256                                    bridgeObject = GameObject.Find(bridgeName);
 0257                                    bridgeGameObjects.Add(bridgeName, bridgeObject);
 258                                }
 259
 0260                                if (bridgeObject != null)
 261                                {
 0262                                    bridgeObject.SendMessage(msg.type, msg.payload);
 263                                }
 264                                break;
 265                        }
 266
 0267                        if (DCLWebSocketService.VERBOSE)
 268                        {
 0269                            Debug.Log(
 270                                "<b><color=#0000FF>WebSocketCommunication</color></b> >>> Got it! passing message of typ
 271                                msg.type);
 272                        }
 273                    }
 274                }
 0275            }
 0276            yield return null;
 277        }
 0278    }
 279}