wrote some code in http-fil.c
This commit is contained in:
parent
953dbd730b
commit
59fc7d23a0
@ -1088,7 +1088,7 @@ static int fmt_outv (mio_fmtout_t* fmtout, va_list ap)
|
||||
sign = 0;
|
||||
if (lm_flag & LF_J)
|
||||
{
|
||||
#if defined(__GNUC__) && \
|
||||
#if 0 && defined(__GNUC__) && \
|
||||
(MIO_SIZEOF_UINTMAX_T > MIO_SIZEOF_OOW_T) && \
|
||||
(MIO_SIZEOF_UINTMAX_T != MIO_SIZEOF_LONG_LONG) && \
|
||||
(MIO_SIZEOF_UINTMAX_T != MIO_SIZEOF_LONG)
|
||||
@ -1132,7 +1132,7 @@ static int fmt_outv (mio_fmtout_t* fmtout, va_list ap)
|
||||
handle_sign:
|
||||
if (lm_flag & LF_J)
|
||||
{
|
||||
#if defined(__GNUC__) && \
|
||||
#if 0 && defined(__GNUC__) && \
|
||||
(MIO_SIZEOF_INTMAX_T > MIO_SIZEOF_OOI_T) && \
|
||||
(MIO_SIZEOF_UINTMAX_T != MIO_SIZEOF_LONG_LONG) && \
|
||||
(MIO_SIZEOF_UINTMAX_T != MIO_SIZEOF_LONG)
|
||||
|
@ -38,7 +38,6 @@
|
||||
|
||||
enum file_state_res_mode_t
|
||||
{
|
||||
FILE_STATE_RES_MODE_CHUNKED,
|
||||
FILE_STATE_RES_MODE_CLOSE,
|
||||
FILE_STATE_RES_MODE_LENGTH
|
||||
};
|
||||
@ -58,8 +57,12 @@ struct file_state_t
|
||||
|
||||
mio_oow_t num_pending_writes_to_client;
|
||||
mio_oow_t num_pending_writes_to_peer;
|
||||
|
||||
int peer;
|
||||
mio_uintmax_t part_size;
|
||||
mio_uintmax_t total_size;
|
||||
mio_uintmax_t start_offset;
|
||||
mio_uintmax_t end_offset;
|
||||
mio_uintmax_t cur_offset;
|
||||
|
||||
mio_svc_htts_cli_t* client;
|
||||
mio_http_version_t req_version; /* client request */
|
||||
@ -81,6 +84,8 @@ struct file_state_t
|
||||
};
|
||||
typedef struct file_state_t file_state_t;
|
||||
|
||||
static int file_state_send_contents_to_client (file_state_t* file_state);
|
||||
|
||||
|
||||
static void file_state_halt_participating_devices (file_state_t* file_state)
|
||||
{
|
||||
@ -161,11 +166,6 @@ static int file_state_write_last_chunk_to_client (file_state_t* file_state)
|
||||
{
|
||||
if (file_state_send_final_status_to_client(file_state, 500, 0) <= -1) return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (file_state->res_mode_to_cli == FILE_STATE_RES_MODE_CHUNKED &&
|
||||
file_state_write_to_client(file_state, "0\r\n\r\n", 5) <= -1) return -1;
|
||||
}
|
||||
|
||||
if (!file_state->keep_alive && file_state_write_to_client(file_state, MIO_NULL, 0) <= -1) return -1;
|
||||
return 0;
|
||||
@ -385,7 +385,6 @@ static int file_client_on_write (mio_dev_sck_t* sck, mio_iolen_t wrlen, void* wr
|
||||
{
|
||||
/* if the connect is keep-alive, this part may not be called */
|
||||
file_state->num_pending_writes_to_client--;
|
||||
printf ("QQQQQQQQQQQQQ %lu\n", (long)file_state->num_pending_writes_to_client);
|
||||
MIO_ASSERT (mio, file_state->num_pending_writes_to_client == 0);
|
||||
MIO_DEBUG3 (mio, "HTTS(%p) - indicated EOF to client %p(%d)\n", file_state->client->htts, sck, (int)sck->hnd);
|
||||
/* since EOF has been indicated to the client, it must not write to the client any further.
|
||||
@ -407,6 +406,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
mio_dev_pro_read(file_state->peer, MIO_DEV_PRO_OUT, 1) <= -1) goto oops;
|
||||
}
|
||||
#endif
|
||||
file_state_send_contents_to_client (file_state);
|
||||
|
||||
if ((file_state->over & FILE_STATE_OVER_READ_FROM_PEER) && file_state->num_pending_writes_to_client <= 0)
|
||||
{
|
||||
@ -461,17 +461,24 @@ static int file_state_send_header_to_client (file_state_t* file_state, int statu
|
||||
{
|
||||
mio_svc_htts_cli_t* cli = file_state->client;
|
||||
mio_bch_t dtbuf[64];
|
||||
mio_uintmax_t content_length;
|
||||
|
||||
mio_svc_htts_fmtgmtime (cli->htts, MIO_NULL, dtbuf, MIO_COUNTOF(dtbuf));
|
||||
|
||||
if (!force_close) force_close = !file_state->keep_alive;
|
||||
|
||||
if (mio_becs_fmt(cli->sbuf, "HTTP/%d.%d %d %hs\r\nServer: %hs\r\nDate: %s\r\nConnection: %hs\r\nContent-Length: %ju\r\n\r\n",
|
||||
content_length = file_state->end_offset - file_state->start_offset + 1;
|
||||
if (status_code == 200 && file_state->total_size != content_length) status_code = 206;
|
||||
|
||||
if (mio_becs_fmt(cli->sbuf, "HTTP/%d.%d %d %hs\r\nServer: %hs\r\nDate: %s\r\nConnection: %hs\r\nAccept-Ranges: bytes\r\n",
|
||||
file_state->req_version.major, file_state->req_version.minor,
|
||||
status_code, mio_http_status_to_bcstr(status_code),
|
||||
cli->htts->server_name, dtbuf,
|
||||
(force_close? "close": "keep-alive"),
|
||||
file_state->part_size) == (mio_oow_t)-1) return -1;
|
||||
content_length) == (mio_oow_t)-1) return -1;
|
||||
|
||||
if (status_code == 206 && mio_becs_fcat(cli->sbuf, "Content-Ranges: bytes %ju-%ju/%ju\r\n", file_state->start_offset, file_state->end_offset, file_state->total_size) == (mio_oow_t)-1) return -1;
|
||||
if (mio_becs_fcat(cli->sbuf, "Content-Length: %ju\r\n\r\n", content_length) == (mio_oow_t)-1) return -1;
|
||||
|
||||
return file_state_write_to_client(file_state, MIO_BECS_PTR(cli->sbuf), MIO_BECS_LEN(cli->sbuf));
|
||||
}
|
||||
@ -485,34 +492,50 @@ static int file_state_send_contents_to_client (file_state_t* file_state)
|
||||
*/
|
||||
|
||||
mio_bch_t buf[8192]; /* TODO: declare this in file_state?? */
|
||||
int i;
|
||||
mio_uintmax_t lim;
|
||||
ssize_t n;
|
||||
|
||||
for (i = 0; i < FILE_STATE_PENDING_IO_THRESHOLD; i++)
|
||||
|
||||
if (file_state->cur_offset > file_state->end_offset)
|
||||
{
|
||||
n = read(file_state->peer, buf, MIO_SIZEOF(buf));
|
||||
/* reached the end */
|
||||
file_state_mark_over (file_state, FILE_STATE_OVER_READ_FROM_PEER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
lim = file_state->end_offset - file_state->cur_offset + 1;
|
||||
n = read(file_state->peer, buf, (lim < MIO_SIZEOF(buf)? lim: MIO_SIZEOF(buf)));
|
||||
if (n == -1)
|
||||
{
|
||||
if (errno == EAGAIN)
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
{
|
||||
/* TODO: arrange to invoke on data writable? */
|
||||
/*mio_dev_sck_watch (file_state->client->sck, MIO_DEV_WATCH_UPDATE, */
|
||||
return 0;
|
||||
}
|
||||
else if (errno == EINTR)
|
||||
{
|
||||
return 0; /* interrupted */
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
else if (n == 0)
|
||||
{
|
||||
/* no more data to read */
|
||||
file_state_mark_over (file_state, FILE_STATE_OVER_READ_FROM_CLIENT);
|
||||
break;
|
||||
/* no more data to read - this must not happend unless file size changed while the file is open. */
|
||||
/* TODO: I probably must close the connection by force??? */
|
||||
file_state_mark_over (file_state, FILE_STATE_OVER_READ_FROM_PEER);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (file_state_write_to_client(file_state, buf, n) <= -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
file_state->cur_offset += n;
|
||||
/* if (file_state->cur_offset > file_state->end_offset)
|
||||
file_state_mark_over (file_state, FILE_STATE_OVER_READ_FROM_PEER);*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -557,20 +580,69 @@ int mio_svc_htts_dofile (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t*
|
||||
|
||||
/* TODO: if method is for download... open it in the read mode. if PUT or POST, open it in RDWR mode? */
|
||||
file_state->peer = open(actual_file, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
|
||||
if (MIO_UNLIKELY(file_state->peer <= -1)) goto oops;
|
||||
|
||||
if (MIO_UNLIKELY(file_state->peer <= -1))
|
||||
{
|
||||
file_state_send_final_status_to_client (file_state, 500, 1);
|
||||
goto oops;
|
||||
}
|
||||
|
||||
{
|
||||
struct stat st;
|
||||
const mio_htre_hdrval_t* tmp;
|
||||
|
||||
if (fstat(file_state->peer, &st) <= -1) goto oops;
|
||||
file_state->part_size = st.st_size;
|
||||
file_state->part_size = MIO_TYPE_MAX(mio_intmax_t);
|
||||
file_state->end_offset = st.st_size;
|
||||
|
||||
tmp = mio_htre_getheaderval(req, "Range"); /* TODO: support multiple ranges? */
|
||||
if (tmp)
|
||||
{
|
||||
mio_http_range_t range;
|
||||
|
||||
|
||||
if (mio_parse_http_range_bcstr(tmp->ptr, &range) <= -1)
|
||||
{
|
||||
range_not_satisifiable:
|
||||
file_state_send_final_status_to_client (file_state, 416, 1); /* 406 Requested Range Not Satisfiable */
|
||||
goto oops;
|
||||
}
|
||||
|
||||
/*
|
||||
file_peer = mio_dev_pro_getxtn(file_state->peer);
|
||||
MIO_SVC_HTTS_RSRC_ATTACH (file_state, file_peer->state);
|
||||
*/
|
||||
switch (range.type)
|
||||
{
|
||||
case MIO_HTTP_RANGE_PROPER:
|
||||
/* Range XXXX-YYYY */
|
||||
if (range.to >= st.st_size) goto range_not_satisifiable;
|
||||
file_state->start_offset = range.from;
|
||||
file_state->end_offset = range.to;
|
||||
break;
|
||||
|
||||
case MIO_HTTP_RANGE_PREFIX:
|
||||
/* Range: XXXX- */
|
||||
if (range.from >= st.st_size) goto range_not_satisifiable;
|
||||
file_state->start_offset = range.from;
|
||||
file_state->end_offset = st.st_size - 1;
|
||||
break;
|
||||
|
||||
case MIO_HTTP_RANGE_SUFFIX:
|
||||
/* Range: -XXXX */
|
||||
if (range.to >= st.st_size) goto range_not_satisifiable;
|
||||
file_state->start_offset = st.st_size - range.to;
|
||||
file_state->end_offset = st.st_size - 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (file_state->start_offset > 0)
|
||||
lseek(file_state->peer, file_state->start_offset, SEEK_SET);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
file_state->start_offset = 0;
|
||||
file_state->end_offset = st.st_size - 1;
|
||||
}
|
||||
|
||||
file_state->cur_offset = file_state->start_offset;
|
||||
file_state->total_size = st.st_size;
|
||||
}
|
||||
|
||||
|
||||
#if !defined(FILE_ALLOW_UNLIMITED_REQ_CONTENT_LENGTH)
|
||||
@ -661,8 +733,7 @@ XXXXXXXXXXXX
|
||||
if (req->flags & MIO_HTRE_ATTR_KEEPALIVE)
|
||||
{
|
||||
file_state->keep_alive = 1;
|
||||
file_state->res_mode_to_cli = FILE_STATE_RES_MODE_CHUNKED;
|
||||
/* the mode still can get switched to FILE_STATE_RES_MODE_LENGTH if the file emits Content-Length */
|
||||
file_state->res_mode_to_cli = FILE_STATE_RES_MODE_LENGTH;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -225,7 +225,7 @@ int mio_parse_http_range_bcstr (const mio_bch_t* str, mio_http_range_t* range)
|
||||
|
||||
str += 6;
|
||||
|
||||
from = 0;
|
||||
from = to = 0;
|
||||
if (mio_is_bch_digit(*str))
|
||||
{
|
||||
do
|
||||
@ -249,10 +249,10 @@ int mio_parse_http_range_bcstr (const mio_bch_t* str, mio_http_range_t* range)
|
||||
str++;
|
||||
}
|
||||
while (mio_is_bch_digit(*str));
|
||||
}
|
||||
else to = MIO_TYPE_MAX(mio_http_range_int_t);
|
||||
|
||||
if (from > to) return -1;
|
||||
}
|
||||
else type = MIO_HTTP_RANGE_PREFIX;
|
||||
|
||||
range->type = type;
|
||||
range->from = from;
|
||||
|
@ -47,8 +47,8 @@ typedef mio_uintmax_t mio_http_range_int_t;
|
||||
|
||||
enum mio_http_range_type_t
|
||||
{
|
||||
MIO_HTTP_RANGE_NONE,
|
||||
MIO_HTTP_RANGE_PROPER,
|
||||
MIO_HTTP_RANGE_PREFIX,
|
||||
MIO_HTTP_RANGE_SUFFIX
|
||||
};
|
||||
typedef enum mio_http_range_type_t mio_http_range_type_t;
|
||||
@ -56,19 +56,14 @@ typedef enum mio_http_range_type_t mio_http_range_type_t;
|
||||
* The mio_http_range_t type defines a structure that can represent
|
||||
* a value for the \b Range: http header.
|
||||
*
|
||||
* If type is #MIO_HTTP_RANGE_NONE, this range is not valid.
|
||||
* If type is #MIO_HTTP_RANGE_PREFIX, 'to' is meaningless and 'from' indicates
|
||||
* the number of bytes from the start.
|
||||
* - 500- => from the 501st bytes all the way to the back.
|
||||
*
|
||||
* If type is #MIO_HTTP_RANGE_SUFFIX, 'from' is meaningleass and 'to' indicates
|
||||
* If type is #MIO_HTTP_RANGE_SUFFIX, 'from' is meaningless and 'to' indicates
|
||||
* the number of bytes from the back.
|
||||
* - -500 => last 500 bytes
|
||||
*
|
||||
* You should adjust a range when the size that this range belongs to is
|
||||
* made known. See this code:
|
||||
* \code
|
||||
* range.from = total_size - range.to;
|
||||
* range.to = range.to + range.from - 1;
|
||||
* \endcode
|
||||
*
|
||||
* If type is #MIO_HTTP_RANGE_PROPER, 'from' and 'to' represents a proper range
|
||||
* where the value of 0 indicates the first byte. This doesn't require any
|
||||
* adjustment.
|
||||
|
Loading…
x
Reference in New Issue
Block a user