[SabreAMF] String references serializing AMF3

Jim Mischel jim at mischel.com
Tue Nov 14 15:32:06 EST 2006


Actually, I don't think this is a problem.  The "references" in AMF are 
really just a simple compression method that prevents you from including 
the same text string multiple times in an AMF message.  For example, 
consider an object (this isn't valid PHP or ActionScript--just pseudo-code):

object
    var id = 2;
    var command = "connect";
    var payload1 = "this is a test";
    var payload2 = "this is a test";
    var payload3 = "this is a test";
    var payload4 = "this is a test";
    var payload5 = "this is a test";
    var payload6 = "this is a test";
end object

The naive way of transmitting this object is to send the string "this is 
a test" six times:  once for each field.  But if you construct this 
object in Flash and look at the generated AMF, you'll see that it only 
sends the string one time and passes a reference (just a string index) 
for the other five occurrences:

0000: 0A 0B 01 0F 63 6F 6D 6D - 61 6E 64 06 0F 63 6F 6E  ....command..con
0010: 6E 65 63 74 11 70 61 79 - 6C 6F 61 64 33 06 1D 74  nect.payload3..t
0020: 68 69 73 20 69 73 20 61 - 20 74 65 73 74 11 70 61  his.is.a.test.pa
0030: 79 6C 6F 61 64 34 06 06 - 05 69 64 04 02 11 70 61  yload4...id...pa
0040: 79 6C 6F 61 64 36 06 06 - 11 70 61 79 6C 6F 61 64  yload6...payload
0050: 32 06 06 11 70 61 79 6C - 6F 61 64 35 06 06 11 70  2...payload5...p
0060: 61 79 6C 6F 61 64 31 06 - 06 01                    ayload1.........

This "reference" isn't saying that one varible is a reference to the 
other, but rather that one variable's value is identical to the other.  
This deserializes in PHP to what you would expect, and changing the 
value of payload1 won't change the value of payload2 or any of the others.

When Flash deserializes this, it does the same thing:  it assigns the 
value "this is a test" to each of the individual strings, but doesn't 
make them refer to each other.

It turns out that modifying writeString() (in 
SabreAMF/AMF3/Serializer.php) was pretty easy.  I've not tested it fully 
yet, but this appears to work:

        /**
         * writeString
         *
         * @param string $str
         * @return void
         */
        public function writeString($str) {

            // Check for this string in the storedStrings array.
            $key = NULL;
            for ($i = 0; $i < sizeof($this->storedStrings); $i++)
            {
                if ($str === $this->storedStrings[$i])
                {
                    $key = $i;
                    break;
                }
            }
            if (is_null($key))
            {
                // string not stored.  Store it and send as a literal.
                $strref = strlen($str) << 1 | 0x01;
                $this->writeInt($strref);
                // Add to the storedStrings array and write.
                // But don't add empty strings or bother to write them.
                if ($str != "")
                {
                    $this->storedStrings[] = $str;
                    $this->stream->writeBuffer($str);
                    //printf("String %d = %s\n", 
sizeof($this->storedStrings)-1, $str);
                }
            }
            else
            {
                // the string already exists.  Store the key.
                //printf("String reference %d\n", $key);
                $strref = ($key << 1);
                $this->writeInt($strref);
            }
        }

That assumes, of course, that you've defined this array in the 
SabreAMF_AMF3_Serializer class:

        /**
         * storedStrings
         *
         * @var array
         */
        private $storedStrings = array();

Jim


Evert | Rooftop wrote:

>Update: there doesn't seem to be a way to check if 2 scalar variables 
>reference the same data. So I would say, don't implement this.. Could be 
>a really bad idea.
>
>For objects it is possible (and should probably be done), because you 
>can do a simple == check.
>
>I'll implement that one of these days.. Along with the fixes you 
>provided I'll put out a 0.5..
>
>To the other people on this list: if you got a feature request, be sure 
>to let me know.. I'll create a roadmap for 1.0 soon, so people know what 
>they can expect.
>
>Evert
>
>Evert | Rooftop wrote:
>  
>
>>There's one big problem with this..
>>
>>You have to check if 2 strings are actually references to each other.. 
>>If this is not the case, unexpected things might happen. If you do a 
>>simple check if 2 strings contain the same data, the data will end up in 
>>flex as references to each other..
>>
>>If you would then change 'stringA', 'stringB' automatically gets 
>>changed. I've never really needed to check if 2 variables are 
>>referencingo the same thing in PHP, but I also could not find it in 
>>the manual..
>>
>>I'm going to see if I can get a bit more info on this.
>>
>>Evert
>>
>>Evert | Rooftop wrote:
>>  
>>    
>>
>>>If your up for it, i'd happily accept a patch! I can also give you write 
>>>access to subversion if you'd like to..
>>>
>>>Jim Mischel wrote:
>>>  
>>>    
>>>      
>>>
>>>>SabreAMF currently does not cache strings and create references when 
>>>>serializing AMF3.  The writeString() function in 
>>>>SabreAMF/AMF3/Serializer.php always writes the literal string.  It 
>>>>doesn't look terribly difficult to cache the strings so that 
>>>>writeString() can create references if needed.  Has anybody done this?  
>>>>If so, I'd like to see the code.  If not, I'll code it up.
>>>>
>>>>Jim
>>>>
>>>>
>>>>
>>>>_______________________________________________
>>>>sabreamf mailing list
>>>>sabreamf at osflash.org
>>>>http://osflash.org/mailman/listinfo/sabreamf_osflash.org
>>>>  
>>>>    
>>>>      
>>>>        
>>>>
>>>_______________________________________________
>>>sabreamf mailing list
>>>sabreamf at osflash.org
>>>http://osflash.org/mailman/listinfo/sabreamf_osflash.org
>>>  
>>>    
>>>      
>>>
>>_______________________________________________
>>sabreamf mailing list
>>sabreamf at osflash.org
>>http://osflash.org/mailman/listinfo/sabreamf_osflash.org
>>  
>>    
>>
>
>
>_______________________________________________
>sabreamf mailing list
>sabreamf at osflash.org
>http://osflash.org/mailman/listinfo/sabreamf_osflash.org
>
>
>  
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://osflash.org/pipermail/sabreamf_osflash.org/attachments/20061114/31f8185e/attachment-0001.htm


More information about the sabreamf mailing list