diff --git a/ober/dub.json b/ober/dub.json index 0b52e3b..9215bd4 100644 --- a/ober/dub.json +++ b/ober/dub.json @@ -11,5 +11,16 @@ "description": "Automatisch In-Uitschakelen Ober", "license": "MIT", "name": "mvoau", - "versions": [] + "configurations": [ + { + "name": "WithoutRPC", + "targetType": "executable", + "versions": [] + }, + { + "name": "WithRPC", + "targetType": "executable", + "versions": ["WithRPC"] + } + ] } diff --git a/ober/meson.build b/ober/meson.build index f6a5d34..aa30b1c 100644 --- a/ober/meson.build +++ b/ober/meson.build @@ -1,17 +1,17 @@ project( - 'MVOAU Ober', 'd', - version: '1.0.0', - license: 'MIT', - meson_version: '>= 0.52' + 'MVOAU Ober', 'd', + version: '1.0.0', + license: 'MIT', + meson_version: '>= 0.52' ) mvoau_ober_src_dir = include_directories('source/') mvoau_ober_src = [ - 'source/msgpackrpc/client.d', - 'source/msgpackrpc/package.d', - 'source/msgpackrpc/protocol.d', - 'source/msgpackrpc/server.d', - 'source/app.d' + 'source/msgpackrpc/client.d', + 'source/msgpackrpc/package.d', + 'source/msgpackrpc/protocol.d', + 'source/msgpackrpc/server.d', + 'source/app.d' ] 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') mvoau_ober_deps = [ddbus_dep, msgpack_d_dep, vibe_core_dep] +mvoau_ober_versions = [] -executable('mvoau', - mvoau_ober_src, - 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')) +if get_option('RPC').enabled() + mvoau_ober_versions += ['WithRPC'] 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 -) +executable('mvoau', + mvoau_ober_src, + include_directories: mvoau_ober_src_dir, + dependencies: [ddbus_dep, msgpack_d_dep, vibe_core_dep], + d_module_versions: mvoau_ober_versions, + install: true) + +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 +#) diff --git a/ober/meson_options.txt b/ober/meson_options.txt new file mode 100644 index 0000000..5259aa5 --- /dev/null +++ b/ober/meson_options.txt @@ -0,0 +1 @@ +option('RPC', type : 'feature', value : 'disabled') diff --git a/ober/source/app.d b/ober/source/app.d index d7a1599..ae26ccf 100644 --- a/ober/source/app.d +++ b/ober/source/app.d @@ -10,7 +10,7 @@ import vibe.core.process; import ddbus; import ddbus.c_lib; -import msgpackrpc; +version(WithRPC) import msgpackrpc; string appName = "Automatisch In- en Uitschakelen Ober"; @@ -21,10 +21,25 @@ extern (C) void close(int fileNo); */ struct Toep { public: + /** + * Tijd die tussen het schakelen van GebruikerActief -> SpelerActief en SpelerActief -> Uit + * moet zitten. + */ immutable float m_waitingTime; + /// Aantal keer dat moet worden gecontroleerd of er een gebruiker actief is. immutable int CHECK_COUNT = 4; Connection m_dbusCon; 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.m_waitingTime = waitingTime / CHECK_COUNT; @@ -43,22 +58,28 @@ public: } } + /** + * Voer de toepassing uit en treed de gebeurtenissenlus binnen. + * + * return: Afsluitcode die geretourneerd moet worden binnen main() + */ int exec() { - info ("Moet blokkeren:", moetBlokkeren()); - info ("Kan afsluiten:", kanAfsluiten()); + info ("Gebruikers actief:", gebruikersActief()); + info ("Spelers actief:", spelersActief()); version(WithRPC) { TCPConnection conn = connectTCP(m_clientAddress, PORT); Duration sleepTime = 500.msecs; while(!conn) { - infof("Not connected, trying again in %s", sleepTime); + infof("Niet verbonden, opnieuw proberen in %s", sleepTime); sleep(sleepTime); conn = connectTCP(m_clientAddress, PORT); } - info("Connected!"); + info("Verbonden!"); 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({ import vibe.core.core : yield; while(m_dbusCon.tick() && m_keepRunning) { @@ -66,12 +87,13 @@ public: } }); + // Start de gebeurtenissenlus voor de hoofdlogica. auto taak = runTask({ FileDescriptor inhibitLock = FileDescriptor.none; - version(WithRPC) { + /+version(WithRPC) { FileDescriptor sleepLock = FileDescriptor.none; FileDescriptor shutdownLock = FileDescriptor.none; - } + }+/ // Get interfaces BusName loginBus = busName("org.freedesktop.login1"); @@ -80,6 +102,7 @@ public: PathIface loginManager = new PathIface(m_dbusCon, loginBus, loginPath, loginIFace); PathIface loginManagerProps = new PathIface(m_dbusCon, loginBus, loginPath, interfaceName("org.freedesktop.DBus.Properties")); + /// Laat een slot los. void releaseLock(ref FileDescriptor fd) { if (fd != FileDescriptor.none) { 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) { // Register signal listeners // FIXME: this does not work yet. - MessageRouter router = new MessageRouter(); + /+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) { @@ -124,13 +139,13 @@ public: 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; + "delay").to!FileDescriptor;+/ } - void block() { + void blokkeerAfsluiten() { 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; } @@ -139,90 +154,97 @@ public: // Als we om een of andere redenen deze functie verlaten, laat het slot los! releaseLock(inhibitLock); version(WithRPC) { - releaseLock(sleepLock); - releaseLock(shutdownLock); + /+releaseLock(sleepLock); + releaseLock(shutdownLock);+/ } } - int checkCount = CHECK_COUNT; - int afsluitNakijkTeller = CHECK_COUNT; - - void werkAfsluitNakijkTellerBij() { - if (kanAfsluiten()) { - afsluitNakijkTeller--; - } else { - afsluitNakijkTeller = CHECK_COUNT; - } - } - + // Teller die bijhoudt wanneer we bepaalde van bepaalde staten mogen wisselen. + Staat staat = Staat.Inactief; + int teller = CHECK_COUNT; + while(m_keepRunning) { + Staat oudeStaat = staat; sleep(seconds(cast(long) (m_waitingTime * 60))); - // Check if we are already preventing shutdown - if (inhibitLock != FileDescriptor.none) { - // We zijn op dit moment het afsluiten niet aan het blokkeren. Kijken of dat wel moet. - if (moetBlokkeren()) { - if (checkCount == 1) { - // Laat het slot los - releaseLock(inhibitLock); - info("Afsluitslot losgelaten."); - } else { - // Kijk nog 1 of meer maal - checkCount--; - tracef("Nog %d maal kijken of we het afsluitslot los kunnen laten", checkCount); - } - } else { - // We kunnen niet afsluiten. De nakijkteller herstellen. - checkCount = CHECK_COUNT; - afsluitNakijkTeller = CHECK_COUNT; - tracef("Spelers zijn nog steeds actief. NIet afsluiten."); + // Staattransities die vanuit elke staat kunnen plaatsvinden. + if (spelersActief()) { + staat = Staat.SpelersActief; + } + final switch(staat) { + case Staat.Inactief: + if (spelersActief()) { + staat = Staat.SpelersActief; + teller = 3; + } else if (gebruikersActief) { + staat = Staat.GebruikersActief; + teller = 3; + } else if (--teller <= 0) { + sluitAf(); + staat = Staat.Uit; } - werkAfsluitNakijkTellerBij(); - } else if (moetBlokkeren()) { + break; + 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 { - block(); - info("Afsluitslot verkregen."); + blokkeerAfsluiten(); } catch(DBusException e) { 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); + if (spelersActief()) { + teller = 3; + } else if (--teller <= 0) { + releaseLock(inhibitLock); + staat = Staat.GebruikersActief; + teller = 3; } - } else { - afsluitNakijkTeller = CHECK_COUNT; - trace("Niets om te doen."); + break; + case Staat.Uit: + 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(); - // cleanup - info("Rotzooi opruimen."); + // Rommel opruimen + info("Rommel opruimen."); 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"]); 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"]); return resultaat.output.splitLines().length == 0; } + + void sluitAf() { + version(WithRPC) m_client.notify("NotifyShutdown"); + execute(["shutdown", "+1", "Systeem gaat afsluiten vanwege inactiviteit"]); + } } diff --git a/ober/source/msgpackrpc/client.d b/ober/source/msgpackrpc/client.d index eb9ea95..53d9465 100644 --- a/ober/source/msgpackrpc/client.d +++ b/ober/source/msgpackrpc/client.d @@ -1,4 +1,6 @@ module msgpackrpc.client; + +version(WithRPC) { import core.atomic; import std.array; @@ -133,3 +135,5 @@ private: }); } } + +} // version(WithRPC) diff --git a/ober/source/msgpackrpc/package.d b/ober/source/msgpackrpc/package.d index 9ce42e8..09b4a23 100644 --- a/ober/source/msgpackrpc/package.d +++ b/ober/source/msgpackrpc/package.d @@ -1,3 +1,7 @@ module msgpackrpc; + +version(WithRPC) { public import msgpackrpc.client; public import msgpackrpc.server; + +} // version(WithRPC) diff --git a/ober/source/msgpackrpc/protocol.d b/ober/source/msgpackrpc/protocol.d index 0a46cd1..226cbc5 100644 --- a/ober/source/msgpackrpc/protocol.d +++ b/ober/source/msgpackrpc/protocol.d @@ -1,5 +1,6 @@ module msgpackrpc.protocol; +version(WithRPC) { import std.exception; import msgpack; @@ -32,3 +33,5 @@ public: @property Value value() { return m_value; } } + +} // version(WithRPC) diff --git a/ober/source/msgpackrpc/server.d b/ober/source/msgpackrpc/server.d index 648fa83..0af6953 100644 --- a/ober/source/msgpackrpc/server.d +++ b/ober/source/msgpackrpc/server.d @@ -1 +1,4 @@ module msgpackrpc.server; +version(WithRPC) { + +}