diff options
author | James M Snell <jasnell@gmail.com> | 2017-12-29 09:44:08 -0800 |
---|---|---|
committer | James M Snell <jasnell@gmail.com> | 2018-01-03 08:45:58 -0800 |
commit | ce22d6f9178507c7a41b04ac4097b9ea902049e3 (patch) | |
tree | 4b82a06cff1bb3fde32e4f101cd254111d8f9bf4 /src | |
parent | f51067a85d64b77f2eae2e099092209156d6e602 (diff) | |
download | android-node-v8-ce22d6f9178507c7a41b04ac4097b9ea902049e3.tar.gz android-node-v8-ce22d6f9178507c7a41b04ac4097b9ea902049e3.tar.bz2 android-node-v8-ce22d6f9178507c7a41b04ac4097b9ea902049e3.zip |
http2: add altsvc support
Add support for sending and receiving ALTSVC frames.
PR-URL: https://github.com/nodejs/node/pull/17917
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/env.h | 1 | ||||
-rw-r--r-- | src/node_http2.cc | 76 | ||||
-rw-r--r-- | src/node_http2.h | 7 |
3 files changed, 84 insertions, 0 deletions
@@ -179,6 +179,7 @@ class ModuleWrap; V(netmask_string, "netmask") \ V(nsname_string, "nsname") \ V(ocsp_request_string, "OCSPRequest") \ + V(onaltsvc_string, "onaltsvc") \ V(onchange_string, "onchange") \ V(onclienthello_string, "onclienthello") \ V(oncomplete_string, "oncomplete") \ diff --git a/src/node_http2.cc b/src/node_http2.cc index e409cdb579..17265a28cd 100644 --- a/src/node_http2.cc +++ b/src/node_http2.cc @@ -103,6 +103,11 @@ Http2Options::Http2Options(Environment* env) { // are required to buffer. nghttp2_option_set_no_auto_window_update(options_, 1); + // Enable built in support for ALTSVC frames. Once we add support for + // other non-built in extension frames, this will need to be handled + // a bit differently. For now, let's let nghttp2 take care of it. + nghttp2_option_set_builtin_recv_extension_type(options_, NGHTTP2_ALTSVC); + AliasedBuffer<uint32_t, v8::Uint32Array>& buffer = env->http2_state()->options_buffer; uint32_t flags = buffer[IDX_OPTIONS_FLAGS]; @@ -847,6 +852,10 @@ inline int Http2Session::OnFrameReceive(nghttp2_session* handle, break; case NGHTTP2_PING: session->HandlePingFrame(frame); + break; + case NGHTTP2_ALTSVC: + session->HandleAltSvcFrame(frame); + break; default: break; } @@ -1185,6 +1194,34 @@ inline void Http2Session::HandleGoawayFrame(const nghttp2_frame* frame) { MakeCallback(env()->ongoawaydata_string(), arraysize(argv), argv); } +// Called by OnFrameReceived when a complete ALTSVC frame has been received. +inline void Http2Session::HandleAltSvcFrame(const nghttp2_frame* frame) { + Isolate* isolate = env()->isolate(); + HandleScope scope(isolate); + Local<Context> context = env()->context(); + Context::Scope context_scope(context); + + int32_t id = GetFrameID(frame); + + nghttp2_extension ext = frame->ext; + nghttp2_ext_altsvc* altsvc = static_cast<nghttp2_ext_altsvc*>(ext.payload); + DEBUG_HTTP2SESSION(this, "handling altsvc frame"); + + Local<Value> argv[3] = { + Integer::New(isolate, id), + String::NewFromOneByte(isolate, + altsvc->origin, + v8::NewStringType::kNormal, + altsvc->origin_len).ToLocalChecked(), + String::NewFromOneByte(isolate, + altsvc->field_value, + v8::NewStringType::kNormal, + altsvc->field_value_len).ToLocalChecked(), + }; + + MakeCallback(env()->onaltsvc_string(), arraysize(argv), argv); +} + // Called by OnFrameReceived when a complete PING frame has been received. inline void Http2Session::HandlePingFrame(const nghttp2_frame* frame) { bool ack = frame->hd.flags & NGHTTP2_FLAG_ACK; @@ -2494,6 +2531,44 @@ void Http2Stream::RefreshState(const FunctionCallbackInfo<Value>& args) { } } +void Http2Session::AltSvc(int32_t id, + uint8_t* origin, + size_t origin_len, + uint8_t* value, + size_t value_len) { + Http2Scope h2scope(this); + CHECK_EQ(nghttp2_submit_altsvc(session_, NGHTTP2_FLAG_NONE, id, + origin, origin_len, value, value_len), 0); +} + +// Submits an AltSvc frame to the sent to the connected peer. +void Http2Session::AltSvc(const FunctionCallbackInfo<Value>& args) { + Environment* env = Environment::GetCurrent(args); + Http2Session* session; + ASSIGN_OR_RETURN_UNWRAP(&session, args.Holder()); + + int32_t id = args[0]->Int32Value(env->context()).ToChecked(); + + // origin and value are both required to be ASCII, handle them as such. + Local<String> origin_str = args[1]->ToString(env->context()).ToLocalChecked(); + Local<String> value_str = args[2]->ToString(env->context()).ToLocalChecked(); + + size_t origin_len = origin_str->Length(); + size_t value_len = value_str->Length(); + + CHECK_LE(origin_len + value_len, 16382); // Max permitted for ALTSVC + // Verify that origin len != 0 if stream id == 0, or + // that origin len == 0 if stream id != 0 + CHECK((origin_len != 0 && id == 0) || (origin_len == 0 && id != 0)); + + MaybeStackBuffer<uint8_t> origin(origin_len); + MaybeStackBuffer<uint8_t> value(value_len); + origin_str->WriteOneByte(*origin); + value_str->WriteOneByte(*value); + + session->AltSvc(id, *origin, origin_len, *value, value_len); +} + // Submits a PING frame to be sent to the connected peer. void Http2Session::Ping(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); @@ -2711,6 +2786,7 @@ void Initialize(Local<Object> target, session->SetClassName(http2SessionClassName); session->InstanceTemplate()->SetInternalFieldCount(1); AsyncWrap::AddWrapMethods(env, session); + env->SetProtoMethod(session, "altsvc", Http2Session::AltSvc); env->SetProtoMethod(session, "ping", Http2Session::Ping); env->SetProtoMethod(session, "consume", Http2Session::Consume); env->SetProtoMethod(session, "destroy", Http2Session::Destroy); diff --git a/src/node_http2.h b/src/node_http2.h index 1065ee8055..2b8542d951 100644 --- a/src/node_http2.h +++ b/src/node_http2.h @@ -800,6 +800,11 @@ class Http2Session : public AsyncWrap { void Consume(Local<External> external); void Unconsume(); void Goaway(uint32_t code, int32_t lastStreamID, uint8_t* data, size_t len); + void AltSvc(int32_t id, + uint8_t* origin, + size_t origin_len, + uint8_t* value, + size_t value_len); bool Ping(v8::Local<v8::Function> function); @@ -879,6 +884,7 @@ class Http2Session : public AsyncWrap { static void UpdateChunksSent(const FunctionCallbackInfo<Value>& args); static void RefreshState(const FunctionCallbackInfo<Value>& args); static void Ping(const FunctionCallbackInfo<Value>& args); + static void AltSvc(const FunctionCallbackInfo<Value>& args); template <get_setting fn> static void RefreshSettings(const FunctionCallbackInfo<Value>& args); @@ -923,6 +929,7 @@ class Http2Session : public AsyncWrap { inline void HandlePriorityFrame(const nghttp2_frame* frame); inline void HandleSettingsFrame(const nghttp2_frame* frame); inline void HandlePingFrame(const nghttp2_frame* frame); + inline void HandleAltSvcFrame(const nghttp2_frame* frame); // nghttp2 callbacks static inline int OnBeginHeadersCallback( |