diff options
author | Anna Henningsen <anna@addaleax.net> | 2018-02-13 01:32:27 +0100 |
---|---|---|
committer | Anna Henningsen <anna@addaleax.net> | 2018-03-15 12:53:22 +0100 |
commit | 1eb6b01fca598194f59f8f4cac499825e6769363 (patch) | |
tree | af72a46b8c74f044ee03301073c8d12c7d8053d7 /src/node_http2.cc | |
parent | 67f1d76956a8a5da9875b113371c8786ad579086 (diff) | |
download | android-node-v8-1eb6b01fca598194f59f8f4cac499825e6769363.tar.gz android-node-v8-1eb6b01fca598194f59f8f4cac499825e6769363.tar.bz2 android-node-v8-1eb6b01fca598194f59f8f4cac499825e6769363.zip |
http2: use native pipe instead of synchronous I/O
This resolves the issue of using synchronous I/O for
`respondWithFile()` and `respondWithFD()`, and enables
scenarios in which the underlying file does not need
to be a regular file.
PR-URL: https://github.com/nodejs/node/pull/18936
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Diffstat (limited to 'src/node_http2.cc')
-rw-r--r-- | src/node_http2.cc | 125 |
1 files changed, 0 insertions, 125 deletions
diff --git a/src/node_http2.cc b/src/node_http2.cc index d6df93cf38..68a684025c 100644 --- a/src/node_http2.cc +++ b/src/node_http2.cc @@ -1888,28 +1888,6 @@ inline int Http2Stream::SubmitResponse(nghttp2_nv* nva, } -// Initiate a response that contains data read from a file descriptor. -inline int Http2Stream::SubmitFile(int fd, - nghttp2_nv* nva, size_t len, - int64_t offset, - int64_t length, - int options) { - CHECK(!this->IsDestroyed()); - Http2Scope h2scope(this); - DEBUG_HTTP2STREAM(this, "submitting file"); - if (options & STREAM_OPTION_GET_TRAILERS) - flags_ |= NGHTTP2_STREAM_FLAG_TRAILERS; - - if (offset > 0) fd_offset_ = offset; - if (length > -1) fd_length_ = length; - - Http2Stream::Provider::FD prov(this, options, fd); - int ret = nghttp2_submit_response(session_->session(), id_, nva, len, *prov); - CHECK_NE(ret, NGHTTP2_ERR_NOMEM); - return ret; -} - - // Submit informational headers for a stream. inline int Http2Stream::SubmitInfo(nghttp2_nv* nva, size_t len) { CHECK(!this->IsDestroyed()); @@ -2085,87 +2063,6 @@ Http2Stream::Provider::~Provider() { provider_.source.ptr = nullptr; } -// The FD Provider pulls data from a file descriptor using libuv. All of the -// data transfer occurs in C++, without any chunks being passed through JS -// land. -Http2Stream::Provider::FD::FD(Http2Stream* stream, int options, int fd) - : Http2Stream::Provider(stream, options) { - CHECK(!stream->IsDestroyed()); - provider_.source.fd = fd; - provider_.read_callback = Http2Stream::Provider::FD::OnRead; -} - -Http2Stream::Provider::FD::FD(int options, int fd) - : Http2Stream::Provider(options) { - provider_.source.fd = fd; - provider_.read_callback = Http2Stream::Provider::FD::OnRead; -} - -ssize_t Http2Stream::Provider::FD::OnRead(nghttp2_session* handle, - int32_t id, - uint8_t* buf, - size_t length, - uint32_t* flags, - nghttp2_data_source* source, - void* user_data) { - Http2Session* session = static_cast<Http2Session*>(user_data); - Http2Stream* stream = session->FindStream(id); - if (stream->statistics_.first_byte_sent == 0) - stream->statistics_.first_byte_sent = uv_hrtime(); - - DEBUG_HTTP2SESSION2(session, "reading outbound file data for stream %d", id); - CHECK_EQ(id, stream->id()); - - int fd = source->fd; - int64_t offset = stream->fd_offset_; - ssize_t numchars = 0; - - if (stream->fd_length_ >= 0 && - stream->fd_length_ < static_cast<int64_t>(length)) - length = stream->fd_length_; - - uv_buf_t data; - data.base = reinterpret_cast<char*>(buf); - data.len = length; - - uv_fs_t read_req; - - if (length > 0) { - // TODO(addaleax): Never use synchronous I/O on the main thread. - numchars = uv_fs_read(session->event_loop(), - &read_req, - fd, &data, 1, - offset, nullptr); - uv_fs_req_cleanup(&read_req); - } - - // Close the stream with an error if reading fails - if (numchars < 0) - return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; - - // Update the read offset for the next read - stream->fd_offset_ += numchars; - stream->fd_length_ -= numchars; - - DEBUG_HTTP2SESSION2(session, "sending %d bytes", numchars); - - // if numchars < length, assume that we are done. - if (static_cast<size_t>(numchars) < length || length <= 0) { - DEBUG_HTTP2SESSION2(session, "no more data for stream %d", id); - *flags |= NGHTTP2_DATA_FLAG_EOF; - session->GetTrailers(stream, flags); - // If the stream or session gets destroyed during the GetTrailers - // callback, check that here and close down the stream - if (stream->IsDestroyed()) - return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; - if (session->IsDestroyed()) - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - - stream->statistics_.sent_bytes += numchars; - return numchars; -} - // The Stream Provider pulls data from a linked list of uv_buf_t structs // built via the StreamBase API and the Streams js API. Http2Stream::Provider::Stream::Stream(int options) @@ -2508,27 +2405,6 @@ void Http2Stream::Respond(const FunctionCallbackInfo<Value>& args) { DEBUG_HTTP2STREAM(stream, "response submitted"); } -// Initiates a response on the Http2Stream using a file descriptor to provide -// outbound DATA frames. -void Http2Stream::RespondFD(const FunctionCallbackInfo<Value>& args) { - Environment* env = Environment::GetCurrent(args); - Local<Context> context = env->context(); - Isolate* isolate = env->isolate(); - Http2Stream* stream; - ASSIGN_OR_RETURN_UNWRAP(&stream, args.Holder()); - - int fd = args[0]->Int32Value(context).ToChecked(); - Local<Array> headers = args[1].As<Array>(); - - int64_t offset = args[2]->IntegerValue(context).ToChecked(); - int64_t length = args[3]->IntegerValue(context).ToChecked(); - int options = args[4]->IntegerValue(context).ToChecked(); - - Headers list(isolate, context, headers); - args.GetReturnValue().Set(stream->SubmitFile(fd, *list, list.length(), - offset, length, options)); - DEBUG_HTTP2STREAM2(stream, "file response submitted for fd %d", fd); -} // Submits informational headers on the Http2Stream void Http2Stream::Info(const FunctionCallbackInfo<Value>& args) { @@ -2891,7 +2767,6 @@ void Initialize(Local<Object> target, env->SetProtoMethod(stream, "priority", Http2Stream::Priority); env->SetProtoMethod(stream, "pushPromise", Http2Stream::PushPromise); env->SetProtoMethod(stream, "info", Http2Stream::Info); - env->SetProtoMethod(stream, "respondFD", Http2Stream::RespondFD); env->SetProtoMethod(stream, "respond", Http2Stream::Respond); env->SetProtoMethod(stream, "rstStream", Http2Stream::RstStream); env->SetProtoMethod(stream, "refreshState", Http2Stream::RefreshState); |