Friday, September 26, 2008

constructor issues with http connection

Two posts ago I was talking about how I had to generate the content-length info before I opened the http connection in talkLock.  Actually, the issue was subtler than that, but does make sense :)

Before you feed your OutputStream to your connection object as an argument, you need to set all of your http header information (like content-length, content-type, &c).  This is because passing the stream to the object calls a constructor to run, and build your connection, including the headers.  Trying to assign values after the constructor runs doesn't do anything for the connection that has already been started.

To my surprise the Knudsen book didn't say anything about this!  I wonder if Jonathan knows but never got around to mentioning it in the book.  That's probably the case, he's really freaking smart.

Anyway, turns out that the last release of talkLock does POST, but the data that gets POSTed is zero bytes.  Haven't fixed that yet, and frankly, I'm scratching my noggin on this one.  My tcpdumps on the web server show the data, but it never makes it to http land.  Hruhh?  Dunno.

Also the copy of talk.php that I put on Sourceforge in the last release (talk.php is the server side script) is broken.  It doesn't work at all :(  It's probably safe to get everything from marmot.

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.