Eerste commit
This commit is contained in:
commit
f84a4f321c
13 changed files with 438 additions and 0 deletions
76
source/app.d
Normal file
76
source/app.d
Normal file
|
@ -0,0 +1,76 @@
|
|||
import std.functional;
|
||||
|
||||
import vibe.vibe;
|
||||
|
||||
import kerstezelprotocol;
|
||||
|
||||
|
||||
|
||||
struct VertaalContext {
|
||||
import std.typetuple;
|
||||
// Throw an error when an translation string is missing/mistyped.
|
||||
enum enforceExistingKeys = true;
|
||||
// The list of supported languages (the same family of languages will
|
||||
// automatically be matched to the closest candidate, e.g. en_GB->en_US)
|
||||
alias languages = TypeTuple!("en_GB", "nl_NL");
|
||||
// The base name of the translation files - the full names will be
|
||||
// kerstman.en_US.po and kerstman.de_DE.po. Any number of these mixin
|
||||
// statements can be used.
|
||||
mixin translationModule!"kerstman";
|
||||
}
|
||||
|
||||
@translationContext!VertaalContext
|
||||
class KerstezelService {
|
||||
|
||||
@path("/")
|
||||
void getIndex() {
|
||||
render!"index.dt";
|
||||
}
|
||||
|
||||
@path("/arreslee")
|
||||
void getArreslee(scope WebSocket bus) {
|
||||
runTask((WebSocket bus) {
|
||||
while(bus.connected) {
|
||||
string commando = bus.receiveText;
|
||||
if (commando == "trommel") {
|
||||
kerstmanTaak.send(TrommelCommando());
|
||||
} else {
|
||||
logInfo("Onbekend commando:" ~ commando);
|
||||
}
|
||||
}
|
||||
}, bus);
|
||||
|
||||
while (bus.connected) {
|
||||
int uitzend_aantal = staatGebeurtenis.emitCount;
|
||||
bus.send(staat.serializeToJsonString());
|
||||
// Wordt elke 30 seconden wakker om de verbinding in leven
|
||||
// te houden en/of te detecteren dat deze juist gestopt is.
|
||||
staatGebeurtenis.wait(30.seconds, uitzend_aantal);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void main() {
|
||||
import vibe.http.router;
|
||||
|
||||
auto settings = new HTTPServerSettings;
|
||||
settings.port = 8090;
|
||||
settings.bindAddresses = ["::", "0.0.0.0"];
|
||||
|
||||
auto router = new URLRouter;
|
||||
router.registerWebInterface(new KerstezelService);
|
||||
|
||||
auto fsettings = new HTTPFileServerSettings;
|
||||
fsettings.serverPathPrefix = "/statisch";
|
||||
router.get("*", serveStaticFiles("statisch/", fsettings));
|
||||
|
||||
listenHTTP(settings, router);
|
||||
|
||||
logInfo("Please open http://127.0.0.1:8080/ in your browser.");
|
||||
if (!listenTCP(9305, toDelegate(&kerstezelProtocolLuister), "0.0.0.0")) {
|
||||
logWarn("Kon kerstezelProtocol niet starten");
|
||||
}
|
||||
runApplication();
|
||||
}
|
142
source/kerstezelprotocol.d
Normal file
142
source/kerstezelprotocol.d
Normal file
|
@ -0,0 +1,142 @@
|
|||
import std.array;
|
||||
import std.algorithm;
|
||||
import std.datetime;
|
||||
import std.exception;
|
||||
import std.format;
|
||||
import std.random;
|
||||
import std.range;
|
||||
|
||||
import vibe.vibe;
|
||||
|
||||
immutable size_t BUF_SIZE = 2048;
|
||||
|
||||
struct Staat {
|
||||
bool verbondenMetKerstman = false;
|
||||
long trommelenVerbodenTot = 0;
|
||||
}
|
||||
|
||||
|
||||
shared Staat staat;
|
||||
shared ManualEvent staatGebeurtenis;
|
||||
shared Task kerstmanTaak;
|
||||
|
||||
__gshared TaskMutex mutex;
|
||||
shared static this() {
|
||||
staatGebeurtenis = createSharedManualEvent();
|
||||
mutex = new TaskMutex();
|
||||
}
|
||||
|
||||
struct TrommelCommando {};
|
||||
|
||||
@trusted
|
||||
void kerstezelProtocolLuister(TCPConnection verbinding) nothrow {
|
||||
try {
|
||||
auto lock = scopedMutexLock(mutex);
|
||||
new Sessie(verbinding).voerUit();
|
||||
} catch (Exception e) {
|
||||
logException(e, "Kon mutex niet verkrijgen");
|
||||
}
|
||||
}
|
||||
|
||||
class UnicodeUitzondering : Exception {
|
||||
mixin basicExceptionCtors;
|
||||
}
|
||||
|
||||
class ProtocolUitzondering : Exception {
|
||||
mixin basicExceptionCtors;
|
||||
}
|
||||
|
||||
class Sessie {
|
||||
private TCPConnection l_verbinding;
|
||||
private bool blijfBezig = true;
|
||||
private SysTime trommelenVerbodenTot;
|
||||
private bool trommelenVerboden = false;
|
||||
|
||||
@safe
|
||||
this(TCPConnection verbinding) nothrow {
|
||||
this.l_verbinding = verbinding;
|
||||
}
|
||||
|
||||
@trusted
|
||||
public void voerUit() nothrow {
|
||||
logInfo("Nieuwe sessie probeert te verbinden");
|
||||
try {
|
||||
handGeven();
|
||||
logInfo("Sessie is verbonden");
|
||||
staat.verbondenMetKerstman = true;
|
||||
kerstmanTaak = Task.getThis();
|
||||
staatGebeurtenis.emit();
|
||||
|
||||
while(true) {
|
||||
auto tijdsduur = trommelenVerboden
|
||||
? min(trommelenVerbodenTot - Clock.currTime, seconds(30))
|
||||
: seconds(30);
|
||||
|
||||
bool received = receiveTimeout(tijdsduur,
|
||||
(TrommelCommando com) {
|
||||
logInfo("Trommelen");
|
||||
auto now = Clock.currTime();
|
||||
if (trommelenVerboden) return;
|
||||
l_verbinding.write("trommel\n");
|
||||
l_verbinding.flush();
|
||||
trommelenVerboden = true;
|
||||
trommelenVerbodenTot = now + seconds(30);
|
||||
staat.trommelenVerbodenTot = trommelenVerbodenTot.toUnixTime;
|
||||
staatGebeurtenis.emit();
|
||||
|
||||
ubyte[] read = l_verbinding.readLine(BUF_SIZE, "\n");
|
||||
enforce!ProtocolUitzondering(read.equal("oké"), "Kerstman deed geen erkenning, maar deed %s".format(read));
|
||||
}
|
||||
);
|
||||
if (Clock.currTime() >= trommelenVerbodenTot) {
|
||||
trommelenVerboden = false;
|
||||
staatGebeurtenis.emit();
|
||||
}
|
||||
if (!received) {
|
||||
l_verbinding.write("ping\n");
|
||||
l_verbinding.flush();
|
||||
ubyte[] read = l_verbinding.readLine(BUF_SIZE, "\n");
|
||||
enforce!ProtocolUitzondering(read.equal("pong"), "Kerstman pongde niet terug, maar deed %s".format(read));
|
||||
}
|
||||
}
|
||||
} catch (ProtocolUitzondering u) {
|
||||
logException(u, "Protocoluitzondering");
|
||||
} catch (Exception e) {
|
||||
logException(e, "Andere uitzondering");
|
||||
} finally {
|
||||
logInfo("Sessie verbroken");
|
||||
staat.verbondenMetKerstman = false;
|
||||
staatGebeurtenis.emit();
|
||||
sluit();
|
||||
}
|
||||
}
|
||||
|
||||
@safe
|
||||
private void handGeven () {
|
||||
// Maak een begroeting
|
||||
string begroeting2 = "e gaat 'ie?\n";
|
||||
// Maak het irritant om het met de hand te doen :P
|
||||
int aantal = cast(int) (rndGen.front % 200) + 100;
|
||||
logInfo("Aantal: %d".format(aantal));
|
||||
rndGen.popFront();
|
||||
|
||||
string begroeting = "ho".replicate(aantal) ~ begroeting2;
|
||||
l_verbinding.write(begroeting);
|
||||
l_verbinding.flush();
|
||||
|
||||
// Wacht op een antwoord in de vorm van (aantal * "go" + "ed!")
|
||||
ubyte[] data = l_verbinding.readLine(BUF_SIZE, "\n");
|
||||
string expected = "go".replicate(aantal) ~ "ed";
|
||||
enforce!ProtocolUitzondering(equal(data, expected), "Ongeldige handdruk");
|
||||
}
|
||||
|
||||
@safe
|
||||
private void sluit() nothrow {
|
||||
try {
|
||||
l_verbinding.close();
|
||||
} catch(Exception e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue