The functionality of an ADU is similar to that of a Packet. It needs to pack user data into an array, which is then included in the user data area of an packet by an Agent (this is not supported by current Agents. User must derive new agents to accept user data from applications, or use an wrapper like TcpApp. We'll discuss this later).
Compared with Packet, ADU provides this functionality in a different way. In Packet, a common area is allocated for all packet headers; an offset is used to access different headers in this area. In ADU this is not applicable, because some ADU allocates their space dynamically according the the availability of user data. For example, if we want to deliver an OTcl script between applications, the size of the script is undetermined beforehand. Therefore, we choose a less efficient but more flexible method. Each ADU defines its own data members, and provides methods to serialize them (i.e., pack data into an array and extract them from an array). For example, in the abstract base class of all ADU, AppData, we have:
class AppData { private: AppDataType type\_; // ADU type public: struct hdr { AppDataType type\_; }; public: AppData(char* b) { assert(b != NULL); type\_ = ((hdr *)b)-\>type\_; } virtual void pack(char* buf) const; }
Here pack(char* buf) is used to write an AppData object into an array, and AppData(char* b) is used to build a new AppData from a ``serialized'' copy of the object in an array.
When deriving new ADU from the base class, users may add more data, but at the same time a new pack(char *b) and a new constructor should be provided to write and read those new data members from an array. For an example as how to derive from an ADU, look at /webcache/http-aux.h.