asio: read_cb: Use similar semantics with nghttp2_data_source_read_callback
This commit is contained in:
parent
44642af227
commit
7fb7575f78
|
@ -61,11 +61,15 @@ void request_impl::call_on_close(uint32_t error_code) {
|
|||
|
||||
void request_impl::on_read(read_cb cb) { read_cb_ = std::move(cb); }
|
||||
|
||||
read_cb::result_type request_impl::call_on_read(uint8_t *buf, std::size_t len) {
|
||||
read_cb::result_type request_impl::call_on_read(uint8_t *buf, std::size_t len,
|
||||
uint32_t *data_flags) {
|
||||
if (read_cb_) {
|
||||
return read_cb_(buf, len);
|
||||
return read_cb_(buf, len, data_flags);
|
||||
}
|
||||
return read_cb::result_type{};
|
||||
|
||||
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void request_impl::header(header_map h) { header_ = std::move(h); }
|
||||
|
|
|
@ -55,7 +55,8 @@ public:
|
|||
void call_on_close(uint32_t error_code);
|
||||
|
||||
void on_read(read_cb cb);
|
||||
read_cb::result_type call_on_read(uint8_t *buf, std::size_t len);
|
||||
read_cb::result_type call_on_read(uint8_t *buf, std::size_t len,
|
||||
uint32_t *data_flags);
|
||||
|
||||
void header(header_map h);
|
||||
header_map &header();
|
||||
|
|
|
@ -409,18 +409,7 @@ const request *session_impl::submit(boost::system::error_code &ec,
|
|||
size_t length, uint32_t *data_flags, nghttp2_data_source *source,
|
||||
void *user_data) -> ssize_t {
|
||||
auto strm = static_cast<stream *>(source->ptr);
|
||||
auto rv = strm->request().impl().call_on_read(buf, length);
|
||||
if (rv.first < 0) {
|
||||
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
|
||||
}
|
||||
|
||||
if (rv.second) {
|
||||
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
|
||||
} else if (rv.first == 0) {
|
||||
return NGHTTP2_ERR_DEFERRED;
|
||||
}
|
||||
|
||||
return rv.first;
|
||||
return strm->request().impl().call_on_read(buf, length, data_flags);
|
||||
};
|
||||
prdptr = &prd;
|
||||
}
|
||||
|
|
|
@ -49,11 +49,16 @@ boost::system::error_code make_error_code(nghttp2_error ev) {
|
|||
read_cb string_reader(std::string data) {
|
||||
auto strio = std::make_shared<std::pair<std::string, size_t>>(std::move(data),
|
||||
data.size());
|
||||
return [strio](uint8_t *buf, size_t len) {
|
||||
auto n = std::min(len, strio->second);
|
||||
std::copy_n(strio->first.c_str(), n, buf);
|
||||
strio->second -= n;
|
||||
return std::make_pair(n, strio->second == 0);
|
||||
return [strio](uint8_t *buf, size_t len, uint32_t *data_flags) {
|
||||
auto &data = strio->first;
|
||||
auto &left = strio->second;
|
||||
auto n = std::min(len, left);
|
||||
std::copy_n(data.c_str() + data.size() - left, n, buf);
|
||||
left -= n;
|
||||
if (left == 0) {
|
||||
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
|
||||
}
|
||||
return n;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -177,13 +177,15 @@ const header_map &response_impl::header() const { return header_; }
|
|||
|
||||
void response_impl::stream(http2_stream *s) { stream_ = s; }
|
||||
|
||||
std::pair<ssize_t, bool> response_impl::call_read(uint8_t *data,
|
||||
std::size_t len) {
|
||||
read_cb::result_type response_impl::call_read(uint8_t *data, std::size_t len,
|
||||
uint32_t *data_flags) {
|
||||
if (read_cb_) {
|
||||
return read_cb_(data, len);
|
||||
return read_cb_(data, len, data_flags);
|
||||
}
|
||||
|
||||
return std::make_pair(0, true);
|
||||
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
http2_stream::http2_stream(http2_handler *h, int32_t stream_id)
|
||||
|
@ -481,18 +483,7 @@ int http2_handler::start_response(http2_stream &stream) {
|
|||
size_t length, uint32_t *data_flags, nghttp2_data_source *source,
|
||||
void *user_data) -> ssize_t {
|
||||
auto &stream = *static_cast<http2_stream *>(source->ptr);
|
||||
auto rv = stream.response().impl().call_read(buf, length);
|
||||
if (rv.first < 0) {
|
||||
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
|
||||
}
|
||||
|
||||
if (rv.second) {
|
||||
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
|
||||
} else if (rv.first == 0) {
|
||||
return NGHTTP2_ERR_DEFERRED;
|
||||
}
|
||||
|
||||
return rv.first;
|
||||
return stream.response().impl().call_read(buf, length, data_flags);
|
||||
};
|
||||
|
||||
rv = nghttp2_submit_response(session_, stream.get_stream_id(), nva.data(),
|
||||
|
|
|
@ -91,7 +91,8 @@ public:
|
|||
const header_map &header() const;
|
||||
bool started() const;
|
||||
void stream(http2_stream *s);
|
||||
read_cb::result_type call_read(uint8_t *data, std::size_t len);
|
||||
read_cb::result_type call_read(uint8_t *data, std::size_t len,
|
||||
uint32_t *data_flags);
|
||||
|
||||
private:
|
||||
http2_stream *stream_;
|
||||
|
|
|
@ -139,20 +139,21 @@ read_cb file_reader(const std::string &path) {
|
|||
read_cb file_reader_from_fd(int fd) {
|
||||
auto d = defer_shared(close, fd);
|
||||
|
||||
return [fd, d](uint8_t *buf, size_t len) -> read_cb::result_type {
|
||||
int rv;
|
||||
while ((rv = read(fd, buf, len)) == -1 && errno == EINTR)
|
||||
return [fd, d](uint8_t *buf, size_t len, uint32_t *data_flags)
|
||||
-> read_cb::result_type {
|
||||
ssize_t n;
|
||||
while ((n = read(fd, buf, len)) == -1 && errno == EINTR)
|
||||
;
|
||||
|
||||
if (rv == -1) {
|
||||
return std::make_pair(-1, false);
|
||||
if (n == -1) {
|
||||
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
|
||||
}
|
||||
|
||||
if (rv == 0) {
|
||||
return std::make_pair(rv, true);
|
||||
if (n == 0) {
|
||||
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
|
||||
}
|
||||
|
||||
return std::make_pair(rv, false);
|
||||
return n;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -76,18 +76,9 @@ typedef std::function<void(void)> void_cb;
|
|||
typedef std::function<void(const boost::system::error_code &ec)> error_cb;
|
||||
typedef std::function<void(uint32_t)> close_cb;
|
||||
|
||||
// Callback function to generate response body. The implementation of
|
||||
// this callback must fill at most |len| bytes data to |buf|. The
|
||||
// return value is pair of written bytes and bool value indicating
|
||||
// that this is the end of the body. If the end of the body was
|
||||
// reached, return true. If there is error and application wants to
|
||||
// terminate stream, return std::make_pair(-1, false). Returning
|
||||
// std::make_pair(0, false) tells the library that don't call this
|
||||
// callback until application calls response::resume(). This is
|
||||
// useful when there is no data to send at the moment but there will
|
||||
// be more to come in near future.
|
||||
typedef std::function<std::pair<ssize_t, bool>(uint8_t *buf, std::size_t len)>
|
||||
read_cb;
|
||||
// Callback function to generate response body. TBD
|
||||
typedef std::function<
|
||||
ssize_t(uint8_t *buf, std::size_t len, uint32_t *data_flags)> read_cb;
|
||||
|
||||
// Convenient function to create function to read file denoted by
|
||||
// |path|. This can be passed to response::end().
|
||||
|
|
Loading…
Reference in New Issue