Skip to content

Commit

Permalink
added linking and a pidfile to account for Linux's lack of shared mutex.
Browse files Browse the repository at this point in the history
  • Loading branch information
TauAkiou committed Oct 17, 2020
1 parent 22dbf78 commit 622cbde
Show file tree
Hide file tree
Showing 7 changed files with 181 additions and 28 deletions.
1 change: 1 addition & 0 deletions AmongUsCapture/AmongUsCapture.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="GtkSharp" Version="3.22.25.128" />
<PackageReference Include="Mono.Posix.NETStandard" Version="5.20.1-preview" />
<PackageReference Include="NamedPipeServerStream.NetFrameworkVersion" Version="1.0.2" />
<PackageReference Include="SharedMemory" Version="2.2.3" />
<PackageReference Include="SocketIOClient" Version="2.0.2.6" />
Expand Down
151 changes: 135 additions & 16 deletions AmongUsCapture/IPC/DBus/IPCadapterDBus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Runtime.InteropServices;
using System.Security.Policy;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Castle.Components.DictionaryAdapter;
using Gtk;
using Mono.Unix;
using SharedMemory;
using Tmds.DBus;
using Tmds.DBus.Transports;
Expand All @@ -28,6 +32,7 @@ public override URIStartResult HandleURIStart(string[] args)
{
var myProcessId = Process.GetCurrentProcess().Id;
//Process[] processes = Process.GetProcessesByName("AmongUsCapture");
//Process[] dotnetprocesses = Process.GetProcessesByName("dotnet");
//foreach (Process p in processes)
//{
//if (p.Id != myProcessId)
Expand All @@ -37,43 +42,158 @@ public override URIStartResult HandleURIStart(string[] args)
// }
Console.WriteLine(Program.GetExecutablePath());

mutex = new Mutex(true, appName, out var createdNew);
//mutex = new Mutex(true, appName, out var createdNew);
bool createdNew = false;
var wasURIStart = args.Length > 0 && args[0].StartsWith(UriScheme + "://");
var result = URIStartResult.CONTINUE;

if (!File.Exists(Path.Join(Settings.StorageLocation, ".amonguscapture.pid")))
{
createdNew = true;
}
else
{
// Open our PID file.
using (var pidfile = File.OpenText(Path.Join(Settings.StorageLocation, ".amonguscapture.pid")))
{
var pid = pidfile.ReadLine();
if (pid != null)
{
var pidint = Int32.Parse(pid);

try
{
var capproc = Process.GetProcessById(pidint);
var assmbname = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
var runnername = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;

if (!capproc.ProcessName.Contains("dotnet"))
{
// We're just going to assume that a dotnet process that matches this set of parameters
// is a running capture process.
throw new ArgumentException();

}
else if (!capproc.ProcessName.Contains(Path.GetFileName(runnername)))
{
throw new ArgumentException();
}


if (capproc.HasExited)
{
throw new ArgumentException();
}
}
catch (ArgumentException e)
{
// Process doesn't exist. Clear the file.
Console.WriteLine($"Found stale PID file containing {pid}.");
File.Delete(Path.Join(Settings.StorageLocation, ".amonguscapture.pid"));
createdNew = true;
}
}
}

}

if (createdNew)
{
using (var pidwriter = File.CreateText(Path.Join(Settings.StorageLocation, ".amonguscapture.pid")))
{
pidwriter.Write(myProcessId);
}
}


if (!createdNew) // send it to already existing instance if applicable, then close
{
if (wasURIStart) SendToken(args[0]);
if (wasURIStart) SendToken(args[0]).Wait();

return URIStartResult.CLOSE;
}
else if (wasURIStart) // URI start on new instance, continue as normal but also handle current argument
{
// if we are running, we create a file lock with our process in it.
// Also attach the pid delete handler from Program.

result = URIStartResult.PARSE;
}

RegisterProtocol();

return result;
}

private static void RegisterProtocol()
{

// we really should query the user for this, but since Dialogs appear to be completely fucked, we're going
// to just install it right now.
var xdg_path = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
"applications");
var xdg_file = Path.Join(xdg_path, "aucapture-opener.desktop");

if (!File.Exists(xdg_file))
{
var executingassmb = System.Reflection.Assembly.GetExecutingAssembly().Location;
if (Path.HasExtension("dll"))
{
executingassmb = "dotnet " + executingassmb;
}

var xdg_file_write = new string[]
{
"[Desktop Entry]",
"Type=Application",
"Name=aucapture URI Handler",
$"Exec={executingassmb} %u",
"StartupNotify=false",
"MimeType=x-scheme-handler/aucapture;"
};

using (var file = File.CreateText(xdg_file))
{
foreach (string str in xdg_file_write)
{
file.WriteLine(str);
}
}

var xdg_posix = new UnixFileInfo(xdg_file);

xdg_posix.FileAccessPermissions = FileAccessPermissions.UserReadWriteExecute
| FileAccessPermissions.GroupRead
| FileAccessPermissions.GroupExecute
| FileAccessPermissions.OtherRead
| FileAccessPermissions.OtherExecute;

// Finally, register with xdg-mime.

var xdgproc = new Process()
{
StartInfo = new ProcessStartInfo
{
FileName = "/usr/bin/xdg-mime",
Arguments = $"default aucapture-opener.desktop x-scheme-handler/aucapture",
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true,
}
};

xdgproc.Start();
string result = xdgproc.StandardOutput.ReadToEnd();
xdgproc.WaitForExit();
}
}

public override async Task<bool> SendToken(string jsonText)
{
while (!_isListening)
{
Thread.Sleep(1000);
}

// Send the token via DBus.
using (Connection conn = new Connection(Address.Session))
{
await conn.ConnectAsync();

var obj = new IPCLink();
await conn.RegisterObjectAsync(obj);
await conn.RegisterServiceAsync("org.AmongUsCapture.ipc", ServiceRegistrationOptions.None);
Expand All @@ -92,7 +212,7 @@ public override void SendToken(string host, string connectCode)

public async override Task RegisterMinion()
{
Task.Factory.StartNew( async () =>
Task.Factory.StartNew(async () =>
{

using (_dbusconnection = new Connection(Address.Session))
Expand All @@ -113,7 +233,7 @@ public async override Task RegisterMinion()
}
}
});

}

public override void startWithToken(string uri)
Expand All @@ -124,18 +244,18 @@ public override void startWithToken(string uri)
public override bool Cancel()
{
if (!_cancellation.IsCancellationRequested)
{
{
_cancellation.Cancel();
return true;
}

return false;
}

private void RespondToDbus(string signalresponse)
{
Settings.conInterface.WriteModuleTextColored("DBus", Color.Silver,
$"Recieved new message on DBus: {signalresponse}");
$"Received new message on DBus: \"{signalresponse}\"");

signalresponse = signalresponse.Trim('\r', '\n');

Expand All @@ -144,5 +264,4 @@ private void RespondToDbus(string signalresponse)
OnTokenEvent(token);
}
}

}
5 changes: 4 additions & 1 deletion AmongUsCapture/Memory/ProcessMemoryLinux.cs
Original file line number Diff line number Diff line change
Expand Up @@ -296,9 +296,12 @@ public static class LinuxAPI
//
// https://man7.org/linux/man-pages/man2/process_vm_readv.2.html

[DllImport("libc.so.6", SetLastError = true)]
[DllImport("libc", SetLastError = true)]
public static extern int process_vm_readv(int pid, IntPtr local_iov, ulong liovcnt, IntPtr remote_iov,
ulong riovcnt, ulong flags);

[DllImport("libc", SetLastError = true)]
private static extern int chmod(string pathname, int mode);
}


Expand Down
44 changes: 38 additions & 6 deletions AmongUsCapture/Program.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Drawing;
using System.IO;
using System.IO.Pipes;
using System.Net.Sockets;
using System.Runtime.InteropServices;
Expand Down Expand Up @@ -34,6 +35,11 @@ private static void Main(string[] args)
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && Settings.PersistentSettings.debugConsole)
AllocConsole(); // needs to be the first call in the program to prevent weird bugs

if (!Directory.Exists(Settings.StorageLocation))
{
// Create Settings directory if it doesn't exist, as we need to stick our pidfile there.
Directory.CreateDirectory(Settings.StorageLocation);
}

URIStartResult uriRes = URIStartResult.CLOSE;
uriRes = IPCadapter.getInstance().HandleURIStart(args);
Expand Down Expand Up @@ -87,17 +93,17 @@ private static void OpenGUI()

window.DeleteEvent += (object o, DeleteEventArgs e) =>
{
// Make sure the pid file is deleted if the application quits.
CleanPid();
Application.Quit();
};

// Post a quick message to the console if we are using Linux, notifying the user that IPC links do not work.

Settings.conInterface.WriteModuleTextColored("Notification", Color.Red,
$"You are running amonguscapture under Linux. Discord capture links are not currently supported. Use the manual details in your DM instead.");

window.ShowAll();

Application.Run();

CleanPid();

Environment.Exit(0);
}

Expand All @@ -106,11 +112,37 @@ public static string GetExecutablePath()
return Process.GetCurrentProcess().MainModule.FileName;
}

private static void CleanPid()
{
// Make sure the pidfile is cleaned up if we have one.
var pidfile = Path.Join(Settings.StorageLocation, ".amonguscapture.pid");

if (File.Exists(pidfile))
{
int pid;
bool fileread;
using (var pidread = File.OpenText(Path.Join(Settings.StorageLocation, ".amonguscapture.pid")))
{
fileread = Int32.TryParse(pidread.ReadLine(), out pid);
}

if (!fileread)
{
// Bad read, file must be corrupt. Clear pidfile.
File.Delete(pidfile);
}

if (pid == Process.GetCurrentProcess().Id)
{
// This is our process. Delete file.
File.Delete(pidfile);
}
}
}

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool AllocConsole();


}
}
2 changes: 1 addition & 1 deletion AmongUsCapture/Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
},
"AmongUsCaptureIPC": {
"commandName": "Project",
"commandLineArgs": "aucapture://localhost:8123/3A9CD4A1?insecure"
"commandLineArgs": "aucapture://localhost:8123/E68A0AD9?insecure"
}
}
}
2 changes: 1 addition & 1 deletion AmongUsCapture/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace AmongUsCapture
{
public static class Settings
{
public static string StorageLocation = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "\\AmongUsCapture");
public static string StorageLocation = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "AmongUsCapture");

public static ConsoleInterface conInterface;

Expand Down
4 changes: 1 addition & 3 deletions AmongUsCapture/UserForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,7 @@ public UserForm(ClientSocket sock) : base("Among Us Capture - GTK")
GameMemReader.getInstance().ChatMessageAdded += OnChatMessageAdded;
GameMemReader.getInstance().JoinedLobby += OnJoinedLobby;
GameMemReader.getInstance().GameUnverified += _eventGameIsPirated;




// Load URL
_urlHostEntryField.Text = Settings.PersistentSettings.host;

Expand Down

0 comments on commit 622cbde

Please sign in to comment.