added mio_foff_t.
adding sendfile support to the core
This commit is contained in:
parent
7adf19f01d
commit
e439c29cb8
@ -59,10 +59,10 @@ struct file_state_t
|
|||||||
mio_oow_t num_pending_writes_to_peer;
|
mio_oow_t num_pending_writes_to_peer;
|
||||||
|
|
||||||
int peer;
|
int peer;
|
||||||
mio_uintmax_t total_size;
|
mio_foff_t total_size;
|
||||||
mio_uintmax_t start_offset;
|
mio_foff_t start_offset;
|
||||||
mio_uintmax_t end_offset;
|
mio_foff_t end_offset;
|
||||||
mio_uintmax_t cur_offset;
|
mio_foff_t cur_offset;
|
||||||
mio_bch_t peer_buf[8192];
|
mio_bch_t peer_buf[8192];
|
||||||
mio_tmridx_t peer_tmridx;
|
mio_tmridx_t peer_tmridx;
|
||||||
|
|
||||||
@ -433,7 +433,7 @@ 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_svc_htts_cli_t* cli = file_state->client;
|
||||||
mio_bch_t dtbuf[64];
|
mio_bch_t dtbuf[64];
|
||||||
mio_uintmax_t content_length;
|
mio_foff_t content_length;
|
||||||
|
|
||||||
mio_svc_htts_fmtgmtime (cli->htts, MIO_NULL, dtbuf, MIO_COUNTOF(dtbuf));
|
mio_svc_htts_fmtgmtime (cli->htts, MIO_NULL, dtbuf, MIO_COUNTOF(dtbuf));
|
||||||
|
|
||||||
@ -449,8 +449,8 @@ static int file_state_send_header_to_client (file_state_t* file_state, int statu
|
|||||||
(force_close? "close": "keep-alive"),
|
(force_close? "close": "keep-alive"),
|
||||||
content_length) == (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 (status_code == 206 && mio_becs_fcat(cli->sbuf, "Content-Ranges: bytes %ju-%ju/%ju\r\n", (mio_uintmax_t)file_state->start_offset, (mio_uintmax_t)file_state->end_offset, (mio_uintmax_t)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;
|
if (mio_becs_fcat(cli->sbuf, "Content-Length: %ju\r\n\r\n", (mio_uintmax_t)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));
|
return file_state_write_to_client(file_state, MIO_BECS_PTR(cli->sbuf), MIO_BECS_LEN(cli->sbuf));
|
||||||
}
|
}
|
||||||
@ -472,7 +472,7 @@ static int file_state_send_contents_to_client (file_state_t* file_state)
|
|||||||
* mio_dev_sck_write(sck, data_required_for_sendfile_operation, 0, MIO_NULL);....
|
* mio_dev_sck_write(sck, data_required_for_sendfile_operation, 0, MIO_NULL);....
|
||||||
*/
|
*/
|
||||||
mio_t* mio = file_state->htts->mio;
|
mio_t* mio = file_state->htts->mio;
|
||||||
mio_uintmax_t lim;
|
mio_foff_t lim;
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
|
|
||||||
if (file_state->cur_offset > file_state->end_offset)
|
if (file_state->cur_offset > file_state->end_offset)
|
||||||
|
@ -214,7 +214,7 @@ int mio_parse_http_range_bcstr (const mio_bch_t* str, mio_http_range_t* range)
|
|||||||
/* NOTE: this function does not support a range set
|
/* NOTE: this function does not support a range set
|
||||||
* like bytes=1-20,30-50 */
|
* like bytes=1-20,30-50 */
|
||||||
|
|
||||||
mio_http_range_int_t from, to;
|
mio_foff_t from, to;
|
||||||
int type = MIO_HTTP_RANGE_PROPER;
|
int type = MIO_HTTP_RANGE_PROPER;
|
||||||
|
|
||||||
if (str[0] != 'b' ||
|
if (str[0] != 'b' ||
|
||||||
|
@ -942,4 +942,33 @@ struct mio_cmgr_t
|
|||||||
|
|
||||||
#define MIO_STATIC_ASSERT_EXPR(expr) ((void)MIO_SIZEOF(char[(expr)? 1: -1]))
|
#define MIO_STATIC_ASSERT_EXPR(expr) ((void)MIO_SIZEOF(char[(expr)? 1: -1]))
|
||||||
|
|
||||||
|
|
||||||
|
/* =========================================================================
|
||||||
|
* FILE OFFSET TYPE
|
||||||
|
* =========================================================================*/
|
||||||
|
/**
|
||||||
|
* The #mio_foff_t type defines an integer that can represent a file offset.
|
||||||
|
* Depending on your system, it's defined to one of #mio_int64_t, #mio_int32_t,
|
||||||
|
* and #mio_int16_t.
|
||||||
|
*/
|
||||||
|
#if defined(MIO_HAVE_INT64_T) && (MIO_SIZEOF_OFF64_T==8)
|
||||||
|
typedef mio_int64_t mio_foff_t;
|
||||||
|
# define MIO_SIZEOF_FOFF_T MIO_SIZEOF_INT64_T
|
||||||
|
#elif defined(MIO_HAVE_INT64_T) && (MIO_SIZEOF_OFF_T==8)
|
||||||
|
typedef mio_int64_t mio_foff_t;
|
||||||
|
# define MIO_SIZEOF_FOFF_T MIO_SIZEOF_INT64_T
|
||||||
|
#elif defined(MIO_HAVE_INT32_T) && (MIO_SIZEOF_OFF_T==4)
|
||||||
|
typedef mio_int32_t mio_foff_t;
|
||||||
|
# define MIO_SIZEOF_FOFF_T MIO_SIZEOF_INT32_T
|
||||||
|
#elif defined(MIO_HAVE_INT16_T) && (MIO_SIZEOF_OFF_T==2)
|
||||||
|
typedef mio_int16_t mio_foff_t;
|
||||||
|
# define MIO_SIZEOF_FOFF_T MIO_SIZEOF_INT16_T
|
||||||
|
#elif defined(MIO_HAVE_INT8_T) && (MIO_SIZEOF_OFF_T==1)
|
||||||
|
typedef mio_int8_t mio_foff_t;
|
||||||
|
# define MIO_SIZEOF_FOFF_T MIO_SIZEOF_INT16_T
|
||||||
|
#else
|
||||||
|
typedef mio_int32_t mio_foff_t; /* this line is for doxygen */
|
||||||
|
# error Unsupported platform
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -34,17 +34,6 @@
|
|||||||
* This file provides basic data types and functions for the http protocol.
|
* This file provides basic data types and functions for the http protocol.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* The #mio_http_range_int_t type defines an integer that can represent
|
|
||||||
* a range offset. Depening on the size of #mio_foff_t, it is defined to
|
|
||||||
* either #mio_foff_t or #mio_ulong_t.
|
|
||||||
*/
|
|
||||||
#if defined(MIO_SIZEOF_FOFF_T) && defined(MIO_SIZEOF_UINTMAX_T) && (MIO_SIZEOF_FOFF_T > MIO_SIZEOF_UINTMAX_T)
|
|
||||||
typedef mio_foff_t mio_http_range_int_t;
|
|
||||||
#else
|
|
||||||
typedef mio_uintmax_t mio_http_range_int_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum mio_http_range_type_t
|
enum mio_http_range_type_t
|
||||||
{
|
{
|
||||||
MIO_HTTP_RANGE_PROPER,
|
MIO_HTTP_RANGE_PROPER,
|
||||||
@ -73,8 +62,8 @@ typedef enum mio_http_range_type_t mio_http_range_type_t;
|
|||||||
struct mio_http_range_t
|
struct mio_http_range_t
|
||||||
{
|
{
|
||||||
mio_http_range_type_t type; /**< type indicator */
|
mio_http_range_type_t type; /**< type indicator */
|
||||||
mio_http_range_int_t from; /**< starting offset */
|
mio_foff_t from; /**< starting offset */
|
||||||
mio_http_range_int_t to; /**< ending offset */
|
mio_foff_t to; /**< ending offset */
|
||||||
};
|
};
|
||||||
typedef struct mio_http_range_t mio_http_range_t;
|
typedef struct mio_http_range_t mio_http_range_t;
|
||||||
|
|
||||||
|
@ -1549,30 +1549,98 @@ enqueue_completed_write:
|
|||||||
return __enqueue_completed_write(dev, len, wrctx, dstaddr);
|
return __enqueue_completed_write(dev, len, wrctx, dstaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __dev_sendfile (mio_dev_t* dev, mio_syshnd_t in_fd, mio_uintmax_t offset, mio_iolen_t len, const mio_ntime_t* tmout, void* wrctx, const mio_devaddr_t* dstaddr)
|
static int __dev_sendfile (mio_dev_t* dev, mio_syshnd_t in_fd, mio_foff_t foff, mio_iolen_t len, const mio_ntime_t* tmout, void* wrctx)
|
||||||
{
|
{
|
||||||
|
#if 1
|
||||||
mio_t* mio = dev->mio;
|
mio_t* mio = dev->mio;
|
||||||
|
mio_foff_t uoff;
|
||||||
|
mio_iolen_t urem, ulen;
|
||||||
|
int x;
|
||||||
|
|
||||||
if (dev->dev_cap & MIO_DEV_CAP_OUT_CLOSED)
|
if (dev->dev_cap & MIO_DEV_CAP_OUT_CLOSED)
|
||||||
{
|
{
|
||||||
mio_seterrbfmt (mio, MIO_ENOCAPA, "unable to write to closed device");
|
mio_seterrbfmt (mio, MIO_ENOCAPA, "unable to sendfile to closed device");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uoff = foff;
|
||||||
|
urem = len;
|
||||||
|
|
||||||
if (!MIO_WQ_IS_EMPTY(&dev->wq))
|
if (!MIO_WQ_IS_EMPTY(&dev->wq))
|
||||||
{
|
{
|
||||||
/* if the writing queue is not empty, enqueue this request immediately */
|
/* the writing queue is not empty.
|
||||||
|
* enqueue this request immediately */
|
||||||
goto enqueue_data;
|
goto enqueue_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
if (dev->dev_cap & MIO_DEV_CAP_STREAM)
|
||||||
|
{
|
||||||
|
/* use the do..while() loop to be able to send a zero-length data */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ulen = urem;
|
||||||
|
x = dev->dev_mth->sendfile(dev, in_fd, foff, &ulen);
|
||||||
|
if (x <= -1) return -1;
|
||||||
|
else if (x == 0)
|
||||||
|
{
|
||||||
|
/* [NOTE]
|
||||||
|
* the write queue is empty at this moment. a zero-length
|
||||||
|
* request for a stream device can still get enqueued if the
|
||||||
|
* write callback returns 0 though i can't figure out if there
|
||||||
|
* is a compelling reason to do so
|
||||||
|
*/
|
||||||
|
goto enqueue_data; /* enqueue remaining data */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* the write callback should return at most the number of requested
|
||||||
|
* bytes. but returning more is harmless as urem is of a signed type.
|
||||||
|
* for a zero-length request, it's necessary to return at least 1
|
||||||
|
* to indicate successful acknowlegement. otherwise, it gets enqueued
|
||||||
|
* as shown in the 'if' block right above. */
|
||||||
|
urem -= ulen;
|
||||||
|
uoff += ulen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (urem > 0);
|
||||||
|
|
||||||
|
if (len <= 0) /* original length */
|
||||||
|
{
|
||||||
|
/* a zero-length writing request is to close the writing end. this causes further write request to fail */
|
||||||
|
dev->dev_cap |= MIO_DEV_CAP_OUT_CLOSED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if i trigger the write completion callback here, the performance
|
||||||
|
* may increase, but there can be annoying recursion issues if the
|
||||||
|
* callback requests another writing operation. it's imperative to
|
||||||
|
* delay the callback until this write function is finished.
|
||||||
|
* ---> if (dev->dev_evcb->on_write(dev, len, wrctx, dstaddr) <= -1) return -1; */
|
||||||
|
goto enqueue_completed_write;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mio_seterrbfmt (mio, MIO_ENOCAPA, "unable to sendfile over a non-stream device");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1; /* written immediately and called on_write callback. but this line will never be reached */
|
||||||
|
|
||||||
enqueue_data:
|
enqueue_data:
|
||||||
/*return __enqueue_pending_write(dev, len, urem, iov, iovcnt, index, tmout, wrctx, dstaddr);*/
|
#if 0
|
||||||
|
iov.iov_ptr = (void*)uptr;
|
||||||
|
iov.iov_len = urem;
|
||||||
|
return __enqueue_pending_write(dev, len, urem, &iov, 1, 0, tmout, wrctx, dstaddr);
|
||||||
|
#else
|
||||||
|
/* TODO: */
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
enqueue_completed_write:
|
enqueue_completed_write:
|
||||||
/*return __enqueue_completed_write(dev, len, wrctx, dstaddr);*/
|
return __enqueue_completed_write(dev, len, wrctx, dstaddr);
|
||||||
|
#else
|
||||||
return 0;
|
return 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int mio_dev_write (mio_dev_t* dev, const void* data, mio_iolen_t len, void* wrctx, const mio_devaddr_t* dstaddr)
|
int mio_dev_write (mio_dev_t* dev, const void* data, mio_iolen_t len, void* wrctx, const mio_devaddr_t* dstaddr)
|
||||||
|
@ -195,6 +195,7 @@ struct mio_dev_mth_t
|
|||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
int (*write) (mio_dev_t* dev, const void* data, mio_iolen_t* len, const mio_devaddr_t* dstaddr);
|
int (*write) (mio_dev_t* dev, const void* data, mio_iolen_t* len, const mio_devaddr_t* dstaddr);
|
||||||
int (*writev) (mio_dev_t* dev, const mio_iovec_t* iov, mio_iolen_t* iovcnt, const mio_devaddr_t* dstaddr);
|
int (*writev) (mio_dev_t* dev, const mio_iovec_t* iov, mio_iolen_t* iovcnt, const mio_devaddr_t* dstaddr);
|
||||||
|
int (*sendfile) (mio_dev_t* dev, mio_syshnd_t in_fd, mio_foff_t foff, mio_iolen_t* len);
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
int (*ioctl) (mio_dev_t* dev, int cmd, void* arg);
|
int (*ioctl) (mio_dev_t* dev, int cmd, void* arg);
|
||||||
|
Loading…
Reference in New Issue
Block a user