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
{
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;

View File

@ -143,6 +143,10 @@ int qse_htre_setstrfromxstr (
const qse_mxstr_t* xstr
);
const qse_mchar_t* qse_htre_gethdrval (
qse_htre_t* re, const qse_mchar_t* key
);
#ifdef __cplusplus
}
#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;
}
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);
array->data[fd].htrd = QSE_NULL;
close (array->data[fd].fd);
close (array->data[fd].handle.i);
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;
client_array_t* array = &httpd->client.array;
int opt;
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);
array->data[fd].fd = fd;
array->data[fd].addr = *addr;
array->data[fd].htrd = qse_htrd_open (httpd->mmgr, QSE_SIZEOF(*xtn));
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);
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)
{
FD_SET (ca->data[fd].fd, r);
if (ca->data[fd].fd > max) max = ca->data[fd].fd;
FD_SET (ca->data[fd].handle.i, r);
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 */
FD_SET (ca->data[fd].fd, w);
if (ca->data[fd].fd > max) max = ca->data[fd].fd;
FD_SET (ca->data[fd].handle.i, w);
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)
{
dequeue_task_locked (httpd, client);
shutdown (client->fd, SHUT_RDWR);
shutdown (client->handle.i, SHUT_RDWR);
}
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 (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;
reread:
m = read (client->fd, buf, QSE_SIZEOF(buf));
m = read (client->handle.i, buf, QSE_SIZEOF(buf));
if (m <= -1)
{
if (errno != EINTR)
{
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;
}
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)
{
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;
}
@ -974,7 +987,7 @@ qse_fprintf (QSE_STDERR, QSE_T("Error: select returned failure\n"));
if (!client->htrd) continue;
if (FD_ISSET(client->fd, &r))
if (FD_ISSET(client->handle.i, &r))
{
/* got input */
if (read_from_client (httpd, client) <= -1)
@ -1237,7 +1250,15 @@ int qse_httpd_entask (
{
int ret;
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;
}
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 (
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;
}
@ -67,7 +67,7 @@ static int httpd_main_sendtext (
if (count >= ctx->left) count = ctx->left;
n = send (
client->fd,
client->handle.i,
ctx->ptr,
count,
0
@ -143,7 +143,7 @@ static int httpd_main_sendfmt (
if (count >= ctx->left) count = ctx->left;
n = send (
client->fd,
client->handle.i,
ctx->ptr,
count,
0
@ -287,7 +287,7 @@ static int httpd_main_sendfile (
if (count >= ctx->left) count = ctx->left;
n = sendfile (
client->fd,
client->handle.i,
ctx->fd,
&ctx->offset,
count
@ -295,6 +295,12 @@ static int httpd_main_sendfile (
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;
if (ctx->left <= 0) return 0;

View File

@ -53,7 +53,6 @@ qse_printf (QSE_T("content = [%.*S]\n"),
QSE_MBS_PTR(&req->content));
}
method = qse_htre_getqmethod (req);
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);
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
{
struct stat st;
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);
return -1;
}
else if (st.st_size <= 0)
{
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"),
req->version.major, req->version.minor,
(int)qse_mbslen(msg) + 4, msg) <= -1) goto oops;
}
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;
const qse_mchar_t* range;
if (st.st_size <= 0) st.st_size = 0;
if (qse_httpd_entasksendfile (httpd, client, fd, 0, st.st_size) <= -1) return -1;
range = qse_htre_gethdrval (req, "Range");
if (range)
{
qse_printf (QSE_T("PARTIAL>>>> %S\n"), range);
#if 0
if (qse_httpd_entasksendfmt (httpd, client,
QSE_MT("HTTP/%d.%d 200 OK\r\nContent-Length: %llu\r\nContent-Location: %sContent-Range: bytes %lld-%lld\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;
}
#endif
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;
}
}
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)
{
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)
{
@ -114,6 +152,10 @@ snprintf (text, sizeof(text),
}
return 0;
oops:
qse_httpd_markclientbad (httpd, client);
return 0;
}
static int handle_expect_continue (