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