public void ConnectToServer(IPAddress ip, int port)
    {
        if (_webSocketConnection != null) return;
        
        _webSocketConnection = new WebSocket($"ws://{ip}:{port}");

        _webSocketConnection.OnOpen += (sender, args) =>
        {
            Connected?.Invoke();
        };
        
        _webSocketConnection.OnClose += (sender, args) =>
        {
            Disconnected?.Invoke();
        };
        
        _webSocketConnection.OnMessage += (sender, args) =>
        {
            if (args.IsText)
            {
                ReceivedTextMessage?.Invoke(args.Data);
            }
            else if (args.IsBinary)
            {
                ReceivedByteArrayMessage?.Invoke(args.RawData);
            }
        };

        _webSocketConnection.OnError += (sender, args) =>
        {
            ReceivedError?.Invoke();
        };
        
        _webSocketConnection.Connect();
    }
예제 #2
0
        private async Task ReceiveLoop(WebSocket webSocket, CancellationToken cancellationToken)
        {
            var buffer = new byte[MaxMessageSize];

            while (true)
            {
                var result = await webSocket.ReceiveAsync(new ArraySegment <byte>(buffer), cancellationToken);

                if (result == null)
                {
                    break;
                }

                if (result.MessageType == WebSocketMessageType.Close)
                {
                    break;
                }

                var data = await ReadFrames(result, webSocket, buffer);

                if (data.Count == 0)
                {
                    break;
                }

                try
                {
                    Received?.Invoke(data);
                }
                catch (Exception e)
                {
                    ReceivedError?.Invoke(e);
                }
            }
        }
예제 #3
0
파일: Server.cs 프로젝트: paulpach/Mirror
        // send message to client using socket connection or throws exception
        public async void Send(int connectionId, ArraySegment <byte> segment)
        {
            // find the connection
            if (clients.TryGetValue(connectionId, out WebSocket client))
            {
                try
                {
                    await client.SendAsync(segment, WebSocketMessageType.Binary, true, cancellation.Token);
                }
                catch (ObjectDisposedException) {
                    // connection has been closed,  swallow exception
                    Disconnect(connectionId);
                }
                catch (Exception exception)
                {
                    if (clients.ContainsKey(connectionId))
                    {
                        // paul:  If someone unplugs their internet
                        // we can potentially get hundreds of errors here all at once
                        // because all the WriteAsync wake up at once and throw exceptions

                        // by hiding inside this if, I ensure that we only report the first error
                        // all other errors are swallowed.
                        // this prevents a log storm that freezes the server for several seconds
                        ReceivedError?.Invoke(connectionId, exception);
                    }

                    Disconnect(connectionId);
                }
            }
            else
            {
                ReceivedError?.Invoke(connectionId, new SocketException((int)SocketError.NotConnected));
            }
        }
예제 #4
0
        public async void Connect(System.Uri uri)
        {
            var clientFactory = new WebSocketClientFactory();

            cancellation = new CancellationTokenSource();

            Connecting = true;

            try
            {
                using (WebSocket = await clientFactory.ConnectAsync(uri, ClientOptions, cancellation.Token))
                {
                    Connecting       = false;
                    ConnectionActive = true;
                    Connected?.Invoke();

                    await Receive(WebSocket, cancellation.Token);
                }
            }
            catch (System.ObjectDisposedException)
            {
                // client closed
                Debug.Log("closed connection");
            }
            catch (System.Exception ex)
            {
                Debug.LogError(ex);
                ReceivedError?.Invoke(ex);
            }
            finally
            {
                Disconnect();
            }
        }
예제 #5
0
        private async Task <ArraySegment <byte> > ReadFrames(WebSocketReceiveResult result, WebSocket webSocket,
                                                             byte[] buffer)
        {
            var count = result.Count;

            while (!result.EndOfMessage)
            {
                if (count >= MaxMessageSize)
                {
                    var closeMessage = $"Maximum message size {MaxMessageSize} bytes reached.";
                    await webSocket.CloseAsync(WebSocketCloseStatus.MessageTooBig, closeMessage,
                                               CancellationToken.None);

                    ReceivedError?.Invoke(new WebSocketException(WebSocketError.HeaderError));
                    return(new ArraySegment <byte>());
                }

                result = await webSocket.ReceiveAsync(new ArraySegment <byte>(buffer, count, MaxMessageSize - count),
                                                      CancellationToken.None);

                count += result.Count;
            }

            return(new ArraySegment <byte>(buffer, 0, count));
        }
예제 #6
0
파일: Server.cs 프로젝트: favoyang/MirrorNG
        public async Task Listen(int port)
        {
            try
            {
                cancellation = new CancellationTokenSource();

                listener = TcpListener.Create(port);
                listener.Server.NoDelay = this.NoDelay;
                listener.Start();
                Debug.Log($"Websocket server started listening on port {port}");
                while (true)
                {
                    TcpClient tcpClient = await listener.AcceptTcpClientAsync();

                    _ = ProcessTcpClient(tcpClient, cancellation.Token);
                }
            }
            catch (ObjectDisposedException)
            {
                // do nothing. This will be thrown if the Listener has been stopped
            }
            catch (Exception ex)
            {
                ReceivedError?.Invoke(0, ex);
            }
        }
        /// <inheritdoc cref="ISocketAdapter.Connect"/>
        public void Connect(Uri uri, int timeout)
        {
            // TODO will need to use window.setTimeout to implement timeouts on DOM WebSocket.
            if (Ref > -1)
            {
                ReceivedError?.Invoke(new SocketException((int)SocketError.IsConnected));
                return;
            }

            _uri         = uri;
            IsConnecting = true;

            Action open = () =>
            {
                IsConnected  = true;
                IsConnecting = false;
                Connected?.Invoke();
            };
            Action <int, string> close = (code, reason) =>
            {
                IsConnected  = false;
                IsConnecting = false;
                Ref          = -1;
                Closed?.Invoke();
            };
            Action <string> error = reason =>
            {
                IsConnected = false;
                Ref         = -1;
                ReceivedError?.Invoke(new Exception(reason));
            };
            Action <string> handler = message => { Received?.Invoke(new ArraySegment <byte>(Encoding.UTF8.GetBytes(message))); };

            Ref = UnityWebGLSocketBridge.Instance.CreateSocket(uri.AbsoluteUri, open, close, error, handler);
        }
        async Task ReceiveLoop(WebSocket webSocket, CancellationToken token)
        {
            byte[] buffer = new byte[MaxMessageSize];

            while (true)
            {
                WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment <byte>(buffer), token);

                if (result == null)
                {
                    break;
                }
                if (result.MessageType == WebSocketMessageType.Close)
                {
                    break;
                }

                // we got a text or binary message,  need the full message
                ArraySegment <byte> data = await ReadFrames(result, webSocket, buffer);

                if (data.Count == 0)
                {
                    break;
                }

                try
                {
                    ReceivedData?.Invoke(data);
                }
                catch (Exception exception)
                {
                    ReceivedError?.Invoke(exception);
                }
            }
        }
예제 #9
0
        /// <summary>
        /// A new socket with server connection and adapter options.
        /// </summary>
        /// <param name="scheme">The protocol scheme. Must be "ws" or "wss".</param>
        /// <param name="host">The host address of the server.</param>
        /// <param name="port">The port number of the server.</param>
        /// <param name="adapter">The adapter for use with the socket.</param>
        public Socket(string scheme, string host, int port, ISocketAdapter adapter)
        {
            Logger     = NullLogger.Instance;
            _adapter   = adapter;
            _baseUri   = new UriBuilder(scheme, host, port).Uri;
            _responses = new ConcurrentDictionary <string, TaskCompletionSource <WebSocketMessageEnvelope> >();

            _adapter.Connected += () => Connected?.Invoke();
            _adapter.Closed    += () =>
            {
                foreach (var response in _responses)
                {
                    response.Value.TrySetCanceled();
                }

                _responses.Clear();
                Closed?.Invoke();
            };
            _adapter.ReceivedError += e =>
            {
                if (!_adapter.IsConnected)
                {
                    foreach (var response in _responses)
                    {
                        response.Value.TrySetCanceled();
                    }

                    _responses.Clear();
                }

                ReceivedError?.Invoke(e);
            };
            _adapter.Received += ReceivedMessage;
        }
예제 #10
0
파일: Server.cs 프로젝트: favoyang/MirrorNG
        async Task ProcessTcpClient(TcpClient tcpClient, CancellationToken token)
        {
            try
            {
                // this worker thread stays alive until either of the following happens:
                // Client sends a close conection request OR
                // An unhandled exception is thrown OR
                // The server is disposed

                // get a secure or insecure stream
                Stream stream = tcpClient.GetStream();
                if (_secure)
                {
                    SslStream sslStream = new SslStream(stream, false, CertVerificationCallback);
                    sslStream.AuthenticateAsServer(_sslConfig.Certificate, _sslConfig.ClientCertificateRequired, _sslConfig.EnabledSslProtocols, _sslConfig.CheckCertificateRevocation);
                    stream = sslStream;
                }
                WebSocketHttpContext context = await webSocketServerFactory.ReadHttpHeaderFromStreamAsync(tcpClient, stream, token);

                if (context.IsWebSocketRequest)
                {
                    WebSocketServerOptions options = new WebSocketServerOptions()
                    {
                        KeepAliveInterval = TimeSpan.FromSeconds(30), SubProtocol = "binary"
                    };

                    WebSocket webSocket = await webSocketServerFactory.AcceptWebSocketAsync(context, options);

                    await ReceiveLoopAsync(webSocket, token);
                }
                else
                {
                    Debug.Log("Http header contains no web socket upgrade request. Ignoring");
                }
            }
            catch (IOException)
            {
                // do nothing. This will be thrown if the transport is closed
            }
            catch (ObjectDisposedException)
            {
                // do nothing. This will be thrown if the Listener has been stopped
            }
            catch (Exception ex)
            {
                ReceivedError?.Invoke(0, ex);
            }
            finally
            {
                try
                {
                    tcpClient.Client.Close();
                    tcpClient.Close();
                }
                catch (Exception ex)
                {
                    ReceivedError?.Invoke(0, ex);
                }
            }
        }
예제 #11
0
파일: Client.cs 프로젝트: favoyang/MirrorNG
        private async Task ReceiveLoop(TcpClient client)
        {
            using (Stream networkStream = client.GetStream())
            {
                while (true)
                {
                    byte[] data = await ReadMessageAsync(networkStream);

                    if (data == null)
                    {
                        break;
                    }

                    try
                    {
                        // we received some data,  raise event
                        ReceivedData?.Invoke(data);
                    }
                    catch (Exception exception)
                    {
                        ReceivedError?.Invoke(exception);
                    }
                }
            }
        }
예제 #12
0
        async Task ReceiveLoopAsync(WebSocket webSocket, CancellationToken token)
        {
            int connectionId = NextConnectionId();

            clients.Add(connectionId, webSocket);

            byte[] buffer = new byte[MaxMessageSize];

            try
            {
                // someone connected,  raise event
                Connected?.Invoke(connectionId);

                while (true)
                {
                    WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment <byte>(buffer), token);

                    if (!enabled)
                    {
                        await WaitForEnabledAsync();
                    }

                    if (result.MessageType == WebSocketMessageType.Close)
                    {
                        Debug.Log($"Client initiated close. Status: {result.CloseStatus} Description: {result.CloseStatusDescription}");
                        break;
                    }

                    ArraySegment <byte> data = await ReadFrames(connectionId, result, webSocket, buffer, token);

                    if (data.Count == 0)
                    {
                        break;
                    }

                    try
                    {
                        // we received some data,  raise event
                        ReceivedData?.Invoke(connectionId, data);
                    }
                    catch (Exception exception)
                    {
                        ReceivedError?.Invoke(connectionId, exception);
                    }
                }
            }
            catch (Exception exception)
            {
                ReceivedError?.Invoke(connectionId, exception);
            }
            finally
            {
                clients.Remove(connectionId);
                Disconnected?.Invoke(connectionId);
            }
        }
        private async Task ReceiveLoop(WebSocket webSocket, CancellationToken canceller)
        {
            canceller.ThrowIfCancellationRequested();

            var buffer          = new byte[_maxMessageReadSize];
            var bufferReadCount = 0;

            try
            {
                do
                {
                    var bufferSegment =
                        new ArraySegment <byte>(buffer, bufferReadCount, _maxMessageReadSize - bufferReadCount);
                    var result = await webSocket.ReceiveAsync(bufferSegment, canceller).ConfigureAwait(false);

                    if (result == null)
                    {
                        break;
                    }

                    if (result.MessageType == WebSocketMessageType.Close)
                    {
                        break;
                    }

                    bufferReadCount += result.Count;
                    if (!result.EndOfMessage)
                    {
                        continue;
                    }

                    try
                    {
                        Received?.Invoke(new ArraySegment <byte>(buffer, 0, bufferReadCount));
                    }
                    catch (Exception e)
                    {
                        ReceivedError?.Invoke(e);
                    }

                    bufferReadCount = 0;
                } while (_webSocket.State == WebSocketState.Open && !canceller.IsCancellationRequested);
            }
            catch (Exception e)
            {
                ReceivedError?.Invoke(e);
            }
            finally
            {
                IsConnecting = false;
                IsConnected  = false;
                Closed?.Invoke();
            }
        }
예제 #14
0
        /// <inheritdoc cref="ISocketAdapter.Send"/>
        public void Send(ArraySegment <byte> buffer, CancellationToken cancellationToken,
                         bool reliable = true)
        {
            if (Ref == -1)
            {
                ReceivedError?.Invoke(new SocketException((int)SocketError.NotConnected));
                return;
            }

            var payload = Encoding.UTF8.GetString(buffer.Array, buffer.Offset, buffer.Count);

            UnityWebGLSocketBridge.Instance.Send(Ref, payload);
        }
예제 #15
0
        public async void Connect(Uri uri)
        {
            // not if already started
            if (webSocket != null)
            {
                // paul:  exceptions are better than silence
                ReceivedError?.Invoke(new Exception("Client already connected"));
                return;
            }

            this.uri = uri;
            // We are connecting from now until Connect succeeds or fails
            Connecting = true;

            var options = new WebSocketClientOptions()
            {
                NoDelay              = true,
                KeepAliveInterval    = TimeSpan.Zero,
                SecWebSocketProtocol = "binary"
            };

            cancellation = new CancellationTokenSource();

            var clientFactory = new WebSocketClientFactory();

            try
            {
                using (webSocket = await clientFactory.ConnectAsync(uri, options, cancellation.Token))
                {
                    var token = cancellation.Token;
                    IsConnected = true;
                    Connecting  = false;
                    Connected?.Invoke();

                    await ReceiveLoop(webSocket, token);
                }
            }
            catch (ObjectDisposedException)
            {
                // No error, the client got closed
            }
            catch (Exception ex)
            {
                ReceivedError?.Invoke(ex);
            }
            finally
            {
                Disconnect();
                Disconnected?.Invoke();
            }
        }
예제 #16
0
        public async void Connect(string host, int port)
        {
            // not if already started
            if (client != null)
            {
                // paul:  exceptions are better than silence
                ReceivedError?.Invoke(new Exception("Client already connected"));
                return;
            }

            // We are connecting from now until Connect succeeds or fails
            Connecting = true;



            try
            {
                // TcpClient can only be used once. need to create a new one each
                // time.
                client = new TcpClient(AddressFamily.InterNetworkV6);
                // works with IPv6 and IPv4
                client.Client.DualMode = true;

                // NoDelay disables nagle algorithm. lowers CPU% and latency
                // but increases bandwidth
                client.NoDelay = this.NoDelay;

                await client.ConnectAsync(host, port);

                // now we are connected:
                IsConnected = true;
                Connecting  = false;

                Connected?.Invoke();
                await ReceiveLoop(client);
            }
            catch (ObjectDisposedException)
            {
                // No error, the client got closed
            }
            catch (Exception ex)
            {
                ReceivedError?.Invoke(ex);
            }
            finally
            {
                Disconnect();
                Disconnected?.Invoke();
            }
        }
예제 #17
0
        public void Send()
        {
            if (Client.ConnectionActive == false)
            {
                ReceivedError?.Invoke(new System.Net.Sockets.SocketException((int)System.Net.Sockets.SocketError.NotConnected));
                return;
            }

            if (EnqueuedMessagesToSend.Count > 0)
            {
                SendEnqueuedMessages(EnqueuedMessagesToSend);
                EnqueuedMessagesToSend = new List <DetourMessage>();
            }
        }
예제 #18
0
파일: Server.cs 프로젝트: realcast/Mirror
        // the listener thread's listen function
        public async Task ListenAsync(int port)
        {
            // absolutely must wrap with try/catch, otherwise thread
            // exceptions are silent
            try
            {
                if (listener != null)
                {
                    ReceivedError?.Invoke(0, new Exception("Already listening"));
                    return;
                }

                // start listener
                listener = TcpListener.Create(port);

                // NoDelay disables nagle algorithm. lowers CPU% and latency
                // but increases bandwidth
                listener.Server.NoDelay = this.NoDelay;
                listener.Start();
                Debug.Log($"Tcp server started listening on port {port}");

                // keep accepting new clients
                while (true)
                {
                    // wait for a tcp client;
                    TcpClient tcpClient = await listener.AcceptTcpClientAsync();

                    // non blocking receive loop
                    // must be on main thread
                    Task receive = ReceiveLoop(tcpClient);
                }
            }
            catch (ObjectDisposedException)
            {
                Debug.Log("Server dispossed");
            }
            catch (Exception exception)
            {
                ReceivedError?.Invoke(0, exception);
            }
            finally
            {
                listener = null;
            }
        }
        /// <inheritdoc cref="ISocketAdapter.Connect"/>
        public async void Connect(Uri uri, int timeout)
        {
            if (_webSocket != null)
            {
                ReceivedError?.Invoke(new SocketException((int)SocketError.IsConnected));
                return;
            }

            _cancellationSource = new CancellationTokenSource();
            _uri         = uri;
            IsConnecting = true;

            var clientFactory = new WebSocketClientFactory();

            try
            {
                var cts  = new CancellationTokenSource(TimeSpan.FromSeconds(timeout));
                var lcts = CancellationTokenSource.CreateLinkedTokenSource(_cancellationSource.Token, cts.Token);
                using (_webSocket = await clientFactory.ConnectAsync(_uri, _options, lcts.Token))
                {
                    IsConnected  = true;
                    IsConnecting = false;
                    Connected?.Invoke();

                    await ReceiveLoop(_webSocket, _cancellationSource.Token);
                }
            }
            catch (TaskCanceledException)
            {
                // No error, the socket got closed via the cancellation signal.
            }
            catch (ObjectDisposedException)
            {
                // No error, the socket got closed.
            }
            catch (Exception e)
            {
                ReceivedError?.Invoke(e);
            }
            finally
            {
                Close();
                Closed?.Invoke();
            }
        }
예제 #20
0
파일: Client.cs 프로젝트: favoyang/MirrorNG
        // send the data or throw exception
        public async Task SendAsync(ArraySegment <byte> data)
        {
            if (client == null)
            {
                ReceivedError?.Invoke(new SocketException((int)SocketError.NotConnected));
                return;
            }

            try
            {
                await SendMessage(client.GetStream(), data);
            }
            catch (Exception ex)
            {
                Disconnect();
                ReceivedError?.Invoke(ex);
            }
        }
예제 #21
0
        // send the data or throw exception
        public async void Send(byte[] data)
        {
            if (webSocket == null)
            {
                ReceivedError?.Invoke(new SocketException((int)SocketError.NotConnected));
                return;
            }

            try
            {
                await webSocket.SendAsync(new ArraySegment <byte>(data), WebSocketMessageType.Binary, true, cancellation.Token);
            }
            catch (Exception ex)
            {
                Disconnect();
                ReceivedError?.Invoke(ex);
            }
        }
예제 #22
0
파일: Server.cs 프로젝트: realcast/Mirror
        private async Task ReceiveLoop(TcpClient tcpClient)
        {
            int connectionId = NextConnectionId();

            clients.Add(connectionId, tcpClient);

            try
            {
                // someone connected,  raise event
                Connected?.Invoke(connectionId);

                using (Stream networkStream = tcpClient.GetStream())
                {
                    while (true)
                    {
                        byte[] data = await ReadMessageAsync(networkStream);

                        if (data == null)
                        {
                            break;
                        }

                        try
                        {
                            // we received some data,  raise event
                            ReceivedData?.Invoke(connectionId, data);
                        }
                        catch (Exception exception)
                        {
                            ReceivedError?.Invoke(connectionId, exception);
                        }
                    }
                }
            }
            catch (Exception exception)
            {
                ReceivedError?.Invoke(connectionId, exception);
            }
            finally
            {
                clients.Remove(connectionId);
                Disconnected?.Invoke(connectionId);
            }
        }
예제 #23
0
        /// <summary>
        /// A new socket with server connection and adapter options.
        /// </summary>
        /// <param name="scheme">The protocol scheme. Must be "ws" or "wss".</param>
        /// <param name="host">The host address of the server.</param>
        /// <param name="port">The port number of the server.</param>
        /// <param name="adapter">The adapter for use with the socket.</param>
        /// <param name="sendTimeoutSec">The maximum time allowed for a message to be sent.</param>
        public Socket(string scheme, string host, int port, ISocketAdapter adapter, int sendTimeoutSec = DefaultSendTimeout)
        {
            Logger          = NullLogger.Instance;
            _adapter        = adapter;
            _baseUri        = new UriBuilder(scheme, host, port).Uri;
            _responses      = new Dictionary <string, TaskCompletionSource <WebSocketMessageEnvelope> >();
            _sendTimeoutSec = TimeSpan.FromSeconds(sendTimeoutSec);

            _adapter.Connected += () => Connected?.Invoke();
            _adapter.Closed    += () =>
            {
                lock (_responsesLock)
                {
                    foreach (var response in _responses)
                    {
                        response.Value.TrySetCanceled();
                    }

                    _responses.Clear();
                }

                Closed?.Invoke();
            };
            _adapter.ReceivedError += e =>
            {
                if (!_adapter.IsConnected)
                {
                    lock (_responsesLock)
                    {
                        foreach (var response in _responses)
                        {
                            response.Value.TrySetCanceled();
                        }

                        _responses.Clear();
                    }
                }

                ReceivedError?.Invoke(e);
            };

            _adapter.Received += ProcessMessage;
        }
예제 #24
0
        /// <inheritdoc cref="ISocketAdapter.Send"/>
        public async void Send(ArraySegment <byte> buffer, CancellationToken cancellationToken,
                               bool reliable = true)
        {
            if (_webSocket == null)
            {
                ReceivedError?.Invoke(new SocketException((int)SocketError.NotConnected));
                return;
            }

            try
            {
                await _webSocket.SendAsync(buffer, WebSocketMessageType.Text, true, cancellationToken);
            }
            catch (Exception e)
            {
                Close();
                ReceivedError?.Invoke(e);
            }
        }
예제 #25
0
        // a message might come splitted in multiple frames
        // collect all frames
        private async Task <byte[]> ReadFrames(WebSocketReceiveResult result, WebSocket webSocket, byte[] buffer)
        {
            int count = result.Count;

            while (!result.EndOfMessage)
            {
                if (count >= MaxMessageSize)
                {
                    string closeMessage = string.Format("Maximum message size: {0} bytes.", MaxMessageSize);
                    await webSocket.CloseAsync(WebSocketCloseStatus.MessageTooBig, closeMessage, CancellationToken.None);

                    ReceivedError?.Invoke(new WebSocketException(WebSocketError.HeaderError));
                    return(null);
                }

                result = await webSocket.ReceiveAsync(new ArraySegment <byte>(buffer, count, MaxMessageSize - count), CancellationToken.None);

                count += result.Count;
            }
            return(new ArraySegment <byte>(buffer, 0, count).ToArray());
        }
예제 #26
0
 private void SendEnqueuedMessages(List <DetourMessage> enqueuedMessagesToSend)
 {
     foreach (var item in enqueuedMessagesToSend)
     {
         if (ConnectionActive)
         {
             try
             {
                 JSONBuffer    = JsonConvert.SerializeObject(item, JSONSettings);
                 MessageBuffer = Encoding.UTF8.GetBytes(JSONBuffer);
                 Client.Send(MessageBuffer);
             }
             catch (System.Exception ex)
             {
                 Debug.LogError(ex);
                 Client.Disconnect();
                 ReceivedError?.Invoke(ex);
             }
         }
     }
 }
예제 #27
0
파일: Server.cs 프로젝트: realcast/Mirror
        // send message to client using socket connection or throws exception
        private async Task SendAsync(int connectionId, MemoryStream data)
        {
            // find the connection
            if (clients.TryGetValue(connectionId, out TcpClient client))
            {
                try
                {
                    NetworkStream stream = client.GetStream();
                    await SendMessage(stream, data);
                }
                catch (ObjectDisposedException)
                {
                    // connection has been closed,  swallow exception
                    Disconnect(connectionId);
                }
                catch (Exception exception)
                {
                    if (clients.ContainsKey(connectionId))
                    {
                        // paul:  If someone unplugs their internet
                        // we can potentially get hundreds of errors here all at once
                        // because all the WriteAsync wake up at once and throw exceptions

                        // by hiding inside this if, I ensure that we only report the first error
                        // all other errors are swallowed.
                        // this prevents a log storm that freezes the server for several seconds
                        ReceivedError?.Invoke(connectionId, exception);
                    }

                    Disconnect(connectionId);
                }
            }
            else
            {
                ReceivedError?.Invoke(connectionId, new SocketException((int)SocketError.NotConnected));
            }
            // we are done with the buffer return it
            bufferPool.PutObject(data);
        }
    public void ConnectToServer(string address, int port, bool isUsingSecureConnection)
    {
        if (_webSocketConnection != null)
        {
            return;
        }

        var urlPrefix = isUsingSecureConnection ? "wss" : "ws";

        _webSocketConnection = new WebSocket($"{urlPrefix}://{address}:{port}/Listener");

        _webSocketConnection.OnOpen += (sender, args) =>
        {
            Connected?.Invoke();
        };

        _webSocketConnection.OnClose += (sender, args) =>
        {
            Disconnected?.Invoke();
        };

        _webSocketConnection.OnMessage += (sender, args) =>
        {
            if (args.IsBinary)
            {
                ReceivedByteArrayMessage?.Invoke(args.RawData);
            }
        };

        _webSocketConnection.OnError += (sender, args) =>
        {
            ReceivedError?.Invoke();
        };

        _webSocketConnection.Connect();

        ConfigureNoDelay();
    }
예제 #29
0
        private void ReceivedMessage(ArraySegment <byte> buffer)
        {
            var contents = System.Text.Encoding.UTF8.GetString(buffer.Array, buffer.Offset, buffer.Count);

            Logger?.DebugFormat("Received JSON over web socket: {0}", contents);

            var envelope = contents.FromJson <WebSocketMessageEnvelope>();

            try
            {
                if (!string.IsNullOrEmpty(envelope.Cid))
                {
                    lock (_lockObj)
                    {
                        // Handle message response.
                        if (_responses.ContainsKey(envelope.Cid))
                        {
                            TaskCompletionSource <WebSocketMessageEnvelope> completer = _responses[envelope.Cid];
                            _responses.Remove(envelope.Cid);

                            if (envelope.Error != null)
                            {
                                completer.SetException(new WebSocketException(WebSocketError.InvalidState, envelope.Error.Message));
                            }
                            else
                            {
                                completer.SetResult(envelope);
                            }
                        }
                        else
                        {
                            Logger?.ErrorFormat("No completer for message cid: {0}", envelope.Cid);
                        }
                    }
                }
                else if (envelope.Error != null)
                {
                    ReceivedError?.Invoke(new WebSocketException(WebSocketError.InvalidState, envelope.Error.Message));
                }
                else if (envelope.ChannelMessage != null)
                {
                    ReceivedChannelMessage?.Invoke(envelope.ChannelMessage);
                }
                else if (envelope.ChannelPresenceEvent != null)
                {
                    ReceivedChannelPresence?.Invoke(envelope.ChannelPresenceEvent);
                }
                else if (envelope.MatchmakerMatched != null)
                {
                    ReceivedMatchmakerMatched?.Invoke(envelope.MatchmakerMatched);
                }
                else if (envelope.MatchPresenceEvent != null)
                {
                    ReceivedMatchPresence?.Invoke(envelope.MatchPresenceEvent);
                }
                else if (envelope.MatchState != null)
                {
                    ReceivedMatchState?.Invoke(envelope.MatchState);
                }
                else if (envelope.NotificationList != null)
                {
                    foreach (var notification in envelope.NotificationList.Notifications)
                    {
                        ReceivedNotification?.Invoke(notification);
                    }
                }
                else if (envelope.StatusPresenceEvent != null)
                {
                    ReceivedStatusPresence?.Invoke(envelope.StatusPresenceEvent);
                }
                else if (envelope.StreamPresenceEvent != null)
                {
                    ReceivedStreamPresence?.Invoke(envelope.StreamPresenceEvent);
                }
                else if (envelope.StreamState != null)
                {
                    ReceivedStreamState?.Invoke(envelope.StreamState);
                }
                else if (envelope.Party != null)
                {
                    ReceivedParty?.Invoke(envelope.Party);
                }
                else if (envelope.PartyClose != null)
                {
                    ReceivedPartyClose?.Invoke(envelope.PartyClose);
                }
                else if (envelope.PartyData != null)
                {
                    ReceivedPartyData?.Invoke(envelope.PartyData);
                }
                else if (envelope.PartyJoinRequest != null)
                {
                    ReceivedPartyJoinRequest?.Invoke(envelope.PartyJoinRequest);
                }
                else if (envelope.PartyLeader != null)
                {
                    ReceivedPartyLeader?.Invoke(envelope.PartyLeader);
                }
                else if (envelope.PartyMatchmakerTicket != null)
                {
                    ReceivedPartyMatchmakerTicket?.Invoke(envelope.PartyMatchmakerTicket);
                }
                else if (envelope.PartyPresenceEvent != null)
                {
                    ReceivedPartyPresence?.Invoke(envelope.PartyPresenceEvent);
                }
                else
                {
                    Logger?.ErrorFormat("Received unrecognised message: '{0}'", contents);
                }
            }
            catch (Exception e)
            {
                ReceivedError?.Invoke(e);
            }
        }
예제 #30
0
        private void ReceivedMessage(ArraySegment <byte> buffer)
        {
            var contents = System.Text.Encoding.UTF8.GetString(buffer.Array, buffer.Offset, buffer.Count);

            var envelope = contents.FromJson <WebSocketMessageEnvelope>();

            try
            {
                if (!string.IsNullOrEmpty(envelope.Cid))
                {
                    // Handle message response.
                    TaskCompletionSource <WebSocketMessageEnvelope> completer;
                    var cid = envelope.Cid;
                    _responses.TryRemove(cid, out completer);
                    if (completer == null)
                    {
                        Logger?.ErrorFormat("No completer for message cid: {0}", envelope.Cid);
                        return;
                    }

                    if (envelope.Error != null)
                    {
                        completer.SetException(new WebSocketException(WebSocketError.InvalidState,
                                                                      envelope.Error.Message));
                    }
                    else
                    {
                        completer.SetResult(envelope);
                    }
                }
                else if (envelope.Error != null)
                {
                    ReceivedError?.Invoke(new WebSocketException(WebSocketError.InvalidState, envelope.Error.Message));
                }
                else if (envelope.ChannelMessage != null)
                {
                    ReceivedChannelMessage?.Invoke(envelope.ChannelMessage);
                }
                else if (envelope.ChannelPresenceEvent != null)
                {
                    ReceivedChannelPresence?.Invoke(envelope.ChannelPresenceEvent);
                }
                else if (envelope.MatchmakerMatched != null)
                {
                    ReceivedMatchmakerMatched?.Invoke(envelope.MatchmakerMatched);
                }
                else if (envelope.MatchPresenceEvent != null)
                {
                    ReceivedMatchPresence?.Invoke(envelope.MatchPresenceEvent);
                }
                else if (envelope.MatchState != null)
                {
                    ReceivedMatchState?.Invoke(envelope.MatchState);
                }
                else if (envelope.NotificationList != null)
                {
                    foreach (var notification in envelope.NotificationList.Notifications)
                    {
                        ReceivedNotification?.Invoke(notification);
                    }
                }
                else if (envelope.StatusPresenceEvent != null)
                {
                    ReceivedStatusPresence?.Invoke(envelope.StatusPresenceEvent);
                }
                else if (envelope.StreamPresenceEvent != null)
                {
                    ReceivedStreamPresence?.Invoke(envelope.StreamPresenceEvent);
                }
                else if (envelope.StreamState != null)
                {
                    ReceivedStreamState?.Invoke(envelope.StreamState);
                }
                else
                {
                    Logger?.ErrorFormat("Received unrecognised message: '{0}'", contents);
                }
            }
            catch (Exception e)
            {
                ReceivedError?.Invoke(e);
            }
        }