attempting to add dynamic modules into httpd
This commit is contained in:
@ -18,6 +18,7 @@ libqsehttp_la_SOURCES = \
|
||||
httpd-proxy.c \
|
||||
httpd-std.c \
|
||||
httpd-std-dns.h \
|
||||
httpd-std-mod.h \
|
||||
httpd-std-urs.h \
|
||||
httpd-task.c \
|
||||
httpd-text.c \
|
||||
|
@ -340,6 +340,7 @@ libqsehttp_la_SOURCES = \
|
||||
httpd-proxy.c \
|
||||
httpd-std.c \
|
||||
httpd-std-dns.h \
|
||||
httpd-std-mod.h \
|
||||
httpd-std-urs.h \
|
||||
httpd-task.c \
|
||||
httpd-text.c \
|
||||
|
@ -2072,7 +2072,7 @@ static int task_main_proxy (
|
||||
/* proxy->url_to_rewrite is the final rewritten URL by prerewrite().
|
||||
* pass QSE_NULL as the second parameter to on_url_rewritten() to
|
||||
* indicate that the original URL is not known */
|
||||
on_url_rewritten (httpd, QSE_NULL, proxy->url_to_rewrite, task);
|
||||
on_url_rewritten (httpd, QSE_NULL, (proxy->url_to_rewrite? proxy->url_to_rewrite: QSE_MT("")), task);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
216
qse/lib/http/httpd-std-mod.h
Normal file
216
qse/lib/http/httpd-std-mod.h
Normal file
@ -0,0 +1,216 @@
|
||||
#if !defined(QSE_HTTPD_DEFAULT_MODPREFIX)
|
||||
# if defined(_WIN32)
|
||||
# define QSE_HTTPD_DEFAULT_MODPREFIX "qsehttpd-"
|
||||
# elif defined(__OS2__)
|
||||
# define QSE_HTTPD_DEFAULT_MODPREFIX "htd-"
|
||||
# elif defined(__DOS__)
|
||||
# define QSE_HTTPD_DEFAULT_MODPREFIX "htd-"
|
||||
# else
|
||||
# define QSE_HTTPD_DEFAULT_MODPREFIX "libqsehttpd-"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(QSE_HTTPD_DEFAULT_MODPOSTFIX)
|
||||
# define QSE_HTTPD_DEFAULT_MODPOSTFIX ""
|
||||
#endif
|
||||
|
||||
|
||||
static int mod_open (qse_httpd_t* httpd, qse_httpd_mod_t* mod)
|
||||
{
|
||||
#if defined(USE_LTDL)
|
||||
void* h;
|
||||
qse_mchar_t* modpath;
|
||||
const qse_char_t* tmp[4];
|
||||
int count;
|
||||
|
||||
count = 0;
|
||||
if (spec->prefix) tmp[count++] = spec->prefix;
|
||||
tmp[count++] = mod->name;
|
||||
if (spec->postfix) tmp[count++] = spec->postfix;
|
||||
tmp[count] = QSE_NULL;
|
||||
|
||||
#if defined(QSE_CHAR_IS_MCHAR)
|
||||
modpath = qse_mbsadup (tmp, QSE_NULL, httpd->mmgr);
|
||||
#else
|
||||
modpath = qse_wcsatombsdup (tmp, QSE_NULL, httpd->mmgr);
|
||||
#endif
|
||||
if (!modpath)
|
||||
{
|
||||
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOMEM, QSE_NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
h = lt_dlopenext (modpath);
|
||||
|
||||
QSE_MMGR_FREE (httpd->mmgr, modpath);
|
||||
|
||||
if (h == QSE_NULL) return -1;
|
||||
mod->handle = h;
|
||||
return 0;
|
||||
|
||||
|
||||
#elif defined(_WIN32)
|
||||
|
||||
HMODULE h;
|
||||
qse_char_t* modpath;
|
||||
const qse_char_t* tmp[4];
|
||||
int count;
|
||||
|
||||
count = 0;
|
||||
if (spec->prefix) tmp[count++] = spec->prefix;
|
||||
tmp[count++] = spec->name;
|
||||
if (spec->postfix) tmp[count++] = spec->postfix;
|
||||
tmp[count] = QSE_NULL;
|
||||
|
||||
modpath = qse_stradup (tmp, QSE_NULL, httpd->mmgr);
|
||||
if (!modpath)
|
||||
{
|
||||
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOMEM, QSE_NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
h = LoadLibrary (modpath);
|
||||
|
||||
QSE_MMGR_FREE (httpd->mmgr, modpath);
|
||||
|
||||
QSE_ASSERT (QSE_SIZEOF(h) <= QSE_SIZEOF(void*));
|
||||
|
||||
if (h == QSE_NULL) return -1;
|
||||
mod->handle = h;
|
||||
return 0;
|
||||
|
||||
#elif defined(__OS2__)
|
||||
|
||||
HMODULE h;
|
||||
qse_mchar_t* modpath;
|
||||
const qse_char_t* tmp[4];
|
||||
int count;
|
||||
char errbuf[CCHMAXPATH];
|
||||
APIRET rc;
|
||||
|
||||
count = 0;
|
||||
if (spec->prefix) tmp[count++] = spec->prefix;
|
||||
tmp[count++] = spec->name;
|
||||
if (spec->postfix) tmp[count++] = spec->postfix;
|
||||
tmp[count] = QSE_NULL;
|
||||
|
||||
#if defined(QSE_CHAR_IS_MCHAR)
|
||||
modpath = qse_mbsadup (tmp, QSE_NULL, httpd->mmgr);
|
||||
#else
|
||||
modpath = qse_wcsatombsdup (tmp, QSE_NULL, httpd->mmgr);
|
||||
#endif
|
||||
if (!modpath)
|
||||
{
|
||||
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOMEM, QSE_NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* DosLoadModule() seems to have severe limitation on
|
||||
* the file name it can load (max-8-letters.xxx) */
|
||||
rc = DosLoadModule (errbuf, QSE_COUNTOF(errbuf) - 1, modpath, &h);
|
||||
if (rc != NO_ERROR) h = QSE_NULL;
|
||||
|
||||
QSE_MMGR_FREE (httpd->mmgr, modpath);
|
||||
|
||||
QSE_ASSERT (QSE_SIZEOF(h) <= QSE_SIZEOF(void*));
|
||||
|
||||
if (h == QSE_NULL) return -1;
|
||||
mod->handle = h;
|
||||
return 0;
|
||||
|
||||
|
||||
#elif defined(__DOS__)
|
||||
|
||||
/* the DOS code here is not generic enough. it's for a specific
|
||||
* dos-extender only. the best is to enable QSE_ENABLE_STATIC_MODULE
|
||||
* when building for DOS. */
|
||||
void* h;
|
||||
qse_mchar_t* modpath;
|
||||
const qse_char_t* tmp[4];
|
||||
int count;
|
||||
|
||||
count = 0;
|
||||
if (spec->prefix) tmp[count++] = spec->prefix;
|
||||
tmp[count++] = spec->name;
|
||||
if (spec->postfix) tmp[count++] = spec->postfix;
|
||||
tmp[count] = QSE_NULL;
|
||||
|
||||
#if defined(QSE_CHAR_IS_MCHAR)
|
||||
modpath = qse_mbsadup (tmp, QSE_NULL, httpd->mmgr);
|
||||
#else
|
||||
modpath = qse_wcsatombsdup (tmp, QSE_NULL, httpd->mmgr);
|
||||
#endif
|
||||
if (!modpath)
|
||||
{
|
||||
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOMEM, QSE_NULL);
|
||||
return 01;
|
||||
}
|
||||
|
||||
h = LoadModule (modpath);
|
||||
|
||||
QSE_MMGR_FREE (httpd->mmgr, modpath);
|
||||
|
||||
QSE_ASSERT (QSE_SIZEOF(h) <= QSE_SIZEOF(void*));
|
||||
|
||||
if (h == QSE_NULL) return -1;
|
||||
mod->handle = h;
|
||||
return 0;
|
||||
|
||||
#else
|
||||
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void mod_close (qse_httpd_t* httpd, qse_httpd_mod_t* mod)
|
||||
{
|
||||
#if defined(USE_LTDL)
|
||||
lt_dlclose (mod->handle);
|
||||
#elif defined(_WIN32)
|
||||
FreeLibrary ((HMODULE)mod->handle);
|
||||
#elif defined(__OS2__)
|
||||
DosFreeModule ((HMODULE)mod->handle);
|
||||
#elif defined(__DOS__)
|
||||
FreeModule (mod->handle);
|
||||
#else
|
||||
/* nothing to do */
|
||||
#endif
|
||||
}
|
||||
|
||||
static void* mod_symbol (qse_httpd_t* httpd, qse_httpd_mod_t* handle, const qse_char_t* name)
|
||||
{
|
||||
void* s;
|
||||
qse_mchar_t* mname;
|
||||
|
||||
#if defined(QSE_CHAR_IS_MCHAR)
|
||||
mname = name;
|
||||
#else
|
||||
mname = qse_wcstombsdup (name, QSE_NULL, httpd->mmgr);
|
||||
if (!mname)
|
||||
{
|
||||
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOMEM);
|
||||
return QSE_NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(USE_LTDL)
|
||||
s = lt_dlsym (mod->handle, mname);
|
||||
#elif defined(_WIN32)
|
||||
s = GetProcAddress ((HMODULE)mod->handle, mname);
|
||||
#elif defined(__OS2__)
|
||||
if (DosQueryProcAddr ((HMODULE)mod->handle, 0, mname, (PFN*)&s) != NO_ERROR) s = QSE_NULL;
|
||||
#elif defined(__DOS__)
|
||||
s = GetProcAddress (mod->handle, mname);
|
||||
#else
|
||||
s = QSE_NULL;
|
||||
#endif
|
||||
|
||||
#if defined(QSE_CHAR_IS_MCHAR)
|
||||
/* nothing to do */
|
||||
#else
|
||||
QSE_MMGR_FREE (httpd->mmgr, mname);
|
||||
#endif
|
||||
|
||||
return s;
|
||||
}
|
||||
|
@ -2294,6 +2294,7 @@ static qse_size_t hash_string (const qse_mchar_t *str)
|
||||
return h;
|
||||
}
|
||||
|
||||
#include "httpd-std-mod.h"
|
||||
#include "httpd-std-dns.h"
|
||||
#include "httpd-std-urs.h"
|
||||
|
||||
@ -2301,72 +2302,87 @@ static qse_size_t hash_string (const qse_mchar_t *str)
|
||||
|
||||
static qse_httpd_scb_t httpd_system_callbacks =
|
||||
{
|
||||
/* server */
|
||||
{ server_open,
|
||||
server_close,
|
||||
server_accept
|
||||
/* module */
|
||||
{
|
||||
mod_open,
|
||||
mod_close,
|
||||
mod_symbol
|
||||
},
|
||||
|
||||
{ peer_open,
|
||||
peer_close,
|
||||
peer_connected,
|
||||
peer_recv,
|
||||
peer_send
|
||||
/* server */
|
||||
{
|
||||
server_open,
|
||||
server_close,
|
||||
server_accept
|
||||
},
|
||||
|
||||
{
|
||||
peer_open,
|
||||
peer_close,
|
||||
peer_connected,
|
||||
peer_recv,
|
||||
peer_send
|
||||
},
|
||||
|
||||
/* multiplexer */
|
||||
{ mux_open,
|
||||
mux_close,
|
||||
mux_addhnd,
|
||||
mux_delhnd,
|
||||
mux_poll,
|
||||
{
|
||||
mux_open,
|
||||
mux_close,
|
||||
mux_addhnd,
|
||||
mux_delhnd,
|
||||
mux_poll,
|
||||
|
||||
mux_readable,
|
||||
mux_writable
|
||||
mux_readable,
|
||||
mux_writable
|
||||
},
|
||||
|
||||
/* file operation */
|
||||
{ file_stat,
|
||||
file_purge,
|
||||
file_ropen,
|
||||
file_wopen,
|
||||
file_close,
|
||||
file_read,
|
||||
file_write
|
||||
{
|
||||
file_stat,
|
||||
file_purge,
|
||||
file_ropen,
|
||||
file_wopen,
|
||||
file_close,
|
||||
file_read,
|
||||
file_write
|
||||
},
|
||||
|
||||
/* directory operation */
|
||||
{ dir_stat,
|
||||
dir_make,
|
||||
dir_purge,
|
||||
dir_open,
|
||||
dir_close,
|
||||
dir_read
|
||||
{
|
||||
dir_stat,
|
||||
dir_make,
|
||||
dir_purge,
|
||||
dir_open,
|
||||
dir_close,
|
||||
dir_read
|
||||
},
|
||||
|
||||
/* client connection */
|
||||
{ client_close,
|
||||
client_shutdown,
|
||||
client_recv,
|
||||
client_send,
|
||||
client_sendfile,
|
||||
client_accepted,
|
||||
client_closed
|
||||
{
|
||||
client_close,
|
||||
client_shutdown,
|
||||
client_recv,
|
||||
client_send,
|
||||
client_sendfile,
|
||||
client_accepted,
|
||||
client_closed
|
||||
},
|
||||
|
||||
/* dns */
|
||||
{ dns_open,
|
||||
dns_close,
|
||||
dns_recv,
|
||||
dns_send
|
||||
{
|
||||
dns_open,
|
||||
dns_close,
|
||||
dns_recv,
|
||||
dns_send
|
||||
},
|
||||
|
||||
/* urs */
|
||||
{ urs_open,
|
||||
urs_close,
|
||||
urs_recv,
|
||||
urs_send,
|
||||
urs_prerewrite
|
||||
{
|
||||
urs_open,
|
||||
urs_close,
|
||||
urs_recv,
|
||||
urs_send,
|
||||
urs_prerewrite
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -37,6 +37,7 @@ struct htrd_xtn_t
|
||||
static void free_server_list (qse_httpd_t* httpd);
|
||||
static int perform_client_task (
|
||||
qse_httpd_t* httpd, void* mux, qse_ubi_t handle, int mask, void* cbarg);
|
||||
static void unload_all_modules (qse_httpd_t* httpd);
|
||||
|
||||
qse_http_version_t qse_http_v11 = { 1, 1 };
|
||||
|
||||
@ -89,6 +90,7 @@ void qse_httpd_fini (qse_httpd_t* httpd)
|
||||
{
|
||||
free_server_list (httpd);
|
||||
qse_tmr_close (httpd->tmr);
|
||||
unload_all_modules (httpd);
|
||||
}
|
||||
|
||||
void qse_httpd_stop (qse_httpd_t* httpd)
|
||||
@ -1844,3 +1846,61 @@ void qse_httpd_removetimerevent (qse_httpd_t* httpd, qse_tmr_index_t index)
|
||||
{
|
||||
qse_tmr_remove (httpd->tmr, index);
|
||||
}
|
||||
|
||||
|
||||
static void unload_all_modules (qse_httpd_t* httpd)
|
||||
{
|
||||
qse_httpd_mod_t* mod;
|
||||
|
||||
while (httpd->modlist)
|
||||
{
|
||||
mod = httpd->modlist;
|
||||
httpd->modlist = mod->next;
|
||||
|
||||
/* call fini */
|
||||
httpd->opt.scb.mod.close (httpd, mod);
|
||||
qse_httpd_freemem (httpd, mod);
|
||||
}
|
||||
}
|
||||
|
||||
int qse_httpd_loadmod (qse_httpd_t* httpd, const qse_char_t* name)
|
||||
{
|
||||
qse_httpd_mod_t* mod;
|
||||
qse_size_t name_len;
|
||||
|
||||
/* TODO: no singly linked list speed up */
|
||||
name_len = qse_strlen(name);
|
||||
|
||||
mod = qse_httpd_allocmem (httpd, QSE_SIZEOF(*mod) + name_len + 1);
|
||||
if (mod == QSE_NULL) return -1;
|
||||
|
||||
QSE_MEMSET (mod, 0, QSE_SIZEOF(*mod));
|
||||
mod->name = mod + 1;
|
||||
qse_strcpy (mod->name, name);
|
||||
|
||||
if (httpd->opt.scb.mod.open (httpd, mod) <= -1)
|
||||
{
|
||||
qse_httpd_freemem (httpd, mod);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* TODO: find init and execute it. if it fails, unload it. */
|
||||
|
||||
mod->next = httpd->modlist;
|
||||
httpd->modlist = mod;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
qse_httpd_mod_t* qse_httpd_findmod (qse_httpd_t* httpd, const qse_char_t* name)
|
||||
{
|
||||
qse_httpd_mod_t* mod;
|
||||
|
||||
/* TODO: no sequential search. speed up */
|
||||
for (mod = httpd->modlist; mod; mod = mod->next)
|
||||
{
|
||||
if (qse_strcmp (mod->name, name) == 0) return mod;
|
||||
}
|
||||
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
@ -52,6 +52,8 @@ struct qse_httpd_t
|
||||
qse_mchar_t sname[128]; /* server name for the server header */
|
||||
qse_mchar_t gtbuf[10][64]; /* GMT time buffers */
|
||||
|
||||
qse_httpd_mod_t* modlist;
|
||||
|
||||
struct
|
||||
{
|
||||
struct
|
||||
|
Reference in New Issue
Block a user