//===========================================================================
//  $Name: cflowd-2-1-b1 $
//  $Id: CflowdNetMatrixKey.hh,v 1.10 1999/02/07 18:16:39 dwm Exp $
//===========================================================================
//  CAIDA Copyright Notice
//
//  By accessing this software, cflowd++, you are duly informed
//  of and agree to be bound by the conditions described below in this
//  notice:
//
//  This software product, cflowd++, is developed by Daniel W. McRobb, and
//  copyrighted(C) 1998 by the University of California, San Diego
//  (UCSD), with all rights reserved.  UCSD administers the CAIDA grant,
//  NCR-9711092, under which part of this code was developed.
//
//  There is no charge for cflowd++ software. You can redistribute it
//  and/or modify it under the terms of the GNU General Public License,
//  v.  2 dated June 1991 which is incorporated by reference herein.
//  cflowd++ is distributed WITHOUT ANY WARRANTY, IMPLIED OR EXPRESS, OF
//  MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE or that the use
//  of it will not infringe on any third party's intellectual property
//  rights.
//
//  You should have received a copy of the GNU GPL along with cflowd++.
//  Copies can also be obtained from:
//
//    http://www.gnu.org/copyleft/gpl.html
//
//  or by writing to:
//
//    University of California, San Diego
//
//    SDSC/CAIDA
//    9500 Gilman Dr., MS-0505
//    La Jolla, CA 92093 - 0505  USA
//
//  Or contact:
//
//    info@caida.org
//===========================================================================

#ifndef _CFLOWDNETMATRIXKEY_HH_
#define _CFLOWDNETMATRIXKEY_HH_

extern "C" {
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <errno.h>
#include <syslog.h>
  
#include "caida_t.h"
}

#include <map>

#include "ArtsPrimitive.hh"

extern ArtsPrimitive g_CfdArtsPrimitive;

//---------------------------------------------------------------------------
//  class CflowdNetMatrixKey
//---------------------------------------------------------------------------
//  This class is used as a key into an network matrix map in cflowd++.
//  The key is comprised of a source and destination network.
//
//  Note how I've inlined all this; we don't want member function call
//  overhead in here because this class' members will be called
//  frequently when it's used as a key in an STL <map>.
//---------------------------------------------------------------------------
class CflowdNetMatrixKey
{
public:
  //-------------------------------------------------------------------------
  //                       inline ipv4addr_t Src() const                       
  //.........................................................................
  //  Returns the source network in the key.
  //-------------------------------------------------------------------------
  inline const ipv4addr_t & Src() const
  {
    return(this->_src);
  }
  
  //-------------------------------------------------------------------------
  //                  inline ipv4addr_t Src(ipv4addr_t src)                    
  //.........................................................................
  //  Sets the source network in the key and returns it.
  //-------------------------------------------------------------------------
  inline ipv4addr_t Src(ipv4addr_t src)
  {
    this->_src = src;
    return(this->_src);
  }
  
  //-------------------------------------------------------------------------
  //                       inline ipv4addr_t Dst() const                       
  //.........................................................................
  //  Returns the destination network in the key.
  //-------------------------------------------------------------------------
  inline const ipv4addr_t & Dst() const
  {
    return(this->_dst);
  }
  
  //-------------------------------------------------------------------------
  //                  inline ipv4addr_t Dst(ipv4addr_t dst)                    
  //.........................................................................
  //  Sets and then returns the destination network in the key.
  //-------------------------------------------------------------------------
  inline ipv4addr_t Dst(ipv4addr_t dst)
  {
    this->_dst = dst;
    return(this->_dst);
  }

  //-------------------------------------------------------------------------
  //                    inline uint8_t SrcMaskLen() const                    
  //.........................................................................
  //  Returns the source network mask length in the key.
  //-------------------------------------------------------------------------
  inline const uint8_t & SrcMaskLen() const
  {
    return(this->_srcMaskLen);
  }
  
  //-------------------------------------------------------------------------
  //              inline uint8_t SrcMaskLen(uint8_t srcMaskLen)              
  //.........................................................................
  //  Sets and returns the source network mask length in the key.
  //-------------------------------------------------------------------------
  inline uint8_t SrcMaskLen(uint8_t srcMaskLen)
  {
    this->_srcMaskLen = srcMaskLen;
    return(this->_srcMaskLen);
  }
  
  //-------------------------------------------------------------------------
  //                    inline uint8_t DstMaskLen() const                    
  //.........................................................................
  //  Returns the destination network mask length in the key.
  //-------------------------------------------------------------------------
  inline const uint8_t & DstMaskLen() const
  {
    return(this->_dstMaskLen);
  }
  
  //-------------------------------------------------------------------------
  //              inline uint8_t DstMaskLen(uint8_t dstMaskLen)              
  //.........................................................................
  //  Sets and returns the destination network mask length in the key.
  //-------------------------------------------------------------------------
  inline uint8_t DstMaskLen(uint8_t dstMaskLen)
  {
    this->_dstMaskLen = dstMaskLen;
    return(this->_dstMaskLen);
  }
  
  
  //-------------------------------------------------------------------------
  //  inline bool operator < (const CflowdNetMatrixKey & netMatrixKey) const
  //.........................................................................
  //  overloaded '<' operator so we can use less<CflowdNetMatrixKey> when
  //  using this class as a key to an STL <map>.
  //-------------------------------------------------------------------------
  inline bool operator < (const CflowdNetMatrixKey & netMatrixKey) const
  {
    if (this->Src() < netMatrixKey.Src())
      return(true);
    if (this->Src() > netMatrixKey.Src())
      return(false);
    if (this->SrcMaskLen() < netMatrixKey.SrcMaskLen())
      return(true);
    if (this->SrcMaskLen() > netMatrixKey.SrcMaskLen())
      return(false);
    if (this->Dst() < netMatrixKey.Dst())
      return(true);
    if (this->Dst() > netMatrixKey.Dst())
      return(false);

    if (this->DstMaskLen() < netMatrixKey.DstMaskLen())
      return(true);

    return(false);
  }

  //-------------------------------------------------------------------------
  //                   inline istream & read(istream & is)                   
  //.........................................................................
  //  Reads the key from an istream.  Returns the istream.
  //-------------------------------------------------------------------------
  inline istream & read(istream & is)
  {
    g_CfdArtsPrimitive.ReadIpv4Network(is,this->_src,sizeof(this->_src));
    is.read(&(this->_srcMaskLen),sizeof(this->_srcMaskLen));
    g_CfdArtsPrimitive.ReadIpv4Network(is,this->_dst,sizeof(this->_dst));
    is.read(&(this->_dstMaskLen),sizeof(this->_dstMaskLen));
    
    return(is);
  }
  
  //-------------------------------------------------------------------------
  //                         inline int read(int fd)                         
  //.........................................................................
  //  Reads the key from a file descriptor.  Returns the number of bytes
  //  read on success, -1 on failure.
  //-------------------------------------------------------------------------
  inline int read(int fd)
  {
    int  rc;
    int  bytesRead = 0;

    //  read the source network address
    rc = g_CfdArtsPrimitive.FdRead(fd,&(this->_src),sizeof(this->_src));
    if (rc < (int)sizeof(this->_src)) {
      syslog(LOG_ERR,
             "[E] FdRead(%d,%p,%d) failed (rc = %d): %m {%s:%d}",
             fd,&(this->_src),sizeof(this->_src),rc,__FILE__,__LINE__);
      return(-1);
    }
    bytesRead += rc;

    //  read the source network mask length
    rc = g_CfdArtsPrimitive.FdRead(fd,&(this->_srcMaskLen),
                                   sizeof(this->_srcMaskLen));
    if (rc < (int)sizeof(this->_srcMaskLen)) {
      syslog(LOG_ERR,"[E] read(%d,%p,%d) failed (rc = %d): %m {%s:%d}",
             fd,&(this->_srcMaskLen),sizeof(this->_srcMaskLen),rc,
             __FILE__,__LINE__);
      return(-1);
    }
    bytesRead += rc;

    //  read the destination network address
    rc = g_CfdArtsPrimitive.FdRead(fd,&(this->_dst),sizeof(this->_dst));
    if (rc < (int)sizeof(this->_dst)) {
      syslog(LOG_ERR,
             "[E] read(%d,%p,%d) failed (rc = %d): %m"
             " {%s:%d}",
             fd,&(this->_dst),sizeof(this->_dst),rc,__FILE__,__LINE__);
      return(-1);
    }
    bytesRead += rc;

    //  read the destination network mask length
    rc = g_CfdArtsPrimitive.FdRead(fd,&(this->_dstMaskLen),
                                   sizeof(this->_dstMaskLen));
    if (rc < (int)sizeof(this->_dstMaskLen)) {
      syslog(LOG_ERR,"[E] read(%d,%p,%d) failed (rc = %d): %m {%s:%d}",
             fd,&(this->_dstMaskLen),sizeof(this->_dstMaskLen),rc,
             __FILE__,__LINE__);
      return(-1);
    }
    bytesRead += rc;
    
    return(bytesRead);
  }
  
  //-------------------------------------------------------------------------
  //                inline ostream & write(ostream & os) const
  //.........................................................................
  //  Writes the key to an ostream.  Returns the ostream.
  //-------------------------------------------------------------------------
  inline ostream & write(ostream & os) const
  {
    g_CfdArtsPrimitive.WriteIpv4Network(os,this->_src,sizeof(this->_src));
    os.write(&(this->_srcMaskLen),sizeof(this->_srcMaskLen));
    g_CfdArtsPrimitive.WriteIpv4Network(os,this->_dst,sizeof(this->_dst));
    os.write(&(this->_dstMaskLen),sizeof(this->_dstMaskLen));
    return(os);
  }
  
  //-------------------------------------------------------------------------
  //                     inline int write(int fd) const
  //.........................................................................
  //  Writes the key to a file descriptor.  Returns the number of bytes
  //  written on success, -1 on failure.
  //-------------------------------------------------------------------------
  inline int write(int fd) const
  {
    int  rc;
    int  bytesWritten = 0;

    rc = g_CfdArtsPrimitive.WriteIpv4Network(fd,this->_src,sizeof(this->_src));
    if (rc < (int)sizeof(this->_src))
      return(-1);
    bytesWritten += rc;
    rc = g_CfdArtsPrimitive.FdWrite(fd,&(this->_srcMaskLen),
                                    sizeof(this->_srcMaskLen));
    if (rc < (int)sizeof(this->_srcMaskLen))
      return(-1);
    bytesWritten += rc;
    rc = g_CfdArtsPrimitive.WriteIpv4Network(fd,this->_dst,sizeof(this->_dst));
    if (rc < (int)sizeof(this->_dst))
      return(-1);
    bytesWritten += rc;
    rc = g_CfdArtsPrimitive.FdWrite(fd,&(this->_dstMaskLen),
                                    sizeof(this->_dstMaskLen));
    if (rc < (int)sizeof(this->_dstMaskLen))
      return(-1);
    bytesWritten += rc;
    
    return(bytesWritten);
  }
  
  //-------------------------------------------------------------------------
  //                         static uint8_t Length()                         
  //.........................................................................
  //  Returns the bytes required to read/write the object from/to a file
  //  descriptor.  Note we just return a static member; the I/O size of
  //  the CflowdNetMatrixKey class is constant.
  //-------------------------------------------------------------------------
  static uint8_t Length()
  {
    return(_ioLength);
  }
  
private:
  ipv4addr_t      _src;
  uint8_t         _srcMaskLen;
  ipv4addr_t      _dst;
  uint8_t         _dstMaskLen;
  static uint8_t  _ioLength;
};

#endif  // _CFLOWDNETMATRIXKEY_HH_
