39 using v8::EscapableHandleScope;
40 using v8::FunctionCallbackInfo;
41 using v8::FunctionTemplate;
42 using v8::HandleScope;
46 using v8::PropertyAttribute;
47 using v8::PropertyCallbackInfo;
55 class SendWrap :
public ReqWrap<uv_udp_send_t> {
61 size_t self_size()
const override {
return sizeof(*this); }
63 const bool have_callback_;
68 Local<Object> req_wrap_obj,
70 : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_UDPSENDWRAP),
71 have_callback_(have_callback) {
72 Wrap(req_wrap_obj,
this);
82 return have_callback_;
86 static void NewSendWrap(
const FunctionCallbackInfo<Value>& args) {
87 CHECK(args.IsConstructCall());
88 ClearWrap(args.This());
92 UDPWrap::UDPWrap(Environment* env, Local<Object>
object)
95 reinterpret_cast<uv_handle_t*>(&handle_),
96 AsyncWrap::PROVIDER_UDPWRAP) {
97 int r = uv_udp_init(env->event_loop(), &handle_);
104 Local<Context> context) {
105 Environment* env = Environment::GetCurrent(context);
107 Local<FunctionTemplate>
t = env->NewFunctionTemplate(
New);
108 t->InstanceTemplate()->SetInternalFieldCount(1);
109 Local<String> udpString =
110 FIXED_ONE_BYTE_STRING(env->isolate(),
"UDP");
111 t->SetClassName(udpString);
113 enum PropertyAttribute attributes =
114 static_cast<PropertyAttribute
>(v8::ReadOnly | v8::DontDelete);
115 t->InstanceTemplate()->SetAccessor(env->fd_string(),
122 env->SetProtoMethod(t,
"bind", Bind);
123 env->SetProtoMethod(t,
"send", Send);
124 env->SetProtoMethod(t,
"bind6", Bind6);
125 env->SetProtoMethod(t,
"send6", Send6);
126 env->SetProtoMethod(t,
"close", Close);
127 env->SetProtoMethod(t,
"recvStart", RecvStart);
128 env->SetProtoMethod(t,
"recvStop", RecvStop);
129 env->SetProtoMethod(t,
"getsockname",
130 GetSockOrPeerName<UDPWrap, uv_udp_getsockname>);
131 env->SetProtoMethod(t,
"addMembership", AddMembership);
132 env->SetProtoMethod(t,
"dropMembership", DropMembership);
133 env->SetProtoMethod(t,
"setMulticastTTL", SetMulticastTTL);
134 env->SetProtoMethod(t,
"setMulticastLoopback", SetMulticastLoopback);
135 env->SetProtoMethod(t,
"setBroadcast", SetBroadcast);
136 env->SetProtoMethod(t,
"setTTL", SetTTL);
138 env->SetProtoMethod(t,
"ref", HandleWrap::Ref);
139 env->SetProtoMethod(t,
"unref", HandleWrap::Unref);
140 env->SetProtoMethod(t,
"hasRef", HandleWrap::HasRef);
142 AsyncWrap::AddWrapMethods(env, t);
144 target->Set(udpString, t->GetFunction());
145 env->set_udp_constructor_function(t->GetFunction());
148 Local<FunctionTemplate> swt =
150 swt->InstanceTemplate()->SetInternalFieldCount(1);
151 AsyncWrap::AddWrapMethods(env, swt);
152 Local<String> sendWrapString =
153 FIXED_ONE_BYTE_STRING(env->isolate(),
"SendWrap");
154 swt->SetClassName(sendWrapString);
155 target->Set(sendWrapString, swt->GetFunction());
159 void UDPWrap::New(
const FunctionCallbackInfo<Value>& args) {
160 CHECK(args.IsConstructCall());
161 Environment* env = Environment::GetCurrent(args);
162 new UDPWrap(env, args.This());
166 void UDPWrap::GetFD(Local<String>,
const PropertyCallbackInfo<Value>& args) {
169 HandleScope scope(args.GetIsolate());
170 UDPWrap*
wrap = Unwrap<UDPWrap>(args.Holder());
172 uv_fileno(reinterpret_cast<uv_handle_t*>(&wrap->handle_), &fd);
174 args.GetReturnValue().Set(fd);
178 void UDPWrap::DoBind(
const FunctionCallbackInfo<Value>& args,
int family) {
180 ASSIGN_OR_RETURN_UNWRAP(&wrap,
182 args.GetReturnValue().Set(UV_EBADF));
185 CHECK_EQ(args.Length(), 3);
187 node::Utf8Value address(args.GetIsolate(), args[0]);
188 const int port = args[1]->Uint32Value();
189 const int flags = args[2]->Uint32Value();
190 char addr[
sizeof(sockaddr_in6)];
195 err = uv_ip4_addr(*address, port, reinterpret_cast<sockaddr_in*>(&addr));
198 err = uv_ip6_addr(*address, port, reinterpret_cast<sockaddr_in6*>(&addr));
201 CHECK(0 &&
"unexpected address family");
206 err = uv_udp_bind(&wrap->handle_,
207 reinterpret_cast<const sockaddr*>(&addr),
211 args.GetReturnValue().Set(err);
215 void UDPWrap::Bind(
const FunctionCallbackInfo<Value>& args) {
216 DoBind(args, AF_INET);
220 void UDPWrap::Bind6(
const FunctionCallbackInfo<Value>& args) {
221 DoBind(args, AF_INET6);
225 #define X(name, fn) \ 226 void UDPWrap::name(const FunctionCallbackInfo<Value>& args) { \ 227 UDPWrap* wrap = Unwrap<UDPWrap>(args.Holder()); \ 228 CHECK_EQ(args.Length(), 1); \ 229 int flag = args[0]->Int32Value(); \ 230 int err = wrap == nullptr ? UV_EBADF : fn(&wrap->handle_, flag); \ 231 args.GetReturnValue().Set(err); \ 234 X(SetTTL, uv_udp_set_ttl)
235 X(SetBroadcast, uv_udp_set_broadcast)
236 X(SetMulticastTTL, uv_udp_set_multicast_ttl)
237 X(SetMulticastLoopback, uv_udp_set_multicast_loop)
242 void UDPWrap::SetMembership(
const FunctionCallbackInfo<Value>& args,
243 uv_membership membership) {
245 ASSIGN_OR_RETURN_UNWRAP(&wrap,
247 args.GetReturnValue().Set(UV_EBADF));
249 CHECK_EQ(args.Length(), 2);
251 node::Utf8Value address(args.GetIsolate(), args[0]);
252 node::Utf8Value iface(args.GetIsolate(), args[1]);
254 const char* iface_cstr = *iface;
255 if (args[1]->IsUndefined() || args[1]->IsNull()) {
256 iface_cstr =
nullptr;
259 int err = uv_udp_set_membership(&wrap->handle_,
263 args.GetReturnValue().Set(err);
267 void UDPWrap::AddMembership(
const FunctionCallbackInfo<Value>& args) {
268 SetMembership(args, UV_JOIN_GROUP);
272 void UDPWrap::DropMembership(
const FunctionCallbackInfo<Value>& args) {
273 SetMembership(args, UV_LEAVE_GROUP);
277 void UDPWrap::DoSend(
const FunctionCallbackInfo<Value>& args,
int family) {
278 Environment* env = Environment::GetCurrent(args);
281 ASSIGN_OR_RETURN_UNWRAP(&wrap,
283 args.GetReturnValue().Set(UV_EBADF));
286 CHECK(args[0]->IsObject());
287 CHECK(args[1]->IsArray());
288 CHECK(args[2]->IsUint32());
289 CHECK(args[3]->IsUint32());
290 CHECK(args[4]->IsString());
291 CHECK(args[5]->IsBoolean());
293 Local<Object> req_wrap_obj = args[0].As<Object>();
294 Local<Array> chunks = args[1].As<Array>();
297 size_t count = args[2]->Uint32Value();
298 const unsigned short port = args[3]->Uint32Value();
299 node::Utf8Value address(env->isolate(), args[4]);
302 env->set_init_trigger_id(wrap->get_id());
306 MaybeStackBuffer<uv_buf_t, 16> bufs(count);
309 for (
size_t i = 0; i < count; i++) {
310 Local<Value> chunk = chunks->Get(i);
320 char addr[
sizeof(sockaddr_in6)];
325 err = uv_ip4_addr(*address, port, reinterpret_cast<sockaddr_in*>(&addr));
328 err = uv_ip6_addr(*address, port, reinterpret_cast<sockaddr_in6*>(&addr));
331 CHECK(0 &&
"unexpected address family");
336 err = uv_udp_send(req_wrap->req(),
340 reinterpret_cast<const sockaddr*
>(&addr),
344 req_wrap->Dispatched();
348 args.GetReturnValue().Set(err);
352 void UDPWrap::Send(
const FunctionCallbackInfo<Value>& args) {
353 DoSend(args, AF_INET);
357 void UDPWrap::Send6(
const FunctionCallbackInfo<Value>& args) {
358 DoSend(args, AF_INET6);
362 void UDPWrap::RecvStart(
const FunctionCallbackInfo<Value>& args) {
364 ASSIGN_OR_RETURN_UNWRAP(&wrap,
366 args.GetReturnValue().Set(UV_EBADF));
367 int err = uv_udp_recv_start(&wrap->handle_, OnAlloc, OnRecv);
369 if (err == UV_EALREADY)
371 args.GetReturnValue().Set(err);
375 void UDPWrap::RecvStop(
const FunctionCallbackInfo<Value>& args) {
377 ASSIGN_OR_RETURN_UNWRAP(&wrap,
379 args.GetReturnValue().Set(UV_EBADF));
380 int r = uv_udp_recv_stop(&wrap->handle_);
381 args.GetReturnValue().Set(r);
385 void UDPWrap::OnSend(uv_udp_send_t*
req,
int status) {
387 if (req_wrap->have_callback()) {
388 Environment* env = req_wrap->env();
389 HandleScope handle_scope(env->isolate());
390 Context::Scope context_scope(env->context());
391 Local<Value> arg[] = {
395 req_wrap->MakeCallback(env->oncomplete_string(), 2, arg);
401 void UDPWrap::OnAlloc(uv_handle_t* handle,
402 size_t suggested_size,
404 buf->base = node::Malloc(suggested_size);
405 buf->len = suggested_size;
409 void UDPWrap::OnRecv(uv_udp_t* handle,
412 const struct sockaddr* addr,
413 unsigned int flags) {
414 if (nread == 0 && addr ==
nullptr) {
415 if (buf->base !=
nullptr)
420 UDPWrap*
wrap =
static_cast<UDPWrap*
>(handle->data);
421 Environment* env = wrap->env();
423 HandleScope handle_scope(env->isolate());
424 Context::Scope context_scope(env->context());
426 Local<Object> wrap_obj = wrap->object();
427 Local<Value> argv[] = {
430 Undefined(env->isolate()),
431 Undefined(env->isolate())
435 if (buf->base !=
nullptr)
437 wrap->MakeCallback(env->onmessage_string(), arraysize(argv), argv);
441 char* base = node::UncheckedRealloc(buf->base, nread);
442 argv[2] =
Buffer::New(env, base, nread).ToLocalChecked();
444 wrap->MakeCallback(env->onmessage_string(), arraysize(argv), argv);
448 Local<Object> UDPWrap::Instantiate(Environment* env, AsyncWrap* parent) {
449 EscapableHandleScope scope(env->isolate());
450 AsyncHooks::InitScope init_scope(env, parent->get_id());
452 CHECK_EQ(env->udp_constructor_function().IsEmpty(),
false);
453 Local<Object> instance = env->udp_constructor_function()
454 ->NewInstance(env->context()).ToLocalChecked();
455 return scope.Escape(instance);
459 uv_udp_t* UDPWrap::UVHandle() {
bool have_callback() const
NODE_MODULE_CONTEXT_AWARE_BUILTIN(inspector, node::inspector::Agent::InitInspector)
size_t self_size() const override
X(SetTTL, uv_udp_set_ttl) X(SetBroadcast
size_t Length(Local< Value > val)
void Initialize(Local< Object > target, Local< Value > unused, Local< Context > context, void *priv)
char * Data(Local< Value > val)
SendWrap(Environment *env, Local< Object > req_wrap_obj, bool have_callback)
Local< Object > AddressToJS(Environment *env, const sockaddr *addr, Local< Object > info)
MaybeLocal< Object > New(Isolate *isolate, Local< String > string, enum encoding enc)
node::Environment::AsyncHooks AsyncHooks