%include "std.mgp" %%default 1 bimage "gtk/gtk-window.jpg" 1024x768, center %page %charset "iso8859-1" %bimage "bg.png" 1280x1024 Freenet "I worry about my child and the Internet all the time, even though she's too young to have logged on yet. Here's what I worry about. I worry that 10 or 15 years from now, she will come to me and say 'Daddy, where were you when they took freedom of the press away from the Internet?'" --Mike Godwin, Electronic Frontier Foundation %center %%image "gtk/hello31.jpg" 0 200 200 1 %page Ziele Projekt, Dokumentation und Implementation frei und für jeden zugänglich %pause Informationsfreiheit ohne Zensur %pause garantiert anonyme Veröffentlichung %pause garantierter Zugang zur Information %page Implementation virtuelles Netzwerk %pause Ausfall auch großer Teile des Netzes werden kompensiert %pause einzelne Knoten %pause kennen die gespeicherten Daten nicht %pause können Datenverkehr anderer Knoten nicht lesen %pause kennen Sender und Empfänger von Daten nicht %page Freenet aus "Benutzersicht" %pause Alle Daten werden in Datenblöcken (keys) organisiert %pause Keys werden in das Netzwerk "eingefügt" %pause Maximale Größe eines Datenblocks: 1MB %pause HTML-Seiten werden üblicherweise in einem Key gespeichert %pause Große Dateien werden mit forward error correction in kleinere Blöcke geteilt %pause Algorithm::FEC %page Freenet-URLs Übliche Form eines Freenet-Links: %font "t4" http://localhost:8888/ CHK@pfAv9IejYPXDguEkUhiNUMAwI,blzDbhN~q4JrfRWw //Suffix %font "s" %pause http://localhost:8888/ nur der Pfad zum HTTP-Proxy des Knotens %pause CHK ist der Typ (hier: Content Hash Key) %pause Dahinter Folgen Parameter (meist Schlüssel u.ä.), "base64"-codiert %pause Suffix (nach //) wird von Freenet ignoriert %page Content Hash Keys %font "t3" CHK@pfAv9IejYPLQwaTLXDguEkUhiNUMAwI,blzDbhN~8Q28esq4JrfRWw ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^ Typ Routing-Key Crypto-Key %font "s" %pause Crypto-Key wird aus den Daten generiert verschlüsselt die Daten %pause Routing-Key wird aus dem Crypto-Key generiert dient zum Indizieren und Suchen der Daten %pause Daten können mehrfach eingefügt werden. Da gleiche Daten == gleicher Key wird das Netzwerk nicht belastet %page Freenet Live %system "/opt/bin/links -g -mode 1024x756 http://129.13.162.73:8888/" %page Abrufen eines Keys (1) Beispiel: ein Bild der Seite "Thought-Crime": %font "t3" CHK@pfAv9IejYPLQwaTLXDguEkUhiNUMAwI,blzDbhN~8Q28esq4JrfRWw %font "s" 1. Suche nach CHK@pfAvI...kUhiNUMAwI %pause (a5f02ff487a36...e12452188d50c0302) %pause 0c == 4k, 0302 == CHK + Twofish %pause Skalierbarkeit durch lineare Suche %pause 2. Entschlüsseln der Daten mit blzDbhN~8Q28esq4JrfRWw (6e5cc36e137ef10dbc7acab826b7d15b) %page Abrufen eines Keys (2) Abgerufene Daten bestehen aus Metadaten und Daten Metadaten: %font "t3" Revision=1 EndPart Document Info.Format=image/png End %font "s" Daten: %font "t3" PNG^Z... %font "s" %page Signed Subspace Key %font "t3" SSK@Sc6qV~D6iFhaYord6HtbjJ8MaEYPAgM,Jrd6HtbjJfw1UO1g/YoYo ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^ Typ Public Key PAgM Entropie + Daten %font "s" %pause Daten werden mit einem private Key signiert %pause maximale Größe 32K %pause mit einem Schüsselpaar können viele Keys eingefügt werden Unterscheidung über angehängte Daten %page Und nun: Perl Net::Freenet::FCP http://www.sf.net/projects/perlfcp %pause stark bei Metadaten %pause Net::FCP CPAN %pause stark beim asynchronen Einfügen bzw. Abrufen %pause ist von mir :) %page Einfache Abfragen %pause Abfragen benutzen das Freenet Client Protocol (FCP) %pause ein einziger Horror %pause zum Glück gibt's Perl :) %pause %font "t5" use Net::FCP; my $fcp = new Net::FCP; %pause my ($meta, $data) = @{ $fcp->client_get ( "freenet:SSK@0O....PAgM/fx/3//" 15 ) }; %font "s" %page Fehlerbehandlung %pause Bei Nichtfinden: die %pause Net::FCP::Exception<> %pause einfach nochmal probieren %pause Bei Netzwerkfehlern: die %pause Net::FCP::Exception<> %pause einfach nochmal probieren %pause Bei Schluckauf: die %pause einfach nochmal probieren %pause Daher: eval { } benutzen. %page Metadaten in Perl %pause Metadaten in Perl: Net::FCP::Metadata-Objekte %pause Am besten einmal ausgeben lassen: %font "t5" use Data::Dumper; print STDERR Dumper $meta; print $data; %font "s" %pause z.B. mit eg/fetch1: %font "t4" eg/fetch1 SSK@0OhV.......oPAgM/fx/3// >data %font "s" %page Metadaten einer Freesite Stark gekürzt: %pause %font "t5" version => { 'revision' => '1' }, document => [ { info => { format => 'image/png' }, redirect=> { target => 'freenet:CHK@...' }, name => 'activelink.png' } ], raw => 'Version Revision=1 ... End ' }; %font "s" %page Manifest-Metadaten Beispiele für Keys aus den Metadaten der Freesite: %pause %font "t3" Hauptseite SSK@0OhVDWutibbBMbXmbxNXW0M6YFoPAgM/fx/3// %pause Icon SSK@0OhVDWutibbBMbXmbxNXW0M6YFoPAgM/fx/3//activelink.png %font "s" %pause client_get liefert identische Daten %pause Freenet ignoriert alles hinter // %page Manifest-Metadaten Selbst nachschauen durch Lookup in den Metadaten: %pause %font "t5" $link = grep $_->{name} eq "activelink.png", @{ $metadata->{document} }; %pause print $link->{redirect}; %font "s" %pause kein Redirect => Daten sind angehängt %page Freesite-Management %pause Wie verändert man Daten, die nicht mehr veränderbar sind? %pause Lösung 1: Veränderbare Keys (TUKs) %pause Viel Rauch, wenig Realität %pause Lösung 2: Editions %pause Links auf zukünftige Inhalte %pause "verkettete Liste" %pause Lösung 3: DBR-Links %pause Date-Based-Redirects %page Editions (1) A-HREF + IMG-Element, zeigt auf activelink der nächsten Edition. %pause Beispiel: Freesite "Freenet Explained" %font "t5" SSK@0OhV...oPAgM/fx/4// # Link-Ziel SSK@0OhV...oPAgM/fx/4//activelink.png # IMG-SRC %font "s" %pause Edition 4 existiert noch nicht %pause Editionen werden durchnummeriert %pause Für Spider: .next-Eintrag %page Editions (2) %pause Vorteile: %pause "relativ" einfach für Autoren %pause realisierbar mit "Hausmittel" %pause keine Pflege notwendig %pause Nachteile: %pause umständlich in der Benutzung %pause "es ist und bleibt ein Hack" %page Date-Based-Redirects (1) Unterstützung spezieller Redirects %pause Timestamp statt fortlaufender Nummer %pause Spezielle Metadaten %pause Beispiel "The Freenet Help Index": %pause %font "t4" 'version' => { 'revision' => '1' }, 'document' => [ { 'date_redirect' => { 'increment' => '15180', 'target' => 'SSK@rjY...8PAgM/FreenetHelp' } } ], %font "s" %page Date-Based-Redirects (2) Vorteile: %pause einfach in der Benutzung %pause "sauber" über Metadaten implementiert %pause festgelegter Key %pause Nachteile: %pause feste Abstände zwischen Updates %pause häufige Pflege %pause keine inserts == keine Freesite %page DBRs in Perl %font "t5" %pause my $D = $metadata->{document}[0]; %pause my $incr = (hex $D->{increment}) || 86400; my $offs = (hex $D->{offset}) || 0; my $targ = $D->{target} || die; %pause my ($head, $tail) = split /\//, $targ, 2; %pause my $NOW = time; my $time = $NOW - $NOW % $incr + $offs; %pause my $result = sprintf "%s/%x-%s", $head, $time, $tail; %pause %font "t3" SSK@rjYFfgPHfolmcStiaoxESFfBXz8PAgM/40a16900-FreenetHelp %page Effiziente Freenet-Abfragen %pause Problem: Freenet == hohe Latenz %pause parallele Anfragen absolut notwendig %pause Implementation über Threads schlecht %pause Perl hat keine echten Threads %pause %font "s" Lösung: %pause Ereignisgesteuerung %pause Unterstützung für Coro, Event, Glib, Tk... %page Transaktionen %pause Implementation von $fcp->client_get: %pause %font "t5" my $txn = $fcp->txn_client_get (...); %pause return $txn->result; %pause %font "s" Jeder FCP-Requesttyp besitzt eine txn_-Methode. %pause Parallelisierung: %pause %font "t5" map $_->result, map $_->txn_client_get ($_), @download; %page Asynchrone Abfragen %pause Ziel: n ausstehende Anfragen zu jedem Zeitpunkt %pause Callback bei Beendigung %pause %font "t5" my $txn = $fcp->txn_client_get (...) ->cb (\&callback); %font "s" %pause txn-Methoden sind i.Allg. "chainbar" %page Hauptprogramm Hauptprogramm muß in die Hauptschleife springen: %font "t5" use Net::FCP qw(event=Event); %pause my $fcp = new Net::FCP; $fcp->txn_client_get ($_)->cb (\&finished) for @ARGV; %pause Event::loop; %font "s" %pause Angabe des Event-Moduls nur im Hauptprogramm %page Callback %font "t5" %pause sub finished { my ($txn) = @_; %pause # .. neue txn starten %pause my ($meta, $data) = eval { @{ $txn->result } }; %pause if ($@) { warn "error $@, who cares :)" } else { warn "Lo and Behold! We got soemthing!"; # tue etwas } } %page Callbacks und Threads Das Coro Modul ermöglicht es, "Callback-Stil" und "Thread-Stil" zu mischen: %pause %font "t4" use Net::FCP qw(event=Coro); my $fcp = new Net::FCP; # Achtung. Pseudocode :) for my $url (@urls) { async { %pause my ($meta, $data) = @{ $fcp->client_get ($url) }; for (@alle_splitfile_blöcke) { $fcp->txn_client_get (...) ->cb (\&save_splitfile_block); } }; } %page Splitfiles %pause Zerteilen von großen Dateien in: %pause Segmente (max. 128MB) %pause Datenblöcke (max 1MB) %pause Checkblöcke (50% der Gesamtzahl) %page Publizieren Einfügen von Keys ist so einfach(?) wie auslesen %pause %font "t4" $fcp->client_put ($uri, $meta, $data, $htl, $remove); %font "s" %pause Parallelität mit txn_client_put %pause Key Collisions sind O.K. %pause Key wird automatisch erzeugt: %pause %font "t4" my $attr = $fcp->client_put ('CHK@', "", "Daten\n", 20); print "Eingefügte URI: $attr->{uri}\n"; %pause %font "t3" => freenet:CHK@MT~LuxKHH8fugJehkcgp239h7C4KAwI,378rJzHVZbsQbd7VGMHxSg %page SSK-Keys generieren SSK = Spezialfall von SVK %pause %font "t4" my ($public, $private, $crypto) = @{ $fcp->generate_svk_pair }; %font "s" %pause Einfüge- und Ausleseschlüssel: %pause %font "t4" my $name = "..."; # beliebig my $get = "SSK\@${public}PAgM,$crypto/$name"; %pause my $put = "SSK\@$private,$crypto/$name"; %font "s" %pause Net::FCP::Key::SSK %page Erzeugen einer Freesite (1) %pause %font "t4" perl -MNet::FCP -MNet::FCP::Key::SSK -e 'Net::FCP::Key::SSK->new_from_fcp (Net::FCP->new) ->save ($ARGV[0])' mykey %font "t5" %pause # Definitionen my $edition = 1; my $keyfile = "mykey"; my $htl = 10; %pause # Module use Net::FCP qw(event=Event); use Net::FCP::Metadata; use Net::FCP::Key::SSK; %page Erzeugen einer Freesite (2) %font "t4" %pause # Notwendige Objekte erzeugen/laden my $fcp = new Net::FCP; my $ssk = new_from_file Net::FCP::Key::SSK $keyfile; %pause \# Hilfsfunktion zum (asynchronen) Einfügen sub add_key { my ($name, $key, $meta, $data) = @_; $fcp->txn_client_put ($chk, $meta, $data, $htl, 1) ->cb (sub { eval { my $attr = $_[0]->result; } or warn "'$name': $@"; }); } %page Erzeugen einer Freesite (3) %font "t4" \# Hilfsfunktion für Dateien sub add_file { my ($name, $path, $contenttype) = @_; # lies die Datei ein my $data = ... my $chk = $fcp->generate_chk ("", $data); $manifest->add_redirect ($name => $chk, format => $contenttype); add_key $name, $chk, "", $data; } %page Erzeugen einer Freesite (4) %font "t4" \# Hauptprogramm: Manifest erzeugen my $manifest = new Net::FCP::Metadata; %pause \# .prev-Link $manifest->add_redirect ( ".prev" => $ssk->gen_pub ($edition - 1)) if $edition > 1; %pause \# .next-Link $manifest->add_redirect ( ".next" => $ssk->gen_pub ($edition + 1)); %page Erzeugen einer Freesite (5) %font "t4" \# Dateien hinzufügen %pause add_file "activelink.png" => "logo.png", "image/png"; add_file "" => "index.html", "text/html"; add_file "index.html" => "index.html", "text/html"; add_file "freesite" => "freesite", "text/plain"; %pause \# Manifest einfügen my $site = $ssk->gen_pub ($edition); %pause add_key "manifest", $site, $manifest, ""; %pause print "site generated as $site//\n"; %pause Event::loop; %page Erzeugen einer Freesite (6) Ausgabe des Programms: %font "t5" %pause site generated as SSK@wg...gPAgM,Jr...UO1g/1// %pause Insert of 'freesite' (1688 bytes) ok. Insert of 'activelink.png' (1346 bytes) ok. Insert of 'index.html' (200 bytes) ok. Insert of '' (200 bytes) ok. Insert of 'manifest' (0 bytes) ok. %page Fragen?