started adding cgi support.
enhanced qse_httpd_entask() and related functions to support entasking within a task handler.
This commit is contained in:
parent
1d41b3fb2a
commit
1b2392571c
@ -155,51 +155,65 @@ void qse_httpd_markclientbad (
|
|||||||
|
|
||||||
#define qse_httpd_gettaskxtn(httpd,task) ((void*)(task+1))
|
#define qse_httpd_gettaskxtn(httpd,task) ((void*)(task+1))
|
||||||
|
|
||||||
int qse_httpd_entask (
|
qse_httpd_task_t* qse_httpd_entask (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
|
const qse_httpd_task_t* pred,
|
||||||
const qse_httpd_task_t* task,
|
const qse_httpd_task_t* task,
|
||||||
qse_size_t xtnsize
|
qse_size_t xtnsize
|
||||||
);
|
);
|
||||||
|
|
||||||
int qse_httpd_entasktext (
|
qse_httpd_task_t* qse_httpd_entaskdisconnect (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
|
const qse_httpd_task_t* pred
|
||||||
|
);
|
||||||
|
|
||||||
|
qse_httpd_task_t* qse_httpd_entasktext (
|
||||||
|
qse_httpd_t* httpd,
|
||||||
|
qse_httpd_client_t* client,
|
||||||
|
const qse_httpd_task_t* pred,
|
||||||
const qse_mchar_t* text
|
const qse_mchar_t* text
|
||||||
);
|
);
|
||||||
|
|
||||||
int qse_httpd_entaskstatictext (
|
qse_httpd_task_t* qse_httpd_entaskstatictext (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
|
const qse_httpd_task_t* pred,
|
||||||
const qse_mchar_t* text
|
const qse_mchar_t* text
|
||||||
);
|
);
|
||||||
|
|
||||||
int qse_httpd_entaskformat (
|
qse_httpd_task_t* qse_httpd_entaskformat (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
|
const qse_httpd_task_t* pred,
|
||||||
const qse_mchar_t* fmt,
|
const qse_mchar_t* fmt,
|
||||||
...
|
...
|
||||||
);
|
);
|
||||||
|
|
||||||
int qse_httpd_entaskfile (
|
qse_httpd_task_t* qse_httpd_entaskfile (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
|
const qse_httpd_task_t* pred,
|
||||||
qse_ubi_t handle,
|
qse_ubi_t handle,
|
||||||
qse_foff_t offset,
|
qse_foff_t offset,
|
||||||
qse_foff_t size
|
qse_foff_t size
|
||||||
);
|
);
|
||||||
|
|
||||||
int qse_httpd_entaskpath (
|
qse_httpd_task_t* qse_httpd_entaskpath (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
|
const qse_httpd_task_t* pred,
|
||||||
const qse_mchar_t* name,
|
const qse_mchar_t* name,
|
||||||
const qse_http_range_t* range,
|
const qse_http_range_t* range,
|
||||||
const qse_http_version_t* version
|
const qse_http_version_t* version
|
||||||
);
|
);
|
||||||
|
|
||||||
int qse_httpd_entaskdisconnect (
|
qse_httpd_task_t* qse_httpd_entaskcgi (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client
|
qse_httpd_client_t* client,
|
||||||
|
const qse_httpd_task_t* pred,
|
||||||
|
const qse_char_t* path
|
||||||
);
|
);
|
||||||
|
|
||||||
void* qse_httpd_allocmem (
|
void* qse_httpd_allocmem (
|
||||||
|
@ -33,7 +33,7 @@ static QSE_INLINE int is_whspace_octet (qse_mchar_t c)
|
|||||||
|
|
||||||
static QSE_INLINE int is_space_octet (qse_mchar_t c)
|
static QSE_INLINE int is_space_octet (qse_mchar_t c)
|
||||||
{
|
{
|
||||||
return c == ' ' || c == '\t' || c == '\r';
|
return c == QSE_MT(' ') || c == QSE_MT('\t') || c == QSE_MT('\r');
|
||||||
}
|
}
|
||||||
|
|
||||||
static QSE_INLINE int is_purespace_octet (qse_mchar_t c)
|
static QSE_INLINE int is_purespace_octet (qse_mchar_t c)
|
||||||
@ -71,18 +71,19 @@ static QSE_INLINE int is_xdigit_octet (qse_mchar_t c)
|
|||||||
|
|
||||||
static QSE_INLINE int digit_to_num (qse_mchar_t c)
|
static QSE_INLINE int digit_to_num (qse_mchar_t c)
|
||||||
{
|
{
|
||||||
if (c >= '0' && c <= '9') return c - '0';
|
if (c >= QSE_MT('0') && c <= QSE_MT('9')) return c - QSE_MT('0');
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QSE_INLINE int xdigit_to_num (qse_mchar_t c)
|
static QSE_INLINE int xdigit_to_num (qse_mchar_t c)
|
||||||
{
|
{
|
||||||
if (c >= '0' && c <= '9') return c - '0';
|
if (c >= QSE_MT('0') && c <= QSE_MT('9')) return c - QSE_MT('0');
|
||||||
if (c >= 'A' && c <= 'Z') return c - 'A' + 10;
|
if (c >= QSE_MT('A') && c <= QSE_MT('Z')) return c - QSE_MT('A') + 10;
|
||||||
if (c >= 'a' && c <= 'z') return c - 'a' + 10;
|
if (c >= QSE_MT('a') && c <= QSE_MT('z')) return c - QSE_MT('a') + 10;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static QSE_INLINE int push_to_buffer (
|
static QSE_INLINE int push_to_buffer (
|
||||||
qse_htrd_t* htrd, qse_htob_t* octb,
|
qse_htrd_t* htrd, qse_htob_t* octb,
|
||||||
const qse_mchar_t* ptr, qse_size_t len)
|
const qse_mchar_t* ptr, qse_size_t len)
|
||||||
|
@ -132,7 +132,8 @@ QSE_INLINE void* qse_httpd_allocmem (qse_httpd_t* httpd, qse_size_t size)
|
|||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSE_INLINE void* qse_httpd_reallocmem (qse_httpd_t* httpd, void* ptr, qse_size_t size)
|
QSE_INLINE void* qse_httpd_reallocmem (
|
||||||
|
qse_httpd_t* httpd, void* ptr, qse_size_t size)
|
||||||
{
|
{
|
||||||
void* nptr = QSE_MMGR_REALLOC (httpd->mmgr, ptr, size);
|
void* nptr = QSE_MMGR_REALLOC (httpd->mmgr, ptr, size);
|
||||||
if (nptr == QSE_NULL) httpd->errnum = QSE_HTTPD_ENOMEM;
|
if (nptr == QSE_NULL) httpd->errnum = QSE_HTTPD_ENOMEM;
|
||||||
@ -144,9 +145,10 @@ QSE_INLINE void qse_httpd_freemem (qse_httpd_t* httpd, void* ptr)
|
|||||||
QSE_MMGR_FREE (httpd->mmgr, ptr);
|
QSE_MMGR_FREE (httpd->mmgr, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int enqueue_task_unlocked (
|
static qse_httpd_task_t* enqueue_task_unlocked (
|
||||||
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
||||||
const qse_httpd_task_t* task, qse_size_t xtnsize)
|
const qse_httpd_task_t* pred, const qse_httpd_task_t* task,
|
||||||
|
qse_size_t xtnsize)
|
||||||
{
|
{
|
||||||
task_queue_node_t* node;
|
task_queue_node_t* node;
|
||||||
|
|
||||||
@ -157,8 +159,9 @@ static int enqueue_task_unlocked (
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
node = qse_httpd_allocmem (httpd, QSE_SIZEOF(*node) + xtnsize);
|
node = (task_queue_node_t*)
|
||||||
if (node == QSE_NULL) return -1;
|
qse_httpd_allocmem (httpd, QSE_SIZEOF(*node) + xtnsize);
|
||||||
|
if (node == QSE_NULL) return QSE_NULL;
|
||||||
|
|
||||||
node->task = *task;
|
node->task = *task;
|
||||||
|
|
||||||
@ -170,43 +173,59 @@ static int enqueue_task_unlocked (
|
|||||||
if (httpd->errnum == QSE_HTTPD_ENOERR)
|
if (httpd->errnum == QSE_HTTPD_ENOERR)
|
||||||
httpd->errnum = QSE_HTTPD_ETASK;
|
httpd->errnum = QSE_HTTPD_ETASK;
|
||||||
qse_httpd_freemem (httpd, node);
|
qse_httpd_freemem (httpd, node);
|
||||||
return -1;
|
return QSE_NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
node->next = QSE_NULL;
|
if (pred)
|
||||||
node->prev = client->task.queue.tail;
|
|
||||||
if (client->task.queue.tail)
|
|
||||||
{
|
{
|
||||||
client->task.queue.tail->next = node;
|
task_queue_node_t* prev;
|
||||||
|
|
||||||
|
/* TODO: confirm if this calculation works all the time,
|
||||||
|
* especially regarding structure alignment */
|
||||||
|
prev = (task_queue_node_t*)
|
||||||
|
((qse_byte_t*)pred - (QSE_SIZEOF(*prev) - QSE_SIZEOF(*pred)));
|
||||||
|
|
||||||
|
node->next = prev->next;
|
||||||
|
node->prev = prev;
|
||||||
|
|
||||||
|
if (prev->next) prev->next->prev = node;
|
||||||
|
else client->task.queue.tail = node;
|
||||||
|
prev->next = node;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
node->next = QSE_NULL;
|
||||||
|
node->prev = client->task.queue.tail;
|
||||||
|
if (client->task.queue.tail)
|
||||||
|
client->task.queue.tail->next = node;
|
||||||
|
else
|
||||||
client->task.queue.head = node;
|
client->task.queue.head = node;
|
||||||
}
|
|
||||||
client->task.queue.tail = node;
|
client->task.queue.tail = node;
|
||||||
|
}
|
||||||
client->task.queue.count++;
|
client->task.queue.count++;
|
||||||
|
|
||||||
return 0;
|
return &node->task;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int enqueue_task_locked (
|
static qse_httpd_task_t* enqueue_task_locked (
|
||||||
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
||||||
const qse_httpd_task_t* task, qse_size_t xtnsize)
|
const qse_httpd_task_t* pred, const qse_httpd_task_t* task,
|
||||||
|
qse_size_t xtnsize)
|
||||||
{
|
{
|
||||||
#if defined(HAVE_PTHREAD)
|
#if defined(HAVE_PTHREAD)
|
||||||
if (httpd->threaded)
|
if (httpd->threaded)
|
||||||
{
|
{
|
||||||
int ret;
|
qse_httpd_task_t* ret;
|
||||||
pthread_mutex_lock (&client->task.mutex);
|
pthread_mutex_lock (&client->task.mutex);
|
||||||
ret = enqueue_task_unlocked (httpd, client, task, xtnsize);
|
ret = enqueue_task_unlocked (httpd, client, pred, task, xtnsize);
|
||||||
pthread_mutex_unlock (&client->task.mutex);
|
pthread_mutex_unlock (&client->task.mutex);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
return enqueue_task_unlocked (httpd, client, task, xtnsize);
|
return enqueue_task_unlocked (httpd, client, pred, task, xtnsize);
|
||||||
#if defined(HAVE_PTHREAD)
|
#if defined(HAVE_PTHREAD)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -641,7 +660,8 @@ 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->handle.i, SHUT_RDWR);
|
/*shutdown (client->handle.i, SHUT_RDWR);*/
|
||||||
|
client->bad = 1;
|
||||||
}
|
}
|
||||||
else if (n == 0)
|
else if (n == 0)
|
||||||
{
|
{
|
||||||
@ -1154,13 +1174,14 @@ void qse_httpd_clearlisteners (qse_httpd_t* httpd)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int qse_httpd_entask (
|
qse_httpd_task_t* qse_httpd_entask (
|
||||||
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
||||||
const qse_httpd_task_t* task, qse_size_t xtnsize)
|
const qse_httpd_task_t* pred, const qse_httpd_task_t* task,
|
||||||
|
qse_size_t xtnsize)
|
||||||
{
|
{
|
||||||
int ret;
|
qse_httpd_task_t* ret;
|
||||||
ret = enqueue_task_locked (httpd, client, task, xtnsize);
|
ret = enqueue_task_locked (httpd, client, pred, task, xtnsize);
|
||||||
if (ret <= -1) client->bad = 1; /* mark this client bad */
|
if (ret == QSE_NULL) client->bad = 1; /* mark this client bad */
|
||||||
#if defined(HAVE_PTHREAD)
|
#if defined(HAVE_PTHREAD)
|
||||||
else if (httpd->threaded) pthread_cond_signal (&httpd->client.cond);
|
else if (httpd->threaded) pthread_cond_signal (&httpd->client.cond);
|
||||||
#endif
|
#endif
|
||||||
@ -1174,3 +1195,4 @@ void qse_httpd_markclientbad (qse_httpd_t* httpd, qse_httpd_client_t* client)
|
|||||||
* like memory allocation failure */
|
* like memory allocation failure */
|
||||||
client->bad = 1;
|
client->bad = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#define MAX_SENDFILE_SIZE 4096
|
#define MAX_SEND_SIZE 4096
|
||||||
|
|
||||||
#ifdef HAVE_SYS_SENDFILE_H
|
#ifdef HAVE_SYS_SENDFILE_H
|
||||||
# include <sys/sendfile.h>
|
# include <sys/sendfile.h>
|
||||||
@ -36,7 +36,7 @@
|
|||||||
qse_ssize_t sendfile (
|
qse_ssize_t sendfile (
|
||||||
int out_fd, int in_fd, qse_foff_t* offset, qse_size_t count)
|
int out_fd, int in_fd, qse_foff_t* offset, qse_size_t count)
|
||||||
{
|
{
|
||||||
qse_mchar_t buf[MAX_SENDFILE_SIZE];
|
qse_mchar_t buf[MAX_SEND_SIZE];
|
||||||
qse_ssize_t n;
|
qse_ssize_t n;
|
||||||
|
|
||||||
if (offset && lseek (in_fd, *offset, SEEK_SET) != *offset)
|
if (offset && lseek (in_fd, *offset, SEEK_SET) != *offset)
|
||||||
@ -46,7 +46,7 @@ qse_ssize_t sendfile (
|
|||||||
n = read (in_fd, buf, count);
|
n = read (in_fd, buf, count);
|
||||||
if (n == (qse_ssize_t)-1 || n == 0) return n;
|
if (n == (qse_ssize_t)-1 || n == 0) return n;
|
||||||
|
|
||||||
n = write (out_fd, buf, n);
|
n = send (out_fd, buf, n, 0);
|
||||||
if (n > 0 && offset) *offset = *offset + n;
|
if (n > 0 && offset) *offset = *offset + n;
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
@ -64,14 +64,17 @@ static int task_main_disconnect (
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int qse_httpd_entaskdisconnect (qse_httpd_t* httpd, qse_httpd_client_t* client)
|
qse_httpd_task_t* qse_httpd_entaskdisconnect (
|
||||||
|
qse_httpd_t* httpd,
|
||||||
|
qse_httpd_client_t* client,
|
||||||
|
const qse_httpd_task_t* pred)
|
||||||
{
|
{
|
||||||
qse_httpd_task_t task;
|
qse_httpd_task_t task;
|
||||||
|
|
||||||
QSE_MEMSET (&task, 0, QSE_SIZEOF(task));
|
QSE_MEMSET (&task, 0, QSE_SIZEOF(task));
|
||||||
task.main = task_main_disconnect;
|
task.main = task_main_disconnect;
|
||||||
|
|
||||||
return qse_httpd_entask (httpd, client, &task, 0);
|
return qse_httpd_entask (httpd, client, pred, &task, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
@ -83,7 +86,7 @@ static int task_main_statictext (
|
|||||||
qse_size_t count = 0;
|
qse_size_t count = 0;
|
||||||
const qse_mchar_t* ptr = (const qse_mchar_t*)task->ctx;
|
const qse_mchar_t* ptr = (const qse_mchar_t*)task->ctx;
|
||||||
|
|
||||||
while (*ptr != QSE_MT('\0') && count < MAX_SENDFILE_SIZE)
|
while (*ptr != QSE_MT('\0') && count < MAX_SEND_SIZE)
|
||||||
{
|
{
|
||||||
ptr++; count++;
|
ptr++; count++;
|
||||||
}
|
}
|
||||||
@ -105,8 +108,11 @@ static int task_main_statictext (
|
|||||||
return 1; /* more work to do */
|
return 1; /* more work to do */
|
||||||
}
|
}
|
||||||
|
|
||||||
int qse_httpd_entaskstatictext (
|
qse_httpd_task_t* qse_httpd_entaskstatictext (
|
||||||
qse_httpd_t* httpd, qse_httpd_client_t* client, const qse_mchar_t* text)
|
qse_httpd_t* httpd,
|
||||||
|
qse_httpd_client_t* client,
|
||||||
|
const qse_httpd_task_t* pred,
|
||||||
|
const qse_mchar_t* text)
|
||||||
{
|
{
|
||||||
qse_httpd_task_t task;
|
qse_httpd_task_t task;
|
||||||
|
|
||||||
@ -114,7 +120,7 @@ int qse_httpd_entaskstatictext (
|
|||||||
task.main = task_main_statictext;
|
task.main = task_main_statictext;
|
||||||
task.ctx = (void*)text;
|
task.ctx = (void*)text;
|
||||||
|
|
||||||
return qse_httpd_entask (httpd, client, &task, 0);
|
return qse_httpd_entask (httpd, client, pred, &task, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
@ -146,7 +152,7 @@ static int task_main_text (
|
|||||||
qse_size_t count;
|
qse_size_t count;
|
||||||
task_text_t* ctx = (task_text_t*)task->ctx;
|
task_text_t* ctx = (task_text_t*)task->ctx;
|
||||||
|
|
||||||
count = MAX_SENDFILE_SIZE;
|
count = MAX_SEND_SIZE;
|
||||||
if (count >= ctx->left) count = ctx->left;
|
if (count >= ctx->left) count = ctx->left;
|
||||||
|
|
||||||
/* TODO: do i need to add code to skip this send if count is 0? */
|
/* TODO: do i need to add code to skip this send if count is 0? */
|
||||||
@ -166,8 +172,11 @@ static int task_main_text (
|
|||||||
return 1; /* more work to do */
|
return 1; /* more work to do */
|
||||||
}
|
}
|
||||||
|
|
||||||
int qse_httpd_entasktext (
|
qse_httpd_task_t* qse_httpd_entasktext (
|
||||||
qse_httpd_t* httpd, qse_httpd_client_t* client, const qse_mchar_t* text)
|
qse_httpd_t* httpd,
|
||||||
|
qse_httpd_client_t* client,
|
||||||
|
const qse_httpd_task_t* pred,
|
||||||
|
const qse_mchar_t* text)
|
||||||
{
|
{
|
||||||
qse_httpd_task_t task;
|
qse_httpd_task_t task;
|
||||||
task_text_t data;
|
task_text_t data;
|
||||||
@ -182,7 +191,7 @@ int qse_httpd_entasktext (
|
|||||||
task.ctx = &data;
|
task.ctx = &data;
|
||||||
|
|
||||||
return qse_httpd_entask (
|
return qse_httpd_entask (
|
||||||
httpd, client, &task, QSE_SIZEOF(data) + data.left);
|
httpd, client, pred, &task, QSE_SIZEOF(data) + data.left);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
@ -223,7 +232,7 @@ static int task_main_format (
|
|||||||
qse_size_t count;
|
qse_size_t count;
|
||||||
task_format_t* ctx = (task_format_t*)task->ctx;
|
task_format_t* ctx = (task_format_t*)task->ctx;
|
||||||
|
|
||||||
count = MAX_SENDFILE_SIZE;
|
count = MAX_SEND_SIZE;
|
||||||
if (count >= ctx->left) count = ctx->left;
|
if (count >= ctx->left) count = ctx->left;
|
||||||
|
|
||||||
n = send (
|
n = send (
|
||||||
@ -242,8 +251,11 @@ static int task_main_format (
|
|||||||
return 1; /* more work to do */
|
return 1; /* more work to do */
|
||||||
}
|
}
|
||||||
|
|
||||||
int qse_httpd_entaskformat (
|
qse_httpd_task_t* qse_httpd_entaskformat (
|
||||||
qse_httpd_t* httpd, qse_httpd_client_t* client, const qse_mchar_t* fmt, ...)
|
qse_httpd_t* httpd,
|
||||||
|
qse_httpd_client_t* client,
|
||||||
|
const qse_httpd_task_t* pred,
|
||||||
|
const qse_mchar_t* fmt, ...)
|
||||||
{
|
{
|
||||||
qse_httpd_task_t task;
|
qse_httpd_task_t task;
|
||||||
task_format_t data;
|
task_format_t data;
|
||||||
@ -266,7 +278,7 @@ int qse_httpd_entaskformat (
|
|||||||
qse_size_t capa = 256;
|
qse_size_t capa = 256;
|
||||||
|
|
||||||
buf = (qse_mchar_t*) qse_httpd_allocmem (httpd, (capa + 1) * QSE_SIZEOF(*buf));
|
buf = (qse_mchar_t*) qse_httpd_allocmem (httpd, (capa + 1) * QSE_SIZEOF(*buf));
|
||||||
if (buf == QSE_NULL) return -1;
|
if (buf == QSE_NULL) return QSE_NULL;
|
||||||
|
|
||||||
/* an old vsnprintf behaves differently from C99 standard.
|
/* an old vsnprintf behaves differently from C99 standard.
|
||||||
* thus, it returns -1 when it can't write all the input given. */
|
* thus, it returns -1 when it can't write all the input given. */
|
||||||
@ -286,7 +298,7 @@ int qse_httpd_entaskformat (
|
|||||||
|
|
||||||
capa = capa * 2;
|
capa = capa * 2;
|
||||||
buf = (qse_mchar_t*) qse_httpd_allocmem (httpd, (capa + 1) * QSE_SIZEOF(*buf));
|
buf = (qse_mchar_t*) qse_httpd_allocmem (httpd, (capa + 1) * QSE_SIZEOF(*buf));
|
||||||
if (buf == QSE_NULL) return -1;
|
if (buf == QSE_NULL) return QSE_NULL;
|
||||||
}
|
}
|
||||||
else break;
|
else break;
|
||||||
}
|
}
|
||||||
@ -297,7 +309,7 @@ int qse_httpd_entaskformat (
|
|||||||
* have been written not including the terminating '\0'
|
* have been written not including the terminating '\0'
|
||||||
* if the _data buffer were large enough */
|
* if the _data buffer were large enough */
|
||||||
buf = (qse_mchar_t*) qse_httpd_allocmem (httpd, (bytes_req + 1) * QSE_SIZEOF(*buf));
|
buf = (qse_mchar_t*) qse_httpd_allocmem (httpd, (bytes_req + 1) * QSE_SIZEOF(*buf));
|
||||||
if (buf == QSE_NULL) return -1;
|
if (buf == QSE_NULL) return QSE_NULL;
|
||||||
|
|
||||||
va_start (ap, fmt);
|
va_start (ap, fmt);
|
||||||
#if defined(_WIN32) && defined(_MSC_VER)
|
#if defined(_WIN32) && defined(_MSC_VER)
|
||||||
@ -313,7 +325,7 @@ int qse_httpd_entaskformat (
|
|||||||
qse_httpd_freemem (httpd, buf);
|
qse_httpd_freemem (httpd, buf);
|
||||||
|
|
||||||
httpd->errnum = QSE_HTTPD_EINTERN;
|
httpd->errnum = QSE_HTTPD_EINTERN;
|
||||||
return -1;
|
return QSE_NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -329,7 +341,7 @@ int qse_httpd_entaskformat (
|
|||||||
task.ctx = &data;
|
task.ctx = &data;
|
||||||
|
|
||||||
return qse_httpd_entask (
|
return qse_httpd_entask (
|
||||||
httpd, client, &task, QSE_SIZEOF(data));
|
httpd, client, pred, &task, QSE_SIZEOF(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: send wide character string when QSE_CHAR_IS_WCHAR */
|
/* TODO: send wide character string when QSE_CHAR_IS_WCHAR */
|
||||||
@ -367,7 +379,7 @@ static int task_main_file (
|
|||||||
qse_size_t count;
|
qse_size_t count;
|
||||||
task_file_t* ctx = (task_file_t*)task->ctx;
|
task_file_t* ctx = (task_file_t*)task->ctx;
|
||||||
|
|
||||||
count = MAX_SENDFILE_SIZE;
|
count = MAX_SEND_SIZE;
|
||||||
if (count >= ctx->left) count = ctx->left;
|
if (count >= ctx->left) count = ctx->left;
|
||||||
|
|
||||||
/* TODO: more adjustment needed for OS with different sendfile semantics... */
|
/* TODO: more adjustment needed for OS with different sendfile semantics... */
|
||||||
@ -396,9 +408,13 @@ static int task_main_file (
|
|||||||
return 1; /* more work to do */
|
return 1; /* more work to do */
|
||||||
}
|
}
|
||||||
|
|
||||||
int qse_httpd_entaskfile (
|
qse_httpd_task_t* qse_httpd_entaskfile (
|
||||||
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
qse_httpd_t* httpd,
|
||||||
qse_ubi_t handle, qse_foff_t offset, qse_foff_t size)
|
qse_httpd_client_t* client,
|
||||||
|
const qse_httpd_task_t* pred,
|
||||||
|
qse_ubi_t handle,
|
||||||
|
qse_foff_t offset,
|
||||||
|
qse_foff_t size)
|
||||||
{
|
{
|
||||||
qse_httpd_task_t task;
|
qse_httpd_task_t task;
|
||||||
task_file_t data;
|
task_file_t data;
|
||||||
@ -414,7 +430,7 @@ int qse_httpd_entaskfile (
|
|||||||
task.fini = task_fini_file;
|
task.fini = task_fini_file;
|
||||||
task.ctx = &data;
|
task.ctx = &data;
|
||||||
|
|
||||||
return qse_httpd_entask (httpd, client, &task, QSE_SIZEOF(data));
|
return qse_httpd_entask (httpd, client, pred, &task, QSE_SIZEOF(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
@ -448,18 +464,20 @@ static int task_main_path (
|
|||||||
task_path_t* data = (task_path_t*)task->ctx;
|
task_path_t* data = (task_path_t*)task->ctx;
|
||||||
qse_ubi_t handle;
|
qse_ubi_t handle;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
int x;
|
qse_httpd_task_t* x = task;
|
||||||
|
|
||||||
|
qse_printf (QSE_T("opending file %S\n"), data->name);
|
||||||
handle.i = open (data->name, O_RDONLY);
|
handle.i = open (data->name, O_RDONLY);
|
||||||
if (handle.i <= -1)
|
if (handle.i <= -1)
|
||||||
{
|
{
|
||||||
const qse_mchar_t* msg = QSE_MT("<html><head><title>Not found</title></head><body><b>REQUESTED FILE NOT FOUND</b></body></html>");
|
const qse_mchar_t* msg = QSE_MT("<html><head><title>Not found</title></head><body><b>REQUESTED FILE NOT FOUND</b></body></html>");
|
||||||
x = qse_httpd_entaskformat (httpd, client,
|
x = qse_httpd_entaskformat (
|
||||||
|
httpd, client, x,
|
||||||
QSE_MT("HTTP/%d.%d 404 Not found\r\nContent-Length: %d\r\n\r\n%s\r\n\r\n"),
|
QSE_MT("HTTP/%d.%d 404 Not found\r\nContent-Length: %d\r\n\r\n%s\r\n\r\n"),
|
||||||
data->version.major, data->version.minor,
|
data->version.major, data->version.minor,
|
||||||
(int)qse_mbslen(msg) + 4, msg
|
(int)qse_mbslen(msg) + 4, msg
|
||||||
);
|
);
|
||||||
goto done;
|
goto no_file_send;
|
||||||
}
|
}
|
||||||
fcntl (handle.i, F_SETFD, FD_CLOEXEC);
|
fcntl (handle.i, F_SETFD, FD_CLOEXEC);
|
||||||
|
|
||||||
@ -467,12 +485,27 @@ static int task_main_path (
|
|||||||
{
|
{
|
||||||
const qse_mchar_t* msg = QSE_MT("<html><head><title>Not found</title></head><body><b>REQUESTED FILE NOT FOUND</b></body></html>");
|
const qse_mchar_t* msg = QSE_MT("<html><head><title>Not found</title></head><body><b>REQUESTED FILE NOT FOUND</b></body></html>");
|
||||||
|
|
||||||
x = qse_httpd_entaskformat (httpd, client,
|
x = qse_httpd_entaskformat (
|
||||||
|
httpd, client, x,
|
||||||
QSE_MT("HTTP/%d.%d 404 Not found\r\nContent-Length: %d\r\n\r\n%s\r\n\r\n"),
|
QSE_MT("HTTP/%d.%d 404 Not found\r\nContent-Length: %d\r\n\r\n%s\r\n\r\n"),
|
||||||
data->version.major, data->version.minor,
|
data->version.major, data->version.minor,
|
||||||
(int)qse_mbslen(msg) + 4, msg
|
(int)qse_mbslen(msg) + 4, msg
|
||||||
);
|
);
|
||||||
goto done;
|
goto no_file_send;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (S_ISDIR(st.st_mode))
|
||||||
|
{
|
||||||
|
/* TODO: directory listing */
|
||||||
|
const qse_mchar_t* msg = QSE_MT("<html><head><title>Directory Listing</title></head><body><li>file1<li>file2<li>file3</body></html>");
|
||||||
|
|
||||||
|
x = qse_httpd_entaskformat (
|
||||||
|
httpd, client, x,
|
||||||
|
QSE_MT("HTTP/%d.%d 200 OK\r\nContent-Type: text/html\r\nContent-Length: %d\r\n\r\n%s\r\n\r\n"),
|
||||||
|
data->version.major, data->version.minor,
|
||||||
|
(int)qse_mbslen(msg) + 4, msg
|
||||||
|
);
|
||||||
|
goto no_file_send;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (st.st_size < 0) st.st_size = 0; /* can this happen? */
|
if (st.st_size < 0) st.st_size = 0; /* can this happen? */
|
||||||
@ -494,12 +527,13 @@ static int task_main_path (
|
|||||||
const qse_mchar_t* msg;
|
const qse_mchar_t* msg;
|
||||||
|
|
||||||
msg = QSE_MT("<html><head><title>Requested range not satisfiable</title></head><body><b>REQUESTED RANGE NOT SATISFIABLE</b></body></html>");
|
msg = QSE_MT("<html><head><title>Requested range not satisfiable</title></head><body><b>REQUESTED RANGE NOT SATISFIABLE</b></body></html>");
|
||||||
x = qse_httpd_entaskformat (httpd, client,
|
x = qse_httpd_entaskformat (
|
||||||
|
httpd, client, x,
|
||||||
QSE_MT("HTTP/%d.%d 416 Requested range not satisfiable\r\nContent-Length: %d\r\n\r\n%s\r\n\r\n"),
|
QSE_MT("HTTP/%d.%d 416 Requested range not satisfiable\r\nContent-Length: %d\r\n\r\n%s\r\n\r\n"),
|
||||||
data->version.major, data->version.minor,
|
data->version.major, data->version.minor,
|
||||||
(int)qse_mbslen(msg) + 4, msg
|
(int)qse_mbslen(msg) + 4, msg
|
||||||
);
|
);
|
||||||
goto done;
|
goto no_file_send;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->range.to >= st.st_size) data->range.to = st.st_size - 1;
|
if (data->range.to >= st.st_size) data->range.to = st.st_size - 1;
|
||||||
@ -512,7 +546,8 @@ static int task_main_path (
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if (QSE_SIZEOF_LONG_LONG > 0)
|
#if (QSE_SIZEOF_LONG_LONG > 0)
|
||||||
x = qse_httpd_entaskformat (httpd, client,
|
x = qse_httpd_entaskformat (
|
||||||
|
httpd, client, x,
|
||||||
QSE_MT("HTTP/%d.%d 206 Partial content\r\n%s%sContent-Length: %llu\r\nContent-Location: %s\r\nContent-Range: bytes %llu-%llu/%llu\r\n\r\n"),
|
QSE_MT("HTTP/%d.%d 206 Partial content\r\n%s%sContent-Length: %llu\r\nContent-Location: %s\r\nContent-Range: bytes %llu-%llu/%llu\r\n\r\n"),
|
||||||
data->version.major,
|
data->version.major,
|
||||||
data->version.minor,
|
data->version.minor,
|
||||||
@ -525,7 +560,8 @@ static int task_main_path (
|
|||||||
(unsigned long long)st.st_size
|
(unsigned long long)st.st_size
|
||||||
);
|
);
|
||||||
#else
|
#else
|
||||||
x = qse_httpd_entaskformat (httpd, client,
|
x = qse_httpd_entaskformat (
|
||||||
|
httpd, client, x,
|
||||||
QSE_MT("HTTP/%d.%d 206 Partial content\r\n%s%sContent-Length: %lu\r\nContent-Location: %s\r\nContent-Range: bytes %lu-%lu/%lu\r\n\r\n"),
|
QSE_MT("HTTP/%d.%d 206 Partial content\r\n%s%sContent-Length: %lu\r\nContent-Location: %s\r\nContent-Range: bytes %lu-%lu/%lu\r\n\r\n"),
|
||||||
data->version.major,
|
data->version.major,
|
||||||
data->version.minor,
|
data->version.minor,
|
||||||
@ -538,14 +574,15 @@ static int task_main_path (
|
|||||||
(unsigned long)st.st_size
|
(unsigned long)st.st_size
|
||||||
);
|
);
|
||||||
#endif
|
#endif
|
||||||
if (x <= -1) goto done;
|
if (x)
|
||||||
|
{
|
||||||
x = qse_httpd_entaskfile (
|
x = qse_httpd_entaskfile (
|
||||||
httpd, client, handle,
|
httpd, client, x,
|
||||||
|
handle,
|
||||||
data->range.from,
|
data->range.from,
|
||||||
(data->range.to - data->range.from + 1)
|
(data->range.to - data->range.from + 1)
|
||||||
);
|
);
|
||||||
if (x <= -1) goto done;
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -560,7 +597,8 @@ static int task_main_path (
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if (QSE_SIZEOF_LONG_LONG > 0)
|
#if (QSE_SIZEOF_LONG_LONG > 0)
|
||||||
x = qse_httpd_entaskformat (httpd, client,
|
x = qse_httpd_entaskformat (
|
||||||
|
httpd, client, x,
|
||||||
QSE_MT("HTTP/%d.%d 200 OK\r\n%s%sContent-Length: %llu\r\nContent-Location: %s\r\n\r\n"),
|
QSE_MT("HTTP/%d.%d 200 OK\r\n%s%sContent-Length: %llu\r\nContent-Location: %s\r\n\r\n"),
|
||||||
data->version.major,
|
data->version.major,
|
||||||
data->version.minor,
|
data->version.minor,
|
||||||
@ -570,7 +608,8 @@ static int task_main_path (
|
|||||||
data->name
|
data->name
|
||||||
);
|
);
|
||||||
#else
|
#else
|
||||||
x = qse_httpd_entaskformat (httpd, client,
|
x = qse_httpd_entaskformat (
|
||||||
|
httpd, client, x,
|
||||||
QSE_MT("HTTP/%d.%d 200 OK\r\n%s%sContent-Length: %lu\r\nContent-Location: %s\r\n\r\n"),
|
QSE_MT("HTTP/%d.%d 200 OK\r\n%s%sContent-Length: %lu\r\nContent-Location: %s\r\n\r\n"),
|
||||||
data->version.major,
|
data->version.major,
|
||||||
data->version.minor,
|
data->version.minor,
|
||||||
@ -580,22 +619,26 @@ static int task_main_path (
|
|||||||
data->name
|
data->name
|
||||||
);
|
);
|
||||||
#endif
|
#endif
|
||||||
if (x <= -1) goto done;
|
if (x)
|
||||||
|
{
|
||||||
x = qse_httpd_entaskfile (httpd, client, handle, 0, st.st_size);
|
x = qse_httpd_entaskfile (
|
||||||
if (x <= -1) goto done;
|
httpd, client, x, handle, 0, st.st_size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return (x == QSE_NULL)? -1: 0;
|
||||||
|
|
||||||
done:
|
no_file_send:
|
||||||
if (handle.i >= 0) close (handle.i);
|
if (handle.i >= 0) close (handle.i);
|
||||||
return x;
|
return (x == QSE_NULL)? -1: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int qse_httpd_entaskpath (
|
qse_httpd_task_t* qse_httpd_entaskpath (
|
||||||
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
qse_httpd_t* httpd,
|
||||||
const qse_mchar_t* name, const qse_http_range_t* range,
|
qse_httpd_client_t* client,
|
||||||
|
const qse_httpd_task_t* pred,
|
||||||
|
const qse_mchar_t* name,
|
||||||
|
const qse_http_range_t* range,
|
||||||
const qse_http_version_t* verison)
|
const qse_http_version_t* verison)
|
||||||
{
|
{
|
||||||
qse_httpd_task_t task;
|
qse_httpd_task_t task;
|
||||||
@ -612,62 +655,142 @@ int qse_httpd_entaskpath (
|
|||||||
task.main = task_main_path;
|
task.main = task_main_path;
|
||||||
task.ctx = &data;
|
task.ctx = &data;
|
||||||
|
|
||||||
return qse_httpd_entask (httpd, client, &task,
|
return qse_httpd_entask (httpd, client, pred, &task,
|
||||||
QSE_SIZEOF(task_path_t) + qse_mbslen(name) + 1);
|
QSE_SIZEOF(task_path_t) + qse_mbslen(name) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#if 0
|
typedef struct task_cgi_t task_cgi_t;
|
||||||
typedef struct httpd_task_cgi_t httpd_task_cgi_t;
|
struct task_cgi_t
|
||||||
struct httpd_task_cgi_t
|
|
||||||
{
|
{
|
||||||
|
const qse_char_t* path;
|
||||||
qse_pio_t* pio;
|
qse_pio_t* pio;
|
||||||
|
qse_mchar_t buf[MAX_SEND_SIZE];
|
||||||
|
qse_size_t buflen;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int httpd_init_cgi (
|
static int task_init_cgi (
|
||||||
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)
|
||||||
{
|
{
|
||||||
httpd_task_cgi_t* xtn = qse_httpd_gettaskxtn (httpd, task);
|
task_cgi_t* xtn = (task_cgi_t*)qse_httpd_gettaskxtn (httpd, task);
|
||||||
|
|
||||||
QSE_MEMSET (xtn, 0, QSE_SIZEOF(*xtn));
|
QSE_MEMSET (xtn, 0, QSE_SIZEOF(*xtn));
|
||||||
xtn->pio = qse_pio_open (httpd->mmgr, task->ctx);
|
qse_strcpy ((qse_char_t*)(xtn + 1), task->ctx);
|
||||||
if (xtn->pio == QSE_NULL)
|
xtn->path = (qse_char_t*)(xtn + 1);
|
||||||
{
|
|
||||||
httpd->errnum = QSE_HTTPD_ECGI;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
task->ctx = xtn;
|
task->ctx = xtn;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void httpd_fini_cgi (
|
static void task_fini_cgi (
|
||||||
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)
|
||||||
{
|
{
|
||||||
httpd_task_cgi_t* xtn = task->ctx;
|
task_cgi_t* cgi = (task_cgi_t*)task->ctx;
|
||||||
qse_pio_close (xtn->pio);
|
if (cgi->pio) qse_pio_close (cgi->pio);
|
||||||
}
|
}
|
||||||
|
static int task_main_cgi_3 (
|
||||||
static void httpd_main_cgi (
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
/* TODO */
|
task_cgi_t* cgi = (task_cgi_t*)task->ctx;
|
||||||
|
qse_ssize_t n;
|
||||||
|
|
||||||
|
QSE_ASSERT (cgi->pio != QSE_NULL);
|
||||||
|
|
||||||
|
n = send (client->handle.i, cgi->buf, cgi->buflen, 0);
|
||||||
|
if (n <= -1)
|
||||||
|
{
|
||||||
|
/* can't return internal server error any more... */
|
||||||
|
/* TODO: logging ... */
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int qse_httpd_entaskcgi (
|
QSE_MEMCPY (&cgi->buf[0], &cgi->buf[n], cgi->buflen - n);
|
||||||
qse_httpd_t* httpd, qse_httpd_client_t* client, const qse_char_t* path)
|
cgi->buflen -= n;
|
||||||
|
|
||||||
|
return (cgi->buflen > 0)? 1: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int task_main_cgi_2 (
|
||||||
|
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
|
||||||
|
{
|
||||||
|
task_cgi_t* cgi = (task_cgi_t*)task->ctx;
|
||||||
|
qse_ssize_t n;
|
||||||
|
|
||||||
|
QSE_ASSERT (cgi->pio != QSE_NULL);
|
||||||
|
|
||||||
|
/* <- can i make it non-block?? or use select??? pio_tryread()? */
|
||||||
|
n = qse_pio_read (
|
||||||
|
cgi->pio,
|
||||||
|
&cgi->buf[cgi->buflen],
|
||||||
|
QSE_SIZEOF(cgi->buf) - cgi->buflen,
|
||||||
|
QSE_PIO_OUT
|
||||||
|
);
|
||||||
|
if (n <= -1)
|
||||||
|
{
|
||||||
|
/* can't return internal server error any more... */
|
||||||
|
/* TODO: logging ... */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (n == 0)
|
||||||
|
{
|
||||||
|
if (cgi->buflen > 0)
|
||||||
|
{
|
||||||
|
task->main = task_main_cgi_3;
|
||||||
|
return task_main_cgi_3 (httpd, client, task);
|
||||||
|
}
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cgi->buflen += n;
|
||||||
|
|
||||||
|
n = send (client->handle.i, cgi->buf, cgi->buflen, 0);
|
||||||
|
if (n <= -1)
|
||||||
|
{
|
||||||
|
/* can't return internal server error any more... */
|
||||||
|
/* TODO: logging ... */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSE_MEMCPY (&cgi->buf[0], &cgi->buf[n], cgi->buflen - n);
|
||||||
|
cgi->buflen -= n;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int task_main_cgi (
|
||||||
|
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
|
||||||
|
{
|
||||||
|
task_cgi_t* cgi = (task_cgi_t*)task->ctx;
|
||||||
|
|
||||||
|
qse_printf (QSE_T("[pip open for %s]\n"), cgi->path);
|
||||||
|
cgi->pio = qse_pio_open (httpd->mmgr, 0, cgi->path, QSE_PIO_READOUT | QSE_PIO_WRITEIN);
|
||||||
|
if (cgi->pio == QSE_NULL)
|
||||||
|
{
|
||||||
|
/* TODO: entask internal server errror */
|
||||||
|
qse_printf (QSE_T("internal server error....\n"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
task->main = task_main_cgi_2; /* cause this function to be called subsequently */
|
||||||
|
|
||||||
|
return task_main_cgi_2 (httpd, client, task); /* let me call it here once */
|
||||||
|
}
|
||||||
|
|
||||||
|
qse_httpd_task_t* qse_httpd_entaskcgi (
|
||||||
|
qse_httpd_t* httpd,
|
||||||
|
qse_httpd_client_t* client,
|
||||||
|
const qse_httpd_task_t* pred,
|
||||||
|
const qse_char_t* path)
|
||||||
{
|
{
|
||||||
qse_httpd_task_t task;
|
qse_httpd_task_t task;
|
||||||
httpd_task_cgi_t data;
|
|
||||||
|
|
||||||
QSE_MEMSET (&task, 0, QSE_SIZEOF(task));
|
QSE_MEMSET (&task, 0, QSE_SIZEOF(task));
|
||||||
task.init = httpd_init_cgi;
|
task.init = task_init_cgi;
|
||||||
task.main = httpd_main_cgi;
|
task.fini = task_fini_cgi;
|
||||||
task.fini = httpd_fini_cgi;
|
task.main = task_main_cgi;
|
||||||
task.ctx = path;
|
task.ctx = (void*)path;
|
||||||
|
|
||||||
return qse_httpd_entask (httpd, client, &task, QSE_SIZEOF(data));
|
return qse_httpd_entask (
|
||||||
|
httpd, client, pred, &task,
|
||||||
|
QSE_SIZEOF(task_cgi_t) + ((qse_strlen(path) + 1) * QSE_SIZEOF(*path))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
@ -44,7 +44,7 @@ static int pio1 (const qse_char_t* cmd, int oflags, qse_pio_hid_t rhid)
|
|||||||
qse_ssize_t i;
|
qse_ssize_t i;
|
||||||
|
|
||||||
/*qse_pio_canread (pio, QSE_PIO_ERR, 1000)*/
|
/*qse_pio_canread (pio, QSE_PIO_ERR, 1000)*/
|
||||||
qse_ssize_t n = qse_pio_read (pio, buf, sizeof(buf), rhid);
|
qse_ssize_t n = qse_pio_read (pio, buf, QSE_SIZEOF(buf), rhid);
|
||||||
if (n == 0) break;
|
if (n == 0) break;
|
||||||
if (n <= -1)
|
if (n <= -1)
|
||||||
{
|
{
|
||||||
|
@ -26,6 +26,7 @@ static int handle_request (
|
|||||||
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_htre_t* req)
|
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_htre_t* req)
|
||||||
{
|
{
|
||||||
int method;
|
int method;
|
||||||
|
qse_httpd_task_t* x;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
httpd_xtn_t* xtn = (httpd_xtn_t*) qse_httpd_getxtn (httpd);
|
httpd_xtn_t* xtn = (httpd_xtn_t*) qse_httpd_getxtn (httpd);
|
||||||
@ -58,11 +59,16 @@ qse_printf (QSE_T("content = [%.*S]\n"),
|
|||||||
{
|
{
|
||||||
const qse_mchar_t* rangestr;
|
const qse_mchar_t* rangestr;
|
||||||
qse_http_range_t range;
|
qse_http_range_t range;
|
||||||
int x;
|
|
||||||
|
|
||||||
rangestr = qse_htre_gethdrval (req, "Range");
|
rangestr = qse_htre_gethdrval (req, "Range");
|
||||||
if (rangestr && qse_parsehttprange (rangestr, &range) <= -1)
|
if (rangestr && qse_parsehttprange (rangestr, &range) <= -1)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
|
qse_httpd_entaskstatictext (httpd, client, QSE_MT("HTTP/1.1 416 Requested range not satisfiable\r\nContent-Length: 5\r\n\r\nA\r\n\r\n"));
|
||||||
|
#endif
|
||||||
|
qse_httpd_entaskcgi (httpd, client, QSE_NULL, QSE_T("/bin/ls -l /etc"));
|
||||||
|
|
||||||
|
#if 0
|
||||||
const qse_mchar_t* msg;
|
const qse_mchar_t* msg;
|
||||||
msg = QSE_MT("<html><head><title>Requested range not satisfiable</title></head><body><b>REQUESTED RANGE NOT SATISFIABLE</b></body></html>");
|
msg = QSE_MT("<html><head><title>Requested range not satisfiable</title></head><body><b>REQUESTED RANGE NOT SATISFIABLE</b></body></html>");
|
||||||
x = qse_httpd_entaskformat (httpd, client,
|
x = qse_httpd_entaskformat (httpd, client,
|
||||||
@ -70,35 +76,42 @@ qse_printf (QSE_T("content = [%.*S]\n"),
|
|||||||
req->version.major, req->version.minor,
|
req->version.major, req->version.minor,
|
||||||
(int)qse_mbslen(msg) + 4, msg
|
(int)qse_mbslen(msg) + 4, msg
|
||||||
);
|
);
|
||||||
if (x <= -1) goto oops;
|
if (x == QSE_NULL) goto oops;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
x = qse_httpd_entaskpath (
|
x = qse_httpd_entaskpath (
|
||||||
httpd, client,
|
httpd, client, QSE_NULL,
|
||||||
qse_htre_getqpathptr(req),
|
qse_htre_getqpathptr(req),
|
||||||
(rangestr? &range: QSE_NULL),
|
(rangestr? &range: QSE_NULL),
|
||||||
qse_htre_getversion(req)
|
qse_htre_getversion(req)
|
||||||
);
|
);
|
||||||
if (x <= -1) goto oops;
|
if (x == QSE_NULL) goto oops;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
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>");
|
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_entaskformat (httpd, client,
|
x = qse_httpd_entaskformat (
|
||||||
|
httpd, client, QSE_NULL,
|
||||||
QSE_MT("HTTP/%d.%d 405 Method not allowed\r\nContent-Length: %d\r\n\r\n%s\r\n\r\n"),
|
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,
|
req->version.major, req->version.minor,
|
||||||
(int)qse_mbslen(msg) + 4, msg) <= -1) goto oops;
|
(int)qse_mbslen(msg) + 4, msg
|
||||||
|
);
|
||||||
|
if (x == QSE_NULL) goto oops;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req->attr.connection_close)
|
if (req->attr.connection_close)
|
||||||
{
|
{
|
||||||
if (qse_httpd_entaskdisconnect (httpd, client) <= -1) return -1;
|
x = qse_httpd_entaskdisconnect (httpd, client, QSE_NULL);
|
||||||
|
if (x == QSE_NULL) goto oops;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
oops:
|
oops:
|
||||||
qse_httpd_markclientbad (httpd, client);
|
/*qse_httpd_markclientbad (httpd, client);*/
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user