diff --git a/html/src/components/terminal/index.tsx b/html/src/components/terminal/index.tsx
index 2f159ed..597294f 100644
--- a/html/src/components/terminal/index.tsx
+++ b/html/src/components/terminal/index.tsx
@@ -7,6 +7,12 @@ import { OverlayAddon } from './overlay';
import 'xterm/dist/xterm.css';
+export interface IWindowWithTerminal extends Window {
+ term: Terminal;
+ tty_auth_token?: string;
+}
+declare let window: IWindowWithTerminal;
+
const enum Command {
// server side
OUTPUT = '0',
@@ -86,7 +92,7 @@ export default class Xterm extends Component {
this.socket = new WebSocket(this.props.url, ['tty']);
this.terminal = new Terminal(this.props.options);
const { socket, terminal, container, fitAddon, overlayAddon } = this;
- (window as any).term = terminal;
+ window.term = terminal;
socket.binaryType = 'arraybuffer';
socket.onopen = this.onSocketOpen;
@@ -121,8 +127,9 @@ export default class Xterm extends Component {
private onSocketOpen() {
console.log('[ttyd] Websocket connection opened');
const { socket, textEncoder, fitAddon } = this;
+ const authToken = window.tty_auth_token;
- socket.send(textEncoder.encode(JSON.stringify({AuthToken: ''})));
+ socket.send(textEncoder.encode(JSON.stringify({AuthToken: authToken})));
fitAddon.fit();
}
diff --git a/src/http.c b/src/http.c
index 38a94e3..2a5d092 100644
--- a/src/http.c
+++ b/src/http.c
@@ -4,10 +4,14 @@
#include "server.h"
#include "html.h"
+enum {
+ AUTH_OK, AUTH_FAIL, AUTH_ERROR
+};
+
int
-check_auth(struct lws *wsi) {
+check_auth(struct lws *wsi, struct pss_http *pss) {
if (server->credential == NULL)
- return 0;
+ return AUTH_OK;
int hdr_length = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_AUTHORIZATION);
char buf[hdr_length + 1];
@@ -26,54 +30,64 @@ check_auth(struct lws *wsi) {
}
}
if (b64_text != NULL && !strcmp(b64_text, server->credential))
- return 0;
+ return AUTH_OK;
}
unsigned char buffer[1024 + LWS_PRE], *p, *end;
p = buffer + LWS_PRE;
end = p + sizeof(buffer) - LWS_PRE;
+ char *body = strdup("401 Unauthorized\n");
+ size_t n = strlen(body);
+
if (lws_add_http_header_status(wsi, HTTP_STATUS_UNAUTHORIZED, &p, end))
- return 1;
+ return AUTH_ERROR;
if (lws_add_http_header_by_token(wsi,
WSI_TOKEN_HTTP_WWW_AUTHENTICATE,
(unsigned char *) "Basic realm=\"ttyd\"",
18, &p, end))
- return 1;
- if (lws_add_http_header_content_length(wsi, 0, &p, end))
- return 1;
+ return AUTH_ERROR;
+ if (lws_add_http_header_content_length(wsi, n, &p, end))
+ return AUTH_ERROR;
if (lws_finalize_http_header(wsi, &p, end))
- return 1;
+ return AUTH_ERROR;
if (lws_write(wsi, buffer + LWS_PRE, p - (buffer + LWS_PRE), LWS_WRITE_HTTP_HEADERS) < 0)
- return 1;
+ return AUTH_ERROR;
- return -1;
+ pss->buffer = pss->ptr = body;
+ pss->len = n;
+ lws_callback_on_writable(wsi);
+
+ return AUTH_FAIL;
+}
+
+void access_log(struct lws *wsi, const char *path) {
+ char name[100], rip[50];
+#if LWS_LIBRARY_VERSION_MAJOR >=2 && LWS_LIBRARY_VERSION_MINOR >=4
+ struct lws *n_wsi = lws_get_network_wsi(wsi);
+#else
+ struct lws *n_wsi = wsi;
+#endif
+ lws_get_peer_addresses(wsi, lws_get_socket_fd(n_wsi), name, sizeof(name), rip, sizeof(rip));
+ lwsl_notice("HTTP %s - %s (%s)\n", path, rip, name);
}
int
callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) {
struct pss_http *pss = (struct pss_http *) user;
unsigned char buffer[4096 + LWS_PRE], *p, *end;
- char buf[256], name[100], rip[50];
+ char buf[256];
switch (reason) {
case LWS_CALLBACK_HTTP:
- // only GET method is allowed
- if (!lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI) || len < 1) {
- lws_return_http_status(wsi, HTTP_STATUS_BAD_REQUEST, NULL);
- goto try_to_reuse;
- }
-
- snprintf(pss->path, sizeof(pss->path), "%s", (const char *)in);
- lws_get_peer_addresses(wsi, lws_get_socket_fd(wsi), name, sizeof(name), rip, sizeof(rip));
- lwsl_notice("HTTP %s - %s (%s)\n", (char *) in, rip, name);
-
- switch (check_auth(wsi)) {
- case 0:
+ access_log(wsi, (const char *) in);
+ snprintf(pss->path, sizeof(pss->path), "%s", (const char *) in);
+ switch (check_auth(wsi, pss)) {
+ case AUTH_OK:
break;
- case -1:
- goto try_to_reuse;
- case 1:
+ case AUTH_FAIL:
+ return 0;
+ case AUTH_ERROR:
default:
return 1;
}
@@ -82,8 +96,8 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, voi
end = p + sizeof(buffer) - LWS_PRE;
if (strncmp(pss->path, "/auth_token.js", 14) == 0) {
- size_t n = server->credential != NULL ? sprintf(buf, "var tty_auth_token = '%s';", server->credential) : 0;
-
+ const char *credential = server->credential != NULL ? server->credential : "";
+ size_t n = sprintf(buf, "var tty_auth_token = '%s';\n", credential);
if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end))
return 1;
if (lws_add_http_header_by_token(wsi,
@@ -97,13 +111,10 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, voi
return 1;
if (lws_write(wsi, buffer + LWS_PRE, p - (buffer + LWS_PRE), LWS_WRITE_HTTP_HEADERS) < 0)
return 1;
- if (n > 0) {
- pss->buffer = pss->ptr = strdup(buf);
- pss->len = n;
- lws_callback_on_writable(wsi);
- break;
- }
- goto try_to_reuse;
+ pss->buffer = pss->ptr = strdup(buf);
+ pss->len = n;
+ lws_callback_on_writable(wsi);
+ break;
}
if (strcmp(pss->path, "/") != 0) {
@@ -134,26 +145,31 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, voi
break;
case LWS_CALLBACK_HTTP_WRITEABLE:
- if (pss->len <= 0)
- goto try_to_reuse;
-
- if (pss ->ptr - pss->buffer == pss->len) {
- if (pss->buffer != (char *) index_html) free(pss->buffer);
+ if (!pss->buffer || pss->len <= 0) {
goto try_to_reuse;
}
- int n = sizeof(buffer) - LWS_PRE;
- if (pss->ptr - pss->buffer + n > pss->len)
- n = (int) (pss->len - (pss->ptr - pss->buffer));
- memcpy(buffer + LWS_PRE, pss->ptr, n);
- pss->ptr += n;
- if (lws_write_http(wsi, buffer + LWS_PRE, (size_t) n) < n) {
- if (pss->buffer != (char *) index_html) free(pss->buffer);
- return -1;
- }
+ do {
+ int n = sizeof(buffer) - LWS_PRE;
+ int m = lws_get_peer_write_allowance(wsi);
+ if (m == 0) {
+ lws_callback_on_writable(wsi);
+ return 0;
+ } else if (m != -1 && m < n) {
+ n = m;
+ }
+ if (pss->ptr + n > pss->buffer + pss->len)
+ n = (int) (pss->len - (pss->ptr - pss->buffer));
+ memcpy(buffer + LWS_PRE, pss->ptr, n);
+ pss->ptr += n;
+ if (lws_write_http(wsi, buffer + LWS_PRE, (size_t) n) < n) {
+ if (pss->buffer != (char *) index_html) free(pss->buffer);
+ return -1;
+ }
+ } while (!lws_send_pipe_choked(wsi) && pss->ptr != pss->buffer + pss->len);
- lws_callback_on_writable(wsi);
- break;
+ if (pss->buffer != (char *) index_html) free(pss->buffer);
+ goto try_to_reuse;
case LWS_CALLBACK_HTTP_FILE_COMPLETION:
goto try_to_reuse;
diff --git a/src/index.html b/src/index.html
index 2d3d9bf..a530e2a 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