summaryrefslogtreecommitdiff
path: root/src/node_http2.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/node_http2.cc')
-rw-r--r--src/node_http2.cc76
1 files changed, 76 insertions, 0 deletions
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);