diff --git a/html/package.json b/html/package.json
index ac61c82..09d62b4 100644
--- a/html/package.json
+++ b/html/package.json
@@ -58,6 +58,7 @@
"webpack-merge": "^4.2.1"
},
"dependencies": {
+ "backoff": "^2.5.0",
"decko": "^1.2.0",
"preact": "^8.4.2",
"xterm": "^3.14.4",
diff --git a/html/src/components/terminal/index.tsx b/html/src/components/terminal/index.tsx
index b7c430b..909f740 100644
--- a/html/src/components/terminal/index.tsx
+++ b/html/src/components/terminal/index.tsx
@@ -1,4 +1,5 @@
import { bind } from 'decko';
+import * as backoff from 'backoff';
import { Component, h } from 'preact';
import { ITerminalOptions, Terminal } from 'xterm';
import { FitAddon } from 'xterm-addon-fit';
@@ -45,6 +46,7 @@ export class Xterm extends Component {
private title: string;
private reconnect: number;
private resizeTimeout: number;
+ private backoff: backoff.Backoff;
constructor(props) {
super(props);
@@ -53,6 +55,16 @@ export class Xterm extends Component {
this.textDecoder = new TextDecoder();
this.fitAddon = new FitAddon();
this.overlayAddon = new OverlayAddon();
+ this.backoff = backoff.exponential({
+ initialDelay: 100,
+ maxDelay: 10000,
+ });
+ this.backoff.on('ready', () => {
+ this.openTerminal();
+ });
+ this.backoff.on('backoff', (_, delay: number) => {
+ console.log(`[ttyd] will attempt to reconnect websocket in ${delay}ms`);
+ });
}
componentDidMount() {
@@ -112,6 +124,7 @@ export class Xterm extends Component {
socket.onopen = this.onSocketOpen;
socket.onmessage = this.onSocketData;
socket.onclose = this.onSocketClose;
+ socket.onerror = this.onSocketError;
terminal.loadAddon(fitAddon);
terminal.loadAddon(overlayAddon);
@@ -141,6 +154,7 @@ export class Xterm extends Component {
@bind
private onSocketOpen() {
console.log('[ttyd] Websocket connection opened');
+ this.backoff.reset();
const { socket, textEncoder, fitAddon } = this;
const authToken = window.tty_auth_token;
@@ -166,6 +180,11 @@ export class Xterm extends Component {
}
}
+ @bind
+ private onSocketError() {
+ this.backoff.backoff();
+ }
+
@bind
private onSocketData(event: MessageEvent) {
const { terminal, textDecoder, zmodemAddon } = this;
diff --git a/html/yarn.lock b/html/yarn.lock
index 8c5287d..33b6df9 100644
--- a/html/yarn.lock
+++ b/html/yarn.lock
@@ -685,6 +685,13 @@ bach@^1.0.0:
async-settle "^1.0.0"
now-and-later "^2.0.0"
+backoff@^2.5.0:
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/backoff/-/backoff-2.5.0.tgz#f616eda9d3e4b66b8ca7fca79f695722c5f8e26f"
+ integrity sha1-9hbtqdPktmuMp/ynn2lXIsX44m8=
+ dependencies:
+ precond "0.2"
+
balanced-match@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
@@ -6628,6 +6635,11 @@ preact@^8.4.2:
resolved "https://registry.yarnpkg.com/preact/-/preact-8.4.2.tgz#1263b974a17d1ea80b66590e41ef786ced5d6a23"
integrity sha512-TsINETWiisfB6RTk0wh3/mvxbGRvx+ljeBccZ4Z6MPFKgu/KFGyf2Bmw3Z/jlXhL5JlNKY6QAbA9PVyzIy9//A==
+precond@0.2:
+ version "0.2.3"
+ resolved "https://registry.yarnpkg.com/precond/-/precond-0.2.3.tgz#aa9591bcaa24923f1e0f4849d240f47efc1075ac"
+ integrity sha1-qpWRvKokkj8eD0hJ0kD0fvwQdaw=
+
prepend-http@^1.0.1:
version "1.0.4"
resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc"
diff --git a/src/index.html b/src/index.html
index 2e895df..6e414ba 100644
--- a/src/index.html
+++ b/src/index.html
@@ -1 +1 @@
-ttyd - Terminal
\ No newline at end of file
+ttyd - Terminal
\ No newline at end of file