LIBWIRE
Next-generation C++17 networking library.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
socket.hpp
Go to the documentation of this file.
1 /*
2  * Copyright © 2018 Max Mazurov (fox.cpp) <fox.cpp [at] disroot [dot] org>
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20  * SOFTWARE.
21  */
22 
23 #pragma once
24 
25 #include <cstdint>
26 #include <tuple>
27 #include <system_error>
28 #include <vector>
29 #include <libwire/error.hpp>
31 
32 /*
33  * If you had to open this file to find answer for your question - we are so
34  * sorry. Please open issue with your question so we can update documentation
35  * to answer it.
36  */
37 
44 namespace libwire::udp {
56  class socket {
57  public:
69  socket(ip ipver) noexcept;
70 
71  socket(const socket&) = delete;
72  socket(socket&&) noexcept = default;
73 
74  socket& operator=(const socket&) = delete;
75  socket& operator=(socket&&) noexcept = default;
76 
80  ~socket();
81 
85  void close() noexcept;
86 
87  internal_::socket& implementation() noexcept;
88  const internal_::socket& implementation() const noexcept;
89 
95  internal_::socket::native_handle_t native_handle() const noexcept;
96 
105 
118  template<typename Option>
119  auto option(const Option& /* tag */) const noexcept {
120  return Option::get(*this);
121  }
122 
140  template<typename Option, typename... Args>
141  void set_option(const Option& /* tag */, Args&&... args) noexcept {
142  Option::set(*this, std::forward<Args>(args)...);
143  }
145 
157  void associate(endpoint target, std::error_code& ec) noexcept;
158 
162  void disassociate() noexcept;
163 
169  void listen(endpoint target, std::error_code& ec) noexcept;
170 
177 
193  template<typename Buffer = std::vector<uint8_t>>
194  Buffer& read(size_t bytes_count, Buffer&, std::error_code&, endpoint* source = nullptr) noexcept;
195 
200  template<typename Buffer = std::vector<uint8_t>>
201  Buffer read(size_t bytes_count, std::error_code&, endpoint* source = nullptr) noexcept;
202 
216  template<typename Buffer = std::vector<uint8_t>>
217  size_t write(const Buffer&, std::error_code&, const endpoint& dest = endpoint::invalid) noexcept;
218 
219 #ifdef __cpp_exceptions
220 
224  void associate(endpoint target);
225 
230  void listen(endpoint target);
231 
236  template<typename Buffer = std::vector<uint8_t>>
237  Buffer& read(size_t bytes_count, Buffer&, endpoint* src = nullptr);
238 
239  template<typename Buffer = std::vector<uint8_t>>
240  Buffer read(size_t bytes_count, endpoint* src = nullptr);
241 
246  template<typename Buffer = std::vector<uint8_t>>
247  size_t write(const Buffer&, const endpoint& dest = endpoint::invalid);
248 #endif // ifdef __cpp_exceptions
249 
251  private:
252  internal_::socket impl;
253  };
254 
255  template<typename Buffer>
256  Buffer& socket::read(size_t bytes_count, Buffer& output, std::error_code& ec, endpoint* source) noexcept {
257  static_assert(sizeof(std::remove_pointer_t<decltype(output.data())>) == sizeof(uint8_t),
258  "socket::read can't be used with container with non-byte elements");
259 
260  output.resize(bytes_count);
261  size_t bytes_received;
262  if (source == nullptr) {
263  bytes_received = impl.read(output.data(), bytes_count, ec);
264  } else {
265  bytes_received = impl.recvfrom(output.data(), bytes_count, *source, ec);
266  }
267  if (ec) return output;
268  output.resize(bytes_received);
269 
270  return output;
271  }
272 
273  template<typename Buffer>
274  Buffer socket::read(size_t bytes_count, std::error_code& ec, endpoint* source) noexcept {
275  Buffer buffer{};
276  return read(bytes_count, buffer, ec, source);
277  }
278 
279  extern template std::vector<uint8_t> socket::read(size_t, std::error_code&, endpoint* source);
280  extern template std::string socket::read(size_t, std::error_code&, endpoint* source);
281 
282  extern template std::vector<uint8_t>& socket::read(size_t, std::vector<uint8_t>&, std::error_code&,
283  endpoint* source);
284  extern template std::string& socket::read(size_t, std::string&, std::error_code&, endpoint*);
285 
286  template<typename Buffer>
287  size_t socket::write(const Buffer& input, std::error_code& ec, const endpoint& dest) noexcept {
288  static_assert(sizeof(std::remove_pointer_t<decltype(input.data())>) == sizeof(uint8_t),
289  "socket::write can't be used with container with non-byte elements");
290 
291  if (dest.is_invalid()) { // default value
292  return impl.write(input.data(), input.size(), ec);
293  } else {
294  return impl.sendto(input.data(), input.size(), dest, ec);
295  }
296  }
297 
298  extern template size_t socket::write(const std::vector<uint8_t>&, std::error_code&, const endpoint&);
299  extern template size_t socket::write(const std::string&, std::error_code&, const endpoint&);
300 
301 #ifdef __cpp_exceptions
302  template<typename Buffer>
303  Buffer& socket::read(size_t bytes_count, Buffer& output, endpoint* source) {
304  std::error_code ec;
305  auto res = read<Buffer>(bytes_count, output, ec, source);
306  if (ec) throw std::system_error(ec);
307  return output;
308  }
309 
310  template<typename Buffer>
311  Buffer socket::read(size_t bytes_count, endpoint* source) {
312  Buffer buffer{};
313  return read(bytes_count, buffer, source);
314  }
315 
316  extern template std::vector<uint8_t>& socket::read(size_t, std::vector<uint8_t>&, endpoint* source);
317  extern template std::string& socket::read(size_t, std::string&, endpoint* source);
318 
319  extern template std::vector<uint8_t> socket::read(size_t, endpoint* source);
320  extern template std::string socket::read(size_t, endpoint* source);
321 
322  template<typename Buffer>
323  size_t socket::write(const Buffer& input, const endpoint& dest) {
324  std::error_code ec;
325  size_t res = write<Buffer>(input, ec, dest);
326  if (ec) throw std::system_error(ec);
327  return res;
328  }
329 
330  extern template size_t socket::write(const std::vector<uint8_t>&, const endpoint&);
331  extern template size_t socket::write(const std::string&, const endpoint&);
332 #endif // ifdef __cpp_exceptions
333 } // namespace libwire::udp
size_t write(const Buffer &, std::error_code &, const endpoint &dest=endpoint::invalid) noexcept
Write contents of buffer to socket.
Definition: socket.hpp:287
void set_option(const Option &, Args &&...args) noexcept
Set socket option value specified by type tag Option to value value.
Definition: socket.hpp:141
void associate(endpoint target, std::error_code &ec) noexcept
Associate UDP socket with remote endpoint.
auto option(const Option &) const noexcept
Query socket option value specified by type tag Option.
Definition: socket.hpp:119
internal_::socket & implementation() noexcept
void listen(endpoint target, std::error_code &ec) noexcept
Accept datagrams coming on specified endpoint.
socket(ip ipver) noexcept
Create new socket object.
static const endpoint invalid
Definition: endpoint.hpp:63
internal_::socket::native_handle_t native_handle() const noexcept
Get native handle/descriptor for socket.
~socket()
Deallocate socket.
Buffer & read(size_t bytes_count, Buffer &, std::error_code &, endpoint *source=nullptr) noexcept
Read pending datagram into buffer.
Definition: socket.hpp:256
This header defines set of enumerations for platform-independent error code handling.
Descriptor wrapper for UDP socket.
Definition: socket.hpp:56
void disassociate() noexcept
Undo previous call to associate().
void close() noexcept
Deallocate socket.
socket & operator=(const socket &)=delete