| 1 | #include "ariba/config.h"
 | 
|---|
| 2 | 
 | 
|---|
| 3 | #ifdef HAVE_LIBBLUETOOTH
 | 
|---|
| 4 | 
 | 
|---|
| 5 | #ifndef BOOST_ASIO_BLUETOOTH_BLUETOOTH_ENDPOINT_HPP__
 | 
|---|
| 6 | #define BOOST_ASIO_BLUETOOTH_BLUETOOTH_ENDPOINT_HPP__
 | 
|---|
| 7 | 
 | 
|---|
| 8 | #include <bluetooth/bluetooth.h>
 | 
|---|
| 9 | #include <bluetooth/rfcomm.h>
 | 
|---|
| 10 | #include <iostream>
 | 
|---|
| 11 | 
 | 
|---|
| 12 | #include <boost/asio/basic_stream_socket.hpp>
 | 
|---|
| 13 | 
 | 
|---|
| 14 | namespace boost {
 | 
|---|
| 15 | namespace asio {
 | 
|---|
| 16 | namespace bluetooth {
 | 
|---|
| 17 | 
 | 
|---|
| 18 | /**
 | 
|---|
| 19 |  * Describes an endpoint for a RFCOMM Bluetooth socket.
 | 
|---|
| 20 |  *
 | 
|---|
| 21 |  * @author Martin Florian <mflorian@lafka.net>
 | 
|---|
| 22 |  */
 | 
|---|
| 23 | template<typename BluetoothProtocol>
 | 
|---|
| 24 | class bluetooth_endpoint {
 | 
|---|
| 25 | private:
 | 
|---|
| 26 |         static const bdaddr_t addr_any;
 | 
|---|
| 27 | 
 | 
|---|
| 28 | public:
 | 
|---|
| 29 |         /// The protocol type associated with the endpoint.
 | 
|---|
| 30 |         typedef BluetoothProtocol protocol_type;
 | 
|---|
| 31 | 
 | 
|---|
| 32 |         /// The type of the endpoint structure. This type is dependent on the
 | 
|---|
| 33 |         /// underlying implementation of the socket layer.
 | 
|---|
| 34 |         typedef boost::asio::detail::socket_addr_type data_type; // <-- Do I need this?
 | 
|---|
| 35 |         //typedef sockaddr_rc data_type;
 | 
|---|
| 36 | 
 | 
|---|
| 37 |         /// Default constructor.
 | 
|---|
| 38 |         bluetooth_endpoint() :
 | 
|---|
| 39 |                 data_() {
 | 
|---|
| 40 |                 data_.rc_family = AF_BLUETOOTH;
 | 
|---|
| 41 |                 data_.rc_bdaddr = addr_any;
 | 
|---|
| 42 |                 data_.rc_channel = 0;
 | 
|---|
| 43 |         }
 | 
|---|
| 44 | 
 | 
|---|
| 45 |         bluetooth_endpoint(const BluetoothProtocol& protocol,
 | 
|---|
| 46 |                         uint8_t channel) :
 | 
|---|
| 47 |                 data_() {
 | 
|---|
| 48 |                 data_.rc_family = AF_BLUETOOTH;
 | 
|---|
| 49 |                 data_.rc_bdaddr = addr_any;
 | 
|---|
| 50 |                 data_.rc_channel = channel;
 | 
|---|
| 51 |         }
 | 
|---|
| 52 | 
 | 
|---|
| 53 |         /// Construct an endpoint using a port number, specified in the host's byte
 | 
|---|
| 54 |         /// order. The IP address will be the any address (i.e. INADDR_ANY or
 | 
|---|
| 55 |         /// in6addr_any). This constructor would typically be used for accepting new
 | 
|---|
| 56 |         /// connections.
 | 
|---|
| 57 |         bluetooth_endpoint(uint8_t channel) :
 | 
|---|
| 58 |                 data_() {
 | 
|---|
| 59 |                 data_.rc_family = AF_BLUETOOTH;
 | 
|---|
| 60 |                 data_.rc_bdaddr = addr_any;
 | 
|---|
| 61 |                 data_.rc_channel = channel;
 | 
|---|
| 62 |         }
 | 
|---|
| 63 | 
 | 
|---|
| 64 |         /// Construct an endpoint using a port number and an BT address.
 | 
|---|
| 65 |         /// The address is in human readable form as a string.
 | 
|---|
| 66 |         bluetooth_endpoint(const char *addr, uint8_t channel) :
 | 
|---|
| 67 |                 data_() {
 | 
|---|
| 68 |                 data_.rc_family = AF_BLUETOOTH;
 | 
|---|
| 69 |                 data_.rc_channel = channel;
 | 
|---|
| 70 |                 str2ba(addr, &data_.rc_bdaddr);
 | 
|---|
| 71 |         }
 | 
|---|
| 72 | 
 | 
|---|
| 73 |         /// Construct an endpoint using a port number and an BT address.
 | 
|---|
| 74 |         /// The address is given in the bluetooth-internal format.
 | 
|---|
| 75 |         bluetooth_endpoint(const bdaddr_t& addr, uint8_t channel) :
 | 
|---|
| 76 |                 data_() {
 | 
|---|
| 77 |                 data_.rc_family = AF_BLUETOOTH;
 | 
|---|
| 78 |                 data_.rc_channel = channel;
 | 
|---|
| 79 |                 data_.rc_bdaddr = addr;
 | 
|---|
| 80 |         }
 | 
|---|
| 81 | 
 | 
|---|
| 82 |         /// Copy constructor.
 | 
|---|
| 83 |         bluetooth_endpoint(const bluetooth_endpoint& other) :
 | 
|---|
| 84 |                 data_(other.data_) {
 | 
|---|
| 85 |         }
 | 
|---|
| 86 | 
 | 
|---|
| 87 |         /// Assign from another endpoint.
 | 
|---|
| 88 |         bluetooth_endpoint& operator=(const bluetooth_endpoint& other) {
 | 
|---|
| 89 |                 data_ = other.data_;
 | 
|---|
| 90 |                 return *this;
 | 
|---|
| 91 |         }
 | 
|---|
| 92 | 
 | 
|---|
| 93 |         /// The protocol associated with the endpoint.
 | 
|---|
| 94 |         protocol_type protocol() const {
 | 
|---|
| 95 |                 return protocol_type::get();
 | 
|---|
| 96 |         }
 | 
|---|
| 97 | 
 | 
|---|
| 98 |         /// Get the underlying endpoint in the native type.
 | 
|---|
| 99 |         /// TODO: make this nice and generic -> union like in tcp
 | 
|---|
| 100 |         data_type* data() {
 | 
|---|
| 101 |                 return (boost::asio::detail::socket_addr_type*) &data_;
 | 
|---|
| 102 |         }
 | 
|---|
| 103 | 
 | 
|---|
| 104 |         /// Get the underlying endpoint in the native type.
 | 
|---|
| 105 |         const data_type* data() const {
 | 
|---|
| 106 |                 return (boost::asio::detail::socket_addr_type*) &data_;
 | 
|---|
| 107 |         }
 | 
|---|
| 108 | 
 | 
|---|
| 109 |         /// Get the underlying size of the endpoint in the native type.
 | 
|---|
| 110 |         std::size_t size() const {
 | 
|---|
| 111 |                 return sizeof(data_type);
 | 
|---|
| 112 |         }
 | 
|---|
| 113 | 
 | 
|---|
| 114 |         /// Set the underlying size of the endpoint in the native type.
 | 
|---|
| 115 |         void resize(std::size_t size) {
 | 
|---|
| 116 |                 if (size > sizeof(data_type)) {
 | 
|---|
| 117 |                         boost::system::system_error e(boost::asio::error::invalid_argument);
 | 
|---|
| 118 |                         boost::throw_exception(e);
 | 
|---|
| 119 |                 }
 | 
|---|
| 120 |         }
 | 
|---|
| 121 | 
 | 
|---|
| 122 |         /// Get the capacity of the endpoint in the native type.
 | 
|---|
| 123 |         std::size_t capacity() const {
 | 
|---|
| 124 |                 return sizeof(data_type);
 | 
|---|
| 125 |         }
 | 
|---|
| 126 | 
 | 
|---|
| 127 |         /// Get the channel associated with the endpoint. The port number is always in
 | 
|---|
| 128 |         /// the host's byte order.
 | 
|---|
| 129 |         uint8_t channel() const {
 | 
|---|
| 130 |                 return data_.rc_channel;
 | 
|---|
| 131 |         }
 | 
|---|
| 132 | 
 | 
|---|
| 133 |         /// Set the channel associated with the endpoint. The port number is always in
 | 
|---|
| 134 |         /// the host's byte order.
 | 
|---|
| 135 |         void channel(uint8_t channel_num) {
 | 
|---|
| 136 |                 data_.rc_channel = channel_num;
 | 
|---|
| 137 |         }
 | 
|---|
| 138 | 
 | 
|---|
| 139 |         /// Get the Bluetooth address associated with the endpoint.
 | 
|---|
| 140 |         const bdaddr_t& address() const {
 | 
|---|
| 141 |                 return data_.rc_bdaddr;
 | 
|---|
| 142 |         }
 | 
|---|
| 143 | 
 | 
|---|
| 144 |         /// Set the Bluetooth address associated with the endpoint.
 | 
|---|
| 145 |         void address(const boost::asio::ip::address& addr) {
 | 
|---|
| 146 |                 bluetooth_endpoint<BluetoothProtocol> tmp_endpoint(addr, channel());
 | 
|---|
| 147 |                 data_ = tmp_endpoint.data_;
 | 
|---|
| 148 |         }
 | 
|---|
| 149 | 
 | 
|---|
| 150 |         /// Compare two endpoints for equality.
 | 
|---|
| 151 |         friend bool operator==(const bluetooth_endpoint& e1,
 | 
|---|
| 152 |                         const bluetooth_endpoint& e2) {
 | 
|---|
| 153 |                 return e1.address() == e2.address() && e1.channel() == e2.channel();
 | 
|---|
| 154 |         }
 | 
|---|
| 155 | 
 | 
|---|
| 156 |         /// Compare two endpoints for inequality.
 | 
|---|
| 157 |         friend bool operator!=(const bluetooth_endpoint& e1,
 | 
|---|
| 158 |                         const bluetooth_endpoint& e2) {
 | 
|---|
| 159 |                 return e1.address() != e2.address() || e1.channel() != e2.channel();
 | 
|---|
| 160 |         }
 | 
|---|
| 161 | 
 | 
|---|
| 162 |         /// Compare endpoints for ordering.
 | 
|---|
| 163 |         friend bool operator<(const bluetooth_endpoint<BluetoothProtocol>& e1,
 | 
|---|
| 164 |                         const bluetooth_endpoint<BluetoothProtocol>& e2) {
 | 
|---|
| 165 |                 int cmp = bacmp(&e1.address(), &e2.address());
 | 
|---|
| 166 |                 
 | 
|---|
| 167 |                 if (cmp == 0) {
 | 
|---|
| 168 |                         return e1.channel() < e2.channel();
 | 
|---|
| 169 |                 } else {
 | 
|---|
| 170 |                         return cmp < 0;
 | 
|---|
| 171 |                 }
 | 
|---|
| 172 |         }
 | 
|---|
| 173 |         
 | 
|---|
| 174 |         friend ostream& operator<<(
 | 
|---|
| 175 |                         ostream& out,
 | 
|---|
| 176 |                         const bluetooth_endpoint<BluetoothProtocol>& endp) {
 | 
|---|
| 177 |                 char* mac_str = batostr(&endp.data_.rc_bdaddr);
 | 
|---|
| 178 |                 out << "[" << mac_str << "]:" << (int)endp.data_.rc_channel;
 | 
|---|
| 179 |                 free(mac_str);
 | 
|---|
| 180 |                 return out;
 | 
|---|
| 181 |         }
 | 
|---|
| 182 | 
 | 
|---|
| 183 | private:
 | 
|---|
| 184 |         // The underlying rfcomm socket address structure thingy.
 | 
|---|
| 185 |         //struct data_type data_;
 | 
|---|
| 186 |         struct sockaddr_rc data_;
 | 
|---|
| 187 | };
 | 
|---|
| 188 | 
 | 
|---|
| 189 | template<typename X>
 | 
|---|
| 190 | const bdaddr_t bluetooth_endpoint<X>::addr_any = { {0u, 0u, 0u, 0u, 0u, 0u} };
 | 
|---|
| 191 | 
 | 
|---|
| 192 | }}} // namespace boost::asio::bluetooth
 | 
|---|
| 193 | 
 | 
|---|
| 194 | #endif /* BOOST_ASIO_BLUETOOTH_BLUETOOTH_ENDPOINT_HPP__ */
 | 
|---|
| 195 | #endif /* HAVE_LIBBLUETOOTH */
 | 
|---|