< Summary

Class:HybridWebSocket.WebSocket
Assembly:HybridWebSocket
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Plugins/unity-websocket-webgl/WebSocket.cs
Covered lines:0
Uncovered lines:56
Coverable lines:56
Total lines:799
Line coverage:0% (0 of 56)
Covered branches:0
Total branches:0
Covered methods:0
Total methods:6
Method coverage:0% (0 of 6)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
WebSocket(...)0%2100%
Connect()0%12300%
Close(...)0%12300%
Send(...)0%6200%
Send(...)0%6200%
GetState()0%42600%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Plugins/unity-websocket-webgl/WebSocket.cs

#LineLine coverage
 1/*
 2 * https://github.com/jirihybek/unity-websocket-webgl
 3 *
 4 * unity-websocket-webgl
 5 *
 6 * @author Jiri Hybek <jiri@hybek.cz>
 7 * @copyright 2018 Jiri Hybek <jiri@hybek.cz>
 8 * @license Apache 2.0 - See LICENSE file distributed with this source code.
 9 */
 10
 11using System;
 12using System.Collections.Generic;
 13using System.Runtime.InteropServices;
 14using UnityEngine;
 15using AOT;
 16using System.Text;
 17
 18namespace HybridWebSocket
 19{
 20
 21    /// <summary>
 22    /// Handler for WebSocket Open event.
 23    /// </summary>
 24    public delegate void WebSocketOpenEventHandler();
 25
 26    /// <summary>
 27    /// Handler for message received from WebSocket.
 28    /// </summary>
 29    public delegate void WebSocketMessageEventHandler(byte[] data);
 30
 31    /// <summary>
 32    /// Handler for an error event received from WebSocket.
 33    /// </summary>
 34    public delegate void WebSocketErrorEventHandler(string errorMsg);
 35
 36    /// <summary>
 37    /// Handler for WebSocket Close event.
 38    /// </summary>
 39    public delegate void WebSocketCloseEventHandler(WebSocketCloseCode closeCode);
 40
 41    /// <summary>
 42    /// Enum representing WebSocket connection state
 43    /// </summary>
 44    public enum WebSocketState
 45    {
 46        Connecting,
 47        Open,
 48        Closing,
 49        Closed
 50    }
 51
 52    /// <summary>
 53    /// Web socket close codes.
 54    /// </summary>
 55    public enum WebSocketCloseCode
 56    {
 57        /* Do NOT use NotSet - it's only purpose is to indicate that the close code cannot be parsed. */
 58        NotSet = 0,
 59        Normal = 1000,
 60        Away = 1001,
 61        ProtocolError = 1002,
 62        UnsupportedData = 1003,
 63        Undefined = 1004,
 64        NoStatus = 1005,
 65        Abnormal = 1006,
 66        InvalidData = 1007,
 67        PolicyViolation = 1008,
 68        TooBig = 1009,
 69        MandatoryExtension = 1010,
 70        ServerError = 1011,
 71        TlsHandshakeFailure = 1015
 72    }
 73
 74    /// <summary>
 75    /// WebSocket class interface shared by both native and JSLIB implementation.
 76    /// </summary>
 77    public interface IWebSocket
 78    {
 79        /// <summary>
 80        /// Open WebSocket connection
 81        /// </summary>
 82        void Connect();
 83
 84        /// <summary>
 85        /// Close WebSocket connection with optional status code and reason.
 86        /// </summary>
 87        /// <param name="code">Close status code.</param>
 88        /// <param name="reason">Reason string.</param>
 89        void Close(WebSocketCloseCode code = WebSocketCloseCode.Normal, string reason = null);
 90
 91        /// <summary>
 92        /// Send binary data over the socket.
 93        /// </summary>
 94        /// <param name="data">Payload data.</param>
 95        void Send(byte[] data);
 96
 97        /// <summary>
 98        /// Return WebSocket connection state.
 99        /// </summary>
 100        /// <returns>The state.</returns>
 101        WebSocketState GetState();
 102
 103        /// <summary>
 104        /// Occurs when the connection is opened.
 105        /// </summary>
 106        event WebSocketOpenEventHandler OnOpen;
 107
 108        /// <summary>
 109        /// Occurs when a message is received.
 110        /// </summary>
 111        event WebSocketMessageEventHandler OnMessage;
 112
 113        /// <summary>
 114        /// Occurs when an error was reported from WebSocket.
 115        /// </summary>
 116        event WebSocketErrorEventHandler OnError;
 117
 118        /// <summary>
 119        /// Occurs when the socked was closed.
 120        /// </summary>
 121        event WebSocketCloseEventHandler OnClose;
 122    }
 123
 124    /// <summary>
 125    /// Various helpers to work mainly with enums and exceptions.
 126    /// </summary>
 127    public static class WebSocketHelpers
 128    {
 129
 130        /// <summary>
 131        /// Safely parse close code enum from int value.
 132        /// </summary>
 133        /// <returns>The close code enum.</returns>
 134        /// <param name="closeCode">Close code as int.</param>
 135        public static WebSocketCloseCode ParseCloseCodeEnum(int closeCode)
 136        {
 137
 138            if (WebSocketCloseCode.IsDefined(typeof(WebSocketCloseCode), closeCode))
 139            {
 140                return (WebSocketCloseCode)closeCode;
 141            }
 142            else
 143            {
 144                return WebSocketCloseCode.Undefined;
 145            }
 146
 147        }
 148
 149        /*
 150         * Return error message based on int code
 151         *
 152
 153         */
 154        /// <summary>
 155        /// Return an exception instance based on int code.
 156        ///
 157        /// Used for resolving JSLIB errors to meaninfull messages.
 158        /// </summary>
 159        /// <returns>Instance of an exception.</returns>
 160        /// <param name="errorCode">Error code.</param>
 161        /// <param name="inner">Inner exception</param>
 162        public static WebSocketException GetErrorMessageFromCode(int errorCode, Exception inner)
 163        {
 164
 165            switch(errorCode)
 166            {
 167
 168                case -1: return new WebSocketUnexpectedException("WebSocket instance not found.", inner);
 169                case -2: return new WebSocketInvalidStateException("WebSocket is already connected or in connecting stat
 170                case -3: return new WebSocketInvalidStateException("WebSocket is not connected.", inner);
 171                case -4: return new WebSocketInvalidStateException("WebSocket is already closing.", inner);
 172                case -5: return new WebSocketInvalidStateException("WebSocket is already closed.", inner);
 173                case -6: return new WebSocketInvalidStateException("WebSocket is not in open state.", inner);
 174                case -7: return new WebSocketInvalidArgumentException("Cannot close WebSocket. An invalid code was speci
 175                default: return new WebSocketUnexpectedException("Unknown error.", inner);
 176
 177            }
 178
 179        }
 180
 181    }
 182
 183    /// <summary>
 184    /// Generic WebSocket exception class
 185    /// </summary>
 186    public class WebSocketException : Exception
 187    {
 188
 189        public WebSocketException()
 190        {
 191        }
 192
 193        public WebSocketException(string message)
 194            : base(message)
 195        {
 196        }
 197
 198        public WebSocketException(string message, Exception inner)
 199            : base(message, inner)
 200        {
 201        }
 202
 203    }
 204
 205    /// <summary>
 206    /// Web socket exception raised when an error was not expected, probably due to corrupted internal state.
 207    /// </summary>
 208    public class WebSocketUnexpectedException : WebSocketException
 209    {
 210        public WebSocketUnexpectedException(){}
 211        public WebSocketUnexpectedException(string message) : base(message){}
 212        public WebSocketUnexpectedException(string message, Exception inner) : base(message, inner) {}
 213    }
 214
 215    /// <summary>
 216    /// Invalid argument exception raised when bad arguments are passed to a method.
 217    /// </summary>
 218    public class WebSocketInvalidArgumentException : WebSocketException
 219    {
 220        public WebSocketInvalidArgumentException() { }
 221        public WebSocketInvalidArgumentException(string message) : base(message) { }
 222        public WebSocketInvalidArgumentException(string message, Exception inner) : base(message, inner) { }
 223    }
 224
 225    /// <summary>
 226    /// Invalid state exception raised when trying to invoke action which cannot be done due to different then required 
 227    /// </summary>
 228    public class WebSocketInvalidStateException : WebSocketException
 229    {
 230        public WebSocketInvalidStateException() { }
 231        public WebSocketInvalidStateException(string message) : base(message) { }
 232        public WebSocketInvalidStateException(string message, Exception inner) : base(message, inner) { }
 233    }
 234
 235#if UNITY_WEBGL && !UNITY_EDITOR
 236    /// <summary>
 237    /// WebSocket class bound to JSLIB.
 238    /// </summary>
 239    public class WebSocket: IWebSocket
 240    {
 241
 242        /* WebSocket JSLIB functions */
 243        [DllImport("__Internal")]
 244        public static extern int WebSocketConnect(int instanceId);
 245
 246        [DllImport("__Internal")]
 247        public static extern int WebSocketClose(int instanceId, int code, string reason);
 248
 249        [DllImport("__Internal")]
 250        public static extern int WebSocketSend(int instanceId, byte[] dataPtr, int dataLength);
 251
 252        [DllImport("__Internal")]
 253        public static extern int WebSocketSendString(int instanceId, string data);
 254
 255        [DllImport("__Internal")]
 256        public static extern int WebSocketGetState(int instanceId);
 257
 258        /// <summary>
 259        /// The instance identifier.
 260        /// </summary>
 261        protected int instanceId;
 262
 263        /// <summary>
 264        /// Occurs when the connection is opened.
 265        /// </summary>
 266        public event WebSocketOpenEventHandler OnOpen;
 267
 268        /// <summary>
 269        /// Occurs when a message is received.
 270        /// </summary>
 271        public event WebSocketMessageEventHandler OnMessage;
 272
 273        /// <summary>
 274        /// Occurs when an error was reported from WebSocket.
 275        /// </summary>
 276        public event WebSocketErrorEventHandler OnError;
 277
 278        /// <summary>
 279        /// Occurs when the socked was closed.
 280        /// </summary>
 281        public event WebSocketCloseEventHandler OnClose;
 282
 283        /// <summary>
 284        /// Constructor - receive JSLIB instance id of allocated socket
 285        /// </summary>
 286        /// <param name="instanceId">Instance identifier.</param>
 287        public WebSocket(int instanceId)
 288        {
 289
 290            this.instanceId = instanceId;
 291
 292        }
 293
 294        /// <summary>
 295        /// Destructor - notifies WebSocketFactory about it to remove JSLIB references
 296        /// Releases unmanaged resources and performs other cleanup operations before the
 297        /// <see cref="T:HybridWebSocket.WebSocket"/> is reclaimed by garbage collection.
 298        /// </summary>
 299        ~WebSocket()
 300        {
 301            WebSocketFactory.HandleInstanceDestroy(this.instanceId);
 302        }
 303
 304        /// <summary>
 305        /// Return JSLIB instance ID
 306        /// </summary>
 307        /// <returns>The instance identifier.</returns>
 308        public int GetInstanceId()
 309        {
 310
 311            return this.instanceId;
 312
 313        }
 314
 315        /// <summary>
 316        /// Open WebSocket connection
 317        /// </summary>
 318        public void Connect()
 319        {
 320
 321            int ret = WebSocketConnect(this.instanceId);
 322
 323            if (ret < 0)
 324                throw WebSocketHelpers.GetErrorMessageFromCode(ret, null);
 325
 326        }
 327
 328        /// <summary>
 329        /// Close WebSocket connection with optional status code and reason.
 330        /// </summary>
 331        /// <param name="code">Close status code.</param>
 332        /// <param name="reason">Reason string.</param>
 333        public void Close(WebSocketCloseCode code = WebSocketCloseCode.Normal, string reason = null)
 334        {
 335
 336            int ret = WebSocketClose(this.instanceId, (int)code, reason);
 337
 338            if (ret < 0)
 339                throw WebSocketHelpers.GetErrorMessageFromCode(ret, null);
 340
 341        }
 342
 343        /// <summary>
 344        /// Send binary data over the socket.
 345        /// </summary>
 346        /// <param name="data">Payload data.</param>
 347        public void Send(byte[] data)
 348        {
 349
 350            int ret = WebSocketSend(this.instanceId, data, data.Length);
 351
 352            if (ret < 0)
 353                throw WebSocketHelpers.GetErrorMessageFromCode(ret, null);
 354
 355        }
 356
 357        /// <summary>
 358        /// Send string data over the socket.
 359        /// </summary>
 360        /// <param name="data">Payload data.</param>
 361        public void Send(string data)
 362        {
 363            int ret = WebSocketSendString(this.instanceId, data);
 364
 365            if (ret < 0)
 366                throw WebSocketHelpers.GetErrorMessageFromCode(ret, null);
 367
 368        }
 369
 370        /// <summary>
 371        /// Return WebSocket connection state.
 372        /// </summary>
 373        /// <returns>The state.</returns>
 374        public WebSocketState GetState()
 375        {
 376
 377            int state = WebSocketGetState(this.instanceId);
 378
 379            if (state < 0)
 380                throw WebSocketHelpers.GetErrorMessageFromCode(state, null);
 381
 382            switch (state)
 383            {
 384                case 0:
 385                    return WebSocketState.Connecting;
 386
 387                case 1:
 388                    return WebSocketState.Open;
 389
 390                case 2:
 391                    return WebSocketState.Closing;
 392
 393                case 3:
 394                    return WebSocketState.Closed;
 395
 396                default:
 397                    return WebSocketState.Closed;
 398            }
 399
 400        }
 401
 402        /// <summary>
 403        /// Delegates onOpen event from JSLIB to native sharp event
 404        /// Is called by WebSocketFactory
 405        /// </summary>
 406        public void DelegateOnOpenEvent()
 407        {
 408
 409            this.OnOpen?.Invoke();
 410
 411        }
 412
 413        /// <summary>
 414        /// Delegates onMessage event from JSLIB to native sharp event
 415        /// Is called by WebSocketFactory
 416        /// </summary>
 417        /// <param name="data">Binary data.</param>
 418        public void DelegateOnMessageEvent(byte[] data)
 419        {
 420
 421            this.OnMessage?.Invoke(data);
 422
 423        }
 424
 425        /// <summary>
 426        /// Delegates onError event from JSLIB to native sharp event
 427        /// Is called by WebSocketFactory
 428        /// </summary>
 429        /// <param name="errorMsg">Error message.</param>
 430        public void DelegateOnErrorEvent(string errorMsg)
 431        {
 432
 433            this.OnError?.Invoke(errorMsg);
 434
 435        }
 436
 437        /// <summary>
 438        /// Delegate onClose event from JSLIB to native sharp event
 439        /// Is called by WebSocketFactory
 440        /// </summary>
 441        /// <param name="closeCode">Close status code.</param>
 442        public void DelegateOnCloseEvent(int closeCode)
 443        {
 444
 445            this.OnClose?.Invoke(WebSocketHelpers.ParseCloseCodeEnum(closeCode));
 446
 447        }
 448
 449    }
 450#else
 451    public class WebSocket : IWebSocket
 452    {
 453
 454        /// <summary>
 455        /// Occurs when the connection is opened.
 456        /// </summary>
 457        public event WebSocketOpenEventHandler OnOpen;
 458
 459        /// <summary>
 460        /// Occurs when a message is received.
 461        /// </summary>
 462        public event WebSocketMessageEventHandler OnMessage;
 463
 464        /// <summary>
 465        /// Occurs when an error was reported from WebSocket.
 466        /// </summary>
 467        public event WebSocketErrorEventHandler OnError;
 468
 469        /// <summary>
 470        /// Occurs when the socked was closed.
 471        /// </summary>
 472        public event WebSocketCloseEventHandler OnClose;
 473
 474        /// <summary>
 475        /// The WebSocketSharp instance.
 476        /// </summary>
 477        protected WebSocketSharp.WebSocket ws;
 478
 479        /// <summary>
 480        /// WebSocket constructor.
 481        /// </summary>
 482        /// <param name="url">Valid WebSocket URL.</param>
 0483        public WebSocket(string url)
 484        {
 485
 486            try
 487            {
 488
 489                // Create WebSocket instance
 0490                this.ws = new WebSocketSharp.WebSocket(url);
 0491                this.ws.SslConfiguration.EnabledSslProtocols = System.Security.Authentication.SslProtocols.Tls12;
 492
 493                // Bind OnOpen event
 0494                this.ws.OnOpen += (sender, ev) =>
 495                {
 0496                    this.OnOpen?.Invoke();
 0497                };
 498
 499                // Bind OnMessage event
 0500                this.ws.OnMessage += (sender, ev) =>
 501                {
 0502                    if (ev.RawData != null)
 0503                        this.OnMessage?.Invoke(ev.RawData);
 0504                };
 505
 506                // Bind OnError event
 0507                this.ws.OnError += (sender, ev) =>
 508                {
 0509                    this.OnError?.Invoke(ev.Message);
 0510                };
 511
 512                // Bind OnClose event
 0513                this.ws.OnClose += (sender, ev) =>
 514                {
 0515                    this.OnClose?.Invoke(
 516                        WebSocketHelpers.ParseCloseCodeEnum( (int)ev.Code )
 517                    );
 0518                };
 519
 0520            }
 0521            catch (Exception e)
 522            {
 523
 0524                throw new WebSocketUnexpectedException("Failed to create WebSocket Client.", e);
 525
 526            }
 527
 0528        }
 529
 530        /// <summary>
 531        /// Open WebSocket connection
 532        /// </summary>
 533        public void Connect()
 534        {
 535
 536            // Check state
 0537            if (this.ws.ReadyState == WebSocketSharp.WebSocketState.Open || this.ws.ReadyState == WebSocketSharp.WebSock
 0538                throw new WebSocketInvalidStateException("WebSocket is already connected or is closing.");
 539
 540            try
 541            {
 0542                this.ws.ConnectAsync();
 0543            }
 0544            catch (Exception e)
 545            {
 0546                throw new WebSocketUnexpectedException("Failed to connect.", e);
 547            }
 548
 0549        }
 550
 551        /// <summary>
 552        /// Close WebSocket connection with optional status code and reason.
 553        /// </summary>
 554        /// <param name="code">Close status code.</param>
 555        /// <param name="reason">Reason string.</param>
 556        public void Close(WebSocketCloseCode code = WebSocketCloseCode.Normal, string reason = null)
 557        {
 558
 559            // Check state
 0560            if (this.ws.ReadyState == WebSocketSharp.WebSocketState.Closing)
 0561                throw new WebSocketInvalidStateException("WebSocket is already closing.");
 562
 0563            if (this.ws.ReadyState == WebSocketSharp.WebSocketState.Closed)
 0564                throw new WebSocketInvalidStateException("WebSocket is already closed.");
 565
 566            try
 567            {
 0568                this.ws.CloseAsync((ushort)code, reason);
 0569            }
 0570            catch (Exception e)
 571            {
 0572                throw new WebSocketUnexpectedException("Failed to close the connection.", e);
 573            }
 574
 0575        }
 576
 577        /// <summary>
 578        /// Send binary data over the socket.
 579        /// </summary>
 580        /// <param name="data">Payload data.</param>
 581        public void Send(byte[] data)
 582        {
 583
 584            // Check state
 0585            if (this.ws.ReadyState != WebSocketSharp.WebSocketState.Open)
 0586                throw new WebSocketInvalidStateException("WebSocket is not in open state.");
 587
 588            try
 589            {
 0590                this.ws.Send(data);
 0591            }
 0592            catch (Exception e)
 593            {
 0594                throw new WebSocketUnexpectedException("Failed to send message.", e);
 595            }
 596
 0597        }
 598
 599        /// <summary>
 600        /// Send binary data over the socket.
 601        /// </summary>
 602        /// <param name="data">Payload data.</param>
 603        public void Send(string data)
 604        {
 605
 606            // Check state
 0607            if (this.ws.ReadyState != WebSocketSharp.WebSocketState.Open)
 0608                throw new WebSocketInvalidStateException("WebSocket is not in open state.");
 609
 610            try
 611            {
 0612                this.ws.Send(data);
 0613            }
 0614            catch (Exception e)
 615            {
 0616                throw new WebSocketUnexpectedException("Failed to send message.", e);
 617            }
 618
 0619        }
 620
 621        /// <summary>
 622        /// Return WebSocket connection state.
 623        /// </summary>
 624        /// <returns>The state.</returns>
 625        public WebSocketState GetState()
 626        {
 627
 0628            switch (this.ws.ReadyState)
 629            {
 630                case WebSocketSharp.WebSocketState.Connecting:
 0631                    return WebSocketState.Connecting;
 632
 633                case WebSocketSharp.WebSocketState.Open:
 0634                    return WebSocketState.Open;
 635
 636                case WebSocketSharp.WebSocketState.Closing:
 0637                    return WebSocketState.Closing;
 638
 639                case WebSocketSharp.WebSocketState.Closed:
 0640                    return WebSocketState.Closed;
 641
 642                default:
 0643                    return WebSocketState.Closed;
 644            }
 645
 646        }
 647
 648    }
 649#endif
 650
 651    /// <summary>
 652    /// Class providing static access methods to work with JSLIB WebSocket or WebSocketSharp interface
 653    /// </summary>
 654    public static class WebSocketFactory
 655    {
 656
 657#if UNITY_WEBGL && !UNITY_EDITOR
 658        /* Map of websocket instances */
 659        private static Dictionary<Int32, WebSocket> instances = new Dictionary<Int32, WebSocket>();
 660
 661        /* Delegates */
 662        public delegate void OnOpenCallback(int instanceId);
 663        public delegate void OnMessageCallback(int instanceId, System.IntPtr msgPtr, int msgSize);
 664        public delegate void OnErrorCallback(int instanceId, System.IntPtr errorPtr);
 665        public delegate void OnCloseCallback(int instanceId, int closeCode);
 666
 667        /* WebSocket JSLIB callback setters and other functions */
 668        [DllImport("__Internal")]
 669        public static extern int WebSocketAllocate(string url);
 670
 671        [DllImport("__Internal")]
 672        public static extern void WebSocketFree(int instanceId);
 673
 674        [DllImport("__Internal")]
 675        public static extern void WebSocketSetOnOpen(OnOpenCallback callback);
 676
 677        [DllImport("__Internal")]
 678        public static extern void WebSocketSetOnMessage(OnMessageCallback callback);
 679
 680        [DllImport("__Internal")]
 681        public static extern void WebSocketSetOnError(OnErrorCallback callback);
 682
 683        [DllImport("__Internal")]
 684        public static extern void WebSocketSetOnClose(OnCloseCallback callback);
 685
 686        /* If callbacks was initialized and set */
 687        private static bool isInitialized = false;
 688
 689        /*
 690         * Initialize WebSocket callbacks to JSLIB
 691         */
 692        private static void Initialize()
 693        {
 694
 695            WebSocketSetOnOpen(DelegateOnOpenEvent);
 696            WebSocketSetOnMessage(DelegateOnMessageEvent);
 697            WebSocketSetOnError(DelegateOnErrorEvent);
 698            WebSocketSetOnClose(DelegateOnCloseEvent);
 699
 700            isInitialized = true;
 701
 702        }
 703
 704        /// <summary>
 705        /// Called when instance is destroyed (by destructor)
 706        /// Method removes instance from map and free it in JSLIB implementation
 707        /// </summary>
 708        /// <param name="instanceId">Instance identifier.</param>
 709        public static void HandleInstanceDestroy(int instanceId)
 710        {
 711
 712            instances.Remove(instanceId);
 713            WebSocketFree(instanceId);
 714
 715        }
 716
 717        [MonoPInvokeCallback(typeof(OnOpenCallback))]
 718        public static void DelegateOnOpenEvent(int instanceId)
 719        {
 720
 721            WebSocket instanceRef;
 722
 723            if (instances.TryGetValue(instanceId, out instanceRef))
 724            {
 725                instanceRef.DelegateOnOpenEvent();
 726            }
 727
 728        }
 729
 730        [MonoPInvokeCallback(typeof(OnMessageCallback))]
 731        public static void DelegateOnMessageEvent(int instanceId, System.IntPtr msgPtr, int msgSize)
 732        {
 733
 734            WebSocket instanceRef;
 735
 736            if (instances.TryGetValue(instanceId, out instanceRef))
 737            {
 738                byte[] msg = new byte[msgSize];
 739                Marshal.Copy(msgPtr, msg, 0, msgSize);
 740
 741                instanceRef.DelegateOnMessageEvent(msg);
 742            }
 743
 744        }
 745
 746        [MonoPInvokeCallback(typeof(OnErrorCallback))]
 747        public static void DelegateOnErrorEvent(int instanceId, System.IntPtr errorPtr)
 748        {
 749
 750            WebSocket instanceRef;
 751
 752            if (instances.TryGetValue(instanceId, out instanceRef))
 753            {
 754
 755                string errorMsg = Marshal.PtrToStringAuto(errorPtr);
 756                instanceRef.DelegateOnErrorEvent(errorMsg);
 757
 758            }
 759
 760        }
 761
 762        [MonoPInvokeCallback(typeof(OnCloseCallback))]
 763        public static void DelegateOnCloseEvent(int instanceId, int closeCode)
 764        {
 765
 766            WebSocket instanceRef;
 767
 768            if (instances.TryGetValue(instanceId, out instanceRef))
 769            {
 770                instanceRef.DelegateOnCloseEvent(closeCode);
 771            }
 772
 773        }
 774#endif
 775
 776        /// <summary>
 777        /// Create WebSocket client instance
 778        /// </summary>
 779        /// <returns>The WebSocket instance.</returns>
 780        /// <param name="url">WebSocket valid URL.</param>
 781        public static WebSocket CreateInstance(string url)
 782        {
 783#if UNITY_WEBGL && !UNITY_EDITOR
 784        if (!isInitialized)
 785            Initialize();
 786
 787        int instanceId = WebSocketAllocate(url);
 788        WebSocket wrapper = new WebSocket(instanceId);
 789        instances.Add(instanceId, wrapper);
 790
 791        return wrapper;
 792#else
 793            return new WebSocket(url);
 794#endif
 795        }
 796
 797    }
 798
 799}