2021-01-22 18:06:44 +00:00
|
|
|
import std.conv;
|
|
|
|
import std.datetime;
|
|
|
|
import std.experimental.logger;
|
|
|
|
import std.stdio;
|
|
|
|
import std.string;
|
|
|
|
|
|
|
|
import vibe.core.core;
|
|
|
|
import vibe.core.net;
|
|
|
|
import vibe.core.process;
|
|
|
|
|
|
|
|
import ddbus;
|
|
|
|
import ddbus.c_lib;
|
|
|
|
import msgpackrpc;
|
|
|
|
|
|
|
|
string appName = "Automatisch In- en Uitschakelen Ober";
|
|
|
|
|
|
|
|
extern (C) void close(int fileNo);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Represententeerd de toepassing
|
|
|
|
*/
|
|
|
|
struct Toep {
|
|
|
|
public:
|
2021-03-02 01:28:48 +00:00
|
|
|
immutable float m_waitingTime;
|
|
|
|
immutable int CHECK_COUNT = 4;
|
2021-01-22 18:06:44 +00:00
|
|
|
Connection m_dbusCon;
|
|
|
|
bool m_keepRunning = true;
|
2021-03-02 01:28:48 +00:00
|
|
|
|
|
|
|
this(float waitingTime) {
|
|
|
|
this.m_waitingTime = waitingTime / CHECK_COUNT;
|
2021-01-22 18:06:44 +00:00
|
|
|
this.m_dbusCon = connectToBus(DBusBusType.DBUS_BUS_SYSTEM);
|
|
|
|
}
|
|
|
|
|
2021-03-02 01:28:48 +00:00
|
|
|
version(WithRPC) {
|
|
|
|
Client m_client;
|
|
|
|
immutable string m_clientAddress;
|
|
|
|
immutable ushort PORT = 18_002;
|
|
|
|
|
|
|
|
this(float waitingTime, string clientAddress) {
|
|
|
|
this.m_waitingTime = waitingTime / CHECK_COUNT;
|
|
|
|
this.m_clientAddress = clientAddress;
|
|
|
|
this.m_dbusCon = connectToBus(DBusBusType.DBUS_BUS_SYSTEM);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-22 18:06:44 +00:00
|
|
|
int exec() {
|
2021-03-02 01:28:48 +00:00
|
|
|
info ("Moet blokkeren:", moetBlokkeren());
|
|
|
|
info ("Kan afsluiten:", kanAfsluiten());
|
2021-01-22 18:06:44 +00:00
|
|
|
version(WithRPC) {
|
|
|
|
TCPConnection conn = connectTCP(m_clientAddress, PORT);
|
|
|
|
Duration sleepTime = 500.msecs;
|
|
|
|
while(!conn) {
|
|
|
|
infof("Not connected, trying again in %s", sleepTime);
|
|
|
|
sleep(sleepTime);
|
|
|
|
conn = connectTCP(m_clientAddress, PORT);
|
|
|
|
}
|
|
|
|
info("Connected!");
|
|
|
|
m_client = new Client(conn);
|
|
|
|
writeln("Receive response: '", m_client.call!(string)("GetBootReason"), "'");
|
|
|
|
}
|
|
|
|
|
|
|
|
runTask({
|
|
|
|
import vibe.core.core : yield;
|
|
|
|
while(m_dbusCon.tick() && m_keepRunning) {
|
|
|
|
yield();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-03-02 01:28:48 +00:00
|
|
|
auto taak = runTask({
|
2021-01-22 18:06:44 +00:00
|
|
|
FileDescriptor inhibitLock = FileDescriptor.none;
|
|
|
|
version(WithRPC) {
|
|
|
|
FileDescriptor sleepLock = FileDescriptor.none;
|
|
|
|
FileDescriptor shutdownLock = FileDescriptor.none;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get interfaces
|
|
|
|
BusName loginBus = busName("org.freedesktop.login1");
|
|
|
|
ObjectPath loginPath = ObjectPath("/org/freedesktop/login1");
|
|
|
|
InterfaceName loginIFace = interfaceName("org.freedesktop.login1.Manager");
|
|
|
|
PathIface loginManager = new PathIface(m_dbusCon, loginBus, loginPath, loginIFace);
|
|
|
|
PathIface loginManagerProps = new PathIface(m_dbusCon, loginBus, loginPath, interfaceName("org.freedesktop.DBus.Properties"));
|
|
|
|
|
|
|
|
void releaseLock(ref FileDescriptor fd) {
|
|
|
|
if (fd != FileDescriptor.none) {
|
|
|
|
close(cast(int) fd);
|
|
|
|
fd = FileDescriptor.none;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-02 00:31:17 +00:00
|
|
|
MessageRouter testRouter = new MessageRouter();
|
|
|
|
MessagePattern desktopChangePattern = MessagePattern(ObjectPath("/VirtualDesktopManager"), interfaceName("org.kde.KWin.VirtualDesktopManager"), "currentChanged", true);
|
|
|
|
dbus_bus_add_match(m_dbusCon.conn, "type='signal',sender='org.kde.KWin',interface='org.kde.KWin.VirtualDesktopManager,path='/VirtualDesktopManager',member='currentChanged'", null);
|
|
|
|
testRouter.setHandler!(void, string)(desktopChangePattern, (string id) {
|
|
|
|
logf("Desktop changed: %s", id);
|
|
|
|
});
|
|
|
|
registerRouter(m_dbusCon, testRouter);
|
|
|
|
|
2021-01-22 18:06:44 +00:00
|
|
|
version(WithRPC) {
|
|
|
|
// Register signal listeners
|
|
|
|
// FIXME: this does not work yet.
|
|
|
|
MessageRouter router = new MessageRouter();
|
|
|
|
MessagePattern sleepPattern = MessagePattern(loginPath, loginIFace, "PrepareForSleep", true);
|
|
|
|
MessagePattern shutdownPattern = MessagePattern(loginPath, loginIFace, "PrepareForShutdown", true);
|
|
|
|
router.setHandler!(void, bool)(sleepPattern, (bool active) {
|
|
|
|
logf("Preparing for sleep: %b", active);
|
|
|
|
if (active) {
|
|
|
|
m_client.notify("NotifySleep");
|
|
|
|
releaseLock(sleepLock);
|
|
|
|
} else {
|
|
|
|
m_client.notify("NotifyWakeup");
|
|
|
|
sleepLock = loginManager.Inhibit("sleep", appName, "Systeem op de hoogte brengen dat de ober gaat slapen", "delay").to!FileDescriptor;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
router.setHandler!(void, bool)(shutdownPattern, (bool active) {
|
|
|
|
logf("Preparing for shutdown: %b", active);
|
|
|
|
if (active) {
|
|
|
|
m_client.notify("NotifyShutdown");
|
|
|
|
releaseLock(shutdownLock);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
registerRouter(m_dbusCon, router);
|
|
|
|
|
|
|
|
// Take the sleep lock
|
|
|
|
sleepLock = loginManager.Inhibit("sleep", appName, "Systeem op de hoogte brengen dat de ober gaat slapen",
|
|
|
|
"delay").to!FileDescriptor;
|
|
|
|
shutdownLock = loginManager.Inhibit("shutdown", appName, "Systeem op de hoogte brengen dat de ober gaat sluiten",
|
|
|
|
"delay").to!FileDescriptor;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void block() {
|
|
|
|
if (inhibitLock != FileDescriptor.none) return;
|
|
|
|
Message mesg = loginManager.Inhibit("shutdown:sleep:idle:handle-suspend-key:handle-power-key", appName, "Er zijn spelers op de server", "block");
|
|
|
|
inhibitLock = mesg.to!FileDescriptor;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
scope (exit) {
|
|
|
|
// Als we om een of andere redenen deze functie verlaten, laat het slot los!
|
|
|
|
releaseLock(inhibitLock);
|
2021-03-02 00:31:17 +00:00
|
|
|
version(WithRPC) {
|
|
|
|
releaseLock(sleepLock);
|
|
|
|
releaseLock(shutdownLock);
|
|
|
|
}
|
2021-01-22 18:06:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int checkCount = CHECK_COUNT;
|
2021-03-02 01:28:48 +00:00
|
|
|
int afsluitNakijkTeller = CHECK_COUNT;
|
|
|
|
|
|
|
|
void werkAfsluitNakijkTellerBij() {
|
|
|
|
if (kanAfsluiten()) {
|
|
|
|
afsluitNakijkTeller--;
|
|
|
|
} else {
|
|
|
|
afsluitNakijkTeller = CHECK_COUNT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-22 18:06:44 +00:00
|
|
|
while(m_keepRunning) {
|
2021-03-02 01:28:48 +00:00
|
|
|
sleep(seconds(cast(long) (m_waitingTime * 60)));
|
2021-01-22 18:06:44 +00:00
|
|
|
// Check if we are already preventing shutdown
|
|
|
|
if (inhibitLock != FileDescriptor.none) {
|
2021-03-02 01:28:48 +00:00
|
|
|
// We zijn op dit moment het afsluiten niet aan het blokkeren. Kijken of dat wel moet.
|
|
|
|
if (moetBlokkeren()) {
|
2021-01-22 18:06:44 +00:00
|
|
|
if (checkCount == 1) {
|
2021-03-02 01:28:48 +00:00
|
|
|
// Laat het slot los
|
2021-01-22 18:06:44 +00:00
|
|
|
releaseLock(inhibitLock);
|
2021-03-02 01:28:48 +00:00
|
|
|
info("Afsluitslot losgelaten.");
|
2021-01-22 18:06:44 +00:00
|
|
|
} else {
|
2021-03-02 01:28:48 +00:00
|
|
|
// Kijk nog 1 of meer maal
|
2021-01-22 18:06:44 +00:00
|
|
|
checkCount--;
|
2021-03-02 01:28:48 +00:00
|
|
|
tracef("Nog %d maal kijken of we het afsluitslot los kunnen laten", checkCount);
|
2021-01-22 18:06:44 +00:00
|
|
|
}
|
|
|
|
} else {
|
2021-03-02 01:28:48 +00:00
|
|
|
// We kunnen niet afsluiten. De nakijkteller herstellen.
|
2021-01-22 18:06:44 +00:00
|
|
|
checkCount = CHECK_COUNT;
|
2021-03-02 01:28:48 +00:00
|
|
|
afsluitNakijkTeller = CHECK_COUNT;
|
|
|
|
tracef("Spelers zijn nog steeds actief. NIet afsluiten.");
|
2021-01-22 18:06:44 +00:00
|
|
|
}
|
2021-03-02 01:28:48 +00:00
|
|
|
werkAfsluitNakijkTellerBij();
|
|
|
|
} else if (moetBlokkeren()) {
|
2021-01-22 18:06:44 +00:00
|
|
|
try {
|
|
|
|
block();
|
2021-03-02 01:28:48 +00:00
|
|
|
info("Afsluitslot verkregen.");
|
2021-01-22 18:06:44 +00:00
|
|
|
} catch(DBusException e) {
|
2021-03-02 01:28:48 +00:00
|
|
|
warning("Kon afsluitslot niet verkrijgen: ", e);
|
|
|
|
}
|
|
|
|
werkAfsluitNakijkTellerBij();
|
|
|
|
} else if (kanAfsluiten()){
|
|
|
|
if (afsluitNakijkTeller <= 1) {
|
|
|
|
trace("We kunnen afsluiten!");
|
|
|
|
execute(["shutdown", "+1", "Systeem gaat afsluiten vanwege inactiviteit"]);
|
|
|
|
m_keepRunning = false;
|
|
|
|
exitEventLoop();
|
|
|
|
} else {
|
|
|
|
afsluitNakijkTeller--;
|
|
|
|
tracef("Nog %s keer, dan kunnen we afsluiten!", afsluitNakijkTeller);
|
2021-01-22 18:06:44 +00:00
|
|
|
}
|
|
|
|
} else {
|
2021-03-02 01:28:48 +00:00
|
|
|
afsluitNakijkTeller = CHECK_COUNT;
|
|
|
|
trace("Niets om te doen.");
|
2021-01-22 18:06:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
int exitCode = runEventLoop();
|
|
|
|
// cleanup
|
2021-03-02 01:28:48 +00:00
|
|
|
info("Rotzooi opruimen.");
|
2021-01-22 18:06:44 +00:00
|
|
|
return exitCode;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2021-03-02 01:28:48 +00:00
|
|
|
* Kijkt of we het afsluiten moeten blokkeren
|
|
|
|
*/
|
|
|
|
bool moetBlokkeren() {
|
|
|
|
auto resultaat = execute(["ss", "-H", "--query=tcp", "state", "established", "sport", "=", ":minecraft"]);
|
|
|
|
return resultaat.output.splitLines().length != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Kijkt of we direct af kunnen sluiten.
|
2021-01-22 18:06:44 +00:00
|
|
|
*/
|
2021-03-02 01:28:48 +00:00
|
|
|
bool kanAfsluiten() {
|
|
|
|
auto resultaat = execute(["who"]);
|
2021-03-02 17:22:54 +00:00
|
|
|
return resultaat.output.splitLines().length == 0;
|
2021-01-22 18:06:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int main(string[] args) {
|
2021-03-02 01:28:48 +00:00
|
|
|
version(WithRPC) {
|
|
|
|
scope(failure) stderr.writefln("GEBRUIK: %s WACHTTIJD KLANTADRES", args[0]);
|
|
|
|
if (args.length < 3) {
|
|
|
|
stderr.writefln("GEBRUIK: %s WACHTTIJD KLANTADRES", args[0]);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
scope(failure) stderr.writefln("GEBRUIK: %s WACHTTIJD", args[0]);
|
|
|
|
if (args.length < 2) {
|
|
|
|
stderr.writefln("GEBRUIK: %s WACHTTIJD", args[0]);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
float waitingTime = to!float(args[1]);
|
|
|
|
version(WithRPC) {
|
|
|
|
return Toep(waitingTime, args[2]).exec();
|
|
|
|
} else {
|
|
|
|
return Toep(waitingTime).exec();
|
2021-01-22 18:06:44 +00:00
|
|
|
}
|
|
|
|
}
|