diff options
author | James M Snell <jasnell@gmail.com> | 2021-03-25 12:19:30 -0700 |
---|---|---|
committer | James M Snell <jasnell@gmail.com> | 2021-04-02 06:16:40 -0700 |
commit | 0b90d352948393e5f92ceb2ef749c643b1002a68 (patch) | |
tree | af799b4214eb4d855b6582fadc0f17d2e724ac84 /src | |
parent | fb9257f6597f0581592826d236cfc7196afebaca (diff) | |
download | node-new-0b90d352948393e5f92ceb2ef749c643b1002a68.tar.gz |
net: add SocketAddress class
Signed-off-by: James M Snell <jasnell@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/37917
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/env.h | 2 | ||||
-rw-r--r-- | src/node_errors.h | 2 | ||||
-rw-r--r-- | src/node_sockaddr.cc | 143 | ||||
-rw-r--r-- | src/node_sockaddr.h | 54 |
4 files changed, 201 insertions, 0 deletions
@@ -258,6 +258,7 @@ constexpr size_t kFsStatsBufferLength = V(fingerprint256_string, "fingerprint256") \ V(fingerprint_string, "fingerprint") \ V(flags_string, "flags") \ + V(flowlabel_string, "flowlabel") \ V(fragment_string, "fragment") \ V(frames_received_string, "framesReceived") \ V(frames_sent_string, "framesSent") \ @@ -475,6 +476,7 @@ constexpr size_t kFsStatsBufferLength = V(script_context_constructor_template, v8::FunctionTemplate) \ V(secure_context_constructor_template, v8::FunctionTemplate) \ V(shutdown_wrap_template, v8::ObjectTemplate) \ + V(socketaddress_constructor_template, v8::FunctionTemplate) \ V(streambaseoutputstream_constructor_template, v8::ObjectTemplate) \ V(qlogoutputstream_constructor_template, v8::ObjectTemplate) \ V(tcp_constructor_template, v8::FunctionTemplate) \ diff --git a/src/node_errors.h b/src/node_errors.h index 1ae461f23d..291365fa3b 100644 --- a/src/node_errors.h +++ b/src/node_errors.h @@ -56,6 +56,7 @@ void OnFatalError(const char* location, const char* message); V(ERR_CRYPTO_JOB_INIT_FAILED, Error) \ V(ERR_DLOPEN_FAILED, Error) \ V(ERR_EXECUTION_ENVIRONMENT_NOT_AVAILABLE, Error) \ + V(ERR_INVALID_ADDRESS, Error) \ V(ERR_INVALID_ARG_VALUE, TypeError) \ V(ERR_OSSL_EVP_INVALID_DIGEST, Error) \ V(ERR_INVALID_ARG_TYPE, TypeError) \ @@ -143,6 +144,7 @@ ERRORS_WITH_CODE(V) V(ERR_DLOPEN_FAILED, "DLOpen failed") \ V(ERR_EXECUTION_ENVIRONMENT_NOT_AVAILABLE, \ "Context not associated with Node.js environment") \ + V(ERR_INVALID_ADDRESS, "Invalid socket address") \ V(ERR_INVALID_MODULE, "No such module") \ V(ERR_INVALID_THIS, "Value of \"this\" is the wrong type") \ V(ERR_INVALID_TRANSFER_OBJECT, "Found invalid object in transferList") \ diff --git a/src/node_sockaddr.cc b/src/node_sockaddr.cc index 653047cc59..e745589b12 100644 --- a/src/node_sockaddr.cc +++ b/src/node_sockaddr.cc @@ -3,6 +3,7 @@ #include "base64-inl.h" #include "base_object-inl.h" #include "memory_tracker-inl.h" +#include "node_errors.h" #include "uv.h" #include <memory> @@ -15,9 +16,11 @@ using v8::Array; using v8::Context; using v8::FunctionCallbackInfo; using v8::FunctionTemplate; +using v8::Int32; using v8::Local; using v8::MaybeLocal; using v8::Object; +using v8::Uint32; using v8::Value; namespace { @@ -752,6 +755,8 @@ void SocketAddressBlockListWrap::Initialize( GetConstructorTemplate(env), Environment::SetConstructorFunctionFlag::NONE); + SocketAddressBase::Initialize(env, target); + NODE_DEFINE_CONSTANT(target, AF_INET); NODE_DEFINE_CONSTANT(target, AF_INET6); } @@ -768,6 +773,144 @@ void SocketAddressBlockListWrap::TransferData::MemoryInfo( blocklist_->MemoryInfo(tracker); } +bool SocketAddressBase::HasInstance(Environment* env, Local<Value> value) { + return GetConstructorTemplate(env)->HasInstance(value); +} + +Local<FunctionTemplate> SocketAddressBase::GetConstructorTemplate( + Environment* env) { + Local<FunctionTemplate> tmpl = env->socketaddress_constructor_template(); + if (tmpl.IsEmpty()) { + tmpl = env->NewFunctionTemplate(New); + tmpl->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "SocketAddress")); + tmpl->InstanceTemplate()->SetInternalFieldCount( + SocketAddressBase::kInternalFieldCount); + tmpl->Inherit(BaseObject::GetConstructorTemplate(env)); + env->SetProtoMethod(tmpl, "detail", Detail); + env->SetProtoMethod(tmpl, "legacyDetail", LegacyDetail); + env->SetProtoMethodNoSideEffect(tmpl, "flowlabel", GetFlowLabel); + env->set_socketaddress_constructor_template(tmpl); + } + return tmpl; +} + +void SocketAddressBase::Initialize(Environment* env, Local<Object> target) { + env->SetConstructorFunction( + target, + "SocketAddress", + GetConstructorTemplate(env), + Environment::SetConstructorFunctionFlag::NONE); +} + +BaseObjectPtr<SocketAddressBase> SocketAddressBase::Create( + Environment* env, + std::shared_ptr<SocketAddress> address) { + Local<Object> obj; + if (!GetConstructorTemplate(env) + ->InstanceTemplate() + ->NewInstance(env->context()).ToLocal(&obj)) { + return BaseObjectPtr<SocketAddressBase>(); + } + + return MakeBaseObject<SocketAddressBase>(env, obj, std::move(address)); +} + +void SocketAddressBase::New(const FunctionCallbackInfo<Value>& args) { + Environment* env = Environment::GetCurrent(args); + CHECK(args.IsConstructCall()); + CHECK(args[0]->IsString()); // address + CHECK(args[1]->IsInt32()); // port + CHECK(args[2]->IsInt32()); // family + CHECK(args[3]->IsUint32()); // flow label + + Utf8Value address(env->isolate(), args[0]); + int32_t port = args[1].As<Int32>()->Value(); + int32_t family = args[2].As<Int32>()->Value(); + uint32_t flow_label = args[3].As<Uint32>()->Value(); + + std::shared_ptr<SocketAddress> addr = std::make_shared<SocketAddress>(); + + if (!SocketAddress::New(family, *address, port, addr.get())) + return THROW_ERR_INVALID_ADDRESS(env); + + addr->set_flow_label(flow_label); + + new SocketAddressBase(env, args.This(), std::move(addr)); +} + +void SocketAddressBase::Detail(const FunctionCallbackInfo<Value>& args) { + Environment* env = Environment::GetCurrent(args); + CHECK(args[0]->IsObject()); + Local<Object> detail = args[0].As<Object>(); + + SocketAddressBase* base; + ASSIGN_OR_RETURN_UNWRAP(&base, args.Holder()); + + Local<Value> address; + if (!ToV8Value(env->context(), base->address_->address()).ToLocal(&address)) + return; + + if (detail->Set(env->context(), env->address_string(), address).IsJust() && + detail->Set( + env->context(), + env->port_string(), + Int32::New(env->isolate(), base->address_->port())).IsJust() && + detail->Set( + env->context(), + env->family_string(), + Int32::New(env->isolate(), base->address_->family())).IsJust() && + detail->Set( + env->context(), + env->flowlabel_string(), + Uint32::New(env->isolate(), base->address_->flow_label())) + .IsJust()) { + args.GetReturnValue().Set(detail); + } +} + +void SocketAddressBase::GetFlowLabel(const FunctionCallbackInfo<Value>& args) { + Environment* env = Environment::GetCurrent(args); + SocketAddressBase* base; + ASSIGN_OR_RETURN_UNWRAP(&base, args.Holder()); + args.GetReturnValue().Set(base->address_->flow_label()); +} + +void SocketAddressBase::LegacyDetail(const FunctionCallbackInfo<Value>& args) { + Environment* env = Environment::GetCurrent(args); + SocketAddressBase* base; + ASSIGN_OR_RETURN_UNWRAP(&base, args.Holder()); + args.GetReturnValue().Set(base->address_->ToJS(env)); +} + +SocketAddressBase::SocketAddressBase( + Environment* env, + Local<Object> wrap, + std::shared_ptr<SocketAddress> address) + : BaseObject(env, wrap), + address_(std::move(address)) { + MakeWeak(); +} + +void SocketAddressBase::MemoryInfo(MemoryTracker* tracker) const { + tracker->TrackField("address", address_); +} + +std::unique_ptr<worker::TransferData> +SocketAddressBase::CloneForMessaging() const { + return std::make_unique<TransferData>(this); +} + +void SocketAddressBase::TransferData::MemoryInfo(MemoryTracker* tracker) const { + tracker->TrackField("address", address_); +} + +BaseObjectPtr<BaseObject> SocketAddressBase::TransferData::Deserialize( + Environment* env, + v8::Local<v8::Context> context, + std::unique_ptr<worker::TransferData> self) { + return SocketAddressBase::Create(env, std::move(address_)); +} + } // namespace node NODE_MODULE_CONTEXT_AWARE_INTERNAL( diff --git a/src/node_sockaddr.h b/src/node_sockaddr.h index 670a8b78d8..62dcab6bad 100644 --- a/src/node_sockaddr.h +++ b/src/node_sockaddr.h @@ -148,6 +148,60 @@ class SocketAddress : public MemoryRetainer { sockaddr_storage address_; }; +class SocketAddressBase : public BaseObject { + public: + static bool HasInstance(Environment* env, v8::Local<v8::Value> value); + static v8::Local<v8::FunctionTemplate> GetConstructorTemplate( + Environment* env); + static void Initialize(Environment* env, v8::Local<v8::Object> target); + static BaseObjectPtr<SocketAddressBase> Create( + Environment* env, + std::shared_ptr<SocketAddress> address); + + static void New(const v8::FunctionCallbackInfo<v8::Value>& args); + static void Detail(const v8::FunctionCallbackInfo<v8::Value>& args); + static void LegacyDetail(const v8::FunctionCallbackInfo<v8::Value>& args); + static void GetFlowLabel(const v8::FunctionCallbackInfo<v8::Value>& args); + + SocketAddressBase( + Environment* env, + v8::Local<v8::Object> wrap, + std::shared_ptr<SocketAddress> address); + + void MemoryInfo(MemoryTracker* tracker) const override; + SET_MEMORY_INFO_NAME(SocketAddressBase); + SET_SELF_SIZE(SocketAddressBase); + + TransferMode GetTransferMode() const override { + return TransferMode::kCloneable; + } + std::unique_ptr<worker::TransferData> CloneForMessaging() const override; + + class TransferData : public worker::TransferData { + public: + inline explicit TransferData(const SocketAddressBase* wrap) + : address_(wrap->address_) {} + + inline explicit TransferData(std::shared_ptr<SocketAddress> address) + : address_(std::move(address)) {} + + BaseObjectPtr<BaseObject> Deserialize( + Environment* env, + v8::Local<v8::Context> context, + std::unique_ptr<worker::TransferData> self) override; + + void MemoryInfo(MemoryTracker* tracker) const override; + SET_MEMORY_INFO_NAME(SocketAddressBase::TransferData) + SET_SELF_SIZE(TransferData) + + private: + std::shared_ptr<SocketAddress> address_; + }; + + private: + std::shared_ptr<SocketAddress> address_; +}; + template <typename T> class SocketAddressLRU : public MemoryRetainer { public: |