Example #1
0
 private void ClearGeneratedApiObjects()
 {
     lock (GeneratedApiObjects)
     {
         foreach (var item in GeneratedApiObjects.Keys)
         {
             try
             {
                 if (GeneratedApiObjects.TryRemove(item, out var value))
                 {
                     GeneratedAPI target = null;
                     if (value?.TryGetTarget(out target) ?? false)
                     {
                         _ = Task.Run(() =>
                         {
                             try
                             {
                                 target?.OnClosed();
                             }
                             catch { }
                         });
                     }
                 }
             }
             catch (Exception ex)
             {
                 logger.Error(ex);
             }
         }
     }
 }
Example #2
0
#pragma warning disable 1591 // no XML Comment Warning for override
        public override bool TryConvert(ConvertBinder binder, out object result)
        {
            Type gArgs            = binder.ReturnType.GetGenericArguments().FirstOrDefault();
            bool tryDynamicResult = false;

            if (gArgs == typeof(object))
            {
                gArgs            = typeof(JObject);
                tryDynamicResult = true;
            }
            gArgs = gArgs ?? typeof(object);
            if (!gArgs.IsAssignableFrom(typeof(JToken)))
            {
                var tcs = new TaskCompletionSource(gArgs);

                input.ContinueWith((message) =>
                {
                    if (message.IsCanceled)
                    {
                        tcs.SetCanceled();
                        return;
                    }
                    if (message.IsFaulted)
                    {
                        tcs.SetException(message.Exception);
                        return;
                    }

                    var qReturn = message?.Result?.SelectToken("qReturn");
                    if (qReturn != null && qReturn.Type == JTokenType.Object && qReturn["qHandle"] != null)
                    {
                        if (qReturn["qHandle"].Type == JTokenType.Null)
                        {
                            tcs.SetResult(null);
                        }
                        else
                        {
                            try
                            {
                                var objectResult = qReturn.ToObject <ObjectResult>();
                                var newObj       = new GeneratedAPI(objectResult, session, gArgs);
                                session.GeneratedApiObjects.TryAdd(objectResult.QHandle, new WeakReference <GeneratedAPI>(newObj));
                                tcs.SetResult(newObj.ProxyClass);
                            }
                            catch (Exception ex)
                            {
                                tcs.SetException(ex);
                            }
                        }
                    }
                    else
                    {
                        try
                        {
                            object newRes      = null;
                            JToken resultToken = null;

                            var results = message.Result.Children().ToList();
                            if (results.Count == 1)
                            {
                                resultToken = results.FirstOrDefault().First();
                            }
                            else
                            {
                                resultToken = message.Result;
                            }

                            if (gArgs.IsAssignableFrom(typeof(JObject)) && resultToken as JObject != null)
                            {
                                if (tryDynamicResult)
                                {
                                    dynamic dt = resultToken as JObject;
                                    var tcs2   = new TaskCompletionSource <dynamic>();
                                    tcs2.SetResult(resultToken);
                                }
                                else
                                {
                                    tcs.SetResult(resultToken);
                                }
                                return;
                            }

                            if (gArgs != typeof(object))
                            {
                                newRes = resultToken.ToObject(gArgs);
                            }
                            else
                            {
                                newRes = resultToken;
                            }

                            tcs.SetResult(newRes);
                        }
                        catch (Exception ex)
                        {
                            tcs.SetException(ex);
                        }
                    }
                }
                                   );

                result = tcs.Task;
                return(true);
            }

            result = input;
            return(true);
        }
Example #3
0
        private void StartReceiveLoop(CancellationToken cancellationToken)
        {
            _ = Task.Run(async() =>
            {
                byte[] buffer = new byte[4096 * 8];

                #region Helper to Notify API Objects
                void notifyGeneratedAPI(WeakReference <GeneratedAPI> wrGeneratedAPI, bool close)
                {
                    Console.WriteLine("notifyGeneratedAPI");
                    GeneratedAPI generatedAPI = null;
                    wrGeneratedAPI?.TryGetTarget(out generatedAPI);
                    if (generatedAPI != null)
                    {
                        Console.WriteLine("notifyGeneratedAPI - genAPI");
                        _ = Task.Run(() =>
                        {
                            try
                            {
                                Console.WriteLine("notifyGeneratedAPI - RUN");
                                if (close)
                                {
                                    generatedAPI?.OnClosed();
                                }
                                else
                                {
                                    generatedAPI?.OnChanged();
                                }
                            }
                            catch (Exception ex)
                            {
                                logger.Error(ex);
                            }
                        }).ConfigureAwait(false);
                    }
                }
                #endregion

                try
                {
                    while (!cancellationToken.IsCancellationRequested && socket != null && socket.State == WebSocketState.Open)
                    {
                        var writeSegment = new ArraySegment <byte>(buffer);
                        WebSocketReceiveResult result;
                        do
                        {
                            result       = await socket.ReceiveAsync(writeSegment, cancellationToken).ConfigureAwait(false);
                            writeSegment = new ArraySegment <byte>(buffer, writeSegment.Offset + result.Count, writeSegment.Count - result.Count);

                            // check buffer overflow
                            if (!result.EndOfMessage && writeSegment.Count == 0)
                            {
                                // autoIncreaseRecieveBuffer)
                                Array.Resize(ref buffer, buffer.Length * 2);
                                writeSegment = new ArraySegment <byte>(buffer, writeSegment.Offset, buffer.Length - writeSegment.Offset);
                            }
                        } while (!result.EndOfMessage);

                        var message = Encoding.UTF8.GetString(buffer, 0, writeSegment.Offset);
                        logger.Trace("Response" + message);
                        try
                        {
                            var responseMessage = JsonConvert.DeserializeObject <JsonRpcGeneratedAPIResponseMessage>(message);
                            try
                            {
                                var list = Messages.GetBuffer();
                                if (responseMessage != null)
                                {
                                    foreach (var item in list)
                                    {
                                        if (item != null && item.ID == responseMessage.Id)
                                        {
                                            var ts        = DateTime.Now - item.StartTime;
                                            item.Duration = ts.TotalMilliseconds;
                                            item.Error    = responseMessage.Error?.ToString() ?? "";
                                        }
                                    }
                                }
                            }
                            catch (Exception ex)
                            {
                                logger.Error(ex);
                            }
                            if (responseMessage != null &&
                                (responseMessage.Result != null ||
                                 responseMessage.Error != null ||
                                 responseMessage.Change?.Count > 0 ||
                                 responseMessage.Closed?.Count > 0
                                ))
                            {
                                if (responseMessage.Id != null)
                                {
                                    OpenRequests.TryRemove(responseMessage.Id.Value, out var tcs);
                                    if (responseMessage.Error != null)
                                    {
                                        tcs?.SetException(new Exception(responseMessage.Error?.ToString()));
                                    }
                                    else
                                    {
                                        tcs?.SetResult(responseMessage.Result);
                                    }
                                }

                                #region Notify Changed or Closed API Objects
                                if (responseMessage.Change != null)
                                {
                                    foreach (var item in responseMessage.Change)
                                    {
                                        logger.Trace($"Object Id: {item} changed.");
                                        GeneratedApiObjects.TryGetValue(item, out var wkValues);
                                        notifyGeneratedAPI(wkValues, false);
                                    }
                                }

                                if (responseMessage.Closed != null)
                                {
                                    foreach (var item in responseMessage.Closed)
                                    {
                                        logger.Trace($"Object Id: {item} closed.");
                                        GeneratedApiObjects.TryRemove(item, out var wkValues);
                                        notifyGeneratedAPI(wkValues, true);
                                    }
                                }
                                #endregion
                            }
                            else
                            {
                                var requestMessage = JsonConvert.DeserializeObject <JsonRpcRequestMessage>(message);
                                if (requestMessage != null)
                                {
                                    _ = Task.Run(() =>
                                    {
                                        try
                                        {
                                            this.RPCMethodCalled?.Invoke(this, requestMessage);
                                        }
                                        catch (Exception ex)
                                        {
                                            logger.Error(ex);
                                        }
                                    });
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            logger.Error(ex);
                        }
                    }

                    ClearGeneratedApiObjects();
                }
                catch (Exception ex)
                {
                    logger.Error(ex);
                }
            });
        }
Example #4
0
        /// <summary>
        /// Establishes the websocket against the configured URL.
        /// Try to get the QIX global interface when the connection has been established.
        /// </summary>
        /// <returns></returns>
        public async Task <dynamic> OpenAsync(CancellationToken?ctn = null)
        {
            if (socket != null)
            {
                await CloseAsync(ctn);
            }
            LastOpenError = null;
            CancellationToken ct = ctn ?? CancellationToken.None;

            socket = await config.CreateSocketCall(ct).ConfigureAwait(false);

            // Todo add here the global Cancelation Token that is
            // triggered from the CloseAsync
            bool?connected = null;

            void RPCMethodCall(object sender, JsonRpcRequestMessage e)
            {
                logger.Trace($"RPCMethodCall - {e.Method}:{e.Parameters}");
                if (e.Method == "OnAuthenticationInformation" && (bool?)e.Parameters["mustAuthenticate"] == true)
                {
                    connected     = false;
                    LastOpenError = "Connection established but authentication failed";
                }
                if (e.Method == "OnConnected")
                {
                    LastOpenError = "";
                    connected     = true;
                }
                if (!connected.HasValue)
                {
                    string message = "";
                    try
                    {
                        message = (string)e.Parameters["message"];
                    }
                    catch (Exception ex)
                    {
                        logger.Error(ex);
                    }
                    string severity = "";
                    try
                    {
                        severity = (string)e.Parameters["severity"];
                    }
                    catch (Exception ex)
                    {
                        logger.Error(ex);
                    }
                    if (!string.IsNullOrEmpty(severity) && severity == "fatal")
                    {
                        try
                        {
                            LastOpenError = e.Method + "\n" + message;
                        }
                        catch (Exception ex)
                        {
                            logger.Error(ex);
                            LastOpenError = "Communication Error";
                        }
                        connected = false;
                    }
                }
            }

            RPCMethodCalled += RPCMethodCall;
            StartReceiveLoop(ct);
            while (connected == null && !ct.IsCancellationRequested)
            {
                Thread.Sleep(10);
            }
            RPCMethodCalled -= RPCMethodCall;

            if (connected == false)
            {
                socket?.CloseAsync(WebSocketCloseStatus.InternalServerError, "", ct);
                throw new Exception("Connection Error");
            }

            // start SendLoop only if connection is opened
            StartSendLoop(ct);
            var global = new GeneratedAPI(new ObjectResult()
            {
                QHandle = -1, QType = "Global"
            }, this);

            GeneratedApiObjects.TryAdd(-1, new WeakReference <GeneratedAPI>(global));
            return(global);
        }