| 1 |
NAME |
| 2 |
Net::FCP - http://freenet.sf.net client protocol |
| 3 |
|
| 4 |
SYNOPSIS |
| 5 |
use Net::FCP; |
| 6 |
|
| 7 |
my $fcp = new Net::FCP; |
| 8 |
|
| 9 |
my $ni = $fcp->txn_node_info->result; |
| 10 |
my $ni = $fcp->node_info; |
| 11 |
|
| 12 |
DESCRIPTION |
| 13 |
See <http://freenet.sourceforge.net/index.php?page=fcp> for a |
| 14 |
description of what the messages do. I am too lazy to document all this |
| 15 |
here. |
| 16 |
|
| 17 |
WARNING |
| 18 |
This module is alpha. While it probably won't destroy (much :) of your |
| 19 |
data, it currently falls short of what it should provide (intelligent |
| 20 |
uri following, splitfile downloads, healing...) |
| 21 |
|
| 22 |
IMPORT TAGS |
| 23 |
Nothing much can be "imported" from this module right now. There are, |
| 24 |
however, certain "import tags" that can be used to select the event |
| 25 |
model to be used. |
| 26 |
|
| 27 |
Event models are implemented as modules under the "Net::FCP::Event::xyz" |
| 28 |
class, where "xyz" is the event model to use. The default is "Event" (or |
| 29 |
later "Auto"). |
| 30 |
|
| 31 |
The import tag to use is named "event=xyz", e.g. "event=Event", |
| 32 |
"event=Glib" etc. |
| 33 |
|
| 34 |
You should specify the event module to use only in the main program. |
| 35 |
|
| 36 |
If no event model has been specified, FCP tries to autodetect it on |
| 37 |
first use (e.g. first transaction), in this order: Coro, Event, Glib, |
| 38 |
Tk. |
| 39 |
|
| 40 |
FREENET BASICS |
| 41 |
Ok, this section will not explain any freenet basics to you, just some |
| 42 |
problems I found that you might want to avoid: |
| 43 |
|
| 44 |
freenet URIs are _NOT_ URIs |
| 45 |
Whenever a "uri" is required by the protocol, freenet expects a kind |
| 46 |
of URI prefixed with the "freenet:" scheme, e.g. "freenet:CHK...". |
| 47 |
However, these are not URIs, as freeent fails to parse them |
| 48 |
correctly, that is, you must unescape an escaped characters ("%2c" |
| 49 |
=> ",") yourself. Maybe in the future this library will do it for |
| 50 |
you, so watch out for this incompatible change. |
| 51 |
|
| 52 |
Numbers are in HEX |
| 53 |
Virtually every number in the FCP protocol is in hex. Be sure to use |
| 54 |
"hex()" on all such numbers, as the module (currently) does nothing |
| 55 |
to convert these for you. |
| 56 |
|
| 57 |
THE Net::FCP CLASS |
| 58 |
$meta = Net::FCP::parse_metadata $string |
| 59 |
Parse a metadata string and return it. |
| 60 |
|
| 61 |
The metadata will be a hashref with key "version" (containing the |
| 62 |
mandatory version header entries) and key "raw" containing the |
| 63 |
original metadata string. |
| 64 |
|
| 65 |
All other headers are represented by arrayrefs (they can be |
| 66 |
repeated). |
| 67 |
|
| 68 |
Since this description is confusing, here is a rather verbose |
| 69 |
example of a parsed manifest: |
| 70 |
|
| 71 |
( |
| 72 |
raw => "Version...", |
| 73 |
version => { revision => 1 }, |
| 74 |
document => [ |
| 75 |
{ |
| 76 |
info => { format" => "image/jpeg" }, |
| 77 |
name => "background.jpg", |
| 78 |
redirect => { target => "freenet:CHK\@ZcagI,ra726bSw" }, |
| 79 |
}, |
| 80 |
{ |
| 81 |
info => { format" => "text/html" }, |
| 82 |
name => ".next", |
| 83 |
redirect => { target => "freenet:SSK\@ilUPAgM/TFEE/3" }, |
| 84 |
}, |
| 85 |
{ |
| 86 |
info => { format" => "text/html" }, |
| 87 |
redirect => { target => "freenet:CHK\@8M8Po8ucwI,8xA" }, |
| 88 |
} |
| 89 |
] |
| 90 |
) |
| 91 |
|
| 92 |
$string = Net::FCP::build_metadata $meta |
| 93 |
Takes a hash reference as returned by "Net::FCP::parse_metadata" and |
| 94 |
returns the corresponding string form. If a string is given, it's |
| 95 |
returned as is. |
| 96 |
|
| 97 |
$fcp = new Net::FCP [host => $host][, port => $port][, progress => \&cb] |
| 98 |
Create a new virtual FCP connection to the given host and port |
| 99 |
(default 127.0.0.1:8481, or the environment variables "FREDHOST" and |
| 100 |
"FREDPORT"). |
| 101 |
|
| 102 |
Connections are virtual because no persistent physical connection is |
| 103 |
established. |
| 104 |
|
| 105 |
You can install a progress callback that is being called with the |
| 106 |
Net::FCP object, a txn object, the type of the transaction and the |
| 107 |
attributes. Use it like this: |
| 108 |
|
| 109 |
sub progress_cb { |
| 110 |
my ($self, $txn, $type, $attr) = @_; |
| 111 |
|
| 112 |
warn "progress<$txn,$type," . (join ":", %$attr) . ">\n"; |
| 113 |
} |
| 114 |
|
| 115 |
$txn = $fcp->txn(type => attr => val,...) |
| 116 |
The low-level interface to transactions. Don't use it. |
| 117 |
|
| 118 |
Here are some examples of using transactions: |
| 119 |
|
| 120 |
The blocking case, no (visible) transactions involved: |
| 121 |
|
| 122 |
my $nodehello = $fcp->client_hello; |
| 123 |
|
| 124 |
A transaction used in a blocking fashion: |
| 125 |
|
| 126 |
my $txn = $fcp->txn_client_hello; |
| 127 |
... |
| 128 |
my $nodehello = $txn->result; |
| 129 |
|
| 130 |
Or shorter: |
| 131 |
|
| 132 |
my $nodehello = $fcp->txn_client_hello->result; |
| 133 |
|
| 134 |
Setting callbacks: |
| 135 |
|
| 136 |
$fcp->txn_client_hello->cb( |
| 137 |
sub { my $nodehello => $_[0]->result } |
| 138 |
); |
| 139 |
|
| 140 |
$txn = $fcp->txn_client_hello |
| 141 |
$nodehello = $fcp->client_hello |
| 142 |
Executes a ClientHello request and returns it's results. |
| 143 |
|
| 144 |
{ |
| 145 |
max_file_size => "5f5e100", |
| 146 |
node => "Fred,0.6,1.46,7050" |
| 147 |
protocol => "1.2", |
| 148 |
} |
| 149 |
|
| 150 |
$txn = $fcp->txn_client_info |
| 151 |
$nodeinfo = $fcp->client_info |
| 152 |
Executes a ClientInfo request and returns it's results. |
| 153 |
|
| 154 |
{ |
| 155 |
active_jobs => "1f", |
| 156 |
allocated_memory => "bde0000", |
| 157 |
architecture => "i386", |
| 158 |
available_threads => 17, |
| 159 |
datastore_free => "5ce03400", |
| 160 |
datastore_max => "2540be400", |
| 161 |
datastore_used => "1f72bb000", |
| 162 |
estimated_load => 52, |
| 163 |
free_memory => "5cc0148", |
| 164 |
is_transient => "false", |
| 165 |
java_name => "Java HotSpot(_T_M) Server VM", |
| 166 |
java_vendor => "http://www.blackdown.org/", |
| 167 |
java_version => "Blackdown-1.4.1-01", |
| 168 |
least_recent_timestamp => "f41538b878", |
| 169 |
max_file_size => "5f5e100", |
| 170 |
most_recent_timestamp => "f77e2cc520" |
| 171 |
node_address => "1.2.3.4", |
| 172 |
node_port => 369, |
| 173 |
operating_system => "Linux", |
| 174 |
operating_system_version => "2.4.20", |
| 175 |
routing_time => "a5", |
| 176 |
} |
| 177 |
|
| 178 |
$txn = $fcp->txn_generate_chk ($metadata, $data[, $cipher]) |
| 179 |
$uri = $fcp->generate_chk ($metadata, $data[, $cipher]) |
| 180 |
Calculates a CHK, given the metadata and data. $cipher is either |
| 181 |
"Rijndael" or "Twofish", with the latter being the default. |
| 182 |
|
| 183 |
$txn = $fcp->txn_generate_svk_pair |
| 184 |
($public, $private) = @{ $fcp->generate_svk_pair } |
| 185 |
Creates a new SVK pair. Returns an arrayref with the public key, the |
| 186 |
private key and a crypto key, which is just additional entropy. |
| 187 |
|
| 188 |
[ |
| 189 |
"acLx4dux9fvvABH15Gk6~d3I-yw", |
| 190 |
"cPoDkDMXDGSMM32plaPZDhJDxSs", |
| 191 |
"BH7LXCov0w51-y9i~BoB3g", |
| 192 |
] |
| 193 |
|
| 194 |
A private key (for inserting) can be constructed like this: |
| 195 |
|
| 196 |
SSK@<private_key>,<crypto_key>/<name> |
| 197 |
|
| 198 |
It can be used to insert data. The corresponding public key looks |
| 199 |
like this: |
| 200 |
|
| 201 |
SSK@<public_key>PAgM,<crypto_key>/<name> |
| 202 |
|
| 203 |
Watch out for the "PAgM"-part! |
| 204 |
|
| 205 |
$txn = $fcp->txn_invert_private_key ($private) |
| 206 |
$public = $fcp->invert_private_key ($private) |
| 207 |
Inverts a private key (returns the public key). $private can be |
| 208 |
either an insert URI (must start with "freenet:SSK@") or a raw |
| 209 |
private key (i.e. the private value you get back from |
| 210 |
"generate_svk_pair"). |
| 211 |
|
| 212 |
Returns the public key. |
| 213 |
|
| 214 |
$txn = $fcp->txn_get_size ($uri) |
| 215 |
$length = $fcp->get_size ($uri) |
| 216 |
Finds and returns the size (rounded up to the nearest power of two) |
| 217 |
of the given document. |
| 218 |
|
| 219 |
$txn = $fcp->txn_client_get ($uri [, $htl = 15 [, $removelocal = 0]]) |
| 220 |
($metadata, $data) = @{ $fcp->client_get ($uri, $htl, $removelocal) |
| 221 |
Fetches a (small, as it should fit into memory) file from freenet. |
| 222 |
$meta is the metadata (as returned by "parse_metadata" or "undef"). |
| 223 |
|
| 224 |
The $uri should begin with "freenet:", but the scheme is currently |
| 225 |
added, if missing. |
| 226 |
|
| 227 |
Due to the overhead, a better method to download big files should be |
| 228 |
used. |
| 229 |
|
| 230 |
my ($meta, $data) = @{ |
| 231 |
$fcp->client_get ( |
| 232 |
"freenet:CHK@hdXaxkwZ9rA8-SidT0AN-bniQlgPAwI,XdCDmBuGsd-ulqbLnZ8v~w" |
| 233 |
) |
| 234 |
}; |
| 235 |
|
| 236 |
$txn = $fcp->txn_client_put ($uri, $metadata, $data, $htl, $removelocal) |
| 237 |
my $uri = $fcp->client_put ($uri, $metadata, $data, $htl, $removelocal); |
| 238 |
Insert a new key. If the client is inserting a CHK, the URI may be |
| 239 |
abbreviated as just CHK@. In this case, the node will calculate the |
| 240 |
CHK. If the key is a private SSK key, the node will calculcate the |
| 241 |
public key and the resulting public URI. |
| 242 |
|
| 243 |
$meta can be a hash reference (same format as returned by |
| 244 |
"Net::FCP::parse_metadata") or a string. |
| 245 |
|
| 246 |
The result is an arrayref with the keys "uri", "public_key" and |
| 247 |
"private_key". |
| 248 |
|
| 249 |
THE Net::FCP::Txn CLASS |
| 250 |
All requests (or transactions) are executed in a asynchronous way. For |
| 251 |
each request, a "Net::FCP::Txn" object is created (worse: a tcp |
| 252 |
connection is created, too). |
| 253 |
|
| 254 |
For each request there is actually a different subclass (and it's |
| 255 |
possible to subclass these, although of course not documented). |
| 256 |
|
| 257 |
The most interesting method is "result". |
| 258 |
|
| 259 |
new arg => val,... |
| 260 |
Creates a new "Net::FCP::Txn" object. Not normally used. |
| 261 |
|
| 262 |
$txn = $txn->cb ($coderef) |
| 263 |
Sets a callback to be called when the request is finished. The |
| 264 |
coderef will be called with the txn as it's sole argument, so it has |
| 265 |
to call "result" itself. |
| 266 |
|
| 267 |
Returns the txn object, useful for chaining. |
| 268 |
|
| 269 |
Example: |
| 270 |
|
| 271 |
$fcp->txn_client_get ("freenet:CHK....") |
| 272 |
->userdata ("ehrm") |
| 273 |
->cb(sub { |
| 274 |
my $data = shift->result; |
| 275 |
}); |
| 276 |
|
| 277 |
$txn = $txn->userdata ([$userdata]) |
| 278 |
Set user-specific data. This is useful in progress callbacks. The |
| 279 |
data can be accessed using "$txn->{userdata}". |
| 280 |
|
| 281 |
Returns the txn object, useful for chaining. |
| 282 |
|
| 283 |
$txn->cancel (%attr) |
| 284 |
Cancels the operation with a "cancel" exception anf the given |
| 285 |
attributes (consider at least giving the attribute "reason"). |
| 286 |
|
| 287 |
UNTESTED. |
| 288 |
|
| 289 |
$result = $txn->result |
| 290 |
Waits until a result is available and then returns it. |
| 291 |
|
| 292 |
This waiting is (depending on your event model) not very efficient, |
| 293 |
as it is done outside the "mainloop". The biggest problem, however, |
| 294 |
is that it's blocking one thread of execution. Try to use the |
| 295 |
callback mechanism, if possible, and call result from within the |
| 296 |
callback (or after is has been run), as then no waiting is |
| 297 |
necessary. |
| 298 |
|
| 299 |
The Net::FCP::Exception CLASS |
| 300 |
Any unexpected (non-standard) responses that make it impossible to |
| 301 |
return the advertised result will result in an exception being thrown |
| 302 |
when the "result" method is called. |
| 303 |
|
| 304 |
These exceptions are represented by objects of this class. |
| 305 |
|
| 306 |
$exc = new Net::FCP::Exception $type, \%attr |
| 307 |
Create a new exception object of the given type (a string like |
| 308 |
"route_not_found"), and a hashref containing additional attributes |
| 309 |
(usually the attributes of the message causing the exception). |
| 310 |
|
| 311 |
$exc->type([$type]) |
| 312 |
With no arguments, returns the exception type. Otherwise a boolean |
| 313 |
indicating wether the exception is of the given type is returned. |
| 314 |
|
| 315 |
$exc->attr([$attr]) |
| 316 |
With no arguments, returns the attributes. Otherwise the named |
| 317 |
attribute value is returned. |
| 318 |
|
| 319 |
SEE ALSO |
| 320 |
<http://freenet.sf.net>. |
| 321 |
|
| 322 |
BUGS |
| 323 |
AUTHOR |
| 324 |
Marc Lehmann <pcg@goof.com> |
| 325 |
http://www.goof.com/pcg/marc/ |
| 326 |
|