Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef ASIO_IP_BASIC_ENDPOINT_HPP
00012 #define ASIO_IP_BASIC_ENDPOINT_HPP
00013
00014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
00015 # pragma once
00016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
00017
00018 #include "asio/detail/push_options.hpp"
00019
00020 #include "asio/detail/push_options.hpp"
00021 #include <boost/throw_exception.hpp>
00022 #include <boost/detail/workaround.hpp>
00023 #include <cstring>
00024 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
00025 # include <ostream>
00026 #endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
00027 #include "asio/detail/pop_options.hpp"
00028
00029 #include "asio/error.hpp"
00030 #include "asio/ip/address.hpp"
00031 #include "asio/detail/socket_ops.hpp"
00032 #include "asio/detail/socket_types.hpp"
00033
00034 namespace asio {
00035 namespace ip {
00036
00038
00049 template <typename InternetProtocol>
00050 class basic_endpoint
00051 {
00052 public:
00054 typedef InternetProtocol protocol_type;
00055
00058 #if defined(GENERATING_DOCUMENTATION)
00059 typedef implementation_defined data_type;
00060 #else
00061 typedef asio::detail::socket_addr_type data_type;
00062 #endif
00063
00065 basic_endpoint()
00066 : data_()
00067 {
00068 data_.v4.sin_family = AF_INET;
00069 data_.v4.sin_port = 0;
00070 data_.v4.sin_addr.s_addr = INADDR_ANY;
00071 }
00072
00077
00089 basic_endpoint(const InternetProtocol& protocol, unsigned short port_num)
00090 : data_()
00091 {
00092 using namespace std;
00093 if (protocol.family() == PF_INET)
00094 {
00095 data_.v4.sin_family = AF_INET;
00096 data_.v4.sin_port =
00097 asio::detail::socket_ops::host_to_network_short(port_num);
00098 data_.v4.sin_addr.s_addr = INADDR_ANY;
00099 }
00100 else
00101 {
00102 data_.v6.sin6_family = AF_INET6;
00103 data_.v6.sin6_port =
00104 asio::detail::socket_ops::host_to_network_short(port_num);
00105 data_.v6.sin6_flowinfo = 0;
00106 asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT;
00107 data_.v6.sin6_addr = tmp_addr;
00108 data_.v6.sin6_scope_id = 0;
00109 }
00110 }
00111
00115 basic_endpoint(const asio::ip::address& addr, unsigned short port_num)
00116 : data_()
00117 {
00118 using namespace std;
00119 if (addr.is_v4())
00120 {
00121 data_.v4.sin_family = AF_INET;
00122 data_.v4.sin_port =
00123 asio::detail::socket_ops::host_to_network_short(port_num);
00124 data_.v4.sin_addr.s_addr =
00125 asio::detail::socket_ops::host_to_network_long(
00126 addr.to_v4().to_ulong());
00127 }
00128 else
00129 {
00130 data_.v6.sin6_family = AF_INET6;
00131 data_.v6.sin6_port =
00132 asio::detail::socket_ops::host_to_network_short(port_num);
00133 data_.v6.sin6_flowinfo = 0;
00134 asio::ip::address_v6 v6_addr = addr.to_v6();
00135 asio::ip::address_v6::bytes_type bytes = v6_addr.to_bytes();
00136 memcpy(data_.v6.sin6_addr.s6_addr, bytes.elems, 16);
00137 data_.v6.sin6_scope_id = v6_addr.scope_id();
00138 }
00139 }
00140
00142 basic_endpoint(const basic_endpoint& other)
00143 : data_(other.data_)
00144 {
00145 }
00146
00148 basic_endpoint& operator=(const basic_endpoint& other)
00149 {
00150 data_ = other.data_;
00151 return *this;
00152 }
00153
00155 protocol_type protocol() const
00156 {
00157 if (is_v4())
00158 return InternetProtocol::v4();
00159 return InternetProtocol::v6();
00160 }
00161
00163 data_type* data()
00164 {
00165 return &data_.base;
00166 }
00167
00169 const data_type* data() const
00170 {
00171 return &data_.base;
00172 }
00173
00175 std::size_t size() const
00176 {
00177 if (is_v4())
00178 return sizeof(asio::detail::sockaddr_in4_type);
00179 else
00180 return sizeof(asio::detail::sockaddr_in6_type);
00181 }
00182
00184 void resize(std::size_t size)
00185 {
00186 if (size > sizeof(asio::detail::sockaddr_storage_type))
00187 {
00188 asio::system_error e(asio::error::invalid_argument);
00189 boost::throw_exception(e);
00190 }
00191 }
00192
00194 std::size_t capacity() const
00195 {
00196 return sizeof(asio::detail::sockaddr_storage_type);
00197 }
00198
00201 unsigned short port() const
00202 {
00203 if (is_v4())
00204 {
00205 return asio::detail::socket_ops::network_to_host_short(
00206 data_.v4.sin_port);
00207 }
00208 else
00209 {
00210 return asio::detail::socket_ops::network_to_host_short(
00211 data_.v6.sin6_port);
00212 }
00213 }
00214
00217 void port(unsigned short port_num)
00218 {
00219 if (is_v4())
00220 {
00221 data_.v4.sin_port
00222 = asio::detail::socket_ops::host_to_network_short(port_num);
00223 }
00224 else
00225 {
00226 data_.v6.sin6_port
00227 = asio::detail::socket_ops::host_to_network_short(port_num);
00228 }
00229 }
00230
00232 asio::ip::address address() const
00233 {
00234 using namespace std;
00235 if (is_v4())
00236 {
00237 return asio::ip::address_v4(
00238 asio::detail::socket_ops::network_to_host_long(
00239 data_.v4.sin_addr.s_addr));
00240 }
00241 else
00242 {
00243 asio::ip::address_v6::bytes_type bytes;
00244 memcpy(bytes.elems, data_.v6.sin6_addr.s6_addr, 16);
00245 return asio::ip::address_v6(bytes, data_.v6.sin6_scope_id);
00246 }
00247 }
00248
00250 void address(const asio::ip::address& addr)
00251 {
00252 basic_endpoint<InternetProtocol> tmp_endpoint(addr, port());
00253 data_ = tmp_endpoint.data_;
00254 }
00255
00257 friend bool operator==(const basic_endpoint<InternetProtocol>& e1,
00258 const basic_endpoint<InternetProtocol>& e2)
00259 {
00260 return e1.address() == e2.address() && e1.port() == e2.port();
00261 }
00262
00264 friend bool operator!=(const basic_endpoint<InternetProtocol>& e1,
00265 const basic_endpoint<InternetProtocol>& e2)
00266 {
00267 return e1.address() != e2.address() || e1.port() != e2.port();
00268 }
00269
00271 friend bool operator<(const basic_endpoint<InternetProtocol>& e1,
00272 const basic_endpoint<InternetProtocol>& e2)
00273 {
00274 if (e1.address() < e2.address())
00275 return true;
00276 if (e1.address() != e2.address())
00277 return false;
00278 return e1.port() < e2.port();
00279 }
00280
00281 private:
00282
00283 bool is_v4() const
00284 {
00285 return data_.base.sa_family == AF_INET;
00286 }
00287
00288
00289 union data_union
00290 {
00291 asio::detail::socket_addr_type base;
00292 asio::detail::sockaddr_storage_type storage;
00293 asio::detail::sockaddr_in4_type v4;
00294 asio::detail::sockaddr_in6_type v6;
00295 } data_;
00296 };
00297
00299
00310 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
00311 template <typename InternetProtocol>
00312 std::ostream& operator<<(std::ostream& os,
00313 const basic_endpoint<InternetProtocol>& endpoint)
00314 {
00315 const address& addr = endpoint.address();
00316 asio::error_code ec;
00317 std::string a = addr.to_string(ec);
00318 if (ec)
00319 {
00320 if (os.exceptions() & std::ios::failbit)
00321 asio::detail::throw_error(ec);
00322 else
00323 os.setstate(std::ios_base::failbit);
00324 }
00325 else
00326 {
00327 if (addr.is_v4())
00328 os << a;
00329 else
00330 os << '[' << a << ']';
00331 os << ':' << endpoint.port();
00332 }
00333 return os;
00334 }
00335 #else // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
00336 template <typename Elem, typename Traits, typename InternetProtocol>
00337 std::basic_ostream<Elem, Traits>& operator<<(
00338 std::basic_ostream<Elem, Traits>& os,
00339 const basic_endpoint<InternetProtocol>& endpoint)
00340 {
00341 const address& addr = endpoint.address();
00342 asio::error_code ec;
00343 std::string a = addr.to_string(ec);
00344 if (ec)
00345 {
00346 if (os.exceptions() & std::ios::failbit)
00347 asio::detail::throw_error(ec);
00348 else
00349 os.setstate(std::ios_base::failbit);
00350 }
00351 else
00352 {
00353 if (addr.is_v4())
00354 os << a;
00355 else
00356 os << '[' << a << ']';
00357 os << ':' << endpoint.port();
00358 }
00359 return os;
00360 }
00361 #endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
00362
00363 }
00364 }
00365
00366 #include "asio/detail/pop_options.hpp"
00367
00368 #endif // ASIO_IP_BASIC_ENDPOINT_HPP