//===========================================================================
//  $Name: arts++-1-1-a12 $
//  $Id: ArtsBgp4Attribute.cc,v 1.2 2004/04/21 23:51:31 kkeys 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
//===========================================================================

extern "C" {
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <string.h>
}

#include <string>

#include "ArtsPrimitive.hh"
#include "ArtsBgp4Attribute.hh"

using namespace std;

static const std::string rcsid = "@(#) $Name: arts++-1-1-a12 $ $Id: ArtsBgp4Attribute.cc,v 1.2 2004/04/21 23:51:31 kkeys Exp $";

//-------------------------------------------------------------------------
//                  ArtsBgp4Attribute::ArtsBgp4Attribute()                 
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
ArtsBgp4Attribute::ArtsBgp4Attribute()
{
  this->_flags = 0;
  this->_type = 0;
  this->_value._origin = 0;
  this->_value._nextHop = 0;
  this->_value._MED = 0;
  this->_value._localPref = 0;
  this->_value._aggregator = (ArtsBgp4AggregatorAttribute *)0;
  this->_value._community = (vector<uint32_t> *)0;
  this->_value._dp = (ArtsBgp4DPAttribute *)0;
  this->_value._asPath = (ArtsBgp4AsPathAttribute *)0;

  #ifndef NDEBUG
    ++_numObjects;
  #endif
}

//----------------------------------------------------------------------------
// ArtsBgp4Attribute::ArtsBgp4Attribute(const ArtsBgp4Attribute & bgp4Attr) 
//............................................................................
//  copy constructor
//----------------------------------------------------------------------------
ArtsBgp4Attribute::ArtsBgp4Attribute(const ArtsBgp4Attribute & bgp4Attr)
{
  this->_flags = bgp4Attr.Flags();
  this->_type = bgp4Attr.Type();

  switch (this->_type) {
    case Bgp4_Attribute_Origin:
      this->_value._origin = bgp4Attr.Origin();
      break;
      
    case Bgp4_Attribute_AsPath:
      this->_value._asPath = new ArtsBgp4AsPathAttribute;
      *(this->_value._asPath) = *(bgp4Attr.AsPath());
      break;
      
    case Bgp4_Attribute_NextHop:
      this->_value._nextHop = bgp4Attr.NextHop();
      break;
      
    case Bgp4_Attribute_MultiExitDisc:
      this->_value._MED = bgp4Attr.MED();
      break;
      
    case Bgp4_Attribute_LocalPref:
      this->_value._localPref = bgp4Attr.LocalPref();
      break;
      
    case Bgp4_Attribute_AtomicAggregate:
      break;
      
    case Bgp4_Attribute_Aggregator:
      this->_value._aggregator = new ArtsBgp4AggregatorAttribute;
      *(this->_value._aggregator) = *(bgp4Attr.Aggregator());
      break;
      
    case Bgp4_Attribute_Community:
      this->_value._community = new vector<uint32_t>(*(bgp4Attr.Community()));
      break;
      
    case Bgp4_Attribute_DPA:
      this->_value._dp = new ArtsBgp4DPAttribute;
      *(this->_value._dp) = *(bgp4Attr.DP());
      break;
      
    case Bgp4_Attribute_MPReachNLRI:
      break;
      
    case Bgp4_Attribute_MPUnreachNLRI:
      break;
      
    default:
      break;
  }
  #ifndef NDEBUG
    ++_numObjects;
  #endif
}

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

//-------------------------------------------------------------------------
//                 uint8_t ArtsBgp4Attribute::Flags() const                
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
uint8_t ArtsBgp4Attribute::Flags() const
{
  return(this->_flags);
}

//------------------------------------------------------------------------
//             uint8_t ArtsBgp4Attribute::Flags(uint8_t flags)             
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
uint8_t ArtsBgp4Attribute::Flags(uint8_t flags)
{
  this->_flags = flags;
  return(this->_flags);
}

//-------------------------------------------------------------------------
//                 uint8_t ArtsBgp4Attribute::Type() const                 
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
uint8_t ArtsBgp4Attribute::Type() const
{
  return(this->_type);
}

//-------------------------------------------------------------------------
//            uint8_t ArtsBgp4Attribute::Type(uint8_t attrType)            
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
uint8_t ArtsBgp4Attribute::Type(uint8_t attrType)
{
  this->_type = attrType;
  return(this->_type);
}

//-------------------------------------------------------------------------
//                uint8_t ArtsBgp4Attribute::Origin() const
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
uint8_t ArtsBgp4Attribute::Origin() const
{
  assert(this->_type == Bgp4_Attribute_Origin);
  return(this->_value._origin);
}

//-------------------------------------------------------------------------
//            uint8_t ArtsBgp4Attribute::Origin(uint8_t origin)
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
uint8_t ArtsBgp4Attribute::Origin(uint8_t origin)
{
  assert(this->_type == Bgp4_Attribute_Origin);
  this->_value._origin = origin;
  return(this->_value._origin);
}

//-------------------------------------------------------------------------
//    const ArtsBgp4AsPathAttribute * ArtsBgp4Attribute::AsPath() const
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
const ArtsBgp4AsPathAttribute * ArtsBgp4Attribute::AsPath() const
{
  assert(this->_type == Bgp4_Attribute_AsPath);
  return(this->_value._asPath);
}

//-------------------------------------------------------------------------
//    const ArtsBgp4AsPathAttribute *
//    ArtsBgp4Attribute::AsPath(const ArtsBgp4AsPathAttribute & asPath)
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
const ArtsBgp4AsPathAttribute *
ArtsBgp4Attribute::AsPath(const ArtsBgp4AsPathAttribute & asPath)
{
  this->DeleteValue();
  
  this->_type = Bgp4_Attribute_AsPath;
  this->_value._asPath = new ArtsBgp4AsPathAttribute(asPath);
  // *(this->_value._asPath) = asPath;
  return(this->_value._asPath);
}

//-------------------------------------------------------------------------
//        const ipv4addr_t & ArtsBgp4Attribute::NextHop() const
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
const ipv4addr_t & ArtsBgp4Attribute::NextHop() const
{
  assert(this->_type == Bgp4_Attribute_NextHop);
  return(this->_value._nextHop);
}

//-------------------------------------------------------------------------
//    const ipv4addr_t &
//          ArtsBgp4Attribute::NextHop(const ipv4addr_t & nextHop)
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
const ipv4addr_t &
ArtsBgp4Attribute::NextHop(const ipv4addr_t & nextHop)
{
  this->_type = Bgp4_Attribute_NextHop;
  this->_value._nextHop = nextHop;
  return(this->_value._nextHop);
}

//-------------------------------------------------------------------------
//                 uint32_t ArtsBgp4Attribute::MED() const;                
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
uint32_t ArtsBgp4Attribute::MED() const
{
  assert(this->_type == Bgp4_Attribute_MultiExitDisc);
  return(this->_value._MED);
}

//-------------------------------------------------------------------------
//              uint32_t ArtsBgp4Attribute::MED(uint32_t med)
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
uint32_t ArtsBgp4Attribute::MED(uint32_t med)
{
  assert(this->_type == Bgp4_Attribute_MultiExitDisc);
  this->_value._MED = med;
  return(this->_value._MED);
}

//-------------------------------------------------------------------------
//              uint32_t ArtsBgp4Attribute::LocalPref() const
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
uint32_t ArtsBgp4Attribute::LocalPref() const
{
  assert(this->_type == Bgp4_Attribute_LocalPref);
  return(this->_value._localPref);
}

//-------------------------------------------------------------------------
//        uint32_t ArtsBgp4Attribute::LocalPref(uint32_t localPref)
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
uint32_t ArtsBgp4Attribute::LocalPref(uint32_t localPref)
{
  assert(this->_type == Bgp4_Attribute_LocalPref);
  this->_value._localPref = localPref;
  return(this->_value._localPref);
}

//-------------------------------------------------------------------------
//               const ArtsBgp4AggregatorAttribute *
//               ArtsBgp4Attribute::Aggregator() const
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
const ArtsBgp4AggregatorAttribute *
ArtsBgp4Attribute::Aggregator() const
{
  assert(this->_type == Bgp4_Attribute_Aggregator);
  return(this->_value._aggregator);
}

//-------------------------------------------------------------------------
//  const ArtsBgp4AggregatorAttribute *
//  ArtsBgp4Attribute::Aggregator(const ArtsBgp4AggregatorAttribute &
//                                aggregator)
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
const ArtsBgp4AggregatorAttribute *
ArtsBgp4Attribute::Aggregator(const ArtsBgp4AggregatorAttribute & aggregator)
{
  this->_type = Bgp4_Attribute_Aggregator;
  this->_value._aggregator = new ArtsBgp4AggregatorAttribute(aggregator);
  return(this->_value._aggregator);
}

//-------------------------------------------------------------------------
//      const vector<uint32_t> * ArtsBgp4Attribute::Community() const
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
const vector<uint32_t> * ArtsBgp4Attribute::Community() const
{
  assert(this->_type == Bgp4_Attribute_Community);
  return(this->_value._community);
}

//-------------------------------------------------------------------------
//     const vector<uint32_t> *
//     ArtsBgp4Attribute::Community(const vector<uint32_t> & community) 
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
const vector<uint32_t> *
ArtsBgp4Attribute::Community(const vector<uint32_t> & community)
{
  this->_type = Bgp4_Attribute_Community;
  this->_value._community = new vector<uint32_t>(community);
  return(this->_value._community);
}


//-------------------------------------------------------------------------
//        const ArtsBgpDPAttribute * ArtsBgp4Attribute::DP() const
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
const ArtsBgp4DPAttribute * ArtsBgp4Attribute::DP() const
{
  assert(this->_type == Bgp4_Attribute_DPA);
  return(this->_value._dp);
}

//-------------------------------------------------------------------------
//         const ArtsBgp4DPAttribute *
//         ArtsBgp4Attribute::DP(const ArtsBgp4DPAttribute & dp)
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
const ArtsBgp4DPAttribute *
ArtsBgp4Attribute::DP(const ArtsBgp4DPAttribute & dp)
{
  this->_type = Bgp4_Attribute_DPA;
  this->_value._dp = new ArtsBgp4DPAttribute(dp);  
  return(this->_value._dp);
}

//-------------------------------------------------------------------------
//                  void ArtsBgp4Attribute::DeleteValue()
//.........................................................................
//                                                                         
//-------------------------------------------------------------------------
void ArtsBgp4Attribute::DeleteValue()
{
  switch (this->_type) {
    case Bgp4_Attribute_AsPath:
      if ((*this)._value._asPath != (ArtsBgp4AsPathAttribute *)0) {
        delete((*this)._value._asPath);
      }
      (*this)._value._asPath = (ArtsBgp4AsPathAttribute *)0;
      break;
    case Bgp4_Attribute_Aggregator:
      if (this->_value._aggregator != (ArtsBgp4AggregatorAttribute *)0) {
        delete(this->_value._aggregator);
      }
      this->_value._aggregator = (ArtsBgp4AggregatorAttribute *)0;
      break;
    case Bgp4_Attribute_Community:
      if (this->_value._community != (vector<uint32_t> *)0) {
        delete(this->_value._community);
      }
      this->_value._community = (vector<uint32_t> *)0;
      break;
    case Bgp4_Attribute_DPA:
      if (this->_value._dp != (ArtsBgp4DPAttribute *)0) {
        delete(this->_value._dp);
      }
      this->_value._dp = (ArtsBgp4DPAttribute *)0;
      break;
    default:
      break;
  }
  this->_type = 0;
  
  return;
}

//----------------------------------------------------------------------------
//   istream & ArtsBgp4Attribute::read(istream & is, uint8_t version)  
//............................................................................
//  
//----------------------------------------------------------------------------
istream & ArtsBgp4Attribute::read(istream & is, uint8_t version)
{
  uint8_t      numCommunities;
  uint32_t     community;

  this->DeleteValue();
  
  is.read((char*)&this->_flags,sizeof(this->_flags));
  is.read((char*)&this->_type,sizeof(this->_type));
  
  switch (this->_type) {
    case Bgp4_Attribute_Origin:
      is.read((char*)&this->_value._origin,sizeof(this->_value._origin));
      break;
    case Bgp4_Attribute_AsPath:
      this->_value._asPath = new ArtsBgp4AsPathAttribute;
      this->_value._asPath->read(is,version);
      break;
    case Bgp4_Attribute_NextHop:
      is.read((char*)&this->_value._nextHop,sizeof(this->_value._nextHop));
      break;
    case Bgp4_Attribute_MultiExitDisc:
      g_ArtsLibInternal_Primitive.ReadUint32(is,this->_value._MED,
                                             sizeof(this->_value._MED));
      break;
    case Bgp4_Attribute_LocalPref:
      g_ArtsLibInternal_Primitive.ReadUint32(is,this->_value._localPref,
                                             sizeof(this->_value._localPref));
      break;
    case Bgp4_Attribute_AtomicAggregate:
      break;
    case Bgp4_Attribute_Aggregator:
      this->_value._aggregator = new ArtsBgp4AggregatorAttribute;
      this->_value._aggregator->read(is,version);
      break;
    case Bgp4_Attribute_Community:
      is.read((char*)&numCommunities,sizeof(numCommunities));
      this->_value._community = new vector<uint32_t>;
      this->_value._community->reserve((int)numCommunities);
      for (int commNum = 0; commNum < numCommunities; commNum++) {
        g_ArtsLibInternal_Primitive.ReadUint32(is,community,sizeof(community));
        this->_value._community->push_back(community);
      }
      break;
    case Bgp4_Attribute_DPA:
      this->_value._dp = new ArtsBgp4DPAttribute;
      this->_value._dp->read(is,version);
      break;
    case Bgp4_Attribute_MPReachNLRI:
      break;
    case Bgp4_Attribute_MPUnreachNLRI:
      break;
    default:
      break;
  }
  return(is);
}

//----------------------------------------------------------------------------
//         int ArtsBgp4Attribute::read(int fd, uint8_t version)        
//............................................................................
//  
//----------------------------------------------------------------------------
int ArtsBgp4Attribute::read(int fd, uint8_t version)
{
  uint8_t      numCommunities;
  uint32_t     community;
  int          rc;
  int          bytesRead = 0;
  
  rc = g_ArtsLibInternal_Primitive.FdRead(fd,&this->_flags,
                                          sizeof(this->_flags));
  if (rc < sizeof(this->_flags))
    return(-1);
  bytesRead += rc;
  
  rc = g_ArtsLibInternal_Primitive.FdRead(fd,&this->_type,sizeof(this->_type));
  if (rc < sizeof(this->_type))
    return(-1);
  bytesRead += rc;
  
  switch (this->_type) {
    case Bgp4_Attribute_Origin:
      rc = g_ArtsLibInternal_Primitive.FdRead(fd,&this->_value._origin,
                                              sizeof(this->_value._origin));
      if (rc < sizeof(this->_value._origin))
        return(-1);
      bytesRead += rc;
      break;
      
    case Bgp4_Attribute_AsPath:
      this->_value._asPath = new ArtsBgp4AsPathAttribute;
      rc = this->_value._asPath->read(fd,version);
      if (rc < 0)
        return(-1);
      bytesRead += rc;
      break;
      
    case Bgp4_Attribute_NextHop:
      rc = g_ArtsLibInternal_Primitive.FdRead(fd,&this->_value._nextHop,
                                              sizeof(this->_value._nextHop));
      if (rc < sizeof(this->_value._nextHop))
        return(-1);
      bytesRead += rc;
      break;
      
    case Bgp4_Attribute_MultiExitDisc:
      rc = g_ArtsLibInternal_Primitive.ReadUint32(fd,this->_value._MED,
                                                  sizeof(this->_value._MED));
      if (rc < sizeof(this->_value._MED))
        return(-1);
      bytesRead += rc;
      break;
      
    case Bgp4_Attribute_LocalPref:
      rc = g_ArtsLibInternal_Primitive.ReadUint32(fd,this->_value._localPref,
                                             sizeof(this->_value._localPref));
      if (rc < sizeof(this->_value._localPref))
        return(-1);
      bytesRead += rc;
      break;
      
    case Bgp4_Attribute_AtomicAggregate:
      break;
      
    case Bgp4_Attribute_Aggregator:
      this->_value._aggregator = new ArtsBgp4AggregatorAttribute;
      rc = this->_value._aggregator->read(fd,version);
      if (rc < 0)
        return(-1);
      bytesRead += rc;
      break;
      
    case Bgp4_Attribute_Community:
      rc = g_ArtsLibInternal_Primitive.FdRead(fd,&numCommunities,
                                              sizeof(numCommunities));
      if (rc < sizeof(numCommunities))
        return(-1);
      bytesRead += rc;
      this->_value._community = new vector<uint32_t>;
      this->_value._community->reserve((int)numCommunities);
      for (int commNum = 0; commNum < numCommunities; commNum++) {
        rc = g_ArtsLibInternal_Primitive.ReadUint32(fd,community,
                                                    sizeof(community));
        if (rc < sizeof(community))
          return(-1);
        bytesRead += rc;
        this->_value._community->push_back(community);
      }
      break;
    case Bgp4_Attribute_DPA:
      this->_value._dp = new ArtsBgp4DPAttribute;
      rc = this->_value._dp->read(fd,version);
      if (rc < 0)
        return(-1);
      bytesRead += rc;
      break;
      
    case Bgp4_Attribute_MPReachNLRI:
      break;
      
    case Bgp4_Attribute_MPUnreachNLRI:
      break;
      
    default:
      break;
  }
  return(bytesRead);
}


//----------------------------------------------------------------------------
//      ostream & ArtsBgp4Attribute::write(ostream & os,
//                                         uint8_t version) const        
//............................................................................
//  
//----------------------------------------------------------------------------
ostream & ArtsBgp4Attribute::write(ostream & os,
                                   uint8_t version) const
{
  uint8_t  numCommunities;
  
  os.write((char*)&this->_flags,sizeof(this->_flags));
  os.write((char*)&this->_type,sizeof(this->_type));

    switch (this->_type) {
    case Bgp4_Attribute_Origin:
      os.write((char*)&this->_value._origin,sizeof(this->_value._origin));
      break;
    case Bgp4_Attribute_AsPath:
      this->_value._asPath->write(os,version);
      break;
    case Bgp4_Attribute_NextHop:
      os.write((char*)&this->_value._nextHop,sizeof(this->_value._nextHop));
      break;
    case Bgp4_Attribute_MultiExitDisc:
      g_ArtsLibInternal_Primitive.WriteUint32(os,this->_value._MED,
                                              sizeof(this->_value._MED));
      break;
    case Bgp4_Attribute_LocalPref:
      g_ArtsLibInternal_Primitive.WriteUint32(os,this->_value._localPref,
                                              sizeof(this->_value._localPref));
      break;
    case Bgp4_Attribute_AtomicAggregate:
      break;
    case Bgp4_Attribute_Aggregator:
      this->_value._aggregator->write(os,version);
      break;
    case Bgp4_Attribute_Community:
      numCommunities = this->_value._community->size();
      os.write((char*)&numCommunities,sizeof(numCommunities));
      for (int commNum = 0; commNum < numCommunities; commNum++) {
        g_ArtsLibInternal_Primitive.WriteUint32(os,
                                        (*(this->_value._community))[commNum],
                                        sizeof(uint32_t));
      }
      break;
    case Bgp4_Attribute_DPA:
      this->_value._dp->write(os,version);
      break;
    case Bgp4_Attribute_MPReachNLRI:
      break;
    case Bgp4_Attribute_MPUnreachNLRI:
      break;
    default:
      break;
  }
  return(os);

}

//----------------------------------------------------------------------------
//     int ArtsBgp4Attribute::write(int fd, uint8_t version) const     
//............................................................................
//  
//----------------------------------------------------------------------------
int ArtsBgp4Attribute::write(int fd, uint8_t version) const
{
  uint8_t  numCommunities;
  int      rc;
  int      bytesWritten = 0;
  
  rc = g_ArtsLibInternal_Primitive.FdWrite(fd,&this->_flags,
                                           sizeof(this->_flags));
  if (rc < sizeof(this->_flags))
    return(-1);
  bytesWritten += rc;
  rc = g_ArtsLibInternal_Primitive.FdWrite(fd,&this->_type,
                                           sizeof(this->_type));
  if (rc < sizeof(this->_type))
    return(-1);
  bytesWritten += rc;
  
  switch (this->_type) {
    case Bgp4_Attribute_Origin:
      rc = g_ArtsLibInternal_Primitive.FdWrite(fd,&this->_value._origin,
                                               sizeof(this->_value._origin));
        if (rc < sizeof(this->_value._origin))
          return(-1);
      bytesWritten += rc;
      break;
      
    case Bgp4_Attribute_AsPath:
      rc = this->_value._asPath->write(fd,version);
      if (rc < 0)
        return(-1);
      bytesWritten += rc;
      break;
      
    case Bgp4_Attribute_NextHop:
      rc = g_ArtsLibInternal_Primitive.FdWrite(fd,&this->_value._nextHop,
                                               sizeof(this->_value._nextHop));
      if (rc < sizeof(this->_value._nextHop))
        return(-1);
      bytesWritten += rc;
      break;
      
    case Bgp4_Attribute_MultiExitDisc:
      rc = g_ArtsLibInternal_Primitive.WriteUint32(fd,this->_value._MED,
                                                   sizeof(this->_value._MED));
      if (rc < sizeof(this->_value._MED))
        return(-1);
      bytesWritten += rc;
      break;
      
    case Bgp4_Attribute_LocalPref:
      rc = g_ArtsLibInternal_Primitive.WriteUint32(fd,this->_value._localPref,
                                              sizeof(this->_value._localPref));
      if (rc < sizeof(this->_value._localPref))
        return(-1);
      bytesWritten += rc;
      break;
      
    case Bgp4_Attribute_AtomicAggregate:
      break;
      
    case Bgp4_Attribute_Aggregator:
      rc = this->_value._aggregator->write(fd,version);
      if (rc < 0)
        return(-1);
      bytesWritten += rc;
      break;
      
    case Bgp4_Attribute_Community:
      numCommunities = this->_value._community->size();
      rc = g_ArtsLibInternal_Primitive.FdWrite(fd,&numCommunities,
                                               sizeof(numCommunities));
      if (rc < sizeof(numCommunities))
        return(-1);
      bytesWritten += rc;
      for (int commNum = 0; commNum < numCommunities; commNum++) {
        rc = g_ArtsLibInternal_Primitive.WriteUint32(fd,
                                        (*(this->_value._community))[commNum],
                                        sizeof(uint32_t));
        if (rc < sizeof(uint32_t))
          return(-1);
        bytesWritten += rc;
      }
      break;
      
    case Bgp4_Attribute_DPA:
      rc = this->_value._dp->write(fd,version);
      if (rc < 0)
        return(-1);
      bytesWritten += rc;
      break;
      
    case Bgp4_Attribute_MPReachNLRI:
      break;
      
    case Bgp4_Attribute_MPUnreachNLRI:
      break;
      
    default:
      break;
  }
  return(bytesWritten);
}


//----------------------------------------------------------------------------
//     ArtsBgp4Attribute &                           
//     ArtsBgp4Attribute::operator = (const ArtsBgp4Attribute & bgp4Attr) 
//............................................................................
//  
//----------------------------------------------------------------------------
ArtsBgp4Attribute &
ArtsBgp4Attribute::operator = (const ArtsBgp4Attribute & bgp4Attr)
{
  this->DeleteValue();
  
  this->_flags = bgp4Attr.Flags();
  this->_type = bgp4Attr.Type();

  switch (this->_type) {
    case Bgp4_Attribute_Origin:
      this->_value._origin = bgp4Attr.Origin();
      break;
      
    case Bgp4_Attribute_AsPath:
      this->_value._asPath = new ArtsBgp4AsPathAttribute;
      *(this->_value._asPath) = *(bgp4Attr.AsPath());
      break;
      
    case Bgp4_Attribute_NextHop:
      this->_value._nextHop = bgp4Attr.NextHop();
      break;
      
    case Bgp4_Attribute_MultiExitDisc:
      this->_value._MED = bgp4Attr.MED();
      break;
      
    case Bgp4_Attribute_LocalPref:
      this->_value._localPref = bgp4Attr.LocalPref();
      break;
      
    case Bgp4_Attribute_AtomicAggregate:
      break;
      
    case Bgp4_Attribute_Aggregator:
      this->_value._aggregator = new ArtsBgp4AggregatorAttribute;
      *(this->_value._aggregator) = *(bgp4Attr.Aggregator());
      break;
      
    case Bgp4_Attribute_Community:
      this->_value._community = new vector<uint32_t>(*(bgp4Attr.Community()));
      break;
      
    case Bgp4_Attribute_DPA:
      this->_value._dp = new ArtsBgp4DPAttribute;
      *(this->_value._dp) = *(bgp4Attr.DP());
      break;
      
    case Bgp4_Attribute_MPReachNLRI:
      break;
      
    case Bgp4_Attribute_MPUnreachNLRI:
      break;
      
    default:
      break;
  }
  return(*this);
  
}

//----------------------------------------------------------------------------
//      uint16_t ArtsBgp4Attribute::Length(uint8_t version) const      
//............................................................................
//  
//----------------------------------------------------------------------------
uint16_t ArtsBgp4Attribute::Length(uint8_t version) const
{
  uint16_t  length = sizeof(this->_flags) + sizeof(this->_type);
  switch (this->_type) {
    case Bgp4_Attribute_Origin:
      length += sizeof(this->_value._origin);
      break;
    case Bgp4_Attribute_AsPath:
      length += this->_value._asPath->Length();
      break;
    case Bgp4_Attribute_NextHop:
      length += sizeof(this->_value._nextHop);
      break;
    case Bgp4_Attribute_MultiExitDisc:
      length += sizeof(this->_value._MED);
      break;
    case Bgp4_Attribute_LocalPref:
      length += sizeof(this->_value._localPref);
      break;
    case Bgp4_Attribute_AtomicAggregate:
      break;
    case Bgp4_Attribute_Aggregator:
      length += this->_value._aggregator->Length();
      break;
    case Bgp4_Attribute_Community:
      length += sizeof(uint8_t) +
        (this->_value._community->size() * sizeof(uint32_t));
      break;
    case Bgp4_Attribute_DPA:
      length += this->_value._dp->Length();
      break;
    case Bgp4_Attribute_MPReachNLRI:
      break;
    case Bgp4_Attribute_MPUnreachNLRI:
      break;
    default:
      break;
  }
  return(length);
}

//----------------------------------------------------------------------------
//      ostream & operator << (ostream& os,                   
//                             const ArtsBgp4Attribute & bgp4Attribute) 
//............................................................................
//  
//----------------------------------------------------------------------------
ostream & operator << (ostream& os,
                       const ArtsBgp4Attribute & bgp4Attribute)
{
  os << "\t\t\tBGP4 ATTRIBUTE" << endl;
  os << "\t\t\t\tflags: 0x"
     << hex << (int)bgp4Attribute.Flags() << dec << endl;
  os << "\t\t\t\ttype: 0x"
     << hex << (int)bgp4Attribute.Type() << dec << endl;

  struct in_addr  inAddr;
  
  switch (bgp4Attribute.Type()) {
    case Bgp4_Attribute_Origin:
      os << "\t\t\t\torigin: " << (int)bgp4Attribute.Origin() << endl;
      break;
    case Bgp4_Attribute_AsPath:
      if (bgp4Attribute.AsPath()) {
        os << "\t\t\t\tAS path: ";
        os << *(bgp4Attribute.AsPath()) << endl;
      }
      break;
    case Bgp4_Attribute_NextHop:
      inAddr.s_addr = bgp4Attribute.NextHop();
      os << "\t\t\t\tnexthop: " << inet_ntoa(inAddr) << endl;
      break;
    case Bgp4_Attribute_MultiExitDisc:
      break;
    case Bgp4_Attribute_LocalPref:
      break;
    case Bgp4_Attribute_AtomicAggregate:
      break;
    case Bgp4_Attribute_Aggregator:
      break;
    case Bgp4_Attribute_Community:
      break;
    case Bgp4_Attribute_DPA:
      break;
    case Bgp4_Attribute_MPReachNLRI:
      break;
    case Bgp4_Attribute_MPUnreachNLRI:
      break;
    default:
      break;
  }
  return(os);
}

uint32_t  ArtsBgp4Attribute::_numObjects = 0;
