Task <PushRouterState> LoadAysnc(CancellationToken cancellationToken)
 {
     try
     {
         return(AVPlugins.Instance.StorageController.LoadAsync().OnSuccess(_ =>
         {
             var currentCache = _.Result;
             object routeCacheStr = null;
             if (currentCache.TryGetValue(routerKey, out routeCacheStr))
             {
                 var routeCache = routeCacheStr as IDictionary <string, object>;
                 var routerState = new PushRouterState()
                 {
                     groupId = routeCache["groupId"] as string,
                     server = routeCache["server"] as string,
                     secondary = routeCache["secondary"] as string,
                     ttl = long.Parse(routeCache["ttl"].ToString()),
                     expire = long.Parse(routeCache["expire"].ToString()),
                     source = "localCache"
                 };
                 return routerState;
             }
             return null;
         }));
     }
     catch
     {
         return(Task.FromResult <PushRouterState>(null));
     }
 }
        Task <PushRouterState> QueryAsync(CancellationToken cancellationToken)
        {
            var appRouter  = AVPlugins.Instance.AppRouterController.Get();
            var routerHost = string.Format("https://{0}/v1/route?appId={1}&secure=1", appRouter.RealtimeRouterServer, AVClient.CurrentConfiguration.ApplicationId) ?? appRouter.RealtimeRouterServer ?? string.Format(routerUrl, AVClient.CurrentConfiguration.ApplicationId);

            return(AVClient.RequestAsync(uri: new Uri(routerHost),
                                         method: "GET",
                                         headers: null,
                                         data: null,
                                         contentType: "",
                                         cancellationToken: CancellationToken.None).ContinueWith <PushRouterState>(t =>
            {
                var httpStatus = (int)t.Result.Item1;
                if (httpStatus != 200)
                {
                    throw new AVException(AVException.ErrorCode.ConnectionFailed, "can not reach router.", null);
                }
                try
                {
                    var result = t.Result.Item2;

                    var routerState = Json.Parse(result) as IDictionary <string, object>;
                    if (routerState.Keys.Count == 0)
                    {
                        throw new KeyNotFoundException("Can not get websocket url from server,please check the appId.");
                    }
                    var ttl = long.Parse(routerState["ttl"].ToString());
                    var expire = DateTime.Now.AddSeconds(ttl);
                    routerState["expire"] = expire.UnixTimeStampSeconds();

                    //save to local cache async.
                    AVPlugins.Instance.StorageController.LoadAsync().OnSuccess(storage => storage.Result.AddAsync(routerKey, routerState));
                    var routerStateObj = new PushRouterState()
                    {
                        groupId = routerState["groupId"] as string,
                        server = routerState["server"] as string,
                        secondary = routerState["secondary"] as string,
                        ttl = long.Parse(routerState["ttl"].ToString()),
                        expire = expire.UnixTimeStampSeconds(),
                        source = "online"
                    };

                    return routerStateObj;
                }
                catch (Exception e)
                {
                    if (e is KeyNotFoundException)
                    {
                        throw e;
                    }
                    return null;
                }
            }));
        }
        Task <PushRouterState> QueryAsync(string pushRouter, bool secure, CancellationToken cancellationToken)
        {
            var routerHost = pushRouter;

            if (routerHost == null)
            {
                var appRouter = AVPlugins.Instance.AppRouterController.Get();
                routerHost = string.Format("https://{0}/v1/route?appId={1}", appRouter.RealtimeRouterServer, AVClient.CurrentConfiguration.ApplicationId) ?? appRouter.RealtimeRouterServer ?? string.Format(routerUrl, AVClient.CurrentConfiguration.ApplicationId);
            }
            AVRealtime.PrintLog($"router: {routerHost}");
            AVRealtime.PrintLog($"push: {pushRouter}");
            if (!string.IsNullOrEmpty(pushRouter))
            {
                var rtmUri = new Uri(pushRouter);
                if (!string.IsNullOrEmpty(rtmUri.Scheme))
                {
                    var url = new Uri(rtmUri, "v1/route").ToString();
                    routerHost = string.Format("{0}?appId={1}", url, AVClient.CurrentConfiguration.ApplicationId);
                }
                else
                {
                    routerHost = string.Format("https://{0}/v1/route?appId={1}", pushRouter, AVClient.CurrentConfiguration.ApplicationId);
                }
            }
            if (secure)
            {
                routerHost += "&secure=1";
            }

            AVRealtime.PrintLog("use push router url:" + routerHost);

            return(AVClient.RequestAsync(uri: new Uri(routerHost),
                                         method: "GET",
                                         headers: null,
                                         data: null,
                                         contentType: "application/json",
                                         cancellationToken: CancellationToken.None).ContinueWith <PushRouterState>(t =>
            {
                if (t.Exception != null)
                {
                    var innnerException = t.Exception.InnerException.InnerException.InnerException;
                    if (innnerException != null)
                    {
                        AVRealtime.PrintLog(innnerException.Message);
                        return null;
                    }
                }
                var httpStatus = (int)t.Result.Item1;
                if (httpStatus != 200)
                {
                    return null;
                }
                try
                {
                    var result = t.Result.Item2;

                    var routerState = Json.Parse(result) as IDictionary <string, object>;
                    if (routerState.Keys.Count == 0)
                    {
                        throw new KeyNotFoundException("Can not get websocket url from server,please check the appId.");
                    }
                    var ttl = long.Parse(routerState["ttl"].ToString());
                    var expire = DateTime.Now.AddSeconds(ttl);
                    routerState["expire"] = expire.ToUnixTimeStamp();

                    //save to local cache async.
                    AVPlugins.Instance.StorageController.LoadAsync().OnSuccess(storage => storage.Result.AddAsync(routerKey, routerState));
                    var routerStateObj = new PushRouterState()
                    {
                        groupId = routerState["groupId"] as string,
                        server = routerState["server"] as string,
                        secondary = routerState["secondary"] as string,
                        ttl = long.Parse(routerState["ttl"].ToString()),
                        expire = expire.ToUnixTimeStamp(),
                        source = "online"
                    };

                    return routerStateObj;
                }
                catch (Exception e)
                {
                    if (e is KeyNotFoundException)
                    {
                        throw e;
                    }
                    return null;
                }
            }));
        }