@@ -834,12 +834,12 @@ unsafe extern "C" fn on_frame_recv_callback(
834834 // destroy the session with NghttpError(NGHTTP2_ERR_PROTO).
835835 if session. pending_pings > 0 {
836836 session. pending_pings -= 1 ;
837- handle_ping_frame ( session) ;
837+ handle_ping_frame ( session, frame , true ) ;
838838 } else {
839839 handle_unsolicited_ping_ack ( session) ;
840840 }
841841 } else {
842- handle_ping_frame ( session) ;
842+ handle_ping_frame ( session, frame , false ) ;
843843 }
844844 } else if ft == ffi:: NGHTTP2_ALTSVC as u32 {
845845 handle_alt_svc_frame ( session, frame) ;
@@ -997,22 +997,43 @@ fn handle_settings_frame(session: &Session) {
997997 callback. call ( scope, recv. into ( ) , & [ ] ) ;
998998}
999999
1000- fn handle_ping_frame ( session : & Session ) {
1000+ fn handle_ping_frame (
1001+ session : & Session ,
1002+ frame : * const ffi:: nghttp2_frame ,
1003+ is_ack : bool ,
1004+ ) {
10011005 let mut isolate =
10021006 // SAFETY: isolate pointer is valid for the session's lifetime
10031007 unsafe { v8:: Isolate :: from_raw_isolate_ptr ( session. isolate ) } ;
10041008 v8:: scope!( let scope, & mut isolate) ;
10051009 let context = v8:: Local :: new ( scope, session. context . clone ( ) ) ;
10061010 let scope = & mut v8:: ContextScope :: new ( scope, context) ;
10071011
1012+ // SAFETY: frame is a valid PING frame per nghttp2 callback contract
1013+ let opaque = unsafe { ( * frame) . ping . opaque_data } ;
1014+ let array_buffer = v8:: ArrayBuffer :: new ( scope, opaque. len ( ) ) ;
1015+ let backing_store = array_buffer. get_backing_store ( ) ;
1016+ if let Some ( backing_data) = backing_store. data ( ) {
1017+ // SAFETY: src and dst are valid, non-overlapping, dst has room for 8 bytes
1018+ unsafe {
1019+ std:: ptr:: copy_nonoverlapping (
1020+ opaque. as_ptr ( ) ,
1021+ backing_data. as_ptr ( ) as * mut u8 ,
1022+ opaque. len ( ) ,
1023+ ) ;
1024+ }
1025+ }
1026+ let payload =
1027+ v8:: Uint8Array :: new ( scope, array_buffer, 0 , opaque. len ( ) ) . unwrap ( ) ;
1028+
10081029 let state = session. op_state . borrow ( ) ;
10091030 let callbacks = state. borrow :: < SessionCallbacks > ( ) ;
10101031 let recv = v8:: Local :: new ( scope, & session. this ) ;
10111032 let callback = v8:: Local :: new ( scope, & callbacks. ping_frame_cb ) ;
10121033 drop ( state) ;
10131034
1014- let arg = v8:: null ( scope) ;
1015- callback. call ( scope, recv. into ( ) , & [ arg . into ( ) ] ) ;
1035+ let is_ack_v = v8:: Boolean :: new ( scope, is_ack ) ;
1036+ callback. call ( scope, recv. into ( ) , & [ payload . into ( ) , is_ack_v . into ( ) ] ) ;
10161037}
10171038
10181039/// Inbound PING ACK with no matching outstanding PING. Mirrors Node's
0 commit comments