//===========================================================================
//  $Name: cflowd-2-1-b1 $
//  $Id: CflowdUint16Uint16Key.hh,v 1.4 1999/08/11 16:11:35 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 _CFLOWDUINT16UINT16KEY_HH_
#define _CFLOWDUINT16UINT16KEY_HH_

extern "C" {
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <syslog.h>
  
#include "caida_t.h"
}

#include <map>

#include "ArtsPrimitive.hh"

extern ArtsPrimitive g_CfdArtsPrimitive;

//---------------------------------------------------------------------------
//  class CflowdUint16Uint16Key
//---------------------------------------------------------------------------
//  This class is used as a key into an AS matrix map, port matrix map,
//  and interface matrix map in cflowd++.  The key is comprised of a
//  source and destination number, stored as uint16_t values.  In the
//  case of the AS matrix, the Src() is the source AS and the Dst() is
//  the destination AS.  In the case of the port matrix, Src() is the
//  source (transmitting) port and Dst() is the destination (receiving)
//  port.  In the case of the interface matrix, Src() is the input
//  interface and Dst() is the output interface.
//
//  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 CflowdUint16Uint16Key
{
public:
  //-------------------------------------------------------------------------
  //                       inline uint16_t Src() const                       
  //.........................................................................
  //  Returns the source in the key.
  //-------------------------------------------------------------------------
  inline uint16_t Src() const
  {
    return(this->_src);
  }
  
  //-------------------------------------------------------------------------
  //                    inline uint16_t Src(uint16_t src)                    
  //.........................................................................
  //  Sets the source in the key and returns it.
  //-------------------------------------------------------------------------
  inline uint16_t Src(uint16_t src)
  {
    this->_src = src;
    return(this->_src);
  }
  
  //-------------------------------------------------------------------------
  //                       inline uint16_t Dst() const                       
  //.........................................................................
  //  Returns the destination in the key.
  //-------------------------------------------------------------------------
  inline uint16_t Dst() const
  {
    return(this->_dst);
  }
  
  //-------------------------------------------------------------------------
  //                    inline uint16_t Dst(uint16_t dst)                    
  //.........................................................................
  //  Sets and then returns the destination in the key.
  //-------------------------------------------------------------------------
  inline uint16_t Dst(uint16_t dst)
  {
    this->_dst = dst;
    return(this->_dst);
  }

  //-------------------------------------------------------------------------
  //    inline bool operator < (const CflowdUint16Uint16Key & key) const
  //.........................................................................
  //  overloaded '<' operator so we can use less<CflowdUint16Uint16Key> when
  //  using this class as a key to an STL <map>.
  //-------------------------------------------------------------------------
  inline bool operator < (const CflowdUint16Uint16Key & key) const
  {
    return((((uint32_t)htons(this->_src) << 16) | htons(this->_dst)) <
           (((uint32_t)htons(key.Src()) << 16) |
            htons(key.Dst())));
  }

  //-------------------------------------------------------------------------
  //                   inline istream & read(istream & is)                   
  //.........................................................................
  //  Reads the key from an istream.  Returns the istream.
  //-------------------------------------------------------------------------
  inline istream & read(istream & is)
  {
    g_CfdArtsPrimitive.ReadUint16(is,this->_src,sizeof(this->_src));
    g_CfdArtsPrimitive.ReadUint16(is,this->_dst,sizeof(this->_dst));
    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;
    rc = g_CfdArtsPrimitive.ReadUint16(fd,this->_src,sizeof(this->_src));
    if (rc < (int)sizeof(this->_src)) {
      syslog(LOG_ERR,
             "[E] ArtsPrimitive.ReadUint16(%d,%d,%d) failed: %m {%s:%d}",
             fd,this->_src,sizeof(this->_src),__FILE__,__LINE__);
      return(-1);
    }
    bytesRead += rc;
    rc = g_CfdArtsPrimitive.ReadUint16(fd,this->_dst,sizeof(this->_dst));
    if (rc < (int)sizeof(this->_dst)) {
      syslog(LOG_ERR,
             "[E] ArtsPrimitive.ReadUint16(%d,%d,%d) failed: %m {%s:%d}",
             fd,this->_dst,sizeof(this->_dst),__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.WriteUint16(os,this->_src,sizeof(this->_src));
    g_CfdArtsPrimitive.WriteUint16(os,this->_dst,sizeof(this->_dst));
    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.WriteUint16(fd,this->_src,sizeof(this->_src));
    if (rc < (int)sizeof(this->_src)) {
      syslog(LOG_ERR,
             "[E] ArtsPrimitive.WriteUint16(%d,%d,%d) failed: %m {%s:%d}",
             fd,this->_src,sizeof(this->_src),__FILE__,__LINE__);
      return(-1);
    }
    bytesWritten += rc;
    rc = g_CfdArtsPrimitive.WriteUint16(fd,this->_dst,sizeof(this->_dst));
    if (rc < (int)sizeof(this->_dst)) {
      syslog(LOG_ERR,
             "[E] ArtsPrimitive.WriteUint16(%d,%d,%d) failed: %m {%s:%d}",
             fd,this->_dst,sizeof(this->_dst),__FILE__,__LINE__);
      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 CflowdUint16Uint16Key class is constant.
  //--------------------------------------------------------------------------
  static uint8_t Length()
  {
    return(_ioLength);
  }
  
private:
  uint16_t        _src;
  uint16_t        _dst;
  static uint8_t  _ioLength;
};

#endif  // _CFLOWDUINT16UINT16KEY_HH_
