Exemple #1
0
        /// <summary>
        /// Asynchonously force the session to be started, and invalidate session if idle; e.g. when <see cref="LastActionTime"/> is longer than <see cref="IdleTimeout"/> ago.
        /// </summary>
        protected async Task ForceSessionAsync(CancellationToken ct)
        {
            // Quit this method if already cancelled
            ct.ThrowIfCancellationRequested();

            if (!IsStarted)
            {
                throw new InvalidSessionException("Session not started");
            }

            if (LastActionTime.TimeoutOccurred(IdleTimeout))
            {
                // Check timeout
                if (await InvalidateAsync(ct))
                {
                    return;
                }

                if (!AutoReconnect)
                {
                    throw new InvalidSessionException("Session timed out");
                }

                await LoginAsync(ct);
            }
        }
Exemple #2
0
        /// <summary>
        /// Asynchronously finalize the api session
        /// </summary>
        /// <returns>Success?</returns>
        public async Task <Boolean> LogoutAsync(CancellationToken ct)
        {
            await ForceSessionAsync(ct);

            var uri          = new Uri(Host, URL_HOME + String.Format(SID_ARG_FORMAT, Id));
            var request      = (HttpWebRequest)WebRequest.Create(uri);
            var responseArgs = new Dictionary <String, String> {
                { @"logout", @"1" }
            };

            // Register the callback to a method that can unblock.
            // Dispose of the CancellationTokenRegistration object
            // after the callback has completed.
            using (ct.Register(request.Abort)) {
                try {
                    // Store response data in a seperate stream and parse content
                    using (var content = await request.PostUrlencodedAsync(responseArgs)) {
                        // Read stream data
                        String text = await content.ReadStringAsync(ct);

                        LastActionTime.Reset();
                        Id = SessionId.Invalid;

                        return(text.Contains(@"/login.lua"));
                    }
                } catch (WebException e) {
                    if (e.Status == WebExceptionStatus.RequestCanceled)
                    {
                        ct.ThrowIfCancellationRequested();
                    }

                    throw;
                }
            }
        }
Exemple #3
0
        /// <summary>
        /// Asynchronously loads a query-item partition
        /// </summary>
        /// <param name="partition">The partition to load</param>
        /// <param name="urlStringBase">The base url string</param>
        /// <param name="resultDict">The result dictionary</param>
        /// <param name="ct">The CancellationToken used to cancel this async operation</param>
        /// <param name="progress">The progress update handler</param>
        /// <param name="total">The total number of items, needed for progress calculation</param>
        /// <returns>A task performing this operation</returns>
        protected async Task LoadPartition(IDictionary <String, String> partition, String urlStringBase, ConcurrentDictionary <UInt64, String> resultDict, CancellationToken ct, IProgress <Tuple <int, int> > progress, int total)
        {
            var uri     = new Uri(Host, urlStringBase + @"&" + HttpWebRequestExtension.FormUrlEncodeParameters(partition));
            var request = (HttpWebRequest)WebRequest.Create(uri);

            request.Method = HTTP_METHOD_GET;

            // Quit this method if already cancelled
            ct.ThrowIfCancellationRequested();

            // Register the callback to a method that can unblock.
            // Dispose of the CancellationTokenRegistration object
            // after the callback has completed.
            using (ct.Register(request.Abort)) {
                try {
                    // Store response data in a seperate stream
                    using (var content = await request.ReadResponseAsync()) {
                        LastActionTime.Update();

                        // Read stream data
                        var text = await content.ReadStringAsync(ct);

                        // Parse JSON Items like
                        //   "a0": "74.05.50"
                        foreach (Match match in QUERY_JSON_RESPONSE_ITEM_REGEX.Matches(text))
                        {
                            UInt64 p;

                            if (!UInt64.TryParse(match.Groups[@"id"].Value, out p))
                            {
                                throw new Exception("Invalid argument number");
                            }

                            if (resultDict.ContainsKey(p))
                            {
                                throw new Exception("Duplicate element");
                            }

                            if (resultDict.TryAdd(p, match.Groups[@"value"].Value) && progress != null)
                            {
                                progress.Report(Tuple.Create(resultDict.Count, total));
                            }
                        }
                    }
                } catch (WebException e) {
                    if (e.Status == WebExceptionStatus.RequestCanceled)
                    {
                        ct.ThrowIfCancellationRequested();
                    }

                    throw;
                }
            }
        }
Exemple #4
0
        /// <summary>
        /// Asynchronously invalidates the current session state
        /// </summary>
        /// <returns>Validity of the current session</returns>
        public async Task <Boolean> InvalidateAsync(CancellationToken ct)
        {
            if (!IsStarted)
            {
                return(false);
            }

            var xml = await ReadSessionDataAsync(Id, ct);

            var sid = new SessionId(xml.DocumentElement[FIELD_NAME_SID].InnerText);

            LastActionTime.Update();

            return(sid.IsValid);
        }
Exemple #5
0
        /// <summary>
        /// Asynchonously execute commands
        /// </summary>
        /// <param name="commands">The commands to execute</param>
        /// <param name="ct">The cancellation token used to cancel this operation</param>
        /// <returns>The api response-text</returns>
        public async Task <String> SendCommandsAsync(IEnumerable <KeyValuePair <String, String> > commands, CancellationToken ct)
        {
            await ForceSessionAsync(ct);

            var uri          = new Uri(Host, URL_WEBCM);
            var request      = (HttpWebRequest)WebRequest.Create(uri);
            var responseArgs = new Dictionary <String, String> {
                { @"sid", Id }
            };

            // Copy over commands
            foreach (var command in commands)
            {
                responseArgs.Add(command.Key, command.Value);
            }

            // Store response data in a seperate stream and read to end
            String responseText;

            // Quit this method if already cancelled
            ct.ThrowIfCancellationRequested();

            // Register the callback to a method that can unblock.
            // Dispose of the CancellationTokenRegistration object
            // after the callback has completed.
            using (ct.Register(request.Abort)) {
                try {
                    using (var content = await request.PostUrlencodedAsync(responseArgs)) {
                        LastActionTime.Update();

                        // Read stream data
                        responseText = await content.ReadStringAsync(ct);
                    }
                } catch (WebException e) {
                    if (e.Status == WebExceptionStatus.RequestCanceled)
                    {
                        ct.ThrowIfCancellationRequested();
                    }

                    throw;
                }
            }

            return(responseText);
        }
Exemple #6
0
        /// <summary>
        /// Asynchronously start a new api session
        /// </summary>
        public async Task LoginAsync(CancellationToken ct)
        {
            ct.ThrowIfCancellationRequested();

            // Request login challange
            XmlDocument xml = await ReadSessionDataAsync(Id, ct);

            // We may already be logged in
            var currentSid = new SessionId(xml.DocumentElement[FIELD_NAME_SID].InnerText);

            if (currentSid.IsValid)
            {
                Id = currentSid;
                LastActionTime.Update();

                return;
            }

            // Login
            var challenge      = xml.DocumentElement[FIELD_NAME_CHALLENGE].InnerText;
            var responseString = CalculateLoginResponse(challenge, Password);

            var uri          = new Uri(Host, URL_LOGIN);
            var request      = (HttpWebRequest)WebRequest.Create(uri);
            var responseArgs = new Dictionary <String, String> {
                { ARG_NAME_RESPONSE, responseString }
            };

            if (!String.IsNullOrEmpty(Username))
            {
                responseArgs.Add(ARG_NAME_USERNAME, Username);
            }

            // Quit this method if already cancelled
            ct.ThrowIfCancellationRequested();

            // Register the callback to a method that can unblock.
            // Dispose of the CancellationTokenRegistration object
            // after the callback has completed.
            using (ct.Register(request.Abort)) {
                try {
                    // Store response data in a seperate stream and parse content
                    using (var content = await request.PostUrlencodedAsync(responseArgs)) {
                        xml = await content.ReadXmlAsync(ct);
                    }
                } catch (WebException e) {
                    if (e.Status == WebExceptionStatus.RequestCanceled)
                    {
                        ct.ThrowIfCancellationRequested();
                    }

                    throw;
                }
            }

            var sid = new SessionId(xml.DocumentElement[FIELD_NAME_SID].InnerText);

            if (!sid.IsValid)
            {
                throw new LoginFailedException();
            }

            Id = sid;
            LastActionTime.Update();
        }