Example #1
0
        /// <summary>Write client messages.</summary>
        /// <param name="webSocket">  The web socket.</param>
        /// <param name="clientGuid"> Unique identifier for the client.</param>
        /// <param name="cancelToken">A token that allows processing to be canceled.</param>
        /// <returns>An asynchronous result.</returns>
        private async Task WriteClientMessages(
            WebSocket webSocket,
            Guid clientGuid,
            CancellationToken cancelToken)
        {
            // get the client object
            if (!WebsocketManager.TryGetClient(clientGuid, out WebsocketClientInformation client))
            {
                // nothing to do here (will cancel on exit)
                return;
            }

            // loop until cancelled
            while (!cancelToken.IsCancellationRequested)
            {
                // do not bubble errors here
                try
                {
                    // **** check for a message ***
                    if (!client.MessageQ.TryDequeue(out string message))
                    {
                        // wait and prevent exceptions
                        await Task.Delay(_sendSleepDelayMs, cancelToken)
                        .ContinueWith(_ => Task.CompletedTask);

                        // go to next loop
                        continue;
                    }

                    // grab a byte buffer of our data
                    byte[] buffer = Encoding.UTF8.GetBytes(message);

                    // send this message
                    await webSocket.SendAsync(
                        buffer,
                        WebSocketMessageType.Text,
                        true,
                        cancelToken).ConfigureAwait(false);

                    WebsocketManager.UpdateTimeoutForSentMessage(clientGuid);
                }

                // keep looping
                catch (Exception ex)
                {
                    Console.WriteLine($"SubscriptionWebsocketHandler.WriteClientMessages" +
                                      $" <<< client: {clientGuid} caught exception: {ex.Message}");

                    // this socket is borked, exit
                    break;
                }
            }
        }
Example #2
0
        /// <summary>Keepalive thread function.</summary>
        private void KeepaliveThreadFunc()
        {
            List <Guid> clientsToRemove = new List <Guid>();

            try
            {
                // loop while there are clients
                while (!_clientMessageTimeoutDict.IsEmpty)
                {
                    long   currentTicks  = DateTime.Now.Ticks;
                    string keepaliveTime = string.Format(CultureInfo.InvariantCulture, "{0:o}", DateTime.Now.ToUniversalTime());

                    // traverse the dictionary looking for clients we need to send messages to
                    foreach (KeyValuePair <Guid, long> kvp in _clientMessageTimeoutDict)
                    {
                        // check timeout
                        if (currentTicks > kvp.Value)
                        {
                            // enqueue a message for this client
                            if (WebsocketManager.TryGetClient(kvp.Key, out WebsocketClientInformation client))
                            {
                                // enqueue a keepalive message
                                client.MessageQ.Enqueue($"keepalive {keepaliveTime}");
                            }
                            else
                            {
                                // client is gone, stop sending (cannot remove inside iterator)
                                clientsToRemove.Add(kvp.Key);
                            }
                        }
                    }

                    // remove any clients we need to remove
                    foreach (Guid clientGuid in clientsToRemove)
                    {
                        _clientMessageTimeoutDict.TryRemove(clientGuid, out _);
                    }

                    clientsToRemove.Clear();

                    Thread.Sleep(1000);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"SubscriptionWebsocketHandler.KeepaliveThreadFunc <<< exception: {ex.Message}");
            }
        }
Example #3
0
        /// <summary>Tests queueing messages.</summary>
        /// <param name="clientGuid">Unique identifier for the client.</param>
        private void TestQueueingMessages(Guid clientGuid)
        {
            bool done          = false;
            long messageNumber = 0;

            while (!done)
            {
                // check for no client
                if (!WebsocketManager.TryGetClient(clientGuid, out WebsocketClientInformation client))
                {
                    // done
                    done = true;
                    continue;
                }

                // queue a message for this client
                client.MessageQ.Enqueue($"Test message: {messageNumber++}, {DateTime.Now}");

                // wait a couple of seconds
                Thread.Sleep(2000);
            }
        }
Example #4
0
        /// <summary>Reads client messages.</summary>
        /// <param name="webSocket">  The web socket.</param>
        /// <param name="clientGuid"> Unique identifier for the client.</param>
        /// <param name="cancelToken">A token that allows processing to be cancelled.</param>
        /// <returns>An asynchronous result.</returns>
        private async Task ReadClientMessages(
            WebSocket webSocket,
            Guid clientGuid,
            CancellationToken cancelToken)
        {
            // get the client object
            if (!WebsocketManager.TryGetClient(clientGuid, out WebsocketClientInformation client))
            {
                // nothing to do here (will cancel on exit)
                return;
            }

            // create our receive buffer
            byte[] buffer = new byte[_messageBufferSize];
            int    count;
            int    messageLength = 0;

            WebSocketReceiveResult result;

            // loop until cancelled
            while (!cancelToken.IsCancellationRequested)
            {
                // reset buffer offset
                messageLength = 0;

                // do not bubble errors here
                try
                {
                    // read a message
                    do
                    {
                        count  = _messageBufferSize - messageLength;
                        result = await webSocket.ReceiveAsync(
                            new ArraySegment <byte>(
                                buffer,
                                messageLength,
                                count),
                            cancelToken).ConfigureAwait(false);

                        messageLength += result.Count;
                    }while (!result.EndOfMessage);

                    // process this message
                    if (result.MessageType == WebSocketMessageType.Close)
                    {
                        break;
                    }

                    // check for a bind request
                    string message = Encoding.UTF8.GetString(buffer).Substring(0, messageLength);

                    if (message.StartsWith("bind ", StringComparison.Ordinal))
                    {
                        // grab the rest of the content
                        message = message.Replace("bind ", string.Empty, StringComparison.Ordinal);

                        string[] ids = message.Split(',');

                        // traverse the requested ids
                        foreach (string id in ids)
                        {
                            string subscriptionId = id.StartsWith("Subscription/", StringComparison.Ordinal)
                                ? id.Replace("Subscription/", string.Empty, StringComparison.Ordinal)
                                : id;

                            // make sure this subscription exists
                            if ((!SubscriptionManagerR4.Exists(subscriptionId)) &&
                                (!SubscriptionManagerR5.Exists(subscriptionId)))
                            {
                                continue;
                            }

                            // register this subscription to this client
                            WebsocketManager.AddSubscriptionToClient(subscriptionId, clientGuid);
                        }
                    }

                    if (message.StartsWith("bind-with-token ", StringComparison.Ordinal))
                    {
                        // grab the rest of the content
                        message = message.Replace("bind-with-token ", string.Empty, StringComparison.Ordinal);

                        if (!Guid.TryParse(message, out Guid tokenGuid))
                        {
                            continue;
                        }

                        // register this token to this client
                        WebsocketManager.BindClientWithToken(tokenGuid, clientGuid);
                    }

                    if (message.StartsWith("unbind ", StringComparison.Ordinal))
                    {
                        // grab the rest of the content
                        message = message.Replace("unbind ", string.Empty, StringComparison.Ordinal);

                        string[] ids = message.Split(',');

                        // traverse the requested ids
                        foreach (string id in ids)
                        {
                            string subscriptionId = id.StartsWith("Subscription/", StringComparison.Ordinal)
                                ? id.Replace("Subscription/", string.Empty, StringComparison.Ordinal)
                                : id;

                            // remove this subscription from this client
                            WebsocketManager.RemoveSubscriptionFromClient(subscriptionId, clientGuid);
                        }
                    }
                }

                // keep looping
                catch (Exception ex)
                {
                    Console.WriteLine($"SubscriptionWebsocketHandler.ReadClientMessages" +
                                      $" <<< client: {clientGuid} caught exception: {ex.Message}");

                    // this socket is borked, exit
                    break;
                }
            }
        }