| #include "http2/adapter/nghttp2_data_provider.h" | |
| #include "http2/adapter/http2_visitor_interface.h" | |
| #include "http2/adapter/nghttp2_util.h" | |
| namespace http2 { | |
| namespace adapter { | |
| namespace callbacks { | |
| namespace { | |
| const size_t kFrameHeaderSize = 9; | |
| } | |
| ssize_t DataFrameSourceReadCallback(nghttp2_session* /* session */, | |
| int32_t /* stream_id */, | |
| uint8_t* /* buf */, | |
| size_t length, | |
| uint32_t* data_flags, | |
| nghttp2_data_source* source, | |
| void* /* user_data */) { | |
| *data_flags |= NGHTTP2_DATA_FLAG_NO_COPY; | |
| auto* frame_source = static_cast<DataFrameSource*>(source->ptr); | |
| auto [result_length, done] = frame_source->SelectPayloadLength(length); | |
| if (result_length == 0 && !done) { | |
| return NGHTTP2_ERR_DEFERRED; | |
| } else if (result_length == DataFrameSource::kError) { | |
| return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; | |
| } | |
| if (done) { | |
| *data_flags |= NGHTTP2_DATA_FLAG_EOF; | |
| } | |
| if (!frame_source->send_fin()) { | |
| *data_flags |= NGHTTP2_DATA_FLAG_NO_END_STREAM; | |
| } | |
| return result_length; | |
| } | |
| int DataFrameSourceSendCallback(nghttp2_session* /* session */, | |
| nghttp2_frame* /* frame */, | |
| const uint8_t* framehd, | |
| size_t length, | |
| nghttp2_data_source* source, | |
| void* /* user_data */) { | |
| auto* frame_source = static_cast<DataFrameSource*>(source->ptr); | |
| frame_source->Send(ToStringView(framehd, kFrameHeaderSize), length); | |
| return 0; | |
| } | |
| } // namespace callbacks | |
| std::unique_ptr<nghttp2_data_provider> MakeDataProvider( | |
| DataFrameSource* source) { | |
| if (source == nullptr) { | |
| return nullptr; | |
| } | |
| auto provider = absl::make_unique<nghttp2_data_provider>(); | |
| provider->source.ptr = source; | |
| provider->read_callback = &callbacks::DataFrameSourceReadCallback; | |
| return provider; | |
| } | |
| } // namespace adapter | |
| } // namespace http2 |