mirror of
https://github.com/tuxbox-neutrino/neutrino.git
synced 2025-08-30 00:41:17 +02:00
our current experimental Neutrino branch
git-svn-id: file:///home/bas/coolstream_public_svn/THIRDPARTY/applications/neutrino-experimental@27 e54a6e83-5905-42d5-8d5c-058d10e6a962
This commit is contained in:
494
src/nhttpd/yhttpd.cpp
Normal file
494
src/nhttpd/yhttpd.cpp
Normal file
@@ -0,0 +1,494 @@
|
||||
//=============================================================================
|
||||
// YHTTPD
|
||||
// Main Program
|
||||
//=============================================================================
|
||||
|
||||
// system
|
||||
#include <csignal>
|
||||
#include <unistd.h>
|
||||
#include <cstdlib>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <syscall.h>
|
||||
|
||||
// yhttpd
|
||||
#include "yconfig.h"
|
||||
#include "ylogging.h"
|
||||
#include "yhook.h"
|
||||
|
||||
#ifdef Y_CONFIG_USE_YPARSER
|
||||
#include "mod_yparser.h"
|
||||
static CyParser yParser;
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Setting yhttpd Instance
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "yhttpd.h"
|
||||
static Cyhttpd *yhttpd = NULL;
|
||||
CStringList Cyhttpd::ConfigList;
|
||||
//=============================================================================
|
||||
// HOOKS: Definition & Instance for Hooks, attach/detach Hooks
|
||||
//=============================================================================
|
||||
|
||||
#ifdef Y_CONFIG_USE_AUTHHOOK
|
||||
#include "mod_auth.h"
|
||||
static CmAuth *auth = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef Y_CONFIG_USE_TESTHOOK
|
||||
#include "mod_testhook.h"
|
||||
static CTesthook *testhook = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef Y_CONFIG_USE_WEBLOG
|
||||
#include "mod_weblog.h"
|
||||
static CmWebLog *weblog = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef Y_CONFIG_USE_SENDFILE
|
||||
#include "mod_sendfile.h"
|
||||
static CmodSendfile *mod_sendfile = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef Y_CONFIG_USE_CACHE
|
||||
#include "mod_cache.h"
|
||||
static CmodCache mod_cache; // static instance
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifdef CONFIG_SYSTEM_TUXBOX
|
||||
#include "neutrinoapi.h"
|
||||
static CNeutrinoAPI *NeutrinoAPI;
|
||||
#endif
|
||||
|
||||
//=============================================================================
|
||||
// Main: Main Entry, Command line passing, Webserver Instance creation & Loop
|
||||
//=============================================================================
|
||||
volatile sig_atomic_t Cyhttpd::sig_do_shutdown = 0;
|
||||
#if 0
|
||||
//-----------------------------------------------------------------------------
|
||||
// Signal Handling
|
||||
//-----------------------------------------------------------------------------
|
||||
static void sig_catch(int msignal)
|
||||
{
|
||||
aprintf("!!! SIGNAL !!! :%d!\n",msignal);
|
||||
switch (msignal) {
|
||||
// case SIGTERM:
|
||||
// case SIGINT:
|
||||
|
||||
case SIGPIPE:
|
||||
aprintf("got signal PIPE, nice!\n");
|
||||
break;
|
||||
case SIGHUP:
|
||||
case SIGUSR1:
|
||||
aprintf("got signal HUP/USR1, reading config\n");
|
||||
if (yhttpd)
|
||||
yhttpd->ReadConfig();
|
||||
break;
|
||||
default:
|
||||
aprintf("No special SIGNAL-Handler:%d!\n",msignal);
|
||||
// log_level_printf(1, "Got SIGTERM\n");
|
||||
Cyhttpd::sig_do_shutdown = 1;
|
||||
yhttpd->stop_webserver();
|
||||
delete yhttpd;
|
||||
exit(EXIT_SUCCESS); //FIXME: return to main() some way...
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void yhttpd_reload_config()
|
||||
{
|
||||
if (yhttpd)
|
||||
yhttpd->ReadConfig();
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// Main Entry
|
||||
//-----------------------------------------------------------------------------
|
||||
//int main(int argc, char **argv)
|
||||
void * nhttpd_main_thread(void *data)
|
||||
{
|
||||
//int argc = 1;
|
||||
//char **argv;
|
||||
//bool do_fork = false;
|
||||
|
||||
pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
|
||||
|
||||
aprintf("Webserver %s tid %ld\n", WEBSERVERNAME, syscall(__NR_gettid));
|
||||
yhttpd = new Cyhttpd();
|
||||
|
||||
//CLogging::getInstance()->setDebug(true);
|
||||
//CLogging::getInstance()->LogLevel = 9;
|
||||
if(!yhttpd)
|
||||
{
|
||||
aprintf("Error initializing WebServer\n");
|
||||
return (void *) EXIT_FAILURE;
|
||||
}
|
||||
yhttpd->flag_threading_off = true;
|
||||
#if 0
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
if ((!strncmp(argv[i], "-d", 2)) || (!strncmp(argv[i], "--debug", 7)))
|
||||
{
|
||||
CLogging::getInstance()->setDebug(true);
|
||||
do_fork = false;
|
||||
}
|
||||
else if ((!strncmp(argv[i], "-f", 2)) || (!strncmp(argv[i], "--fork", 6)) || (!strncmp(argv[i], "-nf", 3)))
|
||||
{
|
||||
do_fork = false;
|
||||
}
|
||||
else if ((!strncmp(argv[i], "-h", 2)) || (!strncmp(argv[i], "--help", 6)))
|
||||
{
|
||||
yhttpd->usage(stdout);
|
||||
return (void *) EXIT_SUCCESS;
|
||||
}
|
||||
else if ((!strncmp(argv[i], "-v", 2)) || (!strncmp(argv[i],"--version", 9)))
|
||||
{
|
||||
yhttpd->version(stdout);
|
||||
return (void *) EXIT_SUCCESS;
|
||||
}
|
||||
else if ((!strncmp(argv[i], "-t", 2)) || (!strncmp(argv[i],"--thread-off", 12)))
|
||||
{
|
||||
yhttpd->flag_threading_off = true;
|
||||
}
|
||||
else if ((!strncmp(argv[i], "-l", 2)) )
|
||||
{
|
||||
if(argv[i][2] >= '0' && argv[i][2] <= '9')
|
||||
CLogging::getInstance()->LogLevel = (argv[i][2]-'0');
|
||||
}
|
||||
else
|
||||
{
|
||||
yhttpd->usage(stderr);
|
||||
return (void *) EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
// setup signal catching (subscribing)
|
||||
//signal(SIGPIPE, sig_catch);
|
||||
//signal(SIGINT, sig_catch);
|
||||
//signal(SIGHUP, sig_catch);
|
||||
//signal(SIGUSR1, sig_catch);
|
||||
//signal(SIGTERM, sig_catch);
|
||||
//signal(SIGCLD, SIG_IGN);
|
||||
// signal(SIGALRM, sig_catch);
|
||||
#endif
|
||||
|
||||
yhttpd->hooks_attach();
|
||||
yhttpd->ReadConfig();
|
||||
if(yhttpd->Configure())
|
||||
{
|
||||
// Start Webserver: fork ist if not in debug mode
|
||||
aprintf("Webserver starting...\n");
|
||||
dprintf("Start in Debug-Mode\n"); // non forked debugging loop
|
||||
|
||||
yhttpd->run();
|
||||
}
|
||||
delete yhttpd;
|
||||
|
||||
aprintf("Main end\n");
|
||||
return (void *) EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Class yhttpd
|
||||
//=============================================================================
|
||||
Cyhttpd::Cyhttpd()
|
||||
{
|
||||
webserver = new CWebserver();
|
||||
flag_threading_off = false;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
Cyhttpd::~Cyhttpd()
|
||||
{
|
||||
if(webserver)
|
||||
delete webserver;
|
||||
webserver = NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Change to Root
|
||||
//-----------------------------------------------------------------------------
|
||||
bool Cyhttpd::Configure()
|
||||
{
|
||||
|
||||
if(!getuid()) // you must be root to do that!
|
||||
{
|
||||
// Get user and group data
|
||||
#ifdef Y_CONFIG_FEATURE_HTTPD_USER
|
||||
struct passwd *pwd = NULL;
|
||||
struct group *grp = NULL;
|
||||
std::string username = ConfigList["server.user_name"];
|
||||
std::string groupname= ConfigList["server.group_name"];
|
||||
|
||||
// get user data
|
||||
if(username != "")
|
||||
{
|
||||
if((pwd = getpwnam(username.c_str())) == NULL)
|
||||
{
|
||||
dperror("Dont know user to set uid\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// get group data
|
||||
if(groupname != "")
|
||||
{
|
||||
if((grp = getgrnam(groupname.c_str())) == NULL)
|
||||
{
|
||||
aprintf("Can not get Group-Information. Group: %s\n", groupname.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// change root directory
|
||||
#ifdef Y_CONFIG_FEATURE_CHROOT
|
||||
if(!ConfigList["server.chroot"].empty())
|
||||
{
|
||||
log_level_printf(2, "do chroot to dir:%s\n", ConfigList["server.chroot"].c_str() );
|
||||
// do change Root
|
||||
if(chroot(ConfigList["server.chroot"].c_str()) == -1)
|
||||
{
|
||||
dperror("Change Root failed\n");
|
||||
return false;
|
||||
}
|
||||
// Set Working Dir
|
||||
if(chdir("/") == -1)
|
||||
{
|
||||
dperror("Change Directory to Root failed\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef Y_CONFIG_FEATURE_HTTPD_USER
|
||||
if(username != "" && pwd != NULL && grp != NULL)
|
||||
{
|
||||
log_level_printf(2, "set user and groups\n");
|
||||
|
||||
// drop root privileges
|
||||
setgid(grp->gr_gid);
|
||||
setgroups(0, NULL);
|
||||
// set user group
|
||||
if(groupname != "")
|
||||
initgroups(username.c_str(), grp->gr_gid);
|
||||
// set user
|
||||
if(setuid(pwd->pw_uid) == -1)
|
||||
{
|
||||
dperror("Change User Context failed\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// Main Webserver call
|
||||
//-----------------------------------------------------------------------------
|
||||
void Cyhttpd::run()
|
||||
{
|
||||
if(webserver)
|
||||
{
|
||||
if(flag_threading_off)
|
||||
webserver->is_threading = false;
|
||||
webserver->run();
|
||||
stop_webserver();
|
||||
}
|
||||
else
|
||||
aprintf("Error initializing WebServer\n");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Show Version Text and Number
|
||||
//-----------------------------------------------------------------------------
|
||||
void Cyhttpd::version(FILE *dest)
|
||||
{
|
||||
fprintf(dest, "%s - Webserver v%s\n", HTTPD_NAME, HTTPD_VERSION);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Show Usage
|
||||
//-----------------------------------------------------------------------------
|
||||
void Cyhttpd::usage(FILE *dest)
|
||||
{
|
||||
version(dest);
|
||||
fprintf(dest, "command line parameters:\n");
|
||||
fprintf(dest, "-d, --debug enable debugging code (implies -f)\n");
|
||||
fprintf(dest, "-f, --fork do not fork\n");
|
||||
fprintf(dest, "-h, --help display this text and exit\n\n");
|
||||
fprintf(dest, "-v, --version display version and exit\n");
|
||||
fprintf(dest, "-l<loglevel>, set loglevel (0 .. 9)\n");
|
||||
fprintf(dest, "-t, --thread-off set threading off\n");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Stop WebServer
|
||||
//-----------------------------------------------------------------------------
|
||||
void Cyhttpd::stop_webserver()
|
||||
{
|
||||
aprintf("stop requested......\n");
|
||||
if (webserver) {
|
||||
webserver->stop();
|
||||
hooks_detach();
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// Attach hooks (use hook order carefully)
|
||||
//-----------------------------------------------------------------------------
|
||||
void Cyhttpd::hooks_attach()
|
||||
{
|
||||
#ifdef Y_CONFIG_USE_AUTHHOOK
|
||||
// First Check Authentication
|
||||
auth = new CmAuth();
|
||||
CyhookHandler::attach(auth);
|
||||
#endif
|
||||
|
||||
#ifdef Y_CONFIG_USE_TESTHOOK
|
||||
testhook = new CTesthook();
|
||||
CyhookHandler::attach(testhook);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYSTEM_TUXBOX
|
||||
NeutrinoAPI = new CNeutrinoAPI();
|
||||
CyhookHandler::attach(NeutrinoAPI->NeutrinoYParser);
|
||||
CyhookHandler::attach(NeutrinoAPI->ControlAPI);
|
||||
#else
|
||||
#ifdef Y_CONFIG_USE_YPARSER
|
||||
CyhookHandler::attach(&yParser);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef Y_CONFIG_USE_CACHE
|
||||
CyhookHandler::attach(&mod_cache);
|
||||
#endif
|
||||
|
||||
#ifdef Y_CONFIG_USE_SENDFILE
|
||||
mod_sendfile = new CmodSendfile();
|
||||
CyhookHandler::attach(mod_sendfile);
|
||||
#endif
|
||||
#ifdef Y_CONFIG_USE_WEBLOG
|
||||
weblog = new CmWebLog();
|
||||
CyhookHandler::attach(weblog);
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Detach hooks & Destroy
|
||||
//-----------------------------------------------------------------------------
|
||||
void Cyhttpd::hooks_detach()
|
||||
{
|
||||
#ifdef Y_CONFIG_USE_AUTHHOOK
|
||||
CyhookHandler::detach(auth);
|
||||
delete auth;
|
||||
#endif
|
||||
|
||||
#ifdef Y_CONFIG_USE_TESTHOOK
|
||||
CyhookHandler::detach(testhook);
|
||||
delete testhook;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYSTEM_TUXBOX
|
||||
CyhookHandler::detach(NeutrinoAPI->NeutrinoYParser);
|
||||
#else
|
||||
#ifdef Y_CONFIG_USE_YPARSER
|
||||
CyhookHandler::detach(&yParser);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef Y_CONFIG_USE_CACHE
|
||||
CyhookHandler::detach(&mod_cache);
|
||||
#endif
|
||||
|
||||
#ifdef Y_CONFIG_USE_SENDFILE
|
||||
CyhookHandler::detach(mod_sendfile);
|
||||
#endif
|
||||
|
||||
#ifdef Y_CONFIG_USE_WEBLOG
|
||||
CyhookHandler::detach(weblog);
|
||||
delete weblog;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Read Webserver Configurationfile
|
||||
// Call "Hooks_ReadConfig" so Hooks can read/write own Configuration Values
|
||||
//-----------------------------------------------------------------------------
|
||||
void Cyhttpd::ReadConfig(void)
|
||||
{
|
||||
log_level_printf(3,"ReadConfig Start\n");
|
||||
CConfigFile *Config = new CConfigFile(',');
|
||||
bool have_config = false;
|
||||
if(access(HTTPD_CONFIGFILE,4) == 0)
|
||||
have_config = true;
|
||||
Config->loadConfig(HTTPD_CONFIGFILE);
|
||||
// convert old config files
|
||||
if(have_config)
|
||||
if(Config->getInt32("Port", 0) != 0)
|
||||
{
|
||||
CConfigFile OrgConfig = *Config;
|
||||
Config->clear();
|
||||
|
||||
Config->setInt32("server.log.loglevel", OrgConfig.getInt32("LogLevel", 0));
|
||||
Config->setString("configfile.version", "1");
|
||||
Config->setString("webserver.websites", "WebsiteMain");
|
||||
Config->setBool("webserver.threading", OrgConfig.getBool("THREADS", true));
|
||||
Config->setInt32("WebsiteMain.port",OrgConfig.getInt32("Port", HTTPD_STANDARD_PORT));
|
||||
Config->setString("WebsiteMain.directory", OrgConfig.getString("PrivatDocRoot", PRIVATEDOCUMENTROOT));
|
||||
if(OrgConfig.getString("PublicDocRoot", "") != "")
|
||||
Config->setString("WebsiteMain.override_directory", OrgConfig.getString("PublicDocRoot", PRIVATEDOCUMENTROOT));
|
||||
if(OrgConfig.getString("HostedDocRoot", "") != "")
|
||||
Config->setString("WebsiteMain.special_locations", "/hosted/="+OrgConfig.getString("HostedDocRoot", PRIVATEDOCUMENTROOT));
|
||||
if(OrgConfig.getString("HostedDocRoot", "") != "")
|
||||
Config->setString("Tuxbox.HostedDocumentRoot", OrgConfig.getString("HostedDocRoot", PRIVATEDOCUMENTROOT));
|
||||
// mod_auth
|
||||
Config->setString("mod_auth.username", OrgConfig.getString("AuthUser", AUTHUSER));
|
||||
Config->setString("mod_auth.password", OrgConfig.getString("AuthPassword", AUTHPASSWORD));
|
||||
Config->setString("mod_auth.no_auth_client", OrgConfig.getString("NoAuthClient", ""));
|
||||
Config->setString("mod_auth.authenticate", OrgConfig.getString("Authenticate", "false"));
|
||||
|
||||
Config->setString("mod_sendfile.mime_types", HTTPD_SENDFILE_EXT);
|
||||
|
||||
Config->saveConfig(HTTPD_CONFIGFILE);
|
||||
|
||||
}
|
||||
// configure debugging & logging
|
||||
if(CLogging::getInstance()->LogLevel == 0)
|
||||
CLogging::getInstance()->LogLevel = Config->getInt32("server.log.loglevel", 0);
|
||||
|
||||
// get variables
|
||||
webserver->init(Config->getInt32("WebsiteMain.port", HTTPD_STANDARD_PORT), Config->getBool("webserver.threading", true));
|
||||
// informational use
|
||||
ConfigList["WebsiteMain.port"]= itoa(Config->getInt32("WebsiteMain.port", HTTPD_STANDARD_PORT));
|
||||
ConfigList["webserver.threading"]= Config->getString("webserver.threading", "true");
|
||||
ConfigList["configfile.version"]= Config->getString("configfile.version", "1");
|
||||
ConfigList["server.log.loglevel"]= itoa(Config->getInt32("server.log.loglevel", 0));
|
||||
ConfigList["server.no_keep-alive_ips"]= Config->getString("server.no_keep-alive_ips", "");
|
||||
webserver->conf_no_keep_alive_ips = Config->getStringVector("server.no_keep-alive_ips");
|
||||
|
||||
// MainSite
|
||||
ConfigList["PrivatDocumentRoot"]= Config->getString("WebsiteMain.directory", PRIVATEDOCUMENTROOT);
|
||||
ConfigList["PublicDocumentRoot"]= Config->getString("WebsiteMain.override_directory", PUBLICDOCUMENTROOT);
|
||||
ConfigList["HostedDocumentRoot"]= Config->getString("Tuxbox.HostedDocumentRoot", HOSTEDDOCUMENTROOT);
|
||||
#ifdef Y_CONFIG_USE_OPEN_SSL
|
||||
ConfigList["SSL"] = Config->getString("WebsiteMain.ssl", "false");
|
||||
ConfigList["SSL_pemfile"] = Config->getString("WebsiteMain.ssl_pemfile", SSL_PEMFILE);
|
||||
ConfigList["SSL_CA_file"] = Config->getString("WebsiteMain.ssl_ca_file", SSL_CA_FILE);
|
||||
|
||||
CySocket::SSL_pemfile = ConfigList["SSL_pemfile"];
|
||||
CySocket::SSL_CA_file = ConfigList["SSL_CA_file"];
|
||||
if(ConfigList["SSL"] == "true")
|
||||
CySocket::initSSL();
|
||||
#endif
|
||||
ConfigList["server.user_name"]= Config->getString("server.user_name", "");
|
||||
ConfigList["server.group_name"]= Config->getString("server.group_name", "");
|
||||
ConfigList["server.chroot"]= Config->getString("server.chroot", "");
|
||||
|
||||
|
||||
// Read App specifig settings by Hook
|
||||
CyhookHandler::Hooks_ReadConfig(Config, ConfigList);
|
||||
|
||||
// Save if new defaults are set
|
||||
if (!have_config)
|
||||
Config->saveConfig(HTTPD_CONFIGFILE);
|
||||
log_level_printf(3,"ReadConfig End\n");
|
||||
delete Config;
|
||||
}
|
Reference in New Issue
Block a user