//-----------------------------------------------------------------------------
// File:  pcap_writer.hh
// Date:  Sat Mar 22 12:12:08 PST 2003 
// Author: Martin Casado
//
// Description:
//
// Used for debugging ...
//
// ----------------------------------------------------------------------------
//
//    Copyright 2003. The Regents of the University of California.
//    All rights reserved.
//
//    This work was produced at the University of California, Lawrence Livermore
//    National Laboratory (UC LLNL) under contract no. W-7405-ENG-48 (Contract
//    48) between the U.S. Department of Energy (DOE) and The Regents of the
//    University of California (University) for the operation of UC LLNL.
//    Copyright is reserved to the University for purposes of controlled
//    dissemination, commercialization through formal licensing, or other
//    disposition under terms of Contract 48; DOE policies, regulations and
//    orders; and U.S. statutes. The rights of the Federal Government are
//    reserved under Contract 48 subject to the restrictions agreed upon by the
//    DOE and University as allowed under DOE Acquisition Letter 91-7.
//
//    DISCLAIMER
//    This software was prepared as an account of work sponsored by an
//    agency of the United States Government. Neither the United States
//    Government nor the University of California nor any of their employees,
//    makes any warranty, express or implied, or assumes any liability or
//    responsibility for the accuracy, completeness, or usefulness of any
//    information, apparatus, product, or process disclosed, or represents that
//    its use would not infringe protectedly-owned rights. Reference herein to any
//    specific commercial products, process, or service by trade name, trademark,
//    manufacturer, or otherwise, does not necessarily constitute or imply its
//    endorsement, recommendation, or favoring by the United States Government or
//    the University of California. The views and opinions of authors expressed
//    herein do not necessarily represent those of the United States
//    Government or the University of California, and shall not be used for
//    advertising or product endorsement purposes.
//
//-----------------------------------------------------------------------------

#ifndef PCAP_WRITER_HH
#define PCAP_WRITER_HH

// -- stl
#include <string>
#include <fstream>

extern "C"
{
#include <sys/time.h>
}

namespace pacman
{

//-----------------------------------------------------------------------------
struct pcap_writer
{
    protected:

        static const uint32_t DEFSNAPLEN = 1024;

        static const uint32_t PCAP_VERSION_MAJOR = 2;
        static const uint32_t PCAP_VERSION_MINOR = 4;
        static const uint32_t PCAP_ETHA_LEN = 6;
        static const uint32_t PCAP_PROTO_LEN = 2;

        static const uint32_t TCPDUMP_MAGIC = 0xa1b2c3d4;

        static const uint32_t LINKTYPE_ETHERNET = 1;

        // file header 
        struct pcap_file_header 
        {
            uint32_t   magic;         // magic number 
            uint16_t version_major;   // version number major 
            uint16_t version_minor;   // version number minor 
            int     thiszone;         // gmt to local correction 
            uint32_t   sigfigs;       // accuracy of timestamps 
            uint32_t   snaplen;       // max length saved portion of each pkt 
            uint32_t   linktype;      // data link type (LINKTYPE_*) 
        };

        // How a `pcap_pkthdr' is actually stored in the dumpfile.

        struct pcap_sf_pkthdr 
        {
            struct timeval ts;  // time stamp 
            uint32_t caplen;    // length of portion present 
            uint32_t len;       // length this packet (off wire) 
        };

        std::fstream thefile;
        unsigned int snaplen;

    public:

        pcap_writer(const std::string&, int thiszone, int snap = DEFSNAPLEN);
        bool operator ! () const;

        template <typename T>
        int write(const T&,int len = sizeof(T));

        void close();
        void flush();

}; // -- pcap_writer
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
inline
pcap_writer::pcap_writer(const std::string& file, int thiszone, int snap):
snaplen(snap)
{
    pcap_file_header hdr;

    hdr.magic = TCPDUMP_MAGIC;
    hdr.version_major = PCAP_VERSION_MAJOR;
    hdr.version_minor = PCAP_VERSION_MINOR;

    hdr.thiszone = thiszone;
    hdr.snaplen = snaplen;
    hdr.sigfigs = 0;
    hdr.linktype = LINKTYPE_ETHERNET;

    thefile.open(file.c_str(), std::ios::out);

    if(! thefile )
    { return; }

    thefile.write((char *)&hdr, sizeof(hdr));
} // -- pcap_writer
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
bool 
pcap_writer::operator ! () const
{
    return thefile.operator!();
}
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
template <typename T>
inline
int
pcap_writer::write(const T& in, int len)
{
    if( ! thefile )
    { return -1; }

    struct pcap_sf_pkthdr sf_hdr;

    ::gettimeofday(&sf_hdr.ts, 0);

    sf_hdr.caplen = len;
    sf_hdr.len    = (len < snaplen) ? len : snaplen;

    thefile.write((const char*)&sf_hdr, sizeof(sf_hdr));
    thefile.write((const char*)&in, sf_hdr.caplen);

    return len;
} // -- write
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
inline
void 
pcap_writer::flush()
{ 
    if( thefile )
    { thefile.flush(); }
}
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
inline
void 
pcap_writer::close()
{ 
    thefile.close(); 
}
//-----------------------------------------------------------------------------

} // -- namespace pacman

#endif  // -- PCAP_WRITER_HH
