Convert to .NET Core.

Works on macOS, haven't tried Windows / .NET Framework yet.
pull/19/head
Netshroud 9 years ago
parent 35aa666ea5
commit c0b6d0ce3c

@ -25,7 +25,7 @@ namespace DepotDownloader
private BlockingCollection<CDNClient.Server> availableServerEndpoints;
private AutoResetEvent populatePoolEvent;
private Thread monitorThread;
private Task monitorTask;
public CDNClientPool(Steam3Session steamSession)
{
@ -37,13 +37,10 @@ namespace DepotDownloader
populatePoolEvent = new AutoResetEvent(true);
monitorThread = new Thread(ConnectionPoolMonitor);
monitorThread.Name = "CDNClient Pool Monitor";
monitorThread.IsBackground = true;
monitorThread.Start();
monitorTask = Task.Factory.StartNew(ConnectionPoolMonitorAsync).Unwrap();
}
private List<CDNClient.Server> FetchBootstrapServerList()
private async Task<IList<CDNClient.Server>> FetchBootstrapServerListAsync()
{
CDNClient bootstrap = new CDNClient(steamSession.steamClient);
@ -51,7 +48,7 @@ namespace DepotDownloader
{
try
{
var cdnServers = bootstrap.FetchServerList(cellId: (uint)ContentDownloader.Config.CellID);
var cdnServers = await bootstrap.FetchServerListAsync(cellId: (uint)ContentDownloader.Config.CellID).ConfigureAwait(false);
if (cdnServers != null)
{
return cdnServers;
@ -64,7 +61,7 @@ namespace DepotDownloader
}
}
private void ConnectionPoolMonitor()
private async Task ConnectionPoolMonitorAsync()
{
while(true)
{
@ -75,7 +72,7 @@ namespace DepotDownloader
steamSession.steamClient.IsConnected &&
steamSession.steamClient.GetServersOfType(EServerType.CS).Count > 0)
{
var servers = FetchBootstrapServerList();
var servers = await FetchBootstrapServerListAsync();
var weightedCdnServers = servers.Select(x =>
{
@ -101,7 +98,7 @@ namespace DepotDownloader
activeClientAuthed.TryRemove(client, out authData);
}
private CDNClient BuildConnection(uint appId, uint depotId, byte[] depotKey, CDNClient.Server serverSeed, CancellationToken token)
private async Task<CDNClient> BuildConnectionAsync(uint appId, uint depotId, byte[] depotKey, CDNClient.Server serverSeed, CancellationToken token)
{
CDNClient.Server server = null;
CDNClient client = null;
@ -147,8 +144,8 @@ namespace DepotDownloader
}
}
client.Connect(server);
client.AuthenticateDepot(depotId, depotKey, cdnAuthToken);
await client.ConnectAsync(server).ConfigureAwait(false);
await client.AuthenticateDepotAsync(depotId, depotKey, cdnAuthToken).ConfigureAwait(false);
}
catch (Exception ex)
{
@ -168,7 +165,7 @@ namespace DepotDownloader
return client;
}
private bool ReauthConnection(CDNClient client, CDNClient.Server server, uint appId, uint depotId, byte[] depotKey)
private async Task<bool> ReauthConnectionAsync(CDNClient client, CDNClient.Server server, uint appId, uint depotId, byte[] depotKey)
{
DebugLog.Assert(server.Type == "CDN" || steamSession.AppTickets[depotId] == null, "CDNClientPool", "Re-authing a CDN or anonymous connection");
@ -193,7 +190,7 @@ namespace DepotDownloader
}
}
client.AuthenticateDepot(depotId, depotKey, cdnAuthToken);
await client.AuthenticateDepotAsync(depotId, depotKey, cdnAuthToken).ConfigureAwait(false);
activeClientAuthed[client] = Tuple.Create(depotId, server);
return true;
}
@ -205,7 +202,7 @@ namespace DepotDownloader
return false;
}
public CDNClient GetConnectionForDepot(uint appId, uint depotId, byte[] depotKey, CancellationToken token)
public async Task<CDNClient> GetConnectionForDepotAsync(uint appId, uint depotId, byte[] depotKey, CancellationToken token)
{
CDNClient client = null;
@ -216,24 +213,24 @@ namespace DepotDownloader
// if we couldn't find a connection, make one now
if (client == null)
{
client = BuildConnection(appId, depotId, depotKey, null, token);
client = await BuildConnectionAsync(appId, depotId, depotKey, null, token).ConfigureAwait(false);
}
// if we couldn't find the authorization data or it's not authed to this depotid, re-initialize
if (!activeClientAuthed.TryGetValue(client, out authData) || authData.Item1 != depotId)
{
if (authData.Item2.Type == "CDN" && ReauthConnection(client, authData.Item2, appId, depotId, depotKey))
if (authData.Item2.Type == "CDN" && await ReauthConnectionAsync(client, authData.Item2, appId, depotId, depotKey).ConfigureAwait(false))
{
Console.WriteLine("Re-authed CDN connection to content server {0} from {1} to {2}", authData.Item2, authData.Item1, depotId);
}
else if (authData.Item2.Type == "CS" && steamSession.AppTickets[depotId] == null && ReauthConnection(client, authData.Item2, appId, depotId, depotKey))
else if (authData.Item2.Type == "CS" && steamSession.AppTickets[depotId] == null && await ReauthConnectionAsync(client, authData.Item2, appId, depotId, depotKey).ConfigureAwait(false))
{
Console.WriteLine("Re-authed anonymous connection to content server {0} from {1} to {2}", authData.Item2, authData.Item1, depotId);
}
else
{
ReleaseConnection(client);
client = BuildConnection(appId, depotId, depotKey, authData.Item2, token);
client = await BuildConnectionAsync(appId, depotId, depotKey, authData.Item2, token).ConfigureAwait(false);
}
}

@ -362,7 +362,7 @@ namespace DepotDownloader
steam3.Disconnect();
}
public static void DownloadApp(uint appId, uint depotId, string branch, bool forceDepot = false)
public static async Task DownloadAppAsync(uint appId, uint depotId, string branch, bool forceDepot = false)
{
if(steam3 != null)
steam3.RequestAppInfo(appId);
@ -451,7 +451,7 @@ namespace DepotDownloader
try
{
DownloadSteam3(appId, infos);
await DownloadSteam3Async(appId, infos).ConfigureAwait(false);
}
catch (OperationCanceledException)
{
@ -524,7 +524,7 @@ namespace DepotDownloader
public ProtoManifest.ChunkData NewChunk { get; private set; }
}
private static void DownloadSteam3( uint appId, List<DepotDownloadInfo> depots )
private static async Task DownloadSteam3Async( uint appId, List<DepotDownloadInfo> depots )
{
ulong TotalBytesCompressed = 0;
ulong TotalBytesUncompressed = 0;
@ -583,9 +583,9 @@ namespace DepotDownloader
{
CDNClient client = null;
try {
client = cdnPool.GetConnectionForDepot(appId, depot.id, depot.depotKey, CancellationToken.None);
client = await cdnPool.GetConnectionForDepotAsync(appId, depot.id, depot.depotKey, CancellationToken.None).ConfigureAwait(false);
depotManifest = client.DownloadManifest(depot.id, depot.manifestId);
depotManifest = await client.DownloadManifestAsync(depot.id, depot.manifestId).ConfigureAwait(false);
cdnPool.ReturnConnection(client);
}
@ -677,10 +677,15 @@ namespace DepotDownloader
}
});
var semaphore = new SemaphoreSlim(Config.MaxDownloads);
filesAfterExclusions.Where(f => !f.Flags.HasFlag(EDepotFileFlag.Directory))
.AsParallel().WithCancellation(cts.Token).WithDegreeOfParallelism(Config.MaxDownloads)
.ForAll(file =>
.ForAll(async file =>
{
try
{
await semaphore.WaitAsync().ConfigureAwait(false);
string fileFinalPath = Path.Combine(depot.installDir, file.FileName);
string fileStagingPath = Path.Combine(stagingDir, file.FileName);
@ -780,7 +785,7 @@ namespace DepotDownloader
size_downloaded += file.TotalSize;
Console.WriteLine("{0,6:#00.00}% {1}", ((float)size_downloaded / (float)complete_download_size) * 100.0f, fileFinalPath);
if (fs != null)
fs.Close();
fs.Dispose();
return;
}
else
@ -801,7 +806,7 @@ namespace DepotDownloader
CDNClient client;
try
{
client = cdnPool.GetConnectionForDepot(appId, depot.id, depot.depotKey, cts.Token);
client = await cdnPool.GetConnectionForDepotAsync(appId, depot.id, depot.depotKey, cts.Token).ConfigureAwait(false);
}
catch (OperationCanceledException)
{
@ -817,7 +822,7 @@ namespace DepotDownloader
try
{
chunkData = client.DownloadDepotChunk(depot.id, data);
chunkData = await client.DownloadDepotChunkAsync(depot.id, data).ConfigureAwait(false);
cdnPool.ReturnConnection(client);
break;
}
@ -868,9 +873,14 @@ namespace DepotDownloader
size_downloaded += chunk.UncompressedLength;
}
fs.Close();
fs.Dispose();
Console.WriteLine("{0,6:#00.00}% {1}", ((float)size_downloaded / (float)complete_download_size) * 100.0f, fileFinalPath);
}
finally
{
semaphore.Release();
}
});
ConfigStore.TheConfig.LastManifests[depot.id] = depot.manifestId;

@ -1,124 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{39159C47-ACD3-449F-96CA-4F30C8ED147A}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>DepotDownloader</RootNamespace>
<AssemblyName>DepotDownloader</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<FileUpgradeFlags>
</FileUpgradeFlags>
<OldToolsVersion>3.5</OldToolsVersion>
<UpgradeBackupLocation />
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<TargetFrameworkProfile />
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages>
<TargetFrameworks>netcoreapp1.1;net46</TargetFrameworks>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<PlatformTarget>x86</PlatformTarget>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<PlatformTarget>AnyCPU</PlatformTarget>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="protobuf-net, Version=2.0.0.668, Culture=neutral, PublicKeyToken=257b51d87d2e4d67, processorArchitecture=MSIL">
<SpecificVersion>True</SpecificVersion>
<HintPath>..\packages\protobuf-net.2.0.0.668\lib\net40\protobuf-net.dll</HintPath>
</Reference>
<Reference Include="SteamKit2, Version=1.8.1.0, Culture=neutral, PublicKeyToken=ed3ce47ed5aad940, processorArchitecture=MSIL">
<HintPath>..\packages\SteamKit2.1.8.1\lib\net45\SteamKit2.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data.DataSetExtensions">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="CDNClientPool.cs" />
<Compile Include="ContentDownloader.cs" />
<Compile Include="ConfigStore.cs" />
<Compile Include="DownloadConfig.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ProtoManifest.cs" />
<Compile Include="Steam3Session.cs" />
<Compile Include="Util.cs" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
<Visible>False</Visible>
<ProductName>Windows Installer 3.1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<ProjectReference Include="..\..\SteamKit\SteamKit2\SteamKit2\SteamKit2.csproj" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
<PackageReference Include="protobuf-net" Version="2.1.0" />
<PackageReference Include="system.componentmodel.typeconverter" Version="4.3.0" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

@ -4,12 +4,16 @@ using System.IO;
using System.Text.RegularExpressions;
using SteamKit2;
using System.ComponentModel;
using System.Threading.Tasks;
namespace DepotDownloader
{
class Program
{
static void Main( string[] args )
=> MainAsync(args).GetAwaiter().GetResult();
static async Task MainAsync( string[] args )
{
if ( args.Length == 0 )
{
@ -19,7 +23,7 @@ namespace DepotDownloader
DebugLog.Enabled = false;
ConfigStore.LoadFromFile(Path.Combine(Environment.CurrentDirectory, "DepotDownloader.config"));
ConfigStore.LoadFromFile(Path.Combine(Directory.GetCurrentDirectory(), "DepotDownloader.config"));
bool bDumpManifest = HasParameter( args, "-manifest-only" );
uint appId = GetParameter<uint>( args, "-app", ContentDownloader.INVALID_APP_ID );
@ -110,7 +114,7 @@ namespace DepotDownloader
if (ContentDownloader.InitializeSteam3(username, password))
{
ContentDownloader.DownloadApp(appId, depotId, branch, forceDepot);
await ContentDownloader.DownloadAppAsync(appId, depotId, branch, forceDepot).ConfigureAwait(false);
ContentDownloader.ShutdownSteam3();
}
}

@ -31,4 +31,4 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.2.1.*")]
[assembly: AssemblyVersion("2.2.2.0")]

@ -11,60 +11,19 @@ namespace DepotDownloader
{
static class Util
{
[DllImport( "libc" )]
static extern int uname( IntPtr buf );
static int _isMacOSX = -1;
// Environment.OSVersion.Platform returns PlatformID.Unix under Mono on OS X
// Code adapted from Mono: mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUI.cs
private static bool IsMacOSX()
{
if ( _isMacOSX != -1 )
return _isMacOSX == 1;
IntPtr buf = IntPtr.Zero;
try
{
// The size of the utsname struct varies from system to system, but this _seems_ more than enough
buf = Marshal.AllocHGlobal( 4096 );
if ( uname( buf ) == 0 )
{
string sys = Marshal.PtrToStringAnsi( buf );
if ( sys == "Darwin" )
public static string GetSteamOS()
{
_isMacOSX = 1;
return true;
}
}
}
catch
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
// Do nothing?
return "windows";
}
finally
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
if ( buf != IntPtr.Zero )
Marshal.FreeHGlobal( buf );
}
_isMacOSX = 0;
return false;
return "macos";
}
public static string GetSteamOS()
{
switch (Environment.OSVersion.Platform)
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
case PlatformID.Win32NT:
case PlatformID.Win32Windows:
return "windows";
case PlatformID.MacOSX:
return "macos";
case PlatformID.Unix:
return IsMacOSX() ? "macos" : "linux";
return "linux";
}
return "unknown";
@ -141,14 +100,13 @@ namespace DepotDownloader
public static byte[] SHAHash( byte[] input )
{
SHA1Managed sha = new SHA1Managed();
byte[] output = sha.ComputeHash( input );
sha.Clear();
using (var sha = SHA1.Create())
{
var output = sha.ComputeHash( input );
return output;
}
}
public static byte[] DecodeHexString( string hex )
{

Loading…
Cancel
Save