Stranger Than Usual

Schnelltesttest

Es ist ja schön, von zerforschung mal nicht nur die nächste Sicherheitskatastrophe berichtet zu bekommen.

Stattdessen haben die Daten des Paul-Ehrlich-Instituts genommen, wie zuverlässig verschiedene Covid-19-Schnelltestkits sind. Und das dann als einfache Web-App online gestellt. Man kann dort manuell die EAN eines Testkits eingeben oder die Kamera eines Smartphones (oder eine andere Kamera, aber ein Smartphone ist wohl am einfachsten) verwenden, um den Code zu scannen.

Dann wird einem gesagt, wie hoch die Erkennungsrate bei hoher Viruslast und bei anderen Viruslasten im Schnitt ist. Natürlich haben sie nicht alle im Handel befindlichen Tests in ihrer Datenbank (oder nicht alle EANs, weil derselbe Test aus verschiedenen Gründen unter unterschiedlichen EANs auftaucht), deswegen kann man auch helfen und die Datenbank erweitern.

Letzteres scheint laut twitter jetzt zu einer überwältigenden Menge an Zuschriften geführt zu haben.

Der Test, den ich immer benutzt habe erkennt jedenfalls Infizierte mit sehr hoher Viruslast zu 100% und im Mittel über alle Viruslasten Infizierte zu 62%, was recht gut ist, wenn man bedenkt, dass letzterer Wert bei einigen Tests nur bei unter 20% liegt.

Die Zeugnishashblockchain

Zerforschung hat einen Haufen Sicherheitslücken in einem Projekt zu digitalen Zeugnissen gefunden. Auf die Sicherheitslücken möchte ich hier nicht eingehen. L. Wittmann wird hier zitiert mit:

Primär zeigt das alles mal wieder, dass die Bundesverwaltung oder in dem Fall das BMBF über keinerlei Digitalkompetenz verfügt und somit nicht fähig ist, solche Projekte zu beauftragen und zu steuern oder gar fachliche Entscheidung zu treffen.

Man hört eine gewisse Frustration heraus.

Wtf blockchain?

Aber ich will hier hauptsächlich auf einen Aspekt eingehen: Eine Blockchain in dem Projekt. Vielleicht hätte man den Aufwand, den man in den Blockchain-Krams gesteckt hat, lieber in einen Sicherheitsaudit stecken sollen. Denn eine Blockchain ist hier meines erachtens völlig nutzlos. Warum?

Fangen wir erst einmal an, wie die Bundesdruckerei die Sache beschreibt:

Die PDF-Datei wird vom System mit einer eingebetteten maschinenlesbaren XML-Datei in einem standardisierten Format angereichert. […] Anschließend wird die Datei über einen Genehmigungsworkflow von den verantwortlichen Stellen (zum Beispiel eine Prüfungskommission oder eine Schulleitung) freigegeben und zentral durch das System der Bundesdruckerei digital signiert.

So weit, so gut. An dieser Stelle hat man schon ein Zeugnis, das von der Bundesdruckerei signiert wurde. Rein theoretisch könnte man hier aufhören. Die Bundesdruckerei kann ihren öffentlichen Schlüssel veröffentlichen, damit kann jeder überprüfen, ob eine gegebene Zeugnisdatei echt ist.

Und so ist das auch gedacht:

Hiermit kann [ein Zeugnisempfänger] sich bei einer Institution bewerben, die die Gültigkeit bei Erhalt entweder offline durch Prüfung der PDF-Signatur im PDF-Reader oder online über die Prüfseite der Bundesdruckerei verifizieren kann.

Aber das ist nicht alles, davor kommt noch folgender Teil:

Daraufhin wird die Prüfsumme der Zeugnisdatei errechnet und zusammen mit der eindeutigen Identität der ausstellenden Institution dauerhaft und unveränderbar in die Blockchain geschrieben.

Warum zur Hölle brauchen wir das? Gehen wir mal theoretisch mögliche Gründe durch.

Invalidierung

Was ist, wenn die Bundesdruckerei ein Zeugnis nachträglich ungültig machen will? Zum Beispiel in einem Betrugsfall? Da reicht dann die alleinige offline-Validierung nicht aus.

Man könnte höchstens den Schlüssel, mit dem das Zeugnis unterschrieben wurde, für ungültig erklären. Damit würde man aber einen Haufen anderer Zeugnisse auch ungültig machen. Wäre also doof.

Man bräuchte also eine Authorität, die sage, ob ein Zeugnis ungültig ist. Das wäre dann ja wohl die Bundesdruckerei. Und siehe da, die will ja auch eine API zum verifizieren bereitstellen.

Das Problem ist nur: Auch hier braucht man keine Blockchain. Es reicht, wenn die Bundesdruckerei eine Liste (aka „Datenbank“) mit Hashes von ungültig gemachten Zeugnishashes enthält. Dort kann dann einmal schnell nachgeschaut werden, ob das Zeugnis ungültig ist, wenn nicht, wird die Signatur überprüft und gut ist.

Die Idee von Blockchains ist, dass es eine große Gruppe von Akteuren gibt, die sich nicht gegenseitig trauen. In diesem Fall haben wir aber eine Authorität, die sagt, wann ein Zeugnis gültig ist. Wir brauchen keine verteilte Blockchain dafür. Und eine private Blockchain ist vollkommen nutzlos, weil man wie gesagt einfach eine Datenbank von Zeugnishashes braucht.

„Aber was ist, wenn wir nicht wollen, dass jemand rückwirkend alte Einträge ändert? Wir wollen überprüfen können, dass die Bundesdruckerei nicht schummelt!“.

Auch hier ist eine Blockchain nicht das richtige Werkzeug. Eine private Blockchain könnte genau so gut gefälscht werden, weil die Bundesdruckerei die alleinige Kontrolle über sie hat. Eine öffentliche Blockchain wäre ein riesiger Overhead im Verhältnis zu einer ganz einfachen, schon lange existierenden Technik: ein ewiges Logfile.

Technisch viel einfacher handhabbar, und die Bundesdruckerei müsste nur regelmäößig den letzten Hash veröffentlichen. So kann z.B. bei einem Audit nachgeprüft werden, dass niemand an den Daten herumgepfuscht hat.

Datenschutz

Wenigstens ist bei dem ganzen Projekt das Datenschutzkonzept erstzunehmen (soweit ich das beurteilen kann), was durchaus nicht selbstverständlich ist. Statement auf der Projektseite:

[Digitale Schulzeugnisse] müssen fälschungssicher, datenschutzkonform und leicht zu überprüfen sein.

Solche Statements sind üblicherweise mit Vorsicht zu genießen, weil sie meist nicht mehr als heiße Luft sind.

Bei diesem Ansatz hier sehe ich aber tatsächlich kein Problem. Das Zeugnis ist weder von der Bundesdruckerei abrufbar, noch speichern sie es überhaupt dauerhaft ab. Zur Verifizierung wird nur ein Hash des Zeugnisses abgelegt, aus dem man das Zeugnis nicht rekonstruieren kann. Wenn es also bei der Validierungsplattform ein Datenleck gibt (was unweigerlich passieren würde, wenn man sich ansieht, das Zerforschung einige Anfängerfehler in der Plattform entdeckt hat), kommen wenigstens keine sensiblen Zeugnisdaten abhanden.

🇺🇦 Ich habe nicht geglaubt, das Putin wirklich angreift

Vor acht Tagen noch hätte ich nicht geglaubt, dass Putin die Ukraine wirklich angreifen will. Ich hatte gedacht, der lässt nur seine Muskeln spielen um ein paar Zugeständnisse von der Ukraine, den USA, der EU und der Nato im Allgemeinen zu bekommen.

Jetzt haben wir einen echten Angriffskrieg direkt in Europa, und ich kan wirklich nicht beschreiben, wie ich mich dabei fühle. Es ist ein ganzer Eintopf aus negativen Gefühlen. Das es überhaupt möglich ist, dass zwei moderne Nationen noch einen solchen Krieg führen. Dass Russland eiskalt behauptet, es ginge um „Entnazifizierung“ der Ukraine. Dass dort gerade Menschen sterben. Dass Arbeitskollegen von mir um ihre Familien bangen. Dass Putin der der EU und den USA unangemessene Aggression vorwirft, weil sie Sanktionen gegen Russland verhängen, während er einen aggressiven Angriffskrieg gegen ein freies Land führt. Dass Vladimir Putin wirklich mit Atomwaffen droht.

Dass die Desinformation, die in den letzten Jahren sowieso immer schlimmer geworden ist, jetzt auch noch im Dienste des Krieges genutzt wird. Dass in Russland Demonstranten gegen den Krieg verhaftet werden und Medien, die abseits der Regierungslinie berichten, abgeschaltet werden. Dass der russischen Wikipedia die Sperrung droht wegen ihres Artikels über den Angriff auf die Ukraine.

Und neben der ganzen humanitären Katastrophe der ganze Krieg Unmengen an Ressourcen verschlingt und vernichtet. Deutschland steckt viele Milliarden mehr in die Rüstung. Russland sowieso, andere Länder jetzt auch. Die Ukraine wird zerbombt. Das alles zerstört Werte, zerstört Wohlstand, zerstört nachhaltig unsere Möglichkeiten, z.B. auf den Klimawandel zu reagieren.

Das ist vielleicht wenig im Vergleich dazu, dass gerade Menschen im Krieg sterben, aber es wird lange nachwirken. Jeder Euro, jeder Dollar und jeder Rubel der in einen Krieg fließt kann nicht sinnvoll eingesetzt werden. Jede Straße, jedes Haus das zerbombt wird muss teuer wieder aufgebaut werden. Das alles ist Geld, das nicht eingesetzt werden kann, um dafür zu sorgen, dass es der Menscheit besser geht. Das nicht eingesetzt werden kann, um die Umwelt zu erhalten. Es ist Verschwendung.

Ich habe auf so vielen Ebenen ein Problem mit diesem Krieg (oder auch mit anderen Kriegen). Ich will nicht mehr. Ich kann nicht mehr. Hört bitte endlich auf mit dem Scheiß!

Undertale — 6½ Jahre zu spät

Letzte Woche Sonntag habe ich zum ersten Mal Undertale gespielt.

Ich habe ja in den vergangenen Jahren immer mal wieder davon gehört, aber nie besonderes Interesse gezeigt. Meine Güte war das ein Fehler. Es ist ein großartiges Spiel.

Spoiler alert: Ich versuche, hier nicht allzuviele Informationen preiszugeben, aber aufgrund der Natur von Undertale ist es schwierig, komplett Spoilerfrei zu bleiben.

Was ist Undertale?

Undertale ist ein 2D-RPG im Retro-Stil, das 2015 erschienen ist. Man spielt ein Kind, dass in eine Höhlenwelt fällt, die von Monstern bewohnt ist und wieder heraus will.

Soweit erst einmal eine recht generische Geschichte. Das Kampfsystem ist schon etwas anderes. Es ist rundenbasiert, aber wenn Gegner angreifen, muss man ein kleines Herz, dass die eigene Seele repräsentiert, steuern um im bullet hell-stil den Attacken auszuweichen (wobei jeder Gegner einzigartige Attacken hat).

Das ist mal eine nette Abwechslung zu üblichen Kampfsystemen.

Viel außergewöhnlicher ist aber, was passiert, wenn man selber am Zug ist. Natürlich kann man kämpfen, die Monster töten und dadurch stärker werden.

Man kann aber stattdessen auch versuchen, den Kampf friedlich beizulegen. So kann man zum Beispiel gegnerische Hunde streicheln, Froschmonstern komplimente machen, einen depressiven Geist aufmuntern oder ein paar königliche Wachen dazu bringen, sich ihre Liebe zu gestehen.

Und wie man vorgeht, hat deutliche Auswirkungen auf den Spielverlauf. Denn Monster sind auch Personen, und wenn man mordend durch die Gegend rennt, flieht bald die ganze Bevölkerung des Untergrunds vor dem Spieler. Wenn man hingegen nicht einmal seinen ärgsten Feinden ein Haar krümmt, kann man auf dem Weg eine Menge Freunde machen.

Mehr kann ich nicht sagen, ohne zu viel vorwegzunehmen.

Warum gefällt mir das Spiel so?

Trotz der einfachen Grafik schafft es Undertale, einen wirklich in die Spielwelt eintauchen zu lassen. Das hat mehrere Gründe.

Die Charaktere, denen man begegnet sind liebenswürdig, meist etwas schrullig und haben alle ihre Stärken und Schwächen. Ich habe beim ersten Durchspielen von Anfang an kein Monster getötet, und es hat sich gelohnt. Nach diesem Durchspielen möchte ich nicht einmal ausprobieren, was passiert, wenn man anfängt, Monster zu töten (obwohl ich mich natürlich selber gespoilert habe um herauszufinden, was passieren würde).

Die Hintergrundgeschichte ist düster, und im Spielverlauf kann man sich die Geschichte aus vielen Puzzleteilen zusammensetzen, wobei je nach Spielart die Puzzleteile anders sind, teilweise ganz fehlen oder einen anderen Schwerpunkt haben

Man kann es mit Geduld, Freundlichkeit, Gnade und Zielstrebigkeit schaffen, das Leben aller zu verbessern. Oder man kann ein unaufhaltsames Monster sein, dem sich die größten Helden der Höhlenwelt entgegenstellen, damit die anderen Monster entkommen können.

Und die Musik hat es mir auch angetan. Der Entwickler, Toby Fox hat sie selber komponiert. Verschiedene Charaktere und Geschehnisse haben häufig ein Thema, das je nach Situation anders interpretiert wird. Sobald man diese Musik erst einmal mit den emotionalen Ereignissen des Spiels verknüpft hat, kriegt man sie nur schwer wieder aus dem Kopf.

Empfehlung

Wer das Spiel noch nicht kennt: Ich kann nur empfehlen, es durchzuspielen ohne vorher auf Youtube Playthroughs anzuschauen und ohne sich auf der dazugehörigen TVtropes-Seite zu spoilern.

Es ist auf verschiedenen Plattformen verfügbar und kostet zwischen 10€ und 15€. Man muss es nicht auf Steam kaufen, um es auf dem PC spielen zu können, es geht auch über andere Plattformen.

Undertale lässt sich auch unter Linux und MacOS spielen, in meinem Fall (Ubuntu 21.10) musste ich aber manuell einige veraltete Bibliotheken herunterladen, um es zum Laufen zu bringen. Dazu war dieser Thread ganz hilfreich, der zwar für ein anderes Spiel ist, aber das gleiche Problem löst.

Reading a positive blogpost about Undertale fills you with determination.

Fragdenstaat.de gewinnt Rechtsstreit gegen BfR

1. Akt: Das Gutachten

Ich hatte im Mai 2019 schon davon berichtet: Fragdenstaat.de, eine Organisation, die staatliche Informationen via Informationsfreiheitsgesetz anfordert und dann veröffentlicht, musste ein Gutachten über Glyphosat wegen einer Urheberrechtsbeschwerde des Bundesinstituts für Risikobewertung (BfI) wieder offline nehmen.

Nun ist es natürlich absurd, dass ein Gutachten, das von Steuergeldern finanziert wurde, für politische Entscheidungsfindung genutzt wurde und für jeden, der es lesen will, per Anfrage einsehbar ist, nicht einfach offen im Netz stehen darf.

2. Akt: DDoS auf das BfR

Fragdenstaat.de hat daraufhin getan, was sie in solchen Fällen immer tun: Statt dem Gutachten haben sie ein Formular online gestellt, bei dem sich jeder eintragen wollte, der das Gutachten lesen will.

Die Idee dahinter: Wenn nur genug Leute das anfragen, hat die entsprechende Behörde keine Lust mehr, alle Anfragen einzeln zu beantworten und stellt die Dokumente entweder auf der eigenen Website frei zu Verfügung oder erlaubt fragdenstaat.de die Veröffentlichung.

Beim BfR hat das nicht so gut funktioniert. Obwohl innerhalb kürzester Zeit zehntausende Anfragen eingingen, hat das BfR die Dokumente nicht einfach online gestellt. Stattdessen haben sie eine Website mit Zugriffsschutz gebaut, die meiner eigenen Analyse nach absichtlich umständlich zu bedienen ist, einen (leicht zu umgehenden) Schutz gegen rechte Mausklicks hat und dazu noch nicht barrierefrei ist, weil die Dokumente nicht in einem Textformat, sondern als Bilddateien veröffentlicht wurden.

3. Akt: Freiklagen des Gutachtens

Fragdenstaat.de hat das natürlich nicht gereicht, also haben sie die Dokumente auch freiklagen wollen. Nach drei Jahren Rechtsstreit und mehreren Instanzen haben sie jetzt vor dem Bundesgerichtshof Recht bekommen.

Epilog: Die nächste Forderung von fragdenstaat.de ist, dass ein Gesetz verabschiedet wird, dass explizit regelt, dass Veröffentlichen behördlicher Dokumente immer urheberrechtlich zulässig ist. Das würde in Zukunft auch Gerichtskosten von mehreren hunderttausend Euro zu lasten des Steuerzahlers vermeiden.

Nebenbemerkung: Glyphosat

Mir geht es bei dieser ganzen Sache nicht um Glyphosat, sondern um Transparenz. Ich habe keine Ahnung von der Schädlichkeit oder nicht-Schädlichkeit von Glpyhosat. Ich habe auch keine Meinung dazu. Aber ich finde, um Vertrauen in Regierung, Verwaltung oder den Staat im Allgemeinen zu haben darf der Staat nicht den Eindruck machen, Informationen vorenthalten zu wollen.

Das besagte Gutachten ist nur wenige Seiten lang und bezieht sich hauptsächlich auf veröffentlichte wissenschaftliche Arbeiten. Es enthält keine brisanten neuen Informationen und wurde mit Steuergeldern finanziert. Es gibt keinen Grund, den Zugriff hier einzuschränken.

Wer aber eine schöne Zusammenfassung über Glyphosat haben möchte: maiLab hat dazu mal ein Video gemacht. Fazit: Verschiedene Institutionen kommen aus jeweils nachvollziehbaren Gründen zu unterschiedlichen Ergebnissen bezüglich Krebsrisiko.

Buchempfehlungen

Zurück aus dem Urlaub, zurück im Stress. Aber immerhin bin ich im Urlaub mal wieder zum Lesen gekommen. Darunter waren ein paar Bücher, die mir recht gut gefallen haben.

Immun

Da ist zunächst Immun. Ein populärwissenschaftlich geschriebenes Sachbuch über das (menschliche) Immunsystem.

In der Schule, über das Fernsehen und über Bücher habe ich in meiner Kindheit und Jugend nicht viel über das Immunsystem gelernt. Weiße Blutkörperchen hier, Antikörper und Imfpung da, ein bisschen was über Allergien, hier und da ist mal der Begriff „Macrophage“, „T-Helferzelle“ oder „T-Killerzelle“ gefallen, und das eine oder andere Schnipsel was das Immunsystem auch noch kann, habe ich auch mitgekriegt.

Aber das war alles sehr oberflächlich.

In Immun erklärt der Autor Philipp Dettmer das Immunsystem in deutlich größerem Detail und stellt auch die Zusammenhänge zwischen verschiedenen Teilen des Immunsystems dar. Ob es um eine Schnittwunde mit Bakterien geht, eine Influenza-Infektion in der Lunge, um parasitäre Würmer oder um eine einfache Überreaktion des Immunsystems: Alles wird detailliert erklärt.

Natürlich betont der Autor immer wieder, dass er ständig Dinge auslässt oder vereinfacht, weil das gesamte Thema einfach unglaublich komplex ist. Trotzdem geht das Buch viel Tiefer in die Details als alles, was ich bisher über das Immunsystem gelesen oder gesehen habe.

Dabei werden nach und nach an verschiedenen Beispielen erklärt, welche Aufgaben verschiedene Teile des Immunsystems haben, wie sie funktionieren und wie sie mit anderen Teilen zusammenarbeiten.

Nach und nach bildete sich in meinem Kopf so ein Bild des Immunsystems, ohne dass ich besonders viel Anstrengung investieren musste, es zu verstehen. Gut erklärt, also.

Ein weißer Schwan in Tabernacle Street

Als zweites ist da der achte Band aus der „Flüsse von London“-Reihe: Ein weißer Schwan in Tabernacle Street.

Urban-Fantasy vom Feinsten, ich habe dieses Buch genossen wie die anderen Bücher aus der Reihe. Dieses Mal geht um Hinterlassenschaften von Ada Lovelace und Charles Babbage, die außer des nie fertiggestellten analytical enginge auch noch eine andere Maschine entwickelt haben, die aber auch nie gebaut wurde. Oder vielleicht doch?

Humble Pi

Humble Pi: A Comedy of Maths Errors ist ein kurzes Buch über verschiedenste Auswirkungen von Berechnungsfehlern, Denkfehlern und anderen mathematischen Unachtsamkeiten, die zum Teil amüsante, aber zum Teil auch sehr teure oder gar tödliche Folgen hatten.

Darunter sind falsch interpretierte Statistiken, ingenieurstechnische Probleme wie z.B. Spiegelfassaden, die einen Parabolspiegel bilden, Verwechslung von Maßeinheiten, und natürlich auch die Lieblingsprobleme eines jeden Programmierers: Datums- und Zeitangabenmit Zeitzonen, Zeitumstellungen, und der Datumsgrenze sowie Off-By-One-Fehler.

⍼: Das Rätsel des Angzarr

Ich bin ja wie üblich zu spät dran mit solchen Dingen. Wenn im Internet gerade wieder eine Sau durchs Dorf getrieben wird, kriege ich davon wochenlang nichts mit.

Ausnahmen bestätigen die Regel. Dieser Fall ist aber keine Ausnahme. Mitte April gab es bei xkcd einen Comic, der so seine Späße mit verschiedenen unicode code points treibt.

Als ich das gelesen habe, kannte ich den Kontext eines der dargestellten Zeichen noch nicht: U+237C, benannt als RIGHT ANGLE WITH DOWNWARDS ZIGZAG ARROW. Auch bekannt als HTML-Entität &angzarr.

Die große Frage ist jetzt: Wofür soll dieses Zeichen stehen? Was bedeutet es? Woher kommt es?

Ein Student der University of British Columbia hat recherchiert und die Ergebnisse auf einem Blog veröffentlich.

Das Ergebnis: Selbst Leute, die daran mitgearbeitet haben, dieses Zeichen in Unicode aufzunehmen, wissen nicht mit Sicherheit, wofür es steht.

Verrottende Links

Verrottende Links sind im WWW ja eigentlich schon immer ein Problem. Da können sich Tim Berners-Lee und das W3C auch noch so sehr für stabile URLs einsetzen, manchmal gehen Seitenbetreiber einfach pleite und die Seite wird nicht länger betrieben.

In anderen Fällen scheren sich die Betreiber einfach nicht um stabile links. Meiner Erfahrung nach fallen darunter besonders Seiten von Zeitungen (ironischerweise, da man gerade die gerne als Quellen angeben möchte) und Webcomics (was mir bei der Benutzung von TVTropes immer wieder auffällt).

Im Laufe der Zeit habe ich in diesem Blog auf viele Seiten verlinkt. Momentan gehe ich gerade mal alte Posts durch um zu schauen, was tot ist, und was davon man vielleicht durch links auf die Internet Archive Wayback Machine ersetzen kann.

Ergebnis

Manche URLs kann man ohne Probleme ersetzen. Manche Links, ironischerweise auch der auf ein privates Blog, in dem seit 2018 nichts mehr geschrieben wurde (siehe hier) funktionieren immer noch Anstandslos.

Andere Links, auf damalige Berichterstattung bei gulli.com sind zwar nicht mehr erreichbar, weil es die Seite nicht mehr gibt, aber dummerweise auch nicht über die wayback machine, denn This URL has been excluded from the Wayback Machine..

Die WAZ hat auch ihr Linkschema geändert (hier verlinkt), aber war wohl nicht wichtig genug, um ins Internetarchiv aufgenommen zu werden. Der erste Eintrag zu dieser URL ist von 2021, und dort taucht schon nur noch die 404-Seite auf. Immerhin die ist archiviert :(

In einem besonders perfiden Fall war die URL zwar noch erreichbar, führte aber nicht mehr zur ursprünglichen Seite, sondern zu einem Onlineshop, der mit der ursprünglichen Seite nichts zu tun hatte.

Fazit

  1. Ich bin bis Ende 2009 gekommen
  2. Manche Seiten sind für immer verloren, da hilft selbst die wayback machine nicht weiter
  3. Durch alte Posts wühlen und nach URLs suchen ist mühsam. Ich sollte zumindest den Teil automatisieren, das sollte relativ leicht gehen.

Link-rot Teil 2

Wie kürzlich berichtet arbeite ich daran, tote Links aus meinem Blog zu beheben. Mittlerweile bin ich irgendwo in 2011.

Dummerweise gibt es einige Seiten, die auch auf archive.org nicht gelistet sind. Um dieses Problem in Zukunft so gut wie möglich zu verhindern (manche Seiten wollen auch nicht auf archive.org archiviert werden), habe ich jetzt, für alle funktionierenden Links (und auch Links in neuen Artikel) zu prüfen, ob sie auch archive.org zu finden sind und wenn nicht, die Zielseite dort zu archivieren.

Damit kann ich, falls die Seite irgendwann mal verschwindet, später die Links besser durch archive.org-Links ersetzen.

Falls irgendjemand auf Artikel meines Blogs linken sollte: Ich gebe mir Mühe, alle Links stabil zu lassen und habe nicht vor, diese Website offline zu nehmen. Trotzdem kann ich nur empfehlen, die Artikel meines Blogs auf archive.org zu sichern, wenn ihr mich verlinkt. Dieses Blog ist nicht bekannt genug, dass archive.org es von sich aus indziert.

Das kann man zum Beispiel hier unter „Save Page Now“ machen.

Archive.org hat ein Problem

Wo wir gerade von archive.org sprechen: die haben gerade eine Existenzbedrohende Millionenklage am Hals. Es geht, wie so oft, ums Urheberrecht.

Ich sollte mal wieder was an die Spenden. Das Internetarchiv ist ein wichtiges Instrument, damit wir zumindes einen Teil der toten Websites, aber auch alte Versionen neuer Websites erhalten. Als Archiv halt. Für die Nachwelt. Oder für jetzt, wenn ich feststelle, dass Artikel, die ich vor mehr als zehn Jahren geschrieben habe, haufenweise tote Links enthalten.

Es wäre wirklich, wirklich schlecht, wenn uns das verloren gehen würde.

Umzug nach Nijmegen

Nach siebeneinhalb Jahren in Hamburg bei freiheit.com habe ich jetzt einen neuen Job in den Niederlanden, eine Forschungsstelle in der Digital Security Group an der Radboud Universiteit (kurz „RU”).

Wie ist es dazu gekommen? Eine ehemalige Kommilitonin von mir ist dort jetzt Assistenzprofessorin, die suchten noch Leute, und ich wollte mal etwas Neues ausprobieren. Das ganze ist schon seit einigen Monaten geplant, um im August geht es los.

Passwörterwahnsinn

Für die Stelle an der Uni musste ich dort natürlich auch einen Account erstellen. Dafür brauchte ich ein Passwort. Um ein sicheres Passwort zu bekommen, lasse ich mir meist einfach eins generieren, in diesem Fall hiefai5Jae. Halbwegs zufällig, Groß- und Kleinbuchstaben, eine Ziffer, zehn Zeichen, keine echten Wörter.

Ziemlich sicher, sollte man meinen. Das System der RU hat strenge Passwortregeln. Ich bin nicht der Einzige, der solche Probleme hat, Bruce Schneier hat sie auch. Ich könnte einen ganzen Blogpost darüber machen, was sinnvoll ist und was nicht (ich habe mal einen Kurzvortrag darüber gehalten, kurze Zusammenfassung: keine Regeln außer einer Mindestlänge, dafür ein Wörterbuchcheck und ein check gegen Have I Been Pwned).

Es fehlte also ein Sonderzeichen, aber auch das hat nicht geholfen: hiefai5JaeFUCKYOUANDYOURSTUPIDPASSWORDRULES! wurde auch nicht akzeptiert. Password Purgatory hätte das nicht besser machen können.

Radwege und Stadtplanung

Aber zu erfreulicheren Themen: Ich fahre ja gerne mit dem Fahrrad zur Arbeit. In meiner Zeit in Hamburg war das der Regelfall. Zur Arbeit war das Fahrrad dort meine schnellste Option. Schneller als zu Fuß oder mit dem ÖPNV, schneller als mit dem Auto, wenn man Parkplatzsuche und weg vom/zum Parkplatz mitrechnet.

Über den ÖPNV in Hamburg kann ich mich meist nicht beklagen, der ist deutlich besser als in meiner Heimatstadt Essen. Die Fahrradinfrastrutkur ist auch besser, aber definitiv noch verbesserungswürdig. Radwege, die hin- und herschwenken, plötzlich aufhören oder plötzlich anfangen, wenn man vorher gerade auf die Straße gewechselt hat, dann aber unerreichbar sind, gefährliche Mischung aus Straße und Radweg, die zu einem beinahe tödlichen Unfall geführt hat… Das geht besser.

Und die Niederlande machen es besser! Als ich im März das erste Mal in Nijmegen war, sind mir sofort die guten Radwege und die Radschnellwege aufgefallen. Autos müssen außen herum, ÖPNV und Fahrräder können die kurze Route nehmen.

Und das kommt nicht von ungefähr: Dahinter stecken Planung und jahrzehntelange Verbesserung.

Not Just Bikes

Ein (mittlerweile ehemaliger) Kollege hat mich dann auf den Youtube-Kanal Not Just Bikes aufmerksam gemacht.

Der Macher dieses Kanals ist gebürtiger Kanadier, hat in vielen Städten auf der ganzen Welt gelebt und irgendwann begonnen, sich für Stadtplanung zu interessieren. Er ist in die Niederlande gezogen, weil ihm die dortige Stadtplanung gefällt.

Wie der Titel schon sagt: Es geht nicht nur um Fahrräder. Der Autor vergleicht an vielen Punkten die Stadtplanung Nordamerikas (USA und Kanada) mit der in den Niederlanden und teilweise auch anderen Ländern. Ihm geht es darum zu vermitteln, wie eine Stadt ein lebenswerter Ort wird, wie man die Autoabhängigkeit verhindert und warum sich das für Städte auch finanziell lohnen kann.

Das geht in Deutschland auch!

Die Vergleiche mit Deutschland kommen in dem Kanal ein bisschen zu kurz, aber ich habe einen Blogpost eines anderen Deutsch-Niederländers ausgegraben, in dem einmal detailliert dargestellt wird, was in den Niederlanden bei der Stadt- und Verkehrsplanung gut läuft, warum Deutschland jetzt gerade die Fahrradinfrastruktur der 80er baut und warum Argumente wie „wir haben keinen Platz dafür“ nur schlechte Ausreden sind.

Ich bin der Meinung, dass wir in Deutschland durchaus das Potential haben, unsere Fahrradinfrastruktur deutlich zu verbessern. Das geht natürlich nicht von jetzt auf gleich, die Niederlande haben dreißig Jahre Vorsprung. Auf der anderen Seite kann man sich bei denen jetzt wunderbar abschauen, was funktioniert und was nicht. Wir müssen also nicht viel neu erfinden, wir können uns auf Bewährtes verlassen.

Zum Ausklang hier noch ein Video von 2016 aus Nijmegen, dass die Fahrradinfrastruktur aus Sicht des Fahrradfahrers zeigt.

Klimaausfall

Gerade in einem IC von Deutschland in die Niederlande: Eine Durchsage, dass dieser Zug ausfällt, weil es einen Klimaausfall gibt und wir alle in Hengelo aussteigen müssen. Mehrmals wiederholt, auf Niederländisch und Deutsch. Und noch ein paar Mal wiederholt, damit es wirklich jeder mitgekriegt hat. Allerdings nicht auf Englisch wiederholt, weswegen ein paar Reisende trotzdem keine Ahnung hatten, was passiert.

Außerdem sei unser Ticket weiterhin gültig. Mag ja sein, aber meine Sitzplatzreservierung aber nicht. In Hengelo angekommen steht dann nämlich der nächste Zug schon da, ist aber natürlich komplett überfüllt und niemand kommt mehr rein.

Außerdem weiß ich garnicht, was es mit diesem „Klimaausfall“ soll. Am Bahnsteig gibt es jede Menge Klima. Mehr als genug für alle. Davon hätte man sicher ein paar Kilo in den Zug laden können.

Immerhin habe ich dann, nachdem ich ausgestiegen bin, eine Mail von der deutschen Bahn bekommen, dass mein Zug ausfällt. Hätte ich sonst nicht mitbekommen.

Fordite

Vor ein paar Monaten habe ich meine damaligen Kollegen vor ein Rätsel gestellt: Was habe ich versucht zu tun, als ich dieses Bild produziert habe?

Rechts sind Kreisteile zu sehen, links Farbstreifen mit Grenzen, die ebenfalls Kreise andeuten, aber die Mitte ist sehr chaotisch

Sieht kaputt aus, oder? Trotzdem kann man es als Kunst bezeichnen. Eine Entwicklerin/Künstlerin hat zum Beispiel schon mal gezielt den Firefox-Rendering-Code kaputt gemacht, um interessante Effekte zu erzielen. Notiz am Rande: Mir fällt gerade auf, dass diese Entwicklerin auch so ein rust-Fan ist und ein paar interessante Artikel geschrieben hat.

In diesem Fall war es aber keine Absicht, und auch nicht das Ergebnis von korrumpierten Daten, sondern einfach die ersten Ergebnisse von code, der noch nicht ganz ausgereift war.

Ursprünglich war der Plan, den Kollegen in einem Kurzvortrag später zu erklären, was ich gemacht habe. Aus verschiedenen Gründen ist daraus aber nichts geworden, und da ich nun nicht mehr dort arbeite, wird das auch so schnell nichts mehr. Ich habe zwar versprochen, mal vobeizuschauen, aber bis ich dazu Zeit finde, können ein paar Monate ins Land gehen.

Also mache ich, was ich sowieso machen wollte, und erkläre das Ganze hier. Und da das hier kein Kurzvortrag ist, kann ich ein bisschen weiter ausholen.

Fordit

Fangen wir mal in der physischen Welt an. Mit „Fordit“, auch bekannt als „motor city agate“ oder „Detroit agate“.

Was ist Fordit? Fordit ist im Prinzip eine Art künstlicher Schmuckstein. In vergangenen Jahrzehnten, bevor die Produktionsmethoden optimiert wurden, ist beim Lackieren von Autos immer ein bisschen Farbe auf den Geräten drumherum gelandet. Die wurde dann zusammen mit den Autoteilen gehärtet. Beim nächsten Auto wurde vielleicht eine andere Farbe verwendet, und so sammelte sich Farbschicht um Farbschicht an.

Irgendwann wurde die Farbe zu dick, dann wurde sie abgebrochen und weggeworfen. Irgendwann sind Leute dann auf die Idee gekommen, diese Lackstücke zu polieren, wobei hübsche Schmucksteine herauskamen. Mehr Infos gibt es z.B. hier. Mittlerweile gibt es einige Leute, die Geld damit verdienen, das Zeug auf Müllkippen auszugraben, zu polieren und als Schmuck zu verkaufen (Bilder werde ich hier keine zeigen, das ist mit mit dem Urheberrecht jetzt zu kompliziert. Hinter dem Link oben findet man ein paar Bilder, ansonsten kann man im Web einfach nach „fordite“ suchen).

Der Sprung ins Digitale

Meine Idee war: Das sieht alles sehr hübsch aus. Vielleicht kann ich ja mit einem Computerprogramm einen ähnlichen Effekt erzielen. Die Idee ist simpel: Schichte in irgendeiner Weise Farben übereinander, dann „poliere“ den Stein, indem eine Höhenkarte darübergelegt wird und an jeder Stelle nur der Farbwert der entsprechenden Höhe genommen wird, und das Ergebnis wird schon irgendwie ordentlich aussehen.

Natürlich wäre das dann keine 3D-Darstellung, sondern eine Projektion, ao als ob man den polierten Fordit von oben fotografiert. Man kann sich das Ergebnis nicht aus verschiedenen Perspektiven anschauen. Das wäre für die Zukunft vielleicht auch interessant, ist aber nicht das, was ich hier machen wollte bzw. gemacht habe.

Wie sieht das Ergebnis aus? Nun hier erst einmal zwei Beispiele.

grünes Fordit

oranges Fordit

Vorgehensweise

Grundidee

Also, wie habe ich es angestellt? Gehen wir mal Schritt für Schritt vor. Als erstes werden Farben übereinander geschichtet. Im einfachsten Fall einfach in waagerechten Ebenen, zu sehen hier im Querschnitt:

eine rote, eine grüne, eine blaue und eine lila Farbschicht übereinander, im Querschnitt

Dann wird „geschliffen“. Für dieses Programm habe ich das mit einer Höhenkarte gemacht, also einer Funktion, die für jeden Punkt eine Höhe angibt. Alle Farbe, die über dieser Höhe ist, wird entfernt. Hier im Querschnitt ist zu sehen, dass der höchste Punkt der Höhenkarte über der höchsten Farbschicht liegt. In diesem Fall wird keine Farbe entfernt und die lila Farbschicht liegt oben:

eine Höhenkarte (eingezeichnet als schwarze Linie) auf den vorher gezeigten Farbschichten. Farbe über der schwarzen Linie wurde entfernt

Dann wird daraus ein Bild erstellt. Da ich keinen 3D-Krams mache, habe ich mich für den einfachsten Weg entschieden: Eine Projektion auf die (x,y)-Ebene. Oder mit anderen Worten: Ich schaue von oben auf die Farbschichten und nehme immer die Farbe, die oben liegt. Da es eine Rastergrafik wird, kann es natürlich sein, dass durch die Abtastrate einzelne Farben nicht vorkommen, obwohl sie eigentlich an der Oberfläche liegen:

Querschnittsdarstellung, wie die Farben für das Bild ausgewählt werden, die Abtastpunkte sind schwarz eignezeichnet, am oberen Ende des Bildes ist die Projektion der Farben dargestellt. In der Projektion ist keine rote Farbe enthalten, weil die Abtastpunkte die rote Farbe nicht erfassen.

Plaudern aus dem Nähkästchen

Natürlich ist es relativ langweilig, waagerechte Ebenen zu nehmen. Da könnte man auch einfach nur die Höhenkarte nehmen und jeder Höhe eine Farbe zuordnen. Die Farbe hängt dann nur von der Höhe ab und nicht von der Position im Bild. Wenn man zum Beispiel einen Paraboloid als Höhenkarte nimmt, sieht das z.B. so aus:

verschiedenfarbige Kreise übereinandergelegt, alle haben denselben Mittelpunkt.

Also braucht man andere Farbschichten. Naheliegend ist ja, die Farbschichten nicht waagerecht, sondern schräg anzuordnen (senkrecht wäre ja auch doof, weil dann die Farbe nur von der Position abhängen würden und überhaupt nicht von der Höhenkarte):

eine rote, eine grüne, eine blaue und einen lila Farbschicht übereinander und um 45° zur x-Achse verdreht, im Querschnitt

Das Ergebnis (wieder mit einem Paraboloid als Höhenkarte) sieht allerdings nicht viel interessanter aus:

bogenförmige Farblinien, die weiter links immer dünner werden

Wie kriege ich also interessante Bilder hin? Ich brauche nichtlineare Farbschichten! Vielleicht könnte man ja einfach einen Haufen Farbkleckse übereinander schichten. Also keine ganzen Ebenen, sondern verschiedenfarbige Kreise, die an zufälligen Positionen mit zufälligem Radius auftauchen und sich teilweise überlappen. So wie in diesem Schema dargestellt, nur mit mehr Kreisen:

mehrere verschiedenfarbige Kreise mit unterschiedlichem Radius an unterschiedlichen Positionen. Die Kreise überlappen sich teilweise

Stellt sich heraus: Das ist mit meiner Vorgehensweise eine ganz schlechte Idee. Daraus ist dieses Bild entstanden, dass ich ganz am Anfang gezeigt habe:

Rechts sind Kreisteile zu sehen, links Farbstreifen mit Grenzen, die ebenfalls Kreise andeuten, aber die Mitte ist sehr chaotisch

Was ist passiert? Nun, je nachdem wie viele Kreise an verschiedenen Stellen unter einem Kreis liegen, ist dieser Kreis an vielen Stellen auf unterschiedlichen Ebenen. Die Höhenkarte ist in diesem Fall eine einfache Schräge, links ist der tiefste Punkt, rechts der höchste Punkt.

Links kann man noch Kreise erkennen, hauptsächlich daran, dass sich Farben entlang von Kreislinien spontan verschieben. Diese Kreislinien gehören zu Kreisen, die mehr oder weniger ganz verdeckt sind, aber ihre Auswirkungen sieht man bis ganz nach oben.

Rechts ist die Höhenkarte über der höchsten Farbschicht, es wird also nur die oberste Schicht gezeigt. Deswegen kann man hier die Kreise am besten sehen.

In der Mitte aber ist es ein Gewusel an verschiedensten Farben, weil eine Farbschicht auf verschiedenste Höhen verteilt wurde. Das sieht nicht so aus, wie ich wollte.

Die Rettung naht

Ich habe dann noch einen anderen Versuch mit Kreisen gemacht, bei dem immer eine ganze Ebene eingefärbt wurde, kreisföfmig in einer Farbe, sonst in einer anderen. Damit ist z.B. oben das orangerote Bild erstanden. Sieht ein bisschen interessanter aus, aber immer noch nicht das, was ich wollte.

Ein weiterer Versuch war, abwechselnd immer nur eine Hälfte des Bildes einzufärben. Also erst die linke Hälfte, dann die obere Hälfte, dann die rechte Hälfte, dann die untere Hälfte, dann wieder die linke, und so weiter.

Auch das führt zu interessanten Bildern, in diesem Fall ist die Höhenkarte einfach eine schiefe Ebene, die von oben links nach unten rechts ansteigt:

Das Bild ist in vier Teile geteilt, in denen jeweils farbige Streifen diagonal verlaufen

Das Problem: Das sieht zu künstlich aus. Zu viele scharfe Kanten, zu viele Brüche. Also zurück ans Reißbrett.

Kugeln

Die nächste Idee, und vorläufig die, die am besten funktioniert, waren Halbkugeln. Eine farbige Halbkugel an einem Punkt, dann Schichtweise weitere Farbschichten halbkugelförmig drum herum.

Das Problem: Mit den Paraboloiden als Höhenkarte sieht das wieder nur ziemlich langweilig aus. Im großen und Ganzen nämlich immer noch nur nach Kreisen. Wenn man genau hinschaut, kann man sehen, wie die Kreise ein bisschen verzerrt sind, aber das war es auch schon. Ich füge jetzt nicht noch ein Bild dazu ein, aber ihr seid dazu eingeladen, das selbst auszuprobieren.

Mit einer Sinuskurve jedoch sieht das schon ganz anders aus. So ist das grüne Bild oben entstanden.

Konfigurationsdateien

Es gehen also eine Menge Parameter in jedes Bild. Wie die Farben geschichtet sind, welche Höhenkarte verwendet wird, wie die Höhenkarte verschoben und ausgerichtet wird, welche Farben verwendet werden, ggf. ein Seed für den RNG

Zunächst, um überhaupt erst einmal zu probieren, was funktioniert, habe ich diese ganzen Parameter hardcodiert. Das skaliert natürlich nicht. Also habe ich das Ganze Umgebaut, so dass es jetzt Dateien mit Konfigurationen lesen kann. Schneller, sauberer und man kann sich Konfigurationen, die gefallen, abspeichern und wieder verwenden.

Animationen

Nachdem die Grundlagen liefen, kam mir die nächste Idee: Ich konnte dem Programm Konfigurationsdateien füttern. Warum also nicht einen Haufen von Konfigurationen erstellen (mehrere Konfigurationen pro Datei sind möglich) und in jeder Konfiguration einen Parameter gegenüber der vorherigen Konfiguration leicht ändern?

Das Ganze dann als Video zusammenfügen und… schaut euch das Ergebnis auf Youtube an. Ich habe Halbkugelförmige Farbschichten und eine Sinushöhenkarte genommen. Die Höhenkarte rotiert und verschiebt ihre Phase, so kommt diese Bewegung zustande.

Repositories

Der Code dazu (natürlich rust) ist auf Gitlab zu finden. Das Ganze ist nicht besonders ordentlich geschrieben, weil es hauptsächlich ein bisschen Herumgebastel war. Es ist aber recht klein, sollte also überschaubar sein. Wichtig: Da ich noch einiges an Verbesserungspotential sehe, kann ich keine Garantie dafür geben, dass irgendeine Konfigurationsdatei, die irgendjemand schreibt, in einer späteren Version vergleichbare Ergebnisse bringt, oder auch nur eingelesen werden kann.

Die Dokumentation lässt noch zu wünschen übrig, aber es gibt ein paar Beispielkonfigurationen, an denen zumindest jeder Parameter irgendwo benutzt wird.

Für die meisten fordite-Beispiele, die ich hier gezeigt habe, liegen die Konfigurationsdateien in einem weiteren git-Repo, im Unterordner blogpost_fordite.

In beiden Repos habe ich die Version, mit der die Bilder für diesen Post erstellt wurden, mit stu-blogpost getagged. Die Bilder hier sollten also reproduzierbar sein, man muss nur eine alte Version auschecken.

Fazit

Im Großen und Ganzen kann man mit fordite also schöne Bilder und Animationen erstellen. Nicht ganz das, was ich mir vorgestellt habe, als ich damit anfing, aber immerhin.

Echte Fordite-Schmucksteine gefallen mir besser, dort bilden die Farben noch interessantere Muster. Aber eine Sache kann ich hier machen, die man mit echtem Fordite nicht machen kann: Animationen.

Ausblick

Auf jeden Fall besteht noch viel Potential für Erweiterungen. Hier nur eine kurze Auflistung von Ideen:

  • ungleichmäßige Dicke von Farbschichten
  • mehr verschiedene Höhenkarten
  • mehr Konfigurierbarkeit von Höhenkarten (Streckung, Scherung, ggf. spezifische Konfigurationen für einzelne Höhenkartentypen)
  • Höhenkarten nach beliebigen Funktionen (erfordert natürlich einen Parser für die Funktion)
  • Höhenkarten aus Bildateien (Grauwertbildern) auslesen (könnte Schwierigkeiten mit Rotieren, Verschieben, Strecken und Scheren verursachen)
  • mehr Konfigurierbarkeit von Farbschichten (z.B. könnte man aus den Halbkugelfarbschichten Kugelfarbschichten mit frei wählbarem Mittelpunkt machen)
  • mehr Schemate für Farbschichten (z.B. Zylinderförmige Schichten)
  • fest vorgegebene Farbreihenfolge (anstatt zufällige Auswahl aus einer Palette)
  • komplett zufällige Farben

Es gibt also noch jede Menge Ideen.

Nachwort

Wie schon früher erwähnt habe ich ja einen kleinen Kompressionsfetisch. Alle Fordite-Bilder hier wurden als verlustfreie WebP encodiert. Das ging sehr gut, weil jedes Bild nur eine kleine Farbpalette hat. Hier mal eine Beispielhafte Aufstellung für eines der Bilder, und zwar die grüne Halbkugel mit Sinus-Höhenkarte:

zopflipng braucht natürlich immer noch ewig, und auch optipng ist nicht gerade schnell. Die WebP-Encodierung hingegen braucht kaum Zeit.

Das Lustige hier ist, dass die Dateien tatsächlich größer werden, wenn ich versuchen würde, sie verlustbehaftet (als JPEG oder verlustbehaftetes WebP) zu komprimieren. Das liegt natürlich daran, dass diese Dateien einfach so gut geeignet sind, sie verlustfrei zu komprimieren, dass es nicht viel besser geht.

Noch ein Nachwort: Mit den ganzen Bildern, Grafiken und den real-life-Herausforderungen hat es mich zwei Wochen gekostet, diesen Blogpost zu schreiben.

Mit C von hinten durch die Brust ins Auge

Die Programmiersprache C hat ja einen besonderen Platz in meinem Herzen. Sie war die erste Programmiersprache, die ich wirklich gelernt habe. Sie ist schnell, maschinennah, man kann eine Menge über die Funktionsweise von Computern lernen, wenn man Programme in C schreibt. Zum Beispiel, warum Felder mit dem Index 0 beginnen.

Ich will auch nicht sagen, dass man jede in C geschriebene Software in rust neu schreiben soll. Das ist in den meisten Fällen nicht praktikabel, ob jetzt in rust oder in irgendeiner anderen Sprache. Außerdem macht man sich unbeliebt, wenn man uneingeladen irgendwo auftaucht und einen Haufen C-Entwickler dazu auffordert, all ihren Krams umzuschreiben.

Es gibt Fälle, wo das gut funktioniert hat librsvg zum Beispiel.

Eine bessere Idee ist wohl eher, einzelne, neue Bestandteile, in rust zu schreiben. So wie im Linux-Kernel zum Beispiel. Oder wie es bei Firefox gemacht wird.

Aber trotz allem sollte man sich es wohl verdammt noch einmal gut überlegen, ob man ein neues Projekt wirklich in C schreiben möchte.

C-Code am Beispiel Open5GS

Ich bin neulich über Open5GS gestolpert. Eine freie Implementierung unter anderem des 5G Core-Networks.

An sich eine schöne Sache. AGPL-Lizensiert. Soweit ich das anhand der wenigen Stellen, die ich mir angeschaut habe, beurteilen kann, recht ordentlich geschrieben.

Ich habe mir den Code angeschaut, weil ein Service (die Network Repository Function, NRF) abgeschmiert ist, als ich eine völlig normale Anfrage gestellt habe.

Dass die NRF abgeschmiert ist, liegt an einer fehlgeschlagenen assertion. Auch hier zumindest in der Hinsicht ordentlich programmiert, sonst hätte es einen Segfault durch eine null pointer dereference gegeben.

Hier geht es nicht um diesen Crash. Hier geht es darum, was ich gefunden habe, als ich herausfinden wollte, warum dieser pointer überhaupt NULL ist. Dabei bin ich ein wenig vom Weg abgekommen.

Generische doppelt-verkettete Listen in C

Dabei bin ich über eine Implementierung einer doppelt verketteter Liste gestoßen. Die Implementierung sieht ganz ordentlich aus, aber… die Anzahl an merkwürdigen Konstrukten, die notwendig waren, um diese Liste stabil, sicher und benutzbar zu implementieren ist Wahnsinn.

Fangen wir mal am Anfang an. Die ganze Implementierung der Liste ist in der Datei lib/core/ogs-list.h in diesem Repo zu finden.

Generische Definition

Die Definition des Listen-structs sieht wie folgt aus:

struct ogs_list_s {
    struct ogs_list_s *prev, *next;
};
typedef struct ogs_list_s ogs_list_t;
typedef struct ogs_list_s ogs_lnode_t;

Erst mal alles, was eine doppelt verkettete Liste braucht. Einen Vorwärtspointer und ein Rückwärtspointer. Dazu noch ein paar typedefs um die Benutzung semantisch klarer zu machen.

Aber irgendwas fehlt. Ach ja. Eine Liste ist recht sinnlos, wenn es keinen Payload gibt. Aber wo ist der Payload?

Hier kommen wir zum ersten Problem: Wenn man in C eine Liste generisch implementieren möchte, hat man ein Problem: C hat keine generischen Typen. Also muss man das irgendwie umgehen.

Das könnte man mit einem void*-pointer lösen. Ist aber aus mehreren Gründen doof, auf die ich hier jetzt nicht eingehen werde.

Die Lösung die hier gewählt wurde, ist nicht ganz offensichtlich. Angenommen, ich würde jetzt einen Typ definieren, der in der Liste stecken soll. Dann würde ich etwa so etwas machen:

struct something {
    ogs_lnode_t lnode;

    int payload;
};

Aber… die prev und next pointer gehen doch wieder nur auf die ogs_lnode_t! Die hat doch wieder keine Payload! Wie geht man damit um?

Nun, schauen wir uns doch mal die Funktion an mit der man das nächste Glied in der Kette bekommt:

static ogs_inline void *ogs_list_next(void *lnode)
{
    ogs_list_t *node = lnode;
    return node->next;
}

Ok, hier kommt ein void-pointer rein, ein void-pointer raus, und innendrin wird der void-pointer zu einer ogs_list_t gecasted und der next-pointer zurückgegeben.

Um dann über die Liste zu iterieren, gibt es diese bequeme Makro:

#define ogs_list_for_each(list, node) \
    for (node = ogs_list_first(list); (node); \
        node = ogs_list_next(node))

Das kann man dann einfach so verwenden:

struct something* some_list;
// [… create list here]

struct something* entry;
ogs_list_for_each(some_list, entry) {
    // do something with an entry
}

Der Vorteil für den Aufrufer hier ist, dass es typsicher ist. Man bekommt nur Einträge vom Typ *something. Der Nachteil ist… what the fuck.

Ich meine, ist das überhaupt definiertes Verhalten? Wer garantiert mir, dass mir nicht gleich Dämonen aus der Nase fliegen? Wir greifen hier immerhin auf Elemente eines structs zu, das in einem anderen struct steckt, über einen pointer auf das äußere struct. Was ist, wenn hier irgendwelches komisches Padding alles durcheinanderbringt?

Die Lage scheint nicht ganz einfach, aber es sieht so aus, als ob es hier definiertes Verhalten ist.

Aber es ist doch schon sehr von hinten durch die Brust ins Auge. Man muss einiges an komischen Dingen anstellen, damit die Liste benutzbar ist. Und offensichtlich ist nicht, wie es funktioniert.

Jede Menge Makros

Doch damit hört es nicht auf- Auffällig ist, dass über die gesamte Datei verteilt sehr viele Makros verwendet werden.

Nun sind C-Makros so eine Sache. Der C-Präprozessor ist unglaublich dumm, deswegen ist es möglich mit ihm so typunabhägige Sachen zu machen, weil die Typen erst später vom Compiler überprüft werden.

Deswegen sollte man Makros immer doppelt und dreifach absichern. Beispiel: Initialisierung einer Liste:

#define ogs_list_init(list) do { \
    (list)->prev = (NULL); \
    (list)->next = (NULL); \
} while (0)

Wozu zur Hölle ist diese do-while-Schleife da? Sie wird immer nur ein Mal durchlaufen und vermutlich vom Compiler wegoptimiert.

Grund dafür ist der dumme Präprozessor. Angenommen, unser Makro sähe nur so aus:

#define ogs_list_init(list) \
    (list)->prev = (NULL); \
    (list)->next = (NULL);

Dann würde folgender code

if (foo) ogs_list_init(list);

wie folgt expandiert:

if (foo)
    (list)->prev = (NULL);
    (list)->next = (NULL);;

Das ist gleichbedeutend mit

if (foo) {
    (list)->prev = (NULL);
}
(list)->next = (NULL);

Ein Teil wird also immer ausgeführt, unabhängig von der Bedingung.

Komplexität

Versteht mich bitte nicht falsch. Die Entscheidungen, den Code so zu schreiben ist vernünftig. Vernünftig unter den Bedingungen, mit denen man arbeiten muss, wenn man C schreibt.

Es geht hier um Komplexität, die überwunden werden muss, um das zu tun, was man eigentlich machen will. An Stellen wie diesen wünsche ich mir eine gute deutsche Version des englischen Ausdrucks „jumping through hoops“.

Es gibt beim Programmieren Komplexität, die man nie los wird, weil das Problem, das man lösen will, einfach entsprechend komplex ist. Wenn man eine verkettete Liste haben möchte, braucht man z.B. Vorwärts- und Rückwärtsverweise.

Dann gibt es Komplexität, die die Sprache vorgibt, für die man aber etwas zurück bekommt. Das ganze Ownership-Konzept in rust zum Beispiel. Man muss sich an halbwegs komplexe Regeln halten, kriegt dafür aber vom Compiler einige Garantien, die das Leben sehr viel einfacher machen.

Als drittes gibt es Komplexität, die einfach unnötig ist. Zum Beispiel, dass man Code in Makros in do-while-Schleifen hängen muss, um sicherzustellen, dass nichts Dummes passiert.

C mag eine einfach aufgebaute Sprache sein, aber aus dieser scheinbaren Einfachheit entsteht solche komplexen Konstrukte wie oben. Für Bequemlichkeiten und Sicherheiten, die die meisten modernen Sprachen von Haus aus mitliefern, in der einen oder anderen Form.

Die ganze Energie, die investiert wird, um diese unnötige Komplexität zu überwinden könnte man viel besser woanders investieren.

Ich mag C, aber eine Sprache, die mich zu solchen Konstrukten zwingt, um ein bisschen Sicherheit und Bequemlichkeit zu bekommen, ist keine Sprache, in der ich entwickeln möchte.

Fordite-Update

Vor kurzem habe ich ja endlich den Blogpost zu meinem fordite-Programm fertig gestellt. Das heißt, ich hatte danach endlich Zeit, mal wieder an der Software selber weiter zu arbeiten.

Das Schöne am momentanen Stand der Software ist, dass es recht einfach ist, neue Höhenkarten und neue Farbschichtschemata hinzuzufügen. Die eigentliche Arbeit ist hier eher, die Beispielkonfigurationen zu erstellen (bzw. die bestehenden Dateien anzupassen, wenn ich inkompatible Änderungen zu bestehenden Optionen gemacht habe).

Die Kugel

Die erste Änderung ist, dass ich die Halbkugel zur Kugel umfunktioniert habe. Anstatt der (im Verhältnis zur Bildgröße) festen Position in der x-y-Ebene, kann man jetzt das Zentrum der Kugel beliebig einstellen.

Die Ergebnisse hier waren aber eher unspektakulär, deswegen gibt es dazu kein Bild.

Neue Höhenkarte: zwei verschiedene Sinuskurven

Die erste neue Höhenkarte, die ich hinzugefügt habe, ist ähnlich der bisherigen Sinuskurve, allerdings zwei davon, in unterschiedlicher Ausrichtung, ggf. mit unterschiedlicher Wellenlänge, aufeinander addiert. Mit einer Halbkugel sieht das dann zum Beispiel so aus:

ungleichmäßig aussehende, zentrierte Farbblobs

Das hat mir schon einmal gefallen. Sah deutlich mehr nach echtem Fordit aus als die anderen Sachen. Also habe ich auch versucht, eine Animation daraus zu machen.

Da ist mir aufgefallen, dass ich in der Ursprungsversion die Phase der Sinuskurven nicht unabhängig voneinander ändern konnte.

Beim einfachen Sinus habe ich dafür einfach die gesamte Höhenkarte verschoben. Hier musste ich hingegen noch ein paar Parameter hinzufügen. Sieht aber schön aus, ein bisschen, wie eine Wasserspiegelung auf leicht welligem Wasser. Das Video ist wieder auf youtube.

Kreisförmige Sinuswellen

Die bisherigen Sinuskurven liefen alle parallel. Als Alternative dazu habe ich die mal kreisförmig angeordnet, also von einem Mittelpunkt ausgehend in alle Richtungen gleichmäßig. Ein bisschen so, als ob man einen kleinen Stein auf eine glatte Wasseroberfläche geworfen hätte.

Und siehe da: Damit sehen selbst die schiefen Farbebenen gut aus:

grün-schwarzes Fordit-Muster aus Wellen, die zum Rand hin kreisförmiger werden

Zylinderfarbschichten

Das Schöne an neuen Höhenkarten und Farbschichtschemata ist, dass man jede neue Höhenkarte mit allen bisherigen Farbschemata kombinieren kann und umgekehrt. Je mehr Farbschichtschemata bzw. Höhenkarten man also hat, desto mehr bringt das Hinzufügen noch einer Höhenkarte bzw. eines Farbschichtschemas.

Nach den zwei neuen Höhenkarten musste ich also erst einmal ein neues Farbschichtschema hinzufügen. Ich hatte ja im letzten Blogpost schon die Idee von zylinderförmigen Schichten geäußert. Und was soll ich sagen? Damit sieht auch der hyperbolische Paraboloid als Höhenkarte wieder interessant aus:

ein blaues Oval in der Mitte, rechts oberhalb davon verlaufen Farbstreifen fast gerade, während sie sich gegen die linke untere Ecke fast rechtwinkelig biegen

Natürlich musste ich den Zylinder auch mal mit den kreisförmigen Sinuskurven kombinieren:

gelb-orange-rote Wellellinien, die eine U-Form um mehrere Kreise in der Mitte bilden.

Ursprünglich verlief der Zylinder hier von der (0,0,0) diagonal in die gegenüberliegende Ecke, aber mit der Farbgebung hier gefiel es mir besser, ihn von der Mitte der X-Achse diagonal nach oben verlaufen zu lassen. Das erweckt irgendwie einen Eindruck von Feuer.

Eine neue Test-Höhenkarte

Für die Farbschichten hatte ich ja schon eine Option, um die Höhenkarten testen zu können. Das Farbschichtschema display_height_map hat anstelle von Farben einfach die Höhenkarte in Graustufen ausgegeben. Sehr hilfreich.

Umgekehrt habe ich jetzt eine waagerechte, flache Höhenkarte eingefügt, damit man Farbschichten testen kann. Man kann natürlich immer nur einen Ausschnitt sehen, aber es hilft beim Debuggen.

Fazit

Die neuen Höhenkarten und die Zylinderfarbschichten haben sie gelohnt, es sind interessante Bilder dabei herausgekommen.

Mir fällt es zunehmend schwerer, originelle, aber auch schöne Farbpaletten zu erfinden. Schwerer zumindest, als Höhenkarten mit Farbschichten zu kombinieren.

Die hier dargestellten Bilder stellen natürlich nur einen kleinen Teil des Parameterraumes dar. Es gibt sicher noch eine Menge cooler Bilder, die sich hier verstecken. Man muss sie nur finden. Ihr seid alle herzlich eingeladen.

Als nächstes werde ich mich mal daran machen, Streckungen und Zerrungen für die Höhenkarten einzubauen. So kann man sicher noch ein paar interessante Effekte aus den bestehenden Höhenkarten herausholen (naja, vermutlich nicht aus allen).

Lang und breit

Ich habe endlich mal was umgesetzt, was ich schon seit knapp zwei Jahren vorhabe (auch hier schon einmal erwähnt): width und height-Attribute an img-tags, die ich per Markdown in meine Blogposts einfüge.

Das ist jetzt kein Riesending, insbesondere, da ich ohnehin nur eher wenige Bilder einbinde. Die zwei Posts über Fordite und das Kochprojekt von 2014 sind die Stellen, wo ich die meisten Bilder einbinde.

Warum will ich diese Attribute? Perfektionismus. Es ist besser, wenn man die tatsächlichen Bildgrößen direkt an den img-tags angibt (nicht zu verwechseln damit, Größenverhältnisse über CSS zu konfigurieren. Das sind zwei verschiedene Dinge mit zwei verschiedenen Zielen). Warum ist es besser? Weil der Browser so wissen kann, wie viel Platz für die Bilder reserviert werden muss und er nicht das Layout die ganze Zeit hin-und herschieben muss, wenn die Bilder endlich geladen sind.

Warum habe ich das mit den Attributen so lange aufgeschoben? Weil ich die Werte dafür nicht in Markdown einfügen kann, und sie woanders her zu laden ist eine Menge Arbeit (dazu unten mehr).

Aber hey, sinnlose Optimierungen sind ja so ein Steckenpferd von mir. Also ran an die Sache!

Warum ist das so aufwändig?

Es gibt zwei Gründe, warum diese Erweiterung so aufwändig ist. Ich muss die Metadaten der Bilder an einer Stelle laden und sie bis zum Rendern der Blogposts durchschleifen. Das ist nervig und macht den Code nicht schöner.

Bildgrößen lesen

Und die Bilder müssen geparsed werden. Für die üblichen Rastergrafiken habe ich das image-crate genommen. Netterweise müssen dazu nicht die ganzen Bilder geladen werden, wenn ich nur die Größe haben möchte kann ich mit dem crate auch nur die Header lesen.

Für die SVG-Dateien wollte ich nicht noch eine Abhängigkeit einbinden. Da ich aber eh schon quick-xml einbinde, um die atom-feeds zu rendern, konnte ich das nutzen um an die nötigen SVG-Attribute zu kommen. Nervig nur, dass die width und height-Attribute von SVGs nicht verpflichtend sind, keine Integer sein müssen, verschiedene Einheiten haben können (z.B. em wie in CSS, aber auch mm oder %). Außerdem gibt es noch das viewBox-Attribut, das auch noch mal verändert, wie sich die Größe verhält. Ich habe hier erst einmal einen minimalen Support eingebaut.

Bildgrößen rendern

Am Ende müssen die Bilder gerendert werden. Zum Parsen und Rendern des Markdowns (streng genommen ist es CommonMark, eine sauberere Spezifikation) benutze ich pulldown-cmark.

Das Crate beinhaltet einen Parser, der netterweise einen Iterator über die Elemente liefert. Außerdem gibt es eine Funktion, um aus so einem Iterator HTML zu bauen.

Das Problem ist, dass ich in diese Funktion zum HTML-bauen nicht direkt eingreifen kann. Ich kann also nichts machen wie „render alles wie gehabt, nur img-tags anders“.

Ich könnte jetzt den kompletten HTML-renderer neu bauen. Das ist sehr viel Arbeit und ich mache vermutlich Fehler dabei.

Was ich alternativ gemacht habe war ein Trick, den ich auch schon benutzt habe, um zu verhindern, dass in Markdown eingebettetes HTML gerendert wird: Ich ersetze Parser-Events durch andere Events. Zum Beispiel: Um zu verhindern, dass das HTML gerendert wird, ersetzte ich Parser-Events vom Typ HTML als HTML gerendert werden, benutze ich stattdessen ein Text-Event mit demselben Inhalt. Der HTML-Renderer am Ende wird dann den Inhalt escapen.

Für Image-Events muss ich also nur das Image-Event durch ein HTML-Event ersetzen, dass als Inhalt das gerenderte image-Tag hat.

Codequalität

Die Codequalität hat unter der ganzen Geschichte etwas gelitten. Das lässt sich aber zumindest teilweise aufräumen, wenn ich mal Lust dazu habe.

Insbesondere achtet der Bloggenerator noch nich darauf, dass sich Bildgrößen geändert haben. Wenn sich also Bildgrößen ändern, werden die Seiten, die die Bilder referenzieren, nicht neu gerendert.

Außerdem ist der Code, um die SVG-Größe herauszufinden nocht ziemlich simpel und wird in vielen Fällen nicht funktionieren. Also viel Verbesserungspotential.

Bauzeit

Das image-crate, das ich eingebunden habe, zieht die Bauzeit schon stark runter (wie hier schon einmal beschrieben). Wenigstens lässt sich der Effekt reduzieren, wenn ich nur die Formate unterstütze, die ich auch wirklich brauche.

Fazit

Am Ende war es viel Aufwand für wenig Nutzen. Aber ich bin ja Perfektionist, ich muss das bestmögliche HTML erzeugen. Außerdem hat die jetzt aufgebaute Infrastruktur ein paar Optionen für mögliche andere Verbesserungen.