private void InvokeHelper(AsyncResult asyncResult)
 {
     if (asyncResult.RetriesAttempt == 0 || Config.ResignRetries)
     {
         if (Credentials is CognitoAWSCredentials)
         {
             var cred = Credentials as CognitoAWSCredentials;
             // very hacky solution
             cred.GetCredentialsAsync(delegate(AmazonServiceResult voidResult)
             {
                 if (voidResult.Exception != null)
                 {
                     asyncResult.IsCompleted = true;
                     AmazonLogging.LogError(AmazonLogging.AmazonLoggingLevel.Errors, "CognitoAWSCredentials", voidResult.Exception.Message);
                     asyncResult.HandleException(voidResult.Exception);
                     return;
                 }
                 ProcessHttpRequest(asyncResult);
             }, null);
             return;
         }
     }
     ProcessHttpRequest(asyncResult);
     return;
 }
Ejemplo n.º 2
0
        protected void GenerateNewCredentialsAsync(AmazonServiceCallback callback)
        {
            AmazonServiceResult voidResult = new AmazonServiceResult(null, null);

            IdentityProvider.RefreshAsync(delegate(AmazonServiceResult refreshResult)
            {
                if (refreshResult.Exception != null)
                {
                    voidResult.Exception = refreshResult.Exception;
                    AmazonMainThreadDispatcher.ExecCallback(callback, voidResult);
                    return;
                }


                // Pick role to use, depending on Logins
                string roleArn = UnAuthRoleArn;
                if (IdentityProvider.Logins.Count > 0)
                {
                    roleArn = AuthRoleArn;
                }
                if (string.IsNullOrEmpty(roleArn))
                {
                    voidResult.Exception = new AmazonServiceException(
                        new InvalidOperationException(string.Format(CultureInfo.InvariantCulture,
                                                                    "Unable to determine Role ARN. AuthRoleArn = [{0}], UnAuthRoleArn = [{1}], Logins.Count = {2}",
                                                                    AuthRoleArn, UnAuthRoleArn, IdentityProvider.Logins.Count)));
                    AmazonMainThreadDispatcher.ExecCallback(callback, voidResult);
                    return;
                }

                // Assume role with Open Id Token
                var assumeRequest = new AssumeRoleWithWebIdentityRequest
                {
                    WebIdentityToken = IdentityProvider.GetCurrentOpenIdToken(),
                    RoleArn          = roleArn,
                    RoleSessionName  = "UnityProviderSession",
                    DurationSeconds  = DefaultDurationSeconds
                };

                sts.AssumeRoleWithWebIdentityAsync(assumeRequest, delegate(AmazonServiceResult result)
                {
                    if (result.Exception != null)
                    {
                        voidResult.Exception = result.Exception;
                        AmazonLogging.LogError(AmazonLogging.AmazonLoggingLevel.Errors, "STS", result.Exception.Message);
                        AmazonMainThreadDispatcher.ExecCallback(callback, voidResult);
                        return;
                    }
                    AssumeRoleWithWebIdentityResponse assumeRoleWithWebIdentityResponse = result.Response as AssumeRoleWithWebIdentityResponse;
                    this._currentState = new CredentialsRefreshState
                    {
                        Credentials = assumeRoleWithWebIdentityResponse.Credentials.GetCredentials(),
                        Expiration  = assumeRoleWithWebIdentityResponse.Credentials.Expiration
                    };
                    // success - FinalResponse
                    AmazonMainThreadDispatcher.ExecCallback(callback, voidResult);
                    return;
                }, null);
            }, null);
        }
Ejemplo n.º 3
0
        // fetching/persisting new credentials in LocalStorage
        public override void GetCredentialsAsync(AmazonServiceCallback callback, object state)
        //internal IEnumerator GetCredentialsCoroutine(VoidResponse voidResponse)
        {
            //lock (this._refreshLock)
            //{

            //
            if (_currentState == null)
            {
                loadCachedCredentials();
            }
            // If credentials are expired, update
            if (ShouldUpdate)
            {
                GenerateNewCredentialsAsync(delegate(AmazonServiceResult voidResult)
                {
                    if (voidResult.Exception != null)
                    {
                        AmazonLogging.LogError(AmazonLogging.AmazonLoggingLevel.Errors, "Cognito", "Error occured during GetCredentialsAsync");
                        AmazonMainThreadDispatcher.ExecCallback(callback, new AmazonServiceResult(null, null, voidResult.Exception, state));
                        return;
                    }
                    // Check if the new credentials are already expired
                    if (ShouldUpdate)
                    {
                        voidResult.Exception = new AmazonServiceException("The retrieved credentials have already expired");
                        AmazonMainThreadDispatcher.ExecCallback(callback, new AmazonServiceResult(null, null, voidResult.Exception, state));
                        return;
                    }

                    // Offset the Expiration by PreemptExpiryTime
                    _currentState.Expiration -= PreemptExpiryTime;

                    if (ShouldUpdate)
                    {
                        // This could happen if the default value of PreemptExpiryTime is
                        // overriden and set too high such that ShouldUpdate returns true.

                        voidResult.Exception = new AmazonClientException(String.Format(
                                                                             "The preempt expiry time is set too high: Current time = {0}, Credentials expiry time = {1}, Preempt expiry time = {2}.",
                                                                             DateTime.Now, _currentState.Expiration, PreemptExpiryTime));
                        AmazonMainThreadDispatcher.ExecCallback(callback, new AmazonServiceResult(null, null, voidResult.Exception, state));
                        return;
                    }
                    saveCredentials();
                    AmazonMainThreadDispatcher.ExecCallback(callback, new AmazonServiceResult(null, null, null, state));
                });
                return;
            }
            AmazonMainThreadDispatcher.ExecCallback(callback, new AmazonServiceResult(null, null, null, state));


            //}
        }
        public override void Put(string key, string value)
        {
            lock (SQLiteDatabase.SQLiteLock)
            {
                string          query = "SELECT count(*) as count FROM " + TABLE_RECORDS + " where " + COLUMN_KEY + " = ?";
                SQLiteStatement stmt  = null;
                try
                {
                    stmt = db.Prepare(query);
                    stmt.BindText(1, key);
                    if (stmt.Read())
                    {
                        long count = stmt.Fields["count"].INTEGER;
                        stmt.FinalizeStm();

                        if (count == 0)
                        {
                            // insert record
                            query = "INSERT INTO " + TABLE_RECORDS + " (" + COLUMN_KEY + ", " + COLUMN_VALUE + ") VALUES(?,?)";
                            stmt  = db.Prepare(query);
                            stmt.BindText(1, key);
                            stmt.BindText(2, value);
                            stmt.Step();
                            return;
                        }
                        else
                        {
                            // update record
                            query = "UPDATE " + TABLE_RECORDS + " SET " + COLUMN_VALUE + " = ? where " + COLUMN_KEY + " = ?";
                            stmt  = db.Prepare(query);
                            stmt.BindText(2, key);
                            stmt.BindText(1, value);
                            stmt.Step();
                            return;
                        }
                    }
                    else
                    {
                        AmazonLogging.LogError(AmazonLogging.AmazonLoggingLevel.Errors, "SQLiteKVStore", "Save failed");
                        throw new Exception("Save failed");
                    }
                }
                finally
                {
                    if (stmt != null)
                    {
                        stmt.FinalizeStm();
                    }
                }
            }
        }
        private void ProcessS3PostResponse(object state)
        {
            AsyncResult asyncResult = null;

            try
            {
                asyncResult = state as AsyncResult;
                asyncResult.ServiceResult.HttpResponseData = asyncResult.ResponseData;

                S3PostUploadResponse response = new S3PostUploadResponse();

                WWWResponseData responseData = asyncResult.ResponseData;

                if (!String.IsNullOrEmpty(responseData.Error) || !String.IsNullOrEmpty(System.Text.Encoding.UTF8.GetString(responseData.GetBytes())))
                {
                    AmazonLogging.LogError(AmazonLogging.AmazonLoggingLevel.Critical, "S3", responseData.Error);
                    foreach (string key in responseData.GetHeaderNames())
                    {
                        AmazonLogging.Log(AmazonLogging.AmazonLoggingLevel.Verbose, "S3", key + " : " + responseData.GetHeaderValue(key));
                    }

                    if (asyncResult.Exception == null)
                    {
                        asyncResult.Exception = new AmazonServiceException("Bad Request");
                    }

                    asyncResult.IsCompleted            = true;
                    response.StatusCode                = HttpStatusCode.BadRequest;
                    asyncResult.ServiceResult.Response = response;
                    AmazonLogging.LogError(AmazonLogging.AmazonLoggingLevel.Warnings, "S3", "RetriesAttempt exceeded");
                    asyncResult.HandleException(asyncResult.Exception);

                    return;
                }
                else
                {
                    asyncResult.IsCompleted            = true;
                    response.StatusCode                = HttpStatusCode.NoContent;
                    asyncResult.ServiceResult.Response = response;
                    asyncResult.InvokeCallback();
                    return;
                }
            }
            catch (Exception e)
            {
                Debug.LogException(e);
                asyncResult.HandleException(e);
                return;
            }
        }
Ejemplo n.º 6
0
        public override void PutValue(string identityId, string datasetName, string key, string value)
        {
            lock (SQLiteDatabase.SQLiteLock)
            {
                bool result = this.PutValueInternal(identityId, datasetName, key, value);

                if (!result)
                {
                    AmazonLogging.LogError(AmazonLogging.AmazonLoggingLevel.Errors, "SQLite", "PutValue failed");
                }
                else
                {
                    this.UpdateLastModifiedTimestamp(identityId, datasetName);
                }
            }
        }
        private void InvokeHelperForS3PostObject(AsyncResult asyncResult, PostObjectRequest request)
        {
            if (asyncResult.RetriesAttempt == 0 || Config.ResignRetries)
            {
                // Add Post policy
                if (request.PostPolicy == null)
                {
                    int    position = request.Key.LastIndexOf('.');
                    string ext = null, contentType = null;
                    if (position != -1)
                    {
                        ext         = request.Key.Substring(position, request.Key.Length - position);
                        contentType = AmazonS3Util.MimeTypeFromExtension(ext);
                    }
                    else
                    {
                        contentType = "application/octet-stream";
                    }
                    request.PostPolicy = S3PostPolicyBuilder.GetPostPolicy(request.Bucket, request.Key, contentType);
                }



                if (Credentials is CognitoAWSCredentials)
                {
                    var cred = Credentials as CognitoAWSCredentials;
                    // very hacky solution
                    cred.GetCredentialsAsync(delegate(AmazonServiceResult voidResult)
                    {
                        if (voidResult.Exception != null)
                        {
                            asyncResult.IsCompleted = true;
                            AmazonLogging.LogError(AmazonLogging.AmazonLoggingLevel.Errors, "CognitoAWSCredentials", voidResult.Exception.Message);
                            asyncResult.HandleException(voidResult.Exception);
                            return;
                        }
                        request.SignedPolicy = S3PostUploadSignedPolicy.GetSignedPolicy(request.PostPolicy, cred);
                        ProcessS3PostRequest(asyncResult, request);
                    }, null);
                    return;
                }
                request.SignedPolicy = S3PostUploadSignedPolicy.GetSignedPolicy(request.PostPolicy, Credentials);
            }

            ProcessS3PostRequest(asyncResult, request);
        }
 public static void LoadEndpointDefinitions()
 {
     try
     {
         TextAsset awsEndpoints = UnityEngine.Resources.Load("aws_endpoints_json") as TextAsset;
         using (Stream stream = new MemoryStream(awsEndpoints.bytes))
         {
             using (StreamReader reader = new StreamReader(stream))
             {
                 LoadEndpointDefinitions(reader);
             }
         }
     }
     catch (System.Exception exception)
     {
         AmazonLogging.LogError(AmazonLogging.AmazonLoggingLevel.ErrorsAsExceptions, "LoadEndpointDefinitions",
                                "cannot load service endpoint file : " + exception.Message);
     }
 }
        protected void Invoke <T, R>(R request, AmazonServiceCallback callback, object state, IMarshaller <T, R> marshaller, ResponseUnmarshaller unmarshaller, AbstractAWSSigner signer)
            where T : IRequest
            where R : AmazonWebServiceRequest
        {
            AsyncResult result = null;

            try
            {
                ProcessPreRequestHandlers(request);

                IRequest irequest = marshaller.Marshall(request);
                result = new AsyncResult(irequest, request, callback, state, signer, unmarshaller);
                Invoke(result);
            }
            catch (Exception e)
            {
                AmazonLogging.LogError(AmazonLogging.AmazonLoggingLevel.Errors, "Runtime", e.Message);
                result.HandleException(e);
                result.IsCompleted = true;
            }
            //return result;
        }
Ejemplo n.º 10
0
        public void SynchronizeInternalAsync()
        {
            try
            {
                List <string> mergedDatasets = GetLocalMergedDatasets();
                if (mergedDatasets.Count != 0)
                {
                    this.OnDatasetMerged(this, mergedDatasets);
                }

                this.RunSyncOperationAsync(MAX_RETRY, delegate(RunSyncOperationResponse response)
                {
                    if (response == null || response.Exception != null)
                    {
                        FireSyncFailureEvent(new DataStorageException("Unknown exception", response.Exception));
                    }
                });
            }
            catch (Exception e)
            {
                FireSyncFailureEvent(new DataStorageException("Unknown exception", e));
                AmazonLogging.LogError(AmazonLogging.AmazonLoggingLevel.Errors, "CognitoSyncManager", "failed to synchronize " + e.Message);
            }
        }
Ejemplo n.º 11
0
 /// <summary>
 /// Logs the GameCircle error.
 /// </summary>
 /// <param name='errorMessage'>
 /// Error message.
 /// </param>
 public static void LogGameCircleError(string errorMessage)
 {
     AmazonLogging.LogError(errorLevel, serviceName, errorMessage);
 }
        private void ProcessS3PostRequest(AsyncResult asyncResult, PostObjectRequest request)
        {
            try
            {
                WWWRequestData requestData = new WWWRequestData();
                string         subdomain   = request.Region.Equals(RegionEndpoint.USEast1) ? "s3" : "s3-" + request.Region.SystemName;

                if (request.Bucket.IndexOf('.') > -1)
                {
                    requestData.Url = string.Format(CultureInfo.InvariantCulture, "http://{0}.amazonaws.com/{1}/", subdomain, request.Bucket);
                }
                else
                {
                    requestData.Url = string.Format(CultureInfo.InvariantCulture, "http://{0}.{1}.amazonaws.com", request.Bucket, subdomain);
                }


                // prepare WWW
                var boundary = Convert.ToBase64String(Guid.NewGuid().ToByteArray()).Replace('=', 'z');
                requestData.Headers.Add(HeaderKeys.ContentTypeHeader, string.Format(CultureInfo.InvariantCulture, "multipart/form-data; boundary={0}", boundary));
#if !UNITY_WEBPLAYER
                requestData.Headers.Add(HeaderKeys.UserAgentHeader, UNITY_USER_AGENT);
#endif

                // append upload data

                using (var reqStream = new MemoryStream())
                {
                    request.WriteFormData(boundary, reqStream);

                    byte[] boundaryBytes = Encoding.UTF8.GetBytes(string.Format(CultureInfo.InvariantCulture, "--{0}\r\nContent-Disposition: form-data; name=\"file\"\r\n\r\n", boundary));

                    reqStream.Write(boundaryBytes, 0, boundaryBytes.Length);

                    using (var inputStream = null == request.Path ? request.InputStream : File.OpenRead(request.Path))
                    {
                        byte[] buf = new byte[1024];
                        int    bytesRead;
                        while ((bytesRead = inputStream.Read(buf, 0, 1024)) > 0)
                        {
                            reqStream.Write(buf, 0, bytesRead);
                        }
                    }

                    byte[] endBoundaryBytes = Encoding.UTF8.GetBytes(string.Format(CultureInfo.InvariantCulture, "\r\n--{0}--", boundary));

                    reqStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);
                    AmazonLogging.Log(AmazonLogging.AmazonLoggingLevel.Verbose, "S3", requestData.Url);

                    requestData.Data = reqStream.ToArray();
                }
                AmazonLogging.Log(AmazonLogging.AmazonLoggingLevel.Verbose, "S3", Encoding.Default.GetString(requestData.Data));

                asyncResult.RequestData  = requestData;
                asyncResult.WaitCallback = ProcessS3PostResponse;

                // switching to main thread
                AmazonMainThreadDispatcher.QueueAWSRequest(asyncResult);
            }
            catch (Exception e)
            {
                AmazonLogging.LogError(AmazonLogging.AmazonLoggingLevel.Errors, "S3", e.Message);
                asyncResult.IsCompleted = true;
                asyncResult.HandleException(e);
                return;
            }
        }
Ejemplo n.º 13
0
        private void RunSyncOperationAsync(int retry, Action <RunSyncOperationResponse> callback)
        {
            if (retry < 0)
            {
                callback(new RunSyncOperationResponse(false, null));
                return;
            }

            long lastSyncCount = _local.GetLastSyncCount(GetIdentityId(), _datasetName);

            // if dataset is deleted locally, push it to remote
            if (lastSyncCount == -1)
            {
#if DELETE_METHOD_SUPPORT
                _remote.DeleteDatasetAsync(_datasetName, delegate(AmazonCognitoResult result)
                {
                    if (result.Exception != null)
                    {
                        var e = result.Exception as DataStorageException;
                        AmazonLogging.LogError(AmazonLogging.AmazonLoggingLevel.Errors, "CognitoSyncManager", "OnSyncFailure" + e.Message);
                        this.FireSyncFailureEvent(e);
                        callback(new RunSyncOperationResponse(false, null));
                        return;
                    }

                    _local.PurgeDataset(GetIdentityId(), _datasetName);
                    AmazonLogging.Log(AmazonLogging.AmazonLoggingLevel.Verbose, "CognitoSyncManager", "OnSyncSuccess: dataset delete is pushed to remote");
                    this.FireSyncSuccessEvent(new List <Record>());
                    callback(new RunSyncOperationResponse(true, null));
                    return;
                }, null);
#endif
                // invalid scenario
                AmazonLogging.LogError(AmazonLogging.AmazonLoggingLevel.Critical, "CognitoSyncManager", "OnSyncFailure: DeleteDataset is an invalid operation");
                FireSyncFailureEvent(new DataStorageException("DeleteDataset is an invalid operation"));
                callback(new RunSyncOperationResponse(false, null));
                return;
            }

            // get latest modified records from remote
            AmazonLogging.Log(AmazonLogging.AmazonLoggingLevel.Verbose, "CognitoSyncManager", "get latest modified records since " + lastSyncCount);

            _remote.ListUpdatesAsync(_datasetName, lastSyncCount, delegate(AmazonCognitoResult listUpdatesResult)
            {
                RemoteDataStorage.DatasetUpdates datasetUpdates = null;
                if (listUpdatesResult == null || listUpdatesResult.Exception != null)
                {
                    var e = listUpdatesResult.Exception as DataStorageException;
                    AmazonLogging.LogException(AmazonLogging.AmazonLoggingLevel.Verbose, "CognitoSyncManager", e);
                    FireSyncFailureEvent(e);
                    callback(new RunSyncOperationResponse(false, listUpdatesResult.Exception));
                    return;
                }

                ListUpdatesResponse listUpdatesResponse = listUpdatesResult.Response as ListUpdatesResponse;
                datasetUpdates = listUpdatesResponse.DatasetUpdates;


                if (datasetUpdates.MergedDatasetNameList.Count != 0 && this.OnDatasetMerged != null)
                {
                    bool resume = this.OnDatasetMerged(this, datasetUpdates.MergedDatasetNameList);
                    if (resume)
                    {
                        this.RunSyncOperationAsync(--retry, callback);
                        return;
                    }
                    else
                    {
                        AmazonLogging.Log(AmazonLogging.AmazonLoggingLevel.Verbose, "CognitoSyncManager", "OnSyncFailure: Manual cancel");
                        FireSyncFailureEvent(new DataStorageException("Manual cancel"));
                        callback(new RunSyncOperationResponse(false, null));
                        return;
                    }
                }


                // if the dataset doesn't exist or is deleted, trigger onDelete
                if (lastSyncCount != 0 && !datasetUpdates.Exists ||
                    datasetUpdates.Deleted && this.OnDatasetDeleted != null)
                {
                    bool resume = this.OnDatasetDeleted(this);
                    if (resume)
                    {
                        // remove both records and metadata
                        _local.DeleteDataset(GetIdentityId(), _datasetName);
                        _local.PurgeDataset(GetIdentityId(), _datasetName);
                        AmazonLogging.Log(AmazonLogging.AmazonLoggingLevel.Verbose, "CognitoSyncManager", "OnSyncSuccess");
                        FireSyncSuccessEvent(new List <Record>());
                        callback(new RunSyncOperationResponse(true, null));
                        return;
                    }
                    else
                    {
                        AmazonLogging.Log(AmazonLogging.AmazonLoggingLevel.Verbose, "CognitoSyncManager", "OnSyncFailure");
                        FireSyncFailureEvent(new DataStorageException("Manual cancel"));
                        callback(new RunSyncOperationResponse(false, null));
                        return;
                    }
                }


                List <Record> remoteRecords = datasetUpdates.Records;
                if (remoteRecords.Count != 0)
                {
                    // if conflict, prompt developer/user with callback
                    List <SyncConflict> conflicts = new List <SyncConflict>();
                    List <Record> conflictRecords = new List <Record>();
                    foreach (Record remoteRecord in remoteRecords)
                    {
                        Record localRecord = _local.GetRecord(GetIdentityId(),
                                                              _datasetName,
                                                              remoteRecord.Key);
                        // only when local is changed and its value is different
                        if (localRecord != null && localRecord.Modified &&
                            !StringUtils.Equals(localRecord.Value, remoteRecord.Value))
                        {
                            conflicts.Add(new SyncConflict(remoteRecord, localRecord));
                            conflictRecords.Add(remoteRecord);
                        }
                    }
                    // retaining only non-conflict records
                    remoteRecords.RemoveAll(t => conflictRecords.Contains(t));

                    if (conflicts.Count > 0)
                    {
                        AmazonLogging.Log(AmazonLogging.AmazonLoggingLevel.Verbose, "CognitoSyncManager", String.Format("{0} records in conflict!", conflicts.Count));

                        bool syncConflictResult = false;
                        if (this.OnSyncConflict == null)
                        {
                            // delegate is not implemented so the conflict resolution is applied
                            syncConflictResult = this.DefaultConflictResolution(conflicts);
                        }
                        else
                        {
                            syncConflictResult = this.OnSyncConflict(this, conflicts);
                        }
                        if (!syncConflictResult)
                        {
                            AmazonLogging.Log(AmazonLogging.AmazonLoggingLevel.Verbose, "CognitoSyncManager", "User cancelled conflict resolution");
                            callback(new RunSyncOperationResponse(false, null));
                            return;
                        }
                    }

                    // save to local
                    if (remoteRecords.Count > 0)
                    {
                        AmazonLogging.Log(AmazonLogging.AmazonLoggingLevel.Verbose, "CognitoSyncManager", String.Format("save {0} records to local", remoteRecords.Count));
                        _local.PutRecords(GetIdentityId(), _datasetName, remoteRecords);
                    }


                    // new last sync count
                    AmazonLogging.Log(AmazonLogging.AmazonLoggingLevel.Verbose, "CognitoSyncManager", String.Format("updated sync count {0}", datasetUpdates.SyncCount));
                    _local.UpdateLastSyncCount(GetIdentityId(), _datasetName,
                                               datasetUpdates.SyncCount);
                }


                // push changes to remote
                List <Record> localChanges = this.GetModifiedRecords();
                if (localChanges.Count != 0)
                {
                    AmazonLogging.Log(AmazonLogging.AmazonLoggingLevel.Verbose, "CognitoSyncManager", String.Format("push {0} records to remote", localChanges.Count));

                    _remote.PutRecordsAsync(_datasetName, localChanges,
                                            datasetUpdates.SyncSessionToken, delegate(AmazonCognitoResult putRecordsResult)
                    {
                        if (putRecordsResult.Exception != null)
                        {
                            if (putRecordsResult.Exception.GetType() == typeof(DataConflictException))
                            {
                                AmazonLogging.LogError(AmazonLogging.AmazonLoggingLevel.Warnings, "CognitoSyncManager", "Conflicts detected when pushing changes to remote: " + putRecordsResult.Exception.Message);
                                this.RunSyncOperationAsync(--retry, callback);
                                return;
                            }
                            else if (putRecordsResult.Exception.GetType() == typeof(DataStorageException))
                            {
                                AmazonLogging.LogError(AmazonLogging.AmazonLoggingLevel.Verbose, "CognitoSyncManager", "OnSyncFailure" + putRecordsResult.Exception.Message);
                                FireSyncFailureEvent(putRecordsResult.Exception);
                                callback(new RunSyncOperationResponse(false, null));
                                return;
                            }
                        }
                        PutRecordsResponse putRecordsResponse = putRecordsResult.Response as PutRecordsResponse;
                        List <Record> result = putRecordsResponse.UpdatedRecords;

                        // update local meta data
                        _local.PutRecords(GetIdentityId(), _datasetName, result);

                        // verify the server sync count is increased exactly by one, aka no
                        // other updates were made during this update.
                        long newSyncCount = 0;
                        foreach (Record record in result)
                        {
                            newSyncCount = newSyncCount < record.SyncCount
                                ? record.SyncCount
                                    : newSyncCount;
                        }
                        if (newSyncCount == lastSyncCount + 1)
                        {
                            AmazonLogging.Log(AmazonLogging.AmazonLoggingLevel.Info, "DefaultDataset",
                                              String.Format("updated sync count %d", newSyncCount));
                            _local.UpdateLastSyncCount(GetIdentityId(), _datasetName,
                                                       newSyncCount);
                        }

                        AmazonLogging.Log(AmazonLogging.AmazonLoggingLevel.Verbose, "CognitoSyncManager", "OnSyncSuccess");
                        // call back
                        FireSyncSuccessEvent(remoteRecords);
                        callback(new RunSyncOperationResponse(true, null));
                        return;
                    }, null);
                    return;
                }


                AmazonLogging.Log(AmazonLogging.AmazonLoggingLevel.Verbose, "CognitoSyncManager", "OnSyncSuccess");
                // call back
                FireSyncSuccessEvent(remoteRecords);
                callback(new RunSyncOperationResponse(true, null));
                return;
            }, null);
        }
        /// <summary>
        /// Invoked as a callback from the AmazonMainThreadDispatcher
        /// Processes the http response
        /// </summary>
        /// <param name="state">State is expected to be AsyncResult</param>
        private void ProcessHttpResponse(object state)
        {
            AsyncResult asyncResult = null;

            try
            {
                asyncResult = state as AsyncResult;
                AmazonWebServiceResponse response = null;
                UnmarshallerContext      context  = null;

                var responseData = asyncResult.ResponseData;

                if (!String.IsNullOrEmpty(responseData.Error))
                {
                    AmazonLogging.LogError(AmazonLogging.AmazonLoggingLevel.Critical,
                                           asyncResult.Request.ServiceName, responseData.Error);

                    if (HandleWWWErrorResponse(asyncResult))
                    {
                        if (++asyncResult.RetriesAttempt >= 3)
                        {
                            if (asyncResult.Exception == null)
                            {
                                asyncResult.Exception = new AmazonServiceException("Maximum retries attempts completed");
                            }
                            // maxretries
                            asyncResult.IsCompleted = true;
                            AmazonLogging.LogException(AmazonLogging.AmazonLoggingLevel.Errors,
                                                       asyncResult.Request.ServiceName, asyncResult.Exception);
                            asyncResult.HandleException(asyncResult.Exception);
                            return;
                        }
                        else
                        {
                            // retry here
                            InvokeHelper(asyncResult);
                            return;
                        }
                    }
                    else
                    {
                        // non-retriable error
                        asyncResult.IsCompleted = true;
                        asyncResult.HandleException(asyncResult.Exception);
                        return;
                    }
                }
                else
                {
                    using (asyncResult.Metrics.StartEvent(Metric.ResponseProcessingTime))
                    {
                        var unmarshaller = asyncResult.Unmarshaller;
                        LogResponse(asyncResult.Metrics, asyncResult.Request, HttpStatusCode.Accepted);

                        context = unmarshaller.CreateContext(responseData,
                                                             this.SupportResponseLogging &&
                                                             (Config.LogResponse || Config.ReadEntireResponse),
                                                             responseData.OpenResponse(),
                                                             asyncResult.Metrics);
                        try
                        {
                            using (asyncResult.Metrics.StartEvent(Metric.ResponseUnmarshallTime))
                            {
                                response = unmarshaller.Unmarshall(context);
                                if (responseData.IsHeaderPresent("STATUS"))
                                {
                                    response.HttpStatusCode = responseData.StatusCode;
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            //unmarshalling exception
                            asyncResult.IsCompleted = true;
                            asyncResult.HandleException(e);
                            return;
                        }
                        context.ValidateCRC32IfAvailable();
                        if (responseData.IsHeaderPresent(HeaderKeys.ContentLengthHeader.ToUpper()))
                        {
                            response.ContentLength = Convert.ToInt32(responseData.GetHeaderValue(HeaderKeys.ContentLengthHeader.ToUpper()));
                        }
                        else
                        {
                            AmazonLogging.Log(AmazonLogging.AmazonLoggingLevel.Warnings, asyncResult.Request.ServiceName, "cannot find CONTENT-LENGTH header");
                        }

                        asyncResult.ServiceResult.Response = response;

                        if (response.ResponseMetadata != null)
                        {
                            asyncResult.Metrics.AddProperty(Metric.AWSRequestID, response.ResponseMetadata.RequestId);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                AmazonLogging.LogException(AmazonLogging.AmazonLoggingLevel.Errors, asyncResult.Request.ServiceName, e);
                asyncResult.HandleException(e);
            }

            asyncResult.IsCompleted = true;
            asyncResult.InvokeCallback();
            return;
        }