Boost logo

Boost Users :

Subject: [Boost-users] [ASIO] Patch to support ATM sockets
From: Casimiro, Daniel C CIV NUWC NWPT (daniel.casimiro_at_[hidden])
Date: 2012-07-20 11:22:06


Hi,

These classes and examples add basic ATM support to ASIO. It works with MS
visual
studio 2010 (Windows XP) and gcc 4.1.2 (Linux CentOS 5.8), but it isn't
always pretty. I only implemented and tested PVC's.

~Dan
---------------------------

// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//

#ifndef BOOST_STDAFX_HEAD
#define BOOST_STDAFX_HEAD

#ifdef _WIN32
#include "targetver.h"

#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from
Windows headers
#endif

#ifdef HAVE_ASIO_ATM
// I forward declare my version of boost::asio::detail::socket_ops::bind so
that
// gcc 4.1.2 picks it up and uses it.
// Otherwise, gcc doesn't consider my version; I'm not sure why.
#include <boost/variant/variant_fwd.hpp>

namespace boost {
  namespace system {
    class error_code;
  }
}
namespace boost {
  namespace asio {
    namespace atm {
      namespace detail {

        struct atmpvc_endpoint_type;
        struct atmsvc_endpoint_type;

      }
    }
  }
}
namespace boost {
  namespace asio {
    namespace detail {
      namespace socket_ops {
         int bind(int s,
                 const
boost::variant<boost::asio::atm::detail::atmpvc_endpoint_type,
                 boost::asio::atm::detail::atmsvc_endpoint_type>* addr,
                 size_t addrlen,
                 boost::system::error_code& ec);
      }
    }
  }
}
#endif
#include <boost/asio.hpp>
#endif // BOOST_STDAFX_HEAD

// Example echo server with ATM sockets
// async_atm_echo_server.cpp : Defines the entry point for the console
application.
//

#include "stdafx.h"
#include <cstdlib>
#include <iostream>
#include <string>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include "boost/asio/atm/aal.hpp"

using namespace boost::asio::atm;

class server {
public:
        server(boost::asio::io_service& io_service, const std::string &a)
                : io_service_(io_service)
                , socket_(io_service, aal::endpoint(address::from_string(a),
qos::ubr_settings(1024u)))
                , data_()
        {
                socket_.async_receive(
                        boost::asio::buffer(data_, max_length),
                        boost::bind(&server::handle_receive_from, this,
                                boost::asio::placeholders::error,
 
boost::asio::placeholders::bytes_transferred));
        }

        void handle_receive_from(const boost::system::error_code& error,
size_t bytes_recvd)
        {
                if (!error && bytes_recvd > 0) {
                        socket_.async_send(
                                boost::asio::buffer(data_, bytes_recvd),
                                boost::bind(&server::handle_send_to, this,
                                        boost::asio::placeholders::error,
 
boost::asio::placeholders::bytes_transferred));
                } else {
                        socket_.async_receive(
                                boost::asio::buffer(data_, max_length),
                                boost::bind(&server::handle_receive_from,
this,
                                        boost::asio::placeholders::error,
 
boost::asio::placeholders::bytes_transferred));
                }
        }

        void handle_send_to(const boost::system::error_code& /*error*/,
size_t /*bytes_sent*/)
        {
                socket_.async_receive(
                        boost::asio::buffer(data_, max_length),
                        boost::bind(&server::handle_receive_from, this,
                                boost::asio::placeholders::error,
 
boost::asio::placeholders::bytes_transferred));
        }
private:
        boost::asio::io_service& io_service_;
        aal::socket socket_;
        enum { max_length = 1024 };
        char data_[max_length];
};

int
main(int argc, char** argv)
{
        try {
                if (argc != 2) {
                        std::cerr << "Usage: async_atm_echo_server
<address>\n";
                        return 1;
                }
                boost::asio::io_service io_service;
                server s(io_service, argv[1]);

                io_service.run();
        } catch (const std::exception& e) {
                std::cerr << "Exception: " << e.what() << "\n";
        }
        return 0;
}

// Example echo client with ATM sockets
// blocking_atm_echo_client.cpp : Defines the entry point for the console
application.
//

#include "stdafx.h"
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <boost/asio.hpp>
#include "boost/asio/atm/aal.hpp"

using namespace boost::asio::atm;

enum { max_length = 1024 };

int
main(int argc, char** argv)
{
        try {
                if (argc != 2) {
                        std::cerr << "Usage: blocking_atm_echo_client
<address>\n";
                        return 1;
                }

                boost::asio::io_service io_service;

                aal::socket s(io_service,
aal::endpoint(address_pvc::from_string(argv[1]), qos::ubr_settings(1024u)));

                using namespace std; // for strlen
                std::cout << "Enter message: ";
                char request[max_length];
                std::cin.getline(request, max_length);
                size_t request_length = strlen(request);
                s.send(boost::asio::buffer(request, request_length));

                char reply[max_length];
                size_t reply_length = s.receive(boost::asio::buffer(reply,
max_length));
                std::cout << "Reply is: ";
                std::cout.write(reply, reply_length);
                std::cout << "\n";
        } catch (const std::exception& e) {
                std::cerr << "Exception: " << e.what() << "\n";
        }
        return 0;
}

/// \file boost/asio/atm/aal.hpp
/// UNCLASSIFIED
/// \brief Asynchronous Transfer Mode support for Boost ASIO
#ifndef BOOST_ASIO_ATM_AAL_HEAD
#define BOOST_ASIO_ATM_AAL_HEAD

#ifdef HAVE_ASIO_ATM

#include <boost/asio.hpp>
#include <boost/variant.hpp>
#include "basic_endpoint.hpp"

namespace boost {
namespace asio {
using boost::asio::basic_raw_socket;
namespace atm {

/// \brief ATM Adaptation Layer
template <class Implementation>
class basic_aal {
public:
        typedef Implementation implementation_type;
        /// The type of a ATM endpoint.
        typedef basic_endpoint<basic_aal> endpoint;

        static basic_aal aal5_pvc()
        {
                return basic_aal(implementation_type::aal5_protocol(),
implementation_type::pvc_family());
        }

        static basic_aal aal5_svc()
        {
                return basic_aal(implementation_type::aal5_protocol(),
implementation_type::svc_family());
        }

        /// Obtain an identifier for the type of the protocol.
        int type() const
        {
                // windows only support SOCK_RAW
                // The Linux examples use SOCK_DGRAM; is there a difference
at application
                // level for AAL5 sockets? Can Linux use SOCK_RAW?
                return implementation_type::socket_type();
        }

        /// Obtain an identifier for the protocol.
        int protocol() const
        {
                return protocol_;
        }

        /// Obtain an identifier for the protocol family.
        int family() const
        {
                return family_;
        }

        /// The ATM/AAL socket type.
        typedef basic_raw_socket<basic_aal> socket;

        /// The ATM/AAL resolver type.
        //typedef basic_resolver<atm> resolver;

        /// Compare two protocols for equality.
        friend bool operator==(const basic_aal& p1, const basic_aal& p2)
        {
                return p1.protocol_ == p2.protocol_
                        && p1.family_ == p2.family_
                        ;
        }

        /// Compare two protocols for inequality.
        friend bool operator!=(const basic_aal& p1, const basic_aal& p2)
        {
                return p1.protocol_ != p2.protocol_
                        || p1.family_ != p2.family_
                        ;
        }

private:
        // Construct with a specific protocol.
        explicit basic_aal(const int protocol, const int family)
                : protocol_(protocol)
                , family_(family)
        {
        }

        int protocol_;
        int family_;
}; // class basic_aal

#if defined BOOST_WINDOWS || defined(__CYGWIN__)

struct windows_atm {
        static int aal5_protocol()
        {
                return ATMPROTO_AAL5;
        }

        static int socket_type()
        {
                return SOCK_RAW;
        }

        static int pvc_family()
        {
                return AF_ATM;
        }

        static int svc_family()
        {
                return AF_ATM;
        }

        /// is this legal?
        //typedef template <class Protocol> basic_raw_socket
socket_template;
}; // windows_atm
typedef basic_aal<windows_atm> aal;
#else
struct bsd_atm {
        static int aal5_protocol()
        {
                return 0;
        }

        static int socket_type()
        {
                return SOCK_RAW;
        }

        static int pvc_family()
        {
                return AF_ATMPVC;
        }

        static int svc_family()
        {
                return AF_ATMSVC;
        }

        /// is this legal?
        //typedef template <class Protocol> basic_raw_socket
socket_template;
}; // bsd_atm
typedef basic_aal<bsd_atm> aal;
#endif
} // namespace atm
} // namespace asio
} // namespace boost

#endif // HAVE_ASIO_ATM
#endif // BOOST_ASIO_ATM_AAL_HEAD

/// \file boost/asio/atm/address.hpp
/// UNCLASSIFIED
/// \brief Asynchronous Transfer Mode address for Boost ASIO
#ifndef BOOST_ASIO_ATM_ADDRESS_HEAD
#define BOOST_ASIO_ATM_ADDRESS_HEAD

#include <string>
#include <boost/asio.hpp>
#include "address_pvc.hpp"
#include "address_svc.hpp"

namespace boost {
namespace asio {
namespace atm {
using boost::system::error_code;

class address {
public:
        address()
                : type_(pvc)
                , pvc_address_()
                , svc_address_()
        {
        }

        address(const address_pvc &pvc_address)
                : type_(pvc)
                , pvc_address_(pvc_address)
                , svc_address_()
        {
        }

        address(const address_svc &svc_address)
                : type_(svc)
                , pvc_address_()
                , svc_address_(svc_address)
        {
        }

        address(const address &other)
                : type_(other.type_)
                , pvc_address_(other.pvc_address_)
                , svc_address_(other.svc_address_)
        {
        }

        bool is_pvc() const { return type_ == pvc; }
        bool is_svc() const { return type_ == svc; }

        const address_pvc& to_pvc() const
        {
                return pvc_address_;
        }

        const address_svc& to_svc() const
        {
                return svc_address_;
        }

        std::string to_string() const
        {
                if (is_pvc()) {
                        return pvc_address_.to_string();
                }
                return svc_address_.to_string();
        }

        std::string to_string(error_code &error) const
        {
                if (is_pvc()) {
                        return pvc_address_.to_string(error);
                }
                return svc_address_.to_string(error);
        }

        static address from_string(const char * str)
        {
                error_code error;
                const address addr = from_string(str, error);
                boost::asio::detail::throw_error(error);
                return addr;
        }

        static address from_string(const char * str, error_code &error)
        {
                const address_pvc pvc_address =
address_pvc::from_string(str, error);
                if (!error) {
                        return address(pvc_address);
                }

                const address_svc svc_address =
address_svc::from_string(str, error);
                if (!error) {
                        return address(svc_address);
                }

                return address();
        }

        static address from_string(const std::string &str)
        {
                return from_string(str.c_str());
        }

        static address from_string(const std::string &str, error_code
&error)
        {
                return from_string(str.c_str(), error);
        }

        /// Compare two addresses for equality.
        friend bool operator==(const address& a1, const address& a2)
        {
                if (a1.type_ != a2.type_) {
                        return false;
                }
                if (a1.type_ == pvc) {
                        return a1.pvc_address_ == a2.pvc_address_;
                }
                return a1.svc_address_ == a2.svc_address_;
        }

        /// Compare two addresses for inequality.
        friend bool operator!=(const address& a1, const address& a2)
        {
                return !(a1 == a2);
        }

        /// Compare addresses for ordering.
        friend bool operator<(const address& a1, const address& a2)
        {
                if (a1.type_ < a2.type_) {
                        return true;
                }
                if (a1.type_ > a2.type_) {
                        return false;
                }
                if (a1.type_ == pvc) {
                        return a1.pvc_address_ < a2.pvc_address_;
                }
                return a1.svc_address_ < a2.svc_address_;
        }

        /// Compare addresses for ordering.
        friend bool operator>(const address& a1, const address& a2)
        {
                return a2 < a1;
        }

        /// Compare addresses for ordering.
        friend bool operator<=(const address& a1, const address& a2)
        {
                return !(a2 < a1);
        }

        /// Compare addresses for ordering.
        friend bool operator>=(const address& a1, const address& a2)
        {
                return !(a1 < a2);
        }
private:
        enum { svc, pvc } type_;
        address_pvc pvc_address_;
        address_svc svc_address_;
}; // class address

#if !defined(BOOST_NO_IOSTREAM)

/// Output an address as a string.
/**
 * Used to output a human-readable string for a specified address.
 *
 * @param os The output stream to which the string will be written.
 *
 * @param addr The address to be written.
 *
 * @return The output stream.
 *
 * @relates boost::asio::atm::address_pvc
 */
template <typename Elem, typename Traits>
std::basic_ostream<Elem, Traits>& operator<<(
    std::basic_ostream<Elem, Traits>& os, const address& addr);

#endif // !defined(BOOST_NO_IOSTREAM)

} // namespace atm
} // namespace asio
} // namespace boost
#endif // BOOST_ASIO_ATM_ADDRESS_HEAD

/// \file boost/asio/atm/address_pvc.hpp
/// UNCLASSIFIED
/// \brief Asynchronous Transfer Mode PVC address for Boost ASIO
#ifndef BOOST_ASIO_ATM_ADDRESS_PVC_HEAD
#define BOOST_ASIO_ATM_ADDRESS_PVC_HEAD

#include <string>
#include <vector>
#include <sstream>
#include <boost/asio.hpp>
#include <boost/algorithm/string.hpp>
#include "detail/socket_types.hpp"
#include "detail/socket_ops.hpp"

namespace boost {
namespace asio {
namespace atm {
using boost::system::error_code;

class address_pvc {
public:
        address_pvc()
                : addr_()
        {
                detail::socket_ops::initialize(addr_);
        }

        address_pvc(const address_pvc &other)
                : addr_(other.addr_)
        {
        }

        address_pvc(const detail::atmpvc_addr_type &a)
                : addr_(a)
        {
        }

        address_pvc(const unsigned long vpi, const unsigned long vci)
                : addr_()
        {
                detail::socket_ops::initialize(addr_);
                set_vpi(vpi);
                set_vci(vci);
        }

        unsigned long itf() const
        {
                return detail::socket_ops::itf(addr_);
        }

        void set_itf(const unsigned long i)
        {
                return detail::socket_ops::set_itf(i, addr_);
        }

        unsigned long vpi() const
        {
                return detail::socket_ops::vpi(addr_);
        }

        void set_vpi(const unsigned long v)
        {
                return detail::socket_ops::set_vpi(v, addr_);
        }

        unsigned long vci() const
        {
                return detail::socket_ops::vci(addr_);
        }

        void set_vci(const unsigned long v)
        {
                return detail::socket_ops::set_vci(v, addr_);
        }

        const detail::atmpvc_addr_type* data() const
        {
                return &addr_;
        }

        std::string to_string() const
        {
                error_code error;
                const std::string str = to_string(error);
                boost::asio::detail::throw_error(error);
                return str;
        }

        std::string to_string(error_code &error) const
        {
                std::ostringstream strm;
                strm << itf() << "." << vpi() << "." << vci();
                return strm.str();
        }

        static address_pvc from_string(const char *str)
        {
                error_code error;
                const address_pvc addr = from_string(str, error);
                boost::asio::detail::throw_error(error);
                return addr;
        }

        static address_pvc from_string(const char *str, error_code &error)
        {
                return from_string(std::string(str), error);
        }

        static address_pvc from_string(const std::string &str)
        {
                return from_string(str.c_str());
        }

        static address_pvc from_string(const std::string &str, error_code
&error)
        {
                typedef std::vector<std::string> container;
                address_pvc addr;
                container tokens;
                boost::split(tokens, str, boost::is_any_of("."));
                if (tokens.empty()) {
                        tokens.push_back(str);
                }
                container::const_reverse_iterator i = tokens.rbegin();
                // Read the VCI first
                std::istringstream vci_strm(*i);
                unsigned long vci;
                if (!(vci_strm >> vci)) {
                        error = boost::asio::error::invalid_argument;
                        return addr;
                }
                addr.set_vci(vci);
                advance(i, 1);
                if (i == tokens.rend()) {
                        return addr;
                }
                // Read the VPI
                std::istringstream vpi_strm(*i);
                unsigned long vpi;
                if (!(vpi_strm >> vpi)) {
                        error = boost::asio::error::invalid_argument;
                        return addr;
                }
                addr.set_vpi(vpi);
                advance(i, 1);
                if (i == tokens.rend()) {
                        return addr;
                }
                // Read the ITF
                std::istringstream itf_strm(*i);
                unsigned long itf;
                if (!(itf_strm >> itf)) {
                        error = boost::asio::error::invalid_argument;
                        return addr;
                }
                addr.set_itf(itf);
                advance(i, 1);
                if (i != tokens.rend()) {
                        error = boost::asio::error::invalid_argument;
                }
                return addr;
        }

        /// Compare two addresses for equality.
        friend bool operator==(const address_pvc& a1, const address_pvc& a2)
        {
                return a1.itf() == a2.itf()
                        && a1.vpi() == a2.vpi()
                        && a2.vci() == a2.vci()
                        ;
        }

        /// Compare two address_pvces for inequality.
        friend bool operator!=(const address_pvc& a1, const address_pvc& a2)
        {
                return !(a1 == a2);
        }

        /// Compare address_pvces for ordering.
        friend bool operator<(const address_pvc& a1, const address_pvc& a2)
        {
                if (a1.itf() < a2.itf()) {
                        return true;
                }
                if (a1.itf() > a2.itf()) {
                        return false;
                }
                if (a1.vpi() < a2.vpi()) {
                        return true;
                }
                if (a1.vpi() > a2.vpi()) {
                        return false;
                }
                return a1.vci() < a2.vci();
        }

        /// Compare address_pvces for ordering.
        friend bool operator>(const address_pvc& a1, const address_pvc& a2)
        {
                return a2 < a1;
        }

        /// Compare address_pvces for ordering.
        friend bool operator<=(const address_pvc& a1, const address_pvc& a2)
        {
                return !(a2 < a1);
        }

        /// Compare address_pvces for ordering.
        friend bool operator>=(const address_pvc& a1, const address_pvc& a2)
        {
                return !(a1 < a2);
        }
private:
        detail::atmpvc_addr_type addr_;
}; // class address_pvc

#if !defined(BOOST_NO_IOSTREAM)

/// Output an address as a string.
/**
 * Used to output a human-readable string for a specified address.
 *
 * @param os The output stream to which the string will be written.
 *
 * @param addr The address to be written.
 *
 * @return The output stream.
 *
 * @relates boost::asio::atm::address_pvc
 */
template <typename Elem, typename Traits>
std::basic_ostream<Elem, Traits>& operator<<(
    std::basic_ostream<Elem, Traits>& os, const address_pvc& addr);

#endif // !defined(BOOST_NO_IOSTREAM)
} // namespace atm
} // namespace asio
} // namespace boost
#endif // BOOST_ASIO_ATM_ADDRESS_PVC_HEAD

/// \file boost/asio/atm/address_svc.hpp
/// UNCLASSIFIED
/// \brief Asynchronous Transfer Mode SVC address for Boost ASIO
#ifndef BOOST_ASIO_ATM_ADDRESS_SVC_HEAD
#define BOOST_ASIO_ATM_ADDRESS_SVC_HEAD

#include <string>
#include <boost/asio.hpp>
#include "detail/socket_types.hpp"

namespace boost {
namespace asio {
namespace atm {
using boost::system::error_code;

class address_svc {
public:
        address_svc()
                : addr_()
        {
        }

        address_svc(const detail::atmsvc_addr_type& a)
                : addr_(a)
        {
        }

        address_svc(const address_svc &other)
                : addr_(other.addr_)
        {
        }

        const detail::atmsvc_addr_type* data() const
        {
                return &addr_;
        }

        std::string to_string() const
        {
                error_code error;
                const std::string str = to_string(error);
                boost::asio::detail::throw_error(error);
                return str;
        }

        std::string to_string(error_code &error) const
        {
                return "";
        }

        static address_svc from_string(const char *str)
        {
                error_code error;
                const address_svc addr = from_string(str, error);
                boost::asio::detail::throw_error(error);
                return addr;
        }

        static address_svc from_string(const char *str, error_code &error)
        {
                address_svc addr;
                return addr;
        }

        static address_svc from_string(const std::string &str)
        {
                return from_string(str.c_str());
        }

        static address_svc from_string(const std::string &str, error_code
&error)
        {
                return from_string(str.c_str(), error);
        }

        /// Compare two addresses for equality.
        friend bool operator==(const address_svc& a1, const address_svc& a2)
        {
                return false;
        }

        /// Compare two address_svces for inequality.
        friend bool operator!=(const address_svc& a1, const address_svc& a2)
        {
                return !(a1 == a2);
        }

        /// Compare address_svces for ordering.
        friend bool operator<(const address_svc& a1, const address_svc& a2)
        {
                return false;
        }

        /// Compare address_svces for ordering.
        friend bool operator>(const address_svc& a1, const address_svc& a2)
        {
                return a2 < a1;
        }

        /// Compare address_svces for ordering.
        friend bool operator<=(const address_svc& a1, const address_svc& a2)
        {
                return !(a2 < a1);
        }

        /// Compare address_svces for ordering.
        friend bool operator>=(const address_svc& a1, const address_svc& a2)
        {
                return !(a1 < a2);
        }
private:
        detail::atmsvc_addr_type addr_;
}; // class address_svc

#if !defined(BOOST_NO_IOSTREAM)

/// Output an address as a string.
/**
 * Used to output a human-readable string for a specified address.
 *
 * @param os The output stream to which the string will be written.
 *
 * @param addr The address to be written.
 *
 * @return The output stream.
 *
 * @relates boost::asio::atm::address_svc
 */
template <typename Elem, typename Traits>
std::basic_ostream<Elem, Traits>& operator<<(
    std::basic_ostream<Elem, Traits>& os, const address_svc& addr);

#endif // !defined(BOOST_NO_IOSTREAM)
} // namespace atm
} // namespace asio
} // namespace boost
#endif // BOOST_ASIO_ATM_ADDRESS_SVC_HEAD

/// \file boost/asio/atm/basic_endpoint.hpp
/// UNCLASSIFIED
/// \brief Endpoint for ATM sockets
#ifndef BOOST_ASIO_ATM_BASIC_ENDPOINT_HEAD
#define BOOST_ASIO_ATM_BASIC_ENDPOINT_HEAD
#include <boost/asio.hpp>
#include "address.hpp"
#include "qos.hpp"
#include "detail/endpoint.hpp"

namespace boost {
namespace asio {
namespace atm {

template <typename AsynchronousTransferModeProtocol>
class basic_endpoint {
public:
        /// The protocol type associated with the endpoint.
        typedef AsynchronousTransferModeProtocol protocol_type;

        /// The type of the endpoint structure. This type is dependent on
the
        /// underlying implementation of the socket layer.
        typedef boost::asio::atm::detail::endpoint endpoint_impl;
        typedef endpoint_impl::data_type data_type;

        /// Default constructor.
        basic_endpoint()
                : impl_()
        {
        }

        /// Construct an endpoint using an ATM address. This
        /// constructor may be used for accepting connections on a specific
interface
        /// or for making a connection to a remote endpoint.
        basic_endpoint(const boost::asio::atm::address& addr)
                : impl_(addr)
        {
        }

        /// Construct an endpoint using an ATM address and Quality Of
Service settings. This
        /// constructor may be used for accepting connections on a specific
interface
        /// or for making a connection to a remote endpoint.
        basic_endpoint(const boost::asio::atm::address& addr, const
qos::settings &qos)
                : impl_(addr, qos)
        {
        }

        /// Copy constructor.
        basic_endpoint(const basic_endpoint& other)
                : impl_(other.impl_)
        {
        }

#if defined(BOOST_ASIO_HAS_MOVE)
        /// Move constructor.
        basic_endpoint(basic_endpoint&& other)
                : impl_(other.impl_)
        {
        }
#endif // defined(BOOST_ASIO_HAS_MOVE)

        /// Assign from another endpoint.
        basic_endpoint& operator=(const basic_endpoint& other)
        {
                impl_ = other.impl_;
                return *this;
        }

#if defined(BOOST_ASIO_HAS_MOVE)
        /// Move-assign from another endpoint.
        basic_endpoint& operator=(basic_endpoint&& other)
        {
                impl_ = other.impl_;
                return *this;
        }
#endif // defined(BOOST_ASIO_HAS_MOVE)

        /// The protocol associated with the endpoint.
        protocol_type protocol() const
        {
                if (is_svc()) {
                        return AsynchronousTransferModeProtocol::aal5_svc();
                }
                return AsynchronousTransferModeProtocol::aal5_pvc();
        }

        bool is_pvc() const
        {
                return impl_.is_pvc();
        }

        bool is_svc() const
        {
                return impl_.is_svc();
        }

        /// Get the underlying endpoint in the native type.
        data_type* data()
        {
                return impl_.data();
        }

        /// Get the underlying endpoint in the native type.
        const data_type* data() const
        {
                return impl_.data();
        }

        /// Get the underlying size of the endpoint in the native type.
        std::size_t size() const
        {
                return impl_.size();
        }

        /// Set the underlying size of the endpoint in the native type.
        void resize(std::size_t new_size)
        {
                return impl_.resize(new_size);
        }

        /// Get the capacity of the endpoint in the native type.
        std::size_t capacity() const
        {
                return impl_.capacity();
        }

        /// Get the IP address associated with the endpoint.
        const boost::asio::atm::address address() const
        {
                return impl_.address();
        }

        /// Set the IP address associated with the endpoint.
        void address(const boost::asio::atm::address& addr)
        {
                impl_.address(addr);
        }

        /// Compare two endpoints for equality.
        friend bool operator==(const
basic_endpoint<AsynchronousTransferModeProtocol>& e1,
                const basic_endpoint<AsynchronousTransferModeProtocol>& e2)
        {
                return e1.impl_ == e2.impl_;
        }

        /// Compare two endpoints for inequality.
        friend bool operator!=(const
basic_endpoint<AsynchronousTransferModeProtocol>& e1,
                const basic_endpoint<AsynchronousTransferModeProtocol>& e2)
        {
                return !(e1 == e2);
        }

        /// Compare endpoints for ordering.
        friend bool operator<(const
basic_endpoint<AsynchronousTransferModeProtocol>& e1,
                const basic_endpoint<AsynchronousTransferModeProtocol>& e2)
        {
                return e1.impl_ < e2.impl_;
        }

        /// Compare endpoints for ordering.
        friend bool operator>(const
basic_endpoint<AsynchronousTransferModeProtocol>& e1,
                const basic_endpoint<AsynchronousTransferModeProtocol>& e2)
        {
                return e2.impl_ < e1.impl_;
        }

        /// Compare endpoints for ordering.
        friend bool operator<=(const
basic_endpoint<AsynchronousTransferModeProtocol>& e1,
                const basic_endpoint<AsynchronousTransferModeProtocol>& e2)
        {
                return !(e2 < e1);
        }

        /// Compare endpoints for ordering.
        friend bool operator>=(const
basic_endpoint<AsynchronousTransferModeProtocol>& e1,
                const basic_endpoint<AsynchronousTransferModeProtocol>& e2)
        {
                return !(e1 < e2);
        }

private:
        // The underlying ATM endpoint.
        endpoint_impl impl_;
}; // class basic_endpoint

#if !defined(BOOST_NO_IOSTREAM)

/// Output an endpoint as a string.
/**
* Used to output a human-readable string for a specified endpoint.
*
* @param os The output stream to which the string will be written.
*
* @param endpoint The endpoint to be written.
*
* @return The output stream.
*
* @relates boost::asio::atm::basic_endpoint
*/
template <typename Elem, typename Traits, typename
AsynchronousTransferModeProtocol>
std::basic_ostream<Elem, Traits>& operator<<(
        std::basic_ostream<Elem, Traits>& os,
        const basic_endpoint<AsynchronousTransferModeProtocol>& endpoint);

#endif // !defined(BOOST_NO_IOSTREAM)
} // namespace atm
} // namespace asio
} // namespace boost
#include "basic_endpoint.ipp"
#endif // BOOST_ASIO_ATM_BASIC_ENDPOINT_HEAD

/// \file boost/asio/atm/basic_endpoint.ipp
/// UNCLASSIFIED
#ifndef BOOST_ASIO_ATM_BASIC_ENDPOINT_IMPL
#define BOOST_ASIO_ATM_BASIC_ENDPOINT_IMPL
#include "address.hpp"
namespace boost {
namespace asio {
namespace atm {

template <typename Elem, typename Traits>
std::basic_ostream<Elem, Traits>& operator<<(std::basic_ostream<Elem,
Traits>& os, const address_pvc& addr)
{
        if (os) {
                os << addr.to_string();
        }
        return os;
}

template <typename Elem, typename Traits>
std::basic_ostream<Elem, Traits>& operator<<(std::basic_ostream<Elem,
Traits>& os, const address& addr)
{
        if (os) {
                os << addr.to_string();
        }
        return os;
}

#if !defined(BOOST_NO_IOSTREAM)
template <typename Elem, typename Traits, typename
AsynchronousTransferModeProtocol>
std::basic_ostream<Elem, Traits>& operator<<(
        std::basic_ostream<Elem, Traits>& os,
        const basic_endpoint<AsynchronousTransferModeProtocol>& endpoint)
{
        if (os) {
                os << endpoint.address();
        }
        return os;
}
#endif // !defined(BOOST_NO_IOSTREAM)
} // namespace atm
} // namespace asio
} // namespace boost
#endif // BOOST_ASIO_ATM_BASIC_ENDPOINT_IMPL

/// \file boost/asio/atm/qos.hpp
/// UNCLASSIFIED
/// \brief Asynchronous Transfer Mode QOS for Boost ASIO
#ifndef BOOST_ASIO_ATM_QOS_HEAD
#define BOOST_ASIO_ATM_QOS_HEAD

#include <boost/variant.hpp>
#include "detail/socket_types.hpp"

namespace boost {
namespace asio {
namespace atm {
namespace qos {
struct do_not_use_qos {
        do_not_use_qos() { }
};

struct ubr_settings {
        unsigned long peak_cell_rate;
        ubr_settings() : peak_cell_rate(0u) { }
        ubr_settings(const unsigned long r) : peak_cell_rate(r) { }
};

struct cbr_settings {
        unsigned long peak_cell_rate;
        cbr_settings() : peak_cell_rate(0u) { }
};

struct vbr_settings {
        unsigned long peak_cell_rate;
        unsigned long substainable_cell_rate;
        unsigned long max_burst_size;
        vbr_settings() : peak_cell_rate(0u), substainable_cell_rate(0u),
max_burst_size(0u) { }
};

struct abr_settings {
        unsigned long peak_cell_rate;
        unsigned long minimum_cell_rate;
        unsigned long allowed_cell_rate;
        unsigned long initial_cell_rate;
        unsigned long rate_increase_factor;
        unsigned long rate_decrease_factor;
        unsigned long cut_off_decrease_factor;
        abr_settings()
                : peak_cell_rate(0u)
                , minimum_cell_rate(0u)
                , allowed_cell_rate(0u)
                , initial_cell_rate(0u)
                , rate_increase_factor(0u)
                , rate_decrease_factor(0u)
                , cut_off_decrease_factor(0u)
        {
        }
};

typedef boost::variant<do_not_use_qos, ubr_settings, cbr_settings,
vbr_settings, abr_settings> settings;

} // namespace qos
} // namespace atm
} // namespace asio
} // namespace boost
#include "detail/qos.hpp"
#endif // BOOST_ASIO_ATM_QOS_HEAD

/// \file boost/asio/atm/detail/endpoint.hpp
/// UNCLASSIFIED
/// \brief Endpoint for ATM sockets
#ifndef BOOST_ASIO_ATM_DETAIL_ENDPOINT_HEAD
#define BOOST_ASIO_ATM_DETAIL_ENDPOINT_HEAD
#include <boost/asio.hpp>
#include <boost/variant.hpp>
#include "boost/asio/atm/address.hpp"
#include "boost/asio/atm/detail/socket_types.hpp"
#include "boost/asio/atm/qos.hpp"

namespace boost {
namespace asio {
namespace atm {
namespace detail {
class endpoint_data_size_visitor : public boost::static_visitor<std::size_t>
{
public:
        std::size_t operator()(const atmpvc_endpoint_type& params) const
        {
                return sizeof(atmpvc_endpoint_type);
        }

        std::size_t operator()(const atmsvc_endpoint_type &ep) const
        {
                return sizeof(atmsvc_endpoint_type);
        }
}; // class endpoint_data_size_visitor

class endpoint_address_visitor : public
boost::static_visitor<boost::asio::atm::address> {
public:
        boost::asio::atm::address operator()(const atmpvc_endpoint_type& ep)
const
        {
                return
boost::asio::atm::address_pvc(ep.native_connection_id());
        }

        boost::asio::atm::address operator()(const atmsvc_endpoint_type &ep)
const
        {
                return
boost::asio::atm::address_svc(ep.native_connection_id());
        }
}; // class endpoint_data_size_visitor

class endpoint {
public:
        typedef boost::asio::atm::detail::atm_endpoint_type data_type;

        endpoint()
                : data_()
                , qos_()
        {
        }

        /// \todo Add QOS parameters to this constructor
        endpoint(const boost::asio::atm::address& addr, const qos::settings
&qos = qos::do_not_use_qos())
                : data_()
                , qos_(qos)
        {
                address(addr);
        }

        bool is_pvc() const
        {
                return boost::get<atmpvc_endpoint_type*>(&data_) != NULL;
        }

        bool is_svc() const
        {
                return boost::get<atmsvc_endpoint_type*>(&data_) != NULL;
        }

        /// Get the underlying endpoint in the native type.
        data_type* data()
        {
                return &data_;
        }

        /// Get the underlying endpoint in the native type.
        const data_type* data() const
        {
                return &data_;
        }

        std::size_t size() const
        {
                return boost::apply_visitor(endpoint_data_size_visitor(),
data_);
        }

        void resize(const std::size_t new_size)
        {
                if (new_size > sizeof(data_type)) {
                        boost::system::error_code
ec(boost::asio::error::invalid_argument);
                        boost::asio::detail::throw_error(ec);
                }
        }

        std::size_t capacity() const
        {
                return sizeof(data_type);
        }

        boost::asio::atm::address address() const
        {
                return boost::apply_visitor(endpoint_address_visitor(),
data_);
        }

        void address(const boost::asio::atm::address& addr)
        {
                if (addr.is_pvc()) {
                        const address_pvc my_pvc_addr = addr.to_pvc();
                        atmpvc_endpoint_type my_data;

 
boost::apply_visitor(boost::asio::atm::qos::detail::pvc_visitor(my_data),
qos_);
                        my_data.assign(*my_pvc_addr.data());
                        data_ = my_data;
                }
        }

        friend bool operator==(const endpoint& e1, const endpoint& e2)
        {
                return e1.address() == e2.address();
        }

        /// Compare endpoints for ordering.
        friend bool operator<(const endpoint& e1, const endpoint& e2)
        {
                return e1.address() < e2.address();
        }
private:
        data_type data_;
        qos::settings qos_;
}; // class endpoint

} // namespace detail
} // namespace atm
} // namespace asio
} // namespace boost

#include "boost/asio/atm/detail/impl/endpoint.ipp"
#endif // BOOST_ASIO_ATM_DETAIL_ENDPOINT_HEAD

/// \file boost/asio/atm/detail/qos.hpp
/// UNCLASSIFIED
/// \brief Asynchronous Transfer Mode QOS details for Boost ASIO
#ifndef BOOST_ASIO_ATM_DETAIL_QOS_HEAD
#define BOOST_ASIO_ATM_DETAIL_QOS_HEAD
namespace boost {
namespace asio {
namespace atm {
namespace qos {
namespace detail {
class pvc_visitor : public boost::static_visitor<> {
public:
        pvc_visitor(boost::asio::atm::detail::atmpvc_endpoint_type &p)
                : boost::static_visitor<>()
                , data(p)
        {
        }

        void operator()(const do_not_use_qos &) const;
        void operator()(const ubr_settings &ubr) const;
        void operator()(const cbr_settings &cbr) const;
        void operator()(const vbr_settings &vbr) const;
        void operator()(const abr_settings &abr) const;
private:
        boost::asio::atm::detail::atmpvc_endpoint_type& data;
};
} // namespace detail
} // namespace qos
} // namespace atm
} // namespace asio
} // namespace boost
#endif // BOOST_ASIO_ATM_DETAIL_QOS_HEAD
#include "boost/asio/atm/detail/impl/qos.ipp"

/// \file boost/asio/atm/detail/socket_ops.hpp
/// UNCLASSIFIED
/// \brief Asynchronous Transfer Mode socket operations for Boost ASIO
#ifndef BOOST_ASIO_ATM_DETAIL_SOCKET_OPS_HEAD
#define BOOST_ASIO_ATM_DETAIL_SOCKET_OPS_HEAD

#include <boost/variant.hpp>
#include <boost/asio.hpp>
#include <boost/exception/all.hpp>
#include "boost/asio/atm/detail/socket_types.hpp"

namespace boost {
namespace asio {
namespace atm {
namespace detail {
namespace socket_ops {
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)

inline void initialize(atmpvc_addr_type& addr)
{
        memset(&addr, 0, sizeof(atmpvc_addr_type));
}

inline void set_itf(const unsigned long itf, atmpvc_addr_type& addr)
{
        addr.DeviceNumber = itf;
}

inline unsigned long itf(const atmpvc_addr_type& addr)
{
        return addr.DeviceNumber;
}

inline void set_vci(const unsigned long vci, atmpvc_addr_type& addr)
{
        addr.VCI = vci;
}

inline unsigned long vci(const atmpvc_addr_type& addr)
{
        return addr.VCI;
}

inline void set_vpi(const unsigned long vpi, atmpvc_addr_type& addr)
{
        addr.VPI = vpi;
}

inline unsigned long vpi(const atmpvc_addr_type& addr)
{
        return addr.VPI;
}
#else // ! (BOOST_WINDOWS || __CYGWIN__)

inline void initialize(atmpvc_addr_type& addr)
{
        memset(&addr, 0, sizeof(atmpvc_addr_type));
        addr.sap_family = AF_ATMPVC;
}

inline void set_itf(const unsigned long itf, atmpvc_addr_type& addr)
{
        addr.sap_addr.itf = itf;
}

inline unsigned long itf(const atmpvc_addr_type& addr)
{
        return addr.sap_addr.itf;
}

inline void set_vci(const unsigned long vci, atmpvc_addr_type& addr)
{
        addr.sap_addr.vci = vci;
}

inline unsigned long vci(const atmpvc_addr_type& addr)
{
        return addr.sap_addr.vci;
}

inline void set_vpi(const unsigned long vpi, atmpvc_addr_type& addr)
{
        addr.sap_addr.vpi = vpi;
}

inline unsigned long vpi(const atmpvc_addr_type& addr)
{
        return addr.sap_addr.vpi;
}
#endif // BOOST_WINDOWS || __CYGWIN__
} // namespace socket_ops

class bind_endpoint_visitor : public boost::static_visitor<int> {
public:
        bind_endpoint_visitor(const boost::asio::detail::socket_type s,
boost::system::error_code &ec)
                : socket_(s)
                , ec_(ec)
        {
        }

        /// Set the VCI/VPI pair for a permament virtual circuit (PVC)
        int operator()(const atmpvc_endpoint_type& params) const;
        int operator()(const atmsvc_endpoint_type& params) const;
private:
        boost::asio::detail::socket_type socket_;
        boost::system::error_code& ec_;
}; // class bind_endpoint_visitor

} // namespace detail
} // namespace atm
} // namespace asio
} // namespace boost

namespace boost {
namespace asio {
namespace detail {
namespace socket_ops {

BOOST_ASIO_DECL int bind(socket_type s, const
boost::asio::atm::detail::atm_endpoint_type* addr, std::size_t addrlen,
boost::system::error_code& ec)
{
        return
boost::apply_visitor(boost::asio::atm::detail::bind_endpoint_visitor(s, ec),
*addr);
}
} // namespace socket_ops
} // namespace detail
} // namespace asio
} // namespace boost
#endif // BOOST_ASIO_ATM_DETAIL_SOCKET_OPS_HEAD

/// \file boost/asio/atm/detail/socket_option.hpp
/// UNCLASSIFIED
/// \brief Asynchronous Transfer Mode socket options for Boost ASIO
#ifndef BOOST_ASIO_ATM_DETAIL_SOCKET_OPTION_HEAD
#define BOOST_ASIO_ATM_DETAIL_SOCKET_OPTION_HEAD

#include <boost/asio.hpp>

namespace boost {
namespace asio {
namespace atm {
namespace detail {
namespace socket_option {

class qos {
public:

        template <typename Protocol>
        int level(const Protocol& protocol) const
        {
        }

        template <typename Protocol>
        int name(const Protocol& protocol) const
        {
        }

        template <typename Protocol>
        void* data(const Protocol& protocol)
        {
        }

        template <typename Protocol>
        const void* data(const Protocol& protocol) const
        {
        }

        template <typename Protocol>
        std::size_t size(const Protocol& protocol) const
        {
        }

        template <typename Protocol>
        void resize(const Protocol& protocol, std::size_t s)
        {
        }
private:
}; // class qos

} // namespace socket_option
} // namespace detail
} // namespace atm
} // namespace asio
} // namespace boost
#endif // BOOST_ASIO_ATM_DETAIL_SOCKET_OPTION_HEAD

/// \file boost/asio/atm/detail/socket_types.hpp
/// UNCLASSIFIED
/// \brief Asynchronous Transfer Mode socket types for Boost ASIO
#ifndef BOOST_ASIO_ATM_DETAIL_SOCKET_TYPES_HEAD
#define BOOST_ASIO_ATM_DETAIL_SOCKET_TYPES_HEAD

#include <string>
#include <boost/asio.hpp>
#include <boost/variant.hpp>

#if defined HAVE_ATM_H
extern "C" {
# include <atm.h>
}
#elif defined HAVE_SYS_NETATM_ATM_H
# include <sys/netatm/atm.h>
#elif defined _WIN32
# include <ws2atm.h>
#else
# error There is no ATM header to include
#endif

namespace boost {
namespace asio {
namespace atm {
namespace detail {

#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)

typedef sockaddr_atm atmsvc_addr_type;
typedef ATM_CONNECTION_ID atmpvc_addr_type;

/// \note Wrap the ATM_PVC_PARAMS so that I have a place to default
construct it.
struct atmpvc_endpoint_type {
        ATM_PVC_PARAMS native_;
        atmpvc_endpoint_type()
                : native_()
        {
                // Initialize Qos Settings with default values : UBR without
specified Qos
                native_.PvcQos.ReceivingFlowspec.TokenRate =
QOS_NOT_SPECIFIED;
                native_.PvcQos.ReceivingFlowspec.TokenBucketSize =
QOS_NOT_SPECIFIED;
                native_.PvcQos.ReceivingFlowspec.PeakBandwidth =
QOS_NOT_SPECIFIED;
                native_.PvcQos.ReceivingFlowspec.Latency =
QOS_NOT_SPECIFIED;
                native_.PvcQos.ReceivingFlowspec.DelayVariation =
QOS_NOT_SPECIFIED;
                native_.PvcQos.ReceivingFlowspec.ServiceType =
SERVICETYPE_BESTEFFORT;
                native_.PvcQos.ReceivingFlowspec.MaxSduSize =
QOS_NOT_SPECIFIED;
                native_.PvcQos.ReceivingFlowspec.MinimumPolicedSize =
QOS_NOT_SPECIFIED;

                native_.PvcQos.SendingFlowspec.TokenRate =
QOS_NOT_SPECIFIED;
                native_.PvcQos.SendingFlowspec.TokenBucketSize =
QOS_NOT_SPECIFIED;
                native_.PvcQos.SendingFlowspec.PeakBandwidth =
QOS_NOT_SPECIFIED;
                native_.PvcQos.SendingFlowspec.Latency = QOS_NOT_SPECIFIED;
                native_.PvcQos.SendingFlowspec.DelayVariation =
QOS_NOT_SPECIFIED;
                native_.PvcQos.SendingFlowspec.ServiceType =
SERVICETYPE_BESTEFFORT;
                native_.PvcQos.SendingFlowspec.MaxSduSize =
QOS_NOT_SPECIFIED;
                native_.PvcQos.SendingFlowspec.MinimumPolicedSize =
QOS_NOT_SPECIFIED;
        }

        const ATM_PVC_PARAMS &native() const
        {
                return native_;
        }

        const ATM_CONNECTION_ID &native_connection_id() const
        {
                return native_.PvcConnectionId;
        }

        void assign(const ATM_CONNECTION_ID &i)
        {
                native_.PvcConnectionId = i;
        }
};

struct atmsvc_endpoint_type {
        sockaddr_atm native_;
        atmsvc_endpoint_type()
                : native_()
        {
        }

        const sockaddr_atm &native() const
        {
                return native_;
        }

        const sockaddr_atm &native_connection_id() const
        {
                return native_;
        }

        void assign(const sockaddr_atm &i)
        {
                native_ = i;
        }
};
#else
typedef sockaddr_atmsvc atmsvc_addr_type;
typedef sockaddr_atmpvc atmpvc_addr_type;
typedef atm_qos atm_qos_type;
struct atmpvc_endpoint_type {
        atmpvc_addr_type addr;
        atm_qos_type qos;

        atmpvc_endpoint_type()
                : addr()
                , qos()
        {
                qos.aal = ATM_AAL5;
        }

        const atmpvc_addr_type &native() const
        {
                return addr;
        }

        const atmpvc_addr_type &native_connection_id() const
        {
                return addr;
        }

        void assign(const atmpvc_addr_type &a)
        {
                addr = a;
        }
};

struct atmsvc_endpoint_type {
        atmsvc_addr_type addr;
        atm_qos_type qos;

        const atmsvc_addr_type &native() const
        {
                return addr;
        }

        const atmsvc_addr_type &native_connection_id() const
        {
                return addr;
        }

        void assign(const atmsvc_addr_type &a)
        {
                addr = a;
        }
};
#endif // BOOST_WINDOWS || __CYGWIN__

typedef boost::variant<atmpvc_endpoint_type, atmsvc_endpoint_type>
atm_endpoint_type;

} // namespace detail
} // namespace atm
} // namespace asio
} // namespace boost
#endif // BOOST_ASIO_ATM_DETAIL_SOCKET_TYPES_HEAD

/// \file boost/asio/atm/detail/impl/endpoint.ipp
/// UNCLASSIFIED
/// \brief Endpoint for ATM sockets
#ifndef BOOST_ASIO_ATM_DETAIL_ENDPOINT_IPP
#define BOOST_ASIO_ATM_DETAIL_ENDPOINT_IPP
namespace boost {
namespace asio {
namespace atm {
namespace detail {
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
int
bind_endpoint_visitor::operator()(const atmpvc_endpoint_type& params) const
{
        using boost::asio::detail::socket_ops::error_wrapper;
        DWORD out_bytes; /// \todo What gets placed in out_bytes?
        return error_wrapper(WSAIoctl(socket_, SIO_ASSOCIATE_PVC, (LPVOID)
&params.native(),
                                      sizeof(ATM_PVC_PARAMS), NULL, 0,
&out_bytes, NULL, NULL), ec_);
}

int
bind_endpoint_visitor::operator()(const atmsvc_endpoint_type& params) const
{
        ec_ = boost::asio::error::invalid_argument;
        return -1;
}
#else // ! (BOOST_WINDOWS || __CYGWIN__)
int
bind_endpoint_visitor::operator()(const atmpvc_endpoint_type& params) const
{
        // I am not convinced that this is the best place to set the ATM QOS
        // options, but it makes the implementation consistent with Windows.
        // Also, it makes the socket constructors that accept an endpoint
work.
        // I probably need an equivalent for "connect" and "listen."
        boost::asio::detail::socket_ops::state_type my_state;
        if (const int result =
boost::asio::detail::socket_ops::setsockopt(socket_, my_state, SOL_ATM,
SO_ATMQOS, &params.qos, sizeof(params.qos), ec_)) {
                return result;
        }
        return boost::asio::detail::socket_ops::bind(socket_, (struct
sockaddr *) &params.addr, sizeof(params.addr), ec_);
}

int
bind_endpoint_visitor::operator()(const atmsvc_endpoint_type& params) const
{
        ec_ = boost::asio::error::invalid_argument;
        return -1;
}
#endif // end defined(BOOST_WINDOWS) || defined(__CYGWIN__)
} // namespace detail
} // namespace atm
} // namespace asio
} // namespace boost
#endif // BOOST_ASIO_ATM_DETAIL_ENDPOINT_IPP

/// \file boost/asio/atm/detail/impl/qos.ipp
/// UNCLASSIFIED
/// \brief Asynchronous Transfer Mode QOS implementation
#ifndef BOOST_ASIO_ATM_QOS_IPP
#define BOOST_ASIO_ATM_QOS_IPP
namespace boost {
namespace asio {
namespace atm {
namespace qos {
namespace detail {
#if defined BOOST_WINDOWS || __CYGWIN__
void
pvc_visitor::operator()(const do_not_use_qos &) const
{
}

void
pvc_visitor::operator()(const ubr_settings &ubr) const
{
        data.native_.PvcQos.SendingFlowspec.PeakBandwidth =
ubr.peak_cell_rate * 48u;
}

void
pvc_visitor::operator()(const cbr_settings &cbr) const
{
        data.native_.PvcQos.SendingFlowspec.ServiceType =
SERVICETYPE_GUARANTEED;
        data.native_.PvcQos.ReceivingFlowspec.ServiceType =
SERVICETYPE_GUARANTEED;
        data.native_.PvcQos.SendingFlowspec.PeakBandwidth =
cbr.peak_cell_rate * 48u;
}

void
pvc_visitor::operator()(const vbr_settings &vbr) const
{
        data.native_.PvcQos.SendingFlowspec.ServiceType =
SERVICETYPE_CONTROLLEDLOAD;
        data.native_.PvcQos.ReceivingFlowspec.ServiceType =
SERVICETYPE_CONTROLLEDLOAD;
        data.native_.PvcQos.SendingFlowspec.PeakBandwidth =
vbr.peak_cell_rate * 48u;
        data.native_.PvcQos.SendingFlowspec.TokenRate =
vbr.substainable_cell_rate * 48u;
        data.native_.PvcQos.SendingFlowspec.TokenBucketSize =
vbr.max_burst_size * 48u;
}

void
pvc_visitor::operator()(const abr_settings &abr) const
{
}
#else
void
pvc_visitor::operator()(const do_not_use_qos &) const
{
        data.qos.txtp.traffic_class = ATM_NONE;
        data.qos.txtp.traffic_class = ATM_NONE;
}

void
pvc_visitor::operator()(const ubr_settings &ubr) const
{
        data.qos.txtp.traffic_class = ATM_UBR;
        data.qos.rxtp.traffic_class = ATM_UBR;
        data.qos.rxtp.max_sdu = ubr.peak_cell_rate;
        data.qos.txtp.max_pcr = ubr.peak_cell_rate;
}

void
pvc_visitor::operator()(const cbr_settings &cbr) const
{
        data.qos.txtp.traffic_class = ATM_CBR;
        data.qos.rxtp.traffic_class = ATM_CBR;
        //data.qos.txtp.ServiceType = SERVICETYPE_GUARANTEED;
        //data.native.qos.rxtp.ServiceType = SERVICETYPE_GUARANTEED;
        data.qos.txtp.max_pcr = cbr.peak_cell_rate;
}

void
pvc_visitor::operator()(const vbr_settings &vbr) const
{
        data.qos.txtp.traffic_class = ATM_VBR;
        data.qos.rxtp.traffic_class = ATM_VBR;
        //data.qos.txtp.ServiceType = SERVICETYPE_CONTROLLEDLOAD;
        //data.qos.rxtp.ServiceType = SERVICETYPE_CONTROLLEDLOAD;
        data.qos.txtp.max_pcr = vbr.peak_cell_rate;
        //data.qos.txtp.TokenRate = vbr.substainable_cell_rate;
        //data.qos.txtp.TokenBucketSize = vbr.max_burst_size;
}

void
pvc_visitor::operator()(const abr_settings &abr) const
{
        data.qos.txtp.traffic_class = ATM_ABR;
        data.qos.rxtp.traffic_class = ATM_ABR;
}
#endif
} // namespace detail
} // namespace qos
} // namespace atm
} // namespace asio
} // namespace boost
#endif // BOOST_ASIO_ATM_QOS_IPP




Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net