70 lines
2 KiB
Python
Executable file
70 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, empty
|
|
|
|
from InputController import InputController
|
|
from MessageParser import MessageParser
|
|
|
|
|
|
app = Sanic(
|
|
"capybara",
|
|
env_prefix="CAPYBARA_"
|
|
)
|
|
input_controller = InputController()
|
|
control_message_parser = MessageParser()
|
|
|
|
# auth packet
|
|
control_message_parser.add_handler("0", {
|
|
"auth_string": "str"
|
|
})
|
|
|
|
app.static("app", "frontend/", 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 accepting 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()
|