diff options
author | Anna Henningsen <anna@addaleax.net> | 2019-10-09 19:56:21 +0300 |
---|---|---|
committer | Myles Borins <mylesborins@google.com> | 2020-03-05 00:30:30 +0300 |
commit | 4dc59b91a71099f054e9ece5fb05657b1b916af6 (patch) | |
tree | 26bd9f5ad594c7b0996cb4cf8adc6fa05a298f00 /src/udp_wrap.h | |
parent | 478450d6b320c9c904bff12d871a62fd7e8bab33 (diff) |
dgram: make UDPWrap more reusable
Allow using the handle more directly for I/O in other parts of
the codebase.
Originally landed in the QUIC repo
Original review metadata:
```
PR-URL: https://github.com/nodejs/quic/pull/165
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com>
```
Signed-off-by: James M Snell <jasnell@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/31871
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'src/udp_wrap.h')
-rw-r--r-- | src/udp_wrap.h | 116 |
1 files changed, 111 insertions, 5 deletions
diff --git a/src/udp_wrap.h b/src/udp_wrap.h index 2026dd1dee1..7afd9784b0a 100644 --- a/src/udp_wrap.h +++ b/src/udp_wrap.h @@ -25,14 +25,101 @@ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #include "handle_wrap.h" +#include "req_wrap.h" #include "uv.h" #include "v8.h" namespace node { -class Environment; +class UDPWrapBase; -class UDPWrap: public HandleWrap { +// A listener that can be attached to an `UDPWrapBase` object and generally +// manages its I/O activity. This is similar to `StreamListener`. +class UDPListener { + public: + virtual ~UDPListener(); + + // Called right before data is received from the socket. Must return a + // buffer suitable for reading data into, that is then passed to OnRecv. + virtual uv_buf_t OnAlloc(size_t suggested_size) = 0; + + // Called right after data is received from the socket, and includes + // information about the source address. If `nread` is negative, an error + // has occurred, and it represents a libuv error code. + virtual void OnRecv(ssize_t nread, + const uv_buf_t& buf, + const sockaddr* addr, + unsigned int flags) = 0; + + // Called when an asynchronous request for writing data is created. + // The `msg_size` value contains the total size of the data to be sent, + // but may be ignored by the implementation of this Method. + // The return value is later passed to OnSendDone. + virtual ReqWrap<uv_udp_send_t>* CreateSendWrap(size_t msg_size) = 0; + + // Called when an asynchronous request for writing data has finished. + // If status is negative, an error has occurred, and it represents a libuv + // error code. + virtual void OnSendDone(ReqWrap<uv_udp_send_t>* wrap, int status) = 0; + + // Optional callback that is called after the socket has been bound. + virtual void OnAfterBind() {} + + inline UDPWrapBase* udp() const { return wrap_; } + + protected: + UDPWrapBase* wrap_ = nullptr; + + friend class UDPWrapBase; +}; + +class UDPWrapBase { + public: + // While UDPWrapBase itself does not extend from HandleWrap, classes + // derived from it will (like UDPWrap) + enum InternalFields { + kUDPWrapBaseField = HandleWrap::kInternalFieldCount, + kInternalFieldCount + }; + virtual ~UDPWrapBase(); + + // Start emitting OnAlloc() + OnRecv() events on the listener. + virtual int RecvStart() = 0; + + // Stop emitting OnAlloc() + OnRecv() events on the listener. + virtual int RecvStop() = 0; + + // Send a chunk of data over this socket. This may call CreateSendWrap() + // on the listener if an async transmission is necessary. + virtual ssize_t Send(uv_buf_t* bufs, + size_t nbufs, + const sockaddr* addr) = 0; + + // Stores the sockaddr for the peer in `name`. + virtual int GetPeerName(sockaddr* name, int* namelen) = 0; + + // Stores the sockaddr for the local socket in `name`. + virtual int GetSockName(sockaddr* name, int* namelen) = 0; + + // Returns an AsyncWrap object with the same lifetime as this object. + virtual AsyncWrap* GetAsyncWrap() = 0; + + void set_listener(UDPListener* listener); + UDPListener* listener() const; + + static UDPWrapBase* FromObject(v8::Local<v8::Object> obj); + + static void RecvStart(const v8::FunctionCallbackInfo<v8::Value>& args); + static void RecvStop(const v8::FunctionCallbackInfo<v8::Value>& args); + static void AddMethods(Environment* env, v8::Local<v8::FunctionTemplate> t); + + private: + UDPListener* listener_ = nullptr; +}; + +class UDPWrap final : public HandleWrap, + public UDPWrapBase, + public UDPListener { public: enum SocketType { SOCKET @@ -51,8 +138,6 @@ class UDPWrap: public HandleWrap { static void Connect6(const v8::FunctionCallbackInfo<v8::Value>& args); static void Send6(const v8::FunctionCallbackInfo<v8::Value>& args); static void Disconnect(const v8::FunctionCallbackInfo<v8::Value>& args); - static void RecvStart(const v8::FunctionCallbackInfo<v8::Value>& args); - static void RecvStop(const v8::FunctionCallbackInfo<v8::Value>& args); static void AddMembership(const v8::FunctionCallbackInfo<v8::Value>& args); static void DropMembership(const v8::FunctionCallbackInfo<v8::Value>& args); static void AddSourceSpecificMembership( @@ -68,6 +153,25 @@ class UDPWrap: public HandleWrap { static void SetTTL(const v8::FunctionCallbackInfo<v8::Value>& args); static void BufferSize(const v8::FunctionCallbackInfo<v8::Value>& args); + // UDPListener implementation + uv_buf_t OnAlloc(size_t suggested_size) override; + void OnRecv(ssize_t nread, + const uv_buf_t& buf, + const sockaddr* addr, + unsigned int flags) override; + ReqWrap<uv_udp_send_t>* CreateSendWrap(size_t msg_size) override; + void OnSendDone(ReqWrap<uv_udp_send_t>* wrap, int status) override; + + // UDPWrapBase implementation + int RecvStart() override; + int RecvStop() override; + ssize_t Send(uv_buf_t* bufs, + size_t nbufs, + const sockaddr* addr) override; + int GetPeerName(sockaddr* name, int* namelen) override; + int GetSockName(sockaddr* name, int* namelen) override; + AsyncWrap* GetAsyncWrap() override; + static v8::MaybeLocal<v8::Object> Instantiate(Environment* env, AsyncWrap* parent, SocketType type); @@ -99,7 +203,6 @@ class UDPWrap: public HandleWrap { static void OnAlloc(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf); - static void OnSend(uv_udp_send_t* req, int status); static void OnRecv(uv_udp_t* handle, ssize_t nread, const uv_buf_t* buf, @@ -107,6 +210,9 @@ class UDPWrap: public HandleWrap { unsigned int flags); uv_udp_t handle_; + + bool current_send_has_callback_; + v8::Local<v8::Object> current_send_req_wrap_; }; } // namespace node |