/// <summary>Adds a subscription to client to 'clientGuid'.</summary>
        /// <param name="subscriptionId">Identifier for the subscription.</param>
        /// <param name="clientGuid">    Unique identifier for the client.</param>
        /// <returns>True if it succeeds, false if it fails.</returns>
        public static bool AddSubscriptionToClient(string subscriptionId, Guid clientGuid)
        {
            if (string.IsNullOrEmpty(subscriptionId))
            {
                return(false);
            }

            if ((!SubscriptionManagerR4.Exists(subscriptionId)) &&
                (!SubscriptionManagerR5.Exists(subscriptionId)))
            {
                return(false);
            }

            if (!_instance._guidInfoDict.ContainsKey(clientGuid))
            {
                return(false);
            }

            _instance._guidInfoDict[clientGuid].SubscriptionIdSet.Add(subscriptionId);

            if (!_instance._subscriptionInfosDict.ContainsKey(subscriptionId))
            {
                _instance._subscriptionInfosDict.Add(subscriptionId, new List <WebsocketClientInformation>());
            }

            _instance._subscriptionInfosDict[subscriptionId].Add(_instance._guidInfoDict[clientGuid]);
            return(true);
        }
        /// <summary>Process the operation get ws binding token described by response.</summary>
        /// <param name="context">          [in,out] The context.</param>
        /// <param name="response">         [in,out] The response.</param>
        /// <param name="previousComponent">The previous component.</param>
        internal static void ProcessOperationGetWsBindingToken(
            ref HttpContext context,
            ref HttpResponseMessage response,
            string previousComponent)
        {
            List <string> ids = new List <string>();

            if (previousComponent != "Subscription")
            {
                ids.Add(previousComponent);
            }
            else
            {
                try
                {
                    using (TextReader reader = new StreamReader(context.Request.Body))
                    {
                        string requestContent = reader.ReadToEndAsync().Result;

                        Parameters opParams = _fhirParser.Parse <Parameters>(requestContent);

                        foreach (Parameters.ParameterComponent param in opParams.Parameter)
                        {
                            if (param.Name == "ids")
                            {
                                ids.Add((param.Value as Id).ToString());
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    response.StatusCode = HttpStatusCode.BadRequest;
                    response.Content    = new StringContent("Caught exception: " + ex.Message);
                    return;
                }
            }

            foreach (string id in ids)
            {
                if (!SubscriptionManagerR4.Exists(id))
                {
                    response.StatusCode = HttpStatusCode.BadRequest;
                    response.Content    = new StringContent($"Invalid subscription id: {id}");
                    return;
                }
            }

            SubscriptionWsBindingToken token = SubscriptionWsBindingToken.GetTokenR4(ids);

            WebsocketManager.RegisterToken(token);

            Parameters parameters = new Parameters();

            parameters.Add("token", new FhirString(token.Token.ToString()));
            parameters.Add("expiration", new FhirDateTime(new DateTimeOffset(token.ExpiresAt)));
            parameters.Add("subscriptions", new FhirString(string.Join(',', ids)));

            ProcessorUtils.SerializeR4(ref response, parameters);
        }
Esempio n. 3
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;
                }
            }
        }