Skip to content

Commit

Permalink
Refactored code to be launched from any folder (#5)
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 authored Jul 24, 2024
1 parent b212724 commit d86419f
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 d86419f

Please sign in to comment.