yEnc - Entstehung und Hintergründe

Wenn man sich yenc.org so ansieht drängt sich der Verdacht auf, daß die ganze Sache ziemlich unausgegoren und zusammengestöpselt ist. Und wenn man mit der Entstehungsgeschichte nicht vertraut ist, kann schnell der Eindruck entstehen daß hier mit heißer Nadel ein Notbehelf zusammen gestrickt worden ist.

Ich erlaube mir hier die Gründe darzulegen, wie es überhaupt zu yEnc gekommen ist - und warum es so aussieht, wie es sich derzeit darstellt. Vielleicht relativiert sich manches bei näherer Betrachung. Auf jeden Fall sei versichert daß es sich hier nicht um einen unüberlegten Schnellschuß handelt. yEnc basiert auf der Erfahrung vieler Personen. Und auf jahrelanger Erfahrung des Authors in den Binary Newsgroups.

** Der erste Ansatz
Binäre Daten - gleich welcher Art - werden für die Übertragung im Usenet aufwendig kodiert. Aufwendig im dem Sinne, daß aus einer 100 kB Datei eine 140 kB große Datei wird. Denn das am weitest verbreitete KodierungFormat (UUencode) macht aus 45 Bytes jeweils 62 Zeichen. Dies ist eine drastische Verschwendung von Ressourcen - und man fragt sich, warum dem nicht schon längst abgeholfen wurde.
Da andere Protokoll auch binäre Daten direkt übertragen können stellt sich die Frage, warum man das nicht auch in NNTP implementiert. Da aber hierzu einschneidende Änderungen am Message-Format und/oder NNTP-Protokoll nötig wären, scheidet dieser Weg aus. (Beide TaskForces lehnen solche Änderungen ab).

Als Alternative besteht die Möglichkeit, die Daten mit einem erweiterten Zeichensatz zu kodieren. Hierbei werden nur die notwendigsten Zeichencodes vermieden. Einige erfahrene Admins & Programmer sind der Meinung daß das Usenet eigentlich im Stande ist, bis auf NULL, CR und LF alle Zeichen verlustfrei zu transportieren. Sie ermutigen einen dazu, weitere Untersuchungen anzustellen. 
Ein möglicher Ansatz hierbei wäre es, das QP-lite Verfahren (quoted prinatble 8 bit) zu nutzen, das nur diese Zeichen kodiert. Leider ist QP-lite nicht spezifiziert - es wird nur darüber geredet. Es gibt auch verschiedene Schwierigkeiten damit, weil es natuerlich so nicht in die existierenden Standards hinein passt. Zudem ist das Verhalten der existierenden Klienten völlig ungeklärt.
Ein kritscher Punkt hierbei ist noch dass gerade NULL ein häufig vorkommendes Zeichen ist, so daß seine Kodierung unter Umständen viel Overhead erzeugen kann.

** Das fundamentale Kodierungsverfahren.
Eine kleine Untersuchung der 'üblichen' Binaries (Jpeg, Mpeg, Avi, Zip) zeigt, dass verschiedene Codes (00, 01, FF, FE, E0, 7F, 80) überdurchschnittlich häufig auftreten. Bei einer 'einfachen' Kodierung besteht durchaus die Gefahr unangemessenen Overhead zu erzeugen. Die Methode der vollständigen Analyse der Quelldatei und einer dynamischen Kodierung wird verworfen, weil dies enorm komplex und auch zeitaufwendig wird. Immerhin sind bis zu 500 MB große Videodateien zu analysieren.
Eine einfache Lösung scheint der Ansatz zu sein, die Zeichencodes zu rotieren. Es zeigt sich das die Addition von 42 die kritschen Codes aus der Escape-Zone befördert. (Andere Faktoren bringen den gleichen Effekt).

** Zeilenlängen
NNTP-Server haben natürliche Beschränkungen für die Länge von Datenzeilen. Daher müssen die kodierten Daten von Zeit zu Zeit durch CRLF in neue Zeilen umgebrochen werden. Nach diversen Rückfragen zeigt sich, daß die Wünsche Anderer von 60 Zeichen pro Zeile über 255 Zeichen pro Zeile bis zu 999 Zeichen pro Zeile gehen. Natürlich sollten die Zeilen so lang wie möglich sein, weil ja auch die Zeilentrenner Overhead erzeugen. Und um flexibel zu sein fällt die Entscheidung die Zeilenlänge ins Ermessen des Kodierungsprogramms zu stellen. Dafür aber die tatsächlich verwendete Zeilenlänge mit im Format unterzubringen. Das erlaubt es auch eines Tages eine Zeilenlänge von 100.000 anzugeben - und Klienten die damit nicht fertig werden können die Bearbeitung definiert verweigern.

** Datenintegrität
Da es völlig unklar ist, ob derart kodierte Daten richtig im Usenet und in angeschlossenen Systemen übertragen werden können, müssen zusätzliche Sicherungsmaßnahmen ergriffen werden.
Da es als zusätzliches Problem immer wieder vorkommt, dass Nachrichten in der langen Kette der Usenet-Server nicht fehlerfrei weitergeleitet werden (gleich aus welchen Gründen) kann auch dieses drängende Problem gleich mit abgehandelt werden.
Die Lösung besteht darin, daß die Länge der kodierten Nachricht mit im Format untergebracht wird. Für noch bessere Prüfungen ist es möglich den CRC32 Wert einer Nachricht ebenfalls hinzuzufügen.
Damit ist jedes Teil der Übertragungskette über Zeilenlänge, Gesamtlänge und CRC32 die Fehlerfreiheit festzustellen und ggf. sogar genauere Fehleranalysen zu erlauben. (Denn nur 'ist kaputt' ist auch nicht immer hilfreich).

** Single Message Format
Um die kodierten Daten sauber übertragen und wieder dekodieren zu können ist es notwendig, sie in einen definierten Rahmen zu fassen. Da yEnc aus Gründen der Datenintegrität zusätzliche Informationen enthält, sind eigene HeaderDaten nötig. Um nicht ins Header-Format - gleich welchen Transportweges - einzugreifen bietet es sich an, die Daten mit eigenen Headern zu versehen. Der Weg den MIME dabei beschreitet ist vorbildlich, kann jedoch nicht verwendet werden, da dann immer die Header-Daten einer Nachricht zum Kodieren nötig sind. Zudem ist MIME recht komplex und bei einigen Programmierern (nicht nur bei mir) unbeliebt. Es wurde mir auch definitiv von einer Verwendung von MIME abgeraten. Da es auch noch andere Gründe gibt, wurde ein vereinfachtes Format gewählt, daß sich am bisher verwendeten UUencode Standard orientiert:
Die ehemalige 'begin' Zeile wird formalisiert, unverwechselbarer gemacht und enthält alle notwendigen Informationen um die binären Daten unter allen Umständen sauber dekodieren zu können. Da geht auch dann, wenn keine Message-Header mehr vorhanden sind - oder die Nachricht auf anderen Wegen (gleich welchen, Hauptsache 8bit fest) übertragen wird. Es ist sogar möglich solche Daten in HTML/XML unterzubringen!
Auf diesem Wege ist es sogar möglich Text vor oder hinter den Daten zu erlauben oder mehrere Datenblöcke zusammen zu fassen (mehrere Dateien in einer Nachricht). Das würde es sogar erlauben, eine komplette HTML Seite mit allen Zusatzdaten (Bildern) in einer Nachricht zu versenden.

** Multipart, Splitting und Joining
Sehr viele Binaries sind heutzutage länger als Usenetserver das erlauben oder verkraften. Daher werden Nachrichten mit mehr als 100/250/500 kB traditionell gesplittet.
Leider ist dieses Splitting für UUencode nur sehr rudimentär definiert - und MIME-Splitting hat seine ganz eigenen Tücken. Auf der Suche nach einem Multipart Format daß von allen Systemen verarbeitet werden kann und sich auch noch für andere Transportwege eignet zeigt sich daß es das Beste ist, komplette Datenblöcke herzustellen: Die Nachricht wird in Teile zerschnitten - jeder Teil hat seine eigenen Kenndaten (Länge, CRC). Auch hat jeder Teil seinen definierten Anfang (=ybegin) und sein definiertes Ende (=ybegin), so dass es wieder möglich ist, Zusatztexte am Anfang oder Ende hinzuzufügen (was manche Usenet-Server mit Leidenschaft tun) ohne die Integrität der Daten zu zerstören.
Die Sicherung der Integrität der gesplitten Daten hat sogar noch einen wichtigen Zusatznutzen: Ist ein Teil einer 50-teiligen Nachricht geschrottet, dann reicht es, diesen einen Teil (aus einer anderen Quelle) nachzuladen - oder erneut anzufordern. Alle bisherigen Verfahren basieren darauf, dass beim geringsten Fehler alle 50 Teile neu angefordert werden müssen (und das normalerweise auf dem selben Versandwege). Durch die Universalität von yEnc ist es möglich, einzelne Teil auf anderen Wegen zu erhalten und damit Lücken zu füllen.

Eine extreme Vision ist es, daß der Empfänger von einer 50-teiligen Nachricht nur 48 Teile erhält. Andere Empfänger haben nur 47 Teile erhalten - und es fehlen andere Teile. (Das Usenet 'vergisst' gerne mal ganze Nachrichten - aus verschiedenen Gründen - ein weiteres, drängendes Problem). Sendet nun ein User die ganze Nachricht noch einmal, so ist es mit yEnc möglich, die fehlenden Stücke zu ergänzen. Hierfür sorgen exakte Positionsangaben für die einzelnen Teile. Auch hier klappt das wieder sogar dann wenn andere Wege benutzt werden - oder sogar mit anderen Parametern (andere Splitting-Größe) gearbeitet wird.
Hierzu ist es natürlich notwendig die Identität der Ausgangsdatei sicherzustellen - was durch einen globalen CRC32 und eine globale Größenangabe erreicht werden kann. 
Diese Vision ist in der heutigen Variante noch nicht definiert - aber bereits vorgesehen.

** Übergangsphase und existierende Tools
Die Einführung eines neuen Kodierverfahrens ist aussichtslos, wenn nicht 'ab sofort' damit gearbeitet werden kann, sondern erst alle beteiligten Tools untersucht oder sogar verändert werden müssen. Ein 'Zeitpunkt' zur Umstellung ist bei der Vielzahl der Werkzeuge nicht mehr möglich. Darum muß die Umstellungsphase besonders berücksichtigt werden.
Sendende Tools müssen selbstverständlich erweitert werden - aber hierbei reichen einige wenige HauptWerkzeuge aus. Wichtig ist, daß alle Empfänger die Nachricht empfangen und dekodieren können. In der ersten Zeit ist es unabdingbar, daß externe Dekoder diese Aufgabe übernehmen. Und dass diese sauber die Korrektheit erkennen können.
Alle NewsReader können Nachrichten abspeichern. Meist die vollständige Nachricht - oder wenigstens den enthaltenen Text. Beim Speichern mehrerer Nachrichten auf einmal kommt es zu Effekten, daß Trennzeichen oder Trennzeilen eingefügt werden. Oder im UUCP-Bag-Format gespeichert wird- oder ..... oder ... oder....  Die Reihenfolge der Speicherung kann auch noch von der gewählten Ansicht (Sortierung) abhängen. 
Beim Speichern von Multipart-Nachrichten kommt es oftmals noch zum Effekt, dass die gespeicherten Daten keine Header mehr enthalten - und damit die Information verloren geht, welcher Teil der Nachricht aus welcher (defekten?) Message stammt.
yEnc hat mit all diesen Effekten und Resultaten so gut wie keine Probleme: Es entdeckt die Blöcke zuverlässig. Es kann aus einem Datenbrei alle Dateien extrahieren - und alle Multiparts wieder zusammen setzen.

** Einfachheit der Programmierung
Um ein neues Kodierverfahren einzuführen sind Beispielprogramme nötig. Diese sollten so einfach wie möglich sein, damit potentielle Einsteiger nicht verschreckt werden. Auch Werkzeuge die bisher kein MIME unterstützen sollten einfach umgestellt/erweitert werden können. Die Implementierung eines 'einfachen' erweiterten UUdecoders ist immer schneller getan als eine komplette MIME Implementierung in einen AutoPoster oder NewsReader. 
Ohne Support durch die binäre Programmierergemeinde gibt es kein neues Format. Und diese Leute gehören nicht zur formal richtigen Fraktion. Hierbei handelt sich sich weitgehend um Freeware / Shareware Programmierer. Um diese Leute kommt man aber nicht herum. Also sind auch deren Bedürftnisse zu berücksichtigen, sondst kommt ein neues Format niemals in die Gänge und es bleibt für alle Zeiten bei UUencode.

** Erweiterung um Zusatznutzen
Nach der ersten Veröffentlichung der yEnc Idee kommt jede Menge Feedback von allen möglichen Seiten. Es gibt auch viele Wünsche das Format noch zu erweitern:
Adaptive Codierung (zur Vermeidung des Overheads bei extremen Dateien), vollständige Kompression, Addition von PARity Informationen und MIME-Einbettung sind die wichtigsten Anregungen. Da die meisten Wünsche die Komplexität sofort drastisch erhöhen würde, werden die Initiatoren um Geduld gebeten - und die Erweiterungen auf spätere Versionen vertröstet. Besonders der Gedanke eine automatischen Kompression ist natürlich bestechend - aber eben auch recht aufwendig. Trotzdem sollten Erweiterungen von vorne herein mit berücksichtigt werden. Der Wunsch nach MIME wird vielfach geäußert, daher werden hierzu spezielle Schritte eingeleitet.

** Einbettung in MIME.
Da MIME als Standard Format für Nachrichten eingeführt ist, sollte es möglich sein, yEnc darin unter zu bringen. Dies ist leider nicht so einfach wie es sich anhört. Die Meinungen wie man das am Besten tut gehen weit auseinander. Gemeinsam ist allen Vorschlägen, daß sie Sätze enthalten wie "Verstößt gegen diese Regel" - "Geht damit nicht" - "Verursacht diese Probleme" - "Weiss ich nicht" - "Wird audrücklich nicht empfohlen".
Da es Fachleute für MIME gibt, die sich wohl in MIME Newsgroups treffen, wird versucht, dort die notwendige Hilfe zu bekommen. Leider stammen diese Leute von der "Mail-Fraktion" - und haben wenig Verständnis für die sich ergebenden Besonderheiten. Schon bei so einfachen Themen wie "welchen Dateinamen verwendet man" zeigt sich die Problematik: Ein MIME-Dekoder der yEnc noch nicht versteht wird die Datei unter dem angegebenen Namen speichern. Das ist dann aber der falsche Name, weil diese Datei noch kodiert ist - und eigentlich unter einem anderen Namen gespeichert werden müßte. Denn sonst kann sie nicht im selben Verzeichnis dekodiert werden ohne sich selbst zu überschreiben. Wenn der 
Encoder jedoch einen um *.yenc erweiterten Dateinamen verwenden würde, muß als genereller MIME-Type  octet-stream/application  verwendet werden um einen externen Dekoder anzusteuern. Das bricht aber mit dem Konzept für neue MIME-Reader die yEnc bereits erkennen. Die Umstellungsphase würde schlicht katastrophal. 
Es hat seinen guten Grund dass die Einführung neuer Transfer-Encodings nicht empfohlen wird. Leider lebten wir dann bis ans Ende aller Tage mit dem Overhead.

Natürlich hört man von MIME-Leuten auch den Vorwurf, dass yEnc redundante Informationen enthält, wenn man komplette MIME-Blöcke von '=ybegin' bis '=yend' in MIME einkapselt. Es wird einem wärmstens empfohlen, diese wegzulassen - und nur die normierten MIME-Header zu verwenden. Wie aber ein externer Encoder dann die Nachricht (ohne Header) dekodieren soll, kann einem natürlich niemand erklären. Und das Zuordnen von Fehlern zu Nachrichten ist dann auch nicht mehr möglich. Die übliche Empfehlung ist dann: Dann muss eben der Newsreader geändert werden. Leider auch wenig hilfreich für die Umstellungsphase.

Zu dieser Zeit meint man endgültig auf dem falschen Dampfer zu sein und beginnt das (unterdessen spezifizierte) QP-lite Verfahren näher zu untersuchen. Da dies ja nur mit MIME funktioniert müßte es ja problemlos gehen. Leider stellt sich heraus, daß bereits existierende Werkzeuge (Agent, Outlook Express) große Probleme mit MultiParts haben. Es ist notwendig, unkorrekte Nachrichten zu erzeugen um das identische Binary zu dekodieren, weil ansonsten mal ein CRLF eingefügt wird. Auch ist dieses Verfahren recht anfällig gegen die von manchen News-Server eingefügten 'Trailer'. Also scheint auch dieser Dampfer in die falsche Richtung zu dampfen. Denn ein Dekoder dessen Verhaltenweise schon heute nicht vorhergesagt werden kann eignet sich wenig für eine Umstellungsphase oder spätere Erweiterungen. Also wieder zurück zum Konzept der völligen Einbettung von yEnc in MIME. Denn diesem Verfahren macht es nichts aus, wenn die existierenden Werkzeuge was dazu dichten.

Übrigens konnte meine Frage, wie man _einzelne_ Messages eines Multiparts mit MIME gegen fehlerhafte Übertragung absichert, bis heute niemand beantworten. Die 'Content-MD5' sichert nur das gesamte Binary ab - und seine Verwendung in MultiPart ist sogar definitiv untersagt.
Was ein MIME-Decoder so treibt, wenn er eine unvollständige Message dekodieren soll ist unklar. Das Hinzufügen von nachgeträglich geposteten Teilen ist ein Rätsel. Das Hinzufügen von auf anderen Wegen erhaltenen Teilen ist völlig im Dunkeln.

Es ist mir übrigens klar daß es sicherlich einen Weg gibt, das alles zu realisieren. Da dazu aber einige MIME-RFCs geändert werden müsen, oder _bewußt_ gegen anerkannte Regeln verstoßen werden muss, braucht es dazu erhebliche Geduld und Risikobereitschaft.
'Irgendwelche' Kodierungen im Usenet als große Text-Message zu versenden ist eine Sache - man macht sich gegebenenfalls unbeliebt. Aber MIME Regeln zu brechen - auf die sich wahrscheinlich viele Werkzeuge verlassen - ist eine ganz andere. Damit wird man innerhalb von kürzester Zeit gekillt.

Mein ganz persönlicher Horror ist, daß irgend eine MIME-Software nicht mit neuen Transfer Encodings zurecht kommt - und dann (weil diese Programmpfade niemals getestet wurden) einfach abstürzt. Dann sind yEncoded MIME Messages sogar ein DOS attack.

** Definition, Alfa- und Beta-Tests
Nach all diesen Erfahrungen - und endlosen Vorgesprächen, Untersuchungen und eMail Verkehr - habe ich mich hingesetzt und versucht den ganzen Haufen in einem yEnc-Draft zusammen zu fassen. Ihn gleich auch zu implementieren und auszuprobieren ist bei der Einfachheit der Konzeption nur das Werk eines Tages.
Die erste Veröffentlichung führt zur Erkennung einiger Schwachstellen, die sich in zusätzlichen Implementierungshinweisen niederschlagen. Ein kleines Team von 3/4 Programmierern diskutiert noch einige Tage per Mail und macht die Sache soweit fest. 
Mit der Erstellung von Beispielprogrammen zum Kodieren und Dekodieren, der Website und einem externen Dekoder für Windows ist die Sache fertig zum ersten Launch. Eine Newsgroup für Testposts wird erstellt - und einige TestPosts erweisen dass die erstellten Werkzeuge untereinander noch abstimmungsbedürftig sind. Größere Testposts in normalen Binary Gruppen erbringen letzte Probleme die auch beseitigt werden. Die Beteiligten benachrichtigen andere Programmierer über den Stand und fordern sie zur Implementierung auf. 

** Userakzeptanz
Den Benutzern des Usenet scheint es übrigens völlig wurscht zu sein, wie die Daten übertragen werden (MIME oder xxxx). Sie freuen sich darüber, dass es schneller geht - und dass höhere Sicherheit gegen defekte Nachrichten vorgesehen ist. (Sie wünschen noch am ehesten eine Erweiterung um eine gute Kompression um den Schritt über WinRAR, MsSplit oder WInZip umgehen zu können).

** Programmiererakzeptanz
Unterdessen haben sich bei mir einige Programmierer wichtiger Usenet-Software gemeldet. Und es kommen laufend welche dazu. Es ist abzusehen, dass yEnc relativ bald in den weit verbreiteten Freewaren und Sharewaren verfuegbar ist. Das freut einen natürlich - da diese Leute genau diejenigen sind, um die es geht. Anscheinend werden auch die Programmierer von Usern direkt aufgefordert yEnc-Support zu bieten. Und die Programmierer würden sich diese Arbeit wohl nicht machen wenn sie meine Ansätze für völligen Blödsinn hielten.

** Weiteres Vorgehen
Unterdessen hat mir ein "Weiser des Usenets" mitgeteilt hat, dass die einzige seiner Ansicht nach in Frage kommende Form der MIME-Implementierung darin besteht, die binären Daten zu verwenden, in ein neues Transfer-Encoding zu packen und ansonsten auf die regulären MIME Header zu vertrauen.
Das löst zwar von allen Dingen die hier angesprochen wurden nur das Problem der Bandbreitenverschwendung - wäre aber ein allerkleinster, erster Schritt. Da sich jemand die Mühe machen muss, einen RFC dazu zu verfassen, eine TaskForce zu gründen und die Sache mit allen Beteiligten abklären, wird noch sehr viel Zeit ins Land gehen, bis es hier weiter vorwärts geht. Hierbei kann ich auch nicht treibende Kraft sein, weil ich davon wirklich keine Ahnung habe. Da müssen richtige Fachleute für RFC & MIME ran.
Und wann das dann von wem auch immer implementiert wird steht in den Sternen. 

Die nächsten Schritte für yEnc sind die integrierte Kompression (wozu mir noch die PD-Ware fehlt) und die endgültige Sicherheit für MultiParts mittels globalem CRC. Es ist vorgesehen, die Vollständigkeit der Distribution von yEncoded Nachrichten zu verbessern (da hier sichergestellt werden kann, keine fehlerhaften Nachrichten zu verbreiten). Und die MultiHost-Reader müssen noch lernen, defekte Teile von Nachrichten automatisch zu eliminieren und auf anderen Wegen (von anderen Servern) zu beschaffen.

Aber ab jetzt geht es eher gemütlich weiter.......

-- 
Juergen Helbing, 06-12-2001