www.pudn.com > vls-0.5.6.rar > application.cpp
/******************************************************************************* * application.cpp: Application class *------------------------------------------------------------------------------- * (c)1999-2004 VideoLAN * $Id: application.cpp,v 1.17.4.6 2004/01/10 21:54:57 alexis Exp $ * * Authors: Benoit Steiner* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * *------------------------------------------------------------------------------- * The C_Application class provides some core mecanisms for applications, such * as a global logging service * *******************************************************************************/ #define COPYRIGHT \ "VideoLAN Server - version 0.5.5 - (c)1996-2004 VideoLAN\n" #define VERSION \ COPYRIGHT \ "\n" \ "This program comes with NO WARRANTY, to the extent permitted by law.\n" \ "You may redistribute it under the terms of the GNU General Public " \ "License;\n" \ "see the file named COPYING for details.\n" \ "Written by the VideoLAN team at Ecole Centrale, Paris.\n" #define HELP \ COPYRIGHT \ "\n" \ " vls [options] target\n" \ " \n" \ " options: \n" \ " --version display version and exit\n" \ " -v --verbose verbosity (v, vv, vvv)\n" \ " -h --help display this help\n" \ " -d --destination output \n" \ " -f --file configuration file\n" \ " -t --ttl ttl value\n" \ " -l --loop looping at end of program\n" \ " --log log to \n" \ " \n" \ " target:\n" \ " dvd: for streaming from a dvd\n" \ " dvd: for streaming from a dvd stored on hard drive\n" \ " file: for streaming from a file\n" \ " dvb: for streaming from a dvb channel\n" \ " udp: for streaming in udp to ip \n" \ " rtp: for streaming in rtp to ip \n" \ " file: for dumping output to filename \n" //------------------------------------------------------------------------------ // Preamble //------------------------------------------------------------------------------ #include "defs.h" #include #include #include #ifdef HAVE_OPENDIR #include #endif #include #include #ifdef SYSLOG #include #endif #ifdef HAVE_GETOPT_H # include /* getopt() */ #else # ifdef WIN32 # define __STDC__ 1 # endif # include "../extras/getopt.h" #endif #include "common.h" #include "debug.h" #include "reflect.h" #include "serialization.h" #include "string.h" #include "stack.h" #include "vector.h" #include "hashtable.h" #include "buffers.h" #include "exception.h" #include "file.h" #include "stream.h" #include "parsers.h" #include "settings.h" #include "log.h" #include "library.h" #include "module.h" #include "application.h" #include "stack.cpp" #include "vector.cpp" #include "hashtable.cpp" #include "library.cpp" //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ C_Application* C_Application::s_pApplication = NULL; //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ C_Application::C_Application(const C_String& strName) : m_strName(strName) { ASSERT(s_pApplication == NULL); s_pApplication = this; m_hLog = NULL; m_pModuleManager = NULL; m_bOnStop = false; m_iLogFlags = LOG_ERRORMSG; } //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ C_Application::~C_Application() { ASSERT(this == s_pApplication); s_pApplication = NULL; delete m_pModuleManager; } //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ int C_Application::Init(int iArgc, char* paArg[]) { // Retrieve global configuration from cmd line and cfg file // Shortly, this step will build a properties table int iRc = RetrieveConfig(iArgc, paArg); // Init the logger if(!iRc) { C_String strLogFileSetting = "Global.LogFile"; C_String strLogFile = GetSetting(strLogFileSetting, ""); if (strLogFile != "") { iRc |= m_cLog.Init(strLogFile); m_iLogFlags |= LOG_FILE; } } // Check if System Logging is enabled in the vls.cfg C_String strSystemLog = GetSetting("Global.SystemLog", "disable"); if (strSystemLog == "enable") m_iLogFlags |= LOG_SYSTEM; // Check if screen Logging is enabled in the vls.cfg C_String strScrLog = GetSetting("Global.ScreenLog", "enable"); if (strScrLog == "enable") m_iLogFlags |= LOG_SCR; // Register the application object by the logger if(!iRc) { m_hLog = StartLog(m_strName, m_iLogFlags ); if(!m_hLog) iRc = GEN_ERR; } // First install the signal handler if(!iRc) iRc = InstallSigHandler(); // Create the module manager m_pModuleManager = new C_ModuleManager(m_hLog); // Do application specific initialisations if(!iRc) iRc = OnAppInit(); return iRc; } //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ int C_Application::Run() { return OnAppRun(); } //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ int C_Application::Stop() { if(!m_bOnStop) { m_bOnStop = true; return OnAppExit(); } else return GEN_ERR; } //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ int C_Application::Destroy() { int iRc = OnAppDestroy(); if(!iRc) { if(m_hLog) StopLog(m_hLog); iRc = m_cLog.End(); } return iRc; } //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ handle C_Application::StartLog(const C_String& strClientDescr, u8 iFlags) { handle hLog = m_cLog.Register(strClientDescr, iFlags); ASSERT(hLog); // Init the syslog if (iFlags & LOG_SYSTEM) { #ifdef SYSLOG openlog("vls", LOG_NOWAIT | LOG_NDELAY | LOG_PID, LOG_USER); #endif } return hLog; } //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ void C_Application::StopLog(handle hLog) { ASSERT(hLog); // close the syslog if (m_iLogFlags & LOG_SYSTEM) { #ifdef SYSLOG closelog(); #endif } m_cLog.Unregister(hLog); } //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ void C_Application::LogMsg(handle hLog, int iLevel, const C_String& strMsg) { if(hLog) { // Use the given handle to log m_cLog.Append(hLog, iLevel, strMsg); } else { // Use the application handle to log m_cLog.Append(m_hLog, iLevel, strMsg); } } //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ int C_Application::InstallSigHandler() { int iRc = NO_ERR; #ifdef HAVE_SIGACTION sigset_t sSigSet; sigemptyset(&sSigSet); struct sigaction sSigAction; sSigAction.sa_mask = sSigSet; sSigAction.sa_flags = 0; //sSigAction.sa_restorer = NULL; sSigAction.sa_handler = SignalHandler; if(sigaction(SIGHUP, &sSigAction, NULL) != 0) { Log(m_hLog, LOG_ERROR, "Could not install handler for signal SIG_HUP"); iRc |= 1; } sSigAction.sa_handler = SignalHandler; if(sigaction(SIGINT, &sSigAction, NULL) != 0) { Log(m_hLog, LOG_ERROR, "Could not install handler for signal SIG_INT"); iRc |= 1; } sSigAction.sa_handler = SignalHandler; if(sigaction(SIGQUIT, &sSigAction, NULL) != 0) { Log(m_hLog, LOG_ERROR, "Could not install handler for signal SIG_QUIT"); iRc |= 1; } sSigAction.sa_handler = SignalHandler; if(sigaction(SIGPIPE, &sSigAction, NULL) != 0) { Log(m_hLog, LOG_ERROR, "Could not install handler for signal SIG_PIPE"); iRc |= 1; } sSigAction.sa_handler = SignalHandler; if(sigaction(SIGURG, &sSigAction, NULL) != 0) { Log(m_hLog, LOG_ERROR, "Could not install handler for signal SIG_URG"); iRc |= 1; } // Don't catch the signal if we are in debug mode unless we wouldn't get a core file #ifndef DEBUG sSigAction.sa_handler = SignalHandler; if(sigaction(SIGSEGV, &sSigAction, NULL) != 0) { Log(m_hLog, LOG_ERROR, "Could not install handler for signal SIG_SEGV"); iRc |= 1; } #endif sSigAction.sa_handler = SignalHandler; if(sigaction(SIGTERM, &sSigAction, NULL) != 0) { Log(m_hLog, LOG_ERROR, "Could not install handler for signal SIG_TERM"); iRc |= 1; } #endif return iRc; } //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ int C_Application::RetrieveConfig(int iArgc, char* paArg[]) { C_String strCfgFile; C_String strDest; int iRc = NO_ERR; int iCommandline=0; int opt; C_String strName = m_strName.ToLower() + ".cfg"; #ifndef _WIN32 strCfgFile = CONFIG_PATH "/" + strName; #else strCfgFile = strName; #endif static const struct option longopts[]={ {"verbose", 0 , 0 , 'v'}, {"help", 0 , 0, 'h'}, {"file", 1, 0, 'f'}, {"version", 0, 0, 129}, {"destination", 1, 0,'d'}, {"ttl", 1, 0, 't'}, {"loop", 0,0, 'l'}, {"log", 1, 0, 130}, {0,0,0,0} }; static char shortopts[]="f:d:hvt:l"; //Parse command line options while((opt = getopt_long(iArgc, paArg, shortopts, longopts, 0)) != EOF) { switch(opt) { case 'v': if(m_iLogFlags&LOG_NOTEMSG) m_iLogFlags |= LOG_DBGMSG; if(m_iLogFlags&LOG_WARNMSG) m_iLogFlags |= LOG_NOTEMSG; if(m_iLogFlags&LOG_ERRORMSG) m_iLogFlags |= LOG_WARNMSG; break; case 129: printf(VERSION); exit(0); break; case 'f': strCfgFile = optarg; break; case 'h': printf(HELP); exit(0); default: if(optarg!=NULL) m_cSettings.AddCmdLineSetting(opt,C_String(optarg)); else m_cSettings.AddCmdLineSetting(opt,""); break; } } if(optind m_hLog; switch(iSignal) { case SIGHUP: { Log(hLog, LOG_WARN, "Received SIGHUP: Hangup detected"); break; } case SIGINT: { Log(hLog, LOG_WARN, "Received SIGINT: Interrupt from keyboard, launching shutdown sequence..."); pApp->Stop(); break; } case SIGQUIT: { Log(hLog, LOG_WARN, "Received SIGQUIT: Quit from keyboard, launching shutdown sequence..."); pApp->Stop(); break; } case SIGTERM: { Log(hLog, LOG_WARN, "Received SIGTERM: Software termination signal, launching shutdown sequence..."); pApp->Stop(); break; } case SIGSEGV: { Log(hLog, LOG_WARN, "Received SIGSEGV: Segmentation Violation, exiting..."); exit(1); break; } case SIGPIPE: { // This signal is sent upon attempt to write on a broken stream // (such as a dead socket) Log(hLog, LOG_WARN, "Received SIGPIPE: Unexpected Broken Pipe encountered"); break; } case SIGURG: { // This signal is sent when AOB data is received on a TCP connection Log(hLog, LOG_NOTE, "Received SIGURG: unexpected AOB data received"); break; } default: { Log(hLog, LOG_NOTE, "Received signal " + iSignal); break; } } #endif }