Skip to content

Commit

Permalink
Refactored code to be launched from any folder
Browse files Browse the repository at this point in the history
Changed notice when starting to be more concrete instead of vague
Added more checks for unauthorized devices
  • Loading branch information
Meister1593 committed Jul 24, 2024
1 parent b212724 commit 6a754f4
Showing 1 changed file with 143 additions and 116 deletions.
259 changes: 143 additions & 116 deletions ADBForwarder/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System.Linq;
using System.Net;
using System.Threading;
using System.Diagnostics;
using System.Net.Http;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
Expand All @@ -13,161 +12,189 @@
using Microsoft.Extensions.Configuration;
using UnixFileMode = System.IO.UnixFileMode;

namespace ADBForwarder
namespace ADBForwarder;

internal class PortConfiguration(List<int> ports)
{
internal class PortConfiguration(List<int> ports)
{
public List<int> Ports { get; set; } = ports;
}
public List<int> Ports { get; set; } = ports;
}

internal static class Program
{
private static readonly AdbClient Client = new();
private static readonly AdbServer Server = new();
private static readonly IPEndPoint EndPoint = new(IPAddress.Loopback, AdbClient.AdbServerPort);
private static PortConfiguration _portConfiguration;

internal static class Program
private static void Main()
{
private static readonly AdbClient Client = new();
private static readonly AdbServer Server = new();
private static readonly IPEndPoint EndPoint = new(IPAddress.Loopback, AdbClient.AdbServerPort);
private static PortConfiguration _portConfiguration;
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("config.json", optional: true);

private static void Main()
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("config.json", optional: true);
IConfiguration config = builder.Build();

IConfiguration config = builder.Build();
_portConfiguration = config.GetSection("PortConfiguration").Get<PortConfiguration>()
?? new PortConfiguration([9943, 9944]);

_portConfiguration = config.GetSection("PortConfiguration").Get<PortConfiguration>()
?? new PortConfiguration([9943, 9944]);
Console.ResetColor();
var currentDirectory = Path.GetDirectoryName(AppContext.BaseDirectory);
if (currentDirectory == null)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Path error!");
return;
}

Console.ResetColor();
var currentDirectory = Path.GetDirectoryName(AppContext.BaseDirectory);
if (currentDirectory == null)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Path error!");
return;
}
var adbFolderPath = Path.Combine(currentDirectory, "adb");
var adbPath = Path.Combine(adbFolderPath, "platform-tools");
var downloadUri = "https://dl.google.com/android/repository/platform-tools-latest-{0}.zip";

var adbPath = "adb/platform-tools/{0}";
var downloadUri = "https://dl.google.com/android/repository/platform-tools-latest-{0}.zip";
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
Console.WriteLine("Platform: Linux");

if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
Console.WriteLine("Platform: Linux");
adbPath = Path.Combine(adbPath, "adb");
downloadUri = string.Format(downloadUri, "linux");
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
Console.WriteLine("Platform: Windows");

adbPath = string.Format(adbPath, "adb");
downloadUri = string.Format(downloadUri, "linux");
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
Console.WriteLine("Platform: Windows");
adbPath = Path.Combine(adbPath, "adb.exe");
downloadUri = string.Format(downloadUri, "windows");
}
else
{
Console.WriteLine("Unsupported platform!");
return;
}

adbPath = string.Format(adbPath, "adb.exe");
downloadUri = string.Format(downloadUri, "windows");
}
else
{
Console.WriteLine("Unsupported platform!");
return;
}
var absoluteAdbPath = Path.Combine(currentDirectory, adbPath);
if (!File.Exists(absoluteAdbPath))
{
Console.WriteLine("ADB not found, downloading...");
DownloadAdb(adbFolderPath, downloadUri).Wait();

var absoluteAdbPath = Path.Combine(currentDirectory, adbPath);
if (!File.Exists(absoluteAdbPath))
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
Console.WriteLine("ADB not found, downloading...");
DownloadADB(downloadUri).Wait();

if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
Console.WriteLine("Giving adb executable permissions");
File.SetUnixFileMode(absoluteAdbPath,
UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute);
}
Console.WriteLine("Giving adb executable permissions");
File.SetUnixFileMode(absoluteAdbPath,
UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute);
}
}

Console.WriteLine("Starting ADB Server...");
Server.StartServer(absoluteAdbPath, false);
Server.StartServer(absoluteAdbPath, false);

Client.Connect(EndPoint);
Client.Connect(EndPoint);

var monitor = new DeviceMonitor(new AdbSocket(EndPoint));
monitor.DeviceConnected += Monitor_DeviceConnected;
monitor.DeviceDisconnected += Monitor_DeviceDisconnected;
monitor.Start();
Console.WriteLine("Adb server started.");
Console.WriteLine("If your device doesn't show up after connecting the device, " +
"please make sure dev mode is enabled on headset and cable or usb port is not damaged.");

while (true)
{
// Main thread needs to stay alive, 100ms is acceptable idle time
Thread.Sleep(100);
}
}
var monitor = new DeviceMonitor(new AdbSocket(EndPoint));
monitor.DeviceConnected += Monitor_DeviceConnected;
monitor.DeviceDisconnected += Monitor_DeviceDisconnected;
monitor.Start();

private static void Monitor_DeviceConnected(object sender, DeviceDataEventArgs e)
while (true)
{
// Prevent duplicate ports
_portConfiguration.Ports = _portConfiguration.Ports.Distinct().ToList();
if (e.Device.Serial.StartsWith("127.0.0.1"))
{
// We don't want to re-forward local device
return;
}

Console.ForegroundColor = ConsoleColor.DarkGreen;
Console.WriteLine($"Connected device: {e.Device.Serial}");
Forward(e.Device);
// Main thread needs to stay alive, 100ms is acceptable idle time
Thread.Sleep(100);
}
}

private static void Monitor_DeviceDisconnected(object sender, DeviceDataEventArgs e)
private static void Monitor_DeviceConnected(object sender, DeviceDataEventArgs e)
{
// Prevent duplicate ports
_portConfiguration.Ports = _portConfiguration.Ports.Distinct().ToList();
if (e.Device.Serial.StartsWith("127.0.0.1"))
{
Console.ForegroundColor = ConsoleColor.DarkRed;
Console.WriteLine($"Disconnected device: {e.Device.Serial}");
// We don't want to re-forward local device
return;
}

private static void Forward(DeviceData device)
{
// DeviceConnected calls without product set yet
Thread.Sleep(1000);
Console.ForegroundColor = ConsoleColor.DarkGreen;
Console.WriteLine($"Connected device: {DeviceStringFromDeviceData(e.Device)}");
Forward(e.Device);
}

foreach (var deviceData in Client.GetDevices().Where(deviceData => device.Serial == deviceData.Serial))
private static void Monitor_DeviceDisconnected(object sender, DeviceDataEventArgs e)
{
Console.ForegroundColor = ConsoleColor.DarkRed;
Console.WriteLine($"Disconnected device: {DeviceStringFromDeviceData(e.Device)}");
}

private static void Forward(DeviceData device)
{
// DeviceConnected calls without product set yet
Thread.Sleep(1000);

foreach (var deviceData in Client.GetDevices().Where(deviceData => device.Serial == deviceData.Serial))
{
if (deviceData.State != DeviceState.Online)
{
if (deviceData.State != DeviceState.Online)
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("Skipped forwarding device: " +
$"{DeviceStringFromDeviceData(deviceData)}," +
$" Error: {deviceData.State}");

if (deviceData.State == DeviceState.Unauthorized)
{
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine(
$"Skipped forwarding device: {(string.IsNullOrEmpty(deviceData.Product) ? deviceData.Serial : deviceData.Product)}");
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) return;
Console.WriteLine("Please make sure you have android-udev-rules installed.");
Console.WriteLine("Install them through package manager or visit https://github.com/M0Rf30/android-udev-rules and follow instructions.");
Console.WriteLine("Unauthorized device, please make sure you enabled developer mode on device, " +
"authorized adb connection on the device and then replug usb cable.");
Console.ForegroundColor = ConsoleColor.White;
return;
}

foreach (var port in _portConfiguration.Ports)
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
Client.CreateForward(deviceData, port, port);
Console.WriteLine("Permission error, please make sure you have " +
"android-udev-rules installed and reboot pc.");
Console.WriteLine("Install udev rules through package manager or visit " +
"https://github.com/M0Rf30/android-udev-rules and follow instructions.");
Console.ForegroundColor = ConsoleColor.White;
return;
}

Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"Successfully forwarded device: {deviceData.Serial} [{deviceData.Product}]");

return;
}
}

private static async Task DownloadADB(string downloadUri)
{
using var client = new HttpClient();
var fileStream = await client.GetStreamAsync(downloadUri);
await using (var outputFileStream = new FileStream("adb.zip", FileMode.Create))
foreach (var port in _portConfiguration.Ports)
{
await fileStream.CopyToAsync(outputFileStream);
Client.CreateForward(deviceData, port, port);
}

Console.WriteLine("Download successful");
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"Successfully forwarded device: {DeviceStringFromDeviceData(deviceData)}");
Console.ForegroundColor = ConsoleColor.White;

var zip = new FastZip();
zip.ExtractZip("adb.zip", "adb", null);
Console.WriteLine("Extraction successful");
return;
}
}

File.Delete("adb.zip");
private static string DeviceStringFromDeviceData(DeviceData deviceData)
{
return string.IsNullOrWhiteSpace(deviceData.Product)
? deviceData.Serial
: $"{deviceData.Serial} [{deviceData.Product}]";
}

private static async Task DownloadAdb(string adbFolderPath, string downloadUri)
{
using var client = new HttpClient();
var fileStream = await client.GetStreamAsync(downloadUri);
Directory.CreateDirectory(adbFolderPath);
var zipPath = Path.Combine(adbFolderPath, "adb.zip");
await using (var outputFileStream = new FileStream(zipPath, FileMode.Create))
{
await fileStream.CopyToAsync(outputFileStream);
}

Console.WriteLine("Download successful");

var zip = new FastZip();
zip.ExtractZip(zipPath, adbFolderPath, null);
Console.WriteLine("Extraction successful");

File.Delete(zipPath);
}
}

0 comments on commit 6a754f4

Please sign in to comment.