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
|
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;
|
||||||
|
@ -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
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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 (
|
||||||
|
Loading…
x
Reference in New Issue
Block a user