ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/docs/pws2004/freenet.pod
Revision: 1.3
Committed: Thu May 13 01:04:58 2004 UTC (22 years, 5 months ago) by root
Branch: MAIN
Changes since 1.2: +5 -6 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 =head1 Freenet - Informationsfreiheit ohne Zensur, aber mit Perl
2    
3     =head2 Abstract
4    
5 root 1.2 Das Freenet-Projekt (http://www.freenetproject.org) hat es sich zur
6     Aufgabe gemacht, jedem die die Möglichkeit freier Meinungsäußerung zu
7     garantieren. Neben den Implementation einer Lösung für dieses Problem
8     geht es in diesem Artikel darum, wie man in Perl selbst Informationen
9     herunterlädt bzw. veröffentlicht.
10    
11     =head1 Einführung
12    
13     Das Freenet-Projekt (http://www.freenetproject.org) hat es sich zur
14     Aufgabe gemacht, jedem die die Möglichkeit freier Meinungsäußerung
15     zu garantieren. Als Mittel zur Umsetzung hat es ein virtuelles Netzwerk
16     gewählt, in dem es nicht realistisch möglich sein wird, Einspeisung
17     von neuen Daten zu verhindern oder den Urheber von Veröffentlichungen
18     ausfindig zu machen, solange er dies nicht selbst zugibt. Darüberhinaus
19     ist es für Betreiber von Freenet-Knoten nicht möglich, zu wissen, was
20     auf ihrer Festplatte gespeichert wurde oder wo die Daten herstammen, so
21     daß es ab einer bestimmten Netzwerkgröße nicht mehr möglich ist,
22     dem Betreiber einer Freenet-Node nachzuweisen, daß er illegale Inhalte
23     besitzt bzw. weitergegeben hat oder davon gewusst hat.
24    
25     In China beispielsweise wird eine frühe Version von Freenet für ein
26     rein chinesisches Freenet-Netzwerk aktiv benutzt, um politische Inhalte
27     verbreiten zu können ohne Maßnahmen von der Regierung zu befürchten.
28    
29     =head2 Freenet für den Benutzer
30    
31     Freenet speichert nur relativ kleine Dokumente (<1MB) am Stück. Diese
32     Dokumente können beliebige Daten enthalten, z.B. HTML-Seiten. Dise
33     Datenblöcke können mit einem für jeden Block eindeutigen Schlüssel
34     abgerufen werden, z.B. in einem Web-Browser.
35    
36     Hier ist ein Beispiel für eine solche HTML-Seite:
37    
38     freenet1.png
39    
40     Die hier verwendete URL ist C<http://129.13.162.73:8888/SSK@Sc6qV~D6iFhaYord6HtbjJ8MaEYPAgM/YoYo//Controversy.html>.
41     C<http://129.13.162.73:8888> ist die Adresse meines Freenet-Daemons,
42     üblicherweise C<http://127.0.0.1:8888>, der Sicherheit wegen sollte man
43     immer einen eigenen Freenet-Daemon laufen lassen. Der Schlüssel der
44     "Freesite" ist C<SSK@Sc6qV~D6iFhaYord6HtbjJ8MaEYPAgM> und in dieser wird
45     wiederum das Unterdokument C<YoYo//Controversy.html> angezeigt.
46    
47     Diese Seite ist Teil eines sehr bekannten Einsprungpunktes ins
48     Freenet. Generell bevorzugt das Freenet-Projekt keine bestimmten
49     Einsprungpunkte. Die Regel ist: kennt man den Einsprungpunkt nicht, findet
50     man die Inhalte nicht; es ist sogar unmöglich zu bestimmten, wieviel oder
51     welche Informationen im Freenet gespeichert sind: Ein Index a'la google
52     ist prinzipbedingt nicht möglich.
53    
54     Obwohl es einige Freenet-Spider und Directory-Freesites gibt ist der
55     überwältigende Teil der Information im Freenet nicht darüber zu
56     erreichen.
57    
58     Neben HTML-Inhalten gibt es auch Mail-, Foren- und Chat-Systeme im
59     Freenet.
60    
61     Die Einspeisung von Daten kann von überall im Netz
62     geschehen. Mehrfacheinspeisung ist möglich (und meistens notwendig) und
63     erhöht führt nicht zur Dupliziering von Daten.
64    
65     Natürlic gibts es auch einige Nachteile, die teilweise mit dem Design
66     und teilweise mit der Implementierung zusammenhängen. So ist der einzige
67     verfügbare Freenet-Daemon in Java implementiert und daher leider extrem
68     unportabel (läuft praktisch nur auf Linux/x86 und Windows, da das
69     benötige Sun-Java-JDK auf andreen Platformen nicht verfügbar oder
70     veraltet ist), sehr langsam und vor allem Speicherhungrig, und häufig
71     auch sehr instabil.
72    
73     Die aktuellen Versionen des Freenet-Daemons sind alle als "nicht sicher"
74     deklariert, da erst die Release 1.0 verspricht, alle Ideen umgesetzt zu
75     haben, wovon das Projekt noch 0.5 Versionen entfernt ist :)
76    
77     Designbedingt ist das Freenet eher langsam (extrem hohe Latenz,
78     akzeptabler Durchsatz) und für interkative Benutzung teilweise
79     ungeeignet, bzw. eine echte Geduldsprobe.
80    
81     Durch die Art der Speicherung kann nicht garantiert werden daß
82     Informationen überhaupt wiedergefunden werden. "Unpopuläre" Information
83     verschwindet, sofern sie nicht regelmäßig eingespeist oder abgerufen
84     wird, automatisch wieder aus dem Freenet.
85    
86     =head2 Die Freenet-Architektur
87    
88     Herkömmliche File-Sharing-Netzwerke haben zwei Große Nachteile: Entweder
89     sind sie nicht wirklich anonym (selbst anonymisierende Netzwerke oder
90     Proxies sind üblicherweise nicht vor Zugriff durch Regierungen sicher
91     (ein bekanntes Beispiel ist I<JAP>, C<http://anon.inf.tu-dresden.de>, das
92 root 1.3 zwar vollmundig vollkommene Anonymität garantiert aber schoneinmal durch
93     die Polizei gezwungen wurde, Log-Informationenen herauszugeben, wozu die
94     Betreiber nach deutschen Recht verpflichtet sind). Oder sie skalieren
95     nicht, da sie Broadcast-Algorithmen benutzen die größere Netzwerke von
96     vorneherein ausschließen (bekanntes Beispiel dafür ist I<gnutella>).
97 root 1.2
98     Das erste Problem umgeht Freenet (Achtung, vereinfacht!), indem es
99     jeden Datenblock hasht und aus diesem Hash einen Schlüssel für die
100     Verschlüsselung generiert und die Daten damit verschlüsselt (sic).
101    
102     Der Schlüssel wird ein zweitesmal gehasht. Dieser Hash wird zur
103     eindeutigen ID des Datenblocks. Diese ID und der verschlüsselte
104     Datenblock werden ins Freenet eingespeist. Dabei, wird immer derselbe
105     Key generiert (da er nur von den Daten abhängt) und der verschlüsselte
106     Block ist ebenfalls immer gleich. Daher kann er problemlos mehrfach und
107     von unterschiedlichen Parteien eingespeist werden ohne die Daten faktisch
108     mehrfach im Freenet abzulegen.
109    
110     Das ist sicher, da ein kryptographisch sicherer Hash (der die Grundlage
111     des Systems bilden muß) nur in eine Richtung funktioniert: Aus der ID
112     (== Hash des Hashes der Daten) kann nicht auf den Schlüssel geschlossen
113     werden. Speichert also ein Netzknoten die Daten und die ID dazu, kann man
114     die Daten zwar abrufen, jedoch nicht entschlüsseln. Selbst der Besitzer
115     eines Knotens kann mit vollkommenen Wissen über alle Vorgänge seines
116     Knotens die Inhalte nicht lesen.
117    
118     Eine weitere Konsequenz dieses Verfahrens ist die Tatsache, das Dokumente
119     niemals verändetr werden können: eine Änderung bewirkt eine Änderung
120     des Schlüssels und damit eine neue ID, praktisch eine völlig neue URL.
121    
122     Möchte man z.B. das grüne Blatt der Freesite "Thought Crime" herunterladen so
123     wird man mit folgendem Freenet-Key konfrontiert:
124    
125     CHK@pfAv9IejYPLQwaTLXDguEkUhiNUMAwI,blzDbhN~8Q28esq4JrfRWw
126    
127     C<CHK> steht für I<Content-Hash-Key>, der häufigste Schlüsseltyp im
128     Freenet, der das oben beschriebene Verfahren benutzt. Der CHK besteht
129     aus zwei Teilen: der ID, unter der der Schlüssel im Freenet abgelegt
130     wird (C<pfAv9IejYPLQwaTLXDguEkUhiNUMAwI>) und dem Schlüssel, mit dem die
131     Daten verschlüsselt wurden (C<blzDbhN~8Q28esq4JrfRWw>), durch ein Komma
132     getrennt.
133    
134     Das sind übrigens (mehr oder weniger) base64-encodete Daten, dekodiert
135     sieht der Schlüssel so aus:
136    
137     CHK@
138     ID = a5f02ff487a360f2d0c1a4cb5c382e12452188d50c0302
139     Key = 6e5cc36e137ef10dbc7acab826b7d15b
140    
141     (Man kann daraus tatsächlich ablesen, das der Datenblock 4k groß (0x0c
142     am Ende der ID bedeutet 2**12) ist und Twofish benutzt. Aber derartige
143     Details überläßt man lieber einem Perl-Modul).
144    
145     Nur der erste Teil wird als Anfrage ins Freenet geschickt, der zweite Teil
146     bleibt im lokalen Freenet-Daemon. Wird nun der Datenblock geliefert, kann
147     er mit dem Schlüssel dekodiert werden und wird an den Benutzer geliefert.
148    
149     Das zweite Problem (der Skalierbarkeit) wird durch lineare
150     statt exponentielle Suche gelöst: mit jeder Anfrage wird eine
151     I<Hops-To-Live>-Angabe (HTL, ähnlich wie das TTL in IPv4)
152     verknüpft. Diese Zahl, die üblicherweise zwischen 5 und 25 (maximal)
153     liegt, gibt an, wie viele Knoten die Anfrage maximal weitergeleitet
154     wird. Jeder Knoten, der die Daten nicht lokal vorrätig hat, leitet sie an
155     denjenigen Knoten weiter, der die Daten am wahrscheinlichsten hat. Da das
156     Verfahren linear ist und nicht exponentiell, skaliert es ebenfalls linear
157     mit der Netzwerkgröße.
158    
159     Lädt man das Dokument, wird man mit Metadaten und "normalen" Daten
160     konfrontiert.
161    
162     Metadaten:
163    
164     Revision=1
165     EndPart
166     Document
167     Info.Format=image/png
168     End
169    
170     Daten:
171    
172     PNG^Z...
173    
174     Nun stellt sich die Frage, wie man sicherstellt, daß Daten im Freenet
175     bleiben, da es nur endliche Speicherkapazität hat. Die Antwort ist
176     überraschend: Es geht nicht. Wenn ein Knoten sich entscheidet, Daten
177     zu löschen oder Platz für neue Daten zu schaffen, gehen zwangsläufig
178     andere Daten verloren. Dagegen hilft nur wiederholtes Einfügen und der
179     Wunsch, daß die eigenen Daten beliebt genug sind, damit sie abgerufen
180     werden und damit länger überleben.
181    
182     Absolute Anonymität und nichtnachvollziehbarkeit von Transaktionen ist
183     eben nicht vereinbar mit garantierter Datenspeicherung. Könnte man
184     garantiert Nachweisen, das ein Dokument existiert, so wäre es für
185     einen Knotenbetreiber schlecht möglich, Wissen über die Art der Daten
186     abzustreiten, die er speichert.
187    
188     =head3 SSK-Schlüssel
189    
190     Der zweite gebräuchliche Schlüsseltyp, mit dem man im Freenet
191     konfrontiert wird, ist ein C<SSK>-Schlüssel (C<SSK> steht für I<Signed
192     Subspace Key>). Hier ist einer:
193    
194     SSK@0OhVDWutibbBMbXmbxNXW0M6YFoPAgM
195    
196     Zwei Dinge unterscheiden Sie von CHK-Schlüsseln:
197    
198     Erstens ist ein SSK-Schlüssel eigentlich ein Schlüsselpaar, ein
199     Schlüssel (der private Schlüssel) muss für das Einfügen von Daten
200     benutzt werden, der zweite Schlüssel (der öffentliche Key) wird für
201     das Auslesen der Daten benutzt. Da die Daten signiert sind, kann nur der
202     oder die Besitzer des privaten Schlüssels Daten unter diesem einfügen,
203     während die Besitzer des öffentlichen Schlüssels überprüfen könenn,
204     ob die Daten tatsächlich mit dme richtigen Schlüssel signiert wurden.
205    
206     Zweitens ist die ID, unter dem diese Date abgelegt werden, nicht von den
207     Daten sondern nur vom "Namen" (dem Key) abhängig, man kann also URIs
208     erzeugen auf Dateien, die noch nicht eingefügt wurden.
209    
210     Diese Art Schlüssel ist relativ ineffizient und kann keine großen
211     Datenmengen speichern, SSKs werden also vorwiegend für Weiterleitungen
212     auf CHKs benutzt.
213    
214     Der obige SSK gehört übrigens zur "Freenet Explained"-Freesite, die die
215     einzelnen Schlüsseltypen (und mehr) erklärt. Finden kann man sie hier:
216    
217     SSK@0OhVDWutibbBMbXmbxNXW0M6YFoPAgM/fx/3//
218    
219     bzw., wenn man einen Freenet-Daemon am Laufen hat, hier:
220    
221     http://127.0.0.1:8888/SSK@0OhVDWutibbBMbXmbxNXW0M6YFoPAgM/fx/3//
222    
223     =head1 Und das ganze in Perl
224    
225     Das ganze wäre relativ witzlos, wenn man nur irgendwelche
226     langweiligen Tools und/oder Java benutzen kann. Es gibt
227     zwei Perl-Module (bzw. Modulfamilien), C<Net::Freenet::FCP>
228     (C<http://www.sf.net/projects/perlfcp>) und C<Net::FCP>.
229    
230     Ersteres ist älter (und vielleicht besser benannt) und konzentriert
231     sich mehr auf die Verarbeitung von Metadaten, ist aber recht schwach
232     beim eigentlichen Protokoll-Handling. Letzteres ist sehr gut beim
233     Protokoll-Handling und stark beim Kodieren und Dekodieren von Daten,
234     überläßt das Metadatenhandling aber dem Programmierer.
235    
236     C<Net::FCP> stammt von mir und ist entstanden, weil ich das andere Modul,
237     die es nur im Freenet gab, nicht herunterladen konnte (tja, so ist das
238     eben als Freenetter). Daher gehe ich auch nur auf dieses Module ein :)
239    
240     =head2 Installation
241    
242     Zuerst braucht man einen Freenet-Daemon
243     (http://www.freenetproject.org/). Die Installation ist unglaublich komplex
244     (unter Windows gibt es einen Installer, unter Unix ein paar Skripte). Der
245     Daemon braucht eine Weile, bis er warm wird (Minuten bis Stunden), was man
246     durch Surf-Versuche unterstützen sollte.
247    
248     Das C<Net::FCP>-Paket gibt es ganz normal per CPAN.
249    
250     =head2 Einfache Abfragen
251    
252     Die Abkürzung I<FCP> steht für I<Freenet Client Protocol> und ist das
253     Protokoll zwischen Freenet-Anwedungen und dem Freenet-Daemon. Es ist
254     unglaublich ineffizient und noch dazu nicht verschlüsselt. Dies ist der
255     Grund für die Empfehlung, den Daemon nur auf dem lokalen Rechner laufen
256     zu lassen: Wäre dumm, wenn man aus dem hochsicheren Freenet über eine
257     ungesicherte Internetverbindung die Windows-Sourcen herunterlädt und
258     sicher erwischen läßt (ist alles schon vorgekommen)...
259    
260     In Perl geht dies denkbar einfach:
261    
262     use Net::FCP;
263     my $fcp = new Net::FCP;
264    
265     Man kann dem Konstruktor von C<Net::FCP> direkt Namen und Port des
266     Freenet-Daemons übergeben. Üblicherweise holt er sich diese aber aus dne
267     Environment-Variablen C<FREDHOST> und C<FREDPORT>, die auf C<127.0.0.1>
268     bzw. C<8481> defaulten.
269    
270     Übrigens wird nur eine virtuelle Verbindung aufgebaut. Möchte man
271     sicherstellen, daß tatsächlich ein Daemon erreichbar ist, kann man einen
272     C<client_hello>-Request ausführen oder einfach loslegen.
273    
274     Im Normalfall heißt das also:: no configuration required.
275    
276     Hat man ein C<Net::FCP>-Objekt, kann man schon alle Requests durchführen,
277     die man amchen möchte:
278    
279     my ($meta, $data) = @{ $fcp->client_get (
280     "freenet:SSK@0OhVDWutibbBMbXmbxNXW0M6YFoPAgM/fx/3//"
281     15
282     ) };
283    
284     Der C<client_get>-Request erwartet zwei Argumente: eine Freenet-URI
285     (C<< freenet:<freenet-schlüssel> >>) und eine HTL. Letztere muss man
286     nicht angeben, man sollte es aber, und vor allem sollte man dem Benutzer
287     die Wahl der HTL überlassen. Das dritte, optionale, Argument ist für
288     spezielle Anwendungen: am besten ignorieren.
289    
290     Als Ergebnis erhält man immer eine Array-Referenz mit den Metadaten
291     und den Daten. Immer. Sollte ein Fehler auftreten wird eine Exception
292     ausgelöst (auf Perl: das Modul C<die>d). C<eval {}> hilft also im
293     Zweifelsfalle, für einfache Anwendungen ist das aber overkill.
294    
295     Bricht das Programm ab, so sieht das folgendermaßen aus:
296    
297     Net::FCP::Exception<<short_data,reason:unexpected eof or internal node error>>
298    
299     Oder, wenn die Daten nicht gefunden wurden:
300    
301     Net::FCP::Exception<<data_not_found,>>
302    
303     Letzteres bedeutet übrigens nicht aufgeben, sondern nochmal versuchen,
304     z.B. mit einer höheren HTL. Ein fehlgeschlagener Versuch mit hoher HTL
305     bedeutet imemr noch nicht aufgeben. Daemons in der "Nähe" wissen nun,
306     das die Daten verlangt werden. Nach einiger Zeit ist es wahrscheinlich,
307     das die Daten auf einmal in der Nähe liegen: daher nie aufgeben, nochmal
308     probieren. Niemand hat behauptet, man bekäme die Daten einfach aus dem
309     Freenet wieder heraus...
310    
311     Die Metadaten sind als Textdokument gespeichert. das Parsen dieser
312     Metadaten ist aber relativ krank, weshalb das Perl-Modul einen Hash mit
313     den geparsten Daten liefert.
314    
315     Die Metadaten und Daten kann man ausgeben:
316    
317     use Data::Dumper;
318     print STDERR Dumper $meta;
319     print $data;
320    
321     Dies ist genau der Quelltext für das "Tool" C<eg/fetch1>, mit dem man
322     I<einen> Freenet-Datenblock herunterladen kann.
323    
324     Ich benutze es üblicherweise so:
325    
326     eg/fetch1 SSK@0OhVDWutibbBMbXmbxNXW0M6YFoPAgM/fx/3// >data
327    
328     Das schreibt die Daten in eine Datei und gibt gleichzeitig dessen
329     Metadaten aus.
330    
331     Für den Key C<SSK@0OhVDWutibbBMbXmbxNXW0M6YFoPAgM/fx/3//> ergibt dies:
332    
333     'version' => { 'revision' => '1' },
334     'document' => [
335     {
336     'info' => { 'format' => 'image/png' },
337     'redirect' => { 'target' => 'freenet:CHK@pMKWiJyE3t-ZWvL1W9VdZvB3jcIKAwI,7pdyQiW7Hp9-8fEp-25C2w' },
338     'name' => 'activelink.png'
339     },
340     {
341     'info' => { 'format' => 'text/plain' },
342     'redirect' => { 'target' => 'freenet:CHK@2hewSY-I5ZhWpJ84dwhPbtdlvyIKAwI,ovcsrpD79xZfoW2021z91w' },
343     'name' => 'description.txt'
344     },
345     {
346     'info' => { 'format' => 'text/html' },
347     'redirect' => { 'target' => 'freenet:CHK@kME~NY2lX3q-em40ExTAFkyr~NkQAwI,3T2hFmTrPbLhCBANdy4OkA' },
348     'name' => 'index.html'
349     },
350     {
351     'info' => { 'format' => 'text/html' },
352     'redirect' => { 'target' => 'freenet:SSK@0OhVDWutibbBMbXmbxNXW0M6YFoPAgM/fx/4' },
353     'name' => '.next'
354     },
355     {
356     'info' => { 'format' => 'text/html' },
357     'redirect' => { 'target' => 'freenet:CHK@kME~NY2lX3q-em40ExTAFkyr~NkQAwI,3T2hFmTrPbLhCBANdy4OkA' }
358     }
359     ],
360     'raw' => 'Version
361     Revision=1
362     [... gekürzt...]
363     Info.Format=text/html
364     End
365     '
366     };
367    
368     Die eigentlichen Daten sind leer (Null Byte gross), das Dokument enthät
369     also nur Metadaten! Man beachte vor allem die teilweise recht tiefe
370     Verschachtelung.
371    
372     Der Key C<< $metadata->{raw} >> enthält die Metadaten, wie sie vom
373     Freenet kamen. Dies ist notwendig, da man manchmal die Metadaten
374     zum Prüfen in der exkaten Form benötigt, wie sie hochgeladen
375     wurden. Ansonsten kann man sie ignorieren.
376    
377     Der Key C<< $metadata->{document} >> enthält Informationen über das
378     Dokument oder in diesem Fall die Dokumente: Ein Hash pro Dokument. Schaut
379     man sich den Inhalt an (ein Array), so sieht man in jedem Hash ein
380     C<name>-Key, der den Namen des Subdokuments angibt (bis auf den letzten,
381     darauf komme ich gleich).
382    
383     Schaut man sich dir Freenet-URIs dieser Freesite an, so sieht man
384     derartige URIs:
385    
386     SSK@0OhVDWutibbBMbXmbxNXW0M6YFoPAgM/fx/3// # Hauptseite
387     SSK@0OhVDWutibbBMbXmbxNXW0M6YFoPAgM/fx/3//activelink.png # Icon
388     SSK@0OhVDWutibbBMbXmbxNXW0M6YFoPAgM/fx/3//description.txt # Beschreibung für Spider
389    
390     Wenn diese Dokumente mit C<client_get> anfordert, bekommt man immer obiges
391     Dokument. Freenet ignoriert nämlich alles, was hinter dem C<//> steht
392     und liefert daher immer das gleiche Dokument aus dem SSK-Bereich. (Darauf
393     verlassen soltle man sich nicht unbedingt, in Zukunft reagiert der
394     Freenet-Daemon vielleicht anders. Als Freenetter hat mans eben nicht
395     leicht).
396    
397     Der Teil hinter den beiden Slashes (C<//>) ist nun das Unterdokument, das
398     man über den Namen identifizieren kann:
399    
400     $activelink = grep $_->{name} eq "activelink.png",
401     @{ $metadata->{document} };
402    
403     Fehlet der C<name>-Eintrag ist es der Eintrag mit dem leeren Namen, in
404     diesem Fall der erste Link, der nichts nach den C<//> stehen hat. Der
405     C<name>-Key I<kann> vorhanden und leer sein: Freenet überprüft die Daten
406     nicht, daher gibt es durchaus unterschiedliche Auslegungen für das genau
407     Format.
408    
409     Die Metadaten sind etwas genauer in dem *hüstel* etwas veralteten
410     *hüstel* I<Freenet Explained>-Dokument beschrieben.
411    
412     Möchte man nun das C<activelink.png> herunterladen muss man in C<<
413     $activelink->{redirect} >> nachsehen. Meistens verweist dies auf ein
414     C<CHK>-Schlüssel. Letztere sind sozusagen Allgemeingut: jeder kann
415     sie benutzen, und da sie nicht änderbar sind, kann sie auch niemand
416     fälschen, daher muss man sie nicht signieren.
417    
418     Auf C<< $activelink->{info}{format} > sollte man sich übrigens nicht
419     verlassen.
420    
421     Und sollte kein C<redirect>-Key vorhanden sein, so ist das Dokument im
422     mitgelieferten Datenblock. Alles ganz logisch, einfach, und klar, wie man
423     sieht.
424    
425     Egal, der CHK-Key für C<activelink.png> liefert folgendes:
426    
427     'version' => { 'revision' => '1' },
428    
429     Und die Daten stellen ein PNG dar. Naja, nicht gerade üppig, die
430     Metadaten, aber man hätt's ja im Link auf dieses Dokument sehen
431     können. Als Freenetter hat mans nicht leicht.
432    
433     Aber mit diesen Erklärungen kann man schon einfacher Freenet-Spider
434     bauen. Die wichtigsten Tools sind veraltete und spärliche Dokumente
435     wie I<Freenet Explained> und Tools wie C<Data::Dumper>. "Veraltet" ist
436     übrigens nicht immer schlecht, da viele Dokumente auch alt sind oder sich
437     eh' nicht exakt an den "Standard" halten. Mit der Zeit wird hier sicher
438     eine Besserung eintreten.
439    
440     =head2 Methoden des Freesite-Managements
441    
442     Oder: "Wenn man Inhalte nicht mehr verändern kann, wie verändert man
443     sie?"
444    
445     Die offensichtliche Methode ist: "Man macht sie veränderbar". In
446     der Freenet-Gemeinde geistert seit langer Zeit der Mythos des
447     I<TUK>-Schlüssels, des I<Time Updatable Keys>. Diese Schlüssel tauchen
448     immer auf, wenn jemand über veränderbare Schlüssel spricht. Leider
449     weiss niemand, wie man sie implementieren soll, und ganz persönlich
450     fürchte ich, es wird niemals veränderbare Keys geben.
451    
452     =head3 "Editions"
453    
454     Die nächstliegende Methode nutzt die Eigenschaft von SSKs (genauer:
455     redirects) aus, das man den Namen sofort generieren kann, den Inhalt aber
456     erst später einfügt.
457    
458     Dies nutzt man aus, indem man I<Editionen> herausgibt und
459     durchnummeriert. Jede Edition enthält einen Link auf die nächste. Bis
460     man die nächste Edition einfügt, wird der Link-Inhalt nicht gefunden.
461    
462     Üblicherweise benutzt man in HTML ein C<IMG>-Element mit Link auf ein
463     Bild aus der nächsten Edition. Sieht man das Bild, weiss man, die
464     nächste Edition existiert und kann sich hinklicken.
465    
466     I<Freenet Explained> benutzt diese Methode. Der Link auf Edition 4 lautet:
467    
468     SSK@0OhVDWutibbBMbXmbxNXW0M6YFoPAgM/fx/4// # Link-Ziel
469     SSK@0OhVDWutibbBMbXmbxNXW0M6YFoPAgM/fx/4//activelink.png # IMG-SRC
470    
471     Beides existierte nicht als ich diesen Artikel schrieb (bzw. Freenet
472     konnte es nicht finden :). Wenn eine neue Edition heruasgegeben werden
473     soll, fügt der Autor einfach einen neuen Datenblock mit vielen Redirects
474     unter obigem SSK-Key ein.
475    
476     Ein C<.next>-Eintrag ist ebenfalls vorhanden: manche Spider folgen diesem
477     und können auf diese Weise immer die aktuelle Edition anzeigen, sofern
478     sie häufig genug scannen.
479    
480     Editionen sind einfach für den Autor einer Freesite und erfordern
481     keine spezielle Unterstützung. In der Benutzung sind sie allerdings
482     umständlich und häufige Updates sind auch nicht effizient.
483    
484     Daher hat sich eine zweite Methode entwickelt, die gerade bei häufig
485     geänderten Inhalten besser funktioniert:
486    
487     =head3 "Date Based Redirects"
488    
489     Freesites, die "Date Based Redirects" benutzen (kurz "DBR-Sites")
490     funktionieren ähnlich wie Editionen-basierte Freesites, nur wird statt
491     einer fortlaufenden Nummer die aktuelle Zeit benutzt.
492    
493     Die Freesite I<The Freenet Help Index>
494     (C<SSK@rjYFfgPHfolmcStiaoxESFfBXz8PAgM/FreenetHelp//>) benutzt diese
495     Methode. Folgende Metadaten wurden dazu hinterlegt:
496    
497     'version' => { 'revision' => '1' },
498     'document' => [
499     { 'date_redirect' => {
500     'increment' => '15180',
501     'target' => 'SSK@rjYFfgPHfolmcStiaoxESFfBXz8PAgM/FreenetHelp'
502     }
503     }
504     ],
505    
506     Statt einem einfachen C<redirect> gibt es jetzt einen
507     C<date_redirect>-Eintrag, und darin ein C<target> (dürfte bekannt sein)
508     und der Key C<increment>. Letzterer darf wie üblich fehlen, man sollte
509     dann C<86400> annehmen (ein Tag hat 86400 Sekunden). In diesem Beispiel
510     wird 86400 genommen (Hexadezimal 15180).
511    
512     Habe ich eigentlich schon erwähnt das jede Zahl im FCP-Protokoll oder
513     im Freenet hexadezimal kodiert wird? Also, praktisch immer, außer wenn
514     es mal nicht so ist. Und wozu man einen Offset addiert ist mir auch
515     schleierhaft. In der freien Wildbahn habe ich sowieso noch keinen gesehen.
516    
517     Der Link in C<target> ist nicht vollständig (unter anderem fehlt
518     hinten ein C<//>). Der komplette Link wird generiert, "indem die
519     aktuelle Zeit (POSIX-Zeit, üblicherweise das, was C<time> liefert),
520     auf C<increment>-Schritte gerundet und C<offset> addiert, als
521     Big-Endian-Hexadezimalzahl nach dem ersten Slash mit folgendem
522     Minuszeichen eingefügt wird."
523    
524     Und jetzt in Perl - zum Verstehen:
525    
526     my $doc = $metadata->{document][0]; # Oder [1] oder ...
527    
528     my $increment = (hex $doc->{increment}) || 86400;
529     my $offset = (hex $doc->{offset}) || 0;
530     my $target = $doc->{target} || die;
531    
532     my ($head, $tail) = split /\//, $target, 2;
533    
534     my $NOW = time;
535     my $time = $NOW - $NOW % $increment + $offset;
536    
537     my $result = sprintf "%s/%x-%s", $head, $time, $tail;
538    
539     Für "jetzt" (C<time() == 1084388445>) liefert der Algorithmus folgenden Link:
540    
541     SSK@rjYFfgPHfolmcStiaoxESFfBXz8PAgM/40a16900-FreenetHelp
542    
543     Und tatsächlich, unter diesem Key findet man wieder ein Dokument mit
544     vielen Redirects.
545    
546     DBRs haben den Vorteil, "automatisch" aktuell zu sein. Solange man nur
547     Redirects einfügt, ist die Belastung durch neue das Einfügen vieler
548     neuer Daten gering, Freenet kommt damit zurecht und löscht alte DBRs
549     bei Bedarf automatisch (ohne natürlich zu wissen, das sich in dne
550     Datenblöcken DBRs befinden, dnen die kann ja niemand dekodieren,d er
551     nicht den Schlüssel besitzt).
552    
553     Der Nachteil ist, das man eine aktuelle Uhrzeit braucht um die Site zu
554     finden. Schlimemr noch: die Freesite muss regelmäßig neu eingefügt
555     werden, eben alle C<increment> Sekunden.
556    
557     DBR-Freesites, die nicht mehr maintained werden, verschwinden deshalb fast
558     sofort, solange man nicht einen Zeitpunkt kennt, zu dem sie noch (bzw.
559     schon!) existierte.
560    
561     All dieses I<sollte> eigentlich in einem Metadata-Modul stattfinden. So
562     weit bin ich aber nicht, da mein Hauptziel das effiziente Herunterladen
563     großer Dateien ist.
564    
565     Womit ich beim Thema wäre.
566    
567     =head1 Effizient herunterladen
568    
569     =head1 Inserts
570 root 1.1
571