101 HTTP implementations

Previous libpurple version suffers from poor HTTP implementation. Ordinary user won’t notice that, because plugins tries to fill the hole. However, when every single component that uses HTTP have to deal with the same issues, there must be some mess left.

Nearly a year ago, I’ve decided to put some effort here and implement new, flexible HTTP API. Now, I’ve came even deeper, replacing existing implementations with my new tool.

Replacing old HTTP API with the new one consisted of few stages. Firstly, I’ve replaced all purple_util_fetch_url occurrences with purple_http_get. That was the pretty easy step, because both functions does roughly the same thing: gets the URL and returns its contents. Then, it was the time for the tricky part: purple_util_fetch_url_request required building and parsing HTTP headers manually. Also, it leaves part of proxy handling on the caller in a weird way – he have to pass an full URL in request header, if proxy is on, or short (without hostname) otherwise.

Getting rid of purple_util_fetch_url* routines raised code quality pretty well, but the most difficult task was still undone. Some protocols had its own HTTP implementations – just imagine that amount of copy-paste. I’d like to share some examples:

  • oscar (ICQ, AIM) implemented it on it’s own to just perform simple GET request; the implementation was so horrible, that the author himself named the functions straight_to_hell, damn_you and struct pieceofcrap; fortunately, this code wasn’t used for a long time;
  • mxit: this could be implemented using old HTTP API, I have no idea, why author hadn’t done that;
  • msn: this one was somehow justified – there were no Keep-Alive connections in old API, so the author did it by himself to gain some performance; the bad thing is, he did it twice (for HTTP relays and SOAP handling);
  • xmpp also has two implementations, just not that obviously superfluous: the BOSH implementation was complex and still full of TODO’s; it took advantage of simple Keep-Alive request, but in really obfuscated way; rewriting of second implementation (out-of-band file transfers) was, by contrast, easy and pleasing task (especially, because I’ve done similar one within Gadu-Gadu protocol before);
  • yahoo protocol plugin was the record-holder with the value of four distinct HTTP implementations; I think, only in case of yahoo file transfers it wouldn’t be possible to do it using existing API.

There are still two remaining, but I’m not sure if I will refactor them at all. The first one is for Gadu-Gadu protocol – it’s included in libgadu library, so it’s not trivial to pull it out without violating its API. The second is for Novell GroupWise Instant Messenger – a closed service, available for companies. There are no public test servers, which I could try out. Also installation and configuration of its demo overwhelmed me (in fact, it’s buggy). I’m not sure if it’s worth the effort to do both cases above.

My next task will be Off-the-record plugin refinement and integration into the main tree.

Leave a Reply

Your email address will not be published. Required fields are marked *