Clone this wiki locally
Table of Contents
The Freenet Client Protocol is a simple, text-based protocol designed to allow third-party applications to interact with Freenet. Supported functionality includes:
- Inserting of data into Freenet
- Retrieval of data from Freenet
- Querying the status of Freenet
- Managing the other Freenet nodes that are connected to your own node.
Note: FCP library authors are encouraged to release their libraries under the Lesser GNU Public License.
- jFCPLib – Java
- pyFreenet - Python; official
- ruby-fcp - Ruby
- perlFreenet - Perl modules to access Freenet
- FCP2lib.NET - (.NET- / Mono-DLL )
To experiment, you can connect with netcat. Example:
nc 127.0.0.1 9481
Start by sending FCPv2/ClientHello.
FCP 2.0 was first supported in Freenet 0.7, and is a non-backwards compatible replacement for the original Freenet Client Protocol supported by versions of Freenet prior to 0.7. The protocol is not backwards compatible because of the fundamental nature of the changes to Freenet 0.7 relative to previous versions of Freenet. Unlike in FCPv1, FCPv2 Client do not have to handle the metadata or reassembling splitfiles.
FCP operates over a TCP connection, typically between Freenet and another application running on the same computer. By default, Freenet listens for FCPv2 connections on port 9481. The protocol is mostly text-based, and uses the UTF-8 character set encoding.
The basic unit of FCPv2 is the message, which consists of a message name, and 0 or more key-value pairs called "fields". The keys of the key-value pairs are case-sensitive, so “identity” is not the same field as “Identity.” Messages can be sent from client to server, or from server to client. Multiple messages can be sent in either direction in pipelined fashion.
An example message is show as follow:
|without payload||with payload|
MessageName Field1=Value1 Field2=Value2 ... EndMessage
MessageName Field1=Value1 Field2=Value2 DataLength=123 ... Data [...payload...]
If the message include some binary "payload", the message will include a field (often called DataLength, or File.N.DataLength) specifying the length of payload in bytes. The message will be ended with Data (instead of EndMessage) in this case.
Most messages include an Identifier, which identifies the request. This is mandatory for request messages (ClientGet, ClientPut, SubscribeUSK), but is optional for most messages and will be echoed back to the client on replies if it is present.
Blank lines between messages are ignored.
Lines can be terminated with or , but not a mixture of both. All node-to-client message break with .
|Client to Node||Node to Client|
|Persistence=connection||request is not persistent, will be dropped if the client connection is lost; default|
|Persistence=reboot||request will persist across client connection drops, but will be lost if the node is restarted|
|Persistence=forever||request will persist forever; the node will write it to a plaintext file on disk, and restart it if the node is restarted|
If a request is persistent (i.e. Persistence=reboot or Persistence=forever) the client will be notified when the follow events occur:
|Event||Message for ClientGet||Message for ClientPut|
|request complete||DataFound (followed by AllData if ReturnType=direct)||PutSuccessful|
|request failed / canceled||GetFailed||PutFailed|
|compression started (only if specified by the Verbose field)||N/A||StartedCompression|
|compression finished (only if specified by the Verbose field)||N/A||FinishedCompression|
|progress (only if specified by the Verbose field)||SimpleProgress||SimpleProgress|
Requests can be assigned to the Global Queue, by setting Global=true when starting them. The idea with the global queue is to have a single queue which all interested FCP apps (e.g. FUQID) can watch, and which all FCP apps can assign downloads to (e.g. Frost or FProxy queuing a download to the global queue so that the user gets the benefit of his preferred download manager interface). All apps have full control of all downloads on the global queue; they can remove them, list them, and receive notifications about them:
ClientPut URI=CHK@ UploadFrom=disk Filename=/home/toad/debian-sarge-dvd1.iso Identifier=sarge-disk-1 ClientToken=This is the debian sarge dvd number 1 Global=true EndMessage
This queues an insert on the global queue. Clients do not receive notifications about requests on the global queue, even if they started the request, unless they ask for them with a WatchGlobal message. Once watch-the-global-queue is enabled, they will receive status updates about all requests on the global queue, and if they do ListPersistentRequests, they will see both their own queued persistent requests and those queued to the global persistent requests queue.
Several priority classes are supported:
|0||Maximum priority: anything more important than Fproxy|
|1||(Very High) Interactive priority class: Fproxy|
|2||(High) Semi-interactive priority class: Fproxy immediate-mode (not to disk) large file downloads|
|3||(Medium) Updatable site checks|
|4||(Low) Bulk offline splitfile fetches (usually to disk)|
|5||(Very Low) Prefetch priority class|
|6||Pause (will not fetch)|
For ClientGet messages, the default priority depends on the ReturnType:
For ClientPut messages, the default priority class is 2. In Freenet 0.7 at present, inserts and requests do not compete directly with one another, nor do SSKs with CHKs; they are scheduled separately because of their different performance characteristics.
|-||-||report when complete (Not a flag, always on)|
|3||4||CompatibilityMode messages (since 1255)|
|4||8||ExpectedHashes messages (since 1255)|
|6||32||ExpectedMIME messages (since 1307)|
|7||64||ExpectedDataLength messages (since 1307)|
SimpleProgress + CompatibilityMode + ExpectedDataLength = 1 + 4 + 64 = 69 = 1 0 0 0 1 0 1 (Binary representation) ^ ^ ^ ^ ^ ^ ^ 7 6 5 4 3 2 1 (Bit position number)
summary of data types used in FCP:
- Byte amount
- Floating point number
- String list
- Time interval
- User input string