11cb0ef41Sopenharmony_ci// Copyright Joyent, Inc. and other Node contributors.
21cb0ef41Sopenharmony_ci//
31cb0ef41Sopenharmony_ci// Permission is hereby granted, free of charge, to any person obtaining a
41cb0ef41Sopenharmony_ci// copy of this software and associated documentation files (the
51cb0ef41Sopenharmony_ci// "Software"), to deal in the Software without restriction, including
61cb0ef41Sopenharmony_ci// without limitation the rights to use, copy, modify, merge, publish,
71cb0ef41Sopenharmony_ci// distribute, sublicense, and/or sell copies of the Software, and to permit
81cb0ef41Sopenharmony_ci// persons to whom the Software is furnished to do so, subject to the
91cb0ef41Sopenharmony_ci// following conditions:
101cb0ef41Sopenharmony_ci//
111cb0ef41Sopenharmony_ci// The above copyright notice and this permission notice shall be included
121cb0ef41Sopenharmony_ci// in all copies or substantial portions of the Software.
131cb0ef41Sopenharmony_ci//
141cb0ef41Sopenharmony_ci// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
151cb0ef41Sopenharmony_ci// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
161cb0ef41Sopenharmony_ci// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
171cb0ef41Sopenharmony_ci// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
181cb0ef41Sopenharmony_ci// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
191cb0ef41Sopenharmony_ci// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
201cb0ef41Sopenharmony_ci// USE OR OTHER DEALINGS IN THE SOFTWARE.
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci#include "udp_wrap.h"
231cb0ef41Sopenharmony_ci#include "env-inl.h"
241cb0ef41Sopenharmony_ci#include "node_buffer.h"
251cb0ef41Sopenharmony_ci#include "node_errors.h"
261cb0ef41Sopenharmony_ci#include "node_sockaddr-inl.h"
271cb0ef41Sopenharmony_ci#include "handle_wrap.h"
281cb0ef41Sopenharmony_ci#include "req_wrap-inl.h"
291cb0ef41Sopenharmony_ci#include "util-inl.h"
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_cinamespace node {
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ciusing errors::TryCatchScope;
341cb0ef41Sopenharmony_ciusing v8::Array;
351cb0ef41Sopenharmony_ciusing v8::ArrayBuffer;
361cb0ef41Sopenharmony_ciusing v8::BackingStore;
371cb0ef41Sopenharmony_ciusing v8::Boolean;
381cb0ef41Sopenharmony_ciusing v8::Context;
391cb0ef41Sopenharmony_ciusing v8::DontDelete;
401cb0ef41Sopenharmony_ciusing v8::FunctionCallbackInfo;
411cb0ef41Sopenharmony_ciusing v8::FunctionTemplate;
421cb0ef41Sopenharmony_ciusing v8::HandleScope;
431cb0ef41Sopenharmony_ciusing v8::Integer;
441cb0ef41Sopenharmony_ciusing v8::Isolate;
451cb0ef41Sopenharmony_ciusing v8::Local;
461cb0ef41Sopenharmony_ciusing v8::MaybeLocal;
471cb0ef41Sopenharmony_ciusing v8::Object;
481cb0ef41Sopenharmony_ciusing v8::PropertyAttribute;
491cb0ef41Sopenharmony_ciusing v8::ReadOnly;
501cb0ef41Sopenharmony_ciusing v8::Signature;
511cb0ef41Sopenharmony_ciusing v8::Uint32;
521cb0ef41Sopenharmony_ciusing v8::Undefined;
531cb0ef41Sopenharmony_ciusing v8::Value;
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_cinamespace {
561cb0ef41Sopenharmony_citemplate <int (*fn)(uv_udp_t*, int)>
571cb0ef41Sopenharmony_civoid SetLibuvInt32(const FunctionCallbackInfo<Value>& args) {
581cb0ef41Sopenharmony_ci  UDPWrap* wrap = Unwrap<UDPWrap>(args.Holder());
591cb0ef41Sopenharmony_ci  if (wrap == nullptr) {
601cb0ef41Sopenharmony_ci    args.GetReturnValue().Set(UV_EBADF);
611cb0ef41Sopenharmony_ci    return;
621cb0ef41Sopenharmony_ci  }
631cb0ef41Sopenharmony_ci  Environment* env = wrap->env();
641cb0ef41Sopenharmony_ci  CHECK_EQ(args.Length(), 1);
651cb0ef41Sopenharmony_ci  int flag;
661cb0ef41Sopenharmony_ci  if (!args[0]->Int32Value(env->context()).To(&flag)) {
671cb0ef41Sopenharmony_ci    return;
681cb0ef41Sopenharmony_ci  }
691cb0ef41Sopenharmony_ci  int err = fn(wrap->GetLibuvHandle(), flag);
701cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(err);
711cb0ef41Sopenharmony_ci}
721cb0ef41Sopenharmony_ci}  // namespace
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ciclass SendWrap : public ReqWrap<uv_udp_send_t> {
751cb0ef41Sopenharmony_ci public:
761cb0ef41Sopenharmony_ci  SendWrap(Environment* env, Local<Object> req_wrap_obj, bool have_callback);
771cb0ef41Sopenharmony_ci  inline bool have_callback() const;
781cb0ef41Sopenharmony_ci  size_t msg_size;
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ci  SET_NO_MEMORY_INFO()
811cb0ef41Sopenharmony_ci  SET_MEMORY_INFO_NAME(SendWrap)
821cb0ef41Sopenharmony_ci  SET_SELF_SIZE(SendWrap)
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_ci private:
851cb0ef41Sopenharmony_ci  const bool have_callback_;
861cb0ef41Sopenharmony_ci};
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ciSendWrap::SendWrap(Environment* env,
901cb0ef41Sopenharmony_ci                   Local<Object> req_wrap_obj,
911cb0ef41Sopenharmony_ci                   bool have_callback)
921cb0ef41Sopenharmony_ci    : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_UDPSENDWRAP),
931cb0ef41Sopenharmony_ci      have_callback_(have_callback) {
941cb0ef41Sopenharmony_ci}
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ci
971cb0ef41Sopenharmony_cibool SendWrap::have_callback() const {
981cb0ef41Sopenharmony_ci  return have_callback_;
991cb0ef41Sopenharmony_ci}
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ciUDPListener::~UDPListener() {
1021cb0ef41Sopenharmony_ci  if (wrap_ != nullptr)
1031cb0ef41Sopenharmony_ci    wrap_->set_listener(nullptr);
1041cb0ef41Sopenharmony_ci}
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ciUDPWrapBase::~UDPWrapBase() {
1071cb0ef41Sopenharmony_ci  set_listener(nullptr);
1081cb0ef41Sopenharmony_ci}
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_ciUDPListener* UDPWrapBase::listener() const {
1111cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(listener_);
1121cb0ef41Sopenharmony_ci  return listener_;
1131cb0ef41Sopenharmony_ci}
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_civoid UDPWrapBase::set_listener(UDPListener* listener) {
1161cb0ef41Sopenharmony_ci  if (listener_ != nullptr)
1171cb0ef41Sopenharmony_ci    listener_->wrap_ = nullptr;
1181cb0ef41Sopenharmony_ci  listener_ = listener;
1191cb0ef41Sopenharmony_ci  if (listener_ != nullptr) {
1201cb0ef41Sopenharmony_ci    CHECK_NULL(listener_->wrap_);
1211cb0ef41Sopenharmony_ci    listener_->wrap_ = this;
1221cb0ef41Sopenharmony_ci  }
1231cb0ef41Sopenharmony_ci}
1241cb0ef41Sopenharmony_ci
1251cb0ef41Sopenharmony_ciUDPWrapBase* UDPWrapBase::FromObject(Local<Object> obj) {
1261cb0ef41Sopenharmony_ci  CHECK_GT(obj->InternalFieldCount(), UDPWrapBase::kUDPWrapBaseField);
1271cb0ef41Sopenharmony_ci  return static_cast<UDPWrapBase*>(
1281cb0ef41Sopenharmony_ci      obj->GetAlignedPointerFromInternalField(UDPWrapBase::kUDPWrapBaseField));
1291cb0ef41Sopenharmony_ci}
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_civoid UDPWrapBase::AddMethods(Environment* env, Local<FunctionTemplate> t) {
1321cb0ef41Sopenharmony_ci  SetProtoMethod(env->isolate(), t, "recvStart", RecvStart);
1331cb0ef41Sopenharmony_ci  SetProtoMethod(env->isolate(), t, "recvStop", RecvStop);
1341cb0ef41Sopenharmony_ci}
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_ciUDPWrap::UDPWrap(Environment* env, Local<Object> object)
1371cb0ef41Sopenharmony_ci    : HandleWrap(env,
1381cb0ef41Sopenharmony_ci                 object,
1391cb0ef41Sopenharmony_ci                 reinterpret_cast<uv_handle_t*>(&handle_),
1401cb0ef41Sopenharmony_ci                 AsyncWrap::PROVIDER_UDPWRAP) {
1411cb0ef41Sopenharmony_ci  object->SetAlignedPointerInInternalField(
1421cb0ef41Sopenharmony_ci      UDPWrapBase::kUDPWrapBaseField, static_cast<UDPWrapBase*>(this));
1431cb0ef41Sopenharmony_ci
1441cb0ef41Sopenharmony_ci  int r = uv_udp_init(env->event_loop(), &handle_);
1451cb0ef41Sopenharmony_ci  CHECK_EQ(r, 0);  // can't fail anyway
1461cb0ef41Sopenharmony_ci
1471cb0ef41Sopenharmony_ci  set_listener(this);
1481cb0ef41Sopenharmony_ci}
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_civoid UDPWrap::Initialize(Local<Object> target,
1521cb0ef41Sopenharmony_ci                         Local<Value> unused,
1531cb0ef41Sopenharmony_ci                         Local<Context> context,
1541cb0ef41Sopenharmony_ci                         void* priv) {
1551cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(context);
1561cb0ef41Sopenharmony_ci  Isolate* isolate = env->isolate();
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_ci  Local<FunctionTemplate> t = NewFunctionTemplate(isolate, New);
1591cb0ef41Sopenharmony_ci  t->InstanceTemplate()->SetInternalFieldCount(
1601cb0ef41Sopenharmony_ci      UDPWrapBase::kInternalFieldCount);
1611cb0ef41Sopenharmony_ci
1621cb0ef41Sopenharmony_ci  enum PropertyAttribute attributes =
1631cb0ef41Sopenharmony_ci      static_cast<PropertyAttribute>(ReadOnly | DontDelete);
1641cb0ef41Sopenharmony_ci
1651cb0ef41Sopenharmony_ci  Local<Signature> signature = Signature::New(isolate, t);
1661cb0ef41Sopenharmony_ci
1671cb0ef41Sopenharmony_ci  Local<FunctionTemplate> get_fd_templ =
1681cb0ef41Sopenharmony_ci      FunctionTemplate::New(isolate, UDPWrap::GetFD, Local<Value>(), signature);
1691cb0ef41Sopenharmony_ci
1701cb0ef41Sopenharmony_ci  t->PrototypeTemplate()->SetAccessorProperty(env->fd_string(),
1711cb0ef41Sopenharmony_ci                                              get_fd_templ,
1721cb0ef41Sopenharmony_ci                                              Local<FunctionTemplate>(),
1731cb0ef41Sopenharmony_ci                                              attributes);
1741cb0ef41Sopenharmony_ci
1751cb0ef41Sopenharmony_ci  UDPWrapBase::AddMethods(env, t);
1761cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "open", Open);
1771cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "bind", Bind);
1781cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "connect", Connect);
1791cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "send", Send);
1801cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "bind6", Bind6);
1811cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "connect6", Connect6);
1821cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "send6", Send6);
1831cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "disconnect", Disconnect);
1841cb0ef41Sopenharmony_ci  SetProtoMethod(isolate,
1851cb0ef41Sopenharmony_ci                 t,
1861cb0ef41Sopenharmony_ci                 "getpeername",
1871cb0ef41Sopenharmony_ci                 GetSockOrPeerName<UDPWrap, uv_udp_getpeername>);
1881cb0ef41Sopenharmony_ci  SetProtoMethod(isolate,
1891cb0ef41Sopenharmony_ci                 t,
1901cb0ef41Sopenharmony_ci                 "getsockname",
1911cb0ef41Sopenharmony_ci                 GetSockOrPeerName<UDPWrap, uv_udp_getsockname>);
1921cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "addMembership", AddMembership);
1931cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "dropMembership", DropMembership);
1941cb0ef41Sopenharmony_ci  SetProtoMethod(
1951cb0ef41Sopenharmony_ci      isolate, t, "addSourceSpecificMembership", AddSourceSpecificMembership);
1961cb0ef41Sopenharmony_ci  SetProtoMethod(
1971cb0ef41Sopenharmony_ci      isolate, t, "dropSourceSpecificMembership", DropSourceSpecificMembership);
1981cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "setMulticastInterface", SetMulticastInterface);
1991cb0ef41Sopenharmony_ci  SetProtoMethod(
2001cb0ef41Sopenharmony_ci      isolate, t, "setMulticastTTL", SetLibuvInt32<uv_udp_set_multicast_ttl>);
2011cb0ef41Sopenharmony_ci  SetProtoMethod(isolate,
2021cb0ef41Sopenharmony_ci                 t,
2031cb0ef41Sopenharmony_ci                 "setMulticastLoopback",
2041cb0ef41Sopenharmony_ci                 SetLibuvInt32<uv_udp_set_multicast_loop>);
2051cb0ef41Sopenharmony_ci  SetProtoMethod(
2061cb0ef41Sopenharmony_ci      isolate, t, "setBroadcast", SetLibuvInt32<uv_udp_set_broadcast>);
2071cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "setTTL", SetLibuvInt32<uv_udp_set_ttl>);
2081cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "bufferSize", BufferSize);
2091cb0ef41Sopenharmony_ci  SetProtoMethodNoSideEffect(isolate, t, "getSendQueueSize", GetSendQueueSize);
2101cb0ef41Sopenharmony_ci  SetProtoMethodNoSideEffect(
2111cb0ef41Sopenharmony_ci      isolate, t, "getSendQueueCount", GetSendQueueCount);
2121cb0ef41Sopenharmony_ci
2131cb0ef41Sopenharmony_ci  t->Inherit(HandleWrap::GetConstructorTemplate(env));
2141cb0ef41Sopenharmony_ci
2151cb0ef41Sopenharmony_ci  SetConstructorFunction(context, target, "UDP", t);
2161cb0ef41Sopenharmony_ci  env->set_udp_constructor_function(t->GetFunction(context).ToLocalChecked());
2171cb0ef41Sopenharmony_ci
2181cb0ef41Sopenharmony_ci  // Create FunctionTemplate for SendWrap
2191cb0ef41Sopenharmony_ci  Local<FunctionTemplate> swt =
2201cb0ef41Sopenharmony_ci      BaseObject::MakeLazilyInitializedJSTemplate(env);
2211cb0ef41Sopenharmony_ci  swt->Inherit(AsyncWrap::GetConstructorTemplate(env));
2221cb0ef41Sopenharmony_ci  SetConstructorFunction(context, target, "SendWrap", swt);
2231cb0ef41Sopenharmony_ci
2241cb0ef41Sopenharmony_ci  Local<Object> constants = Object::New(isolate);
2251cb0ef41Sopenharmony_ci  NODE_DEFINE_CONSTANT(constants, UV_UDP_IPV6ONLY);
2261cb0ef41Sopenharmony_ci  NODE_DEFINE_CONSTANT(constants, UV_UDP_REUSEADDR);
2271cb0ef41Sopenharmony_ci  target->Set(context,
2281cb0ef41Sopenharmony_ci              env->constants_string(),
2291cb0ef41Sopenharmony_ci              constants).Check();
2301cb0ef41Sopenharmony_ci}
2311cb0ef41Sopenharmony_ci
2321cb0ef41Sopenharmony_ci
2331cb0ef41Sopenharmony_civoid UDPWrap::New(const FunctionCallbackInfo<Value>& args) {
2341cb0ef41Sopenharmony_ci  CHECK(args.IsConstructCall());
2351cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
2361cb0ef41Sopenharmony_ci  new UDPWrap(env, args.This());
2371cb0ef41Sopenharmony_ci}
2381cb0ef41Sopenharmony_ci
2391cb0ef41Sopenharmony_ci
2401cb0ef41Sopenharmony_civoid UDPWrap::GetFD(const FunctionCallbackInfo<Value>& args) {
2411cb0ef41Sopenharmony_ci  int fd = UV_EBADF;
2421cb0ef41Sopenharmony_ci#if !defined(_WIN32)
2431cb0ef41Sopenharmony_ci  UDPWrap* wrap = Unwrap<UDPWrap>(args.This());
2441cb0ef41Sopenharmony_ci  if (wrap != nullptr)
2451cb0ef41Sopenharmony_ci    uv_fileno(reinterpret_cast<uv_handle_t*>(&wrap->handle_), &fd);
2461cb0ef41Sopenharmony_ci#endif
2471cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(fd);
2481cb0ef41Sopenharmony_ci}
2491cb0ef41Sopenharmony_ci
2501cb0ef41Sopenharmony_ciint sockaddr_for_family(int address_family,
2511cb0ef41Sopenharmony_ci                        const char* address,
2521cb0ef41Sopenharmony_ci                        const unsigned short port,
2531cb0ef41Sopenharmony_ci                        struct sockaddr_storage* addr) {
2541cb0ef41Sopenharmony_ci  switch (address_family) {
2551cb0ef41Sopenharmony_ci    case AF_INET:
2561cb0ef41Sopenharmony_ci      return uv_ip4_addr(address, port, reinterpret_cast<sockaddr_in*>(addr));
2571cb0ef41Sopenharmony_ci    case AF_INET6:
2581cb0ef41Sopenharmony_ci      return uv_ip6_addr(address, port, reinterpret_cast<sockaddr_in6*>(addr));
2591cb0ef41Sopenharmony_ci    default:
2601cb0ef41Sopenharmony_ci      UNREACHABLE("unexpected address family");
2611cb0ef41Sopenharmony_ci  }
2621cb0ef41Sopenharmony_ci}
2631cb0ef41Sopenharmony_ci
2641cb0ef41Sopenharmony_civoid UDPWrap::DoBind(const FunctionCallbackInfo<Value>& args, int family) {
2651cb0ef41Sopenharmony_ci  UDPWrap* wrap;
2661cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&wrap,
2671cb0ef41Sopenharmony_ci                          args.Holder(),
2681cb0ef41Sopenharmony_ci                          args.GetReturnValue().Set(UV_EBADF));
2691cb0ef41Sopenharmony_ci
2701cb0ef41Sopenharmony_ci  // bind(ip, port, flags)
2711cb0ef41Sopenharmony_ci  CHECK_EQ(args.Length(), 3);
2721cb0ef41Sopenharmony_ci
2731cb0ef41Sopenharmony_ci  node::Utf8Value address(args.GetIsolate(), args[0]);
2741cb0ef41Sopenharmony_ci  Local<Context> ctx = args.GetIsolate()->GetCurrentContext();
2751cb0ef41Sopenharmony_ci  uint32_t port, flags;
2761cb0ef41Sopenharmony_ci  if (!args[1]->Uint32Value(ctx).To(&port) ||
2771cb0ef41Sopenharmony_ci      !args[2]->Uint32Value(ctx).To(&flags))
2781cb0ef41Sopenharmony_ci    return;
2791cb0ef41Sopenharmony_ci  struct sockaddr_storage addr_storage;
2801cb0ef41Sopenharmony_ci  int err = sockaddr_for_family(family, address.out(), port, &addr_storage);
2811cb0ef41Sopenharmony_ci  if (err == 0) {
2821cb0ef41Sopenharmony_ci    err = uv_udp_bind(&wrap->handle_,
2831cb0ef41Sopenharmony_ci                      reinterpret_cast<const sockaddr*>(&addr_storage),
2841cb0ef41Sopenharmony_ci                      flags);
2851cb0ef41Sopenharmony_ci  }
2861cb0ef41Sopenharmony_ci
2871cb0ef41Sopenharmony_ci  if (err == 0)
2881cb0ef41Sopenharmony_ci    wrap->listener()->OnAfterBind();
2891cb0ef41Sopenharmony_ci
2901cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(err);
2911cb0ef41Sopenharmony_ci}
2921cb0ef41Sopenharmony_ci
2931cb0ef41Sopenharmony_ci
2941cb0ef41Sopenharmony_civoid UDPWrap::DoConnect(const FunctionCallbackInfo<Value>& args, int family) {
2951cb0ef41Sopenharmony_ci  UDPWrap* wrap;
2961cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&wrap,
2971cb0ef41Sopenharmony_ci                          args.Holder(),
2981cb0ef41Sopenharmony_ci                          args.GetReturnValue().Set(UV_EBADF));
2991cb0ef41Sopenharmony_ci
3001cb0ef41Sopenharmony_ci  CHECK_EQ(args.Length(), 2);
3011cb0ef41Sopenharmony_ci
3021cb0ef41Sopenharmony_ci  node::Utf8Value address(args.GetIsolate(), args[0]);
3031cb0ef41Sopenharmony_ci  Local<Context> ctx = args.GetIsolate()->GetCurrentContext();
3041cb0ef41Sopenharmony_ci  uint32_t port;
3051cb0ef41Sopenharmony_ci  if (!args[1]->Uint32Value(ctx).To(&port))
3061cb0ef41Sopenharmony_ci    return;
3071cb0ef41Sopenharmony_ci  struct sockaddr_storage addr_storage;
3081cb0ef41Sopenharmony_ci  int err = sockaddr_for_family(family, address.out(), port, &addr_storage);
3091cb0ef41Sopenharmony_ci  if (err == 0) {
3101cb0ef41Sopenharmony_ci    err = uv_udp_connect(&wrap->handle_,
3111cb0ef41Sopenharmony_ci                         reinterpret_cast<const sockaddr*>(&addr_storage));
3121cb0ef41Sopenharmony_ci  }
3131cb0ef41Sopenharmony_ci
3141cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(err);
3151cb0ef41Sopenharmony_ci}
3161cb0ef41Sopenharmony_ci
3171cb0ef41Sopenharmony_ci
3181cb0ef41Sopenharmony_civoid UDPWrap::Open(const FunctionCallbackInfo<Value>& args) {
3191cb0ef41Sopenharmony_ci  UDPWrap* wrap;
3201cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&wrap,
3211cb0ef41Sopenharmony_ci                          args.Holder(),
3221cb0ef41Sopenharmony_ci                          args.GetReturnValue().Set(UV_EBADF));
3231cb0ef41Sopenharmony_ci  CHECK(args[0]->IsNumber());
3241cb0ef41Sopenharmony_ci  int fd = static_cast<int>(args[0].As<Integer>()->Value());
3251cb0ef41Sopenharmony_ci  int err = uv_udp_open(&wrap->handle_, fd);
3261cb0ef41Sopenharmony_ci
3271cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(err);
3281cb0ef41Sopenharmony_ci}
3291cb0ef41Sopenharmony_ci
3301cb0ef41Sopenharmony_ci
3311cb0ef41Sopenharmony_civoid UDPWrap::Bind(const FunctionCallbackInfo<Value>& args) {
3321cb0ef41Sopenharmony_ci  DoBind(args, AF_INET);
3331cb0ef41Sopenharmony_ci}
3341cb0ef41Sopenharmony_ci
3351cb0ef41Sopenharmony_ci
3361cb0ef41Sopenharmony_civoid UDPWrap::Bind6(const FunctionCallbackInfo<Value>& args) {
3371cb0ef41Sopenharmony_ci  DoBind(args, AF_INET6);
3381cb0ef41Sopenharmony_ci}
3391cb0ef41Sopenharmony_ci
3401cb0ef41Sopenharmony_ci
3411cb0ef41Sopenharmony_civoid UDPWrap::BufferSize(const FunctionCallbackInfo<Value>& args) {
3421cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
3431cb0ef41Sopenharmony_ci  UDPWrap* wrap;
3441cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&wrap,
3451cb0ef41Sopenharmony_ci                          args.Holder(),
3461cb0ef41Sopenharmony_ci                          args.GetReturnValue().Set(UV_EBADF));
3471cb0ef41Sopenharmony_ci
3481cb0ef41Sopenharmony_ci  CHECK(args[0]->IsUint32());
3491cb0ef41Sopenharmony_ci  CHECK(args[1]->IsBoolean());
3501cb0ef41Sopenharmony_ci  bool is_recv = args[1].As<Boolean>()->Value();
3511cb0ef41Sopenharmony_ci  const char* uv_func_name = is_recv ? "uv_recv_buffer_size" :
3521cb0ef41Sopenharmony_ci                                       "uv_send_buffer_size";
3531cb0ef41Sopenharmony_ci
3541cb0ef41Sopenharmony_ci  if (!args[0]->IsInt32()) {
3551cb0ef41Sopenharmony_ci    env->CollectUVExceptionInfo(args[2], UV_EINVAL, uv_func_name);
3561cb0ef41Sopenharmony_ci    return args.GetReturnValue().SetUndefined();
3571cb0ef41Sopenharmony_ci  }
3581cb0ef41Sopenharmony_ci
3591cb0ef41Sopenharmony_ci  uv_handle_t* handle = reinterpret_cast<uv_handle_t*>(&wrap->handle_);
3601cb0ef41Sopenharmony_ci  int size = static_cast<int>(args[0].As<Uint32>()->Value());
3611cb0ef41Sopenharmony_ci  int err;
3621cb0ef41Sopenharmony_ci
3631cb0ef41Sopenharmony_ci  if (is_recv)
3641cb0ef41Sopenharmony_ci    err = uv_recv_buffer_size(handle, &size);
3651cb0ef41Sopenharmony_ci  else
3661cb0ef41Sopenharmony_ci    err = uv_send_buffer_size(handle, &size);
3671cb0ef41Sopenharmony_ci
3681cb0ef41Sopenharmony_ci  if (err != 0) {
3691cb0ef41Sopenharmony_ci    env->CollectUVExceptionInfo(args[2], err, uv_func_name);
3701cb0ef41Sopenharmony_ci    return args.GetReturnValue().SetUndefined();
3711cb0ef41Sopenharmony_ci  }
3721cb0ef41Sopenharmony_ci
3731cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(size);
3741cb0ef41Sopenharmony_ci}
3751cb0ef41Sopenharmony_ci
3761cb0ef41Sopenharmony_ci
3771cb0ef41Sopenharmony_civoid UDPWrap::Connect(const FunctionCallbackInfo<Value>& args) {
3781cb0ef41Sopenharmony_ci  DoConnect(args, AF_INET);
3791cb0ef41Sopenharmony_ci}
3801cb0ef41Sopenharmony_ci
3811cb0ef41Sopenharmony_ci
3821cb0ef41Sopenharmony_civoid UDPWrap::Connect6(const FunctionCallbackInfo<Value>& args) {
3831cb0ef41Sopenharmony_ci  DoConnect(args, AF_INET6);
3841cb0ef41Sopenharmony_ci}
3851cb0ef41Sopenharmony_ci
3861cb0ef41Sopenharmony_ci
3871cb0ef41Sopenharmony_civoid UDPWrap::Disconnect(const FunctionCallbackInfo<Value>& args) {
3881cb0ef41Sopenharmony_ci  UDPWrap* wrap;
3891cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&wrap,
3901cb0ef41Sopenharmony_ci                          args.Holder(),
3911cb0ef41Sopenharmony_ci                          args.GetReturnValue().Set(UV_EBADF));
3921cb0ef41Sopenharmony_ci
3931cb0ef41Sopenharmony_ci  CHECK_EQ(args.Length(), 0);
3941cb0ef41Sopenharmony_ci
3951cb0ef41Sopenharmony_ci  int err = uv_udp_connect(&wrap->handle_, nullptr);
3961cb0ef41Sopenharmony_ci
3971cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(err);
3981cb0ef41Sopenharmony_ci}
3991cb0ef41Sopenharmony_ci
4001cb0ef41Sopenharmony_civoid UDPWrap::SetMulticastInterface(const FunctionCallbackInfo<Value>& args) {
4011cb0ef41Sopenharmony_ci  UDPWrap* wrap;
4021cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&wrap,
4031cb0ef41Sopenharmony_ci                          args.Holder(),
4041cb0ef41Sopenharmony_ci                          args.GetReturnValue().Set(UV_EBADF));
4051cb0ef41Sopenharmony_ci
4061cb0ef41Sopenharmony_ci  CHECK_EQ(args.Length(), 1);
4071cb0ef41Sopenharmony_ci  CHECK(args[0]->IsString());
4081cb0ef41Sopenharmony_ci
4091cb0ef41Sopenharmony_ci  Utf8Value iface(args.GetIsolate(), args[0]);
4101cb0ef41Sopenharmony_ci
4111cb0ef41Sopenharmony_ci  const char* iface_cstr = *iface;
4121cb0ef41Sopenharmony_ci
4131cb0ef41Sopenharmony_ci  int err = uv_udp_set_multicast_interface(&wrap->handle_, iface_cstr);
4141cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(err);
4151cb0ef41Sopenharmony_ci}
4161cb0ef41Sopenharmony_ci
4171cb0ef41Sopenharmony_civoid UDPWrap::SetMembership(const FunctionCallbackInfo<Value>& args,
4181cb0ef41Sopenharmony_ci                            uv_membership membership) {
4191cb0ef41Sopenharmony_ci  UDPWrap* wrap;
4201cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&wrap,
4211cb0ef41Sopenharmony_ci                          args.Holder(),
4221cb0ef41Sopenharmony_ci                          args.GetReturnValue().Set(UV_EBADF));
4231cb0ef41Sopenharmony_ci
4241cb0ef41Sopenharmony_ci  CHECK_EQ(args.Length(), 2);
4251cb0ef41Sopenharmony_ci
4261cb0ef41Sopenharmony_ci  node::Utf8Value address(args.GetIsolate(), args[0]);
4271cb0ef41Sopenharmony_ci  node::Utf8Value iface(args.GetIsolate(), args[1]);
4281cb0ef41Sopenharmony_ci
4291cb0ef41Sopenharmony_ci  const char* iface_cstr = *iface;
4301cb0ef41Sopenharmony_ci  if (args[1]->IsUndefined() || args[1]->IsNull()) {
4311cb0ef41Sopenharmony_ci      iface_cstr = nullptr;
4321cb0ef41Sopenharmony_ci  }
4331cb0ef41Sopenharmony_ci
4341cb0ef41Sopenharmony_ci  int err = uv_udp_set_membership(&wrap->handle_,
4351cb0ef41Sopenharmony_ci                                  *address,
4361cb0ef41Sopenharmony_ci                                  iface_cstr,
4371cb0ef41Sopenharmony_ci                                  membership);
4381cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(err);
4391cb0ef41Sopenharmony_ci}
4401cb0ef41Sopenharmony_ci
4411cb0ef41Sopenharmony_ci
4421cb0ef41Sopenharmony_civoid UDPWrap::AddMembership(const FunctionCallbackInfo<Value>& args) {
4431cb0ef41Sopenharmony_ci  SetMembership(args, UV_JOIN_GROUP);
4441cb0ef41Sopenharmony_ci}
4451cb0ef41Sopenharmony_ci
4461cb0ef41Sopenharmony_ci
4471cb0ef41Sopenharmony_civoid UDPWrap::DropMembership(const FunctionCallbackInfo<Value>& args) {
4481cb0ef41Sopenharmony_ci  SetMembership(args, UV_LEAVE_GROUP);
4491cb0ef41Sopenharmony_ci}
4501cb0ef41Sopenharmony_ci
4511cb0ef41Sopenharmony_civoid UDPWrap::SetSourceMembership(const FunctionCallbackInfo<Value>& args,
4521cb0ef41Sopenharmony_ci                                  uv_membership membership) {
4531cb0ef41Sopenharmony_ci  UDPWrap* wrap;
4541cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&wrap,
4551cb0ef41Sopenharmony_ci                          args.Holder(),
4561cb0ef41Sopenharmony_ci                          args.GetReturnValue().Set(UV_EBADF));
4571cb0ef41Sopenharmony_ci
4581cb0ef41Sopenharmony_ci  CHECK_EQ(args.Length(), 3);
4591cb0ef41Sopenharmony_ci
4601cb0ef41Sopenharmony_ci  node::Utf8Value source_address(args.GetIsolate(), args[0]);
4611cb0ef41Sopenharmony_ci  node::Utf8Value group_address(args.GetIsolate(), args[1]);
4621cb0ef41Sopenharmony_ci  node::Utf8Value iface(args.GetIsolate(), args[2]);
4631cb0ef41Sopenharmony_ci
4641cb0ef41Sopenharmony_ci  if (*iface == nullptr) return;
4651cb0ef41Sopenharmony_ci  const char* iface_cstr = *iface;
4661cb0ef41Sopenharmony_ci  if (args[2]->IsUndefined() || args[2]->IsNull()) {
4671cb0ef41Sopenharmony_ci    iface_cstr = nullptr;
4681cb0ef41Sopenharmony_ci  }
4691cb0ef41Sopenharmony_ci
4701cb0ef41Sopenharmony_ci  int err = uv_udp_set_source_membership(&wrap->handle_,
4711cb0ef41Sopenharmony_ci                                         *group_address,
4721cb0ef41Sopenharmony_ci                                         iface_cstr,
4731cb0ef41Sopenharmony_ci                                         *source_address,
4741cb0ef41Sopenharmony_ci                                         membership);
4751cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(err);
4761cb0ef41Sopenharmony_ci}
4771cb0ef41Sopenharmony_ci
4781cb0ef41Sopenharmony_civoid UDPWrap::AddSourceSpecificMembership(
4791cb0ef41Sopenharmony_ci  const FunctionCallbackInfo<Value>& args) {
4801cb0ef41Sopenharmony_ci  SetSourceMembership(args, UV_JOIN_GROUP);
4811cb0ef41Sopenharmony_ci}
4821cb0ef41Sopenharmony_ci
4831cb0ef41Sopenharmony_ci
4841cb0ef41Sopenharmony_civoid UDPWrap::DropSourceSpecificMembership(
4851cb0ef41Sopenharmony_ci  const FunctionCallbackInfo<Value>& args) {
4861cb0ef41Sopenharmony_ci  SetSourceMembership(args, UV_LEAVE_GROUP);
4871cb0ef41Sopenharmony_ci}
4881cb0ef41Sopenharmony_ci
4891cb0ef41Sopenharmony_ci
4901cb0ef41Sopenharmony_civoid UDPWrap::DoSend(const FunctionCallbackInfo<Value>& args, int family) {
4911cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
4921cb0ef41Sopenharmony_ci
4931cb0ef41Sopenharmony_ci  UDPWrap* wrap;
4941cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&wrap,
4951cb0ef41Sopenharmony_ci                          args.Holder(),
4961cb0ef41Sopenharmony_ci                          args.GetReturnValue().Set(UV_EBADF));
4971cb0ef41Sopenharmony_ci
4981cb0ef41Sopenharmony_ci  CHECK(args.Length() == 4 || args.Length() == 6);
4991cb0ef41Sopenharmony_ci  CHECK(args[0]->IsObject());
5001cb0ef41Sopenharmony_ci  CHECK(args[1]->IsArray());
5011cb0ef41Sopenharmony_ci  CHECK(args[2]->IsUint32());
5021cb0ef41Sopenharmony_ci
5031cb0ef41Sopenharmony_ci  bool sendto = args.Length() == 6;
5041cb0ef41Sopenharmony_ci  if (sendto) {
5051cb0ef41Sopenharmony_ci    // send(req, list, list.length, port, address, hasCallback)
5061cb0ef41Sopenharmony_ci    CHECK(args[3]->IsUint32());
5071cb0ef41Sopenharmony_ci    CHECK(args[4]->IsString());
5081cb0ef41Sopenharmony_ci    CHECK(args[5]->IsBoolean());
5091cb0ef41Sopenharmony_ci  } else {
5101cb0ef41Sopenharmony_ci    // send(req, list, list.length, hasCallback)
5111cb0ef41Sopenharmony_ci    CHECK(args[3]->IsBoolean());
5121cb0ef41Sopenharmony_ci  }
5131cb0ef41Sopenharmony_ci
5141cb0ef41Sopenharmony_ci  Local<Array> chunks = args[1].As<Array>();
5151cb0ef41Sopenharmony_ci  // it is faster to fetch the length of the
5161cb0ef41Sopenharmony_ci  // array in js-land
5171cb0ef41Sopenharmony_ci  size_t count = args[2].As<Uint32>()->Value();
5181cb0ef41Sopenharmony_ci
5191cb0ef41Sopenharmony_ci  MaybeStackBuffer<uv_buf_t, 16> bufs(count);
5201cb0ef41Sopenharmony_ci
5211cb0ef41Sopenharmony_ci  // construct uv_buf_t array
5221cb0ef41Sopenharmony_ci  for (size_t i = 0; i < count; i++) {
5231cb0ef41Sopenharmony_ci    Local<Value> chunk;
5241cb0ef41Sopenharmony_ci    if (!chunks->Get(env->context(), i).ToLocal(&chunk)) return;
5251cb0ef41Sopenharmony_ci
5261cb0ef41Sopenharmony_ci    size_t length = Buffer::Length(chunk);
5271cb0ef41Sopenharmony_ci
5281cb0ef41Sopenharmony_ci    bufs[i] = uv_buf_init(Buffer::Data(chunk), length);
5291cb0ef41Sopenharmony_ci  }
5301cb0ef41Sopenharmony_ci
5311cb0ef41Sopenharmony_ci  int err = 0;
5321cb0ef41Sopenharmony_ci  struct sockaddr_storage addr_storage;
5331cb0ef41Sopenharmony_ci  sockaddr* addr = nullptr;
5341cb0ef41Sopenharmony_ci  if (sendto) {
5351cb0ef41Sopenharmony_ci    const unsigned short port = args[3].As<Uint32>()->Value();
5361cb0ef41Sopenharmony_ci    node::Utf8Value address(env->isolate(), args[4]);
5371cb0ef41Sopenharmony_ci    err = sockaddr_for_family(family, address.out(), port, &addr_storage);
5381cb0ef41Sopenharmony_ci    if (err == 0)
5391cb0ef41Sopenharmony_ci      addr = reinterpret_cast<sockaddr*>(&addr_storage);
5401cb0ef41Sopenharmony_ci  }
5411cb0ef41Sopenharmony_ci
5421cb0ef41Sopenharmony_ci  if (err == 0) {
5431cb0ef41Sopenharmony_ci    wrap->current_send_req_wrap_ = args[0].As<Object>();
5441cb0ef41Sopenharmony_ci    wrap->current_send_has_callback_ =
5451cb0ef41Sopenharmony_ci        sendto ? args[5]->IsTrue() : args[3]->IsTrue();
5461cb0ef41Sopenharmony_ci
5471cb0ef41Sopenharmony_ci    err = static_cast<int>(wrap->Send(*bufs, count, addr));
5481cb0ef41Sopenharmony_ci
5491cb0ef41Sopenharmony_ci    wrap->current_send_req_wrap_.Clear();
5501cb0ef41Sopenharmony_ci    wrap->current_send_has_callback_ = false;
5511cb0ef41Sopenharmony_ci  }
5521cb0ef41Sopenharmony_ci
5531cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(err);
5541cb0ef41Sopenharmony_ci}
5551cb0ef41Sopenharmony_ci
5561cb0ef41Sopenharmony_cissize_t UDPWrap::Send(uv_buf_t* bufs_ptr,
5571cb0ef41Sopenharmony_ci                      size_t count,
5581cb0ef41Sopenharmony_ci                      const sockaddr* addr) {
5591cb0ef41Sopenharmony_ci  if (IsHandleClosing()) return UV_EBADF;
5601cb0ef41Sopenharmony_ci
5611cb0ef41Sopenharmony_ci  size_t msg_size = 0;
5621cb0ef41Sopenharmony_ci  for (size_t i = 0; i < count; i++)
5631cb0ef41Sopenharmony_ci    msg_size += bufs_ptr[i].len;
5641cb0ef41Sopenharmony_ci
5651cb0ef41Sopenharmony_ci  int err = 0;
5661cb0ef41Sopenharmony_ci  if (!UNLIKELY(env()->options()->test_udp_no_try_send)) {
5671cb0ef41Sopenharmony_ci    err = uv_udp_try_send(&handle_, bufs_ptr, count, addr);
5681cb0ef41Sopenharmony_ci    if (err == UV_ENOSYS || err == UV_EAGAIN) {
5691cb0ef41Sopenharmony_ci      err = 0;
5701cb0ef41Sopenharmony_ci    } else if (err >= 0) {
5711cb0ef41Sopenharmony_ci      size_t sent = err;
5721cb0ef41Sopenharmony_ci      while (count > 0 && bufs_ptr->len <= sent) {
5731cb0ef41Sopenharmony_ci        sent -= bufs_ptr->len;
5741cb0ef41Sopenharmony_ci        bufs_ptr++;
5751cb0ef41Sopenharmony_ci        count--;
5761cb0ef41Sopenharmony_ci      }
5771cb0ef41Sopenharmony_ci      if (count > 0) {
5781cb0ef41Sopenharmony_ci        CHECK_LT(sent, bufs_ptr->len);
5791cb0ef41Sopenharmony_ci        bufs_ptr->base += sent;
5801cb0ef41Sopenharmony_ci        bufs_ptr->len -= sent;
5811cb0ef41Sopenharmony_ci      } else {
5821cb0ef41Sopenharmony_ci        CHECK_EQ(static_cast<size_t>(err), msg_size);
5831cb0ef41Sopenharmony_ci        // + 1 so that the JS side can distinguish 0-length async sends from
5841cb0ef41Sopenharmony_ci        // 0-length sync sends.
5851cb0ef41Sopenharmony_ci        return msg_size + 1;
5861cb0ef41Sopenharmony_ci      }
5871cb0ef41Sopenharmony_ci    }
5881cb0ef41Sopenharmony_ci  }
5891cb0ef41Sopenharmony_ci
5901cb0ef41Sopenharmony_ci  if (err == 0) {
5911cb0ef41Sopenharmony_ci    AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(this);
5921cb0ef41Sopenharmony_ci    ReqWrap<uv_udp_send_t>* req_wrap = listener()->CreateSendWrap(msg_size);
5931cb0ef41Sopenharmony_ci    if (req_wrap == nullptr) return UV_ENOSYS;
5941cb0ef41Sopenharmony_ci
5951cb0ef41Sopenharmony_ci    err = req_wrap->Dispatch(
5961cb0ef41Sopenharmony_ci        uv_udp_send,
5971cb0ef41Sopenharmony_ci        &handle_,
5981cb0ef41Sopenharmony_ci        bufs_ptr,
5991cb0ef41Sopenharmony_ci        count,
6001cb0ef41Sopenharmony_ci        addr,
6011cb0ef41Sopenharmony_ci        uv_udp_send_cb{[](uv_udp_send_t* req, int status) {
6021cb0ef41Sopenharmony_ci          UDPWrap* self = ContainerOf(&UDPWrap::handle_, req->handle);
6031cb0ef41Sopenharmony_ci          self->listener()->OnSendDone(
6041cb0ef41Sopenharmony_ci              ReqWrap<uv_udp_send_t>::from_req(req), status);
6051cb0ef41Sopenharmony_ci        }});
6061cb0ef41Sopenharmony_ci    if (err)
6071cb0ef41Sopenharmony_ci      delete req_wrap;
6081cb0ef41Sopenharmony_ci  }
6091cb0ef41Sopenharmony_ci
6101cb0ef41Sopenharmony_ci  return err;
6111cb0ef41Sopenharmony_ci}
6121cb0ef41Sopenharmony_ci
6131cb0ef41Sopenharmony_ci
6141cb0ef41Sopenharmony_ciReqWrap<uv_udp_send_t>* UDPWrap::CreateSendWrap(size_t msg_size) {
6151cb0ef41Sopenharmony_ci  SendWrap* req_wrap = new SendWrap(env(),
6161cb0ef41Sopenharmony_ci                                    current_send_req_wrap_,
6171cb0ef41Sopenharmony_ci                                    current_send_has_callback_);
6181cb0ef41Sopenharmony_ci  req_wrap->msg_size = msg_size;
6191cb0ef41Sopenharmony_ci  return req_wrap;
6201cb0ef41Sopenharmony_ci}
6211cb0ef41Sopenharmony_ci
6221cb0ef41Sopenharmony_ci
6231cb0ef41Sopenharmony_civoid UDPWrap::Send(const FunctionCallbackInfo<Value>& args) {
6241cb0ef41Sopenharmony_ci  DoSend(args, AF_INET);
6251cb0ef41Sopenharmony_ci}
6261cb0ef41Sopenharmony_ci
6271cb0ef41Sopenharmony_ci
6281cb0ef41Sopenharmony_civoid UDPWrap::Send6(const FunctionCallbackInfo<Value>& args) {
6291cb0ef41Sopenharmony_ci  DoSend(args, AF_INET6);
6301cb0ef41Sopenharmony_ci}
6311cb0ef41Sopenharmony_ci
6321cb0ef41Sopenharmony_ci
6331cb0ef41Sopenharmony_ciAsyncWrap* UDPWrap::GetAsyncWrap() {
6341cb0ef41Sopenharmony_ci  return this;
6351cb0ef41Sopenharmony_ci}
6361cb0ef41Sopenharmony_ci
6371cb0ef41Sopenharmony_ciSocketAddress UDPWrap::GetPeerName() {
6381cb0ef41Sopenharmony_ci  return SocketAddress::FromPeerName(handle_);
6391cb0ef41Sopenharmony_ci}
6401cb0ef41Sopenharmony_ci
6411cb0ef41Sopenharmony_ciSocketAddress UDPWrap::GetSockName() {
6421cb0ef41Sopenharmony_ci  return SocketAddress::FromSockName(handle_);
6431cb0ef41Sopenharmony_ci}
6441cb0ef41Sopenharmony_ci
6451cb0ef41Sopenharmony_civoid UDPWrapBase::RecvStart(const FunctionCallbackInfo<Value>& args) {
6461cb0ef41Sopenharmony_ci  UDPWrapBase* wrap = UDPWrapBase::FromObject(args.Holder());
6471cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(wrap == nullptr ? UV_EBADF : wrap->RecvStart());
6481cb0ef41Sopenharmony_ci}
6491cb0ef41Sopenharmony_ci
6501cb0ef41Sopenharmony_ciint UDPWrap::RecvStart() {
6511cb0ef41Sopenharmony_ci  if (IsHandleClosing()) return UV_EBADF;
6521cb0ef41Sopenharmony_ci  int err = uv_udp_recv_start(&handle_, OnAlloc, OnRecv);
6531cb0ef41Sopenharmony_ci  // UV_EALREADY means that the socket is already bound but that's okay
6541cb0ef41Sopenharmony_ci  if (err == UV_EALREADY)
6551cb0ef41Sopenharmony_ci    err = 0;
6561cb0ef41Sopenharmony_ci  return err;
6571cb0ef41Sopenharmony_ci}
6581cb0ef41Sopenharmony_ci
6591cb0ef41Sopenharmony_ci
6601cb0ef41Sopenharmony_civoid UDPWrapBase::RecvStop(const FunctionCallbackInfo<Value>& args) {
6611cb0ef41Sopenharmony_ci  UDPWrapBase* wrap = UDPWrapBase::FromObject(args.Holder());
6621cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(wrap == nullptr ? UV_EBADF : wrap->RecvStop());
6631cb0ef41Sopenharmony_ci}
6641cb0ef41Sopenharmony_ci
6651cb0ef41Sopenharmony_ciint UDPWrap::RecvStop() {
6661cb0ef41Sopenharmony_ci  if (IsHandleClosing()) return UV_EBADF;
6671cb0ef41Sopenharmony_ci  return uv_udp_recv_stop(&handle_);
6681cb0ef41Sopenharmony_ci}
6691cb0ef41Sopenharmony_ci
6701cb0ef41Sopenharmony_ci
6711cb0ef41Sopenharmony_civoid UDPWrap::OnSendDone(ReqWrap<uv_udp_send_t>* req, int status) {
6721cb0ef41Sopenharmony_ci  BaseObjectPtr<SendWrap> req_wrap{static_cast<SendWrap*>(req)};
6731cb0ef41Sopenharmony_ci  if (req_wrap->have_callback()) {
6741cb0ef41Sopenharmony_ci    Environment* env = req_wrap->env();
6751cb0ef41Sopenharmony_ci    HandleScope handle_scope(env->isolate());
6761cb0ef41Sopenharmony_ci    Context::Scope context_scope(env->context());
6771cb0ef41Sopenharmony_ci    Local<Value> arg[] = {
6781cb0ef41Sopenharmony_ci      Integer::New(env->isolate(), status),
6791cb0ef41Sopenharmony_ci      Integer::New(env->isolate(), req_wrap->msg_size),
6801cb0ef41Sopenharmony_ci    };
6811cb0ef41Sopenharmony_ci    req_wrap->MakeCallback(env->oncomplete_string(), 2, arg);
6821cb0ef41Sopenharmony_ci  }
6831cb0ef41Sopenharmony_ci}
6841cb0ef41Sopenharmony_ci
6851cb0ef41Sopenharmony_ci
6861cb0ef41Sopenharmony_civoid UDPWrap::OnAlloc(uv_handle_t* handle,
6871cb0ef41Sopenharmony_ci                      size_t suggested_size,
6881cb0ef41Sopenharmony_ci                      uv_buf_t* buf) {
6891cb0ef41Sopenharmony_ci  UDPWrap* wrap = ContainerOf(&UDPWrap::handle_,
6901cb0ef41Sopenharmony_ci                              reinterpret_cast<uv_udp_t*>(handle));
6911cb0ef41Sopenharmony_ci  *buf = wrap->listener()->OnAlloc(suggested_size);
6921cb0ef41Sopenharmony_ci}
6931cb0ef41Sopenharmony_ci
6941cb0ef41Sopenharmony_ciuv_buf_t UDPWrap::OnAlloc(size_t suggested_size) {
6951cb0ef41Sopenharmony_ci  return env()->allocate_managed_buffer(suggested_size);
6961cb0ef41Sopenharmony_ci}
6971cb0ef41Sopenharmony_ci
6981cb0ef41Sopenharmony_civoid UDPWrap::OnRecv(uv_udp_t* handle,
6991cb0ef41Sopenharmony_ci                     ssize_t nread,
7001cb0ef41Sopenharmony_ci                     const uv_buf_t* buf,
7011cb0ef41Sopenharmony_ci                     const sockaddr* addr,
7021cb0ef41Sopenharmony_ci                     unsigned int flags) {
7031cb0ef41Sopenharmony_ci  UDPWrap* wrap = ContainerOf(&UDPWrap::handle_, handle);
7041cb0ef41Sopenharmony_ci  wrap->listener()->OnRecv(nread, *buf, addr, flags);
7051cb0ef41Sopenharmony_ci}
7061cb0ef41Sopenharmony_ci
7071cb0ef41Sopenharmony_civoid UDPWrap::OnRecv(ssize_t nread,
7081cb0ef41Sopenharmony_ci                     const uv_buf_t& buf_,
7091cb0ef41Sopenharmony_ci                     const sockaddr* addr,
7101cb0ef41Sopenharmony_ci                     unsigned int flags) {
7111cb0ef41Sopenharmony_ci  Environment* env = this->env();
7121cb0ef41Sopenharmony_ci  Isolate* isolate = env->isolate();
7131cb0ef41Sopenharmony_ci  std::unique_ptr<BackingStore> bs = env->release_managed_buffer(buf_);
7141cb0ef41Sopenharmony_ci  if (nread == 0 && addr == nullptr) {
7151cb0ef41Sopenharmony_ci    return;
7161cb0ef41Sopenharmony_ci  }
7171cb0ef41Sopenharmony_ci
7181cb0ef41Sopenharmony_ci  HandleScope handle_scope(isolate);
7191cb0ef41Sopenharmony_ci  Context::Scope context_scope(env->context());
7201cb0ef41Sopenharmony_ci
7211cb0ef41Sopenharmony_ci  Local<Value> argv[] = {
7221cb0ef41Sopenharmony_ci      Integer::New(isolate, static_cast<int32_t>(nread)),
7231cb0ef41Sopenharmony_ci      object(),
7241cb0ef41Sopenharmony_ci      Undefined(isolate),
7251cb0ef41Sopenharmony_ci      Undefined(isolate)};
7261cb0ef41Sopenharmony_ci
7271cb0ef41Sopenharmony_ci  if (nread < 0) {
7281cb0ef41Sopenharmony_ci    MakeCallback(env->onmessage_string(), arraysize(argv), argv);
7291cb0ef41Sopenharmony_ci    return;
7301cb0ef41Sopenharmony_ci  } else if (nread == 0) {
7311cb0ef41Sopenharmony_ci    bs = ArrayBuffer::NewBackingStore(isolate, 0);
7321cb0ef41Sopenharmony_ci  } else {
7331cb0ef41Sopenharmony_ci    CHECK_LE(static_cast<size_t>(nread), bs->ByteLength());
7341cb0ef41Sopenharmony_ci    bs = BackingStore::Reallocate(isolate, std::move(bs), nread);
7351cb0ef41Sopenharmony_ci  }
7361cb0ef41Sopenharmony_ci
7371cb0ef41Sopenharmony_ci  Local<Object> address;
7381cb0ef41Sopenharmony_ci  {
7391cb0ef41Sopenharmony_ci    bool has_caught = false;
7401cb0ef41Sopenharmony_ci    {
7411cb0ef41Sopenharmony_ci      TryCatchScope try_catch(env);
7421cb0ef41Sopenharmony_ci      if (!AddressToJS(env, addr).ToLocal(&address)) {
7431cb0ef41Sopenharmony_ci        DCHECK(try_catch.HasCaught() && !try_catch.HasTerminated());
7441cb0ef41Sopenharmony_ci        argv[2] = try_catch.Exception();
7451cb0ef41Sopenharmony_ci        DCHECK(!argv[2].IsEmpty());
7461cb0ef41Sopenharmony_ci        has_caught = true;
7471cb0ef41Sopenharmony_ci      }
7481cb0ef41Sopenharmony_ci    }
7491cb0ef41Sopenharmony_ci    if (has_caught) {
7501cb0ef41Sopenharmony_ci      DCHECK(!argv[2].IsEmpty());
7511cb0ef41Sopenharmony_ci      MakeCallback(env->onerror_string(), arraysize(argv), argv);
7521cb0ef41Sopenharmony_ci      return;
7531cb0ef41Sopenharmony_ci    }
7541cb0ef41Sopenharmony_ci  }
7551cb0ef41Sopenharmony_ci
7561cb0ef41Sopenharmony_ci  Local<ArrayBuffer> ab = ArrayBuffer::New(isolate, std::move(bs));
7571cb0ef41Sopenharmony_ci  {
7581cb0ef41Sopenharmony_ci    bool has_caught = false;
7591cb0ef41Sopenharmony_ci    {
7601cb0ef41Sopenharmony_ci      TryCatchScope try_catch(env);
7611cb0ef41Sopenharmony_ci      if (!Buffer::New(env, ab, 0, ab->ByteLength()).ToLocal(&argv[2])) {
7621cb0ef41Sopenharmony_ci        DCHECK(try_catch.HasCaught() && !try_catch.HasTerminated());
7631cb0ef41Sopenharmony_ci        argv[2] = try_catch.Exception();
7641cb0ef41Sopenharmony_ci        DCHECK(!argv[2].IsEmpty());
7651cb0ef41Sopenharmony_ci        has_caught = true;
7661cb0ef41Sopenharmony_ci      }
7671cb0ef41Sopenharmony_ci    }
7681cb0ef41Sopenharmony_ci    if (has_caught) {
7691cb0ef41Sopenharmony_ci      DCHECK(!argv[2].IsEmpty());
7701cb0ef41Sopenharmony_ci      MakeCallback(env->onerror_string(), arraysize(argv), argv);
7711cb0ef41Sopenharmony_ci      return;
7721cb0ef41Sopenharmony_ci    }
7731cb0ef41Sopenharmony_ci  }
7741cb0ef41Sopenharmony_ci
7751cb0ef41Sopenharmony_ci  argv[3] = address;
7761cb0ef41Sopenharmony_ci  MakeCallback(env->onmessage_string(), arraysize(argv), argv);
7771cb0ef41Sopenharmony_ci}
7781cb0ef41Sopenharmony_ci
7791cb0ef41Sopenharmony_ciMaybeLocal<Object> UDPWrap::Instantiate(Environment* env,
7801cb0ef41Sopenharmony_ci                                        AsyncWrap* parent,
7811cb0ef41Sopenharmony_ci                                        UDPWrap::SocketType type) {
7821cb0ef41Sopenharmony_ci  AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(parent);
7831cb0ef41Sopenharmony_ci
7841cb0ef41Sopenharmony_ci  // If this assert fires then Initialize hasn't been called yet.
7851cb0ef41Sopenharmony_ci  CHECK_EQ(env->udp_constructor_function().IsEmpty(), false);
7861cb0ef41Sopenharmony_ci  return env->udp_constructor_function()->NewInstance(env->context());
7871cb0ef41Sopenharmony_ci}
7881cb0ef41Sopenharmony_ci
7891cb0ef41Sopenharmony_civoid UDPWrap::GetSendQueueSize(const FunctionCallbackInfo<Value>& args) {
7901cb0ef41Sopenharmony_ci  UDPWrap* wrap;
7911cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(
7921cb0ef41Sopenharmony_ci      &wrap, args.Holder(), args.GetReturnValue().Set(UV_EBADF));
7931cb0ef41Sopenharmony_ci
7941cb0ef41Sopenharmony_ci  size_t size = uv_udp_get_send_queue_size(&wrap->handle_);
7951cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(static_cast<double>(size));
7961cb0ef41Sopenharmony_ci}
7971cb0ef41Sopenharmony_ci
7981cb0ef41Sopenharmony_civoid UDPWrap::GetSendQueueCount(const FunctionCallbackInfo<Value>& args) {
7991cb0ef41Sopenharmony_ci  UDPWrap* wrap;
8001cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(
8011cb0ef41Sopenharmony_ci      &wrap, args.Holder(), args.GetReturnValue().Set(UV_EBADF));
8021cb0ef41Sopenharmony_ci
8031cb0ef41Sopenharmony_ci  size_t count = uv_udp_get_send_queue_count(&wrap->handle_);
8041cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(static_cast<double>(count));
8051cb0ef41Sopenharmony_ci}
8061cb0ef41Sopenharmony_ci
8071cb0ef41Sopenharmony_ci}  // namespace node
8081cb0ef41Sopenharmony_ci
8091cb0ef41Sopenharmony_ciNODE_BINDING_CONTEXT_AWARE_INTERNAL(udp_wrap, node::UDPWrap::Initialize)
810