Further cleanup of the document
[obnox/wireshark/wip.git] / doc / README.request_response_tracking
index 031bb9f686b7df0de3f11ef06329bde051c42542..560a5ad661c3f30de490da157132cf05e7cb7fc3 100644 (file)
@@ -1,49 +1,50 @@
+$Id$
+
+1. Introduction
+
 It is often useful to enhance dissectors for request/response style protocols
 to match requests with responses.
-This allows you to display useful information in the decode tree
-such as which requests are matched to which response and the response time
-for individual transactions.
+This allows you to display useful information in the decode tree such as which
+requests are matched to which response and the response time for individual 
+transactions.
 
 This is also useful if you want to pass some data from the request onto the
 dissection of the actual response. The RPC dissector for example does
-something like this to pass the actual command opcode from the request
-onto the response dissector since the opcode itself is not part of the
-response packet  and without the opcode we would not know how to decode the
-data.
+something like this to pass the actual command opcode from the request onto 
+the response dissector since the opcode itself is not part of the response 
+packet and without the opcode we would not know how to decode the data.
 
 It is also useful when you need to track information on a per conversation 
 basis such as when some parameters are negotiated during a login phase of the 
-protocol and when these parameters affect how future commands on that
-session are to be decoded. The iSCSI dissector does something similar to that
-to track which sessions that HeaderDigest is activated for and which ones
-it is not.
-
-
+protocol and when these parameters affect how future commands on that session
+are to be decoded. The iSCSI dissector does something similar to that to track 
+which sessions that HeaderDigest is activated for and which ones it is not.
 
+2. Implementation
 
-The example below shows how simple this is to add to the dissector IF
-1, there is something like a transaction id in the header
-2, it is very unlikely that the transaction identifier is reused for the same conversation
+The example below shows how simple this is to add to the dissector IF:
+1. there is something like a transaction id in the header,
+2. it is very unlikely that the transaction identifier is reused for the 
+   same conversation.
 
-The example is taken from the PANA dissector :
+The example is taken from the PANA dissector:
 
-
-First we need to include the definitions for conversations and memory
-management
+First we need to include the definitions for conversations and memory 
+management.
 
        #include <epan/conversation.h>
        #include <epan/emem.h>
 
 Then we also need a few header fields to show the relations between request 
-and response as well as the response time
+and response as well as the response time.
 
        static int hf_pana_response_in = -1;
        static int hf_pana_response_to = -1;
        static int hf_pana_time = -1;
 
-We need a structure that holds all the information we need to remember
-between the request and the responses.
-One such structure will be allocated for each unique transaction.
+We need a structure that holds all the information we need to remember 
+between the request and the responses. One such structure will be allocated 
+for each unique transaction.
 In the example we only keep the frame numbers of the request and the response
 as well as the timestamp for the request.
 But since this structure is persistent and also a unique one is allocated for 
@@ -57,8 +58,9 @@ data you may want to keep track of from a request to a response.
        } pana_transaction_t;
 
 We also need a structure that holds persistent information for each 
-conversation. ( a conversation is identified by SRC/DST address, protocol and SRC/DST port)
-In this case we only want to have keep a binary tree to track the actual 
+conversation. A conversation is identified by SRC/DST address, protocol and 
+SRC/DST port, see README.developer.
+In this case we only want to have a binary tree to track the actual 
 transactions that occur for this unique conversation.
 Some protocols negotiate session parameters during a login phase and those
 parameters may affect how later commands on the same session is to be decoded,
@@ -69,10 +71,8 @@ around.
                emem_tree_t *pdus;
        } pana_conv_info_t;
 
-
-
-Finally for the meat of it,  add the conversation and tracking code to the 
-actual dissector
+Finally for the meat of it, add the conversation and tracking code to the 
+actual dissector.
 
        ...
        guint32 seq_num;
@@ -108,69 +108,68 @@ actual dissector
         */
        pana_info = conversation_get_proto_data(conversation, proto_pana);
        if (!pana_info) {
-               /* No.  Attach that information to the conversation, and add
+               /*
+                 * No.  Attach that information to the conversation, and add
                 * it to the list of information structures.
                 */
                pana_info = se_alloc(sizeof(pana_conv_info_t));
-               pana_info->pdus=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "pana_pdus");
+               pana_info->pdus = se_tree_create_non_persistent(
+                                       EMEM_TREE_TYPE_RED_BLACK, "pana_pdus");
 
                conversation_add_proto_data(conversation, proto_pana, pana_info);
        }
-       if(!pinfo->fd->flags.visited){
-               if(flags&PANA_FLAG_R){
+       if (!pinfo->fd->flags.visited) {
+               if (flags&PANA_FLAG_R) {
                        /* This is a request */
-                       pana_trans=se_alloc(sizeof(pana_transaction_t));
-                       pana_trans->req_frame=pinfo->fd->num;
-                       pana_trans->rep_frame=0;
-                       pana_trans->req_time=pinfo->fd->abs_ts;
+                       pana_trans = se_alloc(sizeof(pana_transaction_t));
+                       pana_trans->req_frame = pinfo->fd->num;
+                       pana_trans->rep_frame = 0;
+                       pana_trans->req_time = pinfo->fd->abs_ts;
                        se_tree_insert32(pana_info->pdus, seq_num, (void *)pana_trans);
                } else {
-                       pana_trans=se_tree_lookup32(pana_info->pdus, seq_num);
-                       if(pana_trans){
-                               pana_trans->rep_frame=pinfo->fd->num;
+                       pana_trans = se_tree_lookup32(pana_info->pdus, seq_num);
+                       if (pana_trans) {
+                               pana_trans->rep_frame = pinfo->fd->num;
                        }
                }
        } else {
-               pana_trans=se_tree_lookup32(pana_info->pdus, seq_num);
+               pana_trans = se_tree_lookup32(pana_info->pdus, seq_num);
        }
-       if(!pana_trans){
+       if (!pana_trans) {
                /* create a "fake" pana_trans structure */
-               pana_trans=ep_alloc(sizeof(pana_transaction_t));
-               pana_trans->req_frame=0;
-               pana_trans->rep_frame=0;
-               pana_trans->req_time=pinfo->fd->abs_ts;
+               pana_trans = ep_alloc(sizeof(pana_transaction_t));
+               pana_trans->req_frame = 0;
+               pana_trans->rep_frame = 0;
+               pana_trans->req_time = pinfo->fd->abs_ts;
        }
 
        /* print state tracking in the tree */
-       if(flags&PANA_FLAG_R){
+       if (flags&PANA_FLAG_R) {
                /* This is a request */
-               if(pana_trans->rep_frame){
+               if (pana_trans->rep_frame) {
                        proto_item *it;
 
-                       it=proto_tree_add_uint(pana_tree, hf_pana_response_in, tvb, 0, 0, pana_trans->rep_frame);
+                       it = proto_tree_add_uint(pana_tree, hf_pana_response_in,
+                                       tvb, 0, 0, pana_trans->rep_frame);
                        PROTO_ITEM_SET_GENERATED(it);
                }
        } else {
                /* This is a reply */
-               if(pana_trans->req_frame){
+               if (pana_trans->req_frame) {
                        proto_item *it;
                        nstime_t ns;
 
-                       it=proto_tree_add_uint(pana_tree, hf_pana_response_to, tvb, 0, 0, pana_trans->req_frame);
+                       it = proto_tree_add_uint(pana_tree, hf_pana_response_to,
+                                       tvb, 0, 0, pana_trans->req_frame);
                        PROTO_ITEM_SET_GENERATED(it);
 
                        nstime_delta(&ns, &pinfo->fd->abs_ts, &pana_trans->req_time);
-                       it=proto_tree_add_time(pana_tree, hf_pana_time, tvb, 0, 0, &ns);
+                       it = proto_tree_add_time(pana_tree, hf_pana_time, tvb, 0, 0, &ns);
                        PROTO_ITEM_SET_GENERATED(it);
                }
-       }              
-
-
-
-
-
+       }
 
-Then we just need to declare the hf fields we used
+Then we just need to declare the hf fields we used.
 
        { &hf_pana_response_in,
                { "Response In", "pana.response_in",