Search code examples
javaactionscript-3blazedsamf

Unknown AMF type & other errors when transfering files from flash to java


I'm using a Flash tool to transfer data to Java. I'm having problems when it comes to sending multiple objects at once. The objects being sent are just generic Object objects, so it's not a case of needed to register a class alias or anything.

Sending one object works fine. Once I start sending multiple objects (putting the same Objects in an Array and sending that), it starts getting weird. Up to three objects in an Array seems to work fine. More than that I get different errors in the readObject() function, such as:

  • Unknown AMF type '47'
  • Unknown AMF type '40'
  • Unknown AMF type '20'
  • OutOfBoundsExceptions index 23, size 0
  • NullPointerException
  • etc.

Sending 3 objects will work, sending 4 gives me the error. If I delete one of the previous 3 that worked (while keeping the fourth that was added), it'll work again. Anyone know what's going on?

Some more info:

  • Communication goes through a Socket class on the Flash side. This is pure AS3, no flex.
  • Messages are compressed before being sent and decompressed on the server, so I'm pretty sure it's not a buffer size issue (unless I'm missing something)
  • BlazeDS version seems to be 4.0.0.14931 on the jar
  • Flash version is 10.1 (it's an AIR app)

Update with rough code

Examples of the objects being sent:

var o:Object    = { };
o._key          = this._key.toString();
o.someParam     = someString;
o.someParam2    = someInt;
o.someParam3    = [someString1, someString2, someString3];
...

It's added to our event object (which we use to determine the event to call, the data etc to pass). The event object is been registered as a class alias

That object is sent to the server through a Socket like so:

myByteArray.writeObject( eventObj );
myByteArray.compress();
mySocket.writeBytes( myByteArray );
mySocket.flush();

On the server side, we receive the bytes, and decompress them. We create a Amf3Input object and set the input stream, then read it:

Amf3Input amf3Input = new Amf3Input( mySerializationContext );
amf3Input.setInputStream( new ByteArrayInputStream( buffer ) ); // buffer is a byte[]
MyEventObj eventObj = (MyEventObj)amf3Input.readObject(); // MyEventObj is the server version of the client event object

If it's going to crash with an "unknown AMF type error", it does so immediately i.e. when we try to read the object, and not when it's trying to read a subobject.

In stepping through the read code, it seems when I pass an array of objects, if the length is <= 4, it reads the length right. If the length is bigger than that, it reads it's length as 4.


Solution

  • Ok, I figured out the problem. Basically messages are compressed before being sent and decompressed on the server. What I didn't see was that the byte[] buffer that the message was being decompressed to was always 1024 length, which was fine for small arrays of objects. Once that was passed however, it would overwrite the buffer (I'm not quite sure what happens in Java when you try to write more bytes than are available - whether it loops back around, or shifts the data).

    When it came to reading the amf object, the first thing it does it read an int, and uses this to determine what type of object it's trying to decode. As this int was gibberish (47, 110, -10), it was failing.

    Time to start prepending message lengths I think :)

    Thanks for the help.