Posted to email@example.com 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:
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:
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.