„Wenn ein Arbeiter seine Arbeit gut machen will, muss er zuerst seine Werkzeuge schärfen.“ – Konfuzius, „Die Gespräche des Konfuzius. Lu Linggong“
Titelseite > Programmierung > NodeJS + ROHC

NodeJS + ROHC

Veröffentlicht am 31.07.2024
Durchsuche:152

Von der Idee bis zur Umsetzung

Ich möchte Ihnen meine Idee vorstellen und wie es dazu kam, „ROHC“ eine Bindung in NodeJS zu geben.

Ich wollte ein VPN implementieren, das über Web-Socket läuft. Die Vorteile wären, dass der Dienst über HTTPS verborgen wäre. Mit HTTP3 wäre dies noch optimierter. Also fing ich an, mit dem TunTap2-Modul für NodeJS herumzuspielen, das ich zuerst patchen musste.

Ich war schon immer von der drahtlosen Technologie fasziniert und bin irgendwann auf „LoRa“ und damit auf ein Projekt „IP2Lora“ gestoßen.

Image description

Bildquelle

In diesem Projekt „IP2Lora“ wurden die IP-Pakete gekürzt, um 40 Bytes einzusparen, was für die Übertragung sehr wichtig ist; mit einem Funkband von 434 MHz oder 868 MHz kann nicht so viel übertragen werden.

NodeJS   ROHC

Bildquelle

In der Grafik ist deutlich zu erkennen, wie die IP-Paketgröße abnimmt.

Leider gab es nur eine lib-Bindung für Python.

Warum also nicht selbst eine Node-Lib-Bindung schreiben?

Das Ergebnis ist nun sichtbar.
https://www.npmjs.com/package/node-rohc

Mehr über die Funktionsweise von ROHC erfahren Sie in den Links zum Projekt oder suchen Sie einfach danach. Ich werde es hier nicht erklären, um den Beitrag nicht zu lang zu machen.

Installationsbibliothek

Ich habe unter Linux Debian/Mint installiert. Ich denke, das sollte ähnlich wie bei anderen Linux-Versionen sein.

(Übrigens musste ich auch die ROHC-lib auf den neuen Kernel patchen.)

sudo apt-get install autotools-dev
sudo apt-get install automake
sudo apt-get install libtool
sudo apt-get install libpcap-dev
sudo apt-get install -y libcmocka-dev

git clone https://github.com/stefanwerfling/rohc.git
cd rohc

./autogen.sh --prefix=/usr

make all
sudo make install

NPM-Installation

Jetzt können wir in unser Projekt gehen und das Modul installieren.

cd yourProject
npm i node-rohc

Jetzt müssen wir die NodeJS-Bindung erstellen (diese muss für jede CPU-Architektur selbst kompiliert werden).

cd yourProject/node_modules/node-rohc
npm run build --loglevel verbose

Die Installation ist nun abgeschlossen.

Codierung/API-Nutzung

Nehmen wir nun an, wir erhalten ein IP-Paket, das wir in die folgenden Pakete komprimieren möchten, um Bytes zu sparen.

const ipU8Packet = new Uint8Array(ipPacketBufferWithContent);
console.log(ipU8Packet);
Uint8Array(52) [
   69,   0,   0,  52,   0,   0,   0,   0,  64,  6, 249,
  112, 192, 168,   0,   1, 192, 168,   0,   2, 72, 101,
  108, 108, 111,  44,  32, 116, 104, 105, 115, 32, 105,
  115,  32, 116, 104, 101,  32, 100,  97, 116, 97,  32,
  112,  97, 121, 108, 111,  97, 100,  33
]

Das Modul wird nun importiert und das Unit8Array, in dem das IP-Paket zur Komprimierung an das Rhoc-Objekt übergeben wird.

import {Rohc} from 'node-rohc';

const r = new Rohc([
  RohcProfiles.ROHC_PROFILE_UNCOMPRESSED,
  RohcProfiles.ROHC_PROFILE_IP,
  RohcProfiles.ROHC_PROFILE_TCP,
  RohcProfiles.ROHC_PROFILE_UDP,
  RohcProfiles.ROHC_PROFILE_ESP,
  RohcProfiles.ROHC_PROFILE_RTP
]);

try {
    const compress = r.compress(ipU8Packet);
    console.log(compress);
} catch (e) {
    console.error(e);
}
Uint8Array(53) [
  253,   4,  69,  64,   6, 192, 168,   0,   1, 192, 168,
    0,   2,   0,  64,   0,   0,  32,   0, 251, 103,  72,
  101, 108, 108, 111,  44,  32, 116, 104, 105, 115,  32,
  105, 115,  32, 116, 104, 101,  32, 100,  97, 116,  97,
   32, 112,  97, 121, 108, 111,  97, 100,  33
]

Im Konstruktor des Rohc-Objekts geben wir die Profile an, die zur Komprimierung in einem Array verwendet werden sollen.

Dann kommt die Komprimierung. In der Ausgabe sehen wir das neue Paket. Aber warum ist es nicht kleiner?

Das erste Paket enthält noch die Informationen zu Port/IP-Adresse etc. Lediglich die folgenden Pakete werden deutlich kleiner.

Um das Rohc-Paket wieder in ein normales IP-Paket umzuwandeln, verwenden wir Dekomprimierung.

try {
    const decompress = r.decompress(compress);
    console.log(decompress);
} catch (e) {
    console.error(e);
}
Uint8Array(52) [
   69,   0,   0,  52,   0,   0,   0,   0,  64,  6, 249,
  112, 192, 168,   0,   1, 192, 168,   0,   2, 72, 101,
  108, 108, 111,  44,  32, 116, 104, 105, 115, 32, 105,
  115,  32, 116, 104, 101,  32, 100,  97, 116, 97,  32,
  112,  97, 121, 108, 111,  97, 100,  33
]

Wichtig ist der Anfang, das erste Paket wird komprimiert und an das Ziel übertragen und das Ziel hat das Paket dekomprimiert, die Instanz muss beibehalten werden. Damit die Verbindungs-ID bekannt bleibt. Das bedeutet, dass das Programm die Objektinstanz am Laufen halten muss. Wenn eine der beiden Seiten (Quelle mit Komprimierung oder Ziel mit Dekomprimierung) gestoppt wird, müssen beide Seiten neu gestartet werden.

Zusätzliche Funktion mit nützlichen Informationen:

Letzter Komprimierungs-/Dekomprimierungsstatus

import {Rohc, RohcStatus} from 'node-rohc';

    if (r.getLastStatus() === RohcStatus.ROHC_OK) {
      console.log('All OK');
    }

Während der Komprimierung oder Dekomprimierung wird der Status gespeichert; Dies kann direkt im Anschluss noch einmal abgefragt werden, um detailliertere Informationen zum Geschehen zu erhalten.

Letzte Informationen zum Komprimieren/Dekomprimieren des Pakets

console.log(r.compressLastPacketInfo());
console.log(r.decompressLastPacketInfo());
{
  version_major: 0,
  version_minor: 0,
  context_id: 0,
  is_context_init: true,
  context_mode: 1,
  context_state: 1,
  context_used: true,
  profile_id: 4,
  packet_type: 0,
  total_last_uncomp_size: 52,
  header_last_uncomp_size: 20,
  total_last_comp_size: 53,
  header_last_comp_size: 21
}
{
  version_major: 0,
  version_minor: 0,
  context_mode: 2,
  context_state: 3,
  profile_id: 4,
  nr_lost_packets: 0,
  nr_misordered_packets: 0,
  is_duplicated: false,
  corrected_crc_failures: 11745388377929038000,
  corrected_sn_wraparounds: 14987979559889062000,
  corrected_wrong_sn_updates: 12105675798372346000,
  packet_type: 449595,
  total_last_comp_size: 18407961667527770000,
  header_last_comp_size: 1940628627783807,
  total_last_uncomp_size: 18407961667125117000,
  header_last_uncomp_size: 217316637802623
}

Informationen zur letzten Komprimierung oder Dekomprimierung.

Allgemeine Komprimierungs-/Dekomprimierungsinformationen

console.log(r.compressGeneralInfo());
console.log(r.decompressGeneralInfo());
{
  version_major: 0,
  version_minor: 0,
  contexts_nr: 1,
  packets_nr: 1,
  uncomp_bytes_nr: 52,
  comp_bytes_nr: 53
}
{
  version_major: 0,
  version_minor: 0,
  contexts_nr: 1,
  packets_nr: 1,
  comp_bytes_nr: 53,
  uncomp_bytes_nr: 52,
  corrected_crc_failures: 0,
  corrected_sn_wraparounds: 8518447232180027000,
  corrected_wrong_sn_updates: 4295000063
}

Allgemeine Informationen zur Komprimierung und Dekomprimierung.

Letztes Wort

Ich hoffe, Ihnen hat mein kleiner Beitrag gefallen. Ich bin immer offen für Verbesserungen.

Freigabeerklärung Dieser Artikel ist abgedruckt unter: https://dev.to/stefanwerfling/nodejs-rohc-11k3?1 Bei Verstößen wenden Sie sich bitte an [email protected], um ihn zu löschen
Neuestes Tutorial Mehr>

Haftungsausschluss: Alle bereitgestellten Ressourcen stammen teilweise aus dem Internet. Wenn eine Verletzung Ihres Urheberrechts oder anderer Rechte und Interessen vorliegt, erläutern Sie bitte die detaillierten Gründe und legen Sie einen Nachweis des Urheberrechts oder Ihrer Rechte und Interessen vor und senden Sie ihn dann an die E-Mail-Adresse: [email protected] Wir werden die Angelegenheit so schnell wie möglich für Sie erledigen.

Copyright© 2022 湘ICP备2022001581号-3