protocol: set windows size on spawm process

This commit is contained in:
Shuanglei Tao
2021-03-06 14:12:17 +08:00
parent 3929e5c2b6
commit 96e88fb4ce
5 changed files with 9491 additions and 9447 deletions

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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);

View File

@@ -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;

View File

@@ -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