gnash-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gnash-commit] gnash/libamf README


From: Rob Savoye
Subject: [Gnash-commit] gnash/libamf README
Date: Wed, 30 Apr 2008 13:32:16 +0000

CVSROOT:        /sources/gnash
Module name:    gnash
Changes by:     Rob Savoye <rsavoye>    08/04/30 13:32:16

Modified files:
        libamf         : README 

Log message:
        Rewritten README with actually useful info now.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/libamf/README?cvsroot=gnash&r1=1.3&r2=1.4

Patches:
Index: README
===================================================================
RCS file: /sources/gnash/gnash/libamf/README,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- README      16 Mar 2007 15:00:49 -0000      1.3
+++ README      30 Apr 2008 13:32:15 -0000      1.4
@@ -1,536 +1,145 @@
-This is currently my sum total documentation on the AMF format, and
-until I find some binary AMF data to test with, it'll be hard to know
-if I've got this initial reverse engineering project working
-correctly. 
-
-Anyone that gets the urge is welcome to split this library off from
-Gnash and make it be a standalone development reesource. There don't
-appear to be any GPL'd AMF tools out there that I could find non
-WinDoze systems.
-
-===========================================================
-
-All of this info came from OSFlash:
-http://osflash.org/amf
-
-
- AMF has core data types that are there every step of the way for
-serializing data. These should not be confused with the AMF
-actionscript data types. The core data types include:
-
-    * Byte
-    * Int
-    * MediumInt
-    * Long
-    * Double
-    * UTF8
-    * LongUTF8
-
-An AMF Byte is the simplest data type to read and write. It is simply
-an 8-bit byte.
-
-An AMF Int is made up of 2 consecutive bytes. It represents a 16-bit
-number. The first byte in the file/stream is the most significant bit
-and the second byte in the file/stream is the LSB. 
-
-An AMF MediumInt is made up of 3 consecutive bytes. It represents a
-24-bit number. The first byte in the file/stream is the most
-significant bit and the third byte in the file/stream is the
-LSB. MediumInt's appear to be used exclusively by FlashCom. 
-
-The AMF Long is made up of 4 consecutive bytes. It represents a 32-bit
-number. Like the Int and MediumInt, it is unsigned and the LSB is on
-the right. 
-
-The AMF Double is made up of 8 consecutive bytes. It represents a
-floating point, signed number. The double is little-endian encoded. In
-PHP a double can be read in the following way (this should also work
-for any language that has a pack function): 
-
-The AMF UTF8 represents a string shorter than 2^16 bytes. It is
-composed of an Int (2 bytes) representing string length followed by
-the UTF8-encoded string. 
-
-The AMF LongUTF8 represents a string potentially longer than 2^16
-bytes. It is composed of an LongInt (4 bytes) representing string
-length followed by the UTF8-encoded string. 
-
-
-Remoting envelope
-
-A Remoting request from the client consists of a short preamble,
-headers, and bodys. The preamble contains basic information about the
-nature of the request. Headers can be used to request debugging
-information, send authentication info, tag transactions, etc. Bodies
-contain actual Remoting requests and responses. A single Remoting
-envelope can contain several requests; Remoting supports batching out
-of the box. 
-
-Client headers and bodies need not be responded to in a one-to-one
-manner. That is, a body or header may not require a response. Debug
-information is requested by a header but sent back as a body
-object. The response index is essential for Flash player to understand
-the response therefore. 
-Preamble
-
-The first byte of the AMF file/stream is believed to be a version
-indicator. So far the only valid value for this field that has been
-found is 0×00. If it is anything other than 0×00 (zero), your
-system should consider the AMF file/stream to be
-'cmalformed'd. This can happen in the IDE if AMF calls are put
-on the stack but never executed and the user exits the movie from the
-IDE; the two top bytes will be random and the number of headers will
-be unreliable.
-
-The second byte of the AMF file/stream is appears to be 0×00 if the
-client is the Flash Player and 0×01 if the client is the FlashCom
-server. 
-
-The third and fourth bytes form an integer value that specifies the
-number of headers. 
-
-AMF Headers
-
-Each header consists of the following:
-
-    * UTF string (including length bytes) - name
-    * Boolean - specifies if understanding the header is `required'
-    * Long - Length in bytes of header
-    * Variable - Actual data (including a type code)
-
-AMF headers may be user-created. However, certain headers have certain
-meaning that a gateway should respond to. See predefined headers for
-more information. 
-AMF Bodies
-
-Between the headers and the start of the bodies is a int specifying
-the number of bodies. Each body consists of the following: 
-
-    * UTF String - Target
-    * UTF String - Response
-    * Long - Body length in bytes
-    * Variable - Actual data (including a type code)
-
-The target may be one of the following:
-
-    * An http or https URL. In that case the gateway should respond by
-sending a SOAP request to that URL with the specified data. In that
-case the data will be an array and the first key (data[0]) contains
-the parameters to be sent. 
-    * A string with at least one period (.). The value to the right of
-the right-most period is the method to be called. The value to the
-left of that is the service to be invoked including package name. In
-that case data will be an array of arguments to be sent to the
-method. 
-
-The response is a string that gives the body an id so it can be
-tracked by the player. 
-
-Body response
-
-The response to a request has the exact same structure as a request. A
-request requiring a body response should be answered in the following
-way: 
-
-    * Target: set to Response index plus one of "/onStatus",
-"onResult", or "/onDebugEvents". "/onStatus" is reserved for
-runtime errors. "/onResult" is for succesful calls. "/onDebugEvents"
-is for debug information, see debug information. Thus if the client
-requested something with response index 1/1', and the call was succesful,
-1/1/onResult' should be sent back. 
-    * Response: should be set to the string `null'.
-    * Data: set to the returned data.
-
-
-==========================================================
-http://www.vanrijkom.org/archives/2005/06/amf_format.html
-
-Flash AMF
-
-Used for:
-
-    * Local Connection
-    * SOL
-    * Remoting
-
-The folowing elements are defined within AMF. These are all based on
-their ActionScript equivalants.
-
-Type   Tagbyte
-
-Number 0x00;
-Boolean 0x01;
-String 0x02;
-Object 0x03;
-MovieClip 0x04;
-Null 0x05;
-Undefined 0x06;
-Reference 0x07;
-ECMAArray 0x08;
-ObjectEnd 0x09;
-StrictArray 0x0a;
-Date 0x0b;
-LongString 0x0c;
-Unsupported 0x0d;
-Recordset 0x0e;
-XMLObject 0x0f;
-TypedObject(Class) 0x10;
-
-
-For terminating sequences, a byte with value 0x09 is used.
-
-Number: 0x00 B7 B6 ’¡Ä B0
-
-Numbers in AMF are 64 bit ’¡ÆBig Endian’¡Ç. Windows works with little
-endians, so conversion is required. 
-
-Boolean: 0x01 B0 (BOOL)
-
-BOOL is 0 for FALSE and 1 for TRUE
-
-String: 0x02 L0 L1 SMBSTRING
-
-L1+L2 is Big Endian, length of the string. String is in multibyte
-format, prefixed with a 2 byte Big Endian length specifier. 
-
-Object: 0x03 [SMBSTRING AMFELEMENT ] 0x09
-
-An object contains zero or more AMF elements that are prefixed with a
-multibyte string that indicates the AMF elements identifyer within the
-object. 
-
-Undefined: 0x06
-
-An undefined element consists of soley one byte with the value 0x06.
-
-Reference (TODO): 0x07 ?
-
-A reference refers to an array or object that stored somewhere
-before. It’¡Çs probably a mechanism that prevents 
-
-Associative Array: 0x08 L3 L2 L1 L0 [SMBSTRING AMFELEMENT ] 0x09
-
-L0..L3 for a 32 bit number indicating the number of elements present
-in the array. The length of the array is followed by (length) AMF
-elements that are prefixed with a multibyte string (with a 2 byte
-length prefix) that indicates the AMF elements identifyer within the
-array. 
-
-Array: 0x0A L3 L2 L1 L0 [ AMFELEMENT ]
-
-L0..L3 form a 32 bit Big Endian number indicating the number of
-elements present in the array. The size of the array is followed by
-(length) AMF elements. Note that this collection is NOT terminated using 0x09. 
-
-Date: 0x0B T7 T6 .. T0 Z1 Z2
-
-T7 to T0 form a 64 bit Big Endian number that specifies the number
-of nanoseconds that have passed since 1/1/1970 0:00 to the
-specified time. This format is ’¡ÈUTC 1970’¡É. Z1 an Z0 for a 16 bit
-Big Endian number indicating the indicated time’¡Çs timezone. 
-
-SimpleObject: 0x0C ?
-
-To do %Gâ€“%@ meaning unknown.
-
-XML: 0x0F LMBSTRING
-
-The multi-byte string is prefixed with a 32 bit Big Endian number,
-indicating the length of the multibytestring that follows. 
-
-Class: 0x10 SMBSTRING [ SMBSTRING AMFELEMENT ] 0x09
-
-A class element is similar to an object element, but has a class
-name indentifyer string prefixed to the array of member elements. 
-
-*Element containers*
-
-Currently AMF is used with SharedObjectsLocal (.sol) files,
-Local Connection and Flash Remoting.
-
-
-  // S3 .. S0 forms a 32 bit Big Endian number indicating the size of
-  // the file. The small multibyte string reflects the name of the
-  // object shared in the file. The array that follows has pairs of
-  // name (SMBSTRING) lue pairs.
-  
-Reference tag
-16 big big-endian number follows the tag identifier 0x07.
- 
-------------------------------------
-http://sourceforge.net/docman/display_doc.php?docid=27130&group_id=131628
-
-Flashcoders Wiki - SharedObjectFile
-SharedObjectFile
-
-The format of the shared object files
-
- This script creates the described .sol file
-
- so = SharedObject.getLocal("test");
- so.data.myInt = 7;
- so.data.myFloat = Math.PIE;
- so.data.myString = 'ralle';
- so.data.myIntArray = [1,2,3];
- so.data.myStringArray = ['eins','zwei'];
- so.data.myObject1 = {p1: 5, p2: 6};
- so.data.myObject2 = {p3: 'hallo', p4: 8};
- so.data.myDate = new Date();
- so.data.myXML = new XML("<start><p>test</p><p>test2</p></start>");
- so.data.myBool = true;
- so.flush();
-
- ----
-
- header   00 BF
- len      00 00 01 04 //length of file starting at filetype
- filetype TCSO ...      00 04 00 00 00 00
-
- //myInt = 7;
- 00 05 myInt         00  40 1C 00 00 00 00 00 00  00
- len   name          typ floatval                        end
-
- //myFloat = Math.PI;
- 00 07 myFloat       00  40 09 21 FB 54 44 2D 18  00
- len   name          typ floatval                end
-
- //myString = "ralle";
- 00 08 myString      02  00 05  r  a  l  l  e    00
- len   name          typ lenstr str              end
-
- //myIntArray = [1,2,3];
- 00 0A myIntArray    08  00 00 00 03
- len   name          typ countidx
-
- 00 01  '0'  00  3F F0 00 00 00 00 00 00       !! no end here
- 00 01  '1'  00  40 00 00 00 00 00 00 00
- 00 01  '2'  00  40 08 00 00 00 00 00 00
- lenidx idx  typ floatval
-
- 00 00 09 00
- end of array
-
- //myStringArray = ["eins","zwei"];
- 00 0D myStringArray 08  00 00 00 02
- len   name          typ count
-
- 00 10  '0'  02  00 04  e  i  n  s
- 00 01  '1'  02  00 04  z  w  e  i
- lenidx idx  typ strlen string
-
- 00 00 09 00
- end of array
-
- //myObject1 = {p1: 5, p2: 6};
- 00 09  myObject1 03
- 00 02  p2  00  40 18 00 00 00 00 00 00        !!no end here
- 00 02  p1  00  40 14 00 00 00 00 00 00
- lenidx idx typ floatval
-
- 00 00 09 00
- end of array
-
- //myObject2 = {p3: "hallo", p4: 8};
- 00 09 myObject2 03
- 00 02  p4  00  40 20 00 00 00 00 00 00        00
- lenidx idx typ floatval                       end
- 00 20  p3  02  00 05  hallo
- lenidx idx typ strlen string
-
- 00 00 09 00
- end of array
-
-// AlexisIsaac
-
- It seems that the previous sample isn't exact there is no end byte on the 
first property:
- 00 09 myObject2 03
- 00 02  p4  00  40 20 00 00 00 00 00 00        00
- lenidx idx typ floatval                       end
- 00 20  p3  02  00 05  hallo
- lenidx idx typ strlen string
-
- 00 00 09 00
- end of array
-
- //myDate = new Date();
- 00 06 myDate 0B
- 42 6D DA E6 18 52 C0 00  FF 88 00
- floatval-getTime         timezone (mins -ve of GMT)
-                          FF88 = GMT +2 (-2 * 60)
-                          FDE4 = GMT +9 (-9 * 60)
-                          0000 = GMT
-                          01E0 = GMT -8 (8 * 60)
-
- //myXML = new XML("<start><p>test</p><p>test2</p></start>")
- 00 05 myXML 0F
- 00 00 00 26 <start><p>test</p><p>test2</p></start> 00
- length      xmlval                                 end
-
- //myBool = true;
- 00 06 myBool 01
- 01 00
-
-// bokel
-
-Here are all the data type ids I can find:
-
-      00 : number
-      01 : boolean
-      02 : string
-      03 : object Object
-      05 : null
-      06 : undefined
-      08 : object Array
-      0A : raw Array (amf only)
-      0B : object Date
-      0D : object String, Number, Boolean, TextFormat
-      0F : object XML
-      10 : object CustomClass
-
-Where CustomClass is a class registered with Object.registerClass
-
- // eg
-      My
-            this.x = 1;
-      }
-      Object.registerClass("classID",MyClass);
-      myObj = new MyClass();
-
-      00 05 m y o b j 10 00 07 c l a s s I D //len   name      typ      class 
identifier
-      00 01 x 00 3F F0 00 00 00 00 00 00 //props
-      00 00 09 00 //end
-
-// Peter Hall
-
-and here is a function to convert binary floats to a float
-
- function binaryFloatStringToFloat(bfs){
-       var c0 = ord(bfs.charAt(0));
-       var c1 = ord(bfs.charAt(1));
-
- //calculate sign
-       var sign = (c0 & (1 << 7)) ? -1 : 1; //negative if highest bit is set
-
- //calculate exponent
-       c0 &= 0x7f; //delete sign
-       var exp = (((c0 << 8) + c1) >> 4) - 1023;
-
- //calculate mantissa
-        var e = 4;
-       var sum = (c1 & 0x0f) / Math.pow(2, e); //delete upper four bits
-       var byteIdx = 2;
-       do {
-                e += 8;
-               var byte = ord(bfs.charAt(byteIdx));
-               sum += byte / Math.pow(2, e);
-       } while (++byteIdx < bfs.length);
-
- //trace(sum + " " + exp + " " + sign);
-       return (1 + sum) * Math.pow(2, exp) * sign;
- }
-
- //some tests
- s = String.fromCharCode(0x40,0x08,0,0,0,0,0,0); //3 //s = 
String.fromCharCode(0x40,0x1c,0,0,0,0,0,0); //7 //s = 
String.fromCharCode(0x40,0x0A,0x66,0x66,0x66,0x66,0x66,0x66); //3.3
- trace(binaryFloatStringToFloat(s));
-
-// bokel 
-
-
-This is the first RTMP message:
-
-(gdb) p buffer
-$10 = 
"address@hidden@\000\000\000\000\000\000\003\000\003app\002\000#software/gnash/tests/1153948634.flv\000\bflashVer\002\000\fLNX
 
6,0,82,0\000\006swfUrl\002\000\035file:///file|address@hidden://localhost/software/gnash/tests/1153948634.flv\000\000\t\002\000\005userx"...
-(gdb) p/x buffer
-$11 = {
- *0x3,* 0x0,  0x0,  0xf,  0x0,  0x0, *0xc9,*0x14, 0x00, 0x00, 0x00,  0x0,  
0x2,  0x0, 0x7,
-  0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00,  0x0,  
0x0,  0x0,
-  0x0,  0x0,  0x3,  0x0,  0x3,  0x61, 0x70, 0x70, 0x02, 0x00, 0x23, 0x73, 
0x6f, 0x66, 0x74,
-  0x77, 0x61, 0x72, 0x65, 0x2f, 0x67, 0x6e, 0x61, 0x73, 0x68, 0x2f, 0x74, 0x65,
-  0x73, 0x74, 0x73, 0x2f, 0x31, 0x31, 0x35, 0x33, 0x39, 0x34, 0x38, 0x36, 0x33,
-  0x34, 0x2e, 0x66, 0x6c, 0x76, 0x0,  0x8,  0x66, 0x6c, 0x61, 0x73, 0x68, 
0x56, 0x65,
-  0x72, 0x2,  0x0,  0xc,  0x4c, 0x4e, 0x58, 0x20, 0x36, 0x2c, 0x30, 0x2c, 
0x38, 0x32,
-  0x2c, 0x30, 0x0,  0x6,  0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, 
0x1d, 0x66,
-  0x69, 0x6c, 0x65, 0x3a, 0x2f, 0x2f, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x7c, 0x25,
-  0x32, 0x46, 0x74, 0x6d, 0x70, 0x25, 0x32, 0x46, 0x6f, 0x75, 0x74, 0x2e, 0x73,
-  0x77, 0x66,*0xc3*,0x0,  0x5,  0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 
0x34, 0x72,
-  0x74, 0x6d, 0x70, 0x3a, 0x2f, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
-  0x73, 0x74, 0x2f, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x2f, 0x67,
-  0x6e, 0x61, 0x73, 0x68, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2f, 0x31, 0x31,
-  0x35, 0x33, 0x39, 0x34, 0x38, 0x36, 0x33, 0x34, 0x2e, 0x66, 0x6c, 0x76, 0x0, 
0x0,
-  0x9,  0x2,  0x0,  0x5,  0x75, 0x73, 0x65, 0x72, 0x78...}
-
-
-"\003\000\000\017\000\000
-%Gï¿¿%@ \024\000\000\000\000\002\000
-\a
-connect\000
-?%G ï¿¿ %@ \000\000\000\000\000\000
-
-First byte:
-\003 = Object type
-\002 = String type
-\000 = Number type
-\008 = Video type
-\009 = Video type
-
-0x09 is also the terminating byte of and object definition
-All numbers are 64 bit big endian in AMF
-
-0xc9 0x14 0x0
-
-0x02 <--- string type
-0x00 0x07 connect
-0x00 <---- number type (64 bit big endian)
-0x3f 0xf0 0x00 0x00 0x00 0x00 0x00 0x00
-
-0x03  <--- object type
-0x00 0x03 app
-0x02 <--- string type
-0x00 0035 software/gnash/tests/1153948634.flv
-
-0x00 0x08 flashVer
-0x02 <--- string type
-0x00 0xf LNX 6,0,82,0
-
-0x00 0x06 swfUrl
-0x02 <--- string type
-0x00 0x00 35 file:///file|/%2Ftmp%2Fout.swf
-
-%G ï¿¿ %@
-0xc3 <---- header byte
-0x00 0x05 tcUrl
-0x02 <--- string type
-0x00 0x00 0x04 rtmp://localhost/software/gnash/tests/1153948634.flv
-
-0x00 0x00 0x09 <--- end of object definition
-
-0x02 0x00 0x05 userx
-
-
-//myInt = 7;
- 00 05 myInt         00  40 1C 00 00 00 00 00 00  00
- len   name          typ floatval                        end
-
- //myFloat = Math.PI;
- 00 07 myFloat       00  40 09 21 FB 54 44 2D 18  00
- len   name          typ floatval                end
-
- //myString = "ralle";
- 00 08 myString      02  00 05  r  a  l  l  e    00
- len   name          typ lenstr str              end
-
- //myIntArray = [1,2,3];
- 00 0A myIntArray    08  00 00 00 03
- len   name          typ countidx
-
- 00 01  '0'  00  3F F0 00 00 00 00 00 00       !! no end here
- 00 01  '1'  00  40 00 00 00 00 00 00 00
- 00 01  '2'  00  40 08 00 00 00 00 00 00
- lenidx idx  typ floatval
-
- 00 00 09 00
- end of array
-
-
-Good examples for SharedObj
-http://www.flash-communications.net/technotes/sharedObjectEditor/editor.html
+*** Please *** read this in it's entirety before making any changes to
+the code in this directory!
+===========================
+
+All of the information in this document has been figured out through
+reverse engineering, so it's entirely possible there are some minor
+misconceptions about concepts. These explanations are based on many
+months of staring at hex dumps of files, memory segments, and network
+traffic. Many thanks to the volunteers that use the proprietary player
+for allowing their data to be captured, and their disk drives
+examined.
+
+AMF is the lowest level representation of an SWF data type. Up until
+swf version 8, the format is refered to as AMF0, and is widely used on
+swf files for the SharedObject and LocalConnection ActionScript
+classes, as well as for remoting and RTMP based streaming.
+
+As of swf version 9, the a new version was created called AMF3, since
+it only works with the new ActionScript 3 classes. The main reason for
+this is performance. For example, AMF0 has only a single data type for
+numbers, which is a double (8 bytes). AMF3 introduced a new integer
+data type, which also supports a simplified packing scheme where if
+the first bit is set, the only 3 bytes, instead of the usual 4 for an
+integer is read.
+
+Currently the AMF implementation in Gnash only supports AMF0. Although
+there are bits of AMF3 implemented for the various constants used for
+handling AMF objects, none of the code is currently using it until we
+actually see some AMF3 based swf files out in the wild. Most of the
+time AMF0 is used by swf version 9 anyway, and uses s special data
+type to switch to AMF3 for that particular piece of data.
+
+Another big difference is that AMF3 has more optimizations, supporting
+a simple caching scheme where after an object has been sent, it can be
+referred to by an index number. Where AMF0 had multiple types for the
+various commonly used ActionScript classes, AMF3 instead as a single
+object type, which can be defined to be an existing or custom
+class. Other optimizations include removing the AMF0 Boolean data
+type, which was 3 bytes ling by a single byte which is either true or
+false.
+
+The usage of AMF has two main types of usage, one is a simple encoding
+of basic data types, like string and number. The other usage is used
+for the properties of ActionScript class objects. A basic AMF object
+has a 3 byte header field. The first byte is the type, followed by 2
+bytes to hold the length. A property uses the same format to hold 
+the data, but is preceeded by the name of the property, which is
+preceeded by two bytes that contsain the length of the name.
+
+As an AMF object doesn't do much but hold data, a header is used to
+signify the number of objects, file size, etc... The SharedObject and
+LocalConnection ActionScript classes have different headers, as
+SharedObjects store AMF objects in a disk based file, while
+LocalConnection stores AMF objects in a shared memory segment.
+
+The basic lowdown on the classes are as follows. The Buffer class is
+used to hold all data. We specifically don't use a std::vector because
+this class is so heavily used. We want to avoid memory fragmentation,
+which often happens when using classes from libstdc++. This class also
+has special methods for handling the data types we use, so this class
+would need to exist anyway. In it's simplest form, this is merely an
+array of unsigned bytes with a length.
+
+As a raw buffer is pretty useless for higher level processing, the
+Element class is used to represent an AMF object. After a buffer is
+read, it's data is extracted into a series of Elements. An Element
+still uses the Buffer class to hold the data, but often this is a much
+smaller buffer than the one used to read data. Most Elements are
+simply a numeric value or string, but Elements can also hold a higher
+level ActionScript class, including all of it's properties. The main
+internal difference is that the properties of an ActionScript class
+have a name, which is the name of the property, in addition to the
+data. Only an Element of the data type *OBJECT* can have properties.
+Properties of an object are stored as an array of more Elements, each
+one representing a single AMF data type. Note that when allocated, the
+memory in the Buffer points to is *not* memset() to 0. All Buffers are
+the exact size they need to be. Setting the memory to zero is nice for
+debugging in GBD, as you get nice clean hex dumps that way, but
+imagine the performance hit if every single time a Buffer is
+allocated, each bytes must be set to zero. If you want to set a
+Buffer's data to zero for debugging, use the Buffer::clear() method,
+and don't forget to remove it later so it doesn't become a subtle
+performance problem.
+
+The AMF class is used to encode and decode data between Buffers and
+Elements. When encoding, all the methods are static, as no data needs
+to be retained between usages of the data. Note that all the
+AMF::encode*() methods allocate a Buffer, which then later needs to be
+freed after usage. Once again, smart pointers, while useful are
+avoided because of the memory fragmentation issue for heavily used
+code. While this sort of defeats the purpose of both C++ and object
+oriented programming, that's life when working with high-performance,
+data-driven code. All decoding is handled by the non static
+AMF::extract*{} methods. These are not static as they must retain the
+current amount of data that has been parsed so subsequent decoding
+starts in the right place.
+
+The the only difference between the two higher level classes SOL and
+LcShm, are where the data is stored (disk or memory), and the
+appropriate headers for the data.
+
+LocalConnection, on unix based systems uses the older SYSV style
+shared memory segments. These are always the same size, 64528
+bytes. There are two sections in the shared memory segment. One I call
+"Listeners", not to be confused with ActionScript object Listeners,
+although the concept is similar. LocalConnection is used as a
+bi-directional way to transfer AMF objects between swf movies, instead
+of using a network connection. When a swf movie attachs to the
+LovalConnection shared memory segment, it registers itself by writing
+it's name into the Listener section. 
+
+This registration step turns out to be optional, as it is possible to
+send and receive data by polling for changes. This is of course a huge
+security problem, as it allows any client to secretly monitor or inject
+the communication between multiple swf files in an untraceable
+way. Some web sites, YouTube in particular, exploit this feature by
+never registering themselves as a Listener, so beware.
+
+
+-------
+Note to developers. Please be very careful making any changes to this
+code without seriously understanding how the code works. Byte
+manipulation is very easy to screw up, minor changes can often cause
+major problems. Anyone making changes here should run the libamf.all
+test cases to make sure they haven't introduced breakage.
+
+As a further note, valgrind gets confused with type casting sometimes,
+displaying errors where there are none. As all data is stored as
+unsigned bytes, to extract numeric values like the length often cause
+valgrind to assume there are errors with word alignment. Eliminating
+valgrind errors is a good thing though, so sometimes we have to jump
+through hoops to keep it quite. Often this requires playing silly
+games with local variables and multiple type casts. This makes the
+code a bit convoluted at times, but that's life if you want solid code.
+
+As this code does much allocation and deleting of memory blocks. After
+any changes make sure there are no memory leaks. This can be done with
+valgrind (eliminating the stupid valgrind errors makes it obvious).
+Optionally, the Memory class in libbase/gmemory.h contains supported
+for a valgrind like API that is under programmer control. Look at the
+test cases in libamf.all for usage examples. Memory::analyze() will do
+the same thing as valgrind to check to make sure all allocated memory
+is properly deleted when the program exits. To use the Memory class,
+you have to configure with --with-statistics=all or
+--with-statistics=mem.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]