Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ARM architecture support. #99

Open
wants to merge 16 commits into
base: release
Choose a base branch
from
10 changes: 3 additions & 7 deletions src/TorSharp/ToolUtility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ public static ToolSettings GetTorToolSettings(TorSharpSettings settings)
{
prefix = "tor-linux64-";
}
else if (settings.Architecture.HasFlag(TorSharpArchitecture.Arm))
else if (settings.Architecture.Contains("Arm"))
{
if (settings.Architecture == TorSharpArchitecture.Arm32)
{
Expand Down Expand Up @@ -286,14 +286,10 @@ public static Tool GetLatestToolOrNull(
public static bool TryFindToolInSystem(TorSharpSettings settings, ToolSettings toolSettings, out Tool tool)
{
tool = null;
if (settings.OSPlatform != TorSharpOSPlatform.Linux) // For windows search exe name in PATH variable?
return false;

// In linux most binaries exists in any bin directory, e.g /bin/ /sbin/ /usr/bin/
var toolPath = WhereIsUtility.WhereIs(toolSettings.TryFindExecutableName);
var toolPath = WhichUtility.Which(settings, toolSettings.TryFindExecutableName);
var toolVariants = toolPath.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
var binToolVariant = Array.Find(toolVariants,
a => Regex.IsMatch(a, $@"\/bin\/.*{toolSettings.TryFindExecutableName}"));
var binToolVariant = toolVariants.FirstOrDefault();
if (!string.IsNullOrEmpty(binToolVariant))
{
var directoryPath = Path.Combine(settings.ExtractedToolsDirectory, "local");
Expand Down
12 changes: 12 additions & 0 deletions src/TorSharp/Tools/EnumHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System;

namespace Knapcode.TorSharp.Tools
{
internal static class EnumHelper
{
public static bool Contains<T>(this T value, string enumValue) where T : Enum
{
return value.ToString().Contains(enumValue);
}
}
}
41 changes: 17 additions & 24 deletions src/TorSharp/Tools/Tor/TorFetcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public async Task<DownloadableFile> GetLatestAsync()
var fileNamePatternAndFormat = GetFileNamePatternAndFormat();
DownloadableFile downloadableFile;

if (_settings.Architecture.HasFlag(TorSharpArchitecture.Arm))
if (_settings.Architecture.Contains("Arm"))
{
if (!_settings.AllowUnofficialSources)
throw new TorSharpException($"{nameof(_settings.AllowUnofficialSources)} == false, there is no official tor distribution for {_settings.Architecture} platform.");
Expand Down Expand Up @@ -84,7 +84,7 @@ private FileNamePatternAndFormat GetFileNamePatternAndFormat()
{
pattern = @"tor-expert-bundle-(?<Version>[\d\.]+)-linux-x86_64\.tar\.gz$";
}
else if (_settings.Architecture.HasFlag(TorSharpArchitecture.Arm))
else if (_settings.Architecture.Contains("Arm"))
{
// Version twice to skip ALSA versions - https://github.com/alsa-project
var arch = _settings.Architecture == TorSharpArchitecture.Arm64 ? "arm64" : "armhf";
Expand All @@ -106,29 +106,22 @@ public async Task<DownloadableFile> GetLatestDownloadableArmFileAsync(HttpClient
FileNamePatternAndFormat patternAndFormat,
CancellationToken token)
{
SyndicationFeed syndicationFeed;
using (var response = await httpClient.GetAsync(baseUrl, HttpCompletionOption.ResponseContentRead, token).ConfigureAwait(false))
{
response.EnsureSuccessStatusCode();

using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
{
var streamReader = new StreamReader(stream);
var xmlReader = XmlReader.Create(streamReader);
syndicationFeed = SyndicationFeed.Load(xmlReader);
if (syndicationFeed == null)
{
return null;
}
}
using var response = await httpClient.GetAsync(baseUrl, HttpCompletionOption.ResponseContentRead, token).ConfigureAwait(false);
response.EnsureSuccessStatusCode();

using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
using var streamReader = new StreamReader(stream);
using var xmlReader = XmlReader.Create(streamReader);
var syndicationFeed = SyndicationFeed.Load(xmlReader);
if (syndicationFeed == null)
return null;

return syndicationFeed.Items
.Where(i => i.Links.Any())
.Select(i => GetDownloadableFile(patternAndFormat.Pattern, patternAndFormat.Format, i))
.Where(i => i != null)
.OrderByDescending(x => x.Version)
.FirstOrDefault();
}
return syndicationFeed.Items
.Where(i => i.Links.Any())
.Select(i => GetDownloadableFile(patternAndFormat.Pattern, patternAndFormat.Format, i))
.Where(i => i != null)
.OrderByDescending(x => x.Version)
.FirstOrDefault();
}

private DownloadableFile GetDownloadableFile(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
using System.Diagnostics;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;

namespace Knapcode.TorSharp.Tools
{
internal static class WhereIsUtility
internal static class WhichUtility
{
public static string WhereIs(string searchPattern)
public static string Which(TorSharpSettings settings, string searchPattern)
{
if (settings.OSPlatform == TorSharpOSPlatform.Windows)
ProKn1fe marked this conversation as resolved.
Show resolved Hide resolved
return SearchInPathVariable(searchPattern);

using (var process = new Process())
{
process.StartInfo.FileName = "whereis";
process.StartInfo.FileName = "which";
process.StartInfo.Arguments = searchPattern;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
Expand All @@ -30,6 +36,19 @@ public static string WhereIs(string searchPattern)
}
}

private static string SearchInPathVariable(string pattern)
{
var variables = Environment.GetEnvironmentVariables();
if (!variables.Contains("Path"))
return null;

var what = variables["Path"].ToString()
.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)
.SelectMany(a => Directory.GetFiles(a, pattern, SearchOption.TopDirectoryOnly));

return what.FirstOrDefault();
}

private static DataReceivedEventHandler GetOutputHandler(StringBuilder output, object outputLock)
{
return (object sender, DataReceivedEventArgs e) =>
Expand Down
16 changes: 6 additions & 10 deletions src/TorSharp/TorSharpArchitecture.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
using System;

namespace Knapcode.TorSharp
namespace Knapcode.TorSharp
{
/// <summary>
/// CPU architectures that TorSharp can run on.
/// </summary>
[Flags]
public enum TorSharpArchitecture
{
Unknown = 0,
X86 = 1,
X64 = 2,
Arm = 4,
Arm32 = Arm | X86,
Arm64 = Arm | X64
Unknown,
X86,
X64,
Arm32,
Arm64
}
}
3 changes: 2 additions & 1 deletion src/TorSharp/TorSharpSettings.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.IO;
using System.Text;
using Knapcode.TorSharp.Tools;
#if NETSTANDARD
using System.Runtime.InteropServices;
using SystemOSPlatform = System.Runtime.InteropServices.OSPlatform;
Expand Down Expand Up @@ -63,7 +64,7 @@ public TorSharpSettings()
PrivoxySettings.AutomaticallyFindInSystem = true;
TorSettings.AutomaticallyFindInSystem = true;
}
if (Architecture.HasFlag(TorSharpArchitecture.Arm))
if (Architecture.Contains("Arm"))
{
PrivoxySettings.Disable = true;
}
Expand Down