#ifndef STF370_PacketFilterDissector_h
#define STF370_PacketFilterDissector_h

#include <string>
 
using namespace std;

struct EthernetHeader {
  unsigned char destination[6];
  unsigned char source[6];
  unsigned short type;
};

struct IpHeader {
#if BYTE_ORDER == LITTLE_ENDIAN
  unsigned char headerLength:4,    // 4-bit header length (in 32-bit words)
    version:4;                     // 4-bit IPv4 version
#else
#if BYTE_ORDER == BIG_ENDIAN
  unsigned char version:4,         // 4-bit IPv4 version
    headerLength:4;                // 4-bit header length (in 32-bit words)
#endif
#endif
  unsigned char  tos;              // IP type of service
  unsigned short totalLength;      // Total length
  unsigned short id;               // Unique identifier 
    
  unsigned char  fragOffset   :5;  // Fragment offset field
    
  unsigned char  moreFragment :1;
  unsigned char  dontFragment :1;
  unsigned char  reservedZero :1;
    
  unsigned char  fragOffset1;      //fragment offset
    
  unsigned char  ttl;              // Time to live
  unsigned char  protocol;         // Protocol(TCP,UDP etc)
  unsigned short checksum;         // IP checksum
  unsigned char  srcAddr[4];       // Source address
  unsigned char  destAddr[4];      // Source address
};

struct UdpHeader
{
  unsigned short srcPort;         // Source port no.
  unsigned short destPort;        // Dest. port no.
  unsigned short length;          // UDP packet length
  unsigned short checksum;        // UDP checksum (optional)
};

struct TcpHeader 
{
  unsigned short srcPort;          // source port 
  unsigned short destPort;         // destination port 
  unsigned int   sequence;         // sequence number - 32 bits 
  unsigned int   acknowledge;      // acknowledgement number - 32 bits 
        
  unsigned char  ns   :1;          //Nonce Sum Flag Added in RFC 3540.
  unsigned char  reservedPart1:3;  //according to rfc
  unsigned char  dataOffset:4;     //number of dwords in the TCP header. 
    
  unsigned char  fin  :1;          //Finish Flag
  unsigned char  syn  :1;          //Synchronise Flag
  unsigned char  rst  :1;          //Reset Flag
  unsigned char  psh  :1;          //Push Flag 
  unsigned char  ack  :1;          //Acknowledgement Flag 
  unsigned char  urg  :1;          //Urgent Flag
    
  unsigned char  ecn  :1;          //ECN-Echo Flag
  unsigned char  cwr  :1;          //Congestion Window Reduced Flag
        
  unsigned short window;           // window 
  unsigned short checksum;         // checksum 
  unsigned short urgentPointer;    // urgent pointer 
};


#define ETH_TYPE_IP     8
#define IP_PROTO_TCP    6
#define IP_PROTO_UDP    17

enum HeaderId {
  e_NoHeader,
  e_Ethernet,
  e_Ip,
  e_Tcp,
  e_Udp
};

enum FieldId {
  e_NoField,
  e_Addr,
  e_Src,
  e_Dst,
  e_Port,
  e_SrcPort,
  e_DstPort,
  e_Proto
};

class PacketDissector {

 public:
  PacketDissector(const char* psPacket = "");
  virtual ~PacketDissector();
  bool Match(const HeaderId& header, const FieldId& sField, const string& sValue) const;

 private:
  EthernetHeader *m_ethHdr;
  IpHeader *m_ipHdr;
  UdpHeader *m_udpHdr;
  TcpHeader *m_tcpHdr;
  char *m_payload;
};

#endif
