xref: /third_party/node/src/udp_wrap.h (revision 1cb0ef41)
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
33namespace node {
34
35class 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`.
39class 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.
67  virtual void OnAfterBind() {}
68
69  inline UDPWrapBase* udp() const { return wrap_; }
70
71 protected:
72  UDPWrapBase* wrap_ = nullptr;
73
74  friend class UDPWrapBase;
75};
76
77class 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
118class 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
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
218int 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