Posted to devl@freenetproject.org on 20090722:

Experiences writing a plugin

I've been slowly working on writing a plugin for Freenet over the past couple weeks. (Details aren't particularly relevant to what follows; for the curious, it's a microblogging / chat application aiming at keeping latencies as low as possible. RFC available at USK@cF9ctaSzA8w2JAfEqmIlN49tfrPdz2Q5M68m1m5r9W0,NQiPGX7tNcaXVRXljGJnFlKhnf0eozNQsb~NwmBAJ4k,AQACAAE/Fritter-site/1/ )

Having not written much actual Freenet code before, I'm learning a lot about how Freenet works in the process — which is harder than it has any reason to be. Why? NOTHING IS DOCUMENTED. For example, after retrieving some text from Freenet, my plugin would like to display it on a web page, including filtering it so that it doesn't break anything, even in the case of malicious input. The method HTMLEncoder.encode() sounds like it ought to do that. Let's take a look at the Javadoc:

encode

public static java.lang.String encode(java.lang.String s)

That's it. Nothing about what the method is supposed to do. So, after hunting through several source files (when reading the Javadoc should have sufficed), I have a fairly good sense of what the method does. I'm pretty sure it doesn't do precisely what I'm looking for (though the HTML specs are complicated enough, and I don't know them well enough, that I'm not certain either way). Neither the Javadoc nor inline comments reference any standard that it is trying to conform to. If there was a contract specified, I could fairly easily determine whether that contract matched what I needed — and therefore whether I should be writing my own function or submitting a patch (or whether I'm misreading the relevant specs, for that matter).

If this were an isolated incident, it wouldn't matter much. It isn't. It is the norm for Freenet. For a platform whose primary impediment to wider adoption (IMO, of course) is a lack of things to do with it, rather than a lack of underlying functionality, this is a problem. I haven't tracked it, but I wouldn't be surprised if I've spent nearly as much time trying to figure out how the plugin API works (or even which classes it consists of) as I have actually writing code.

In case I haven't made my point yet, here are a few questions I've had. Can anyone point me to documentation that answers them (Javadoc or wiki)? I've spent some time looking, and I haven't found it. Most (but not all) I've answered for myself by reading lots of Freenet code — a vastly slower process. Some of them I believe represent bugs.

How do I make a request keep retrying forever?
How do I determine whether a ClientGetter represents an active request?
Are there any circumstances under which ClientGetCallback.onSuccess() will be called more than once, and do I need to handle them?
Why doesn't ClientGetCallback.onFetchable() get called (more than a trivial time) before onSuccess()?
How do I guarantee that an insert won't generate a redirect?
What, if anything, should I be doing with this "ObjectContainer container" that gets passed around everywhere?
Under what circumstances will I see a FetchException or InsertException thrown when using the HighLevelSimpleClient?
Why does the Hello World plugin break if I turn it into a FredPluginHTTP?

None of these seem like overly complex or unexpected questions for someone trying to write a plugin for Freenet. They should all be answerable by reading documentation.

On a closely related note, here are a few related issues — imho they need fixes in the code, but proper documentation of the actual behavior would have left me far less confused when debugging:

FreenetURI.setDocName(String) doesn't.
Creating a ClientSSK from a FreenetURI and then attempting to insert a file to it throws an exception about "wrong extra bytes" even though the extra bytes are unchanged from the FreenetURI the node generated for me.

At this point, I think I have a much better understanding of why Freenet has so little software that makes use of it, despite the fact that Freenet itself seems to work fairly well.