fix reconnect and add banner message when trying to reconnect5r

This commit is contained in:
hippoz 2022-01-25 17:10:35 +02:00
parent 6bbd925dbc
commit 0f881b668c
Signed by: hippoz
GPG key ID: 7C52899193467641
5 changed files with 73 additions and 29 deletions

View file

@ -2,7 +2,7 @@ import sys
from asyncio import wait_for, TimeoutError from asyncio import wait_for, TimeoutError
from base64 import b64encode from base64 import b64encode
from sanic import Sanic from sanic import Sanic
from sanic.response import file, redirect from sanic.response import file, redirect, empty
from InputController import InputController from InputController import InputController
from MessageParser import MessageParser from MessageParser import MessageParser
@ -10,7 +10,7 @@ from MessageParser import MessageParser
app = Sanic( app = Sanic(
"capybara", "capybara",
load_env="CAPYBARA_" env_prefix="CAPYBARA_"
) )
input_controller = InputController() input_controller = InputController()
control_message_parser = MessageParser() control_message_parser = MessageParser()
@ -40,13 +40,15 @@ async def gateway(req, ws):
return return
code, args = control_message_parser.parse(auth_payload) code, args = control_message_parser.parse(auth_payload)
if (not code or if (
not code or
code != "0" or code != "0" or
args["auth_string"] != app.ctx.EXPECTED_AUTH_STRING): # 0 is the code for the initial auth packet 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") await ws.close(code=4001, reason="Invalid auth packet")
return return
await ws.send("1") # send a single `1` to let the client know the server is input packets await ws.send("1") # send a single `1` to let the client know the server is accepting input packets
while True: while True:
input_controller.process_message(await ws.recv()) input_controller.process_message(await ws.recv())

View file

@ -1,3 +1,4 @@
import Banner from "./Banner";
import Connection from "./Connection"; import Connection from "./Connection";
import KeyboardController from "./Keyboard"; import KeyboardController from "./Keyboard";
import { getAuth, setAuth } from "./LocalConfiguration"; import { getAuth, setAuth } from "./LocalConfiguration";
@ -18,6 +19,8 @@ class App {
this.unmountApp(); this.unmountApp();
if (code === 4001) { // 4001 - code for bad auth if (code === 4001) { // 4001 - code for bad auth
this.transitionTo("login"); this.transitionTo("login");
} else {
this.transitionTo("reconnectingBanner");
} }
}); });
this.connection.onHandshakeCompleted = () => { this.connection.onHandshakeCompleted = () => {
@ -28,24 +31,45 @@ class App {
transitionTo(type) { transitionTo(type) {
switch (type) { switch (type) {
case "login": case "login":
this.unmountBannerComponent();
this.unmountApp(); this.unmountApp();
this.mountLoginComponent(); this.mountLoginComponent();
break; break;
case "app": case "app":
this.unmountBannerComponent();
this.unmountLoginComponent(); this.unmountLoginComponent();
this.mountApp(); this.mountApp();
break; break;
case "reconnectingBanner":
this.unmountApp();
this.unmountLoginComponent();
this.mountBannerComponent("Connecting...", "Looks like you've lost connection. We're trying to reconnect you.");
break;
default: default:
throw new Error(`transitionTo type ${type} is invalid`); throw new Error(`transitionTo type ${type} is invalid`);
} }
} }
mountBannerComponent(title, text) {
if (!this.bannerComponent)
this.bannerComponent = new Banner();
this.bannerComponent.mountOn(this.mountElement);
this.bannerComponent.updateTitle(title);
this.bannerComponent.updateText(text);
}
unmountBannerComponent() {
if (this.bannerComponent)
this.bannerComponent.unmount();
}
mountLoginComponent() { mountLoginComponent() {
if (!this.loginPromptComponent) if (!this.loginPromptComponent)
this.loginPromptComponent = new LoginPrompt(this.connection); this.loginPromptComponent = new LoginPrompt(this.connection);
this.loginPromptComponent.mountOn(this.mountElement); this.loginPromptComponent.mountOn(this.mountElement);
this.loginPromptComponent.onPasswordSubmitted = p => { this.loginPromptComponent.onPasswordSubmitted = (p) => {
setAuth(p); setAuth(p);
this.connection.connect(p); this.connection.connect(p);
}; };

View file

@ -1,10 +1,19 @@
class Banner { class Banner {
constructor() { constructor() {
this.text = null; this.element = null;
this.title = "";
this.text = "";
} }
updateText(text) { updateText(newText) {
this.text = text; this.text = newText;
this.element.querySelector("#banner-text").innerText = this.text;
}
updateTitle(newTitle) {
this.title = newTitle;
this.element.querySelector("#banner-title").innerText = this.title;
} }
mountOn(target) { mountOn(target) {
@ -13,22 +22,21 @@ class Banner {
this.element = document.createRange().createContextualFragment(` this.element = document.createRange().createContextualFragment(`
<div class="card small-card center-text"> <div class="card small-card center-text">
<h2>Login</h2> <h2 id="banner-title"></h2>
<p>You need to enter the login code before you can start controlling your device.</p> <p id="banner-text"></p>
<br>
<div class="full-width">
<input id="code-input" class="input full-width" placeholder="Code">
<br>
<button id="continue-button" class="button-default full-width">Continue</button>
</div>
</div> </div>
`).children[0]; `).children[0];
this.element.querySelector("#continue-button").addEventListener("click", () => {
if (this.onPasswordSubmitted)
this.onPasswordSubmitted(this.element.querySelector("#code-input").value);
});
target.appendChild(this.element); target.appendChild(this.element);
} }
}
unmount() {
if (!this.element)
return; // Already unmounted
this.element.parentElement.removeChild(this.element);
this.element = null;
}
}
export default Banner;

View file

@ -7,6 +7,7 @@ class Connection {
this.messageLog = Logger(["Connection", "Message"], ["log"]).log; this.messageLog = Logger(["Connection", "Message"], ["log"]).log;
this.url = url; this.url = url;
this.isReady = false; this.isReady = false;
this.reconnectTimeout = 0;
} }
formatAuthString(password) { formatAuthString(password) {
@ -18,6 +19,7 @@ class Connection {
this.ws.onerror = (e) => this.log("Error", e); this.ws.onerror = (e) => this.log("Error", e);
this.ws.onopen = () => { this.ws.onopen = () => {
this.log("Open"); this.log("Open");
this.reconnectTimeout = 0;
this.log("Sending authentication packet"); this.log("Sending authentication packet");
this.ws.send(`0${this.formatAuthString(password)}`); // send auth packet this.ws.send(`0${this.formatAuthString(password)}`); // send auth packet
}; };
@ -35,9 +37,12 @@ class Connection {
this.log("Closed due to bad auth - skipping reconnect"); this.log("Closed due to bad auth - skipping reconnect");
return; return;
} }
this.log("Closed - attempting to reconnect in 4000ms");
this.isReady = false; this.isReady = false;
setTimeout(() => this.connect(), 4000); this.reconnectTimeout += 400;
if (this.reconnectTimeout >= 30000)
this.reconnectTimeout = 30000;
this.log(`Closed - will reconnect in ${this.reconnectTimeout}ms`);
setTimeout(() => this.connect(password), this.reconnectTimeout);
} }
} }

View file

@ -20,7 +20,7 @@ body {
color: var(--accent-bg-color); color: var(--accent-bg-color);
overflow-x: none; overflow-x: none;
margin: 0; margin: 0;
padding: 8px; padding: 12px;
} }
.card { .card {
@ -105,7 +105,7 @@ body {
} }
.touchpad { .touchpad {
height: clamp(5rem, 30rem, 55vh); height: clamp(5rem, 30rem, 50vh);
width: 100%; width: 100%;
background-color: var(--accent-bg-color); background-color: var(--accent-bg-color);
border-radius: var(--card-border-radius); border-radius: var(--card-border-radius);
@ -113,9 +113,15 @@ body {
/* for virtual keyboard */ /* for virtual keyboard */
.hg-theme-default {
font-weight: var(--main-font-weight);
font-family: var(--fonts-regular);
}
.keyboard { .keyboard {
padding: 8px;
color: var(--body-bg-color); color: var(--body-bg-color);
margin-top: 28px; margin-top: 24px;
border-radius: var(--card-border-radius); border-radius: var(--card-border-radius);
background-color: var(--accent-bg-color); background-color: var(--accent-bg-color);
} }
@ -126,7 +132,6 @@ body {
.hg-button { .hg-button {
margin: 2px; margin: 2px;
padding: 12px;
} }
.hg-activeButton { .hg-activeButton {