@@ -69,18 +69,57 @@ SendWrap::SendWrap(Environment* env,
69
69
}
70
70
71
71
72
- inline bool SendWrap::have_callback () const {
72
+ bool SendWrap::have_callback () const {
73
73
return have_callback_;
74
74
}
75
75
76
+ UDPListener::~UDPListener () {
77
+ if (wrap_ != nullptr )
78
+ wrap_->set_listener (nullptr );
79
+ }
80
+
81
+ UDPWrapBase::~UDPWrapBase () {
82
+ set_listener (nullptr );
83
+ }
84
+
85
+ UDPListener* UDPWrapBase::listener () const {
86
+ CHECK_NOT_NULL (listener_);
87
+ return listener_;
88
+ }
89
+
90
+ void UDPWrapBase::set_listener (UDPListener* listener) {
91
+ if (listener_ != nullptr )
92
+ listener_->wrap_ = nullptr ;
93
+ listener_ = listener;
94
+ if (listener_ != nullptr ) {
95
+ CHECK_NULL (listener_->wrap_ );
96
+ listener_->wrap_ = this ;
97
+ }
98
+ }
99
+
100
+ UDPWrapBase* UDPWrapBase::FromObject (Local<Object> obj) {
101
+ CHECK_GT (obj->InternalFieldCount (), UDPWrapBase::kUDPWrapBaseField );
102
+ return static_cast <UDPWrapBase*>(
103
+ obj->GetAlignedPointerFromInternalField (UDPWrapBase::kUDPWrapBaseField ));
104
+ }
105
+
106
+ void UDPWrapBase::AddMethods (Environment* env, Local<FunctionTemplate> t) {
107
+ env->SetProtoMethod (t, " recvStart" , RecvStart);
108
+ env->SetProtoMethod (t, " recvStop" , RecvStop);
109
+ }
76
110
77
111
UDPWrap::UDPWrap (Environment* env, Local<Object> object)
78
112
: HandleWrap(env,
79
113
object,
80
114
reinterpret_cast <uv_handle_t *>(&handle_),
81
115
AsyncWrap::PROVIDER_UDPWRAP) {
116
+ object->SetAlignedPointerInInternalField (
117
+ UDPWrapBase::kUDPWrapBaseField , static_cast <UDPWrapBase*>(this ));
118
+
82
119
int r = uv_udp_init (env->event_loop (), &handle_);
83
120
CHECK_EQ (r, 0 ); // can't fail anyway
121
+
122
+ set_listener (this );
84
123
}
85
124
86
125
@@ -91,7 +130,8 @@ void UDPWrap::Initialize(Local<Object> target,
91
130
Environment* env = Environment::GetCurrent (context);
92
131
93
132
Local<FunctionTemplate> t = env->NewFunctionTemplate (New);
94
- t->InstanceTemplate ()->SetInternalFieldCount (UDPWrap::kInternalFieldCount );
133
+ t->InstanceTemplate ()->SetInternalFieldCount (
134
+ UDPWrapBase::kInternalFieldCount );
95
135
Local<String> udpString =
96
136
FIXED_ONE_BYTE_STRING (env->isolate (), " UDP" );
97
137
t->SetClassName (udpString);
@@ -112,6 +152,7 @@ void UDPWrap::Initialize(Local<Object> target,
112
152
Local<FunctionTemplate>(),
113
153
attributes);
114
154
155
+ UDPWrapBase::AddMethods (env, t);
115
156
env->SetProtoMethod (t, " open" , Open);
116
157
env->SetProtoMethod (t, " bind" , Bind);
117
158
env->SetProtoMethod (t, " connect" , Connect);
@@ -120,8 +161,6 @@ void UDPWrap::Initialize(Local<Object> target,
120
161
env->SetProtoMethod (t, " connect6" , Connect6);
121
162
env->SetProtoMethod (t, " send6" , Send6);
122
163
env->SetProtoMethod (t, " disconnect" , Disconnect);
123
- env->SetProtoMethod (t, " recvStart" , RecvStart);
124
- env->SetProtoMethod (t, " recvStop" , RecvStop);
125
164
env->SetProtoMethod (t, " getpeername" ,
126
165
GetSockOrPeerName<UDPWrap, uv_udp_getpeername>);
127
166
env->SetProtoMethod (t, " getsockname" ,
@@ -220,6 +259,9 @@ void UDPWrap::DoBind(const FunctionCallbackInfo<Value>& args, int family) {
220
259
flags);
221
260
}
222
261
262
+ if (err == 0 )
263
+ wrap->listener ()->OnAfterBind ();
264
+
223
265
args.GetReturnValue ().Set (err);
224
266
}
225
267
@@ -464,14 +506,10 @@ void UDPWrap::DoSend(const FunctionCallbackInfo<Value>& args, int family) {
464
506
CHECK (args[3 ]->IsBoolean ());
465
507
}
466
508
467
- Local<Object> req_wrap_obj = args[0 ].As <Object>();
468
509
Local<Array> chunks = args[1 ].As <Array>();
469
510
// it is faster to fetch the length of the
470
511
// array in js-land
471
512
size_t count = args[2 ].As <Uint32>()->Value ();
472
- const bool have_callback = sendto ? args[5 ]->IsTrue () : args[3 ]->IsTrue ();
473
-
474
- size_t msg_size = 0 ;
475
513
476
514
MaybeStackBuffer<uv_buf_t , 16 > bufs (count);
477
515
@@ -483,7 +521,6 @@ void UDPWrap::DoSend(const FunctionCallbackInfo<Value>& args, int family) {
483
521
size_t length = Buffer::Length (chunk);
484
522
485
523
bufs[i] = uv_buf_init (Buffer::Data (chunk), length);
486
- msg_size += length;
487
524
}
488
525
489
526
int err = 0 ;
@@ -493,14 +530,36 @@ void UDPWrap::DoSend(const FunctionCallbackInfo<Value>& args, int family) {
493
530
const unsigned short port = args[3 ].As <Uint32>()->Value ();
494
531
node::Utf8Value address (env->isolate (), args[4 ]);
495
532
err = sockaddr_for_family (family, address.out (), port, &addr_storage);
496
- if (err == 0 ) {
533
+ if (err == 0 )
497
534
addr = reinterpret_cast <sockaddr*>(&addr_storage);
498
- }
499
535
}
500
536
501
- uv_buf_t * bufs_ptr = *bufs;
502
- if (err == 0 && !UNLIKELY (env->options ()->test_udp_no_try_send )) {
503
- err = uv_udp_try_send (&wrap->handle_ , bufs_ptr, count, addr);
537
+ if (err == 0 ) {
538
+ wrap->current_send_req_wrap_ = args[0 ].As <Object>();
539
+ wrap->current_send_has_callback_ =
540
+ sendto ? args[5 ]->IsTrue () : args[3 ]->IsTrue ();
541
+
542
+ err = wrap->Send (*bufs, count, addr);
543
+
544
+ wrap->current_send_req_wrap_ .Clear ();
545
+ wrap->current_send_has_callback_ = false ;
546
+ }
547
+
548
+ args.GetReturnValue ().Set (err);
549
+ }
550
+
551
+ ssize_t UDPWrap::Send (uv_buf_t * bufs_ptr,
552
+ size_t count,
553
+ const sockaddr* addr) {
554
+ if (IsHandleClosing ()) return UV_EBADF;
555
+
556
+ size_t msg_size = 0 ;
557
+ for (size_t i = 0 ; i < count; i++)
558
+ msg_size += bufs_ptr[i].len ;
559
+
560
+ int err = 0 ;
561
+ if (!UNLIKELY (env ()->options ()->test_udp_no_try_send )) {
562
+ err = uv_udp_try_send (&handle_, bufs_ptr, count, addr);
504
563
if (err == UV_ENOSYS || err == UV_EAGAIN) {
505
564
err = 0 ;
506
565
} else if (err >= 0 ) {
@@ -518,28 +577,41 @@ void UDPWrap::DoSend(const FunctionCallbackInfo<Value>& args, int family) {
518
577
CHECK_EQ (static_cast <size_t >(err), msg_size);
519
578
// + 1 so that the JS side can distinguish 0-length async sends from
520
579
// 0-length sync sends.
521
- args.GetReturnValue ().Set (static_cast <uint32_t >(msg_size) + 1 );
522
- return ;
580
+ return msg_size + 1 ;
523
581
}
524
582
}
525
583
}
526
584
527
585
if (err == 0 ) {
528
- AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope (wrap);
529
- SendWrap* req_wrap = new SendWrap (env, req_wrap_obj, have_callback);
530
- req_wrap->msg_size = msg_size;
531
-
532
- err = req_wrap->Dispatch (uv_udp_send,
533
- &wrap->handle_ ,
534
- bufs_ptr,
535
- count,
536
- addr,
537
- OnSend);
586
+ AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope (this );
587
+ ReqWrap<uv_udp_send_t >* req_wrap = listener ()->CreateSendWrap (msg_size);
588
+ if (req_wrap == nullptr ) return UV_ENOSYS;
589
+
590
+ err = req_wrap->Dispatch (
591
+ uv_udp_send,
592
+ &handle_,
593
+ bufs_ptr,
594
+ count,
595
+ addr,
596
+ uv_udp_send_cb{[](uv_udp_send_t * req, int status) {
597
+ UDPWrap* self = ContainerOf (&UDPWrap::handle_, req->handle );
598
+ self->listener ()->OnSendDone (
599
+ ReqWrap<uv_udp_send_t >::from_req (req), status);
600
+ }});
538
601
if (err)
539
602
delete req_wrap;
540
603
}
541
604
542
- args.GetReturnValue ().Set (err);
605
+ return err;
606
+ }
607
+
608
+
609
+ ReqWrap<uv_udp_send_t >* UDPWrap::CreateSendWrap (size_t msg_size) {
610
+ SendWrap* req_wrap = new SendWrap (env (),
611
+ current_send_req_wrap_,
612
+ current_send_has_callback_);
613
+ req_wrap->msg_size = msg_size;
614
+ return req_wrap;
543
615
}
544
616
545
617
@@ -553,31 +625,46 @@ void UDPWrap::Send6(const FunctionCallbackInfo<Value>& args) {
553
625
}
554
626
555
627
556
- void UDPWrap::RecvStart (const FunctionCallbackInfo<Value>& args) {
557
- UDPWrap* wrap;
558
- ASSIGN_OR_RETURN_UNWRAP (&wrap,
559
- args.Holder (),
560
- args.GetReturnValue ().Set (UV_EBADF));
561
- int err = uv_udp_recv_start (&wrap->handle_ , OnAlloc, OnRecv);
628
+ AsyncWrap* UDPWrap::GetAsyncWrap () {
629
+ return this ;
630
+ }
631
+
632
+ int UDPWrap::GetPeerName (sockaddr* name, int * namelen) {
633
+ return uv_udp_getpeername (&handle_, name, namelen);
634
+ }
635
+
636
+ int UDPWrap::GetSockName (sockaddr* name, int * namelen) {
637
+ return uv_udp_getsockname (&handle_, name, namelen);
638
+ }
639
+
640
+ void UDPWrapBase::RecvStart (const FunctionCallbackInfo<Value>& args) {
641
+ UDPWrapBase* wrap = UDPWrapBase::FromObject (args.Holder ());
642
+ args.GetReturnValue ().Set (wrap == nullptr ? UV_EBADF : wrap->RecvStart ());
643
+ }
644
+
645
+ int UDPWrap::RecvStart () {
646
+ if (IsHandleClosing ()) return UV_EBADF;
647
+ int err = uv_udp_recv_start (&handle_, OnAlloc, OnRecv);
562
648
// UV_EALREADY means that the socket is already bound but that's okay
563
649
if (err == UV_EALREADY)
564
650
err = 0 ;
565
- args. GetReturnValue (). Set ( err) ;
651
+ return err;
566
652
}
567
653
568
654
569
- void UDPWrap::RecvStop (const FunctionCallbackInfo<Value>& args) {
570
- UDPWrap* wrap;
571
- ASSIGN_OR_RETURN_UNWRAP (&wrap,
572
- args.Holder (),
573
- args.GetReturnValue ().Set (UV_EBADF));
574
- int r = uv_udp_recv_stop (&wrap->handle_ );
575
- args.GetReturnValue ().Set (r);
655
+ void UDPWrapBase::RecvStop (const FunctionCallbackInfo<Value>& args) {
656
+ UDPWrapBase* wrap = UDPWrapBase::FromObject (args.Holder ());
657
+ args.GetReturnValue ().Set (wrap == nullptr ? UV_EBADF : wrap->RecvStop ());
658
+ }
659
+
660
+ int UDPWrap::RecvStop () {
661
+ if (IsHandleClosing ()) return UV_EBADF;
662
+ return uv_udp_recv_stop (&handle_);
576
663
}
577
664
578
665
579
- void UDPWrap::OnSend ( uv_udp_send_t * req, int status) {
580
- std::unique_ptr<SendWrap> req_wrap{static_cast <SendWrap*>(req-> data )};
666
+ void UDPWrap::OnSendDone (ReqWrap< uv_udp_send_t > * req, int status) {
667
+ std::unique_ptr<SendWrap> req_wrap{static_cast <SendWrap*>(req)};
581
668
if (req_wrap->have_callback ()) {
582
669
Environment* env = req_wrap->env ();
583
670
HandleScope handle_scope (env->isolate ());
@@ -594,43 +681,53 @@ void UDPWrap::OnSend(uv_udp_send_t* req, int status) {
594
681
void UDPWrap::OnAlloc (uv_handle_t * handle,
595
682
size_t suggested_size,
596
683
uv_buf_t * buf) {
597
- UDPWrap* wrap = static_cast <UDPWrap*>(handle->data );
598
- *buf = wrap->env ()->AllocateManaged (suggested_size).release ();
684
+ UDPWrap* wrap = ContainerOf (&UDPWrap::handle_,
685
+ reinterpret_cast <uv_udp_t *>(handle));
686
+ *buf = wrap->listener ()->OnAlloc (suggested_size);
687
+ }
688
+
689
+ uv_buf_t UDPWrap::OnAlloc (size_t suggested_size) {
690
+ return env ()->AllocateManaged (suggested_size).release ();
599
691
}
600
692
601
693
void UDPWrap::OnRecv (uv_udp_t * handle,
602
694
ssize_t nread,
603
- const uv_buf_t * buf_ ,
604
- const struct sockaddr * addr,
695
+ const uv_buf_t * buf ,
696
+ const sockaddr* addr,
605
697
unsigned int flags) {
606
- UDPWrap* wrap = static_cast <UDPWrap*>(handle->data );
607
- Environment* env = wrap->env ();
698
+ UDPWrap* wrap = ContainerOf (&UDPWrap::handle_, handle);
699
+ wrap->listener ()->OnRecv (nread, *buf, addr, flags);
700
+ }
608
701
609
- AllocatedBuffer buf (env, *buf_);
702
+ void UDPWrap::OnRecv (ssize_t nread,
703
+ const uv_buf_t & buf_,
704
+ const sockaddr* addr,
705
+ unsigned int flags) {
706
+ Environment* env = this ->env ();
707
+ AllocatedBuffer buf (env, buf_);
610
708
if (nread == 0 && addr == nullptr ) {
611
709
return ;
612
710
}
613
711
614
712
HandleScope handle_scope (env->isolate ());
615
713
Context::Scope context_scope (env->context ());
616
714
617
- Local<Object> wrap_obj = wrap->object ();
618
715
Local<Value> argv[] = {
619
716
Integer::New (env->isolate (), nread),
620
- wrap_obj ,
717
+ object () ,
621
718
Undefined (env->isolate ()),
622
719
Undefined (env->isolate ())
623
720
};
624
721
625
722
if (nread < 0 ) {
626
- wrap-> MakeCallback (env->onmessage_string (), arraysize (argv), argv);
723
+ MakeCallback (env->onmessage_string (), arraysize (argv), argv);
627
724
return ;
628
725
}
629
726
630
727
buf.Resize (nread);
631
728
argv[2 ] = buf.ToBuffer ().ToLocalChecked ();
632
729
argv[3 ] = AddressToJS (env, addr);
633
- wrap-> MakeCallback (env->onmessage_string (), arraysize (argv), argv);
730
+ MakeCallback (env->onmessage_string (), arraysize (argv), argv);
634
731
}
635
732
636
733
MaybeLocal<Object> UDPWrap::Instantiate (Environment* env,
0 commit comments