diff --git a/server.py b/server.py new file mode 100755 index 0000000..4b53203 --- /dev/null +++ b/server.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python3 + +import os, setuptools, socketserver, sys, syslog, threading + +SYSLOG = 0 +STDOUT = 1 +STDDEB = 2 # STDOUT + Debug + +exec("logging = %s or STDOUT" % setuptools.getSetting("Log", "sink")) + +def logger(message, prio=syslog.LOG_INFO, sink=logging): + if sink in (STDOUT, STDDEB): + if prio not in (syslog.LOG_NOTICE, syslog.LOG_INFO, syslog.LOG_DEBUG): + print(message) + sys.stderr.write(message) + elif prio != syslog.LOG_DEBUG or sink == STDDEB: + print(message) + elif sink == SYSLOG: + syslog.openlog("KumiStatusServer", syslog.LOG_PID) + syslog.syslog(prio, message) + else: + try: + sys.stderr.write("Unknown logging level %s, assuming STDOUT from now on." % str(sink)) + except: + pass + logging = STDOUT + logger(message, prio, logging) + +def worker(message): + command = message.split() + if command[0].lower() in ("heartbeat", "hb", "ping"): + return "HB: Still here? Wow." + +class TCPHandler(socketserver.StreamRequestHandler): + def readString(self): + return self.rfile.readline().strip() + + def sendString(self, string): + self.request.sendall((string + "\n").encode('utf8')) + + def handle(self): + remote = self.client_address[0] + ":" + str(self.client_address[1]) + logger("New connection from %s." % remote, syslog.LOG_INFO) + self.sendString("HI: Kumi Status v0.8.15") + while True: + message = self.readString().decode('utf8') + if not message: + logger("Connection from %s closed." % remote, syslog.LOG_DEBUG) + break + logger("%s said: %s" % (remote, message)) + response = worker(message) + if response: + self.sendString(response) + logger("Sent to %s: %s" % (remote, response), syslog.LOG_DEBUG) + +class TCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer): + pass + +def shutdown(reboot = False, status = 0): + if reboot: + args = sys.argv[:] + args.insert(0, sys.executable) + try: + os.execv(sys.executable, args) + except: + logger("Restart failed. Shutting down.") + exit(2) + else: + exit(status) + +if __name__ == "__main__": + socketserver.TCPServer.allow_reuse_address = True + try: + server = TCPServer((setuptools.getSetting("Server", "bind"), int(setuptools.getSetting("Server", "port"))), TCPHandler) + except: + logger("Unable to bind on %s:%s. Make sure the port is not in use or use a different port.") + shutdown(status=1) + logger("Kumi Status server running on %s:%s." % (setuptools.getSetting("Server", "bind"), setuptools.getSetting("Server", "port"))) + + try: + thread = threading.Thread(target=server.serve_forever(), daemon=True) + except KeyboardInterrupt: + logger("Caught KeyboardInterrupt. Shutting down.") + shutdown() + except EOFError: + logger("Caught EOF. Shutting down.") + shutdown() + except BaseException as e: + logger(str(e), syslog.LOG_CRIT) + logger("Caught some bad exception. Trying to reload...", syslog.LOG_CRIT) + shutdown(reboot=True) +