//===========================================================================
//  $Name: arts++-1-1-a12 $
//  $Id: ArtsBgp4RouteTableData.cc,v 1.3 2004/06/23 16:57:26 youngh Exp $
//===========================================================================
//  Copyright Notice
//
//  By accessing this software, arts++, you are duly informed
//  of and agree to be bound by the conditions described below in this
//  notice:
//
//  This software product, arts++, 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 arts++ software.  You can redistribute it
//  and/or modify it under the terms of the GNU Lesser General Public
//  License, Version 2.1, February 1999, which is incorporated by
//  reference herein.
//
//  arts++ 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 Lesser General Public
//  License along with arts++.  Copies can also be obtained from:
//
//    http://www.gnu.org/copyleft/lesser.html
//
//  or by writing to:
//
//  Free Software Foundation, Inc.
//  59 Temple Place, Suite 330
//  Boston, MA 02111-1307
//  USA
//
//  Or contact:
//
//    info@caida.org
//===========================================================================

#include <string>
#include <assert.h>

#include "ArtsPrimitive.hh"
#include "ArtsBgp4RouteTableData.hh"

using namespace std;

static const std::string rcsid = "@(#) $Name: arts++-1-1-a12 $ $Id: ArtsBgp4RouteTableData.cc,v 1.3 2004/06/23 16:57:26 youngh Exp $";

//----------------------------------------------------------------------------
//             ArtsBgp4RouteTableData::ArtsBgp4RouteTableData()            
//............................................................................
//  
//----------------------------------------------------------------------------
ArtsBgp4RouteTableData::ArtsBgp4RouteTableData()
{
  #ifndef NDEBUG
    ++this->_numObjects;
  #endif
}

//----------------------------------------------------------------------------
//            ArtsBgp4RouteTableData::~ArtsBgp4RouteTableData()            
//............................................................................
//  
//----------------------------------------------------------------------------
ArtsBgp4RouteTableData::~ArtsBgp4RouteTableData()
{
  #ifndef NDEBUG
    --this->_numObjects;
  #endif

  if (this->_routes.size() > 0)
    this->_routes.erase(this->_routes.begin(),this->_routes.end());
}

//----------------------------------------------------------------------------
//            uint32_t ArtsBgp4RouteTableData::NumRoutes() const             
//............................................................................
//  
//----------------------------------------------------------------------------
uint32_t ArtsBgp4RouteTableData::NumRoutes() const
{
  return(this->_routes.size());
}

//----------------------------------------------------------------------------
//  ArtsBgp4RouteEntry &                          
//  ArtsBgp4RouteTableData::AddRoute(const Ipv4Network & prefix, 
//                                   const ArtsBgp4RouteEntry & routeEntry) 
//............................................................................
//  
//----------------------------------------------------------------------------
ArtsBgp4RouteEntry &
ArtsBgp4RouteTableData::AddRoute(const Ipv4Network & prefix,
                             const ArtsBgp4RouteEntry & routeEntry)
{
  this->_routes[prefix] = routeEntry;
  return(this->_routes[prefix]);
}

//----------------------------------------------------------------------------
//    bool ArtsBgp4RouteTableData::DeleteRoute(const Ipv4Network & prefix)    
//............................................................................
//  
//----------------------------------------------------------------------------
bool ArtsBgp4RouteTableData::DeleteRoute(const Ipv4Network & prefix)
{
  return(this->_routes.erase(prefix));
}

//----------------------------------------------------------------------------
// istream & ArtsBgp4RouteTableData::read(istream & is, uint8_t version)  
//............................................................................
//  
//----------------------------------------------------------------------------
istream & ArtsBgp4RouteTableData::read(istream & is, uint8_t version)
{
  uint32_t            numRoutes;
  ArtsBgp4RouteEntry  routeEntry;
  Ipv4Network         network;
  
  g_ArtsLibInternal_Primitive.ReadUint32(is,numRoutes,sizeof(numRoutes));
  for (uint32_t routeNum = 0; routeNum < numRoutes; ++routeNum) {
    network.read(is);
    routeEntry.read(is,version);
    this->_routes[network] = routeEntry;
  }
  return(is);
}

//----------------------------------------------------------------------------
//      int ArtsBgp4RouteTableData::read(int fd, uint8_t version)        
//............................................................................
//  
//----------------------------------------------------------------------------
int ArtsBgp4RouteTableData::read(int fd, uint8_t version)
{
  uint32_t            numRoutes;
  ArtsBgp4RouteEntry  routeEntry;
  Ipv4Network         network;
  int                 rc;
  int                 bytesRead = 0;

  rc = g_ArtsLibInternal_Primitive.ReadUint32(fd,numRoutes,sizeof(numRoutes));
  for (uint32_t routeNum = 0; routeNum < numRoutes; ++routeNum) {
    rc = network.read(fd);
    if (rc < 0)
      return(-1);
    bytesRead += rc;
    rc = routeEntry.read(fd,version);
    if (rc < 0)
      return(-1);
    bytesRead += rc;
    this->_routes[network] = routeEntry;
  }

  return(bytesRead);
}

//----------------------------------------------------------------------------
//    ostream & ArtsBgp4RouteTableData::write(ostream & os,
//                                            uint8_t version) const 
//............................................................................
//  
//----------------------------------------------------------------------------
ostream & ArtsBgp4RouteTableData::write(ostream & os,
                                        uint8_t version) const
{
  Ipv4PrefixPatricia<ArtsBgp4RouteEntry>::iterator  routeIter;

  g_ArtsLibInternal_Primitive.WriteUint32(os,this->_routes.size(),
                                          sizeof(uint32_t));
  
  for (routeIter = this->_routes.begin(); routeIter != this->_routes.end();
       routeIter++) {
    (*routeIter).first.write(os);
    (*routeIter).second.write(os,version);
  }
  return(os);
}

//----------------------------------------------------------------------------
//    int ArtsBgp4RouteTableData::write(int fd, uint8_t version) const    
//............................................................................
//  
//----------------------------------------------------------------------------
int ArtsBgp4RouteTableData::write(int fd, uint8_t version) const
{
  Ipv4PrefixPatricia<ArtsBgp4RouteEntry>::iterator  routeIter;
  int    rc;
  int    bytesWritten = 0;
  
  rc = g_ArtsLibInternal_Primitive.WriteUint32(fd,this->_routes.size(),
                                               sizeof(uint32_t));
  if (rc < sizeof(uint32_t))
    return(-1);
  bytesWritten += rc;
  
  for (routeIter = this->_routes.begin(); routeIter != this->_routes.end();
       routeIter++) {
    rc = (*routeIter).first.write(fd);
    if (rc < 0)
      return(-1);
    bytesWritten += rc;
    rc = (*routeIter).second.write(fd,version);
    if (rc < 0)
      return(-1);
    bytesWritten += rc;
  }
  return(bytesWritten);
}

//----------------------------------------------------------------------------
//    uint32_t ArtsBgp4RouteTableData::Length(uint8_t version) const     
//............................................................................
//  
//----------------------------------------------------------------------------
uint32_t ArtsBgp4RouteTableData::Length(uint8_t version) const
{
  uint32_t  length = sizeof(uint32_t);
  Ipv4PrefixPatricia<ArtsBgp4RouteEntry>::iterator  routeIter;
  for (routeIter = this->_routes.begin(); routeIter != this->_routes.end();
       routeIter++) {
    length += (*routeIter).first.Length();
    length += (*routeIter).second.Length();
  }
  return(length);
}

//----------------------------------------------------------------------------
//                 Ipv4PrefixPatricia<ArtsBgp4RouteEntry> &                
//                 ArtsBgp4RouteTableData::Routes() const                  
//............................................................................
//  
//----------------------------------------------------------------------------
Ipv4PrefixPatricia<ArtsBgp4RouteEntry> &
ArtsBgp4RouteTableData::Routes() const
{
  return(this->_routes);
}

//----------------------------------------------------------------------------
//   ostream& operator << (ostream & os,                   
//                         const ArtsBgp4RouteTableData & bgp4RouteTable) 
//............................................................................
//  
//----------------------------------------------------------------------------
ostream& operator << (ostream & os,
                      const ArtsBgp4RouteTableData & bgp4RouteTable)
{
  os << "BGP4 ROUTE TABLE DATA" << endl;
  os << "\tnumber of routes: " << bgp4RouteTable.Routes().size() << endl;

  Ipv4PrefixPatricia<ArtsBgp4RouteEntry>::iterator  routeIter;
  for (routeIter = bgp4RouteTable.Routes().begin();
       routeIter != bgp4RouteTable.Routes().end(); routeIter++) {
    os << "\tBGP4 ROUTE ENTRY" << endl;
    os << "\t\tnetwork: " << (*routeIter).first << endl;
    os << (*routeIter).second;
  }
  return(os);
}


uint32_t  ArtsBgp4RouteTableData::_numObjects = 0;
