1 #pragma once
2 
3 
4 #include <cstddef>
5 #include <utility>
6 #include <memory>
7 #include <uv.h>
8 #include "resource.hpp"
9 #include "util.hpp"
10 
11 
12 namespace uvw {
13 
14 
15 /**
16  * @brief CloseEvent event.
17  *
18  * It will be emitted by the handles according with their functionalities.
19  */
20 struct CloseEvent {};
21 
22 
23 /**
24  * @brief Handle base class.
25  *
26  * Base type for all `uvw` handle types.
27  */
28 template<typename T, typename U>
29 class Handle: public BaseHandle, public Resource<T, U>
30 {
closeCallback(uv_handle_t * handle)31     static void closeCallback(uv_handle_t *handle) {
32         Handle<T, U> &ref = *(static_cast<T*>(handle->data));
33         auto ptr = ref.shared_from_this();
34         (void)ptr;
35         ref.reset();
36         ref.publish(CloseEvent{});
37     }
38 
39 protected:
allocCallback(uv_handle_t *,std::size_t suggested,uv_buf_t * buf)40     static void allocCallback(uv_handle_t *, std::size_t suggested, uv_buf_t *buf) {
41         auto size = static_cast<unsigned int>(suggested);
42         *buf = uv_buf_init(new char[size], size);
43     }
44 
45     template<typename F, typename... Args>
initialize(F && f,Args &&...args)46     bool initialize(F &&f, Args&&... args) {
47         if(!this->self()) {
48             auto err = std::forward<F>(f)(this->parent(), this->get(), std::forward<Args>(args)...);
49 
50             if(err) {
51                 this->publish(ErrorEvent{err});
52             } else {
53                 this->leak();
54             }
55         }
56 
57         return this->self();
58     }
59 
60     template<typename F, typename... Args>
invoke(F && f,Args &&...args)61     void invoke(F &&f, Args&&... args) {
62         auto err = std::forward<F>(f)(std::forward<Args>(args)...);
63         if(err) { Emitter<T>::publish(ErrorEvent{err}); }
64     }
65 
66 public:
67     using Resource<T, U>::Resource;
68 
69     /**
70      * @brief Gets the category of the handle.
71      *
72      * A base handle offers no functionality to promote it to the actual handle
73      * type. By means of this function, an opaque value that identifies the
74      * category of the handle is made available to the users.
75      *
76      * @return The actual category of the handle.
77      */
category() const78     HandleCategory category() const noexcept override {
79         return HandleCategory{this->template get<uv_handle_t>()->type};
80     }
81 
82     /**
83      * @brief Gets the type of the handle.
84      *
85      * A base handle offers no functionality to promote it to the actual handle
86      * type. By means of this function, the type of the underlying handle as
87      * specified by HandleType is made available to the users.
88      *
89      * @return The actual type of the handle.
90      */
type() const91     HandleType type() const noexcept override {
92         return Utilities::guessHandle(category());
93     }
94 
95     /**
96      * @brief Checks if the handle is active.
97      *
98      * What _active_ means depends on the type of handle:
99      *
100      * * An AsyncHandle handle is always active and cannot be deactivated,
101      * except by closing it with uv_close().
102      * * A PipeHandle, TcpHandle, UDPHandle, etc. handle - basically any handle
103      * that deals with I/O - is active when it is doing something that involves
104      * I/O, like reading, writing, connecting, accepting new connections, etc.
105      * * A CheckHandle, IdleHandle, TimerHandle, etc. handle is active when it
106      * has been started with a call to `start()`.
107      *
108      * Rule of thumb: if a handle of type `FooHandle` has a `start()` member
109      * method, then it’s active from the moment that method is called. Likewise,
110      * `stop()` deactivates the handle again.
111      *
112      * @return True if the handle is active, false otherwise.
113      */
active() const114     bool active() const noexcept override {
115         return !(uv_is_active(this->template get<uv_handle_t>()) == 0);
116     }
117 
118     /**
119      * @brief Checks if a handle is closing or closed.
120      *
121      * This function should only be used between the initialization of the
122      * handle and the arrival of the close callback.
123      *
124      * @return True if the handle is closing or closed, false otherwise.
125      */
closing() const126     bool closing() const noexcept override {
127         return !(uv_is_closing(this->template get<uv_handle_t>()) == 0);
128     }
129 
130     /**
131      * @brief Request handle to be closed.
132      *
133      * This **must** be called on each handle before memory is released.<br/>
134      * In-progress requests are cancelled and this can result in an ErrorEvent
135      * emitted.
136      *
137      * The handle will emit a CloseEvent when finished.
138      */
close()139     void close() noexcept override {
140         if(!closing()) {
141             uv_close(this->template get<uv_handle_t>(), &Handle<T, U>::closeCallback);
142         }
143     }
144 
145     /**
146      * @brief Reference the given handle.
147      *
148      * References are idempotent, that is, if a handle is already referenced
149      * calling this function again will have no effect.
150      */
reference()151     void reference() noexcept override {
152         uv_ref(this->template get<uv_handle_t>());
153     }
154 
155     /**
156      * @brief Unreference the given handle.
157      *
158      * References are idempotent, that is, if a handle is not referenced calling
159      * this function again will have no effect.
160      */
unreference()161     void unreference() noexcept override {
162         uv_unref(this->template get<uv_handle_t>());
163     }
164 
165     /**
166      * @brief Checks if the given handle referenced.
167      * @return True if the handle referenced, false otherwise.
168      */
referenced() const169     bool referenced() const noexcept override {
170         return !(uv_has_ref(this->template get<uv_handle_t>()) == 0);
171     }
172 
173     /**
174      * @brief Returns the size of the underlying handle type.
175      * @return The size of the underlying handle type.
176      */
size() const177     std::size_t size() const noexcept {
178         return uv_handle_size(this->template get<uv_handle_t>()->type);
179     }
180 
181     /**
182      * @brief Gets the size of the send buffer used for the socket.
183      *
184      * Gets the size of the send buffer that the operating system uses for the
185      * socket.<br/>
186      * This function works for TcpHandle, PipeHandle and UDPHandle handles on
187      * Unix and for TcpHandle and UDPHandle handles on Windows.<br/>
188      * Note that Linux will return double the size of the original set value.
189      *
190      * @return The size of the send buffer, 0 in case of errors.
191      */
sendBufferSize()192     int sendBufferSize() {
193         int value = 0;
194         auto err = uv_send_buffer_size(this->template get<uv_handle_t>(), &value);
195         return err ? 0 : value;
196     }
197 
198     /**
199      * @brief Sets the size of the send buffer used for the socket.
200      *
201      * Sets the size of the send buffer that the operating system uses for the
202      * socket.<br/>
203      * This function works for TcpHandle, PipeHandle and UDPHandle handles on
204      * Unix and for TcpHandle and UDPHandle handles on Windows.<br/>
205      * Note that Linux will set double the size.
206      *
207      * @return True in case of success, false otherwise.
208      */
sendBufferSize(int value)209     bool sendBufferSize(int value) {
210         return (0 == uv_send_buffer_size(this->template get<uv_handle_t>(), &value));
211     }
212 
213     /**
214      * @brief Gets the size of the receive buffer used for the socket.
215      *
216      * Gets the size of the receive buffer that the operating system uses for
217      * the socket.<br/>
218      * This function works for TcpHandle, PipeHandle and UDPHandle handles on
219      * Unix and for TcpHandle and UDPHandle handles on Windows.<br/>
220      * Note that Linux will return double the size of the original set value.
221      *
222      * @return The size of the receive buffer, 0 in case of errors.
223      */
recvBufferSize()224     int recvBufferSize() {
225         int value = 0;
226         auto err = uv_recv_buffer_size(this->template get<uv_handle_t>(), &value);
227         return err ? 0 : value;
228     }
229 
230     /**
231      * @brief Sets the size of the receive buffer used for the socket.
232      *
233      * Sets the size of the receive buffer that the operating system uses for
234      * the socket.<br/>
235      * This function works for TcpHandle, PipeHandle and UDPHandle handles on
236      * Unix and for TcpHandle and UDPHandle handles on Windows.<br/>
237      * Note that Linux will set double the size.
238      *
239      * @return True in case of success, false otherwise.
240      */
recvBufferSize(int value)241     bool recvBufferSize(int value) {
242         return (0 == uv_recv_buffer_size(this->template get<uv_handle_t>(), &value));
243     }
244 
245     /**
246      * @brief Gets the platform dependent file descriptor equivalent.
247      *
248      * Supported handles:
249      *
250      * * TcpHandle
251      * * PipeHandle
252      * * TTYHandle
253      * * UDPHandle
254      * * PollHandle
255      *
256      * It will emit an ErrorEvent event if invoked on any other handle.<br/>
257      * If a handle doesn’t have an attached file descriptor yet or the handle
258      * itself has been closed, an ErrorEvent event will be emitted.
259      *
260      * See the official
261      * [documentation](http://docs.libuv.org/en/v1.x/handle.html#c.uv_fileno)
262      * for further details.
263      *
264      * @return The file descriptor attached to the hande or a negative value in
265      * case of errors.
266      */
fileno() const267     OSFileDescriptor fileno() const {
268         uv_os_fd_t fd;
269         uv_fileno(this->template get<uv_handle_t>(), &fd);
270         return fd;
271     }
272 };
273 
274 
275 }
276