basic_endpoint.hpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. //
  2. // basic_endpoint.hpp
  3. // ~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. // Derived from a public domain implementation written by Daniel Casimiro.
  7. //
  8. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  9. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  10. //
  11. #ifndef ASIO_LOCAL_BASIC_ENDPOINT_HPP
  12. #define ASIO_LOCAL_BASIC_ENDPOINT_HPP
  13. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  14. # pragma once
  15. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  16. #include "asio/detail/push_options.hpp"
  17. #include "asio/detail/push_options.hpp"
  18. #include <boost/throw_exception.hpp>
  19. #include <cstddef>
  20. #include <cstring>
  21. #include <ostream>
  22. #include "asio/detail/pop_options.hpp"
  23. #include "asio/error.hpp"
  24. #include "asio/system_error.hpp"
  25. #include "asio/detail/socket_ops.hpp"
  26. #include "asio/detail/socket_types.hpp"
  27. #include "asio/detail/throw_error.hpp"
  28. #if !defined(ASIO_DISABLE_LOCAL_SOCKETS)
  29. # if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
  30. # define ASIO_HAS_LOCAL_SOCKETS 1
  31. # endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
  32. #endif // !defined(ASIO_DISABLE_LOCAL_SOCKETS)
  33. #if defined(ASIO_HAS_LOCAL_SOCKETS) \
  34. || defined(GENERATING_DOCUMENTATION)
  35. namespace asio {
  36. namespace local {
  37. /// Describes an endpoint for a UNIX socket.
  38. /**
  39. * The asio::local::basic_endpoint class template describes an endpoint
  40. * that may be associated with a particular UNIX socket.
  41. *
  42. * @par Thread Safety
  43. * @e Distinct @e objects: Safe.@n
  44. * @e Shared @e objects: Unsafe.
  45. *
  46. * @par Concepts:
  47. * Endpoint.
  48. */
  49. template <typename Protocol>
  50. class basic_endpoint
  51. {
  52. public:
  53. /// The protocol type associated with the endpoint.
  54. typedef Protocol protocol_type;
  55. /// The type of the endpoint structure. This type is dependent on the
  56. /// underlying implementation of the socket layer.
  57. #if defined(GENERATING_DOCUMENTATION)
  58. typedef implementation_defined data_type;
  59. #else
  60. typedef asio::detail::socket_addr_type data_type;
  61. #endif
  62. /// Default constructor.
  63. basic_endpoint()
  64. {
  65. init("", 0);
  66. }
  67. /// Construct an endpoint using the specified path name.
  68. basic_endpoint(const char* path)
  69. {
  70. using namespace std; // For strlen.
  71. init(path, strlen(path));
  72. }
  73. /// Construct an endpoint using the specified path name.
  74. basic_endpoint(const std::string& path)
  75. {
  76. init(path.data(), path.length());
  77. }
  78. /// Copy constructor.
  79. basic_endpoint(const basic_endpoint& other)
  80. : data_(other.data_),
  81. path_length_(other.path_length_)
  82. {
  83. }
  84. /// Assign from another endpoint.
  85. basic_endpoint& operator=(const basic_endpoint& other)
  86. {
  87. data_ = other.data_;
  88. path_length_ = other.path_length_;
  89. return *this;
  90. }
  91. /// The protocol associated with the endpoint.
  92. protocol_type protocol() const
  93. {
  94. return protocol_type();
  95. }
  96. /// Get the underlying endpoint in the native type.
  97. data_type* data()
  98. {
  99. return &data_.base;
  100. }
  101. /// Get the underlying endpoint in the native type.
  102. const data_type* data() const
  103. {
  104. return &data_.base;
  105. }
  106. /// Get the underlying size of the endpoint in the native type.
  107. std::size_t size() const
  108. {
  109. return path_length_
  110. + offsetof(asio::detail::sockaddr_un_type, sun_path);
  111. }
  112. /// Set the underlying size of the endpoint in the native type.
  113. void resize(std::size_t size)
  114. {
  115. if (size > sizeof(asio::detail::sockaddr_un_type))
  116. {
  117. asio::system_error e(asio::error::invalid_argument);
  118. boost::throw_exception(e);
  119. }
  120. else if (size == 0)
  121. {
  122. path_length_ = 0;
  123. }
  124. else
  125. {
  126. path_length_ = size
  127. - offsetof(asio::detail::sockaddr_un_type, sun_path);
  128. // The path returned by the operating system may be NUL-terminated.
  129. if (path_length_ > 0 && data_.local.sun_path[path_length_ - 1] == 0)
  130. --path_length_;
  131. }
  132. }
  133. /// Get the capacity of the endpoint in the native type.
  134. std::size_t capacity() const
  135. {
  136. return sizeof(asio::detail::sockaddr_un_type);
  137. }
  138. /// Get the path associated with the endpoint.
  139. std::string path() const
  140. {
  141. return std::string(data_.local.sun_path, path_length_);
  142. }
  143. /// Set the path associated with the endpoint.
  144. void path(const char* p)
  145. {
  146. using namespace std; // For strlen.
  147. init(p, strlen(p));
  148. }
  149. /// Set the path associated with the endpoint.
  150. void path(const std::string& p)
  151. {
  152. init(p.data(), p.length());
  153. }
  154. /// Compare two endpoints for equality.
  155. friend bool operator==(const basic_endpoint<Protocol>& e1,
  156. const basic_endpoint<Protocol>& e2)
  157. {
  158. return e1.path() == e2.path();
  159. }
  160. /// Compare two endpoints for inequality.
  161. friend bool operator!=(const basic_endpoint<Protocol>& e1,
  162. const basic_endpoint<Protocol>& e2)
  163. {
  164. return e1.path() != e2.path();
  165. }
  166. /// Compare endpoints for ordering.
  167. friend bool operator<(const basic_endpoint<Protocol>& e1,
  168. const basic_endpoint<Protocol>& e2)
  169. {
  170. return e1.path() < e2.path();
  171. }
  172. private:
  173. // The underlying UNIX socket address.
  174. union data_union
  175. {
  176. asio::detail::socket_addr_type base;
  177. asio::detail::sockaddr_un_type local;
  178. } data_;
  179. // The length of the path associated with the endpoint.
  180. std::size_t path_length_;
  181. // Initialise with a specified path.
  182. void init(const char* path, std::size_t path_length)
  183. {
  184. if (path_length > sizeof(data_.local.sun_path) - 1)
  185. {
  186. // The buffer is not large enough to store this address.
  187. asio::error_code ec(asio::error::name_too_long);
  188. asio::detail::throw_error(ec);
  189. }
  190. using namespace std; // For memcpy.
  191. data_.local = asio::detail::sockaddr_un_type();
  192. data_.local.sun_family = AF_UNIX;
  193. memcpy(data_.local.sun_path, path, path_length);
  194. path_length_ = path_length;
  195. // NUL-terminate normal path names. Names that start with a NUL are in the
  196. // UNIX domain protocol's "abstract namespace" and are not NUL-terminated.
  197. if (path_length > 0 && data_.local.sun_path[0] == 0)
  198. data_.local.sun_path[path_length] = 0;
  199. }
  200. };
  201. /// Output an endpoint as a string.
  202. /**
  203. * Used to output a human-readable string for a specified endpoint.
  204. *
  205. * @param os The output stream to which the string will be written.
  206. *
  207. * @param endpoint The endpoint to be written.
  208. *
  209. * @return The output stream.
  210. *
  211. * @relates asio::local::basic_endpoint
  212. */
  213. template <typename Elem, typename Traits, typename Protocol>
  214. std::basic_ostream<Elem, Traits>& operator<<(
  215. std::basic_ostream<Elem, Traits>& os,
  216. const basic_endpoint<Protocol>& endpoint)
  217. {
  218. os << endpoint.path();
  219. return os;
  220. }
  221. } // namespace local
  222. } // namespace asio
  223. #endif // defined(ASIO_HAS_LOCAL_SOCKETS)
  224. // || defined(GENERATING_DOCUMENTATION)
  225. #include "asio/detail/pop_options.hpp"
  226. #endif // ASIO_LOCAL_BASIC_ENDPOINT_HPP