Skip to content

Commit

Permalink
Fixed inability to get manifest IDs for some apps
Browse files Browse the repository at this point in the history
  • Loading branch information
Nuclearistt committed Jan 12, 2024
1 parent f249501 commit a672d95
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 7 deletions.
4 changes: 2 additions & 2 deletions TEKSteamClient.csproj
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Version>1.0.1</Version>
<Version>1.1.0</Version>
<Authors>Nuclearist</Authors>
<Product>TEK Steam Client library</Product>
<Title>TEK Steam Client</Title>
<Copyright>Copyright © 2023 Nuclearist</Copyright>
<Copyright>Copyright © 2023-2024 Nuclearist</Copyright>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageTags>steam;tek</PackageTags>
Expand Down
18 changes: 18 additions & 0 deletions protos/cm/messages/bodies/pics_access_token.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
syntax="proto3";

package teksteamclient.cm.messages.bodies;
option csharp_namespace = "TEKSteamClient.CM.Messages.Bodies";

message PicsAccessToken
{
repeated uint32 app_ids = 2;
}
message PicsAccessTokenResponse
{
message AppToken
{
uint32 app_id = 1;
uint64 token = 2;
}
repeated AppToken apps = 3;
}
2 changes: 2 additions & 0 deletions protos/cm/messages/message_type.proto
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,6 @@ enum MessageType
LOG_ON = 5514;
PRODUCT_INFO = 8903;
PRODUCT_INFO_RESPONSE = 8904;
PICS_ACCESS_TOKEN = 8905;
PICS_ACCESS_TOKEN_RESPONSE = 8906;
}
3 changes: 1 addition & 2 deletions src/CDNClient.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Collections.Frozen;
using System.IO.Hashing;
using System.IO.Hashing;
using System.Net;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
Expand Down
40 changes: 37 additions & 3 deletions src/CM/CMClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,13 @@ static CMClient()
private readonly WebSocketConnection _connection;
/// <summary>OS type value included into logon messages.</summary>
private static readonly int s_osType;
/// <summary>HTTP client that downloads PICS app info.</summary>
private static readonly HttpClient s_clientConfigClient = new()
{
BaseAddress = new("http://clientconfig.akamai.steamstatic.com/appinfo/"),
DefaultRequestVersion = HttpVersion.Version20,
Timeout = TimeSpan.FromSeconds(10)
};
/// <summary>When <see langword="true"/>, ensures that the client is connected and logged on before every request and logs on with anonymous user credentials if it's not.</summary>
public bool EnsureLogOn { get; set; }
/// <summary>Steam cell ID used in certain requests.</summary>
Expand Down Expand Up @@ -301,11 +308,38 @@ public FrozenDictionary<uint, ulong> GetDepotManifestIds(uint appId)
message.Body.Apps.Add(new ProductInfo.Types.AppInfo { AppId = appId, AccessToken = 0 });
message.Body.MetadataOnly = false;
var response = _connection.TransceiveMessage<ProductInfo, ProductInfoResponse>(message, MessageType.ProductInfoResponse, jobId);
if (response is null || response.Body.Apps.Count is 0 || !MemoryMarshal.TryGetArray(response.Body.Apps[0].Buffer.Memory, out var segment))
if (response is null || response.Body.Apps.Count is 0)
throw new SteamException(SteamException.ErrorType.CMFailedToGetManifestIds);
if (response.Body.Apps[0].MissingToken)
{
jobId = GlobalId.NextJobId;
var tokenMessage = new Message<PicsAccessToken>(MessageType.PicsAccessToken) { Header = new() { SourceJobId = jobId } };
tokenMessage.Body.AppIds.Add(appId);
var tokenResponse = _connection.TransceiveMessage<PicsAccessToken, PicsAccessTokenResponse>(tokenMessage, MessageType.PicsAccessTokenResponse, jobId);
if (tokenResponse is null || tokenResponse.Body.Apps.Count is 0)
throw new SteamException(SteamException.ErrorType.CMFailedToGetPicsAccessToken);
jobId = GlobalId.NextJobId;
message.Header.SourceJobId = jobId;
message.Body.Apps[0].AccessToken = tokenResponse.Body.Apps[0].Token;
response = _connection.TransceiveMessage<ProductInfo, ProductInfoResponse>(message, MessageType.ProductInfoResponse, jobId);
if (response is null || response.Body.Apps.Count is 0)
throw new SteamException(SteamException.ErrorType.CMFailedToGetManifestIds);
}
var appInfo = response.Body.Apps[0];
List<VDFEntry>? entries;
using (var reader = new StreamReader(new MemoryStream(segment.Array!, false)))
entries = new VDFEntry(reader)["depots"]?.Children;
if (MemoryMarshal.TryGetArray(appInfo.Buffer.Memory, out var segment))
using (var reader = new StreamReader(new MemoryStream(segment.Array!, false)))
entries = new VDFEntry(reader)["depots"]?.Children;
else
try
{
var httpRequest = new HttpRequestMessage(HttpMethod.Get, new Uri($"{appId}/sha/{Convert.ToHexString(appInfo.Sha.Span)}.txt.gz")) { Version = HttpVersion.Version20 };
using var httpResponse = s_clientConfigClient.SendAsync(httpRequest, HttpCompletionOption.ResponseContentRead, CancellationToken.None).Result.EnsureSuccessStatusCode();
using var content = httpResponse.Content;
using var reader = new StreamReader(content.ReadAsStream());
entries = new VDFEntry(reader)["depots"]?.Children;
}
catch (HttpRequestException e) { throw new SteamException(SteamException.ErrorType.CMFailedToGetManifestIds, e); }
if (entries is null)
return FrozenDictionary<uint, ulong>.Empty;
entries.RemoveAll(e => !uint.TryParse(e.Key, out _) || e["manifests"]?["public"] is null);
Expand Down
2 changes: 2 additions & 0 deletions src/SteamException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ public enum ErrorType
CMFailedToGetManifestRequestCode,
/// <summary>[CM Client] Failed to get depot patch availability.</summary>
CMFailedToGetPatchAvailablity,
/// <summary>[CM Client] Failed to get PICS access token for app.</summary>
CMFailedToGetPicsAccessToken,
/// <summary>[CM Client] Failed to get workshop item details.</summary>
CMFailedToGetWorkshopItemDetails,
/// <summary>[CM Client] Log on failed.</summary>
Expand Down

0 comments on commit a672d95

Please sign in to comment.