/**
 * @file PCAPCapture.h
 * This header file defines the PCAPCapture class.
 * @author Tomas Urban
 * @version 0.2
 * @date 22/07/2009
 */
#ifndef PCAP_CAPTURE_H
#define PCAP_CAPTURE_H

#include "GenericCapture.h"
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>

#define HAVE_REMOTE
#include "pcap/pcap.h"

/**
 * This abstract class describes capturing based on the pcap library.
 */
class PCAPCapture :	public GenericCapture
{
private:
	static const int SNAP_LEN = 0x1000; 
	pcap_t ** m_fp; //array of pcap handles
	int m_nHandleCount;
	bool * m_threadRunning;
	static void DispatcherHandler(u_char * temp1, const struct pcap_pkthdr *header, const u_char *pkt_data);
	boost::mutex m_mutex;
	boost::condition m_threadClosed;
	bool m_bRunning;
	pcap_dumper_t ** m_dumpFiles;
	void CloseCaptureFile();	
	class CapturingThread
	{ 
	public:
		PCAPCapture * m_pCapture;
		int m_nHandleIndex;
		CapturingThread(PCAPCapture * pCapture, int nHandleIndex);
		void operator()();
	}; 
protected:
	PCAPCapture();	
	/**
	 * Saves supplied array of pcap sources for later use. This method is usually called
	 * by the #OpenDevice method of child classes.
	 * @param srcBuf Source array
	 * @param nLen Number of elements in the source array
	 */
	void SetPcapHandles(pcap_t ** srcBuf, int nLen);
	/**
	 * Helper method for opening a pcap data source
	 * @return Pointer to the pcap source or \c NULL if the operation is not successful.
	 */
	pcap_t * OpenPcapSource(const std::string sSource);
	/**
	 * Helper method for setting up data saving into a file. It is used by child classes
	 * that allow data saving into a file.
	 * @param sFile Path to the capture file
	 */
	bool InitCaptureFile(const std::string sFile);
public:
	virtual ~PCAPCapture(void);
	virtual ECaptureType GetCaptureType() { return ECaptureType_PCAP; }
	/**
	 * Sets a traffic filter. The filter must follow pcap library syntax for filtering expressions.
	 * @param sFilter Filtering data in pcap format
	 * @return \c true if the operation was successful, \c false otherwise (e.g. in case
	 * of invalid filter format)
	 */
	virtual bool SetFilter(const std::string sFilter);
	virtual void CloseDevice();
	virtual bool StartCapture();
	virtual bool StopCapture();
};

#endif
