ezFCPlib
An Easy-to-use API for Freenet C/C++ Clients
Reference Manual
Contents
This document describes ezFCPlib, an API library for Freenet clients written in C or C++.
For Windows programmers, starting out with programming to Freenet can be daunting, to say the least. It certainly was for me. As a programmer who (due to a very welcome career change) hadn't coded for 7 years, I was very rusty. Worse, I had virtually no Windows API experience whatsoever.
I wish a library like this had been available when I'd started learning Freenet. It would have saved me countless frustrating hours.
Hopefully ezFCPlib will save you from suffering similar frustrations. Many programmers want to concentrate on user aspects of their programs - look-n-feel, interaction, features etc, without having to be dragged through the low-level entrails of the system they're coding to. It is especially for such programmers that this API is written.
I hope you find ezFCPlib to
be simple and intuitive, fast to learn and understand, yet robust and flexible.
Have fun.
Kind Regards
David McNab
david@rebirthing.co.nz
1. Required Headers
2. Establishment/Housekeeping Funtions
3. High-Level Freenet Key I/O Functions
4. In-Freenet Key Index Functions
5. Key Creation Functions
6. Low Level Key Streaming Functions
int fcpStartup(char
*host, int
port, int
defaultHtl, int
rawMode)
Brief
Starts up FCP interface, and handshakes with Freenet node.
Arguments
host - ASCII string containing an internet hostname. This can be a domain name, or IP address string such as "12.212.33.5". If this argument is NULL, the host defaults to the local machine.
port - port number on which Freenet is listening for FCP connections. Set this to zero to use the default FCP port number 8082.
defaultHtl - default value to set for Hops To Live. Normal settings for htl are between 10 and 100. For writing to Freenet, this determines how deeply a key is inserted into Freenet.
Lower values result in faster inserts, but inserted keys are less likely to be found by other nodes requesting them. High values can cause inserts to take up to an hour or more.
For reading from Freenet, this determines how deeply to search into Freenet for the required key. Shorter values result in faster requests, but have a higher risk of failure with finding keys, especially new or unpopular keys.
rawMode - by default, all incoming metadata is handled automatically, so that redirects are followed transparently.
Return Value
0 if successful, non-zero otherwise (see Error Codes)
Description
This function should be called by the application's main thread as soon as possible after calling the required WSAStartup() function (refer Windows API docs on sockets)
Brief
Creates an FCP 'handle', needed for subsequent FCP operations.
Arguments
None
Return Value
If successful, a pointer to an "FCP Handle", which is needed in all future operations on Freenet.
If failed, NULL is returned.
Description
An FCP handle is much like a FILE * pointer, used with fopen(), fprintf() etc. You need an FCP handle before you can do anything with Freenet.
This function must not be called unless the calling process has already successfully called fcpCreate(). If you don't abide by this, the results will be unpredictable and potentially dangerous to your system. Worse, such effects can prove very hard to debug.
Like FILE * handles, FCP handles can only operate on one Freenet key at a time. If you want to work with two or more keys at once, you will need to create that number of FCP handles.
However, after you've finished working with a Freenet key, you don't have to destroy this handle. You can simply use it again and again, only destroying it when you're really finished with it.
Note that these FCP handles are not necessarily intended to be created on a per-thread basis (although you're free to do this, and it may be the most convenient way for you). It's quite OK for a single thread to work with several handles, or even several threads to share the one handle (as long as they don't collide from simultaneously doing operations on that one handle).
void fcpDestroyHandle(HFCP
*hfcp)
Brief
Destroys an FCP handle that's no longer needed.
Arguments
hfcp - pointer to an existing FCP handle.
Returns
Nothing.
Description
Frees up all dynamically-allocated memory resources used within an FCP handle, and destroys the FCP handle itself. If hfcp does not point to a valid FCP handle, calling this function will have unpredictable and dangerous results.
void fcpSetHtl(HFCP
*hfcp, int htl)
Brief
Sets a different HTL value for an individual FCP handle.
Arguments
hfcp - pointer to an existing FCP handle.
htl - Hops To Live value to set for this handle
Returns
Nothing.
Description
When you called fcpStartup(), you chose a 'default HTL' value. This will set the HTL for all FCP handles you subsequently create.
But there may be times when you will want to set different HTL values for different FCP handles. That's what this function is for.
HTL values should ideally be between 10 and 100. If the value is too low, any Freenet operations will barely scratch the surface of Freenet, and are apt to fail. However, they are fast. On the other hand, Freenet operations with high HTL values take a long time to complete, perhaps several minutes to an hour or even several hours, but give much more reliable results.
void fcpRawMode(HFCP
*hfcp, int rawMode)
Brief
Enables or disables "raw mode" for a given FCP handle.
Arguments
hfcp - pointer to an existing FCP handle.
rawMode - 1 to set the handle into 'raw mode, 0 to disable raw mode.
Returns
Nothing
Description
When you called fcpStartup(), you may choose to set raw mode, which disables automatic metadata handling for all FCP handles you subsequently create.
But you may want to enable or disable auto metadata handling selectively for certain handles. That's what this function is for.
int
fcpGetKeyToMem(HFCP *hfcp,
char *key,
char **pData,
char **pMetadata)
Brief
Read a key and its metadata into memory
Arguments
hfcp - an FCP handle, previously created by calling fcpCreateHandle()
key - pointer to a char string containing a valid Freenet URI (eg 'freenet:KSK@AARDVARK')
pData - pointer to a pointer to the received key data (see example below). If this argument is NULL, then the key's data will be discarded
pMetadata - pointer to a pointer to the received key's metadata (again see example). If this argument is NULL, then the key's metadata will be discarded
Returns
Size of the key in bytes if the key was successfully read;
-1 if there was a failure (see error descriptions).
Description
Retrieving a key from Freenet has never been this easy! This function will request a key from Freenet, using the default HTL (see fcpStartup() ), or the FCP handle's own HTL (see fcpSetHtl()).
If the key can be retrieved, its entire contents and metadata will be written to memory, and locations of the data and metadata will be written to pData and pMetadata respectively.
Note that the pData and pMetadata are malloc()ed. To prevent memory leaks, you should free() them when you're finished with them.
It's quite acceptable to supply NULL pointers for both these arguments - this is a handy way to find out if a given key exists on Freenet.
As regards Freenet metadata - metadata commands like redirects, date-based redirects and file splits are handled automagically and transparently.
CAUTION - be careful with this function. Some Freenet keys can be up to a gigabyte or more in size. Using this function to retrieve such keys could have interesting effects on your system.
Example
#include <sys/types.h>
#include <winsock.h> #include "ezfcplib.h" int main(int argc, char *argv[]) { HFCP *hfcp; // FCP handle pointer char *data; // for Freenet key's data char *metadata; // for Freenet key's metadata // Start up FCP interface if (fcpStartup("localhost", 8082, 60) != 0) { printf("fcpStartup failed\n"); exit(1); } // Create an FCP handle if ((hfcp = fcpCreateHandle()) == NULL) { printf("Failed to create FCP handle\n"); return -1; } // Try to fetch a key if (fcpGetKeyToMem(hfcp, "KSK@AARDVARK", &data, &metadata) != 0) { printf("Failed to retrieve 'KSK@AARDVARK'\n"); fcpDestroyHandle(hfcp); exit(1); } // write key to stdout printf("Here is your key, Sir/Madam:\n"); puts(data); // Finished with FCP handle fcpDestroyHandle(hfcp); exit(0); } // 'main()'
fcpPutKeyFromMem(HFCP
*hfcp, char
*name, char
*data, char *metadata, char
**pUri)
Brief
Write a key and/or metadata from memory
Arguments
hfcp - an FCP handle, previously created by calling fcpCreateHandle()
name - URI to insert this key under. If NULL, then key is inserted as a CHK, whose name is returned in uri.
data - location of raw key data in memory. If NULL, then key is created with no data.
metadata - location in memory of key's metadata. If NULL, then key will be created with no metadata.
uri - location into which the created key's name will be written (see example). If NULL, then the key's URI will be forgotten.
Returns
0 if key was inserted successfully, non-zero if failed (see errors).
Description
This is a mindlessly easy way to create a Freenet key. Just create a key in memory, then call this function to insert it into Freenet.
Example
#include <sys/types.h>
#include <winsock.h> #include "ezfcplib.h" int main(int argc, char *argv[]) { HFCP *hfcp; char *data = "This is a freenet key"; char uri[128]; // this is big enough for Freenet URIs. // Start up FCP interface if (fcpStartup("localhost", 8082, 60) != 0) { printf("fcpStartup failed\n"); exit(1); } // Create an FCP handle if ((hfcp = fcpCreateHandle()) == NULL) { printf("Failed to create FCP handle\n"); return -1; } // Try to insert a key if (fcpPutKeyFromMem(hfcp, "KSK@my-own-key", data, uri) != 0) { printf("Failed to insert KSK@my-own-key'\n"); fcpDestroyHandle(hfcp); exit(1); } // write key's name to stdout printf("Key created successfully with URI '%s'\n", uri); // Finished with FCP handle fcpDestroyHandle(hfcp); exit(0); } // 'main()'
fcpGetKeyToFile(HFCP
*hfcp,
char *key, char *file,
char **pMetadata)
Brief
Read a key and saves it to a file.
Arguments
hfcp - an FCP handle, previously created by calling fcpCreateHandle()
key - pointer to a char string containing a valid Freenet URI (eg 'freenet:KSK@AARDVARK')
file - string - a full pathname of a file to which to write the key's data. Note - all directories in the path must already exist.
pMetadata - pointer to a pointer to the received key's metadata (again see example). If this argument is NULL, then the key's metadata will be discarded
Returns
0 if the key was successfully read; nonzero if there was a failure (see error descriptions).
Description
Retrieving a key from Freenet has never been this easy! This function will request a key from Freenet, using the default HTL (see fcpStartup() ), or the FCP handle's own HTL (see fcpSetHtl()).
If the key can be retrieved, its entire contents will be written, in binary form, to the file nominated by the caller, and the metadata will be written to memory, with the locations of this metadata being written to pMetadata.
Note that pMetadata is malloc()ed. To prevent memory leaks, you should free() it when you're finished with it.
As regards Freenet metadata - metadata commands like redirects, date-based redirects and file splits are handled automagically and transparently.
CAUTION - be careful with this function. Some Freenet keys can be up to a gigabyte or more in size. Unless you basically know what kind of key you are retrieving, make sure you've got plenty of free disk space.
Example
#include <sys/types.h>
#include <winsock.h> #include "ezfcplib.h" int main(int argc, char *argv[]) { HFCP *hfcp; // FCP handle pointer char *metadata; // for Freenet key's metadata // Start up FCP interface if (fcpStartup("localhost", 8082, 60) != 0) { printf("fcpStartup failed\n"); exit(1); } // Create an FCP handle if ((hfcp = fcpCreateHandle()) == NULL) { printf("Failed to create FCP handle\n"); return -1; } // Try to fetch a key if (fcpGetKeyToMem(hfcp, "KSK@AARDVARK", "C:\\aardvark.txt", &metadata) != 0) { printf("Failed to retrieve 'KSK@AARDVARK'\n"); fcpDestroyHandle(hfcp); exit(1); } // write key to stdout printf("Successfully retrieved key to c:\aardvark.html - metadata follows:\n"); puts(metadata); // Finished with FCP handle fcpDestroyHandle(hfcp); exit(0); } // 'main()'
fcpPutKeyFromFile(HFCP
*hfcp, char *name,
char *file, char *metadata,
char *uri)
Insert the contents of a file into Freenet
Brief
Insert the contents of a file into Freenet
Arguments
hfcp - an FCP handle, previously created by calling fcpCreateHandle()
name - URI to insert this key under. If NULL, then key is inserted as a CHK, whose name is returned in uri.
file - full pathname of a file to be inserted into Freenet. The syntax of this pathname must obey the requirements of the host operating system.
metadata - location in memory of key's metadata. If NULL, then key will be created with no metadata.
uri - location into which the created key's name will be written (see example). If NULL, then the key's URI will be forgotten.
Returns
0 if key was inserted successfully, non-zero if failed (see errors).
Description
This is another mindlessly easy way to create a Freenet key.
Just create a file, then call this function to insert it into Freenet.
Example
#include <sys/types.h>
#include <winsock.h> #include <stdio.h> #include "ezfcplib.h" int main(int argc, char *argv[]) { FILE *fp; HFCP *hfcp; char uri[128]; // this is big enough for Freenet URIs. char *filename = "c:\\myfile.txt"; // Start up FCP interface if (fcpStartup("localhost", 8082, 60) != 0) { printf("fcpStartup failed\n"); exit(1); } // Create an FCP handle if ((hfcp = fcpCreateHandle()) == NULL) { printf("Failed to create FCP handle\n"); return -1; } // Create a file if ((fp = fopen(filename, "wt")) == NULL) { printf("Failed to create file\n"); exit(1); } fprintf(fp, "This is the first line of the file\n"); fprintf(fp, "This is another line for the file\n"); fclose(fp); // Try to insert the file as a key if (fcpPutKeyFromMem(hfcp, "KSK@my-own-key", filename, uri) != 0) { printf("Failed to insert KSK@my-own-key'\n"); fcpDestroyHandle(hfcp); exit(1); } // write key's name to stdout printf("Key created successfully with URI '%s'\n", uri); // Finished with FCP handle fcpDestroyHandle(hfcp); exit(0); } // 'main()'
fcpOpenKeyIndex(HFCP
*hfcp, char *name, char
*date)
Brief
Open an in-freenet key index for reading
Arguments
hfcp - an FCP handle, previously created by calling fcpCreateHandle()
name - name of key index to open
date - date from which to read keys, in the format
Returns
0 if successful, non-zero otherwise (see errors)
Description
fcpReadKeyIndex(HFCP
*hfcp)
Read the next key from a previously opened key index
fcpWriteKeyIndex(HFCP
*hfcp, char *indexname, char
*data)
Write an entry to an in-Freenet key index
fcpMakeChkFromMem()
Create a CHK value from data in memory
fcpMakeChkFromFile()
Create a CHK value from data in a file
fcpMakeSvkKeypair()
Generate an SVK keypair
fcpOpenKey(HFCP
*hfcp, char *key, int
mode)
Brief
Open a key for reading or writing (like Unix open())
Arguments
hfcp - FCP 'handle', as previously created by calling fcpCreateHandle()
key - text string containing a Freenet URI for the key to open.
mode - flags indicating the modes under which the key is to be opened. These are:
_FCP_O_READ - open an existing Freenet key for reading
_FCP_O_WRITE - create a new Freenet key for writing
_FCP_O_RAW - disable automatic handling of metadata (enabled by default)
Returns
0 if the key was successfully opened
nonzero if an error occurred
Description
This layer of ezFCPlib provides a low-level streaming access to Freenet keys that strongly resembles the familiar Unix functions open()/close()/read()/write(). It is used by the higher-level ezFCPlib functions.
The mode flags should be OR-ed together. However, please note that it is illegal to combine the _FCP_O_READ and _FCP_O_WRITE flags in the same operation - read/write access is not a concept which exists in Freenet, and will result in this function returning an error.
fcpCloseKey(HFCP
*hfcp)
Close a previously open key (like Unix close())
fcpReadKey(HFCP
*hfcp, char *buf, int
count)
Brief
Reads an arbitrary number of bytes from a key (like Unix read())
Arguments
hfcp - an FCP handle, previously created by calling fcpCreateHandle()
buf - pointer to a buffer that's large enough to hold the requested number of bytes
count - number of bytes requested
Returns
Number of bytes actually read, or -1 if a problem occurred
Description
This function attempts to read an arbitrary number of bytes from a key which has been previously 'opened' via the fcpOpenKey() function.
fcpWriteKey()
Writes an arbitrary number of bytes to a key (like Unix write())
For most of these functions, the client program must supply a logging function called fcpLogCallback().
Since the user interface - whether scripts, console, socket, GUI etc - is under the control of the client, it's the client's responsibility to decide how to dispose of the various status and error messages that arise from calling ezFCPlib functions.
When the client program calls some of the ezFCPlib functions, some of these functions may make calls to fcpLogCallback().
The required definition of fcpLogCallback() is
int fcpLogCallback(int level, char *buf)
{ /* do something with text log message in buf */ }
The 'level' argument indicates the importance of the log message. This allows your application to 'screen' log messages according to importance (or desired user settings).
The logging levels are defined in ezFCPlib.h as:
#define FCP_LOG_SILENT 0 // don't log
#define FCP_LOG_CRITICAL 1 // critical messages, eg failures
#define FCP_LOG_NORMAL 2 // default log level - interesting progress messages
#define FCP_LOG_VERBOSE 3 // more detailed progress information
#define FCP_LOG_DEBUG 4 // voluminous commentary - for detailed debugging
For examples of this callback function, refer to the fcpget.c and fcpput.c source files
You should already have the source of this program with the library and header.