added more code for qse_httpd_t

added qse_htre_gethdrval()
This commit is contained in:
hyung-hwan 2011-07-22 09:50:38 +00:00
parent d9d2cda5c3
commit 0967928a90
7 changed files with 364 additions and 277 deletions

View File

@ -39,7 +39,9 @@ typedef enum qse_htrd_errnum_t qse_htrd_errnum_t;
enum qse_htrd_option_t enum qse_htrd_option_t
{ {
QSE_HTRD_LEADINGEMPTYLINES = (1 << 0) QSE_HTRD_LEADINGEMPTYLINES = (1 << 0),
QSE_HTRD_REQUEST = (1 << 1),
QSE_HTRD_RESPONSE = (1 << 2)
}; };
typedef enum qse_htrd_option_t qse_htrd_option_t; typedef enum qse_htrd_option_t qse_htrd_option_t;

View File

@ -143,6 +143,10 @@ int qse_htre_setstrfromxstr (
const qse_mxstr_t* xstr const qse_mxstr_t* xstr
); );
const qse_mchar_t* qse_htre_gethdrval (
qse_htre_t* re, const qse_mchar_t* key
);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -56,3 +56,12 @@ int qse_htre_setstrfromxstr (
return (qse_mbs_ncpy (str, xstr->ptr, xstr->len) == (qse_size_t)-1)? -1: 0; return (qse_mbs_ncpy (str, xstr->ptr, xstr->len) == (qse_size_t)-1)? -1: 0;
} }
const qse_mchar_t* qse_htre_gethdrval (
qse_htre_t* re, const qse_mchar_t* name)
{
qse_htb_pair_t* pair;
pair = qse_htb_search (&re->hdrtab, name, qse_mbslen(name));
if (pair == QSE_NULL) return pair;
return QSE_HTB_VPTR(pair);
}

View File

@ -610,7 +610,7 @@ static void delete_from_client_array (qse_httpd_t* httpd, int fd)
qse_htrd_close (array->data[fd].htrd); qse_htrd_close (array->data[fd].htrd);
array->data[fd].htrd = QSE_NULL; array->data[fd].htrd = QSE_NULL;
close (array->data[fd].fd); close (array->data[fd].handle.i);
array->size--; array->size--;
} }
} }
@ -636,6 +636,7 @@ static qse_httpd_client_t* insert_into_client_array (qse_httpd_t* httpd, int fd,
{ {
htrd_xtn_t* xtn; htrd_xtn_t* xtn;
client_array_t* array = &httpd->client.array; client_array_t* array = &httpd->client.array;
int opt;
if (fd >= array->capa) if (fd >= array->capa)
{ {
@ -655,10 +656,17 @@ static qse_httpd_client_t* insert_into_client_array (qse_httpd_t* httpd, int fd,
QSE_ASSERT (array->data[fd].htrd == QSE_NULL); QSE_ASSERT (array->data[fd].htrd == QSE_NULL);
array->data[fd].fd = fd;
array->data[fd].addr = *addr;
array->data[fd].htrd = qse_htrd_open (httpd->mmgr, QSE_SIZEOF(*xtn)); array->data[fd].htrd = qse_htrd_open (httpd->mmgr, QSE_SIZEOF(*xtn));
if (array->data[fd].htrd == QSE_NULL) return QSE_NULL; if (array->data[fd].htrd == QSE_NULL) return QSE_NULL;
opt = qse_htrd_getoption (array->data[fd].htrd);
opt |= QSE_HTRD_REQUEST;
opt &= ~QSE_HTRD_RESPONSE;
qse_htrd_setoption (array->data[fd].htrd, opt);
array->data[fd].bad = 0;
array->data[fd].handle.i = fd;
array->data[fd].addr = *addr;
pthread_mutex_init (&array->data[fd].task.mutex, NULL); pthread_mutex_init (&array->data[fd].task.mutex, NULL);
xtn = (htrd_xtn_t*)qse_htrd_getxtn (array->data[fd].htrd); xtn = (htrd_xtn_t*)qse_htrd_getxtn (array->data[fd].htrd);
@ -765,14 +773,14 @@ static int make_fd_set_from_client_array (qse_httpd_t* httpd, fd_set* r, fd_set*
{ {
if (r) if (r)
{ {
FD_SET (ca->data[fd].fd, r); FD_SET (ca->data[fd].handle.i, r);
if (ca->data[fd].fd > max) max = ca->data[fd].fd; if (ca->data[fd].handle.i > max) max = ca->data[fd].handle.i;
} }
if (w && ca->data[fd].task.queue.count > 0) if (w && (ca->data[fd].task.queue.count > 0 || ca->data[fd].bad))
{ {
/* add it to the set if it has a response to send */ /* add it to the set if it has a response to send */
FD_SET (ca->data[fd].fd, w); FD_SET (ca->data[fd].handle.i, w);
if (ca->data[fd].fd > max) max = ca->data[fd].fd; if (ca->data[fd].handle.i > max) max = ca->data[fd].handle.i;
} }
} }
} }
@ -793,7 +801,7 @@ static void perform_task (qse_httpd_t* httpd, qse_httpd_client_t* client)
if (n <= -1) if (n <= -1)
{ {
dequeue_task_locked (httpd, client); dequeue_task_locked (httpd, client);
shutdown (client->fd, SHUT_RDWR); shutdown (client->handle.i, SHUT_RDWR);
} }
else if (n == 0) else if (n == 0)
{ {
@ -853,9 +861,14 @@ qse_fprintf (QSE_STDERR, QSE_T("Error: select returned failure - %S\n"), strerro
if (!client->htrd) continue; if (!client->htrd) continue;
if (FD_ISSET(client->fd, &w)) if (FD_ISSET(client->handle.i, &w))
{ {
if (client->task.queue.count > 0) perform_task (httpd, client); if (client->bad)
{
/*send (client->handle, i, "INTERNAL SERVER ERROR..", ...);*/
shutdown (client->handle.i, 0);
}
else if (client->task.queue.count > 0) perform_task (httpd, client);
} }
} }
@ -871,13 +884,13 @@ static int read_from_client (qse_httpd_t* httpd, qse_httpd_client_t* client)
qse_ssize_t m; qse_ssize_t m;
reread: reread:
m = read (client->fd, buf, QSE_SIZEOF(buf)); m = read (client->handle.i, buf, QSE_SIZEOF(buf));
if (m <= -1) if (m <= -1)
{ {
if (errno != EINTR) if (errno != EINTR)
{ {
httpd->errnum = QSE_HTTPD_ESOCKET; httpd->errnum = QSE_HTTPD_ESOCKET;
qse_fprintf (QSE_STDERR, QSE_T("Error: failed to read from a client %d\n"), client->fd); qse_fprintf (QSE_STDERR, QSE_T("Error: failed to read from a client %d\n"), client->handle.i);
return -1; return -1;
} }
goto reread; goto reread;
@ -885,7 +898,7 @@ qse_fprintf (QSE_STDERR, QSE_T("Error: failed to read from a client %d\n"), clie
else if (m == 0) else if (m == 0)
{ {
httpd->errnum = QSE_HTTPD_EDISCON; httpd->errnum = QSE_HTTPD_EDISCON;
qse_fprintf (QSE_STDERR, QSE_T("Debug: connection closed %d\n"), client->fd); qse_fprintf (QSE_STDERR, QSE_T("Debug: connection closed %d\n"), client->handle.i);
return -1; return -1;
} }
@ -974,7 +987,7 @@ qse_fprintf (QSE_STDERR, QSE_T("Error: select returned failure\n"));
if (!client->htrd) continue; if (!client->htrd) continue;
if (FD_ISSET(client->fd, &r)) if (FD_ISSET(client->handle.i, &r))
{ {
/* got input */ /* got input */
if (read_from_client (httpd, client) <= -1) if (read_from_client (httpd, client) <= -1)
@ -1237,7 +1250,15 @@ int qse_httpd_entask (
{ {
int ret; int ret;
ret = enqueue_task_locked (httpd, client, task, xtnsize); ret = enqueue_task_locked (httpd, client, task, xtnsize);
if (ret >= 0) pthread_cond_signal (&httpd->client.cond); if (ret <= -1) client->bad = 1; /* mark this client bad */
else pthread_cond_signal (&httpd->client.cond);
return ret; return ret;
} }
void qse_httpd_markclientbad (qse_httpd_t* httpd, qse_httpd_client_t* client)
{
/* mark that something is wrong in processing requests from this client.
* this client could be bad... or the system could encounter some errors
* like memory allocation failure */
client->bad = 1;
}

View File

@ -20,7 +20,7 @@
static int task_main_disconnect ( static int task_main_disconnect (
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task) qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
{ {
shutdown (client->fd, SHUT_RDWR); shutdown (client->handle.i, SHUT_RDWR);
return 0; return 0;
} }
@ -67,7 +67,7 @@ static int httpd_main_sendtext (
if (count >= ctx->left) count = ctx->left; if (count >= ctx->left) count = ctx->left;
n = send ( n = send (
client->fd, client->handle.i,
ctx->ptr, ctx->ptr,
count, count,
0 0
@ -143,7 +143,7 @@ static int httpd_main_sendfmt (
if (count >= ctx->left) count = ctx->left; if (count >= ctx->left) count = ctx->left;
n = send ( n = send (
client->fd, client->handle.i,
ctx->ptr, ctx->ptr,
count, count,
0 0
@ -287,7 +287,7 @@ static int httpd_main_sendfile (
if (count >= ctx->left) count = ctx->left; if (count >= ctx->left) count = ctx->left;
n = sendfile ( n = sendfile (
client->fd, client->handle.i,
ctx->fd, ctx->fd,
&ctx->offset, &ctx->offset,
count count
@ -295,6 +295,12 @@ static int httpd_main_sendfile (
if (n <= -1) return -1; if (n <= -1) return -1;
if (n == 0 && count > 0)
{
/* TODO: .... */
/* anything to do in this case? can this happen if the file has been truncated during transfer.... */
}
ctx->left -= n; ctx->left -= n;
if (ctx->left <= 0) return 0; if (ctx->left <= 0) return 0;

View File

@ -53,7 +53,6 @@ qse_printf (QSE_T("content = [%.*S]\n"),
QSE_MBS_PTR(&req->content)); QSE_MBS_PTR(&req->content));
} }
method = qse_htre_getqmethod (req); method = qse_htre_getqmethod (req);
if (method == QSE_HTTP_GET || method == QSE_HTTP_POST) if (method == QSE_HTTP_GET || method == QSE_HTTP_POST)
@ -63,50 +62,89 @@ qse_printf (QSE_T("content = [%.*S]\n"),
fd = open (qse_htre_getqpathptr(req), O_RDONLY); fd = open (qse_htre_getqpathptr(req), O_RDONLY);
if (fd <= -1) if (fd <= -1)
{ {
return -1; const qse_mchar_t* msg = QSE_MT("<html><head><title>Not found</title></head><body><b>REQUESTED FILE NOT FOUND</b></body></html>");
if (qse_httpd_entasksendfmt (httpd, client,
QSE_MT("HTTP/%d.%d 404 Not found\r\nContent-Length: %d\r\n\r\n%s\r\n\r\n"),
req->version.major, req->version.minor,
(int)qse_mbslen(msg) + 4, msg) <= -1) goto oops;
} }
else else
{ {
struct stat st; struct stat st;
if (fstat (fd, &st) <= -1) if (fstat (fd, &st) <= -1)
{ {
const qse_mchar_t* msg = QSE_MT("<html><head><title>Not found</title></head><body><b>REQUESTED FILE NOT FOUND</b></body></html>");
close (fd); close (fd);
return -1; if (qse_httpd_entasksendfmt (httpd, client,
} QSE_MT("HTTP/%d.%d 404 Not found\r\nContent-Length: %d\r\n\r\n%s\r\n\r\n"),
else if (st.st_size <= 0) req->version.major, req->version.minor,
{ (int)qse_mbslen(msg) + 4, msg) <= -1) goto oops;
close (fd);
return -1;
} }
else else
{ {
int n; const qse_mchar_t* range;
if (st.st_size <= 0) st.st_size = 0;
range = qse_htre_gethdrval (req, "Range");
if (range)
{
qse_printf (QSE_T("PARTIAL>>>> %S\n"), range);
#if 0 #if 0
qse_mchar_t text[128]; if (qse_httpd_entasksendfmt (httpd, client,
snprintf (text, sizeof(text), QSE_MT("HTTP/%d.%d 200 OK\r\nContent-Length: %llu\r\nContent-Location: %sContent-Range: bytes %lld-%lld\r\n\r\n"),
"HTTP/%d.%d 200 OK\r\nContent-Length: %llu\r\nContent-Location: %s\r\n\r\n",
qse_htre_getmajorversion(req), qse_htre_getmajorversion(req),
qse_htre_getminorversion(req), qse_htre_getminorversion(req),
(unsigned long long)st.st_size, (unsigned long long)st.st_size,
qse_htre_getqpathptr(req) qse_htre_getqpathptr(req)) <= -1)
); {
n = qse_httpd_entasksendfmt (httpd, client, text); close (fd);
goto oops;
}
#endif #endif
n = qse_httpd_entasksendfmt (httpd, client, if (qse_httpd_entasksendfmt (httpd, client,
"HTTP/%d.%d 200 OK\r\nContent-Length: %llu\r\nContent-Location: %s\r\n\r\n", QSE_MT("HTTP/%d.%d 200 OK\r\nContent-Length: %llu\r\nContent-Location: %s\r\n\r\n"),
qse_htre_getmajorversion(req), qse_htre_getmajorversion(req),
qse_htre_getminorversion(req), qse_htre_getminorversion(req),
(unsigned long long)st.st_size, (unsigned long long)st.st_size,
qse_htre_getqpathptr(req) qse_htre_getqpathptr(req)) <= -1)
); {
if (n <= -1) return -1; close (fd);
goto oops;
}
}
else
{
/* TODO: int64 format.... don't hard code it llu */
if (qse_httpd_entasksendfmt (httpd, client,
QSE_MT("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)) <= -1)
{
close (fd);
goto oops;
}
}
if (qse_httpd_entasksendfile (httpd, client, fd, 0, st.st_size) <= -1) return -1; if (qse_httpd_entasksendfile (httpd, client, fd, 0, st.st_size) <= -1)
{
close (fd);
goto oops;
}
} }
} }
} }
else
{
const qse_mchar_t* msg = QSE_MT("<html><head><title>Method not allowed</title></head><body><b>REQUEST METHOD NOT ALLOWED</b></body></html>");
if (qse_httpd_entasksendfmt (httpd, client,
QSE_MT("HTTP/%d.%d 405 Method not allowed\r\nContent-Length: %d\r\n\r\n%s\r\n\r\n"),
req->version.major, req->version.minor,
(int)qse_mbslen(msg) + 4, msg) <= -1) goto oops;
}
if (req->attr.connection_close) if (req->attr.connection_close)
{ {
@ -114,6 +152,10 @@ snprintf (text, sizeof(text),
} }
return 0; return 0;
oops:
qse_httpd_markclientbad (httpd, client);
return 0;
} }
static int handle_expect_continue ( static int handle_expect_continue (