improved qse_httpd_entask() and related functions
This commit is contained in:
@ -3,18 +3,193 @@
|
||||
#include <qse/cmn/stdio.h>
|
||||
#include <qse/cmn/main.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/sendfile.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#define MAX_SENDFILE_SIZE 4096
|
||||
typedef struct httpd_xtn_t httpd_xtn_t;
|
||||
struct httpd_xtn_t
|
||||
{
|
||||
const qse_httpd_cbs_t* orgcbs;
|
||||
};
|
||||
|
||||
typedef struct httpd_task_sendfile_t httpd_task_sendfile_t;
|
||||
struct httpd_task_sendfile_t
|
||||
{
|
||||
int fd;
|
||||
qse_foff_t left;
|
||||
qse_foff_t offset;
|
||||
};
|
||||
|
||||
typedef struct httpd_task_sendtext_t httpd_task_sendtext_t;
|
||||
struct httpd_task_sendtext_t
|
||||
{
|
||||
const qse_mchar_t* ptr;
|
||||
qse_size_t left;
|
||||
};
|
||||
|
||||
static int httpd_init_sendfile (
|
||||
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
|
||||
{
|
||||
httpd_task_sendfile_t* xtn = qse_httpd_gettaskxtn (httpd, task);
|
||||
memcpy (xtn, task->ctx, QSE_SIZEOF(*xtn));
|
||||
task->ctx = xtn;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void httpd_fini_sendfile (
|
||||
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
|
||||
{
|
||||
httpd_task_sendfile_t* ctx = (httpd_task_sendfile_t*)task->ctx;
|
||||
close (ctx->fd);
|
||||
}
|
||||
|
||||
static int httpd_main_sendfile (
|
||||
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
|
||||
{
|
||||
ssize_t n;
|
||||
size_t count;
|
||||
httpd_task_sendfile_t* ctx = (httpd_task_sendfile_t*)task->ctx;
|
||||
|
||||
count = MAX_SENDFILE_SIZE;
|
||||
if (count >= ctx->left) count = ctx->left;
|
||||
|
||||
n = sendfile (
|
||||
/* TODO: client->fd, */ *(int*)client,
|
||||
ctx->fd,
|
||||
&ctx->offset,
|
||||
count
|
||||
);
|
||||
|
||||
if (n <= -1) return -1;
|
||||
|
||||
ctx->left -= n;
|
||||
if (ctx->left <= 0) return 0;
|
||||
|
||||
return 1; /* more work to do */
|
||||
}
|
||||
|
||||
static int entask_sendfile (
|
||||
qse_httpd_t* httpd, qse_httpd_client_t* client, int fd, qse_foff_t size)
|
||||
{
|
||||
qse_httpd_task_t task;
|
||||
httpd_task_sendfile_t data;
|
||||
|
||||
memset (&data, 0, QSE_SIZEOF(data));
|
||||
data.fd = fd;
|
||||
data.left = size;
|
||||
|
||||
memset (&task, 0, QSE_SIZEOF(task));
|
||||
task.init = httpd_init_sendfile;
|
||||
task.main = httpd_main_sendfile;
|
||||
task.fini = httpd_fini_sendfile;
|
||||
task.ctx = &data;
|
||||
|
||||
return qse_httpd_entask (httpd, client, &task, QSE_SIZEOF(data));
|
||||
}
|
||||
|
||||
|
||||
static qse_htb_walk_t walk (qse_htb_t* htb, qse_htb_pair_t* pair, void* ctx)
|
||||
{
|
||||
qse_printf (QSE_T("HEADER OK %d[%S] %d[%S]\n"), (int)QSE_HTB_KLEN(pair), QSE_HTB_KPTR(pair), (int)QSE_HTB_VLEN(pair), QSE_HTB_VPTR(pair));
|
||||
return QSE_HTB_WALK_FORWARD;
|
||||
}
|
||||
|
||||
static int handle_request (
|
||||
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_htre_t* req)
|
||||
{
|
||||
int method;
|
||||
|
||||
#if 0
|
||||
httpd_xtn_t* xtn = (httpd_xtn_t*) qse_httpd_getxtn (httpd);
|
||||
return xtn->orgcbs->handle_request (httpd, client, req);
|
||||
#endif
|
||||
|
||||
qse_printf (QSE_T("================================\n"));
|
||||
qse_printf (QSE_T("REQUEST ==> [%S] version[%d.%d] method[%d]\n"),
|
||||
qse_htre_getqpathptr(req),
|
||||
qse_htre_getmajorversion(req),
|
||||
qse_htre_getminorversion(req),
|
||||
qse_htre_getqmethod(req)
|
||||
);
|
||||
if (qse_htre_getqparamlen(req) > 0)
|
||||
{
|
||||
qse_printf (QSE_T("PARAMS ==> [%S]\n"), qse_htre_getqparamptr(req));
|
||||
}
|
||||
|
||||
qse_htb_walk (&req->hdrtab, walk, QSE_NULL);
|
||||
if (QSE_MBS_LEN(&req->content) > 0)
|
||||
{
|
||||
qse_printf (QSE_T("content = [%.*S]\n"),
|
||||
(int)QSE_MBS_LEN(&req->content),
|
||||
QSE_MBS_PTR(&req->content));
|
||||
}
|
||||
|
||||
|
||||
method = qse_htre_getqmethod (req);
|
||||
|
||||
if (method == QSE_HTTP_GET || method == QSE_HTTP_POST)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = open (qse_htre_getqpathptr(req), O_RDONLY);
|
||||
if (fd <= -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct stat st;
|
||||
if (fstat (fd, &st) <= -1)
|
||||
{
|
||||
close (fd);
|
||||
return -1;
|
||||
}
|
||||
else if (st.st_size <= 0)
|
||||
{
|
||||
close (fd);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
int n;
|
||||
#if 0
|
||||
qse_mchar_t text[128];
|
||||
snprintf (text, sizeof(text),
|
||||
"HTTP/%d.%d 200 OK\r\nContent-Length: %llu\r\nContent-Location: %s\r\n\r\n",
|
||||
qse_htre_getmajorversion(req),
|
||||
qse_htre_getminorversion(req),
|
||||
(unsigned long long)st.st_size,
|
||||
qse_htre_getqpathptr(req)
|
||||
);
|
||||
n = qse_httpd_entasksendfmt (httpd, client, text);
|
||||
#endif
|
||||
n = qse_httpd_entasksendfmt (httpd, client,
|
||||
"HTTP/%d.%d 200 OK\r\nContent-Length: %llu\r\nContent-Location: %s\r\n\r\n",
|
||||
qse_htre_getmajorversion(req),
|
||||
qse_htre_getminorversion(req),
|
||||
(unsigned long long)st.st_size,
|
||||
qse_htre_getqpathptr(req)
|
||||
);
|
||||
if (n <= -1) return -1;
|
||||
|
||||
if (entask_sendfile (httpd, client, fd, st.st_size) <= -1) return -1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (req->attr.connection_close)
|
||||
{
|
||||
if (qse_httpd_entaskdisconnect (httpd, client) <= -1) return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_expect_continue (
|
||||
|
Reference in New Issue
Block a user