static void dissect_APP_ACK(tvbuff_t *tvb,
  packet_info *pinfo,
  gint offset,
  guint8 flags,
  const guint encoding,
  int octets_to_next_header,
  proto_tree *tree,
  proto_item *item,
  endpoint_guid * guid)
  {
  /*
  * 0...2...........7...............15.............23...............31
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  * |   APP_ACK     |X|X|X|X|X|X|X|E|      octetsToNextHeader       |
  * +---------------+---------------+---------------+---------------+
  * | EntityId readerEntityId                                       |
  * +---------------+---------------+---------------+---------------+
  * | EntityId writerEntityId                                       |
  * +---------------+---------------+---------------+---------------+
  * + unsigned long virtualWriterCount                              +
  * +---------------+---------------+---------------+---------------+
  * | GuidPrefix  virtualWriterGuidPrefix                           |
  * +---------------+---------------+---------------+---------------+
  * EntityId virtualWriterObjectId
  * unsigned short intervalCount  | unsigned short bytesToNextVirtualWriter
  *
  * SequenceNumber intervalFirstSn
  * SequenceNumber intervalLastSn
  * unsigned short intervalFlags  | unsigned short payloadLength
  *
  * (after last interval) unsigned long virtualWriterEpoch
  *
  */
  gint original_offset; /* Offset to the readerEntityId */
  gint32 virtual_writer_count;
  guint32 wid;                  /* Writer EntityID */
  proto_item *octet_item;
  proto_tree_add_bitmask_value(tree, tvb, offset + 1, hf_rtps_sm_flags, ett_rtps_flags, APP_ACK_FLAGS, flags);

  octet_item = proto_tree_add_item(tree, hf_rtps_sm_octets_to_next_header, tvb,
      offset + 2, 2, encoding);

  if (octets_to_next_header < 56) {
    expert_add_info_format(pinfo, octet_item, &ei_rtps_sm_octets_to_next_header_error, "(Error: should be >= %u)", 56);
    return;
  }

  offset += 4;
  original_offset = offset;

  /* readerEntityId */
  rtps_util_add_entity_id(tree,
    tvb,
    offset,
    hf_rtps_sm_rdentity_id,
    hf_rtps_sm_rdentity_id_key,
    hf_rtps_sm_rdentity_id_kind,
    ett_rtps_rdentity,
    "readerEntityId",
    &wid);
  offset += 4;
  guid->entity_id = wid;
  rtps_util_topic_info_add_tree(tree, tvb, offset, guid);

  /* writerEntityId */
  rtps_util_add_entity_id(tree,
    tvb,
    offset,
    hf_rtps_sm_wrentity_id,
    hf_rtps_sm_wrentity_id_key,
    hf_rtps_sm_wrentity_id_kind,
    ett_rtps_wrentity,
    "writerEntityId",
    &wid);
  offset += 4;

  /* virtualWriterCount */
  proto_tree_add_item_ret_int(tree, hf_rtps_param_app_ack_virtual_writer_count, tvb, offset, 4, encoding, &virtual_writer_count);
  offset += 4;


  {
    /* Deserialize Virtual Writers */
    proto_tree *sil_tree_writer_list;

    gint32 current_writer_index;
    gint32 current_interval_count;
    /* guint16 interval_flags = 0; */
    /* guint32 current_virtual_guid_index = 0;*/

    /** Writer list **/
    sil_tree_writer_list = proto_tree_add_subtree_format(tree, tvb, offset, -1,
           ett_rtps_app_ack_virtual_writer_list, NULL, "Virtual Writer List");

    current_writer_index = 0;

    while (current_writer_index < virtual_writer_count) {
      proto_tree *sil_tree_writer;
      proto_tree *sil_tree_interval_list;
      gint32 interval_count;

      sil_tree_writer = proto_tree_add_subtree_format(sil_tree_writer_list, tvb, offset, -1,
           ett_rtps_app_ack_virtual_writer, NULL, "virtualWriter[%d]", current_writer_index);

      /* Virtual Writer Guid */
#if 0
      rtps_util_add_generic_guid(sil_tree_writer,
      tvb,
      offset,
      "virtualGUID",
      buffer,
      MAX_GUID_SIZE);
#endif
      offset += 16;


      /* Interval count */
      proto_tree_add_item_ret_int(sil_tree_writer, hf_rtps_param_app_ack_interval_count,
        tvb, offset, 2, encoding, &interval_count);
      offset += 2;

      /* bytes to next virtual writer */
      proto_tree_add_item(sil_tree_writer, hf_rtps_param_app_ack_octets_to_next_virtual_writer,
        tvb, offset, 2, encoding);
      offset += 2;

      /* Interval list */
      sil_tree_interval_list = proto_tree_add_subtree_format(sil_tree_writer, tvb, offset, -1,
           ett_rtps_app_ack_virtual_writer_interval_list, NULL, "Interval List");

      current_interval_count = 0;
      while (current_interval_count < interval_count) {
        proto_tree *sil_tree_interval;
        gint32 interval_payload_length;

        sil_tree_interval = proto_tree_add_subtree_format(sil_tree_interval_list, tvb, offset, -1,
           ett_rtps_app_ack_virtual_writer_interval, NULL, "Interval[%d]", current_interval_count);

        /* firstVirtualSN */
        rtps_util_add_seq_number(sil_tree_interval,
          tvb,
          offset,
          encoding,
          "firstVirtualSN");
        offset += 8;

        /* lastVirtualSN */
        rtps_util_add_seq_number(sil_tree_interval,
          tvb,
          offset,
          encoding,
          "lastVirtualSN");
        offset += 8;

        /* interval flags */
        proto_tree_add_item(sil_tree_interval, hf_rtps_param_app_ack_interval_flags,
          tvb, offset, 2, encoding);
        offset += 2;

        /* interval payload length */
        proto_tree_add_item_ret_int(sil_tree_interval, hf_rtps_param_app_ack_interval_payload_length,
          tvb, offset, 2, encoding, &interval_payload_length);
        offset += 2;

        if (interval_payload_length > 0) {
          proto_tree_add_item(sil_tree_interval, hf_rtps_serialized_data, tvb, offset,
                  interval_payload_length, ENC_NA);
          offset += ((interval_payload_length + 3) & 0xfffffffc);
        }

        ++current_interval_count;

      } /* interval list */

      /* Count */
      proto_tree_add_item(tree, hf_rtps_param_app_ack_count, tvb, offset, 4, encoding);
      offset += 4;

      current_writer_index++;

    } /* virtual_writer_count */
  }


  if (offset < original_offset + octets_to_next_header)
  {
    /* In this case there must be something wrong in the bitmap: there
    * are some extra bytes that we don't know how to decode
    */
    expert_add_info_format(pinfo, item, &ei_rtps_extra_bytes, "Don't know how to decode those extra bytes: %d", octets_to_next_header - offset);
  }
  else if (offset > original_offset + octets_to_next_header)
  {
    /* Decoding the bitmap went over the end of this submessage.
    * Enter an item in the protocol tree that spans over the entire
    * submessage.
    */
    expert_add_info(pinfo, item, &ei_rtps_missing_bytes);
  }
}
static void dissect_APP_ACK(tvbuff_t *tvb,
  packet_info *pinfo,
  gint offset,
  guint8 flags,
  const guint encoding,
  int octets_to_next_header,
  proto_tree *tree,
  proto_item *item,
  endpoint_guid * guid)
  {
   
  gint original_offset;  
  gint32 virtual_writer_count;
  guint32 wid;                   
  proto_item *octet_item;
  proto_tree_add_bitmask_value(tree, tvb, offset + 1, hf_rtps_sm_flags, ett_rtps_flags, APP_ACK_FLAGS, flags);

  octet_item = proto_tree_add_item(tree, hf_rtps_sm_octets_to_next_header, tvb,
      offset + 2, 2, encoding);

  if (octets_to_next_header < 56) {
    expert_add_info_format(pinfo, octet_item, &ei_rtps_sm_octets_to_next_header_error, "(Error: should be >= %u)", 56);
    return;
  }

  offset += 4;
  original_offset = offset;

   
  rtps_util_add_entity_id(tree,
    tvb,
    offset,
    hf_rtps_sm_rdentity_id,
    hf_rtps_sm_rdentity_id_key,
    hf_rtps_sm_rdentity_id_kind,
    ett_rtps_rdentity,
    "readerEntityId",
    &wid);
  offset += 4;
  guid->entity_id = wid;
  rtps_util_topic_info_add_tree(tree, tvb, offset, guid);

   
  rtps_util_add_entity_id(tree,
    tvb,
    offset,
    hf_rtps_sm_wrentity_id,
    hf_rtps_sm_wrentity_id_key,
    hf_rtps_sm_wrentity_id_kind,
    ett_rtps_wrentity,
    "writerEntityId",
    &wid);
  offset += 4;

   
  proto_tree_add_item_ret_int(tree, hf_rtps_param_app_ack_virtual_writer_count, tvb, offset, 4, encoding, &virtual_writer_count);
  offset += 4;


  {
     
    proto_tree *sil_tree_writer_list;

    gint32 current_writer_index;
    gint32 current_interval_count;
     
     

     
    sil_tree_writer_list = proto_tree_add_subtree_format(tree, tvb, offset, -1,
           ett_rtps_app_ack_virtual_writer_list, NULL, "Virtual Writer List");

    current_writer_index = 0;

    while (current_writer_index < virtual_writer_count) {
      proto_tree *sil_tree_writer;
      proto_tree *sil_tree_interval_list;
      gint32 interval_count;

      sil_tree_writer = proto_tree_add_subtree_format(sil_tree_writer_list, tvb, offset, -1,
           ett_rtps_app_ack_virtual_writer, NULL, "virtualWriter[%d]", current_writer_index);

       
#if 0
      rtps_util_add_generic_guid(sil_tree_writer,
      tvb,
      offset,
      "virtualGUID",
      buffer,
      MAX_GUID_SIZE);
#endif
      offset += 16;


       
      proto_tree_add_item_ret_int(sil_tree_writer, hf_rtps_param_app_ack_interval_count,
        tvb, offset, 2, encoding, &interval_count);
      offset += 2;

       
      proto_tree_add_item(sil_tree_writer, hf_rtps_param_app_ack_octets_to_next_virtual_writer,
        tvb, offset, 2, encoding);
      offset += 2;

       
      sil_tree_interval_list = proto_tree_add_subtree_format(sil_tree_writer, tvb, offset, -1,
           ett_rtps_app_ack_virtual_writer_interval_list, NULL, "Interval List");

      current_interval_count = 0;
      while (current_interval_count < interval_count) {
        proto_tree *sil_tree_interval;
        gint32 interval_payload_length;

        sil_tree_interval = proto_tree_add_subtree_format(sil_tree_interval_list, tvb, offset, -1,
           ett_rtps_app_ack_virtual_writer_interval, NULL, "Interval[%d]", current_interval_count);

         
        rtps_util_add_seq_number(sil_tree_interval,
          tvb,
          offset,
          encoding,
          "firstVirtualSN");
        offset += 8;

         
        rtps_util_add_seq_number(sil_tree_interval,
          tvb,
          offset,
          encoding,
          "lastVirtualSN");
        offset += 8;

         
        proto_tree_add_item(sil_tree_interval, hf_rtps_param_app_ack_interval_flags,
          tvb, offset, 2, encoding);
        offset += 2;

         
        proto_tree_add_item_ret_int(sil_tree_interval, hf_rtps_param_app_ack_interval_payload_length,
          tvb, offset, 2, encoding, &interval_payload_length);
        offset += 2;

        if (interval_payload_length > 0) {
          proto_tree_add_item(sil_tree_interval, hf_rtps_serialized_data, tvb, offset,
                  interval_payload_length, ENC_NA);
          offset += ((interval_payload_length + 3) & 0xfffffffc);
        }

        ++current_interval_count;

      }  

       
      proto_tree_add_item(tree, hf_rtps_param_app_ack_count, tvb, offset, 4, encoding);
      offset += 4;

      current_writer_index++;

    }  
  }


  if (offset < original_offset + octets_to_next_header)
  {
     
    expert_add_info_format(pinfo, item, &ei_rtps_extra_bytes, "Don't know how to decode those extra bytes: %d", octets_to_next_header - offset);
  }
  else if (offset > original_offset + octets_to_next_header)
  {
     
    expert_add_info(pinfo, item, &ei_rtps_missing_bytes);
  }
}