commit f9a0f497d8537fecc71613fb590119b2c8dccf07
parent e17a630b17bbd6c78fca30618a6958647749f190
Author: Evgeny Grin (Karlson2k) <k2k@drgrin.dev>
Date: Mon, 17 Aug 2026 16:08:17 +0200
HTTP/2: implemented file-based replies with unknown size
Diffstat:
1 file changed, 38 insertions(+), 16 deletions(-)
diff --git a/src/mhd2/h2/h2_reply_funcs.c b/src/mhd2/h2/h2_reply_funcs.c
@@ -403,13 +403,14 @@ content_read_iovec (struct MHD_Response *restrict r,
static MHD_FN_PAR_NONNULL_ALL_
MHD_FN_PAR_OUT_SIZE_ (4, 3)
-MHD_FN_PAR_OUT_ (5) bool
+MHD_FN_PAR_OUT_ (5) enum mhd_FileReadResult
content_read_file (struct MHD_Response *restrict r,
uint_fast64_t offset,
size_t buff_size,
uint8_t *restrict buff,
size_t *restrict written)
{
+ enum mhd_FileReadResult res;
uint_fast64_t file_off;
mhd_assert (mhd_RESPONSE_CONTENT_DATA_FILE == r->cntn_dtype);
@@ -418,14 +419,18 @@ content_read_file (struct MHD_Response *restrict r,
file_off = offset + r->cntn.file.offset;
if (file_off < offset)
- return false; /* Offset too large */
-
- return (mhd_FILE_READ_OK ==
- mhd_read_file (r->cntn.file.fd,
- file_off,
- buff_size,
- (char *)buff,
- written));
+ return mhd_FILE_READ_OFFSET_TOO_LARGE; /* Offset too large */
+
+ res = mhd_read_file (r->cntn.file.fd,
+ file_off,
+ buff_size,
+ (char *)buff,
+ written);
+ if ((mhd_FILE_READ_EOF == res)
+ && (r->cntn_size != MHD_SIZE_UNKNOWN))
+ res = mhd_FILE_READ_ERROR; /* Unexpected EOF */
+
+ return res;
}
@@ -522,12 +527,27 @@ stream_content_send (struct mhd_H2Stream *s)
payload_used = 0u;
break;
case mhd_RESPONSE_CONTENT_DATA_FILE:
- if (!content_read_file (r,
- s->rpl.cntn_read_pos,
- (size_t)payload_size_limit,
- pld_buff,
- &payload_used))
+ switch (content_read_file (r,
+ s->rpl.cntn_read_pos,
+ (size_t)payload_size_limit,
+ pld_buff,
+ &payload_used))
+ {
+ case mhd_FILE_READ_OK:
+ break;
+ case mhd_FILE_READ_ERROR:
+ case mhd_FILE_READ_OFFSET_TOO_LARGE:
+ payload_used = 0u; // TODO: handle it better
+ break;
+ case mhd_FILE_READ_EOF:
payload_used = 0u;
+ dat->end_stream = true;
+ break;
+ default:
+ mhd_UNREACHABLE ();
+ payload_used = 0u;
+ break;
+ }
break;
case mhd_RESPONSE_CONTENT_DATA_CALLBACK:
s->rpl.stage = mhd_H2_RPL_STAGE_BROKEN;
@@ -539,9 +559,11 @@ stream_content_send (struct mhd_H2Stream *s)
break;
}
- dat->end_stream = (payload_used + s->rpl.cntn_read_pos == r->cntn_size);
+ dat->end_stream = dat->end_stream
+ || (payload_used + s->rpl.cntn_read_pos == r->cntn_size);
- if (0u != payload_used)
+ if ((0u != payload_used)
+ || (dat->end_stream))
{
const size_t full_fr_size = mhd_h2_frame_set_payload_size (&h2frame,
payload_used);