Пример #1
0
        private static async Task <ResponseEnvelope> PerformRemoteProcedureCall <TRequest>(this System.Net.Http.HttpClient client,
                                                                                           string url,
                                                                                           RequestEnvelope requestEnvelope, int tries = 0) where TRequest : IMessage <TRequest>
        {
            //Encode payload and put in envelope, then send
            var data   = requestEnvelope.ToByteString();
            var result = await client.PostAsync(url, new ByteArrayContent(data.ToByteArray())).ConfigureAwait(false);

            //Decode message
            var responseData = await result.Content.ReadAsByteArrayAsync().ConfigureAwait(false);

            var codedStream     = new CodedInputStream(responseData);
            var decodedResponse = new ResponseEnvelope();

            decodedResponse.MergeFrom(codedStream);
            Logger.Debug("requestEnvelope: " + strRequestEnvelope(requestEnvelope));
            Logger.Debug("decodedResponse: " + strResponseEnvelope(decodedResponse));

            if (tries < 8)
            {
                if (decodedResponse.StatusCode == ResponseEnvelope.Types.StatusCode.InvalidAuthToken)
                {
                    RandomHelper.RandomSleep(600);
                    return(PerformRemoteProcedureCall <TRequest>(client, url, requestEnvelope, ++tries).Result);
                }
                if (decodedResponse.StatusCode == ResponseEnvelope.Types.StatusCode.Redirect && requestEnvelope.Requests.Count == 1)
                {
                    RandomHelper.RandomSleep(600);
                    return(PerformRemoteProcedureCall <TRequest>(client, url, requestEnvelope, ++tries).Result);
                }
            }

            return(decodedResponse);
        }
        /// <summary>
        /// Called when <see cref="RestSharp"/> recieves a response envelope async.
        /// </summary>
        /// <param name="envelope">Response envelope recieved.</param>
        public void OnResponse(IRestResponse response)
        {
            ResponseEnvelope resEnv = new ResponseEnvelope();

            //At this point we've got a response
            //Probably a response envelope
            if (response.RawBytes != null && response.RawBytes.Length != 0)
            {
                resEnv.MergeFrom(response.RawBytes);
                decoratedFuture.OnResponse(resEnv);
            }

            //TODO: Handle exceptions
        }
Пример #3
0
        public static async Task <ResponseEnvelope> PostProto(this HttpClient client, string url, IMessage request)
        {
            //Encode payload and put in envelop, then send
            var data   = request.ToByteString();
            var result = await client.PostAsync(url, new ByteArrayContent(data.ToByteArray()));

            //Decode message
            var responseData = await result.Content.ReadAsByteArrayAsync();

            var codedStream     = new CodedInputStream(responseData);
            var decodedResponse = new ResponseEnvelope();

            decodedResponse.MergeFrom(codedStream);

            return(decodedResponse);
        }
Пример #4
0
        public async Task <ResponseEnvelope> PostProto <TRequest>(string url,
                                                                  RequestEnvelope requestEnvelope) where TRequest : IMessage <TRequest>
        {
            //Encode payload and put in envelop, then send
            var data   = requestEnvelope.ToByteString();
            var result = await PostAsync(url, new ByteArrayContent(data.ToByteArray()));

            //Decode message
            var responseData = await result.Content.ReadAsByteArrayAsync();

            var codedStream     = new CodedInputStream(responseData);
            var decodedResponse = new ResponseEnvelope();

            decodedResponse.MergeFrom(codedStream);

            return(decodedResponse);
        }
        private static async Task <ResponseEnvelope> PerformRemoteProcedureCall <TRequest>(this System.Net.Http.HttpClient client,
                                                                                           string url,
                                                                                           RequestEnvelope requestEnvelope) where TRequest : IMessage <TRequest>
        {
            //Encode payload and put in envelop, then send
            var data   = requestEnvelope.ToByteString();
            var result = await client.PostAsync(url, new ByteArrayContent(data.ToByteArray()));

            //Decode message
            var responseData = await result.Content.ReadAsByteArrayAsync();

            var codedStream     = new CodedInputStream(responseData);
            var decodedResponse = new ResponseEnvelope();

            decodedResponse.MergeFrom(codedStream);

            return(decodedResponse);
        }
        public static async Task <ResponseEnvelope> PostProto <TRequest>(this System.Net.Http.HttpClient client, string url,
                                                                         RequestEnvelope requestEnvelope) where TRequest : IMessage <TRequest>
        {
            //Encode payload and put in envelop, then send
            var data   = requestEnvelope.ToByteString();
            var result = await client.PostAsync(url, new ByteArrayContent(data.ToByteArray()));

            if (result.StatusCode == System.Net.HttpStatusCode.Forbidden)
            {
                throw new IPBannedException("IP Address is banned");
            }

            //Decode message
            var responseData = await result.Content.ReadAsByteArrayAsync();

            var codedStream     = new CodedInputStream(responseData);
            var decodedResponse = new ResponseEnvelope();

            decodedResponse.MergeFrom(codedStream);

            return(decodedResponse);
        }
Пример #7
0
        public static async Task <ResponseEnvelope> PostProto <TRequest>(this System.Net.Http.HttpClient client, string url,
                                                                         RequestEnvelope requestEnvelope) where TRequest : IMessage <TRequest>
        {
            HttpResponseMessage result = null;

            for (int i = 0; i < 3; i++)
            {
                try
                {
                    //Encode payload and put in envelop, then send
                    if (requestEnvelope == null)
                    {
                        return(new ResponseEnvelope());
                    }
                    var data = requestEnvelope.ToByteString();
                    result = await client.PostAsync(url, new ByteArrayContent(data.ToByteArray()));

                    break;
                }
                catch
                {
                    // ignored
                }
            }

            if (result != null)
            {
                //Decode message
                var responseData = await result.Content.ReadAsByteArrayAsync();

                var codedStream     = new CodedInputStream(responseData);
                var decodedResponse = new ResponseEnvelope();
                decodedResponse.MergeFrom(codedStream);

                return(decodedResponse);
            }
            return(new ResponseEnvelope());
        }
Пример #8
0
        public async Task <ResponseEnvelope> PostProto <TRequest>(string url, RequestEnvelope requestEnvelope)
            where TRequest : IMessage <TRequest>
        {
            // robertmclaws: Let's be pro-active about token failures, instead of reactive.
            if (AccessToken == null || AccessToken.IsExpired)
            {
                await Login.DoLogin();
            }

            //Encode payload and put in envelop, then send
            var data   = requestEnvelope.ToByteString();
            var result = await PostAsync(url, new ByteArrayContent(data.ToByteArray()));

            //Decode message
            var responseData = await result.Content.ReadAsByteArrayAsync();

            var codedStream     = new CodedInputStream(responseData);
            var decodedResponse = new ResponseEnvelope();

            decodedResponse.MergeFrom(codedStream);

            return(decodedResponse);
        }
        private static async Task <ResponseEnvelope> PerformRemoteProcedureCall <TRequest>(this System.Net.Http.HttpClient client,
                                                                                           Client apiClient,
                                                                                           RequestEnvelope requestEnvelope) where TRequest : IMessage <TRequest>
        {
            // Check killswitch from url before making API calls.
            if (!apiClient.Settings.UseLegacyAPI)
            {
                if (apiClient.CheckCurrentVersionOutdated())
                {
                    throw new MinimumClientVersionException(apiClient.CurrentApiEmulationVersion, apiClient.MinimumClientVersion);
                }
            }

            //Encode payload and put in envelop, then send
            var data   = requestEnvelope.ToByteString();
            var result = await client.PostAsync(apiClient.ApiUrl, new ByteArrayContent(data.ToByteArray())).ConfigureAwait(false);

            //Decode message
            var responseData = await result.Content.ReadAsByteArrayAsync().ConfigureAwait(false);

            var codedStream = new CodedInputStream(responseData);
            ResponseEnvelope serverResponse = new ResponseEnvelope();

            serverResponse.MergeFrom(codedStream);

            // Process Platform8Response
            CommonRequest.ProcessPlatform8Response(apiClient, serverResponse);

            if (!string.IsNullOrEmpty(serverResponse.ApiUrl))
            {
                apiClient.ApiUrl = "https://" + serverResponse.ApiUrl + "/rpc";
            }

            if (serverResponse.AuthTicket != null)
            {
                if (serverResponse.AuthTicket.ExpireTimestampMs > (ulong)Utils.GetTime(true))
                {
                    apiClient.AuthTicket = serverResponse.AuthTicket;
                }
                else
                {
                    // Expired auth ticket.
                    apiClient.AuthTicket = null;
                }
            }

            switch (serverResponse.StatusCode)
            {
            case ResponseEnvelope.Types.StatusCode.InvalidAuthToken:
                await apiClient.RequestBuilder.RegenerateRequestEnvelopeWithNewAccessToken(requestEnvelope).ConfigureAwait(false);

                return(await PerformRemoteProcedureCall <TRequest>(client, apiClient, requestEnvelope).ConfigureAwait(false));

            case ResponseEnvelope.Types.StatusCode.Redirect:
                // 53 means that the api_endpoint was not correctly set, should be at this point, though, so redo the request
                return(await PerformRemoteProcedureCall <TRequest>(client, apiClient, requestEnvelope).ConfigureAwait(false));

            case ResponseEnvelope.Types.StatusCode.BadRequest:
                // Your account may be banned! please try from the official client.
                throw new APIBadRequestException("BAD REQUEST \r\n" + JsonConvert.SerializeObject(requestEnvelope));

            case ResponseEnvelope.Types.StatusCode.Unknown:
                break;

            case ResponseEnvelope.Types.StatusCode.Ok:
                break;

            case ResponseEnvelope.Types.StatusCode.OkRpcUrlInResponse:
                break;

            case ResponseEnvelope.Types.StatusCode.InvalidRequest:
                break;

            case ResponseEnvelope.Types.StatusCode.InvalidPlatformRequest:
                break;

            case ResponseEnvelope.Types.StatusCode.SessionInvalidated:
                throw new SessionInvalidatedException("SESSION INVALIDATED EXCEPTION");

            default:
                throw new ArgumentOutOfRangeException();
            }
            return(serverResponse);
        }
Пример #10
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="url"></param>
        /// <param name="payload"></param>
        /// <param name="retryPolicy"></param>
        /// <param name="token"></param>
        /// <param name="attemptCount"></param>
        /// <param name="redirectCount"></param>
        /// <returns></returns>
        internal async Task <ResponseEnvelope> PostProto(string url, ByteArrayContent payload, RetryPolicy retryPolicy, CancellationToken token,
                                                         int attemptCount = 0, int redirectCount = 0)
        {
            // robertmclaws: If someone wants us to be done, we're done.
            if (token.IsCancellationRequested)
            {
                Logger.Write("The request was cancelled. (PostProto cancellation check)");
                return(null);
            }

            attemptCount++;

            // robertmclaws: If we've exceeded the maximum number of attempts, we're done.
            if (attemptCount > retryPolicy.MaxFailureAttempts)
            {
                Logger.Write("The request exceeded the number of retries allowed and has been cancelled.");
                return(null);
            }
            if (redirectCount > retryPolicy.MaxRedirectAttempts)
            {
                Logger.Write("The request exceeded the number of redirect attempts allowed and has been cancelled.");
                return(null);
            }

            // robertmclaws: We're gonna keep going, so let's be pro-active about token failures, instead of reactive.
            if (AuthenticatedUser == null || AuthenticatedUser.IsExpired)
            {
                // @robertmclaws: Calling "Authenticate" cancels all current requests and fires off a complex login routine.
                //                More than likely, we just want to refresh the tokens.
                await CurrentProvider.GetAuthenticatedUser().ConfigureAwait(false);
            }

            var result = await PostAsync(url, payload, token);

            var response     = new ResponseEnvelope();
            var responseData = await result.Content.ReadAsByteArrayAsync();

            using (var codedStream = new CodedInputStream(responseData))
            {
                response.MergeFrom(codedStream);
            }

            switch ((StatusCodes)response.StatusCode)
            {
            case StatusCodes.ValidResponse:
                if (response.AuthTicket != null)
                {
                    Logger.Write("Received a new AuthTicket from the Api!");
                    AuthenticatedUser.AuthTicket = response.AuthTicket;
                    // robertmclaws to do: See if we need to clone the AccessToken so we don't have a threading violation.
                    RaiseAuthenticatedUserUpdated(AuthenticatedUser);
                }
                return(response);

            case StatusCodes.AccessDenied:
                Logger.Write("Account has been banned. Our condolences for your loss.");
                CancelCurrentRequests();
                //RequestQueue.CompleteAdding();
                // robertmclaws to do: Allow you to stop adding events to the queue, and re-initialize the queue if needed.
                throw new AccountLockedException();

            case StatusCodes.Redirect:
                if (!Regex.IsMatch(response.ApiUrl, "pgorelease\\.nianticlabs\\.com\\/plfe\\/\\d+"))
                {
                    throw new Exception($"Received an incorrect API url '{response.ApiUrl}', status code was '{response.StatusCode}'.");
                }
                ApiUrl = $"https://{response.ApiUrl}/rpc";
                Logger.Write($"Received an updated API url = {ApiUrl}");
                // robertmclaws to do: Check to see if redirects should count against the RetryPolicy.
                await Task.Delay(retryPolicy.DelayInSeconds * 1000);

                redirectCount++;
                return(await PostProto(response.ApiUrl, payload, retryPolicy, token, attemptCount, redirectCount));

            case StatusCodes.InvalidToken:
                Logger.Write("Received StatusCode 102, reauthenticating.");
                AuthenticatedUser?.Expire();
                // robertmclaws: trigger a retry here. We'll automatically try to log in again on the next request.
                await Task.Delay(retryPolicy.DelayInSeconds * 1000);

                return(await PostProto(response.ApiUrl, payload, retryPolicy, token, attemptCount, redirectCount));

            case StatusCodes.ServerOverloaded:
                // Per @wallycz, on code 52, wait 11 seconds before sending the request again.
                Logger.Write("Server says to slow the hell down. Try again in 11 sec.");
                await Task.Delay(11000);

                return(await PostProto(response.ApiUrl, payload, retryPolicy, token, attemptCount, redirectCount));

            default:
                Logger.Write($"Unknown status code: {response.StatusCode}");
                break;
            }

            return(response);
        }
        private static async Task <ResponseEnvelope> PerformRemoteProcedureCall <TRequest>(this System.Net.Http.HttpClient client,
                                                                                           Client apiClient,
                                                                                           RequestEnvelope requestEnvelope) where TRequest : IMessage <TRequest>
        {
            // Check killswitch from url before making API calls.
            if (!apiClient.Settings.UseLegacyAPI)
            {
                if (apiClient.CheckCurrentVersionOutdated())
                {
                    throw new MinimumClientVersionException(apiClient.CurrentApiEmulationVersion, apiClient.MinimumClientVersion);
                }
            }

            //Encode payload and put in envelop, then send
            var data   = requestEnvelope.ToByteString();
            var result = await client.PostAsync(apiClient.ApiUrl, new ByteArrayContent(data.ToByteArray()));

            //Decode message
            var responseData = await result.Content.ReadAsByteArrayAsync();

            var codedStream = new CodedInputStream(responseData);
            ResponseEnvelope serverResponse = new ResponseEnvelope();

            serverResponse.MergeFrom(codedStream);

            if (!string.IsNullOrEmpty(serverResponse.ApiUrl))
            {
                apiClient.ApiUrl = "https://" + serverResponse.ApiUrl + "/rpc";
            }

            if (serverResponse.AuthTicket != null)
            {
                apiClient.AccessToken.AuthTicket = serverResponse.AuthTicket;
            }

            switch (serverResponse.StatusCode)
            {
            case ResponseEnvelope.Types.StatusCode.InvalidAuthToken:
                apiClient.AccessToken.Expire();
                await Rpc.Login.Reauthenticate(apiClient);

                Rpc.Login.SaveAccessToken(apiClient.AccessToken);
                throw new AccessTokenExpiredException();

            case ResponseEnvelope.Types.StatusCode.Redirect:
                // 53 means that the api_endpoint was not correctly set, should be at this point, though, so redo the request
                return(await PerformRemoteProcedureCall <TRequest>(client, apiClient, requestEnvelope));

            case ResponseEnvelope.Types.StatusCode.BadRequest:
                // Your account may be banned! please try from the official client.
                throw new LoginFailedException("Your account may be banned! please try from the official client.");

            case ResponseEnvelope.Types.StatusCode.Unknown:
                break;

            case ResponseEnvelope.Types.StatusCode.Ok:
                break;

            case ResponseEnvelope.Types.StatusCode.OkRpcUrlInResponse:
                break;

            case ResponseEnvelope.Types.StatusCode.InvalidRequest:
                break;

            case ResponseEnvelope.Types.StatusCode.InvalidPlatformRequest:
                break;

            case ResponseEnvelope.Types.StatusCode.SessionInvalidated:
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
            return(serverResponse);
        }