1 // Copyright Joyent, Inc. and other Node contributors. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a 4 // copy of this software and associated documentation files (the 5 // "Software"), to deal in the Software without restriction, including 6 // without limitation the rights to use, copy, modify, merge, publish, 7 // distribute, sublicense, and/or sell copies of the Software, and to permit 8 // persons to whom the Software is furnished to do so, subject to the 9 // following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included 12 // in all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22 #ifndef SRC_UDP_WRAP_H_ 23 #define SRC_UDP_WRAP_H_ 24 25 #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 26 27 #include "handle_wrap.h" 28 #include "req_wrap.h" 29 #include "node_sockaddr.h" 30 #include "uv.h" 31 #include "v8.h" 32 33 namespace node { 34 35 class UDPWrapBase; 36 37 // A listener that can be attached to an `UDPWrapBase` object and generally 38 // manages its I/O activity. This is similar to `StreamListener`. 39 class UDPListener { 40 public: 41 virtual ~UDPListener(); 42 43 // Called right before data is received from the socket. Must return a 44 // buffer suitable for reading data into, that is then passed to OnRecv. 45 virtual uv_buf_t OnAlloc(size_t suggested_size) = 0; 46 47 // Called right after data is received from the socket, and includes 48 // information about the source address. If `nread` is negative, an error 49 // has occurred, and it represents a libuv error code. 50 virtual void OnRecv(ssize_t nread, 51 const uv_buf_t& buf, 52 const sockaddr* addr, 53 unsigned int flags) = 0; 54 55 // Called when an asynchronous request for writing data is created. 56 // The `msg_size` value contains the total size of the data to be sent, 57 // but may be ignored by the implementation of this Method. 58 // The return value is later passed to OnSendDone. 59 virtual ReqWrap<uv_udp_send_t>* CreateSendWrap(size_t msg_size) = 0; 60 61 // Called when an asynchronous request for writing data has finished. 62 // If status is negative, an error has occurred, and it represents a libuv 63 // error code. 64 virtual void OnSendDone(ReqWrap<uv_udp_send_t>* wrap, int status) = 0; 65 66 // Optional callback that is called after the socket has been bound. OnAfterBind()67 virtual void OnAfterBind() {} 68 udp()69 inline UDPWrapBase* udp() const { return wrap_; } 70 71 protected: 72 UDPWrapBase* wrap_ = nullptr; 73 74 friend class UDPWrapBase; 75 }; 76 77 class UDPWrapBase { 78 public: 79 // While UDPWrapBase itself does not extend from HandleWrap, classes 80 // derived from it will (like UDPWrap) 81 enum InternalFields { 82 kUDPWrapBaseField = HandleWrap::kInternalFieldCount, 83 kInternalFieldCount 84 }; 85 virtual ~UDPWrapBase(); 86 87 // Start emitting OnAlloc() + OnRecv() events on the listener. 88 virtual int RecvStart() = 0; 89 90 // Stop emitting OnAlloc() + OnRecv() events on the listener. 91 virtual int RecvStop() = 0; 92 93 // Send a chunk of data over this socket. This may call CreateSendWrap() 94 // on the listener if an async transmission is necessary. 95 virtual ssize_t Send(uv_buf_t* bufs, 96 size_t nbufs, 97 const sockaddr* addr) = 0; 98 99 virtual SocketAddress GetPeerName() = 0; 100 virtual SocketAddress GetSockName() = 0; 101 102 // Returns an AsyncWrap object with the same lifetime as this object. 103 virtual AsyncWrap* GetAsyncWrap() = 0; 104 105 void set_listener(UDPListener* listener); 106 UDPListener* listener() const; 107 108 static UDPWrapBase* FromObject(v8::Local<v8::Object> obj); 109 110 static void RecvStart(const v8::FunctionCallbackInfo<v8::Value>& args); 111 static void RecvStop(const v8::FunctionCallbackInfo<v8::Value>& args); 112 static void AddMethods(Environment* env, v8::Local<v8::FunctionTemplate> t); 113 114 private: 115 UDPListener* listener_ = nullptr; 116 }; 117 118 class UDPWrap final : public HandleWrap, 119 public UDPWrapBase, 120 public UDPListener { 121 public: 122 enum SocketType { 123 SOCKET 124 }; 125 static void Initialize(v8::Local<v8::Object> target, 126 v8::Local<v8::Value> unused, 127 v8::Local<v8::Context> context, 128 void* priv); 129 static void GetFD(const v8::FunctionCallbackInfo<v8::Value>& args); 130 static void New(const v8::FunctionCallbackInfo<v8::Value>& args); 131 static void Open(const v8::FunctionCallbackInfo<v8::Value>& args); 132 static void Bind(const v8::FunctionCallbackInfo<v8::Value>& args); 133 static void Connect(const v8::FunctionCallbackInfo<v8::Value>& args); 134 static void Send(const v8::FunctionCallbackInfo<v8::Value>& args); 135 static void Bind6(const v8::FunctionCallbackInfo<v8::Value>& args); 136 static void Connect6(const v8::FunctionCallbackInfo<v8::Value>& args); 137 static void Send6(const v8::FunctionCallbackInfo<v8::Value>& args); 138 static void Disconnect(const v8::FunctionCallbackInfo<v8::Value>& args); 139 static void AddMembership(const v8::FunctionCallbackInfo<v8::Value>& args); 140 static void DropMembership(const v8::FunctionCallbackInfo<v8::Value>& args); 141 static void AddSourceSpecificMembership( 142 const v8::FunctionCallbackInfo<v8::Value>& args); 143 static void DropSourceSpecificMembership( 144 const v8::FunctionCallbackInfo<v8::Value>& args); 145 static void SetMulticastInterface( 146 const v8::FunctionCallbackInfo<v8::Value>& args); 147 static void BufferSize(const v8::FunctionCallbackInfo<v8::Value>& args); 148 static void GetSendQueueSize(const v8::FunctionCallbackInfo<v8::Value>& args); 149 static void GetSendQueueCount( 150 const v8::FunctionCallbackInfo<v8::Value>& args); 151 152 // UDPListener implementation 153 uv_buf_t OnAlloc(size_t suggested_size) override; 154 void OnRecv(ssize_t nread, 155 const uv_buf_t& buf, 156 const sockaddr* addr, 157 unsigned int flags) override; 158 ReqWrap<uv_udp_send_t>* CreateSendWrap(size_t msg_size) override; 159 void OnSendDone(ReqWrap<uv_udp_send_t>* wrap, int status) override; 160 161 // UDPWrapBase implementation 162 int RecvStart() override; 163 int RecvStop() override; 164 ssize_t Send(uv_buf_t* bufs, 165 size_t nbufs, 166 const sockaddr* addr) override; 167 168 SocketAddress GetPeerName() override; 169 SocketAddress GetSockName() override; 170 171 AsyncWrap* GetAsyncWrap() override; 172 GetLibuvHandle()173 inline uv_udp_t* GetLibuvHandle() { return &handle_; } 174 175 static v8::MaybeLocal<v8::Object> Instantiate(Environment* env, 176 AsyncWrap* parent, 177 SocketType type); 178 SET_NO_MEMORY_INFO() 179 SET_MEMORY_INFO_NAME(UDPWrap) 180 SET_SELF_SIZE(UDPWrap) 181 182 private: 183 typedef uv_udp_t HandleType; 184 185 template <typename T, 186 int (*F)(const typename T::HandleType*, sockaddr*, int*)> 187 friend void GetSockOrPeerName(const v8::FunctionCallbackInfo<v8::Value>&); 188 189 UDPWrap(Environment* env, v8::Local<v8::Object> object); 190 191 static void DoBind(const v8::FunctionCallbackInfo<v8::Value>& args, 192 int family); 193 static void DoConnect(const v8::FunctionCallbackInfo<v8::Value>& args, 194 int family); 195 static void DoSend(const v8::FunctionCallbackInfo<v8::Value>& args, 196 int family); 197 static void SetMembership(const v8::FunctionCallbackInfo<v8::Value>& args, 198 uv_membership membership); 199 static void SetSourceMembership( 200 const v8::FunctionCallbackInfo<v8::Value>& args, 201 uv_membership membership); 202 203 static void OnAlloc(uv_handle_t* handle, 204 size_t suggested_size, 205 uv_buf_t* buf); 206 static void OnRecv(uv_udp_t* handle, 207 ssize_t nread, 208 const uv_buf_t* buf, 209 const struct sockaddr* addr, 210 unsigned int flags); 211 212 uv_udp_t handle_; 213 214 bool current_send_has_callback_; 215 v8::Local<v8::Object> current_send_req_wrap_; 216 }; 217 218 int sockaddr_for_family(int address_family, 219 const char* address, 220 const unsigned short port, 221 sockaddr_storage* addr); 222 223 } // namespace node 224 225 #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 226 227 #endif // SRC_UDP_WRAP_H_ 228