mirror of
https://github.com/tsl0922/ttyd.git
synced 2025-12-24 20:54:21 +01:00
protocol: set windows size on spawm process
This commit is contained in:
@@ -284,13 +284,16 @@ export class Xterm extends Component<Props> {
|
||||
this.backoff.reset();
|
||||
|
||||
const { socket, textEncoder, terminal, fitAddon, overlayAddon } = this;
|
||||
socket.send(textEncoder.encode(JSON.stringify({ AuthToken: this.token })));
|
||||
const dims = fitAddon.proposeDimensions();
|
||||
socket.send(textEncoder.encode(JSON.stringify({
|
||||
AuthToken: this.token,
|
||||
columns: dims.cols,
|
||||
rows: dims.rows,
|
||||
})));
|
||||
|
||||
if (this.reconnect) {
|
||||
const dims = fitAddon.proposeDimensions();
|
||||
terminal.reset();
|
||||
terminal.resize(dims.cols, dims.rows);
|
||||
this.onTerminalResize(dims); // may not be triggered by terminal.resize
|
||||
overlayAddon.showOverlay('Reconnected', 300);
|
||||
} else {
|
||||
this.reconnect = true;
|
||||
|
||||
18852
src/html.h
generated
18852
src/html.h
generated
File diff suppressed because it is too large
Load Diff
@@ -35,27 +35,18 @@ static int send_initial_message(struct lws *wsi, int index) {
|
||||
return lws_write(wsi, p, (size_t)n, LWS_WRITE_BINARY);
|
||||
}
|
||||
|
||||
static bool parse_window_size(struct pss_tty *pss, uint16_t *cols, uint16_t *rows) {
|
||||
char json[pss->len];
|
||||
strncpy(json, pss->buffer + 1, pss->len - 1);
|
||||
json[pss->len - 1] = '\0';
|
||||
|
||||
json_object *obj = json_tokener_parse(json);
|
||||
static json_object* parse_window_size(const char *buf, size_t len, uint16_t *cols, uint16_t *rows) {
|
||||
json_tokener *tok = json_tokener_new();
|
||||
json_object *obj = json_tokener_parse_ex(tok, buf, len);
|
||||
struct json_object *o = NULL;
|
||||
|
||||
if (!json_object_object_get_ex(obj, "columns", &o)) {
|
||||
lwsl_err("columns field not exists, json: %s\n", json);
|
||||
return false;
|
||||
}
|
||||
*cols = (uint16_t) json_object_get_int(o);
|
||||
if (!json_object_object_get_ex(obj, "rows", &o)) {
|
||||
lwsl_err("rows field not exists, json: %s\n", json);
|
||||
return false;
|
||||
}
|
||||
*rows = (uint16_t) json_object_get_int(o);
|
||||
json_object_put(obj);
|
||||
|
||||
return true;
|
||||
if (json_object_object_get_ex(obj, "columns", &o))
|
||||
*cols = (uint16_t) json_object_get_int(o);
|
||||
if (json_object_object_get_ex(obj, "rows", &o))
|
||||
*rows = (uint16_t) json_object_get_int(o);
|
||||
|
||||
json_tokener_free(tok);
|
||||
return obj;
|
||||
}
|
||||
|
||||
static bool check_host_origin(struct lws *wsi) {
|
||||
@@ -103,7 +94,7 @@ static void process_exit_cb(void *ctx, pty_process *process) {
|
||||
}
|
||||
}
|
||||
|
||||
static bool spawn_process(struct pss_tty *pss) {
|
||||
static bool spawn_process(struct pss_tty *pss, uint16_t columns, uint16_t rows) {
|
||||
// append url args to arguments
|
||||
char *argv[server->argc + pss->argc + 1];
|
||||
int i, n = 0;
|
||||
@@ -116,6 +107,8 @@ static bool spawn_process(struct pss_tty *pss) {
|
||||
argv[n] = NULL;
|
||||
|
||||
pty_process *process = process_init((void *) pss, server->loop, argv);
|
||||
if (columns > 0) process->columns = columns;
|
||||
if (rows > 0) process->rows = rows;
|
||||
if (pty_spawn(process, process_read_cb, process_exit_cb) != 0) {
|
||||
lwsl_err("pty_spawn: %d (%s)\n", errno, strerror(errno));
|
||||
process_free(process);
|
||||
@@ -275,12 +268,12 @@ int callback_tty(struct lws *wsi, enum lws_callback_reasons reason, void *user,
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case RESIZE_TERMINAL: {
|
||||
uint16_t cols, rows;
|
||||
if (parse_window_size(pss, &cols, &rows)) {
|
||||
pty_resize(pss->process, cols, rows);
|
||||
}
|
||||
} break;
|
||||
case RESIZE_TERMINAL:
|
||||
if (pss->process == NULL) break;
|
||||
json_object_put(parse_window_size(pss->buffer + 1, pss->len - 1,
|
||||
&pss->process->columns, &pss->process->rows));
|
||||
pty_resize(pss->process);
|
||||
break;
|
||||
case PAUSE:
|
||||
pty_pause(pss->process);
|
||||
break;
|
||||
@@ -289,22 +282,25 @@ int callback_tty(struct lws *wsi, enum lws_callback_reasons reason, void *user,
|
||||
break;
|
||||
case JSON_DATA:
|
||||
if (pss->process != NULL) break;
|
||||
uint16_t columns = 0;
|
||||
uint16_t rows = 0;
|
||||
char *token = NULL;
|
||||
json_object *obj = parse_window_size(pss->buffer, pss->len, &columns, &rows);
|
||||
if (server->credential != NULL) {
|
||||
json_object *obj = json_tokener_parse(pss->buffer);
|
||||
struct json_object *o = NULL;
|
||||
if (json_object_object_get_ex(obj, "AuthToken", &o)) {
|
||||
const char *token = json_object_get_string(o);
|
||||
if (token != NULL && !strcmp(token, server->credential))
|
||||
pss->authenticated = true;
|
||||
else
|
||||
lwsl_warn("WS authentication failed with token: %s\n", token);
|
||||
pss->authenticated = token != NULL && !strcmp(token, server->credential);
|
||||
}
|
||||
if (!pss->authenticated) {
|
||||
lwsl_warn("WS authentication failed with token: %s\n", token);
|
||||
json_object_put(obj);
|
||||
lws_close_reason(wsi, LWS_CLOSE_STATUS_POLICY_VIOLATION, NULL, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (!spawn_process(pss)) return 1;
|
||||
json_object_put(obj);
|
||||
if (!spawn_process(pss, columns, rows)) return 1;
|
||||
break;
|
||||
default:
|
||||
lwsl_warn("ignored unknown message type: %c\n", command);
|
||||
|
||||
14
src/pty.c
14
src/pty.c
@@ -93,6 +93,8 @@ pty_process *process_init(void *ctx, uv_loop_t *loop, char **argv) {
|
||||
process->ctx = ctx;
|
||||
process->loop = loop;
|
||||
process->argv = argv;
|
||||
process->columns = 80;
|
||||
process->rows = 24;
|
||||
process->exit_code = -1;
|
||||
return process;
|
||||
}
|
||||
@@ -138,12 +140,13 @@ int pty_write(pty_process *process, pty_buf_t *buf) {
|
||||
return uv_write(req, (uv_stream_t *) io->in, &b, 1, write_cb);
|
||||
}
|
||||
|
||||
bool pty_resize(pty_process *process, uint16_t width, uint16_t height) {
|
||||
bool pty_resize(pty_process *process) {
|
||||
if (process->columns <= 0 || process->rows <= 0) return false;
|
||||
#ifdef _WIN32
|
||||
COORD size = { (int16_t) width, (int16_t) height };
|
||||
COORD size = { (int16_t) process->columns, (int16_t) process->rows };
|
||||
return pResizePseudoConsole(process->pty, size) == S_OK;
|
||||
#else
|
||||
struct winsize size = { height, width, 0, 0 };
|
||||
struct winsize size = { process->rows, process->columns, 0, 0 };
|
||||
return ioctl(process->pty, TIOCSWINSZ, &size) == 0;
|
||||
#endif
|
||||
}
|
||||
@@ -303,7 +306,7 @@ int pty_spawn(pty_process *process, pty_read_cb read_cb, pty_exit_cb exit_cb) {
|
||||
char *in_name = NULL;
|
||||
char *out_name = NULL;
|
||||
DWORD flags = EXTENDED_STARTUPINFO_PRESENT | CREATE_UNICODE_ENVIRONMENT;
|
||||
COORD size = { 80, 24 };
|
||||
COORD size = { (int16_t) process->columns, (int16_t) process->rows };
|
||||
|
||||
if (!conpty_setup(&process->pty, size, &process->si, &in_name, &out_name)) return 1;
|
||||
|
||||
@@ -401,7 +404,8 @@ int pty_spawn(pty_process *process, pty_read_cb read_cb, pty_exit_cb exit_cb) {
|
||||
uv_disable_stdio_inheritance();
|
||||
|
||||
int master, pid;
|
||||
pid = forkpty(&master, NULL, NULL, NULL);
|
||||
struct winsize size = { process->rows, process->columns, 0, 0 };
|
||||
pid = forkpty(&master, NULL, NULL, &size);
|
||||
if (pid < 0) {
|
||||
status = -errno;
|
||||
goto error;
|
||||
|
||||
@@ -38,6 +38,7 @@ typedef void (*pty_exit_cb)(void *, pty_process *);
|
||||
|
||||
struct pty_process_ {
|
||||
int pid, exit_code, exit_signal;
|
||||
uint16_t columns, rows;
|
||||
bool killed;
|
||||
#ifdef _WIN32
|
||||
STARTUPINFOEXW si;
|
||||
@@ -66,7 +67,7 @@ int pty_spawn(pty_process *process, pty_read_cb read_cb, pty_exit_cb exit_cb);
|
||||
void pty_pause(pty_process *process);
|
||||
void pty_resume(pty_process *process);
|
||||
int pty_write(pty_process *process, pty_buf_t *buf);
|
||||
bool pty_resize(pty_process *process, uint16_t width, uint16_t height);
|
||||
bool pty_resize(pty_process *process);
|
||||
bool pty_close(pty_process *process, int sig);
|
||||
|
||||
#endif // TTYD_PTY_H
|
||||
|
||||
Reference in New Issue
Block a user