/*

Copyright (C) 2000 - 2006 Christian Kreibich <christian@whoop.org>.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies of the Software and its documentation and acknowledgment shall be
given in the documentation and software packages that this Software was
used.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

*/
#ifndef __libnd_packet_iterator_h
#define __libnd_packet_iterator_h

#include <libnd_types.h>
#include <libnd_packet.h>
#include <libnd_packet_iterator.h>
#include <libnd_tpm.h>
#include <libnd_tp.h>

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

typedef enum {

  /* Iterate over selected packets only, in read-only or
   * read-write mode.
   */
  LND_PACKET_IT_SEL_R,
  LND_PACKET_IT_SEL_RW,

  /* Iterate over all packets in currently loaded
   * trace part, read-only or read-write.
   */
  LND_PACKET_IT_PART_R,
  LND_PACKET_IT_PART_RW,
  
  /* Iterate over an area in the trace, starting at
   * currently loaded part and going arbitrarily far.
   * Comes in read-only and read-write flavours.
   */
  LND_PACKET_IT_AREA_R,
  LND_PACKET_IT_AREA_RW,

} LND_PacketIteratorMode;


/* Packet iterators can report their progress to observing entities
 * through a set of callbacks. The signatures of these callbacks are
 * defined below. See libnd_pit_add_observer().
 */
typedef struct lnd_pit_observer
{
  void  (*pit_init) (int num_total);
  void  (*pit_progress) (int num_progress);
  void  (*pit_clear) (void);

} LND_PacketIteratorObserver;


struct lnd_packet_iterator
{
  /* The trace whose packets are iterated. */
  LND_Trace             *trace;

  LND_PacketIteratorMode mode;
  
  /* Whether to skip filtered packets or not. */
  gboolean               skip_filtered;

  /* Whether to drop the current packet (i.e., not write it out)
   * in LND_PACKET_IT_AREA_RW mode.
   */
  gboolean               drop_current;
  
  /* The packet that's currently iterated. */
  LND_Packet            *current;

  LND_Packet             packet;

  /* End condition for LND_PACKET_IT_AREA_* -- we stop
   * once we reach the given part at the given offset.
   */
  off_t                  offset;

  /* After a trace area iteration, we need to jump back to the
   * original location if there was one. This check and the 
   * offset, if any, are stored here:
   */
  off_t                  offset_orig;

  LND_TraceLoc           stop_loc;
  gboolean               stopped;

  /* A counter for the number of packets we've iterated. */
  guint64                packet_count;

};


/* An iterator interface for iterating over a trace's packets,
   either all of them or only the selected ones. If apply-to-all
   is activated, iterating over all selected packets automatically
   equals iterating over all packets. */

/**
 * libnd_pit_init - packet iterator initializer
 * @pit: iterator to initialize.
 * @trace: trace whose packets are to be iterated.
 *
 * Initializes the packet iterator pointed to by @pit to
 * the iterator mode and possibly the trace area (if the
 * trace's iterator mode is one of the area iterator modes)
 * currently used by @trace.
 *
 * Returns: %TRUE when iterator initialization was
 * successful, %FALSE otherwise.
 */
gboolean            libnd_pit_init(LND_PacketIterator *pit,
				   LND_Trace *trace);

/**
 * libnd_pit_init_mode - initializes iterator using a given mode.
 * @pit: packet iterator to initialize.
 * @trace: the trace that will be iterated over.
 * @mode: the mode to use for iteration.
 *
 * The function prepares @pit to iterate over @trace using @mode.
 * If the mode is a trace area iterator, the trace's current
 * trace area is used.
 *
 * Returns: %TRUE when iterator initialization was
 * successful, %FALSE otherwise.
 */
gboolean            libnd_pit_init_mode(LND_PacketIterator *pit,
					LND_Trace *trace,
					LND_PacketIteratorMode mode);
					
/**
 * libnd_pit_cleanup - releases iterator state.
 * @pit: iterator to clean up.
 *
 * This function releases any state created by @pit. It does not free
 * @pit itself, as packet iterators are conveniently used from the function
 * call stack. You *must* call this function if you abort an iteration
 * prematurely, that is, if you don't just break out of a for-loop when
 * libnd_pit_get() returns %NULL. In this and only in this case is the
 * cleanup performed automatically.
 */
void                libnd_pit_cleanup(LND_PacketIterator *pit);

/**
 * libnd_pit_get - accessor function.
 * @pit: iterator to retrieve current packet from.
 *
 * Accessor function, returns the packet the iterator currently
 * points to. You do *not* need to clean up this packet.
 *
 * Returns: currently iterated packet.
 */
LND_Packet         *libnd_pit_get(LND_PacketIterator *pit);


/**
 * libnd_pit_next - advances the iterator.
 * @pit: iterator to advance
 *
 * This function advances the iterator, and returns that packet. If there are
 * no more packets, %NULL is returned. Upon advancing the iterator,
 * the progressbar and the packet's tcpdump line automatically
 * get updated.
 *
 * Returns: next packet.
 */
LND_Packet         *libnd_pit_next(LND_PacketIterator *pit);


/**
 * libnd_pit_get_count - get number of iterated packets.
 * @pit: iterator to get current count from.
 *
 * Returns: the number of packets iterated using @pit.
 */
guint64            libnd_pit_get_count(LND_PacketIterator *pit);


/**
 * libnd_pit_skip_filtered - enable/disable skipping of filtered packets.
 * @pit: iterator to adjust.
 * @skip_filtered: whether to skip or not.
 *
 * The function enables or disables skipping of filtered packets for
 * the given iterator. By default, filtered packets are skipped!
 */
void               libnd_pit_skip_filtered(LND_PacketIterator *pit, gboolean skip_filtered);


/**
 * libnd_pit_drop_current - don't write out current packet.
 * @pit: packet iterator.
 *
 * This function only makes sense in iteration mode LND_PACKET_IT_AREA_RW.
 * Calling it during iteration causes the current packet not to be written
 * out. This only applies to the current packet -- the corresponding flag
 * is reset in every iteration.
 */
void               libnd_pit_drop_current(LND_PacketIterator *pit);


/* ---------------------------- Iterator Observers ----------------------------- */


/**
 * libnd_pit_observer_new - creates new iterator observer.
 *
 * The function allocates a new, empty iterator observer. You should
 * then fill in callbacks for the events you're interested in,
 * and register it using libnd_pit_add_observer().
 *
 * Returns: new observer.
 */
LND_PacketIteratorObserver *libnd_pit_observer_new(void);

/**
 * libnd_pit_observer_free - deleted trace observer.
 * @ob: observer to delete.
 * 
 * The function releases all memory associated with @ob.
 */
void               libnd_pit_observer_free(LND_PacketIteratorObserver *ob);


/**
 * libnd_pit_add_observer - registers a new iterator observer.
 * @ob: new observer to register.
 *
 * The function registers the new observer for notifications about
 * future iterations.
 */
void               libnd_pit_add_observer(LND_PacketIteratorObserver *ob);

/**
 * libnd_pit_del_observer - deletes a iterator observer.
 * @ob: observer to drop.
 *
 * The function stops iterator operations from being reported to
 * @ob. It does not release @ob's memory, use libnd_pit_observer_free()
 * for that. 
 */
void               libnd_pit_del_observer(LND_PacketIteratorObserver *ob);

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif
