Il Freenet Client Protocol (FCP) è progettato per astrarre gli elementi base di Freenet, cosicché gli svluppatori di client non debbano tener traccia del protocollo principale di Freenet. FCP dovrebbe costituire l'ossatura di Freenet - la gestione dei metadati non è compresa in FCP, anche se un'estensione a quest'ultimo potrebbe venire ad essere più avanti per evitare di scrivere librerie per la gestione di metadati in molti linguaggi.
Questo protocollo non è stato progettato per viaggiare su una rete - solo via loopback. Di default i nodi non dovrebbero accettare connessioni FCP da nodi diversi da localhost.
Di default FCP usa la porta 8481, ma qualsiasi client che usa FCP dovrebbe permettere di configurare tale valore, perché questo potrebbe essere cambiato nel file di configurazione del nodo o da qualche futura revisione di FCP.
FCP segue il setup FNP per la sessione e la presentazione.
Nella parte che segue i numeri sono sempre espressi in esadecimale e i campi tra parentesi quadre sono opzionali.
FCP permettere una transazione per ogni connessione, dopodiché la connessione viene interrotta. All'inizio di ogni connessione il client deve inviare i seguenti 4 byte:
00 00 00 02
Essi sono i 2 byte per l'identificativo di sessione e i 2 byte per l'identificativo di presentazione. In futuro identificativi differenti potranno essere usato per permettere l'esistenza di sintassi alternative o connessioni FCP cifrate da host remoti, per esempio.
Dopo aver mandato gli identificativi di sessione e presentazione il client invia un messaggio per iniziare la transazione, dopodiché attende uno o più messaggi da parte del nodo finché la transazione non è completata. I messaggi consistono in una serie di linee terminate da LF o da CRLF, in questa forma:
Header
[Campo1=Valore1]
.
.
[CampoN=ValoreN]
EndMessage
Quello che segue è l'insieme completo dei messaggi da client a nodo, con le possibili risposte da nodo a client (vengono mostrate solo le intestazioni).
-
ClientGet
-
URIError
-
Restarted
-
DataNotFound
-
RouteNotFound
-
DataFound
-
ClientPut
-
URIError
-
Restarted
-
RouteNotFound
-
KeyCollision
-
Pending
-
Success
Inoltre, il nodo può rispondere a qualsiasi messaggi di un client con un FormatError , il che significa che il comando non è stato compreso, e il nodo può rispondere in qualsiasi momento con un Failed , il che indica un fallimento del nodo medesimo:
FormatError
[Reason=<stringa descrittiva>]
EndMessage
Failed
[Reason=<stringa descrittiva>]
EndMessage
Failed e FormatError non verranno discussi nel resto di questo documento. I client dovrebbero essere pronti a gestire un messaggio Failer in qualsiasi momento, ed un messaggio FormatError come risposta a qualsiasi loro messaggio. Entrambi questi messaggi terminando la transazione e la connessione.
L'handshaking è totalmente opzionale per il client. Si noti che essa conta come una transazione, e dunque la connessione viene interrotta dopo di essa.
(Client->Nodo)
ClientHello
EndMessage
Il nodo manda come risposta il seguente messaggio:
(Nodo->Client)
NodeHello
Protocol=<numero: numero di versione del protocollo. 1 al momento>
Node=<stringa: forma libera: Descrizione dei nodi>
EndMessage
(Client->Nodo)
ClientGet
URI=<stringa: URI pienamente specificata, come freenet:KSK@gpl.txt>
HopsToLive=<numero: hop di vita>
EndMessage
Ora il client è in uno stato di waiting. Il nodo può restituire uno
dei seguenti messaggi di errore:
-
URIError : URL Freenet non valida. La transazione è terminata.
-
Restarted : Il client dovrebbe continuare ad aspettare.
-
DataNotFound : La transazione viene terminata a causa dell'incapacità di trovare i dati.
-
RouteNotFound : La transazione viene terminata a causa dell'incapacità di trovare una rotta.
Altrimenti viene restituito un messaggio DataFound :
DataFound
DataLength=<numero: numero di byte di metadati + dati>
[MetadataLength=<number: default = 0, numero di byte di metadati>
EndMessage
Dopo un messaggio DataFound vengono inviati a blocchi i dati stessi:
DataChunk
Length=<numero: numero di byte nel campo che segue>
Data
<@Length bytes of data>
Finché l'intero insieme di dati non è stato trasferito, un messaggio
Restarted può essere inviato in qualsiasi momento. Ciò significa che
i dati da verificare e il trasferimento saranno fatti ripartire. Il
client dovrebbe tornare nello stato waiting, e se un DataFound è
ricevuto a questo punto, il trasferimento di dati dovrà ricominciare
dall'inizio. Altrimenti, quando viene ricevuto il DataChunk finale,
la transazione è completa e la connessione muore.
(Client->Node)
ClientPut
HopsToLive=<numero: hops di vita>
URI=<stringa: URI pienamente specificata, come freenet:KSK@gpl.txt>
DataLength=<numero: numero di byte di metadati + dati>
[MetadataLength=<numero: default = 0, numero di byte di metadati>]
Data
<@DataLength numero di byte>
Se il client sta inserendo una CHK o una SVK, l'URI può essere abbreviato
come CHK@ o SVK@ . Nel primo caso il nodo calcolerà la CHK, mentre nel
secondo il nodo generera` una nuova coppia di chiavi. Il nodo deve avere
tutti i campi seguenti prima di poter inserire la chiave in Freenet. Il
nodo può rispondere con uno dei seguenti messaggi:
-
URIError : URL Freenet non valida. La transazione viene terminata.
-
Restareted : il client dovrebbe continuare ad aspettare.
-
RouteNotFound : la transazione viene terminata perché non è possibile trovare una rotta.
-
KeyCollision : la transazione viene terminata perchè in Freenet esiste già un documento con la stessa chiave. Questo messaggio contiene un campo URI con l'URI Freenet del documento.
-
SizeError : la transazione viene terminata perché i dati sono troppo grossi per il tipo di chiave; tutte le chiavi non CHK hanno un limite di 32 kB di dati.
Durante un inserimento si possono ricevere diversi messaggi Pending in risposta. Questi messaggi segnalano che i dati sono stati inseriti con successo, ma che l'inserimento non è completo, e il nodo non ha ancora ricevuto un messaggio StoreData :
Pending
URI=<stringa: URI pienamente specificato, come freenet:KSK@gpl.txt>
[PublicKey=<stringa: chiave pubblica>]
[PrivateKey=<stringa: chiave privata>]
EndMessage
Quando il nodo riceve un messaggio StoreData (e l'inserimento è dunque completo) viene restituito un messaggio Success contenente l'URI Freenet del nuovo documento ed eventualmente una coppia di chiavi privata/pubblica, se il documento inserito era un SVK. Si veda la sezione della generazione delle chiavi a questo proposito.
Success
URI=<stringa: URI pienamente specificato, come freenet:KSK@gpl.txt>
[PublicKey=<stringa: chiave pubblica>]
[PrivateKey=<string: chiave privata>]
EndMessage
Questi messaggi permettono ad un client di generare delle chiavi. Ciò non influisce in nessun modo su Freenet - i calcoli vengono generati al di fuori del nodo.
Le richieste di generazione delle chiavi vengono eseguite tramite un messaggio GenerateKey . Si possono generare sia una coppia di chiavi CHK che SVK:
GenerateCHK
DataLength=<numero: numero di byte di dati + metadati>
[MetadataLength=<numero: default = 0, numero di byte di metadati>]
Dati
<@DataLength numero di byte>
Il nodo calcola il CHK come se stesse effettuando un inserimento, ma invece lo invia come valore di ritorno. Ciò completa la transazione:
Success
URI=<stringa: URI pienamente specificato, come freenet:KSK@gpl.txt>
EndMessage
Il formato per generare le SVK è molto simile ma generare una coppia di chiavi (pubblica e privata) che sono indipendenti da qualsiasi dato. Generalmente questo viene fatto per impostare le SSK:
GenerateSVKPair
EndMessage
Il nodo genera una coppia di chiavi e invia come valore di ritorno:
Success
PublicKey=<stringa: chiave Freenet pubblica>
PrivateKey=<stringa: chiave privata Freenet>
EndMessage
PublicKey e PrivateKey vengono inviati come stringhe con codifica Freenet-base64. Queste chiavi possono essere usate per richiedere o inserire delle SSK:
(insert) freenet:SSK@<PrivateKey>/<nome>
(request) freenet:SSK@<PublicKey>/<nome>
|