Thursday, September 4, 2008

base64 ascii armor and http POST works :)

Well, about a month ago I posted about starting to look at how the network part of talkLock would work. It isn't all finalized yet, but at the moment you can post audio data to marmot from your phone.

The biggest trick was "ascii armor"-ing the audio data, base64 encoding. Trying to send the raw audio data blew things up, because some of the characters in the audio data stream messed with things in http land. Mobile Java does not have any built-in support for base64 encoding or decoding.

First I found Roedy Green's excellent Base64 implementation, which was beautifully written and commented. I jammed it into talkLock and it built straight away. On reading Roedy's software license though, I couldn't decide if it was GPL-friendly or not. It was interesting to think about though, Roedy's software is free for non-military use. I think that that is great. However, part of the risk of the GPL is that software can be used by anyone for anything, as long as sources are provided. A conundrum.

So then I found Stephen Ostermiller's GPL Java Base64 implementation. Once I figured out how his library worked, I was able to incorporate it into talkLock, and it built. So now I had Base64 encoding and it was all GPL. Hooray!

After some testing, and getting stuff back from the encoding routine that looked like normal ASCII gibberish, I went about doing an http POST with the data. I tried setting the Content-Type to "multipart/form-data". But my php script on the web server never acknowledged it as a POST. I started sniffing on marmot and I could see the data come in, but apache never acknowledged a POST. Even though my MIDP code set the Content-Type, in my sniffs I could see that it was being ignored, either by the OS on my phone, or maybe even by Verizon's Squid servers. I tried adding the http header code before the content in the http stream, but Hartley grinned at my naivete, and explained that the headers were built in Java land, and I could not gin up my own fake ones.

Much testing and frustration, and help from my buddy Hartley. We switched to Content-Type text/plain. Added a submit button and tested with Camino on the Mac, which POSTed fine, but no joy from talkLock. Called it a night.

Finally I forced the client code to calculate the length of the data, and did a setConnectionRequest("Content-Length", Integer.toString(dataLength)). Then I pushed all writing to the connection to happen after setting the Content-Length, to avoid the obviously broken automatic Content-Length calculation stuff in Blackberry MIDP-land.

It freaking POSTs Base64-encoded audio data to marmot now :) And there was much rejoicing. Next is getting the audio back and making it play.

I will push out the build and sources, and source for the server side, to SourceForge today.

No comments: