capybara/capybara.py

68 lines
2 KiB
Python
Executable file

import sys
from asyncio import wait_for, TimeoutError
from base64 import b64encode
from sanic import Sanic
from sanic.response import file, redirect
from InputController import InputController
from MessageParser import MessageParser
app = Sanic(
"capybara",
load_env="CAPYBARA_"
)
input_controller = InputController()
control_message_parser = MessageParser()
# auth packet
control_message_parser.add_handler("0", {
"auth_string": "str"
})
app.static("app", "frontend/dist/", resource_type="dir")
@app.get("/")
async def home(req):
return redirect("/app/app.html")
@app.get("/app")
async def app_route(req):
return redirect("/app/app.html")
@app.websocket("/gateway")
async def gateway(req, ws):
# Before the client is able to send any data, we must await an authorization packet
try:
auth_payload = await wait_for(ws.recv(), timeout=5)
except TimeoutError:
await ws.close(code=4001, reason="Invalid auth packet")
return
code, args = control_message_parser.parse(auth_payload)
if (not code or
code != "0" or
args["auth_string"] != app.ctx.EXPECTED_AUTH_STRING): # 0 is the code for the initial auth packet
await ws.close(code=4001, reason="Invalid auth packet")
return
await ws.send("1") # send a single `1` to let the client know the server is input packets
while True:
input_controller.process_message(await ws.recv())
def main():
if not app.config.get("AUTH_PASSWORD"):
print(
"capybara: FATAL ERROR: Capybara is expecting the `CAPYBARA_AUTH_PASSWORD` environment variable to be set (to a password of your choice).\nYour users will use this password to authenticate to your server.\nEXITING...",
file=sys.stderr
)
exit(1)
return
app.ctx.EXPECTED_AUTH_STRING = "%auth%" + str(b64encode(app.config.AUTH_PASSWORD.encode("utf-8")), "utf-8")
app.run(host='0.0.0.0', port=4003, access_log=False)
if __name__ == "__main__":
main()