Herschrijf logica, voeg RPC-bouwoptie toe
This commit is contained in:
parent
94cc2a7512
commit
e0f0e6b05c
|
@ -11,5 +11,16 @@
|
||||||
"description": "Automatisch In-Uitschakelen Ober",
|
"description": "Automatisch In-Uitschakelen Ober",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"name": "mvoau",
|
"name": "mvoau",
|
||||||
"versions": []
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "WithoutRPC",
|
||||||
|
"targetType": "executable",
|
||||||
|
"versions": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "WithRPC",
|
||||||
|
"targetType": "executable",
|
||||||
|
"versions": ["WithRPC"]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
project(
|
project(
|
||||||
'MVOAU Ober', 'd',
|
'MVOAU Ober', 'd',
|
||||||
version: '1.0.0',
|
version: '1.0.0',
|
||||||
license: 'MIT',
|
license: 'MIT',
|
||||||
meson_version: '>= 0.52'
|
meson_version: '>= 0.52'
|
||||||
)
|
)
|
||||||
|
|
||||||
mvoau_ober_src_dir = include_directories('source/')
|
mvoau_ober_src_dir = include_directories('source/')
|
||||||
mvoau_ober_src = [
|
mvoau_ober_src = [
|
||||||
'source/msgpackrpc/client.d',
|
'source/msgpackrpc/client.d',
|
||||||
'source/msgpackrpc/package.d',
|
'source/msgpackrpc/package.d',
|
||||||
'source/msgpackrpc/protocol.d',
|
'source/msgpackrpc/protocol.d',
|
||||||
'source/msgpackrpc/server.d',
|
'source/msgpackrpc/server.d',
|
||||||
'source/app.d'
|
'source/app.d'
|
||||||
]
|
]
|
||||||
|
|
||||||
ddbus_dep = dependency('ddbus', version: '3.0.0')
|
ddbus_dep = dependency('ddbus', version: '3.0.0')
|
||||||
|
@ -21,26 +21,30 @@ vibe_core_dep = dependency('vibe-core', version: '>=1.13')
|
||||||
systemd_dep = dependency('systemd')
|
systemd_dep = dependency('systemd')
|
||||||
|
|
||||||
mvoau_ober_deps = [ddbus_dep, msgpack_d_dep, vibe_core_dep]
|
mvoau_ober_deps = [ddbus_dep, msgpack_d_dep, vibe_core_dep]
|
||||||
|
mvoau_ober_versions = []
|
||||||
|
|
||||||
executable('mvoau',
|
if get_option('RPC').enabled()
|
||||||
mvoau_ober_src,
|
mvoau_ober_versions += ['WithRPC']
|
||||||
include_directories: mvoau_ober_src_dir,
|
|
||||||
dependencies: [ddbus_dep,
|
|
||||||
msgpack_d_dep,
|
|
||||||
vibe_core_dep],
|
|
||||||
install: true)
|
|
||||||
|
|
||||||
if systemd_dep.found()
|
|
||||||
install_data('mvoau.service',
|
|
||||||
install_dir: systemd_dep.get_pkgconfig_variable('systemdsystemunitdir'))
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
dlang = import('dlang')
|
executable('mvoau',
|
||||||
dlang.generate_dub_file(meson.project_name().to_lower(), meson.source_root(),
|
mvoau_ober_src,
|
||||||
authors: 'Meson Team',
|
include_directories: mvoau_ober_src_dir,
|
||||||
copyright: 'Copyright © 2018, Meson Team',
|
dependencies: [ddbus_dep, msgpack_d_dep, vibe_core_dep],
|
||||||
license: meson.project_license(),
|
d_module_versions: mvoau_ober_versions,
|
||||||
sourceFiles: mvoau_ober_src,
|
install: true)
|
||||||
targetType: 'executable',
|
|
||||||
dependencies: mvoau_ober_deps
|
if systemd_dep.found()
|
||||||
)
|
install_data('mvoau.service',
|
||||||
|
install_dir: systemd_dep.get_pkgconfig_variable('systemdsystemunitdir'))
|
||||||
|
endif
|
||||||
|
|
||||||
|
# dlang = import('dlang')
|
||||||
|
#dlang.generate_dub_file(meson.project_name().to_lower(), meson.source_root(),
|
||||||
|
#authors: 'Meson Team',
|
||||||
|
#copyright: 'Copyright © 2018, Meson Team',
|
||||||
|
#license: meson.project_license(),
|
||||||
|
#sourceFiles: mvoau_ober_src,
|
||||||
|
#targetType: 'executable',
|
||||||
|
#dependencies: mvoau_ober_deps
|
||||||
|
#)
|
||||||
|
|
1
ober/meson_options.txt
Normal file
1
ober/meson_options.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
option('RPC', type : 'feature', value : 'disabled')
|
|
@ -10,7 +10,7 @@ import vibe.core.process;
|
||||||
|
|
||||||
import ddbus;
|
import ddbus;
|
||||||
import ddbus.c_lib;
|
import ddbus.c_lib;
|
||||||
import msgpackrpc;
|
version(WithRPC) import msgpackrpc;
|
||||||
|
|
||||||
string appName = "Automatisch In- en Uitschakelen Ober";
|
string appName = "Automatisch In- en Uitschakelen Ober";
|
||||||
|
|
||||||
|
@ -21,11 +21,26 @@ extern (C) void close(int fileNo);
|
||||||
*/
|
*/
|
||||||
struct Toep {
|
struct Toep {
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* Tijd die tussen het schakelen van GebruikerActief -> SpelerActief en SpelerActief -> Uit
|
||||||
|
* moet zitten.
|
||||||
|
*/
|
||||||
immutable float m_waitingTime;
|
immutable float m_waitingTime;
|
||||||
|
/// Aantal keer dat moet worden gecontroleerd of er een gebruiker actief is.
|
||||||
immutable int CHECK_COUNT = 4;
|
immutable int CHECK_COUNT = 4;
|
||||||
Connection m_dbusCon;
|
Connection m_dbusCon;
|
||||||
bool m_keepRunning = true;
|
bool m_keepRunning = true;
|
||||||
|
|
||||||
|
enum Staat {
|
||||||
|
Inactief,
|
||||||
|
/// Een (Unix-)gebruiker is actief op het rekentuig
|
||||||
|
GebruikersActief,
|
||||||
|
/// Een speler is actief op de mijnvervaardigingsober
|
||||||
|
SpelersActief,
|
||||||
|
/// Het rekentuig moet uit
|
||||||
|
Uit
|
||||||
|
}
|
||||||
|
|
||||||
this(float waitingTime) {
|
this(float waitingTime) {
|
||||||
this.m_waitingTime = waitingTime / CHECK_COUNT;
|
this.m_waitingTime = waitingTime / CHECK_COUNT;
|
||||||
this.m_dbusCon = connectToBus(DBusBusType.DBUS_BUS_SYSTEM);
|
this.m_dbusCon = connectToBus(DBusBusType.DBUS_BUS_SYSTEM);
|
||||||
|
@ -43,22 +58,28 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Voer de toepassing uit en treed de gebeurtenissenlus binnen.
|
||||||
|
*
|
||||||
|
* return: Afsluitcode die geretourneerd moet worden binnen main()
|
||||||
|
*/
|
||||||
int exec() {
|
int exec() {
|
||||||
info ("Moet blokkeren:", moetBlokkeren());
|
info ("Gebruikers actief:", gebruikersActief());
|
||||||
info ("Kan afsluiten:", kanAfsluiten());
|
info ("Spelers actief:", spelersActief());
|
||||||
version(WithRPC) {
|
version(WithRPC) {
|
||||||
TCPConnection conn = connectTCP(m_clientAddress, PORT);
|
TCPConnection conn = connectTCP(m_clientAddress, PORT);
|
||||||
Duration sleepTime = 500.msecs;
|
Duration sleepTime = 500.msecs;
|
||||||
while(!conn) {
|
while(!conn) {
|
||||||
infof("Not connected, trying again in %s", sleepTime);
|
infof("Niet verbonden, opnieuw proberen in %s", sleepTime);
|
||||||
sleep(sleepTime);
|
sleep(sleepTime);
|
||||||
conn = connectTCP(m_clientAddress, PORT);
|
conn = connectTCP(m_clientAddress, PORT);
|
||||||
}
|
}
|
||||||
info("Connected!");
|
info("Verbonden!");
|
||||||
m_client = new Client(conn);
|
m_client = new Client(conn);
|
||||||
writeln("Receive response: '", m_client.call!(string)("GetBootReason"), "'");
|
writeln("Antwoord ontvangen: '", m_client.call!(string)("GetBootReason"), "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start de D-Bus-gebeurtenissenlus.
|
||||||
runTask({
|
runTask({
|
||||||
import vibe.core.core : yield;
|
import vibe.core.core : yield;
|
||||||
while(m_dbusCon.tick() && m_keepRunning) {
|
while(m_dbusCon.tick() && m_keepRunning) {
|
||||||
|
@ -66,12 +87,13 @@ public:
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Start de gebeurtenissenlus voor de hoofdlogica.
|
||||||
auto taak = runTask({
|
auto taak = runTask({
|
||||||
FileDescriptor inhibitLock = FileDescriptor.none;
|
FileDescriptor inhibitLock = FileDescriptor.none;
|
||||||
version(WithRPC) {
|
/+version(WithRPC) {
|
||||||
FileDescriptor sleepLock = FileDescriptor.none;
|
FileDescriptor sleepLock = FileDescriptor.none;
|
||||||
FileDescriptor shutdownLock = FileDescriptor.none;
|
FileDescriptor shutdownLock = FileDescriptor.none;
|
||||||
}
|
}+/
|
||||||
|
|
||||||
// Get interfaces
|
// Get interfaces
|
||||||
BusName loginBus = busName("org.freedesktop.login1");
|
BusName loginBus = busName("org.freedesktop.login1");
|
||||||
|
@ -80,6 +102,7 @@ public:
|
||||||
PathIface loginManager = new PathIface(m_dbusCon, loginBus, loginPath, loginIFace);
|
PathIface loginManager = new PathIface(m_dbusCon, loginBus, loginPath, loginIFace);
|
||||||
PathIface loginManagerProps = new PathIface(m_dbusCon, loginBus, loginPath, interfaceName("org.freedesktop.DBus.Properties"));
|
PathIface loginManagerProps = new PathIface(m_dbusCon, loginBus, loginPath, interfaceName("org.freedesktop.DBus.Properties"));
|
||||||
|
|
||||||
|
/// Laat een slot los.
|
||||||
void releaseLock(ref FileDescriptor fd) {
|
void releaseLock(ref FileDescriptor fd) {
|
||||||
if (fd != FileDescriptor.none) {
|
if (fd != FileDescriptor.none) {
|
||||||
close(cast(int) fd);
|
close(cast(int) fd);
|
||||||
|
@ -87,18 +110,10 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
version(WithRPC) {
|
version(WithRPC) {
|
||||||
// Register signal listeners
|
// Register signal listeners
|
||||||
// FIXME: this does not work yet.
|
// FIXME: this does not work yet.
|
||||||
MessageRouter router = new MessageRouter();
|
/+MessageRouter router = new MessageRouter();
|
||||||
MessagePattern sleepPattern = MessagePattern(loginPath, loginIFace, "PrepareForSleep", true);
|
MessagePattern sleepPattern = MessagePattern(loginPath, loginIFace, "PrepareForSleep", true);
|
||||||
MessagePattern shutdownPattern = MessagePattern(loginPath, loginIFace, "PrepareForShutdown", true);
|
MessagePattern shutdownPattern = MessagePattern(loginPath, loginIFace, "PrepareForShutdown", true);
|
||||||
router.setHandler!(void, bool)(sleepPattern, (bool active) {
|
router.setHandler!(void, bool)(sleepPattern, (bool active) {
|
||||||
|
@ -124,13 +139,13 @@ public:
|
||||||
sleepLock = loginManager.Inhibit("sleep", appName, "Systeem op de hoogte brengen dat de ober gaat slapen",
|
sleepLock = loginManager.Inhibit("sleep", appName, "Systeem op de hoogte brengen dat de ober gaat slapen",
|
||||||
"delay").to!FileDescriptor;
|
"delay").to!FileDescriptor;
|
||||||
shutdownLock = loginManager.Inhibit("shutdown", appName, "Systeem op de hoogte brengen dat de ober gaat sluiten",
|
shutdownLock = loginManager.Inhibit("shutdown", appName, "Systeem op de hoogte brengen dat de ober gaat sluiten",
|
||||||
"delay").to!FileDescriptor;
|
"delay").to!FileDescriptor;+/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void block() {
|
void blokkeerAfsluiten() {
|
||||||
if (inhibitLock != FileDescriptor.none) return;
|
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");
|
Message mesg = loginManager.Inhibit("shutdown:sleep:idle:handle-suspend-key", appName, "Er zijn spelers op de ober", "block");
|
||||||
inhibitLock = mesg.to!FileDescriptor;
|
inhibitLock = mesg.to!FileDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,90 +154,97 @@ public:
|
||||||
// Als we om een of andere redenen deze functie verlaten, laat het slot los!
|
// Als we om een of andere redenen deze functie verlaten, laat het slot los!
|
||||||
releaseLock(inhibitLock);
|
releaseLock(inhibitLock);
|
||||||
version(WithRPC) {
|
version(WithRPC) {
|
||||||
releaseLock(sleepLock);
|
/+releaseLock(sleepLock);
|
||||||
releaseLock(shutdownLock);
|
releaseLock(shutdownLock);+/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int checkCount = CHECK_COUNT;
|
// Teller die bijhoudt wanneer we bepaalde van bepaalde staten mogen wisselen.
|
||||||
int afsluitNakijkTeller = CHECK_COUNT;
|
Staat staat = Staat.Inactief;
|
||||||
|
int teller = CHECK_COUNT;
|
||||||
void werkAfsluitNakijkTellerBij() {
|
|
||||||
if (kanAfsluiten()) {
|
|
||||||
afsluitNakijkTeller--;
|
|
||||||
} else {
|
|
||||||
afsluitNakijkTeller = CHECK_COUNT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while(m_keepRunning) {
|
while(m_keepRunning) {
|
||||||
|
Staat oudeStaat = staat;
|
||||||
sleep(seconds(cast(long) (m_waitingTime * 60)));
|
sleep(seconds(cast(long) (m_waitingTime * 60)));
|
||||||
// Check if we are already preventing shutdown
|
// Staattransities die vanuit elke staat kunnen plaatsvinden.
|
||||||
if (inhibitLock != FileDescriptor.none) {
|
if (spelersActief()) {
|
||||||
// We zijn op dit moment het afsluiten niet aan het blokkeren. Kijken of dat wel moet.
|
staat = Staat.SpelersActief;
|
||||||
if (moetBlokkeren()) {
|
}
|
||||||
if (checkCount == 1) {
|
final switch(staat) {
|
||||||
// Laat het slot los
|
case Staat.Inactief:
|
||||||
releaseLock(inhibitLock);
|
if (spelersActief()) {
|
||||||
info("Afsluitslot losgelaten.");
|
staat = Staat.SpelersActief;
|
||||||
} else {
|
teller = 3;
|
||||||
// Kijk nog 1 of meer maal
|
} else if (gebruikersActief) {
|
||||||
checkCount--;
|
staat = Staat.GebruikersActief;
|
||||||
tracef("Nog %d maal kijken of we het afsluitslot los kunnen laten", checkCount);
|
teller = 3;
|
||||||
}
|
} else if (--teller <= 0) {
|
||||||
} else {
|
sluitAf();
|
||||||
// We kunnen niet afsluiten. De nakijkteller herstellen.
|
staat = Staat.Uit;
|
||||||
checkCount = CHECK_COUNT;
|
|
||||||
afsluitNakijkTeller = CHECK_COUNT;
|
|
||||||
tracef("Spelers zijn nog steeds actief. NIet afsluiten.");
|
|
||||||
}
|
}
|
||||||
werkAfsluitNakijkTellerBij();
|
break;
|
||||||
} else if (moetBlokkeren()) {
|
case Staat.GebruikersActief:
|
||||||
|
if (spelersActief()) {
|
||||||
|
teller = 3;
|
||||||
|
staat = Staat.SpelersActief;
|
||||||
|
} else if (gebruikersActief()) {
|
||||||
|
teller = 3;
|
||||||
|
} else if (--teller <= 0) {
|
||||||
|
staat = Staat.Uit;
|
||||||
|
sluitAf();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Staat.SpelersActief:
|
||||||
try {
|
try {
|
||||||
block();
|
blokkeerAfsluiten();
|
||||||
info("Afsluitslot verkregen.");
|
|
||||||
} catch(DBusException e) {
|
} catch(DBusException e) {
|
||||||
warning("Kon afsluitslot niet verkrijgen: ", e);
|
warning("Kon afsluitslot niet verkrijgen: ", e);
|
||||||
}
|
}
|
||||||
werkAfsluitNakijkTellerBij();
|
if (spelersActief()) {
|
||||||
} else if (kanAfsluiten()){
|
teller = 3;
|
||||||
if (afsluitNakijkTeller <= 1) {
|
} else if (--teller <= 0) {
|
||||||
trace("We kunnen afsluiten!");
|
releaseLock(inhibitLock);
|
||||||
execute(["shutdown", "+1", "Systeem gaat afsluiten vanwege inactiviteit"]);
|
staat = Staat.GebruikersActief;
|
||||||
m_keepRunning = false;
|
teller = 3;
|
||||||
exitEventLoop();
|
|
||||||
} else {
|
|
||||||
afsluitNakijkTeller--;
|
|
||||||
tracef("Nog %s keer, dan kunnen we afsluiten!", afsluitNakijkTeller);
|
|
||||||
}
|
}
|
||||||
} else {
|
break;
|
||||||
afsluitNakijkTeller = CHECK_COUNT;
|
case Staat.Uit:
|
||||||
trace("Niets om te doen.");
|
info("We gaan dit programma afsluiten");
|
||||||
|
m_keepRunning = false;
|
||||||
|
exitEventLoop();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
tracef("Oude -> nieuwe staat: %s -> %s (teller: %d)", oudeStaat, staat, teller);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
int exitCode = runEventLoop();
|
int exitCode = runEventLoop();
|
||||||
// cleanup
|
// Rommel opruimen
|
||||||
info("Rotzooi opruimen.");
|
info("Rommel opruimen.");
|
||||||
return exitCode;
|
return exitCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kijkt of we het afsluiten moeten blokkeren
|
* Kijkt of we het afsluiten moeten blokkeren, oftewel, of we naar de SpelerActief-staat moeten.
|
||||||
*/
|
*/
|
||||||
bool moetBlokkeren() {
|
bool spelersActief() {
|
||||||
|
// Kijk of er verbindingen actief zijn naar poort ":minecraft"
|
||||||
auto resultaat = execute(["ss", "-H", "--query=tcp", "state", "established", "sport", "=", ":minecraft"]);
|
auto resultaat = execute(["ss", "-H", "--query=tcp", "state", "established", "sport", "=", ":minecraft"]);
|
||||||
return resultaat.output.splitLines().length != 0;
|
return resultaat.output.splitLines().length != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kijkt of we direct af kunnen sluiten.
|
* Kijkt of we direct af kunnen sluiten, oftewel dat we naar de Uit-staat mogen.
|
||||||
*/
|
*/
|
||||||
bool kanAfsluiten() {
|
bool gebruikersActief() {
|
||||||
auto resultaat = execute(["who"]);
|
auto resultaat = execute(["who"]);
|
||||||
return resultaat.output.splitLines().length == 0;
|
return resultaat.output.splitLines().length == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sluitAf() {
|
||||||
|
version(WithRPC) m_client.notify("NotifyShutdown");
|
||||||
|
execute(["shutdown", "+1", "Systeem gaat afsluiten vanwege inactiviteit"]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
module msgpackrpc.client;
|
module msgpackrpc.client;
|
||||||
|
|
||||||
|
version(WithRPC) {
|
||||||
import core.atomic;
|
import core.atomic;
|
||||||
|
|
||||||
import std.array;
|
import std.array;
|
||||||
|
@ -133,3 +135,5 @@ private:
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // version(WithRPC)
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
module msgpackrpc;
|
module msgpackrpc;
|
||||||
|
|
||||||
|
version(WithRPC) {
|
||||||
public import msgpackrpc.client;
|
public import msgpackrpc.client;
|
||||||
public import msgpackrpc.server;
|
public import msgpackrpc.server;
|
||||||
|
|
||||||
|
} // version(WithRPC)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
module msgpackrpc.protocol;
|
module msgpackrpc.protocol;
|
||||||
|
|
||||||
|
version(WithRPC) {
|
||||||
import std.exception;
|
import std.exception;
|
||||||
|
|
||||||
import msgpack;
|
import msgpack;
|
||||||
|
@ -32,3 +33,5 @@ public:
|
||||||
@property Value value() { return m_value; }
|
@property Value value() { return m_value; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // version(WithRPC)
|
||||||
|
|
|
@ -1 +1,4 @@
|
||||||
module msgpackrpc.server;
|
module msgpackrpc.server;
|
||||||
|
version(WithRPC) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue