#include <stdio.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include <iostream>
#include "Monitor.h"
#include "SocketServer.h"
#include "MonitorConfiguration.h"
#include "SocketThreadMonitord.h"
#include "MonitorLogging.h"
#ifdef PLUGINS
#include "plugins/mplugin.h"
#include "PluginThread.h"
#endif
#ifdef WIN32
#include <monitord/win32/MonitorService.h>
#define usleep Sleep
#endif
#include "lua.hpp"
using namespace std ;
#ifdef HAVE_LOG4CXX
using namespace log4cxx;
using namespace log4cxx::helpers;
#endif // HAVE_LOG4CXX
void Monitor::CreateSocketServer(MonitorConfiguration *config)
{
static SocketServer socketServer(config,0) ;
static SocketServer fms32ProServer(config,1000) ;
fms32ProServer.m_ServerModus = SocketThread::fms32pro ;
static SocketServer crusaderServer(config,2000) ;
crusaderServer.m_ServerModus = SocketThread::crusader ;
socketServer.Start() ;
fms32ProServer.Start() ;
crusaderServer.Start() ;
}
void Monitor::Initialize (int argc, char *argv[])
{
m_bWantStop=false;
if ( memLockCreate( 12345, & s) < 0) {
ThrowMonitorException("memLockCreate failed") ;
}
m_MonitorConfig.ParseCommandline(argc,argv) ;
m_MonitorConfig.ReadConfiguration(m_MonitorConfig.m_ConfigFile) ;
m_MonitorConfig.ParseCommandline(argc,argv) ;
}
void initFileLogging(MonitorConfiguration *config)
{
bool bConfigureReportingLevel = true;
if (!(config->m_sLogfile=="screen") && !(config->m_sLogfile=="log4cxx"))
{
FILE* pFile = fopen(config->m_sLogfile.c_str(), "a");
Output2FILE::Stream() = pFile;
LOG_INFO("monitord restarted - logging with loglevel " << config->m_sLoglevel)
}
else if (config->m_sLogfile=="log4cxx") {
#ifdef HAVE_LOG4CXX
cout << "using log4cxx for further logging..." << endl;
if (config->m_sLogConfigurationFile=="") {
BasicConfigurator::configure();
}
else {
cout << "using log4cxx configuration file '" << config->m_sLogConfigurationFile << "'" << endl;
PropertyConfigurator::configure(config->m_sLogConfigurationFile);
}
bConfigureReportingLevel = false;
#else
LOG_ERROR("log4cxx can not be used. monitord is not compiled --with-log4cxx")
#endif
}
else {
LOG_INFO("Logging with loglevel " << config->m_sLoglevel)
}
if (bConfigureReportingLevel) {
FILELog::ReportingLevel() = FILELog::FromString(config->m_sLoglevel);
}
}
int main(int argc, char** argv)
{
Monitor m_monitor;
try {
m_monitor.Initialize (argc, argv);
initFileLogging(&m_monitor.m_MonitorConfig) ;
m_monitor.m_SignalStopped = new MonitorBlockingSignal();
GlobalDispatcher = new MonitorResultsDispatcher();
#ifdef WIN32
/**
* Soll als Dienst ausgef�hrt werden ?
*/
try
{
if (m_monitor.m_MonitorConfig.m_service_uninstall == true) {
LOG_INFO(PACKAGE_NAME << " wird als Dienst entfernt.")
/* uninstall service from service control daemon */
MonitorService *m_MonitorService = new MonitorService(&m_monitor);
m_MonitorService->UnInstallService();
delete m_MonitorService;
} else if (m_monitor.m_MonitorConfig.m_service_install == true) {
LOG_INFO(PACKAGE_NAME << " wird als Dienst eingerichtet.")
/* install service in service control daemon */
MonitorService *m_MonitorService = new MonitorService(&m_monitor);
m_MonitorService->InstallService();
delete m_MonitorService ;
} else {
if (m_monitor.m_MonitorConfig.m_service_run == true) {
LOG_INFO(PACKAGE_NAME << " startet als Dienst.")
/* running monitor as windows service application */
MonitorService *m_MonitorService = new MonitorService(&m_monitor);
m_MonitorService->Run ();
delete m_MonitorService ;
} else {
#endif
/* running monitor as command line application */
LOG_INFO(PACKAGE_STRING << " READY" )
cout << PACKAGE_STRING << " running...\r\n";
if (!(m_monitor.m_MonitorConfig.m_sLogfile == "screen") && !(m_monitor.m_MonitorConfig.m_sLogfile == "log4cxx")) {
cout << "Logging in Logfiles, keine weiteren Ausgaben hier." << endl;
}
m_monitor.MainLoop ();
#ifdef WIN32
}
}
} catch (MonitorServiceException(err))
{
// FIXME: Dienste koennen nicht auf die Console schreiben, da siehe
// unsichtbar im Hintergrund laufen
LOG_ERROR(err.what() )
}
#endif
} catch (MonitorException(err))
{
LOG_ERROR(err.what() )
}
}
void Monitor::MainLoop()
{
// Soundkarte initialisieren
InitSndCard() ;
/********************************************************/
static SocketServer socketServer(&m_MonitorConfig,m_MonitorConfig.m_socketFilterFileName ,0) ;
socketServer.Start() ;
LOG_INFO("monitord socketserver started" )
static SocketServer fms32ProServer(&m_MonitorConfig,m_MonitorConfig.m_socketFilterFileName ,1000) ;
fms32ProServer.m_ServerModus=SocketThread::fms32pro ;
fms32ProServer.Start() ;
LOG_INFO("fms32pro socketserver started" )
static SocketServer crusaderServer(&m_MonitorConfig,m_MonitorConfig.m_socketFilterFileName ,2000) ;
crusaderServer.m_ServerModus=SocketThread::crusader ;
crusaderServer.Start() ;
LOG_INFO("crusader socketserver started" )
/*******************************************************/
#ifdef PLUGINS
//GetPluginsManager().loadPlugin("plugins/.libs/libmplugin_mysql-0.dll",NULL);
GetPluginsManager().loadScriptFilter(m_MonitorConfig.m_pluginFilterFileName) ;
GetPluginsManager().loadPluginsFromConfigNode(&m_MonitorConfig.m_configDataPlugins);
LOG_DEBUG("PluginManager started" )
#endif
/*********************************************************/
while (!m_bWantStop)
{
/**
* Wer sich fragt, wo eigentlich denn die Arbeit gemacht wird:
* Die drei SocketServer sind eigenstaendige Threads. Die bedienen
* die TCP/IP Verbindungen und laufen unabhaegig.
*
* Die eigentliche (Ton) Auswertung erfolgt in jeweils einem Thread
* pro Soundkarte. Diese Threads werden im InitSndCard gestartet.
*
* Dann gibt es noch den GlobalDispatcher. Er ist auch ein eigenstaendiger
* Thread. Er wird von dem Auswerten mit ResultSets versorgt. Die Auswerter
* haben damit Ihren Teil erledigt.
* Der Dispatcher verteilt dann die Results an alle Sockets und Plugins (ohne die
* Auswerter zu blockieren)
*
*/
usleep(100);
// Wie man sieht: hier gibt es im Moment nichts zu tun :-
}
LOG_INFO(PACKAGE_NAME << " shutting down..." )
StopSndCard() ;
LOG_INFO("stopping socketserver monitord")
socketServer.m_bWantStop=true ;
LOG_INFO("stopping socketserver FMS32")
fms32ProServer.m_bWantStop=true ;
LOG_INFO("stopping socketserver Crusader")
crusaderServer.m_bWantStop=true ;
usleep(1000) ;
m_SignalStopped->SetSignal() ;
usleep(500) ;
LOG_INFO("all done. " << PACKAGE_NAME << " exiting")
}
void Monitor::InitSndCard()
{
unsigned int cardnum;
for (cardnum=0;cardnum<4;cardnum++)
{
if (m_MonitorConfig.m_sndConfig[cardnum].iAktiv==1)
{
m_sndIn[cardnum] = new CSndPipe();
LOG_INFO("starting soundcard #" << cardnum)
m_sndIn[cardnum]->initDecoderModules(cardnum,&m_MonitorConfig) ;
m_sndIn[cardnum]->m_SoundIn.setDevice(m_MonitorConfig.m_sndConfig[cardnum].sDevice, 22050) ;
#ifdef PLUGINS
m_sndIn[cardnum]->loadPlugins(&m_MonitorConfig, m_MonitorConfig.m_sndConfig[cardnum].configChannel[0],m_MonitorConfig.m_sndConfig[cardnum].configChannel[1]) ;
#endif
m_sndIn[cardnum]->m_SoundIn.Start() ;
LOG_INFO("Soundcard #" << cardnum << " started - complete" )
}
}
}
void Monitor::StopSndCard()
{
unsigned int cardnum;
for (cardnum=0;cardnum<4;cardnum++)
{
if (m_MonitorConfig.m_sndConfig[cardnum].iAktiv==1)
{
LOG_INFO("stopping soundcard# " << cardnum )
m_sndIn[cardnum]->m_SoundIn.Stop() ;
LOG_INFO("soundcard #" << cardnum<< " halted." )
delete m_sndIn[cardnum];
}
}
}