#ifndef IP_DISSECTOR_H
#define IP_DISSECTOR_H

#include "Dissector.h"
#include <map>
#include <list>
#include <string>

class IpDissector : public Dissector {

 public:
  IpDissector();
  virtual ~IpDissector();
  virtual IpDissector * Clone() const;
  virtual bool Dissect(const unsigned char * pData, const ssize_t nDataLen);
  virtual bool NeedReassembly() const;
  virtual bool Reassemble(Dissector * pDissector, ProtocolInfo * pProtocolInfo);
  virtual const EProtocolType GetUpperLayerType() const;

 private:
  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
  };

 private:
  IpHeader * m_ipHdr;

  // Reassembly
  std::list<std::pair<unsigned short, unsigned short> > m_holes;
  std::map<unsigned short, const unsigned char *> m_fragments;
  std::map<unsigned short, ssize_t> m_fragmentSizes;
 protected:
  ProtocolInfoElement * CreateLayerInfo();
};

#endif
