Xterm.js: Contrôle de flux à l'aide de XON / XOFF

Créé le 10 nov. 2020  ·  3Commentaires  ·  Source: xtermjs/xterm.js

Salut les contributeurs,

J'utilise xtermjs pour créer une application de terminal fonctionnant sur un navigateur Web et le serveur cible utilise Linux. J'ai remarqué que xtermjs v4.9.0 ne répond pas à ^ C lors de l'exécution de la commande yes .
Ensuite, je suis revenu à la v4.0.2 et j'ai activé l'option useFlowControl , cela a fonctionné.

Le useFlowControl utilisant XON / XOFF a été ajouté à partir de la v2.3.0 (PR # 447) mais supprimé de la v4.1.0 (PR # 2422).
Je ne trouve aucune discussion sur la raison de sa suppression. La solution XON / XOFF a-t-elle un piège?

Sinon, pouvons-nous avoir un plan pour ramener cette fonctionnalité à la lib ou je devrais l'implémenter sur ma propre application?

Le contrôle de flux décrit dans le document (https://xtermjs.org/docs/guides/flowcontrol/) n'aide pas beaucoup puisque j'utilise websocket pour me connecter au backend.

typquestion

Commentaire le plus utile

Nous avons supprimé XON / XOFF car il ne fonctionnait pas de manière fiable dans certains scénarios. Du fond de ma tête, je me souviens que nous avions des problèmes avec le shell ZSH, qui utilisait les séquences XON / XOFF pour quelque chose de différent. Je pense que le terminal Windows a également eu des problèmes avec ces séquences.

Quoi qu'il en soit - la façon dont j'ai résolu cela (également en utilisant WebSockets - dans mon cas socket.io mais cela n'a pas d'importance) est d'établir manuellement un mécanisme de contrôle de flux sur le socket lui-même.

Ainsi, chaque fois que des données arrivent sur la socket qui doit être écrite dans xterm.js, nous augmentons un compteur, et une fois que les données ont été écrites avec succès dans xterm.js (ce qui signifie qu'elles ont été rendues par xterm.js), nous diminuons ce compteur .

Si le compteur dépasse un certain seuil, nous envoyons un message pause sur le Websocket, qui du côté serveur mettra en pause le flux pty ( terminalStream.pause() ). Une fois que nous passons en dessous de ce seuil, nous envoyons un message resume sur le Websocket, qui du côté serveur reprendra le flux pty ( terminalStream.resume() ).

Notez que les méthodes terminalStream.pause() et terminalStream.resume() sont les méthodes de flux node.js intégrées pour gérer la contre-pression. node-pty ainsi que ssh2 prennent en charge la gestion de la contre-pression via ces méthodes.

// client
const MAX_PENDING_WRITES = 5;
let pendingWrites = 0;
let paused = false;
socket.on('data', (data) => {
  pendingWrites++;
  xterm.write(data, () => {
    pendingWrites--;
    if (pendingWrites > MAX_PENDING_WRITES && !paused) {
      paused = true;
      socket.emit('pause');
      return;
    }
    if (pendingWrites <= MAX_PENDING_WRITES && paused) {
      paused = false;
      socket.emit('resume');
      return;
    }
  });
});

// server
terminalStream.on('data', (data) => socket.emit('data', data);
socket.on('data', (data) => terminalStream.write(data));
socket.on('pause', () => terminalStream.pause();
socket.on('resume', () => terminalStream.resume();

Ce mécanisme fonctionne de manière assez fiable jusqu'à présent. La commande yes n'inondera plus la connexion. Il y a toujours un délai d'environ 0,5 seconde entre CTRL+C et l'arrêt réel de la commande dans les scénarios à haut débit, mais IMO c'est correct.

J'espère que cela aide.

Tous les 3 commentaires

Nous avons supprimé XON / XOFF car il ne fonctionnait pas de manière fiable dans certains scénarios. Du fond de ma tête, je me souviens que nous avions des problèmes avec le shell ZSH, qui utilisait les séquences XON / XOFF pour quelque chose de différent. Je pense que le terminal Windows a également eu des problèmes avec ces séquences.

Quoi qu'il en soit - la façon dont j'ai résolu cela (également en utilisant WebSockets - dans mon cas socket.io mais cela n'a pas d'importance) est d'établir manuellement un mécanisme de contrôle de flux sur le socket lui-même.

Ainsi, chaque fois que des données arrivent sur la socket qui doit être écrite dans xterm.js, nous augmentons un compteur, et une fois que les données ont été écrites avec succès dans xterm.js (ce qui signifie qu'elles ont été rendues par xterm.js), nous diminuons ce compteur .

Si le compteur dépasse un certain seuil, nous envoyons un message pause sur le Websocket, qui du côté serveur mettra en pause le flux pty ( terminalStream.pause() ). Une fois que nous passons en dessous de ce seuil, nous envoyons un message resume sur le Websocket, qui du côté serveur reprendra le flux pty ( terminalStream.resume() ).

Notez que les méthodes terminalStream.pause() et terminalStream.resume() sont les méthodes de flux node.js intégrées pour gérer la contre-pression. node-pty ainsi que ssh2 prennent en charge la gestion de la contre-pression via ces méthodes.

// client
const MAX_PENDING_WRITES = 5;
let pendingWrites = 0;
let paused = false;
socket.on('data', (data) => {
  pendingWrites++;
  xterm.write(data, () => {
    pendingWrites--;
    if (pendingWrites > MAX_PENDING_WRITES && !paused) {
      paused = true;
      socket.emit('pause');
      return;
    }
    if (pendingWrites <= MAX_PENDING_WRITES && paused) {
      paused = false;
      socket.emit('resume');
      return;
    }
  });
});

// server
terminalStream.on('data', (data) => socket.emit('data', data);
socket.on('data', (data) => terminalStream.write(data));
socket.on('pause', () => terminalStream.pause();
socket.on('resume', () => terminalStream.resume();

Ce mécanisme fonctionne de manière assez fiable jusqu'à présent. La commande yes n'inondera plus la connexion. Il y a toujours un délai d'environ 0,5 seconde entre CTRL+C et l'arrêt réel de la commande dans les scénarios à haut débit, mais IMO c'est correct.

J'espère que cela aide.

@tandatle Consultez également la documentation sur le contrôle de

Edit: Désolé, j'ai oublié votre remarque sur les documents. Voulez-vous expliquer ce qui n'est pas clair? Oui, la section websocket n'est qu'un stub (pas d'extrait prêt à l'emploi), car je n'ai pas quoi créer des tonnes d'extraits pour différentes bibliothèques de socket et des besoins personnalisés (c'est difficile à faire correctement avec les websockets pour des raisons de sécurité uniquement) . N'hésitez pas à ajouter un extrait de code concret, qui couvre ces aspects.

@mofux @jerch Merci pour votre aide.
Je n'utilise pas node.js en backend, mais un processus écrit en C ++, donc je devrai peut-être faire quelques investigations supplémentaires pour choisir entre utiliser XON / XOFF et implémenter la gestion de backpresure dans mon processus backend.
Merci beaucoup.

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

circuitry2 picture circuitry2  ·  4Commentaires

jerch picture jerch  ·  3Commentaires

fabiospampinato picture fabiospampinato  ·  4Commentaires

johnpoth picture johnpoth  ·  3Commentaires

LB-J picture LB-J  ·  3Commentaires