Line | Count | Source |
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 ExternalReferenceRegistry; |
36 | | class UDPWrapBase; |
37 | | |
38 | | // A listener that can be attached to an `UDPWrapBase` object and generally |
39 | | // manages its I/O activity. This is similar to `StreamListener`. |
40 | | class UDPListener { |
41 | | public: |
42 | | virtual ~UDPListener(); |
43 | | |
44 | | // Called right before data is received from the socket. Must return a |
45 | | // buffer suitable for reading data into, that is then passed to OnRecv. |
46 | | virtual uv_buf_t OnAlloc(size_t suggested_size) = 0; |
47 | | |
48 | | // Called right after data is received from the socket, and includes |
49 | | // information about the source address. If `nread` is negative, an error |
50 | | // has occurred, and it represents a libuv error code. |
51 | | virtual void OnRecv(ssize_t nread, |
52 | | const uv_buf_t& buf, |
53 | | const sockaddr* addr, |
54 | | unsigned int flags) = 0; |
55 | | |
56 | | // Called when an asynchronous request for writing data is created. |
57 | | // The `msg_size` value contains the total size of the data to be sent, |
58 | | // but may be ignored by the implementation of this Method. |
59 | | // The return value is later passed to OnSendDone. |
60 | | virtual ReqWrap<uv_udp_send_t>* CreateSendWrap(size_t msg_size) = 0; |
61 | | |
62 | | // Called when an asynchronous request for writing data has finished. |
63 | | // If status is negative, an error has occurred, and it represents a libuv |
64 | | // error code. |
65 | | virtual void OnSendDone(ReqWrap<uv_udp_send_t>* wrap, int status) = 0; |
66 | | |
67 | | // Optional callback that is called after the socket has been bound. |
68 | 0 | virtual void OnAfterBind() {} |
69 | | |
70 | 0 | inline UDPWrapBase* udp() const { return wrap_; } |
71 | | |
72 | | protected: |
73 | | UDPWrapBase* wrap_ = nullptr; |
74 | | |
75 | | friend class UDPWrapBase; |
76 | | }; |
77 | | |
78 | | class UDPWrapBase { |
79 | | public: |
80 | | // While UDPWrapBase itself does not extend from HandleWrap, classes |
81 | | // derived from it will (like UDPWrap) |
82 | | enum InternalFields { |
83 | | kUDPWrapBaseField = HandleWrap::kInternalFieldCount, |
84 | | kInternalFieldCount |
85 | | }; |
86 | | virtual ~UDPWrapBase(); |
87 | | |
88 | | // Start emitting OnAlloc() + OnRecv() events on the listener. |
89 | | virtual int RecvStart() = 0; |
90 | | |
91 | | // Stop emitting OnAlloc() + OnRecv() events on the listener. |
92 | | virtual int RecvStop() = 0; |
93 | | |
94 | | // Send a chunk of data over this socket. This may call CreateSendWrap() |
95 | | // on the listener if an async transmission is necessary. |
96 | | virtual ssize_t Send(uv_buf_t* bufs, |
97 | | size_t nbufs, |
98 | | const sockaddr* addr) = 0; |
99 | | |
100 | | virtual SocketAddress GetPeerName() = 0; |
101 | | virtual SocketAddress GetSockName() = 0; |
102 | | |
103 | | // Returns an AsyncWrap object with the same lifetime as this object. |
104 | | virtual AsyncWrap* GetAsyncWrap() = 0; |
105 | | |
106 | | void set_listener(UDPListener* listener); |
107 | | UDPListener* listener() const; |
108 | | |
109 | | static UDPWrapBase* FromObject(v8::Local<v8::Object> obj); |
110 | | |
111 | | static void RecvStart(const v8::FunctionCallbackInfo<v8::Value>& args); |
112 | | static void RecvStop(const v8::FunctionCallbackInfo<v8::Value>& args); |
113 | | static void AddMethods(Environment* env, v8::Local<v8::FunctionTemplate> t); |
114 | | static void RegisterExternalReferences(ExternalReferenceRegistry* registry); |
115 | | |
116 | | private: |
117 | | UDPListener* listener_ = nullptr; |
118 | | }; |
119 | | |
120 | | class UDPWrap final : public HandleWrap, |
121 | | public UDPWrapBase, |
122 | | public UDPListener { |
123 | | public: |
124 | | enum SocketType { |
125 | | SOCKET |
126 | | }; |
127 | | static void Initialize(v8::Local<v8::Object> target, |
128 | | v8::Local<v8::Value> unused, |
129 | | v8::Local<v8::Context> context, |
130 | | void* priv); |
131 | | static void RegisterExternalReferences(ExternalReferenceRegistry* registry); |
132 | | static void GetFD(const v8::FunctionCallbackInfo<v8::Value>& args); |
133 | | static void New(const v8::FunctionCallbackInfo<v8::Value>& args); |
134 | | static void Open(const v8::FunctionCallbackInfo<v8::Value>& args); |
135 | | static void Bind(const v8::FunctionCallbackInfo<v8::Value>& args); |
136 | | static void Connect(const v8::FunctionCallbackInfo<v8::Value>& args); |
137 | | static void Send(const v8::FunctionCallbackInfo<v8::Value>& args); |
138 | | static void Bind6(const v8::FunctionCallbackInfo<v8::Value>& args); |
139 | | static void Connect6(const v8::FunctionCallbackInfo<v8::Value>& args); |
140 | | static void Send6(const v8::FunctionCallbackInfo<v8::Value>& args); |
141 | | static void Disconnect(const v8::FunctionCallbackInfo<v8::Value>& args); |
142 | | static void AddMembership(const v8::FunctionCallbackInfo<v8::Value>& args); |
143 | | static void DropMembership(const v8::FunctionCallbackInfo<v8::Value>& args); |
144 | | static void AddSourceSpecificMembership( |
145 | | const v8::FunctionCallbackInfo<v8::Value>& args); |
146 | | static void DropSourceSpecificMembership( |
147 | | const v8::FunctionCallbackInfo<v8::Value>& args); |
148 | | static void SetMulticastInterface( |
149 | | const v8::FunctionCallbackInfo<v8::Value>& args); |
150 | | static void BufferSize(const v8::FunctionCallbackInfo<v8::Value>& args); |
151 | | static void GetSendQueueSize(const v8::FunctionCallbackInfo<v8::Value>& args); |
152 | | static void GetSendQueueCount( |
153 | | const v8::FunctionCallbackInfo<v8::Value>& args); |
154 | | |
155 | | // UDPListener implementation |
156 | | uv_buf_t OnAlloc(size_t suggested_size) override; |
157 | | void OnRecv(ssize_t nread, |
158 | | const uv_buf_t& buf, |
159 | | const sockaddr* addr, |
160 | | unsigned int flags) override; |
161 | | ReqWrap<uv_udp_send_t>* CreateSendWrap(size_t msg_size) override; |
162 | | void OnSendDone(ReqWrap<uv_udp_send_t>* wrap, int status) override; |
163 | | |
164 | | // UDPWrapBase implementation |
165 | | int RecvStart() override; |
166 | | int RecvStop() override; |
167 | | ssize_t Send(uv_buf_t* bufs, |
168 | | size_t nbufs, |
169 | | const sockaddr* addr) override; |
170 | | |
171 | | SocketAddress GetPeerName() override; |
172 | | SocketAddress GetSockName() override; |
173 | | |
174 | | AsyncWrap* GetAsyncWrap() override; |
175 | | |
176 | 0 | inline uv_udp_t* GetLibuvHandle() { return &handle_; } |
177 | | |
178 | | static v8::MaybeLocal<v8::Object> Instantiate(Environment* env, |
179 | | AsyncWrap* parent, |
180 | | SocketType type); |
181 | | SET_NO_MEMORY_INFO() |
182 | | SET_MEMORY_INFO_NAME(UDPWrap) |
183 | | SET_SELF_SIZE(UDPWrap) |
184 | | |
185 | | private: |
186 | | typedef uv_udp_t HandleType; |
187 | | |
188 | | template <typename T, |
189 | | int (*F)(const typename T::HandleType*, sockaddr*, int*)> |
190 | | friend void GetSockOrPeerName(const v8::FunctionCallbackInfo<v8::Value>&); |
191 | | |
192 | | UDPWrap(Environment* env, v8::Local<v8::Object> object); |
193 | | |
194 | | static void DoBind(const v8::FunctionCallbackInfo<v8::Value>& args, |
195 | | int family); |
196 | | static void DoConnect(const v8::FunctionCallbackInfo<v8::Value>& args, |
197 | | int family); |
198 | | static void DoSend(const v8::FunctionCallbackInfo<v8::Value>& args, |
199 | | int family); |
200 | | static void SetMembership(const v8::FunctionCallbackInfo<v8::Value>& args, |
201 | | uv_membership membership); |
202 | | static void SetSourceMembership( |
203 | | const v8::FunctionCallbackInfo<v8::Value>& args, |
204 | | uv_membership membership); |
205 | | |
206 | | static void OnAlloc(uv_handle_t* handle, |
207 | | size_t suggested_size, |
208 | | uv_buf_t* buf); |
209 | | static void OnRecv(uv_udp_t* handle, |
210 | | ssize_t nread, |
211 | | const uv_buf_t* buf, |
212 | | const struct sockaddr* addr, |
213 | | unsigned int flags); |
214 | | |
215 | | uv_udp_t handle_; |
216 | | |
217 | | bool current_send_has_callback_; |
218 | | v8::Local<v8::Object> current_send_req_wrap_; |
219 | | }; |
220 | | |
221 | | int sockaddr_for_family(int address_family, |
222 | | const char* address, |
223 | | const unsigned short port, |
224 | | sockaddr_storage* addr); |
225 | | |
226 | | } // namespace node |
227 | | |
228 | | #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS |
229 | | |
230 | | #endif // SRC_UDP_WRAP_H_ |