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