protected async Task <XdtsTokenResponse> FetchXdtsToken(string aadToken, string scid, IEnumerable <string> sandboxes) { using (var tokenRequest = new XboxLiveHttpRequest()) { HttpResponseMessage response = (await tokenRequest.SendAsync(() => { var requestMsg = new HttpRequestMessage(HttpMethod.Post, this.AuthContext.XtdsEndpoint); var requestContent = JsonConvert.SerializeObject(new XdtsTokenRequest(scid, sandboxes)); requestMsg.Content = new StringContent(requestContent); // Add the aadToken header without validation as the framework // does not like the values returned for aadTokens for MSA accounts. requestMsg.Headers.TryAddWithoutValidation("Authorization", aadToken); return(requestMsg); })).Response; response.EnsureSuccessStatusCode(); Log.WriteLog("Fetch xdts Token succeeded."); var token = await response.Content.DeserializeJsonAsync <XdtsTokenResponse>(); string key = XdtsTokenCache.GetCacheKey(this.AuthContext.UserName, this.AuthContext.AccountSource, scid, sandboxes); this.ETokenCache.Value.UpdateToken(key, token); return(token); } }
/// <summary> /// Downloads a savedgame from Connected Storage. /// </summary> /// <param name="xuid">The xuid of the user</param> /// <param name="serviceConfigurationId">The service configuration ID (SCID) of the title</param> /// <param name="sandbox">The target sandbox id for title storage</param> /// <param name="pathAndFileName">Blob path and file name on XboxLive service.</param> /// <returns>The byte array contains downloaded blob data</returns> public static async Task <SavedGameV2Response> DownloadSavedGameAsync(ulong xuid, Guid serviceConfigurationId, string sandbox, string pathAndFileName) { using (var request = new XboxLiveHttpRequest(true, serviceConfigurationId, sandbox)) { HttpResponseMessage response = (await request.SendAsync(() => { var requestMsg = new HttpRequestMessage(HttpMethod.Get, new Uri(baseUri, $"/connectedstorage/users/xuid({xuid})/scids/{serviceConfigurationId}/savedgames/{pathAndFileName}")); requestMsg.Headers.Add("x-xbl-contract-version", "1"); return(requestMsg); })).Response; response.EnsureSuccessStatusCode(); Log.WriteLog($"DownloadSavedGameAsync for xuid: {xuid}, scid: {serviceConfigurationId}, sandbox: {sandbox}"); JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(); using (StreamReader streamReader = new StreamReader(await response.Content.ReadAsStreamAsync())) { using (JsonTextReader jsonTextReader = new JsonTextReader(streamReader)) { return(jsonSerializer.Deserialize <SavedGameV2Response>(jsonTextReader)); } } } }
/// <summary> /// Downloads atom from Connected Storage. /// </summary> /// <param name="xuid">The xuid of the user</param> /// <param name="serviceConfigurationId">The service configuration ID (SCID) of the title</param> /// <param name="sandbox">The target sandbox id for title storage</param> /// <param name="pathAndFileName">Blob path and file name to store on XboxLive service.(example: "foo\bar\blob.txt")</param> /// <returns>The byte array contains downloaded blob data</returns> public static async Task <byte[]> DownloadAtomAsync(ulong xuid, Guid serviceConfigurationId, string sandbox, string pathAndFileName) { using (var request = new XboxLiveHttpRequest(true, serviceConfigurationId, sandbox)) { HttpResponseMessage response = (await request.SendAsync(() => { var requestMsg = new HttpRequestMessage(HttpMethod.Get, new Uri(baseUri, $"/connectedstorage/users/xuid({xuid})/scids/{serviceConfigurationId}/{pathAndFileName},binary")); requestMsg.Headers.Add("x-xbl-contract-version", "1"); requestMsg.Headers.AcceptEncoding.Add(StringWithQualityHeaderValue.Parse("gzip")); return(requestMsg); })).Response; response.EnsureSuccessStatusCode(); Log.WriteLog($"DownloadAtomAsync for xuid: {xuid}, scid: {serviceConfigurationId}, sandbox: {sandbox}"); // if the response came gzip encoded, we need to decompress it if (response.Content.Headers.ContentEncoding.FirstOrDefault() == "gzip") { using (GZipStream gzipStream = new GZipStream(await response.Content.ReadAsStreamAsync(), CompressionMode.Decompress)) { using (var memoryStream = new MemoryStream()) { await gzipStream.CopyToAsync(memoryStream); return(memoryStream.ToArray()); } } } else { return(await response.Content.ReadAsByteArrayAsync()); } } }
private static async Task <UserResetJob> SubmitJobAsync(string sandbox, string scid, string xuid) { var job = new UserResetJob { Sandbox = sandbox, Scid = scid }; using (var submitRequest = new XboxLiveHttpRequest(true, scid, sandbox)) { var response = await submitRequest.SendAsync(() => { var requestMsg = new HttpRequestMessage(HttpMethod.Post, new Uri(baseUri, "submitJob")); var requestContent = JsonConvert.SerializeObject(new JobSubmitReqeust(scid, xuid)); requestMsg.Content = new StringContent(requestContent); requestMsg.Headers.Add("x-xbl-contract-version", "100"); return(requestMsg); }); response.Response.EnsureSuccessStatusCode(); // remove "" if found one. string responseContent = await response.Response.Content.ReadAsStringAsync(); job.JobId = responseContent.Trim(new char[] { '\\', '\"' }); job.CorrelationId = response.CorrelationId; Log.WriteLog($"Submitting delete job for scid:{scid}, user:{xuid}, sandbox:{sandbox} succeeded. Jobid: {job.JobId}"); } return(job); }
/// <summary> /// Deletes a blob from title storage. /// </summary> /// <param name="serviceConfigurationId">The service configuration ID (SCID) of the title</param> /// <param name="sandbox">The target sandbox id for title storage</param> /// <param name="pathAndFileName">Blob path and file name to store on XboxLive service.(example: "foo\bar\blob.txt")</param> /// <param name="blobType">Title storage blob type</param> public static async Task DeleteGlobalStorageBlobAsync(string serviceConfigurationId, string sandbox, string pathAndFileName, TitleStorageBlobType blobType) { using (var request = new XboxLiveHttpRequest(true, serviceConfigurationId, sandbox)) { var response = await request.SendAsync(() => { var requestMsg = new HttpRequestMessage(HttpMethod.Delete, new Uri(baseUri, $"/global/scids/{serviceConfigurationId}/data/{pathAndFileName},{blobType.ToString().ToLower()}")); requestMsg.Headers.Add("x-xbl-contract-version", "1"); return(requestMsg); }); Log.WriteLog($"DeleteGlobalStorageBlobAsync for scid: {serviceConfigurationId}, sandbox: {sandbox}"); } }
/// <summary> /// Downloads blob data from title storage. /// </summary> /// <param name="serviceConfigurationId">The service configuration ID (SCID) of the title</param> /// <param name="sandbox">The target sandbox id for title storage</param> /// <param name="pathAndFileName">Blob path and file name to store on XboxLive service.(example: "foo\bar\blob.txt")</param> /// <param name="blobType">Title storage blob type</param> /// <returns>The byte array contains downloaded blob data</returns> public static async Task <byte[]> DownloadGlobalStorageBlobAsync(string serviceConfigurationId, string sandbox, string pathAndFileName, TitleStorageBlobType blobType) { using (var request = new XboxLiveHttpRequest(true, serviceConfigurationId, sandbox)) { HttpResponseMessage response = (await request.SendAsync(() => { var requestMsg = new HttpRequestMessage(HttpMethod.Get, new Uri(baseUri, $"/global/scids/{serviceConfigurationId}/data/{pathAndFileName},{blobType.ToString().ToLower()}")); requestMsg.Headers.Add("x-xbl-contract-version", "1"); return(requestMsg); })).Response; response.EnsureSuccessStatusCode(); Log.WriteLog($"DownloadGlobalStorageBlobAsync for scid: {serviceConfigurationId}, sandbox: {sandbox}"); return(await response.Content.ReadAsByteArrayAsync()); } }
internal static async Task <ListTitleDataResponse> ListSavedGamesAsync(ulong xuid, string serviceConfigurationId, string sandbox, string path, uint maxItems, uint skipItems, string continuationToken) { using (var request = new XboxLiveHttpRequest(true, serviceConfigurationId, sandbox)) { var uriBuilder = new UriBuilder(baseUri) { Path = $"/connectedstorage/users/xuid({xuid})/scids/{serviceConfigurationId}/{path}" }; AppendPagingInfo(ref uriBuilder, maxItems, skipItems, continuationToken); HttpResponseMessage response = (await request.SendAsync(() => { var requestMsg = new HttpRequestMessage(HttpMethod.Get, uriBuilder.Uri); requestMsg.Headers.Add("x-xbl-contract-version", "1"); return(requestMsg); })).Response; // Return empty list on 404 if (response.StatusCode == HttpStatusCode.NotFound) { return(new ListTitleDataResponse()); } response.EnsureSuccessStatusCode(); Log.WriteLog($"ListSavedGamesAsync for xuid: {xuid}, scid: {serviceConfigurationId}, sandbox: {sandbox}"); JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(); using (StreamReader streamReader = new StreamReader(await response.Content.ReadAsStreamAsync())) { using (JsonTextReader jsonTextReader = new JsonTextReader(streamReader)) { return(jsonSerializer.Deserialize <ListTitleDataResponse>(jsonTextReader)); } } } }
private static async Task <JobStatusResponse> CheckJobStatus(UserResetJob userResetJob) { using (var submitRequest = new XboxLiveHttpRequest(true, userResetJob.Scid, userResetJob.Sandbox)) { XboxLiveHttpResponse xblResponse = await submitRequest.SendAsync(() => { var requestMsg = new HttpRequestMessage(HttpMethod.Get, new Uri(baseUri, "jobs/" + userResetJob.JobId)); if (!string.IsNullOrEmpty(userResetJob.CorrelationId)) { requestMsg.Headers.Add("X-XblCorrelationId", userResetJob.CorrelationId); } requestMsg.Headers.Add("x-xbl-contract-version", "100"); return(requestMsg); }); // There is a chance if polling too early for job status, it will return 400. // We threat it as job queue and wait for next poll. if (xblResponse.Response.StatusCode == System.Net.HttpStatusCode.BadRequest) { return(new JobStatusResponse { Status = "Queued", JobId = userResetJob.JobId }); } // Throw HttpRequestExcetpion for other HTTP status code xblResponse.Response.EnsureSuccessStatusCode(); string responseConent = await xblResponse.Response.Content.ReadAsStringAsync(); var jobstatus = JsonConvert.DeserializeObject <JobStatusResponse>(responseConent); Log.WriteLog($"Checking {userResetJob.JobId} job stauts: {jobstatus.Status}"); return(jobstatus); } }
/// <summary> /// Get title global storage quota information. /// </summary> /// <param name="serviceConfigurationId">The service configuration ID (SCID) of the title</param> /// <param name="sandbox">The target sandbox id for title storage</param> /// <returns>GlobalStorageQuotaInfo object contains quota info</returns> public static async Task <GlobalStorageQuotaInfo> GetGlobalStorageQuotaAsync(string serviceConfigurationId, string sandbox) { using (var request = new XboxLiveHttpRequest(true, serviceConfigurationId, sandbox)) { HttpResponseMessage response = (await request.SendAsync(() => { var requestMsg = new HttpRequestMessage(HttpMethod.Get, new Uri(baseUri, "/global/scids/" + serviceConfigurationId)); requestMsg.Headers.Add("x-xbl-contract-version", "1"); return(requestMsg); })).Response; response.EnsureSuccessStatusCode(); string content = await response.Content.ReadAsStringAsync(); JObject storageQuota = JObject.Parse(content); GlobalStorageQuotaInfo info = storageQuota["quotaInfo"].ToObject <GlobalStorageQuotaInfo>(); Log.WriteLog($"GetGlobalStorageQuotaAsync for scid: {serviceConfigurationId}, sandbox: {sandbox}"); return(info); } }
internal static async Task <TitleStorageBlobMetadataResult> GetGlobalStorageBlobMetaDataAsync(string serviceConfigurationId, string sandbox, string path, uint maxItems, uint skipItems, string continuationToken) { using (var request = new XboxLiveHttpRequest(true, serviceConfigurationId, sandbox)) { var uriBuilder = new UriBuilder(baseUri) { Path = $"/global/scids/{serviceConfigurationId}/data/{path}" }; AppendPagingInfo(ref uriBuilder, maxItems, skipItems, continuationToken); HttpResponseMessage response = (await request.SendAsync(() => { var requestMsg = new HttpRequestMessage(HttpMethod.Get, uriBuilder.Uri); requestMsg.Headers.Add("x-xbl-contract-version", "1"); return(requestMsg); })).Response; // Return empty list on 404 if (response.StatusCode == HttpStatusCode.NotFound) { return(new TitleStorageBlobMetadataResult()); } response.EnsureSuccessStatusCode(); Log.WriteLog($"GetGlobalStorageBlobMetaDataAsync for scid: {serviceConfigurationId}, sandbox: {sandbox}"); string stringContent = await response.Content.ReadAsStringAsync(); JObject storageMetadata = JObject.Parse(stringContent); var result = new TitleStorageBlobMetadataResult { TotalItems = storageMetadata["pagingInfo"]["totalItems"].Value <uint>(), ContinuationToken = storageMetadata["pagingInfo"]["continuationToken"].Value <string>(), ServiceConfigurationId = serviceConfigurationId, Sandbox = sandbox, Path = path }; var array = (JArray)storageMetadata["blobs"]; var metadataArray = array.Select((o) => { string fileName = o["fileName"].Value <string>(); ulong size = o["size"].Value <ulong>(); var filePathAndTypeArray = fileName.Split(','); if (filePathAndTypeArray.Length != 2) { throw new FormatException("Invalid file name format in TitleStorageBlobMetadata response"); } if (!Enum.TryParse(filePathAndTypeArray[1], true, out TitleStorageBlobType type)) { throw new FormatException("Invalid file type in TitleStorageBlobMetadata response"); } return(new TitleStorageBlobMetadata { Path = filePathAndTypeArray[0], Size = size, Type = type }); }).ToArray(); result.Items = metadataArray; return(result); } }
protected async Task <XasTokenResponse> FetchXstsToken(string msaToken, string sandbox) { // Get XASU token XasTokenResponse token = null; using (var tokenRequest = new XboxLiveHttpRequest()) { HttpResponseMessage response = (await tokenRequest.SendAsync(() => { var requestMsg = new HttpRequestMessage(HttpMethod.Post, ClientSettings.Singleton.XASUEndpoint); XasuTokenRequest xasuTokenRequest = new XasuTokenRequest(); xasuTokenRequest.Properties["SiteName"] = "user.auth.xboxlive.com"; xasuTokenRequest.Properties["RpsTicket"] = $"d={msaToken}"; var requestContent = JsonConvert.SerializeObject(xasuTokenRequest); requestMsg.Content = new StringContent(requestContent); requestMsg.Content.Headers.ContentType.MediaType = "application/json"; return(requestMsg); })).Response; // Get XASU token with MSA token response.EnsureSuccessStatusCode(); Log.WriteLog("Fetch XASU token succeeded."); token = await response.Content.DeserializeJsonAsync <XasTokenResponse>(); } // Get XSTS token using (var tokenRequest = new XboxLiveHttpRequest()) { HttpResponseMessage response = (await tokenRequest.SendAsync(() => { var requestMsg = new HttpRequestMessage(HttpMethod.Post, ClientSettings.Singleton.XSTSEndpoint); XstsTokenRequest xstsTokenRequest = new XstsTokenRequest(sandbox) { RelyingParty = "http://xboxlive.com" }; xstsTokenRequest.Properties["UserTokens"] = new[] { token.Token }; var requestContent = JsonConvert.SerializeObject(xstsTokenRequest); requestMsg.Content = new StringContent(requestContent); requestMsg.Content.Headers.ContentType.MediaType = "application/json"; return(requestMsg); })).Response; // Get XASU token with MSA token response.EnsureSuccessStatusCode(); Log.WriteLog("Fetch XSTS token succeeded."); token = await response.Content.DeserializeJsonAsync <XasTokenResponse>(); } string key = AuthTokenCache.GetCacheKey(this.AuthContext.UserName, this.AuthContext.AccountSource, this.AuthContext.Tenant, string.Empty, sandbox); this.XTokenCache.Value.UpdateToken(key, token); return(token); }