added more code for qse_httpd_t
added qse_htre_gethdrval()
This commit is contained in:
parent
d9d2cda5c3
commit
0967928a90
@ -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;
|
||||
|
@ -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
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
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
|
||||
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",
|
||||
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)
|
||||
);
|
||||
n = qse_httpd_entasksendfmt (httpd, client, text);
|
||||
qse_htre_getqpathptr(req)) <= -1)
|
||||
{
|
||||
close (fd);
|
||||
goto oops;
|
||||
}
|
||||
#endif
|
||||
n = qse_httpd_entasksendfmt (httpd, client,
|
||||
"HTTP/%d.%d 200 OK\r\nContent-Length: %llu\r\nContent-Location: %s\r\n\r\n",
|
||||
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)
|
||||
);
|
||||
if (n <= -1) return -1;
|
||||
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) 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)
|
||||
{
|
||||
@ -114,6 +152,10 @@ snprintf (text, sizeof(text),
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
oops:
|
||||
qse_httpd_markclientbad (httpd, client);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_expect_continue (
|
||||
|
Loading…
x
Reference in New Issue
Block a user