@@ -237,6 +237,7 @@ Http2Session::Http2Settings::Http2Settings(Environment* env,
237
237
: AsyncWrap(env, obj, PROVIDER_HTTP2SETTINGS),
238
238
session_ (session),
239
239
startTime_(start_time) {
240
+ RemoveCleanupHook (); // This object is owned by the Http2Session.
240
241
Init ();
241
242
}
242
243
@@ -311,12 +312,11 @@ void Http2Session::Http2Settings::Done(bool ack) {
311
312
uint64_t end = uv_hrtime ();
312
313
double duration = (end - startTime_) / 1e6 ;
313
314
314
- Local<Value> argv[2 ] = {
315
+ Local<Value> argv[] = {
315
316
Boolean::New (env ()->isolate (), ack),
316
317
Number::New (env ()->isolate (), duration)
317
318
};
318
319
MakeCallback (env ()->ondone_string (), arraysize (argv), argv);
319
- delete this ;
320
320
}
321
321
322
322
// The Http2Priority class initializes an appropriate nghttp2_priority_spec
@@ -746,11 +746,14 @@ void Http2Session::Close(uint32_t code, bool socket_closed) {
746
746
// If there are outstanding pings, those will need to be canceled, do
747
747
// so on the next iteration of the event loop to avoid calling out into
748
748
// javascript since this may be called during garbage collection.
749
- while (!outstanding_pings_.empty ()) {
750
- Http2Session::Http2Ping* ping = PopPing ();
751
- env ()->SetImmediate ([](Environment* env, void * data) {
752
- static_cast <Http2Session::Http2Ping*>(data)->Done (false );
753
- }, static_cast <void *>(ping));
749
+ while (std::unique_ptr<Http2Ping> ping = PopPing ()) {
750
+ ping->DetachFromSession ();
751
+ env ()->SetImmediate (
752
+ [](Environment* env, void * data) {
753
+ std::unique_ptr<Http2Ping> ping{static_cast <Http2Ping*>(data)};
754
+ ping->Done (false );
755
+ },
756
+ static_cast <void *>(ping.release ()));
754
757
}
755
758
756
759
statistics_.end_time = uv_hrtime ();
@@ -1435,9 +1438,9 @@ void Http2Session::HandlePingFrame(const nghttp2_frame* frame) {
1435
1438
Local<Value> arg;
1436
1439
bool ack = frame->hd .flags & NGHTTP2_FLAG_ACK;
1437
1440
if (ack) {
1438
- Http2Ping* ping = PopPing ();
1441
+ std::unique_ptr< Http2Ping> ping = PopPing ();
1439
1442
1440
- if (ping == nullptr ) {
1443
+ if (! ping) {
1441
1444
// PING Ack is unsolicited. Treat as a connection error. The HTTP/2
1442
1445
// spec does not require this, but there is no legitimate reason to
1443
1446
// receive an unsolicited PING ack on a connection. Either the peer
@@ -1470,8 +1473,8 @@ void Http2Session::HandleSettingsFrame(const nghttp2_frame* frame) {
1470
1473
1471
1474
// If this is an acknowledgement, we should have an Http2Settings
1472
1475
// object for it.
1473
- Http2Settings* settings = PopSettings ();
1474
- if (settings != nullptr ) {
1476
+ std::unique_ptr< Http2Settings> settings = PopSettings ();
1477
+ if (settings) {
1475
1478
settings->Done (true );
1476
1479
return ;
1477
1480
}
@@ -2775,15 +2778,12 @@ void Http2Session::Ping(const FunctionCallbackInfo<Value>& args) {
2775
2778
}
2776
2779
if (obj->Set (env->context (), env->ondone_string (), args[1 ]).IsNothing ())
2777
2780
return ;
2778
- Http2Session::Http2Ping* ping = new Http2Ping (session, obj);
2779
2781
2782
+ Http2Ping* ping = session->AddPing (std::make_unique<Http2Ping>(session, obj));
2780
2783
// To prevent abuse, we strictly limit the number of unacknowledged PING
2781
2784
// frames that may be sent at any given time. This is configurable in the
2782
2785
// Options when creating a Http2Session.
2783
- if (!session->AddPing (ping)) {
2784
- ping->Done (false );
2785
- return args.GetReturnValue ().Set (false );
2786
- }
2786
+ if (ping == nullptr ) return args.GetReturnValue ().Set (false );
2787
2787
2788
2788
// The Ping itself is an Async resource. When the acknowledgement is received,
2789
2789
// the callback will be invoked and a notification sent out to JS land. The
@@ -2808,60 +2808,67 @@ void Http2Session::Settings(const FunctionCallbackInfo<Value>& args) {
2808
2808
if (obj->Set (env->context (), env->ondone_string (), args[0 ]).IsNothing ())
2809
2809
return ;
2810
2810
2811
- Http2Session::Http2Settings* settings =
2812
- new Http2Settings (session->env (), session, obj, 0 );
2813
- if (!session->AddSettings (settings)) {
2814
- settings->Done (false );
2815
- return args.GetReturnValue ().Set (false );
2816
- }
2811
+ Http2Session::Http2Settings* settings = session->AddSettings (
2812
+ std::make_unique<Http2Settings>(session->env (), session, obj, 0 ));
2813
+ if (settings == nullptr ) return args.GetReturnValue ().Set (false );
2817
2814
2818
2815
settings->Send ();
2819
2816
args.GetReturnValue ().Set (true );
2820
2817
}
2821
2818
2822
-
2823
- Http2Session::Http2Ping* Http2Session::PopPing () {
2824
- Http2Ping* ping = nullptr ;
2819
+ std::unique_ptr<Http2Session::Http2Ping> Http2Session::PopPing () {
2820
+ std::unique_ptr<Http2Ping> ping;
2825
2821
if (!outstanding_pings_.empty ()) {
2826
- ping = outstanding_pings_.front ();
2822
+ ping = std::move ( outstanding_pings_.front () );
2827
2823
outstanding_pings_.pop ();
2828
2824
DecrementCurrentSessionMemory (sizeof (*ping));
2829
2825
}
2830
2826
return ping;
2831
2827
}
2832
2828
2833
- bool Http2Session::AddPing (Http2Session::Http2Ping* ping) {
2834
- if (outstanding_pings_.size () == max_outstanding_pings_)
2835
- return false ;
2836
- outstanding_pings_.push (ping);
2829
+ Http2Session::Http2Ping* Http2Session::AddPing (
2830
+ std::unique_ptr<Http2Session::Http2Ping> ping) {
2831
+ if (outstanding_pings_.size () == max_outstanding_pings_) {
2832
+ ping->Done (false );
2833
+ return nullptr ;
2834
+ }
2835
+ Http2Ping* ptr = ping.get ();
2836
+ outstanding_pings_.emplace (std::move (ping));
2837
2837
IncrementCurrentSessionMemory (sizeof (*ping));
2838
- return true ;
2838
+ return ptr ;
2839
2839
}
2840
2840
2841
- Http2Session::Http2Settings* Http2Session::PopSettings () {
2842
- Http2Settings* settings = nullptr ;
2841
+ std::unique_ptr< Http2Session::Http2Settings> Http2Session::PopSettings () {
2842
+ std::unique_ptr< Http2Settings> settings;
2843
2843
if (!outstanding_settings_.empty ()) {
2844
- settings = outstanding_settings_.front ();
2844
+ settings = std::move ( outstanding_settings_.front () );
2845
2845
outstanding_settings_.pop ();
2846
2846
DecrementCurrentSessionMemory (sizeof (*settings));
2847
2847
}
2848
2848
return settings;
2849
2849
}
2850
2850
2851
- bool Http2Session::AddSettings (Http2Session::Http2Settings* settings) {
2852
- if (outstanding_settings_.size () == max_outstanding_settings_)
2853
- return false ;
2854
- outstanding_settings_.push (settings);
2851
+ Http2Session::Http2Settings* Http2Session::AddSettings (
2852
+ std::unique_ptr<Http2Session::Http2Settings> settings) {
2853
+ if (outstanding_settings_.size () == max_outstanding_settings_) {
2854
+ settings->Done (false );
2855
+ return nullptr ;
2856
+ }
2857
+ Http2Settings* ptr = settings.get ();
2858
+ outstanding_settings_.emplace (std::move (settings));
2855
2859
IncrementCurrentSessionMemory (sizeof (*settings));
2856
- return true ;
2860
+ return ptr ;
2857
2861
}
2858
2862
2859
2863
Http2Session::Http2Ping::Http2Ping (Http2Session* session, Local<Object> obj)
2860
2864
: AsyncWrap(session->env (), obj, AsyncWrap::PROVIDER_HTTP2PING),
2861
2865
session_(session),
2862
- startTime_(uv_hrtime()) {}
2866
+ startTime_(uv_hrtime()) {
2867
+ RemoveCleanupHook (); // This object is owned by the Http2Session.
2868
+ }
2863
2869
2864
2870
void Http2Session::Http2Ping::Send (const uint8_t * payload) {
2871
+ CHECK_NOT_NULL (session_);
2865
2872
uint8_t data[8 ];
2866
2873
if (payload == nullptr ) {
2867
2874
memcpy (&data, &startTime_, arraysize (data));
@@ -2872,8 +2879,12 @@ void Http2Session::Http2Ping::Send(const uint8_t* payload) {
2872
2879
}
2873
2880
2874
2881
void Http2Session::Http2Ping::Done (bool ack, const uint8_t * payload) {
2875
- session_->statistics_ .ping_rtt = uv_hrtime () - startTime_;
2876
- double duration = session_->statistics_ .ping_rtt / 1e6 ;
2882
+ uint64_t duration_ns = uv_hrtime () - startTime_;
2883
+ double duration_ms = duration_ns / 1e6 ;
2884
+ if (session_ != nullptr ) session_->statistics_ .ping_rtt = duration_ns;
2885
+
2886
+ HandleScope handle_scope (env ()->isolate ());
2887
+ Context::Scope context_scope (env ()->context ());
2877
2888
2878
2889
Local<Value> buf = Undefined (env ()->isolate ());
2879
2890
if (payload != nullptr ) {
@@ -2882,15 +2893,17 @@ void Http2Session::Http2Ping::Done(bool ack, const uint8_t* payload) {
2882
2893
8 ).ToLocalChecked ();
2883
2894
}
2884
2895
2885
- Local<Value> argv[3 ] = {
2896
+ Local<Value> argv[] = {
2886
2897
Boolean::New (env ()->isolate (), ack),
2887
- Number::New (env ()->isolate (), duration ),
2898
+ Number::New (env ()->isolate (), duration_ms ),
2888
2899
buf
2889
2900
};
2890
2901
MakeCallback (env ()->ondone_string (), arraysize (argv), argv);
2891
- delete this ;
2892
2902
}
2893
2903
2904
+ void Http2Session::Http2Ping::DetachFromSession () {
2905
+ session_ = nullptr ;
2906
+ }
2894
2907
2895
2908
void nghttp2_stream_write::MemoryInfo (MemoryTracker* tracker) const {
2896
2909
if (req_wrap != nullptr )
0 commit comments