uvcc
libuv C++ bindings
handle-stream.hpp
1 
2 #ifndef UVCC_HANDLE_STREAM__HPP
3 #define UVCC_HANDLE_STREAM__HPP
4 
5 #include "uvcc/utility.hpp"
6 #include "uvcc/handle-base.hpp"
7 #include "uvcc/handle-io.hpp"
8 #include "uvcc/buffer.hpp"
9 #include "uvcc/loop.hpp"
10 
11 #include <cstddef> // size_t
12 #include <uv.h>
13 
14 #include <functional> // function
15 #include <string> // string
16 #include <type_traits> // enable_if_t
17 
18 
19 namespace uv
20 {
21 
22 
23 /*! \ingroup doxy_group__handle
24  \brief Stream handle.
25  \sa libuv API documentation: [`uv_stream_t` — Stream handle](http://docs.libuv.org/en/v1.x/stream.html#uv-stream-t-stream-handle). */
26 class stream : public io
27 {
28  //! \cond
29  friend class handle::uv_interface;
30  friend class handle::instance< stream >;
31  friend class connect;
32  friend class write;
33  friend class shutdown;
34  friend class pipe;
35  //! \endcond
36 
37 public: /*types*/
38  using uv_t = ::uv_stream_t;
39  using on_connection_t = std::function< void(stream _server) >;
40  /*!< \brief The function type of the callback called when a stream server has received an incoming connection.
41  \details The user can accept the connection by calling accept().
42  \sa libuv API documentation: [`uv_connection_cb`](http://docs.libuv.org/en/v1.x/stream.html#c.uv_connection_cb). */
43 
44 protected: /*types*/
45  //! \cond internals
46  //! \addtogroup doxy_group__internals
47  //! \{
48 
49  struct properties : io::properties
50  {
51  on_connection_t connection_cb;
52  };
53 
54  struct uv_interface : handle::uv_handle_interface, io::uv_interface
55  {
56  std::size_t write_queue_size(void *_uv_handle) const noexcept override
57  { return static_cast< ::uv_stream_t* >(_uv_handle)->write_queue_size; }
58 
59  int read_start(void *_uv_handle, int64_t _offset) const noexcept override
60  {
61  if (_offset >= 0) instance::from(_uv_handle)->properties().rdoffset = _offset;
62  return ::uv_read_start(static_cast< ::uv_stream_t* >(_uv_handle), alloc_cb, read_cb);
63  }
64 
65  int read_stop(void *_uv_handle) const noexcept override
66  { return ::uv_read_stop(static_cast< ::uv_stream_t* >(_uv_handle)); }
67  };
68 
69  //! \}
70  //! \endcond
71 
72 private: /*types*/
73  using instance = handle::instance< stream >;
74 
75 protected: /*constructors*/
76  //! \cond
77  stream() noexcept = default;
78 
79  explicit stream(uv_t *_uv_handle) : io(static_cast< io::uv_t* >(_uv_handle)) {}
80  //! \endcond
81 
82 public: /*constructors*/
83  ~stream() = default;
84 
85  stream(const stream&) = default;
86  stream& operator =(const stream&) = default;
87 
88  stream(stream&&) noexcept = default;
89  stream& operator =(stream&&) noexcept = default;
90 
91 private: /*functions*/
92  template< typename = void > static void alloc_cb(::uv_handle_t*, std::size_t, ::uv_buf_t*);
93  template< typename = void > static void read_cb(::uv_stream_t*, ssize_t, const ::uv_buf_t*);
94  template< typename = void > static void connection_cb(::uv_stream_t*, int);
95 
96 public: /*interface*/
97  on_connection_t& on_connection() const noexcept { return instance::from(uv_handle)->properties().connection_cb; }
98 
99  /*! \brief Start listening for incoming connections.
100  \sa libuv API documentation: [`uv_listen()`](http://docs.libuv.org/en/v1.x/stream.html#c.uv_listen).*/
101  int listen(int _backlog, const on_connection_t &_connection_cb) const
102  {
103  instance::from(uv_handle)->properties().connection_cb = _connection_cb;
104  uv_status(0);
105  auto uv_ret = ::uv_listen(static_cast< uv_t* >(uv_handle), _backlog, connection_cb);
106  if (uv_ret < 0) uv_status(uv_ret);
107  return uv_ret;
108  }
109  /*! \brief Accept incoming connections.
110  \details The function returns `stream` instance that actually is an object of one of the stream subtype:
111  `tcp`, `pipe`, or `tty` depending on the actual subtype of the stream object which this function is applied to.
112  \sa libuv API documentation: [`uv_accept()`](http://docs.libuv.org/en/v1.x/stream.html#c.uv_accept). */
113  stream accept() const;
114 
115  /*! \brief The amount of queued bytes waiting to be sent. */
116  std::size_t write_queue_size() const noexcept { return static_cast< uv_t* >(uv_handle)->write_queue_size; }
117 
118  /*! \brief Check if the stream is readable. */
119  bool is_readable() const noexcept { return uv_status(::uv_is_readable(static_cast< uv_t* >(uv_handle))); }
120  /*! \brief Check if the stream is writable. */
121  bool is_writable() const noexcept { return uv_status(::uv_is_writable(static_cast< uv_t* >(uv_handle))); }
122 
123  /*! \brief Enable or disable blocking mode for the stream.
124  \sa libuv API documentation: [`uv_stream_set_blocking()`](http://docs.libuv.org/en/v1.x/stream.html#c.uv_stream_set_blocking). */
125  int set_blocking(bool _enable) noexcept { return uv_status(::uv_stream_set_blocking(static_cast< uv_t* >(uv_handle), _enable)); }
126 
127 public: /*conversion operators*/
128  explicit operator const uv_t*() const noexcept { return static_cast< const uv_t* >(uv_handle); }
129  explicit operator uv_t*() noexcept { return static_cast< uv_t* >(uv_handle); }
130 };
131 
132 template< typename >
133 void stream::alloc_cb(::uv_handle_t *_uv_handle, std::size_t _suggested_size, ::uv_buf_t *_uv_buf)
134 { io_alloc_cb(_uv_handle, _suggested_size, _uv_buf); }
135 
136 template< typename >
137 void stream::read_cb(::uv_stream_t *_uv_stream, ssize_t _nread, const ::uv_buf_t *_uv_buf)
138 { io_read_cb(_uv_stream, _nread, _uv_buf, nullptr); }
139 
140 template< typename >
141 void stream::connection_cb(::uv_stream_t *_uv_stream, int _status)
142 {
143  auto instance_ptr = instance::from(_uv_stream);
144  instance_ptr->uv_error = _status;
145  auto &connection_cb = instance_ptr->properties().connection_cb;
146  if (connection_cb) connection_cb(stream(_uv_stream));
147 }
148 
149 
150 
151 /*! \ingroup doxy_group__handle
152  \brief TCP handle.
153  \sa libuv API documentation: [`uv_tcp_t` — TCP handle](http://docs.libuv.org/en/v1.x/tcp.html#uv-tcp-t-tcp-handle). */
154 class tcp : public stream
155 {
156  //! \cond
157  friend class handle::instance< tcp >;
158  friend class connect;
159  //! \endcond
160 
161 public: /*types*/
162  using uv_t = ::uv_tcp_t;
163 
164 private: /*types*/
165  using instance = handle::instance< tcp >;
166 
167 protected: /*constructors*/
168  //! \cond
169  explicit tcp(uv_t *_uv_handle) : stream(reinterpret_cast< stream::uv_t* >(_uv_handle)) {}
170  //! \endcond
171 
172 public: /*constructors*/
173  ~tcp() = default;
174 
175  tcp(const tcp&) = default;
176  tcp& operator =(const tcp&) = default;
177 
178  tcp(tcp&&) noexcept = default;
179  tcp& operator =(tcp&&) noexcept = default;
180 
181  /*! \brief Create a TCP socket with the specified flags.
182  \note With `AF_UNSPEC` flag no socket is actually created on the system.
183  \sa libuv API documentation: [`uv_tcp_init_ex()`](http://docs.libuv.org/en/v1.x/tcp.html#c.uv_tcp_init_ex).\n
184  libuv enhancement proposals: <https://github.com/libuv/leps/blob/master/003-create-sockets-early.md>. */
185  tcp(uv::loop &_loop, unsigned _flags = AF_UNSPEC)
186  {
187  uv_handle = instance::create();
188 
189  auto uv_ret = ::uv_tcp_init_ex(static_cast< uv::loop::uv_t* >(_loop), static_cast< uv_t* >(uv_handle), _flags);
190  if (uv_status(uv_ret) < 0) return;
191 
192  instance::from(uv_handle)->book_loop();
193  }
194  /*! \brief Create a handle object from an existing native platform depended TCP socket descriptor.
195  \sa libuv API documentation: [`uv_tcp_open()`](http://docs.libuv.org/en/v1.x/tcp.html#c.uv_tcp_open),
196  [`uv_tcp_init()`](http://docs.libuv.org/en/v1.x/tcp.html#c.uv_tcp_init). */
197  tcp(uv::loop &_loop, ::uv_os_sock_t _socket, bool _set_blocking)
198  {
199  uv_handle = instance::create();
200 
201  auto uv_ret = ::uv_tcp_init(static_cast< uv::loop::uv_t* >(_loop), static_cast< uv_t* >(uv_handle));
202  if (uv_status(uv_ret) < 0) return;
203 
204  instance::from(uv_handle)->book_loop();
205 
206  uv_ret = ::uv_tcp_open(static_cast< uv_t* >(uv_handle), _socket);
207  if (uv_status(uv_ret) < 0) return;
208 
209  if (_set_blocking) set_blocking(_set_blocking);
210  }
211 
212 public: /*interface*/
213  /*! \brief Get the platform dependent socket descriptor. The alias for `handle::fileno()`. */
214  ::uv_os_sock_t socket() const noexcept { return (::uv_os_sock_t)fileno(); }
215 
216  /*! \brief Enable or disable Nagle’s algorithm on the socket. */
217  int nodelay(bool _enable) noexcept { return uv_status(::uv_tcp_nodelay(static_cast< uv_t* >(uv_handle), _enable)); }
218  /*! \brief Enable or disable TCP keep-alive.
219  \arg `_delay` is the initial delay in seconds, ignored when `_enable = false`. */
220  int keepalive(bool _enable, unsigned int _delay) noexcept { return uv_status(::uv_tcp_keepalive(static_cast< uv_t* >(uv_handle), _enable, _delay)); }
221  /*! \details Enable or disable simultaneous asynchronous accept requests that are queued by the operating system when listening for new TCP connections.
222  \sa libuv API documentation: [`uv_tcp_simultaneous_accepts()`](http://docs.libuv.org/en/v1.x/tcp.html#c.uv_tcp_simultaneous_accepts). */
223  int simultaneous_accepts(bool _enable) noexcept { return uv_status(::uv_tcp_simultaneous_accepts(static_cast< uv_t* >(uv_handle), _enable)); }
224 
225  /*! \brief Bind the handle to an address and port.
226  \sa libuv API documentation: [`uv_tcp_bind()`](http://docs.libuv.org/en/v1.x/tcp.html#c.uv_tcp_bind). */
227  template<
228  typename _T_,
230  >
231  int bind(const _T_ &_sockaddr, unsigned int _flags = 0) noexcept
232  {
233  return uv_status(::uv_tcp_bind(static_cast< uv_t* >(uv_handle), reinterpret_cast< const ::sockaddr* >(&_sockaddr), _flags));
234  }
235 
236  /*! \brief Get the local address which this handle is bound to.
237  \returns `true` if the operation has completed successfully (can be checked with `uv_status()`) and
238  the size of the passed argument (i.e. `sizeof(_T_)`) is enough to hold the returned socket address structure.
239  \sa libuv API documentation: [`uv_tcp_getsockname()`](http://docs.libuv.org/en/v1.x/tcp.html#c.uv_tcp_getsockname). */
240  template< typename _T_, typename = std::enable_if_t< is_one_of< _T_, ::sockaddr_in, ::sockaddr_in6, ::sockaddr_storage >::value > >
241  bool getsockname(_T_ &_sockaddr) const noexcept
242  {
243  int z = sizeof(_T_);
244  return
245  uv_status(::uv_tcp_getsockname(static_cast< uv_t* >(uv_handle), reinterpret_cast< ::sockaddr* >(&_sockaddr), &z))
246  and
247  sizeof(_T_) >= z;
248  }
249  /*! \brief Get the address of the remote peer connected to this handle.
250  \returns `true` if the operation has completed successfully (can be checked with `uv_status()`) and
251  the size of the passed argument (i.e. `sizeof(_T_)`) is enough to hold the returned socket address structure.
252  \sa libuv API documentation: [`uv_tcp_getpeername()`](http://docs.libuv.org/en/v1.x/tcp.html#c.uv_tcp_getpeername). */
253  template< typename _T_, typename = std::enable_if_t< is_one_of< _T_, ::sockaddr_in, ::sockaddr_in6, ::sockaddr_storage >::value > >
254  bool getpeername(_T_ &_sockaddr) const noexcept
255  {
256  int z = sizeof(_T_);
257  return
258  uv_status(::uv_tcp_getpeername(static_cast< uv_t* >(uv_handle), reinterpret_cast< ::sockaddr* >(&_sockaddr), &z))
259  and
260  sizeof(_T_) >= z;
261  }
262 
263 #if 1
264  /*! \brief _Get_ the size of the send buffer that the operating system uses for the socket.
265  \sa libuv API documentation: [`uv_send_buffer_size()`](http://docs.libuv.org/en/v1.x/handle.html#c.uv_send_buffer_size). */
266  unsigned int send_buffer_size() const noexcept
267  {
268  unsigned int v = 0;
269  uv_status(::uv_send_buffer_size(static_cast< handle::uv_t* >(uv_handle), (int*)&v));
270  return v;
271  }
272  /*! \brief _Set_ the size of the send buffer that the operating system uses for the socket.
273  \sa libuv API documentation: [`uv_send_buffer_size()`](http://docs.libuv.org/en/v1.x/handle.html#c.uv_send_buffer_size). */
274  void send_buffer_size(unsigned int _value) noexcept { uv_status(::uv_send_buffer_size(static_cast< handle::uv_t* >(uv_handle), (int*)&_value)); }
275 
276  /*! \brief _Get_ the size of the receive buffer that the operating system uses for the socket.
277  \sa libuv API documentation: [`uv_recv_buffer_size()`](http://docs.libuv.org/en/v1.x/handle.html#c.uv_recv_buffer_size). */
278  unsigned int recv_buffer_size() const noexcept
279  {
280  unsigned int v = 0;
281  uv_status(::uv_recv_buffer_size(static_cast< handle::uv_t* >(uv_handle), (int*)&v));
282  return v;
283  }
284  /*! \brief _Set_ the size of the receive buffer that the operating system uses for the socket.
285  \sa libuv API documentation: [`uv_recv_buffer_size()`](http://docs.libuv.org/en/v1.x/handle.html#c.uv_recv_buffer_size). */
286  void recv_buffer_size(unsigned int _value) noexcept { uv_status(::uv_recv_buffer_size(static_cast< handle::uv_t* >(uv_handle), (int*)&_value)); }
287 #endif
288 
289 public: /*conversion operators*/
290  explicit operator const uv_t*() const noexcept { return static_cast< const uv_t* >(uv_handle); }
291  explicit operator uv_t*() noexcept { return static_cast< uv_t* >(uv_handle); }
292 };
293 
294 
295 
296 /*! \ingroup doxy_group__handle
297  \brief Pipe handle.
298  \sa libuv API documentation: [`uv_pipe_t` — Pipe handle](http://docs.libuv.org/en/v1.x/pipe.html#uv-pipe-t-pipe-handle). */
299 class pipe : public stream
300 {
301  //! \cond
302  friend class handle::instance< pipe >;
303  friend class connect;
304  friend class write;
305  friend class process;
306  //! \endcond
307 
308 public: /*types*/
309  using uv_t = ::uv_pipe_t;
310 
311 private: /*types*/
312  using instance = handle::instance< pipe >;
313 
314 protected: /*constructors*/
315  //! \cond
316  explicit pipe(uv_t *_uv_handle) : stream(reinterpret_cast< stream::uv_t* >(_uv_handle)) {}
317 
318  pipe(uv::loop &_loop, bool _ipc)
319  {
320  uv_handle = instance::create();
321 
322  auto uv_ret = ::uv_pipe_init(static_cast< uv::loop::uv_t* >(_loop), static_cast< uv_t* >(uv_handle), _ipc);
323  if (uv_status(uv_ret) < 0) return;
324 
325  instance::from(uv_handle)->book_loop();
326  }
327  //! \endcond
328 
329 public: /*constructors*/
330  ~pipe() = default;
331 
332  pipe(const pipe&) = default;
333  pipe& operator =(const pipe&) = default;
334 
335  pipe(pipe&&) noexcept = default;
336  pipe& operator =(pipe&&) noexcept = default;
337 
338  /*! \brief Create a pipe bound to a file path (Unix domain socket) or a name (Windows named pipe).
339  \sa libuv API documentation: [`uv_pipe_init()`](http://docs.libuv.org/en/v1.x/pipe.html#c.uv_pipe_init),
340  [`uv_pipe_bind()`](http://docs.libuv.org/en/v1.x/pipe.html#c.uv_pipe_bind). */
341  pipe(uv::loop &_loop, const char* _name, bool _ipc)
342  : pipe(_loop, _ipc)
343  {
344  if (uv_status() < 0) return;
345  uv_status(::uv_pipe_bind(static_cast< uv_t* >(uv_handle), _name));
346  }
347  /*! \brief Create a pipe object from an existing OS native pipe descriptor.
348  \sa libuv API documentation: [`uv_pipe_open()`](http://docs.libuv.org/en/v1.x/pipe.html#c.uv_pipe_open). */
349  pipe(uv::loop &_loop, ::uv_file _fd, bool _ipc, bool _set_blocking)
350  : pipe(_loop, _ipc)
351  {
352  if (uv_status() < 0) return;
353 
354  auto uv_ret = ::uv_pipe_open(static_cast< uv_t* >(uv_handle), _fd);
355  if (uv_status(uv_ret) < 0) return;
356 
357  if (_set_blocking) set_blocking(_set_blocking);
358  }
359 
360 public: /*interface*/
361  /*! \brief Non-zero if this pipe is used for passing handles. */
362  int ipc() const noexcept { return static_cast< uv_t* >(uv_handle)->ipc; }
363 
364  /*! \brief Get the name of the Unix domain socket or the Windows named pipe for this pipe object. */
365  std::string getsockname() const noexcept
366  {
367 #ifdef UNIX_PATH_MAX
368  std::size_t len = UNIX_PATH_MAX;
369 #else
370  std::size_t len = 108;
371 #endif
372  std::string name(len, '\0');
373  while (
374  uv_status(::uv_pipe_getsockname(static_cast< uv_t* >(uv_handle), const_cast< char* >(name.c_str()), &len)) < 0
375  and
376  uv_status() == UV_ENOBUFS
377  ) name.resize(len, '\0');
378  return name;
379  }
380  /*! \brief Get the name of the Unix domain socket or the Windows named pipe which this pipe object is connected to. */
381  std::string getpeername() const noexcept
382  {
383 #ifdef UNIX_PATH_MAX
384  std::size_t len = UNIX_PATH_MAX;
385 #else
386  std::size_t len = 108;
387 #endif
388  std::string name(len, '\0');
389  while (
390  uv_status(::uv_pipe_getpeername(static_cast< uv_t* >(uv_handle), const_cast< char* >(name.c_str()), &len)) < 0
391  and
392  uv_status() == UV_ENOBUFS
393  ) name.resize(len, '\0');
394  return name;
395  }
396  /*! \brief Set the number of pending pipe instances when this pipe server is waiting for connections. (_Windows only._) */
397  void pending_instances(int _count) noexcept { ::uv_pipe_pending_instances(static_cast< uv_t* >(uv_handle), _count); }
398 
399  /*! \brief The number of pending handles being sent over the IPC pipe.
400  \details Used in conjunction with `accept_pending_handle()`. */
401  int pending_handle_count() const noexcept { return ::uv_pipe_pending_count(static_cast< uv_t* >(uv_handle)); }
402  /*! \brief Used to receive handles over the IPC pipe.
403  \sa libuv API documentation: [`uv_pipe_pending_type()`](http://docs.libuv.org/en/v1.x/pipe.html#c.uv_pipe_pending_type). */
405 
406 #if 1
407  /*! \brief _Get_ the size of the send buffer that the operating system uses for the pipe.
408  \sa libuv API documentation: [`uv_send_buffer_size()`](http://docs.libuv.org/en/v1.x/handle.html#c.uv_send_buffer_size). */
409  unsigned int send_buffer_size() const noexcept
410  {
411  unsigned int v = 0;
412  uv_status(::uv_send_buffer_size(static_cast< handle::uv_t* >(uv_handle), (int*)&v));
413  return v;
414  }
415  /*! \brief _Set_ the size of the send buffer that the operating system uses for the pipe.
416  \sa libuv API documentation: [`uv_send_buffer_size()`](http://docs.libuv.org/en/v1.x/handle.html#c.uv_send_buffer_size). */
417  void send_buffer_size(unsigned int _value) noexcept { uv_status(::uv_send_buffer_size(static_cast< handle::uv_t* >(uv_handle), (int*)&_value)); }
418 
419  /*! \brief _Get_ the size of the receive buffer that the operating system uses for the pipe.
420  \sa libuv API documentation: [`uv_recv_buffer_size()`](http://docs.libuv.org/en/v1.x/handle.html#c.uv_recv_buffer_size). */
421  unsigned int recv_buffer_size() const noexcept
422  {
423  unsigned int v = 0;
424  uv_status(::uv_recv_buffer_size(static_cast< handle::uv_t* >(uv_handle), (int*)&v));
425  return v;
426  }
427  /*! \brief _Set_ the size of the receive buffer that the operating system uses for the pipe.
428  \sa libuv API documentation: [`uv_recv_buffer_size()`](http://docs.libuv.org/en/v1.x/handle.html#c.uv_recv_buffer_size). */
429  void recv_buffer_size(unsigned int _value) noexcept { uv_status(::uv_recv_buffer_size(static_cast< handle::uv_t* >(uv_handle), (int*)&_value)); }
430 #endif
431 
432 public: /*conversion operators*/
433  explicit operator const uv_t*() const noexcept { return static_cast< const uv_t* >(uv_handle); }
434  explicit operator uv_t*() noexcept { return static_cast< uv_t* >(uv_handle); }
435 };
436 
437 
438 
439 /*! \ingroup doxy_group__handle
440  \brief TTY handle.
441  \sa libuv API documentation: [`uv_tty_t` — TTY handle](http://docs.libuv.org/en/v1.x/tty.html#uv-tty-t-tty-handle). */
442 class tty : public stream
443 {
444  //! \cond
445  friend class handle::instance< tty >;
446  //! \endcond
447 
448 public: /*types*/
449  using uv_t = ::uv_tty_t;
450 
451 private: /*types*/
452  using instance = handle::instance< pipe >;
453 
454 protected: /*constructors*/
455  //! \cond
456  explicit tty(uv_t *_uv_handle) : stream(reinterpret_cast< stream::uv_t* >(_uv_handle)) {}
457  //! \endcond
458 
459 public: /*constructors*/
460  ~tty() = default;
461 
462  tty(const tty&) = default;
463  tty& operator =(const tty&) = default;
464 
465  tty(tty&&) noexcept = default;
466  tty& operator =(tty&&) noexcept = default;
467 
468  /*! \brief Create a tty object from the given TTY file descriptor.
469  \sa libuv API documentation: [`uv_tty_init()`](http://docs.libuv.org/en/v1.x/tty.html#c.uv_tty_init). */
470  tty(uv::loop &_loop, ::uv_file _fd, bool _readable, bool _set_blocking)
471  {
472  uv_handle = instance::create();
473 
474  auto uv_ret = ::uv_tty_init(static_cast< uv::loop::uv_t* >(_loop), static_cast< uv_t* >(uv_handle), _fd, _readable);
475  if (uv_status(uv_ret) < 0) return;
476 
477  instance::from(uv_handle)->book_loop();
478 
479  if (_set_blocking) set_blocking(_set_blocking);
480  }
481 
482 public: /*interface*/
483  /*! \brief Set the TTY using the specified terminal mode.
484  \sa libuv API documentation: [`uv_tty_set_mode()`](http://docs.libuv.org/en/v1.x/tty.html#c.uv_tty_set_mode),
485  [`uv_tty_mode_t`](http://docs.libuv.org/en/v1.x/tty.html#c.uv_tty_mode_t). */
486  int set_mode(::uv_tty_mode_t _mode) noexcept
487  {
488  return uv_status(::uv_tty_set_mode(static_cast< uv_t* >(uv_handle), _mode));
489  }
490 
491  /*! \brief Get the current window size.
492  \sa libuv API documentation: [`uv_tty_get_winsize()`](http://docs.libuv.org/en/v1.x/tty.html#c.uv_tty_get_winsize). */
493  int get_winsize(int &_width, int &_height) const noexcept
494  {
495  return uv_status(::uv_tty_get_winsize(static_cast< uv_t* >(uv_handle), &_width, &_height));
496  }
497 
498  /*! \brief Reset TTY settings to default values. To be called when the program exits.
499  \sa libuv API documentation: [`uv_tty_reset_mode()`](http://docs.libuv.org/en/v1.x/tty.html#c.uv_tty_reset_mode). */
500  static int reset_mode() noexcept { return ::uv_tty_reset_mode(); }
501 
502 public: /*conversion operators*/
503  explicit operator const uv_t*() const noexcept { return static_cast< const uv_t* >(uv_handle); }
504  explicit operator uv_t*() noexcept { return static_cast< uv_t* >(uv_handle); }
505 };
506 
507 
508 
509 inline stream stream::accept() const
510 {
511  stream client;
512 
513  switch (static_cast< uv_t* >(uv_handle)->type)
514  {
515  case UV_NAMED_PIPE:
516  client.uv_handle = handle::instance< pipe >::create();
517  client.uv_status(::uv_pipe_init(
518  static_cast< ::uv_pipe_t* >(uv_handle)->loop,
519  static_cast< ::uv_pipe_t* >(client.uv_handle),
520  static_cast< ::uv_pipe_t* >(uv_handle)->ipc
521  ));
522  if (client) handle::instance< pipe >::from(client.uv_handle)->book_loop();
523  break;
524  case UV_TCP:
525  client.uv_handle = handle::instance< tcp >::create();
526  client.uv_status(::uv_tcp_init(
527  static_cast< ::uv_tcp_t* >(uv_handle)->loop,
528  static_cast< ::uv_tcp_t* >(client.uv_handle)
529  ));
530  if (client) handle::instance< tcp >::from(client.uv_handle)->book_loop();
531  break;
532  case UV_TTY:
533  client.uv_status(UV_ENOTSUP);
534  break;
535  default:
536  client.uv_status(UV_EBADF);
537  break;
538  }
539 
540  if (!client)
541  uv_status(client.uv_status());
542  else
543  {
544  auto uv_ret = ::uv_accept(static_cast< uv_t* >(uv_handle), static_cast< uv_t* >(client));
545  if (uv_status(uv_ret) < 0) client.uv_status(uv_ret);
546  }
547 
548  return client;
549 }
550 
551 
553 {
554  stream fd;
555 
556  switch (::uv_pipe_pending_type(static_cast< uv_t* >(uv_handle)))
557  {
558  case UV_NAMED_PIPE:
559  fd.uv_handle = handle::instance< pipe >::create();
560  fd.uv_status(::uv_pipe_init(
561  static_cast< uv_t* >(uv_handle)->loop,
562  static_cast< ::uv_pipe_t* >(fd.uv_handle),
563  static_cast< uv_t* >(uv_handle)->ipc
564  ));
565  if (fd) handle::instance< pipe >::from(fd.uv_handle)->book_loop();
566  break;
567  case UV_TCP:
568  fd.uv_handle = handle::instance< tcp >::create();
569  fd.uv_status(::uv_tcp_init(
570  static_cast< uv_t* >(uv_handle)->loop,
571  static_cast< ::uv_tcp_t* >(fd.uv_handle)
572  ));
573  if (fd) handle::instance< tcp >::from(fd.uv_handle)->book_loop();
574  break;
575  default:
576  fd.uv_status(UV_EBADF);
577  break;
578  }
579 
580  if (!fd)
581  uv_status(fd.uv_status());
582  else
583  {
584  auto uv_ret = ::uv_accept(static_cast< ::uv_stream_t* >(uv_handle), static_cast< ::uv_stream_t* >(fd));
585  if (uv_status(uv_ret) < 0) fd.uv_status(uv_ret);
586  }
587 
588  return fd;
589 }
590 
591 
592 }
593 
594 
595 #endif
Namespace for all uvcc definitions.
Definition: buffer.hpp:17
int keepalive(bool _enable, unsigned int _delay) noexcept
Enable or disable TCP keep-alive.
tcp(uv::loop &_loop, ::uv_os_sock_t _socket, bool _set_blocking)
Create a handle object from an existing native platform depended TCP socket descriptor.
static int reset_mode() noexcept
Reset TTY settings to default values. To be called when the program exits.
bool getsockname(_T_ &_sockaddr) const noexcept
Get the local address which this handle is bound to.
Stream handle.
tcp(uv::loop &_loop, unsigned _flags=AF_UNSPEC)
Create a TCP socket with the specified flags.
int bind(const _T_ &_sockaddr, unsigned int _flags=0) noexcept
Bind the handle to an address and port.
tty(uv::loop &_loop, ::uv_file _fd, bool _readable, bool _set_blocking)
Create a tty object from the given TTY file descriptor.
bool getpeername(_T_ &_sockaddr) const noexcept
Get the address of the remote peer connected to this handle.
int set_mode(::uv_tty_mode_t _mode) noexcept
Set the TTY using the specified terminal mode.
std::string getpeername() const noexcept
Get the name of the Unix domain socket or the Windows named pipe which this pipe object is connected ...
pipe(uv::loop &_loop, const char *_name, bool _ipc)
Create a pipe bound to a file path (Unix domain socket) or a name (Windows named pipe).
void recv_buffer_size(unsigned int _value) noexcept
Set the size of the receive buffer that the operating system uses for the socket. ...
void send_buffer_size(unsigned int _value) noexcept
Set the size of the send buffer that the operating system uses for the socket.
TTY handle.
stream accept_pending_handle() const
Used to receive handles over the IPC pipe.
int uv_status() const noexcept
The status value returned by the last executed libuv API function on this handle. ...
The base class for the libuv handles.
Definition: handle-base.hpp:33
std::string getsockname() const noexcept
Get the name of the Unix domain socket or the Windows named pipe for this pipe object.
std::size_t write_queue_size() const noexcept
The amount of queued bytes waiting to be sent.
void send_buffer_size(unsigned int _value) noexcept
Set the size of the send buffer that the operating system uses for the pipe.
pipe(uv::loop &_loop, ::uv_file _fd, bool _ipc, bool _set_blocking)
Create a pipe object from an existing OS native pipe descriptor.
The I/O event loop class.
Definition: loop.hpp:33
unsigned int recv_buffer_size() const noexcept
Get the size of the receive buffer that the operating system uses for the pipe.
bool is_writable() const noexcept
Check if the stream is writable.
The base class for handles representing I/O endpoints: a file, TCP/UDP socket, pipe, TTY.
Definition: handle-io.hpp:25
Pipe handle.
TCP handle.
int get_winsize(int &_width, int &_height) const noexcept
Get the current window size.
int simultaneous_accepts(bool _enable) noexcept
void pending_instances(int _count) noexcept
Set the number of pending pipe instances when this pipe server is waiting for connections. (Windows only.)
int ipc() const noexcept
Non-zero if this pipe is used for passing handles.
unsigned int recv_buffer_size() const noexcept
Get the size of the receive buffer that the operating system uses for the socket. ...
int set_blocking(bool _enable) noexcept
Enable or disable blocking mode for the stream.
unsigned int send_buffer_size() const noexcept
Get the size of the send buffer that the operating system uses for the pipe.
int pending_handle_count() const noexcept
The number of pending handles being sent over the IPC pipe.
stream accept() const
Accept incoming connections.
bool is_readable() const noexcept
Check if the stream is readable.
::uv_os_sock_t socket() const noexcept
Get the platform dependent socket descriptor. The alias for handle::fileno().
void recv_buffer_size(unsigned int _value) noexcept
Set the size of the receive buffer that the operating system uses for the pipe.
int listen(int _backlog, const on_connection_t &_connection_cb) const
Start listening for incoming connections.
int nodelay(bool _enable) noexcept
Enable or disable Nagle’s algorithm on the socket.
unsigned int send_buffer_size() const noexcept
Get the size of the send buffer that the operating system uses for the socket.