touched up the file handler in http-file.c
This commit is contained in:
parent
e54867e42e
commit
e5d0946c5f
@ -242,7 +242,7 @@ void* thr_func (void* arg)
|
|||||||
hio_setoption (hio, HIO_LOG_TARGET_BCSTR, "/dev/stderr");
|
hio_setoption (hio, HIO_LOG_TARGET_BCSTR, "/dev/stderr");
|
||||||
|
|
||||||
memset (&htts_bind_info, 0, HIO_SIZEOF(htts_bind_info));
|
memset (&htts_bind_info, 0, HIO_SIZEOF(htts_bind_info));
|
||||||
hio_skad_init_for_qx (&htts_bind_info[0].localaddr);
|
hio_skad_init_for_qx (&htts_bind_info[0].localaddr); /* QX socket device */
|
||||||
|
|
||||||
hio_bcstrtoskad (hio, "0.0.0.0:9988", &htts_bind_info[1].localaddr);
|
hio_bcstrtoskad (hio, "0.0.0.0:9988", &htts_bind_info[1].localaddr);
|
||||||
htts_bind_info[1].options = HIO_DEV_SCK_BIND_REUSEADDR | HIO_DEV_SCK_BIND_REUSEPORT | HIO_DEV_SCK_BIND_IGNERR;
|
htts_bind_info[1].options = HIO_DEV_SCK_BIND_REUSEADDR | HIO_DEV_SCK_BIND_REUSEPORT | HIO_DEV_SCK_BIND_IGNERR;
|
||||||
|
239
lib/http-file.c
239
lib/http-file.c
@ -74,6 +74,7 @@ struct file_t
|
|||||||
typedef struct file_t file_t;
|
typedef struct file_t file_t;
|
||||||
|
|
||||||
static void unbind_task_from_client (file_t* file, int rcdown);
|
static void unbind_task_from_client (file_t* file, int rcdown);
|
||||||
|
static void unbind_task_from_peer (file_t* file, int rcdown);
|
||||||
static int file_send_contents_to_client (file_t* file);
|
static int file_send_contents_to_client (file_t* file);
|
||||||
|
|
||||||
static HIO_INLINE void set_tcp_cork (hio_dev_sck_t* sck, int tcp_cork)
|
static HIO_INLINE void set_tcp_cork (hio_dev_sck_t* sck, int tcp_cork)
|
||||||
@ -91,26 +92,8 @@ static void file_halt_participating_devices (file_t* file)
|
|||||||
{
|
{
|
||||||
HIO_DEBUG3 (file->htts->hio, "HTTS(%p) - file(c=%d,p=%d) Halting participating devices\n", file->htts, (int)file->task_csck->hnd, (int)file->peer);
|
HIO_DEBUG3 (file->htts->hio, "HTTS(%p) - file(c=%d,p=%d) Halting participating devices\n", file->htts, (int)file->task_csck->hnd, (int)file->peer);
|
||||||
|
|
||||||
/* only the client socket device.
|
|
||||||
* the peer side is just a file descriptor - no hio-managed device */
|
|
||||||
if (file->task_csck) hio_dev_sck_halt (file->task_csck);
|
if (file->task_csck) hio_dev_sck_halt (file->task_csck);
|
||||||
}
|
unbind_task_from_peer (file, 1);
|
||||||
|
|
||||||
static void file_close_peer (file_t* file)
|
|
||||||
{
|
|
||||||
hio_t* hio = file->htts->hio;
|
|
||||||
|
|
||||||
if (file->peer_tmridx != HIO_TMRIDX_INVALID)
|
|
||||||
{
|
|
||||||
hio_deltmrjob (hio, file->peer_tmridx);
|
|
||||||
HIO_ASSERT (hio, file->peer_tmridx == HIO_TMRIDX_INVALID);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file->peer >= 0)
|
|
||||||
{
|
|
||||||
close (file->peer);
|
|
||||||
file->peer = -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void file_mark_over (file_t* file, int over_bits)
|
static void file_mark_over (file_t* file, int over_bits)
|
||||||
@ -144,7 +127,7 @@ static void file_mark_over (file_t* file, int over_bits)
|
|||||||
{
|
{
|
||||||
/* ready to stop */
|
/* ready to stop */
|
||||||
HIO_DEBUG3 (hio, "HTTS(%p) - file(c=%d,p=%d) halting peer as it is unneeded\n", htts, (int)file->task_csck->hnd, file->peer);
|
HIO_DEBUG3 (hio, "HTTS(%p) - file(c=%d,p=%d) halting peer as it is unneeded\n", htts, (int)file->task_csck->hnd, file->peer);
|
||||||
file_close_peer (file);
|
unbind_task_from_peer (file, 1);
|
||||||
|
|
||||||
if (file->task_csck)
|
if (file->task_csck)
|
||||||
{
|
{
|
||||||
@ -206,7 +189,9 @@ static void file_on_kill (hio_svc_htts_task_t* task)
|
|||||||
|
|
||||||
if (file->on_kill) file->on_kill (task);
|
if (file->on_kill) file->on_kill (task);
|
||||||
|
|
||||||
file_close_peer (file);
|
/* this callback function doesn't decrement the reference count on file because
|
||||||
|
* it is the task destruction callback. (passing 0 to unbind_task_from_peer/client) */
|
||||||
|
unbind_task_from_peer (file, 0);
|
||||||
|
|
||||||
if (file->task_csck)
|
if (file->task_csck)
|
||||||
{
|
{
|
||||||
@ -238,6 +223,11 @@ static void file_client_on_disconnect (hio_dev_sck_t* sck)
|
|||||||
/* detach the task from the client and the client socket */
|
/* detach the task from the client and the client socket */
|
||||||
unbind_task_from_client (file, 1);
|
unbind_task_from_client (file, 1);
|
||||||
|
|
||||||
|
/* the current file peer implemenation is not async. so there is no IO event associated
|
||||||
|
* when the client side is disconnecte, simple close the peer side as it's not needed.
|
||||||
|
* this behavior is different from http-fcgi or http-cgi */
|
||||||
|
unbind_task_from_peer (file, 1);
|
||||||
|
|
||||||
/* call the parent handler*/
|
/* call the parent handler*/
|
||||||
/*if (file->client_org_on_disconnect) file->client_org_on_disconnect (sck);*/
|
/*if (file->client_org_on_disconnect) file->client_org_on_disconnect (sck);*/
|
||||||
if (sck->on_disconnect) sck->on_disconnect (sck); /* restored to the orginal parent handelr in unbind_task_from_client() */
|
if (sck->on_disconnect) sck->on_disconnect (sck); /* restored to the orginal parent handelr in unbind_task_from_client() */
|
||||||
@ -276,7 +266,6 @@ static int file_client_on_read (hio_dev_sck_t* sck, const void* buf, hio_iolen_t
|
|||||||
{
|
{
|
||||||
/* EOF on the client side. arrange to close */
|
/* EOF on the client side. arrange to close */
|
||||||
HIO_DEBUG3 (cli->htts->hio, "HTTS(%p) - file(c=%d,p=%d) EOF detected on client\n", file->htts, (int)sck->hnd, file->peer);
|
HIO_DEBUG3 (cli->htts->hio, "HTTS(%p) - file(c=%d,p=%d) EOF detected on client\n", file->htts, (int)sck->hnd, file->peer);
|
||||||
//file->client_eof_detected = 1;
|
|
||||||
|
|
||||||
if (!(file->over & FILE_OVER_READ_FROM_CLIENT)) /* if this is true, EOF is received without file_client_htrd_poke() */
|
if (!(file->over & FILE_OVER_READ_FROM_CLIENT)) /* if this is true, EOF is received without file_client_htrd_poke() */
|
||||||
{
|
{
|
||||||
@ -639,6 +628,8 @@ static int open_peer_with_mode (file_t* file, const hio_bch_t* actual_file, int
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------- */
|
||||||
|
|
||||||
static void bind_task_to_client (file_t* file, hio_dev_sck_t* csck)
|
static void bind_task_to_client (file_t* file, hio_dev_sck_t* csck)
|
||||||
{
|
{
|
||||||
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(csck);
|
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(csck);
|
||||||
@ -715,6 +706,127 @@ static void unbind_task_from_client (file_t* file, int rcdown)
|
|||||||
if (rcdown) HIO_SVC_HTTS_TASK_RCDOWN ((hio_svc_htts_task_t*)file);
|
if (rcdown) HIO_SVC_HTTS_TASK_RCDOWN ((hio_svc_htts_task_t*)file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static int bind_task_to_peer (file_t* file, hio_htre_t* req, const hio_bch_t* file_path, const hio_bch_t* mime_type)
|
||||||
|
{
|
||||||
|
int status_code;
|
||||||
|
|
||||||
|
switch (file->task_req_method)
|
||||||
|
{
|
||||||
|
case HIO_HTTP_GET:
|
||||||
|
case HIO_HTTP_HEAD:
|
||||||
|
{
|
||||||
|
const hio_bch_t* actual_mime_type = mime_type;
|
||||||
|
|
||||||
|
if (open_peer_with_mode(file, file_path, O_RDONLY, &status_code, (mime_type? HIO_NULL: &actual_mime_type)) <= -1 ||
|
||||||
|
process_range_header(file, req, &status_code) <= -1) goto done_with_status_code;
|
||||||
|
|
||||||
|
if (HIO_LIKELY(file->task_req_method == HIO_HTTP_GET))
|
||||||
|
{
|
||||||
|
if (file->etag_match)
|
||||||
|
{
|
||||||
|
status_code = HIO_HTTP_STATUS_NOT_MODIFIED;
|
||||||
|
goto done_with_status_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* normal full transfer */
|
||||||
|
#if defined(HAVE_POSIX_FADVISE)
|
||||||
|
posix_fadvise (file->peer, file->start_offset, file->end_offset - file->start_offset + 1, POSIX_FADV_SEQUENTIAL);
|
||||||
|
#endif
|
||||||
|
set_tcp_cork (file->task_csck, 1);
|
||||||
|
|
||||||
|
if (file_send_header_to_client(file, HIO_HTTP_STATUS_OK, 0, actual_mime_type) <= -1) goto oops;
|
||||||
|
if (file_send_contents_to_client(file) <= -1) goto oops;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (file_send_header_to_client(file, HIO_HTTP_STATUS_OK, 0, actual_mime_type) <= -1) goto oops;
|
||||||
|
/* no content must be transmitted for HEAD despite Content-Length in the header. */
|
||||||
|
goto done_with_status_code_2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case HIO_HTTP_POST:
|
||||||
|
case HIO_HTTP_PUT:
|
||||||
|
if (file->options & HIO_SVC_HTTS_FILE_READ_ONLY)
|
||||||
|
{
|
||||||
|
status_code = HIO_HTTP_STATUS_METHOD_NOT_ALLOWED;
|
||||||
|
goto done_with_status_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (open_peer_with_mode(file, file_path, O_WRONLY | O_TRUNC | O_CREAT, &status_code, HIO_NULL) <= -1) goto done_with_status_code;
|
||||||
|
|
||||||
|
/* the client input must be written to the peer side */
|
||||||
|
file_mark_over (file, FILE_OVER_READ_FROM_PEER);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HIO_HTTP_DELETE:
|
||||||
|
if (file->options & HIO_SVC_HTTS_FILE_READ_ONLY)
|
||||||
|
{
|
||||||
|
status_code = HIO_HTTP_STATUS_METHOD_NOT_ALLOWED;
|
||||||
|
goto done_with_status_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlink(file_path) <= -1)
|
||||||
|
{
|
||||||
|
if (errno != EISDIR || (errno == EISDIR && rmdir(file_path) <= -1))
|
||||||
|
{
|
||||||
|
status_code = ERRNO_TO_STATUS_CODE(errno);
|
||||||
|
goto done_with_status_code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
status_code = HIO_HTTP_STATUS_OK;
|
||||||
|
goto done_with_status_code;
|
||||||
|
|
||||||
|
default:
|
||||||
|
status_code = HIO_HTTP_STATUS_METHOD_NOT_ALLOWED;
|
||||||
|
done_with_status_code:
|
||||||
|
if (hio_svc_htts_task_sendfinalres(file, status_code, HIO_NULL, HIO_NULL, 0) <= -1) goto oops;
|
||||||
|
done_with_status_code_2:
|
||||||
|
file_mark_over (file, FILE_OVER_READ_FROM_PEER | FILE_OVER_WRITE_TO_PEER);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
HIO_SVC_HTTS_TASK_RCUP (file); /* for file->peer opened */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
oops:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void unbind_task_from_peer (file_t* file, int rcdown)
|
||||||
|
{
|
||||||
|
hio_svc_htts_t* htts = file->htts;
|
||||||
|
hio_t* hio = htts->hio;
|
||||||
|
int n = 0;
|
||||||
|
|
||||||
|
if (file->peer_tmridx != HIO_TMRIDX_INVALID)
|
||||||
|
{
|
||||||
|
hio_deltmrjob (hio, file->peer_tmridx);
|
||||||
|
HIO_ASSERT (hio, file->peer_tmridx == HIO_TMRIDX_INVALID);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file->peer >= 0)
|
||||||
|
{
|
||||||
|
close (file->peer);
|
||||||
|
file->peer = -1;
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rcdown)
|
||||||
|
{
|
||||||
|
while (n > 0)
|
||||||
|
{
|
||||||
|
n--;
|
||||||
|
HIO_SVC_HTTS_TASK_RCDOWN((hio_svc_htts_task_t*)file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------- */
|
||||||
|
|
||||||
static int setup_for_content_length(file_t* file, hio_htre_t* req)
|
static int setup_for_content_length(file_t* file, hio_htre_t* req)
|
||||||
{
|
{
|
||||||
@ -764,7 +876,6 @@ int hio_svc_htts_dofile (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_htre_t*
|
|||||||
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(csck);
|
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(csck);
|
||||||
file_t* file = HIO_NULL;
|
file_t* file = HIO_NULL;
|
||||||
hio_bch_t* actual_file = HIO_NULL;
|
hio_bch_t* actual_file = HIO_NULL;
|
||||||
int status_code;
|
|
||||||
|
|
||||||
/* ensure that you call this function before any contents is received */
|
/* ensure that you call this function before any contents is received */
|
||||||
HIO_ASSERT (hio, hio_htre_getcontentlen(req) == 0);
|
HIO_ASSERT (hio, hio_htre_getcontentlen(req) == 0);
|
||||||
@ -782,91 +893,15 @@ int hio_svc_htts_dofile (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_htre_t*
|
|||||||
file->options = options;
|
file->options = options;
|
||||||
file->cbs = cbs; /* the given pointer must outlive the lifespan of the while file handling cycle. */
|
file->cbs = cbs; /* the given pointer must outlive the lifespan of the while file handling cycle. */
|
||||||
file->sendfile_ok = hio_dev_sck_sendfileok(csck);
|
file->sendfile_ok = hio_dev_sck_sendfileok(csck);
|
||||||
|
|
||||||
bind_task_to_client (file, csck);
|
|
||||||
file->peer_tmridx = HIO_TMRIDX_INVALID;
|
file->peer_tmridx = HIO_TMRIDX_INVALID;
|
||||||
file->peer = -1;
|
file->peer = -1;
|
||||||
|
|
||||||
|
bind_task_to_client (file, csck);
|
||||||
|
|
||||||
if (hio_svc_htts_task_handleexpect100(file, options) <= -1) goto oops;
|
if (hio_svc_htts_task_handleexpect100(file, options) <= -1) goto oops;
|
||||||
if (setup_for_content_length(file, req) <= -1) goto oops;
|
if (setup_for_content_length(file, req) <= -1) goto oops;
|
||||||
|
|
||||||
switch (file->task_req_method)
|
if (bind_task_to_peer(file, req, actual_file, mime_type) <= -1) goto oops;
|
||||||
{
|
|
||||||
case HIO_HTTP_GET:
|
|
||||||
case HIO_HTTP_HEAD:
|
|
||||||
{
|
|
||||||
const hio_bch_t* actual_mime_type = mime_type;
|
|
||||||
|
|
||||||
if (open_peer_with_mode(file, actual_file, O_RDONLY, &status_code, (mime_type? HIO_NULL: &actual_mime_type)) <= -1 ||
|
|
||||||
process_range_header(file, req, &status_code) <= -1) goto done_with_status_code;
|
|
||||||
|
|
||||||
if (HIO_LIKELY(file->task_req_method == HIO_HTTP_GET))
|
|
||||||
{
|
|
||||||
if (file->etag_match)
|
|
||||||
{
|
|
||||||
status_code = HIO_HTTP_STATUS_NOT_MODIFIED;
|
|
||||||
goto done_with_status_code;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* normal full transfer */
|
|
||||||
#if defined(HAVE_POSIX_FADVISE)
|
|
||||||
posix_fadvise (file->peer, file->start_offset, file->end_offset - file->start_offset + 1, POSIX_FADV_SEQUENTIAL);
|
|
||||||
#endif
|
|
||||||
set_tcp_cork (file->task_csck, 1);
|
|
||||||
|
|
||||||
if (file_send_header_to_client(file, HIO_HTTP_STATUS_OK, 0, actual_mime_type) <= -1) goto oops;
|
|
||||||
if (file_send_contents_to_client(file) <= -1) goto oops;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (file_send_header_to_client(file, HIO_HTTP_STATUS_OK, 0, actual_mime_type) <= -1) goto oops;
|
|
||||||
/* no content must be transmitted for HEAD despite Content-Length in the header. */
|
|
||||||
goto done_with_status_code_2;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case HIO_HTTP_POST:
|
|
||||||
case HIO_HTTP_PUT:
|
|
||||||
if (file->options & HIO_SVC_HTTS_FILE_READ_ONLY)
|
|
||||||
{
|
|
||||||
status_code = HIO_HTTP_STATUS_METHOD_NOT_ALLOWED;
|
|
||||||
goto done_with_status_code;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (open_peer_with_mode(file, actual_file, O_WRONLY | O_TRUNC | O_CREAT, &status_code, HIO_NULL) <= -1) goto done_with_status_code;
|
|
||||||
|
|
||||||
/* the client input must be written to the peer side */
|
|
||||||
file_mark_over (file, FILE_OVER_READ_FROM_PEER);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case HIO_HTTP_DELETE:
|
|
||||||
if (file->options & HIO_SVC_HTTS_FILE_READ_ONLY)
|
|
||||||
{
|
|
||||||
status_code = HIO_HTTP_STATUS_METHOD_NOT_ALLOWED;
|
|
||||||
goto done_with_status_code;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unlink(actual_file) <= -1)
|
|
||||||
{
|
|
||||||
if (errno != EISDIR || (errno == EISDIR && rmdir(actual_file) <= -1))
|
|
||||||
{
|
|
||||||
status_code = ERRNO_TO_STATUS_CODE(errno);
|
|
||||||
goto done_with_status_code;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
status_code = HIO_HTTP_STATUS_OK;
|
|
||||||
goto done_with_status_code;
|
|
||||||
|
|
||||||
default:
|
|
||||||
status_code = HIO_HTTP_STATUS_METHOD_NOT_ALLOWED;
|
|
||||||
done_with_status_code:
|
|
||||||
if (hio_svc_htts_task_sendfinalres(file, status_code, HIO_NULL, HIO_NULL, 0) <= -1) goto oops;
|
|
||||||
done_with_status_code_2:
|
|
||||||
file_mark_over (file, FILE_OVER_READ_FROM_PEER | FILE_OVER_WRITE_TO_PEER);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: store current input watching state and use it when destroying the file data */
|
/* TODO: store current input watching state and use it when destroying the file data */
|
||||||
if (hio_dev_sck_read(csck, !(file->over & FILE_OVER_READ_FROM_CLIENT)) <= -1) goto oops;
|
if (hio_dev_sck_read(csck, !(file->over & FILE_OVER_READ_FROM_CLIENT)) <= -1) goto oops;
|
||||||
|
Loading…
Reference in New Issue
Block a user