272 lines
6.1 KiB
C
272 lines
6.1 KiB
C
|
|
#include <qse/net/httpd.h>
|
|
#include <qse/cmn/stdio.h>
|
|
#include <qse/cmn/main.h>
|
|
#include <qse/cmn/str.h>
|
|
#include <qse/cmn/mem.h>
|
|
#include <qse/cmn/mbwc.h>
|
|
#include <qse/cmn/time.h>
|
|
|
|
#include <signal.h>
|
|
#include <locale.h>
|
|
|
|
#if defined(_WIN32)
|
|
# include <windows.h>
|
|
# include <tchar.h>
|
|
# include <process.h>
|
|
#elif defined(__OS2__)
|
|
# define INCL_DOSPROCESS
|
|
# define INCL_DOSEXCEPTIONS
|
|
# define INCL_ERRORS
|
|
# include <os2.h>
|
|
#elif defined(__DOS__)
|
|
# include <dos.h>
|
|
#else
|
|
# include <unistd.h>
|
|
# include <errno.h>
|
|
#endif
|
|
|
|
|
|
#if defined(HAVE_SSL)
|
|
# include <openssl/ssl.h>
|
|
# include <openssl/err.h>
|
|
# include <openssl/engine.h>
|
|
#endif
|
|
|
|
/* --------------------------------------------------------------------- */
|
|
|
|
static qse_httpd_t* g_httpd = QSE_NULL;
|
|
|
|
static void sigint (int sig)
|
|
{
|
|
if (g_httpd) qse_httpd_stop (g_httpd);
|
|
}
|
|
|
|
/* --------------------------------------------------------------------- */
|
|
|
|
typedef struct server_xtn_t server_xtn_t;
|
|
struct server_xtn_t
|
|
{
|
|
int tproxy;
|
|
qse_httpd_server_cbstd_t* orgcbstd;
|
|
};
|
|
|
|
static int makersrc (
|
|
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_htre_t* req, qse_httpd_rsrc_t* rsrc)
|
|
{
|
|
server_xtn_t* server_xtn;
|
|
|
|
server_xtn = qse_httpd_getserverxtnstd (httpd, client->server);
|
|
|
|
if (server_xtn->tproxy)
|
|
{
|
|
if (qse_nwadequal(&client->orgdst_addr, &client->local_addr)) /* both equal and error */
|
|
{
|
|
/* TODO: implement a better check that the
|
|
* destination is not one of the local addresses */
|
|
|
|
rsrc->type = QSE_HTTPD_RSRC_ERROR;
|
|
rsrc->u.error.code = 500;
|
|
}
|
|
else
|
|
{
|
|
rsrc->type = QSE_HTTPD_RSRC_PROXY;
|
|
rsrc->u.proxy.dst = client->orgdst_addr;
|
|
rsrc->u.proxy.src = client->remote_addr;
|
|
|
|
if (rsrc->u.proxy.src.type == QSE_NWAD_IN4)
|
|
rsrc->u.proxy.src.u.in4.port = 0; /* reset the port to 0. */
|
|
else if (rsrc->u.proxy.src.type == QSE_NWAD_IN6)
|
|
rsrc->u.proxy.src.u.in6.port = 0; /* reset the port to 0. */
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
#if 0
|
|
if (server_xtn->orgcbstd->makersrc (httpd, client, req, rsrc) <= -1) return -1;
|
|
if (rsrc->type == QSE_HTTPD_RSRC_DIR)
|
|
{
|
|
/* no directory listing - */
|
|
if (server_xtn->orgcbstd->freersrc)
|
|
server_xtn->orgcbstd->freersrc (httpd, client, req, rsrc);
|
|
rsrc->type = QSE_HTTPD_RSRC_ERROR;
|
|
rsrc->u.error.code = 403;
|
|
}
|
|
return 0;
|
|
#endif
|
|
return server_xtn->orgcbstd->makersrc (httpd, client, req, rsrc);
|
|
}
|
|
}
|
|
|
|
static void freersrc (qse_httpd_t* httpd, qse_httpd_client_t* client, qse_htre_t* req, qse_httpd_rsrc_t* rsrc)
|
|
{
|
|
server_xtn_t* server_xtn;
|
|
|
|
server_xtn = qse_httpd_getserverxtnstd (httpd, client->server);
|
|
|
|
if (server_xtn->tproxy)
|
|
{
|
|
/* nothing to do */
|
|
}
|
|
else
|
|
{
|
|
if (server_xtn->orgcbstd->freersrc)
|
|
server_xtn->orgcbstd->freersrc (httpd, client, req, rsrc);
|
|
}
|
|
}
|
|
|
|
/* --------------------------------------------------------------------- */
|
|
|
|
static qse_httpd_server_t* attach_server (
|
|
qse_httpd_t* httpd, qse_char_t* uri, qse_httpd_server_cbstd_t* cbstd)
|
|
{
|
|
qse_httpd_server_t* server;
|
|
qse_httpd_server_xtn_t* server_xtn_inner;
|
|
server_xtn_t* server_xtn;
|
|
int tproxy = 0;
|
|
|
|
static qse_httpd_server_idxstd_t idxstd[] =
|
|
{
|
|
{ QSE_MT("index.cgi") },
|
|
{ QSE_MT("index.html") },
|
|
{ QSE_NULL }
|
|
};
|
|
|
|
if (qse_strzcasecmp (uri, QSE_T("http-tproxy://"), 14) == 0)
|
|
{
|
|
tproxy = 1;
|
|
qse_strcpy (&uri[4], &uri[11]);
|
|
}
|
|
|
|
server = qse_httpd_attachserverstd (
|
|
httpd, uri, QSE_NULL, QSE_SIZEOF(server_xtn_t));
|
|
if (server == QSE_NULL) return QSE_NULL;
|
|
|
|
/* qse_httpd_getserverxtnstd() returns the pointer to
|
|
* the extension space requested above, of the size
|
|
* QSE_SIZEOF(server_xtn_t) */
|
|
server_xtn = qse_httpd_getserverxtnstd (httpd, server);
|
|
server_xtn->tproxy = tproxy;
|
|
|
|
/* qse_httpd_getserverxtn() returns the pointer to the
|
|
* extension space created by qse_httpd_attachserverstd()
|
|
* internally.
|
|
*/
|
|
server_xtn_inner = qse_httpd_getserverxtn (httpd, server);
|
|
/* remember the callback set in qse_httpd_attachserverstd() */
|
|
server_xtn->orgcbstd = server_xtn_inner->cbstd;
|
|
/* override it with a new callback for chaining */
|
|
server_xtn_inner->cbstd = cbstd;
|
|
server_xtn_inner->idxstd = idxstd; /* override index file list */
|
|
|
|
return server;
|
|
}
|
|
/* --------------------------------------------------------------------- */
|
|
static int httpd_main (int argc, qse_char_t* argv[])
|
|
{
|
|
qse_httpd_t* httpd = QSE_NULL;
|
|
int ret = -1, i;
|
|
static qse_httpd_server_cbstd_t cbstd = { makersrc, freersrc };
|
|
|
|
if (argc <= 1)
|
|
{
|
|
qse_fprintf (QSE_STDERR, QSE_T("Usage: %s <listener_uri> ...\n"), argv[0]);
|
|
goto oops;
|
|
}
|
|
|
|
httpd = qse_httpd_openstd (QSE_SIZEOF(server_xtn_t));
|
|
if (httpd == QSE_NULL)
|
|
{
|
|
qse_fprintf (QSE_STDERR, QSE_T("Cannot open httpd\n"));
|
|
goto oops;
|
|
}
|
|
|
|
for (i = 1; i < argc; i++)
|
|
{
|
|
if (attach_server (httpd, argv[i], &cbstd) == QSE_NULL)
|
|
{
|
|
qse_fprintf (QSE_STDERR,
|
|
QSE_T("Failed to add httpd listener - %s\n"), argv[i]);
|
|
goto oops;
|
|
}
|
|
}
|
|
|
|
g_httpd = httpd;
|
|
signal (SIGINT, sigint);
|
|
signal (SIGPIPE, SIG_IGN);
|
|
|
|
qse_httpd_setname (httpd, QSE_MT("httpd02/qse 1.0"));
|
|
|
|
qse_httpd_setoption (httpd, QSE_HTTPD_CGIERRTONUL);
|
|
ret = qse_httpd_loopstd (httpd, 10000);
|
|
|
|
signal (SIGINT, SIG_DFL);
|
|
signal (SIGPIPE, SIG_DFL);
|
|
g_httpd = QSE_NULL;
|
|
|
|
if (ret <= -1) qse_fprintf (QSE_STDERR, QSE_T("Httpd error\n"));
|
|
|
|
oops:
|
|
if (httpd) qse_httpd_close (httpd);
|
|
return ret;
|
|
}
|
|
|
|
int qse_main (int argc, qse_achar_t* argv[])
|
|
{
|
|
int ret;
|
|
|
|
#if defined(_WIN32)
|
|
char locale[100];
|
|
UINT codepage;
|
|
WSADATA wsadata;
|
|
|
|
codepage = GetConsoleOutputCP();
|
|
if (codepage == CP_UTF8)
|
|
{
|
|
/*SetConsoleOUtputCP (CP_UTF8);*/
|
|
qse_setdflcmgrbyid (QSE_CMGR_UTF8);
|
|
}
|
|
else
|
|
{
|
|
sprintf (locale, ".%u", (unsigned int)codepage);
|
|
setlocale (LC_ALL, locale);
|
|
qse_setdflcmgrbyid (QSE_CMGR_SLMB);
|
|
}
|
|
|
|
|
|
if (WSAStartup (MAKEWORD(2,0), &wsadata) != 0)
|
|
{
|
|
qse_fprintf (QSE_STDERR, QSE_T("Failed to start up winsock\n"));
|
|
return -1;
|
|
}
|
|
|
|
#else
|
|
setlocale (LC_ALL, "");
|
|
qse_setdflcmgrbyid (QSE_CMGR_SLMB);
|
|
#endif
|
|
|
|
#if defined(HAVE_SSL)
|
|
SSL_load_error_strings ();
|
|
SSL_library_init ();
|
|
#endif
|
|
|
|
ret = qse_runmain (argc, argv, httpd_main);
|
|
|
|
#if defined(HAVE_SSL)
|
|
/*ERR_remove_state ();*/
|
|
ENGINE_cleanup ();
|
|
ERR_free_strings ();
|
|
EVP_cleanup ();
|
|
CRYPTO_cleanup_all_ex_data ();
|
|
#endif
|
|
|
|
#if defined(_WIN32)
|
|
WSACleanup ();
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|