private async Task <string> SendAsync(HttpClient client, string data, HttpMethod method, CancellationToken?token = null)
        {
            var responseData = string.Empty;
            var statusCode   = HttpStatusCode.OK;
            var requestData  = data;

            string url;

            try
            {
                url = await BuildUrl(token).ConfigureAwait(false);

                var message = new HttpRequestMessage(method, url)
                {
                    Content = new StringContent(requestData)
                };

                CancellationToken invokeToken;
                if (token == null)
                {
                    invokeToken = new CancellationTokenSource(App.Config.DatabaseRequestTimeout).Token;
                }
                else
                {
                    invokeToken = CancellationTokenSource.CreateLinkedTokenSource(token.Value, new CancellationTokenSource(App.Config.DatabaseRequestTimeout).Token).Token;
                }

                HttpResponseMessage result = null;
                result = await client.SendAsync(message, invokeToken).ConfigureAwait(false);

                statusCode   = result.StatusCode;
                responseData = await result.Content.ReadAsStringAsync().ConfigureAwait(false);

                result.EnsureSuccessStatusCode();

                return(responseData);
            }
            catch (OperationCanceledException ex)
            {
                throw new FirebaseException(FirebaseExceptionReason.OperationCancelled, ex);
            }
            catch (FirebaseException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                throw new FirebaseException(ExceptionHelpers.GetFailureReason(statusCode), ex);
            }
        }
Esempio n. 2
0
        private async void ReceiveThread()
        {
            while (true)
            {
                var url        = string.Empty;
                var line       = string.Empty;
                var statusCode = HttpStatusCode.OK;

                try
                {
                    cancel.Token.ThrowIfCancellationRequested();

                    url = await query.BuildUrl().ConfigureAwait(false);

                    var request = App.Config.HttpStreamFactory.GetStreamHttpRequestMessage(HttpMethod.Get, url);

                    HttpResponseMessage response = null;

                    if (await Task.Run(async delegate
                    {
                        response = await http.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancel.Token).ConfigureAwait(false);
                        return(false);
                    }).WithTimeout(App.Config.DatabaseColdStreamTimeout, true).ConfigureAwait(false))
                    {
                        continue;
                    }

                    var serverEvent = ServerEventType.KeepAlive;

                    statusCode = response.StatusCode;
                    response.EnsureSuccessStatusCode();

                    using (var stream = await response.Content.ReadAsStreamAsync())
                        using (var reader = new NonBlockingStreamReader(stream))
                        {
                            try
                            {
                                reader.Peek(); // ReadlineAsync bug fix (no idea)
                            }
                            catch { }
                            while (true)
                            {
                                cancel.Token.ThrowIfCancellationRequested();

                                line = string.Empty;

                                if (await Task.Run(async delegate
                                {
                                    line = (await reader.ReadLineAsync().ConfigureAwait(false))?.Trim();
                                    return(false);
                                }).WithTimeout(App.Config.DatabaseColdStreamTimeout, true).ConfigureAwait(false))
                                {
                                    break;
                                }

                                if (string.IsNullOrWhiteSpace(line))
                                {
                                    continue;
                                }

                                var tuple = line.Split(new[] { ':' }, 2, StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim()).ToArray();

                                switch (tuple[0].ToLower())
                                {
                                case "event":
                                    serverEvent = ParseServerEvent(serverEvent, tuple[1]);
                                    break;

                                case "data":
                                    ProcessServerData(url, serverEvent, tuple[1]);
                                    break;
                                }

                                if (serverEvent == ServerEventType.AuthRevoked)
                                {
                                    // auth token no longer valid, reconnect
                                    break;
                                }
                            }
                        }
                }
                catch (OperationCanceledException)
                {
                    break;
                }
                catch (Exception ex)
                {
                    var fireEx = new FirebaseException(ExceptionHelpers.GetFailureReason(statusCode), ex);
                    onError?.Invoke(this, fireEx);
                }
                await Task.Delay(App.Config.DatabaseRetryDelay).ConfigureAwait(false);
            }
        }
        /// <inheritdoc/>
        public async Task Put(Func <string> jsonData, CancellationToken?token = null, Action <RetryExceptionEventArgs> onException = null)
        {
            async Task invoke(Func <string> invokeJsonData)
            {
                string url;
                var    responseData = string.Empty;
                var    statusCode   = HttpStatusCode.OK;

                if (App.Config.OfflineMode)
                {
                    throw new FirebaseException(FirebaseExceptionReason.OfflineMode, new Exception("Offline mode"));
                }

                var c = GetClient();

                var currentJsonToInvoke = invokeJsonData();

                if (currentJsonToInvoke == null)
                {
                    try
                    {
                        url = await BuildUrl(token).ConfigureAwait(false);

                        CancellationToken invokeToken;

                        if (token == null)
                        {
                            invokeToken = new CancellationTokenSource(App.Config.DatabaseRequestTimeout).Token;
                        }
                        else
                        {
                            invokeToken = CancellationTokenSource.CreateLinkedTokenSource(token.Value, new CancellationTokenSource(App.Config.DatabaseRequestTimeout).Token).Token;
                        }

                        var result = await c.DeleteAsync(url, invokeToken).ConfigureAwait(false);

                        statusCode   = result.StatusCode;
                        responseData = await result.Content.ReadAsStringAsync().ConfigureAwait(false);

                        result.EnsureSuccessStatusCode();
                    }
                    catch (OperationCanceledException ex)
                    {
                        throw new FirebaseException(FirebaseExceptionReason.OperationCancelled, ex);
                    }
                    catch (FirebaseException ex)
                    {
                        throw ex;
                    }
                    catch (Exception ex)
                    {
                        throw new FirebaseException(ExceptionHelpers.GetFailureReason(statusCode), ex);
                    }
                }
                else
                {
                    await Silent().SendAsync(c, currentJsonToInvoke, HttpMethod.Put, token).ConfigureAwait(false);
                }
            };

            async Task recursive()
            {
                try
                {
                    await invoke(jsonData).ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    var retryEx = new RetryExceptionEventArgs(ex, Task.Run(async delegate
                    {
                        await Task.Delay(App.Config.DatabaseRetryDelay).ConfigureAwait(false);
                        return(false);
                    }));
                    onException?.Invoke(retryEx);
                    if (retryEx.Retry != null)
                    {
                        if (await retryEx.Retry)
                        {
                            await recursive().ConfigureAwait(false);
                        }
                    }
                }
            }

            await recursive().ConfigureAwait(false);
        }
        /// <inheritdoc/>
        public async Task <string> Get(CancellationToken?token = null, Action <RetryExceptionEventArgs> onException = null)
        {
            async Task <string> invoke()
            {
                var url          = string.Empty;
                var responseData = string.Empty;
                var statusCode   = HttpStatusCode.OK;

                if (App.Config.OfflineMode)
                {
                    throw new FirebaseException(FirebaseExceptionReason.OfflineMode, new Exception("Offline mode"));
                }

                try
                {
                    url = await BuildUrl(token).ConfigureAwait(false);

                    CancellationToken invokeToken;

                    if (token == null)
                    {
                        invokeToken = new CancellationTokenSource(App.Config.DatabaseRequestTimeout).Token;
                    }
                    else
                    {
                        invokeToken = CancellationTokenSource.CreateLinkedTokenSource(token.Value, new CancellationTokenSource(App.Config.DatabaseRequestTimeout).Token).Token;
                    }

                    var response = await GetClient().GetAsync(url, invokeToken).ConfigureAwait(false);

                    statusCode   = response.StatusCode;
                    responseData = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

                    response.EnsureSuccessStatusCode();
                    response.Dispose();

                    return(responseData);
                }
                catch (OperationCanceledException ex)
                {
                    throw new FirebaseException(FirebaseExceptionReason.OperationCancelled, ex);
                }
                catch (FirebaseException ex)
                {
                    throw ex;
                }
                catch (Exception ex)
                {
                    throw new FirebaseException(ExceptionHelpers.GetFailureReason(statusCode), ex);
                }
            }

            async Task <string> recursive()
            {
                try
                {
                    return(await invoke().ConfigureAwait(false));
                }
                catch (Exception ex)
                {
                    var retryEx = new RetryExceptionEventArgs(ex, Task.Run(async delegate
                    {
                        await Task.Delay(App.Config.DatabaseRetryDelay).ConfigureAwait(false);
                        return(false);
                    }));
                    onException?.Invoke(retryEx);
                    if (retryEx.Retry != null)
                    {
                        if (await retryEx.Retry)
                        {
                            await recursive().ConfigureAwait(false);
                        }
                    }
                    return(null);
                }
            }

            return(await recursive().ConfigureAwait(false));
        }