//===========================================================================
//  $Name: cflowd-2-1-b1 $
//  $Id: CflowdCiscoMap.cc,v 1.7 1999/05/25 10:27:07 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
//===========================================================================

#include <string>
#include <vector>

#include "CflowdCiscoMap.hh"

static const string rcsid = "@(#) $Name: cflowd-2-1-b1 $ $Id: CflowdCiscoMap.cc,v 1.7 1999/05/25 10:27:07 dwm Exp $";

//-------------------------------------------------------------------------
//                       void CflowdCiscoMap::Clear()                      
//.........................................................................
//  
//-------------------------------------------------------------------------
void CflowdCiscoMap::Clear()
{
  CflowdCiscoMap::iterator          ciscomIter;
  vector<CflowdCiscoMap::iterator>  deleteIterVect;

  //  We can't just clear the whole map using erase() because our map
  //  contains pointers to CflowdCisco objects, and may contain multiple
  //  pointers to the same Cisco.  We always store a CflowdCisco with
  //  its main IP address as a key, so we'll match on it.  We put
  //  the iterators referring to true CflowdCisco objects into a
  //  vector which we'll use for deleting the CflowdCisco objects,
  //  then call erase() on the map.

  for (ciscomIter = (*this).begin(); ciscomIter != (*this).end();
       ciscomIter++) {
    if ((*ciscomIter).second != (CflowdCisco *)NULL) {
      if ((*ciscomIter).first == (*(*ciscomIter).second).IpAddress()) {
        deleteIterVect.push_back(ciscomIter);
      }
    }
  }

  vector<CflowdCiscoMap::iterator>::iterator  deleteIter;
  
  for (deleteIter = deleteIterVect.begin();
       deleteIter != deleteIterVect.end();
       deleteIter++) {
    delete((*(*deleteIter)).second);
    (*(*deleteIter)).second = (CflowdCisco *)NULL;
  }
  
  (*this).erase((*this).begin(),(*this).end());
  return;
}

//-------------------------------------------------------------------------
//           ostream & CflowdCiscoMap::Write(ostream & os) const           
//.........................................................................
//  
//-------------------------------------------------------------------------
ostream & CflowdCiscoMap::Write(ostream & os) const
{
  const_iterator   ciscomIter;
  uint32_t         numCiscos = 0;

  //  Figure out how many Ciscos we have.  We can't just use the
  //  size() member of the map because our map contains pointers
  //  to CflowdCisco objects, and may contain multiple pointers
  //  to the same Cisco.  We always store a CflowdCisco with
  //  its main IP address as a key, so we'll match on it.
  
  for (ciscomIter = (*this).begin(); ciscomIter != (*this).end();
       ciscomIter++) {
    if ((*ciscomIter).second != (CflowdCisco *)NULL) {
      if ((*ciscomIter).first == (*(*ciscomIter).second).IpAddress()) {
        numCiscos++;
      }
    }
  }
        
  numCiscos = htonl(numCiscos);
  os.write(&numCiscos,sizeof(numCiscos));
  
  for (ciscomIter = (*this).begin(); ciscomIter != (*this).end();
       ciscomIter++) {
    if ((*ciscomIter).second != (CflowdCisco *)NULL) {
      if ((*ciscomIter).first == (*(*ciscomIter).second).IpAddress()) {
        (*(*ciscomIter).second).write(os);
      }
    }
  }
  return(os);
}

//-------------------------------------------------------------------------
//                 int CflowdCiscoMap::Write(int fd) const                 
//.........................................................................
//  
//-------------------------------------------------------------------------
int CflowdCiscoMap::Write(int fd) const
{
  const_iterator   ciscomIter;
  uint32_t         numCiscos = 0;
  int              rc;
  int              bytesWritten = 0;

  //  Figure out how many Ciscos we have.  We can't just use the
  //  size() member of the map because our map contains pointers
  //  to CflowdCisco objects, and may contain multiple pointers
  //  to the same Cisco.  We always store a CflowdCisco with
  //  its main IP address as a key, so we'll match on it.
  
  for (ciscomIter = (*this).begin(); ciscomIter != (*this).end();
       ciscomIter++) {
    if ((*ciscomIter).second != (CflowdCisco *)NULL) {
      if ((*ciscomIter).first == (*(*ciscomIter).second).IpAddress()) {
        numCiscos++;
      }
    }
  }

  //  write the number of Ciscos
  if ((rc = g_CfdArtsPrimitive.WriteUint32(fd,numCiscos,sizeof(numCiscos))) <
      (int)sizeof(numCiscos)) {
    return(-1);
  }
  bytesWritten += rc;

  //  write the Ciscos
  for (ciscomIter = (*this).begin(); ciscomIter != (*this).end();
       ciscomIter++) {
    if ((*ciscomIter).second != (CflowdCisco *)NULL) {
      if ((*ciscomIter).first == (*(*ciscomIter).second).IpAddress()) {
        if ((rc = (*(*ciscomIter).second).write(fd)) < 0) {
          return(-1);
        }
        bytesWritten += rc;
      }
    }
  }
  return(bytesWritten);
}

//----------------------------------------------------------------------------
//                  int CflowdCiscoMap::GetInterfaceInfo() 
//............................................................................
//  
//----------------------------------------------------------------------------
int CflowdCiscoMap::GetInterfaceInfo()
{
  iterator   ciscomIter;
  
  for (ciscomIter = (*this).begin(); ciscomIter != (*this).end();
       ciscomIter++) {
    ((*ciscomIter).second)->GetInterfaceInfo();
  }

  return(0);
}
