Patch level : 10.0
Files correlati : lurch.exe Ricompilazione Demo : [ ] Commento : Questo maggiordomo non solo e' in grado di ammazzare la servitu' oziosa... ma anche di risuscitarla quanto questa si suicida! git-svn-id: svn://10.65.10.50/trunk@19979 c028cbd2-c16b-5b4b-a496-9718f37d4682
This commit is contained in:
parent
28fb3889c5
commit
46d30d0ca2
@ -15,7 +15,7 @@
|
|||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// headers
|
// headers
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
#include <wx/wxprec.h>
|
||||||
#include "baseserv.h"
|
#include "baseserv.h"
|
||||||
|
|
||||||
#include <wx/config.h>
|
#include <wx/config.h>
|
||||||
@ -25,12 +25,10 @@
|
|||||||
#include <wx/mstream.h>
|
#include <wx/mstream.h>
|
||||||
#include <wx/sckstrm.h>
|
#include <wx/sckstrm.h>
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifndef __WXMSW__
|
||||||
#include <wx/fileconf.h>
|
#include <wx/fileconf.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <wx/app.h>
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
// Utilities
|
// Utilities
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
@ -589,6 +587,11 @@ const wxString& TBaseServerApp::GetConfigName() const
|
|||||||
|
|
||||||
void TBaseServerApp::SetConfigString(const wxChar* key, const wxChar* val, const wxChar* app) const
|
void TBaseServerApp::SetConfigString(const wxChar* key, const wxChar* val, const wxChar* app) const
|
||||||
{
|
{
|
||||||
|
#ifdef __WXMSW__
|
||||||
|
if (app == NULL || *app == '\0')
|
||||||
|
app = GetAppName();
|
||||||
|
::WritePrivateProfileString(app, key, val, GetConfigName());
|
||||||
|
#else
|
||||||
wxFileConfig ini("", "", GetConfigName(), "", wxCONFIG_USE_LOCAL_FILE | wxCONFIG_USE_RELATIVE_PATH);
|
wxFileConfig ini("", "", GetConfigName(), "", wxCONFIG_USE_LOCAL_FILE | wxCONFIG_USE_RELATIVE_PATH);
|
||||||
wxString str;
|
wxString str;
|
||||||
if (app == NULL || *app == '\0')
|
if (app == NULL || *app == '\0')
|
||||||
@ -596,6 +599,7 @@ void TBaseServerApp::SetConfigString(const wxChar* key, const wxChar* val, const
|
|||||||
str << '/' << app;
|
str << '/' << app;
|
||||||
ini.SetPath(str);
|
ini.SetPath(str);
|
||||||
ini.Write(key, val);
|
ini.Write(key, val);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void TBaseServerApp::SetConfigInt(const wxChar* key, int val, const wxChar* app) const
|
void TBaseServerApp::SetConfigInt(const wxChar* key, int val, const wxChar* app) const
|
||||||
@ -606,13 +610,19 @@ void TBaseServerApp::SetConfigInt(const wxChar* key, int val, const wxChar* app)
|
|||||||
|
|
||||||
wxString TBaseServerApp::GetConfigString(const wxChar* key, const wxChar* def, const wxChar* app) const
|
wxString TBaseServerApp::GetConfigString(const wxChar* key, const wxChar* def, const wxChar* app) const
|
||||||
{
|
{
|
||||||
wxFileConfig ini("", "", GetConfigName(), "", wxCONFIG_USE_LOCAL_FILE | wxCONFIG_USE_RELATIVE_PATH);
|
|
||||||
wxString str;
|
wxString str;
|
||||||
if (app == NULL || *app == '\0')
|
if (app == NULL || *app == '\0')
|
||||||
app = GetAppName();
|
app = GetAppName();
|
||||||
|
#ifdef __WXMSW__
|
||||||
|
wxChar value[512]; memset(value, 0, sizeof(value));
|
||||||
|
const int len = ::GetPrivateProfileString(app, key, def, value, sizeof(value)-1, GetConfigName());
|
||||||
|
str = len <= 0 ? def : value;
|
||||||
|
#else
|
||||||
|
wxFileConfig ini("", "", GetConfigName(), "", wxCONFIG_USE_LOCAL_FILE | wxCONFIG_USE_RELATIVE_PATH);
|
||||||
str << '/' << app;
|
str << '/' << app;
|
||||||
ini.SetPath(str);
|
ini.SetPath(str);
|
||||||
ini.Read(key, &str, def);
|
ini.Read(key, &str, def);
|
||||||
|
#endif
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
#include <wx/wxprec.h>
|
#ifndef __BASESERV_H__
|
||||||
|
#define __BASESERV_H__
|
||||||
|
|
||||||
|
#include <wx/app.h>
|
||||||
#include <wx/datetime.h>
|
#include <wx/datetime.h>
|
||||||
|
#include <wx/hash.h>
|
||||||
#include <wx/snglinst.h>
|
#include <wx/snglinst.h>
|
||||||
#include <wx/socket.h>
|
#include <wx/socket.h>
|
||||||
#include <wx/wfstream.h>
|
#include <wx/wfstream.h>
|
||||||
#ifdef LINUX
|
|
||||||
#include <wx/app.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "xml.h"
|
#include "xml.h"
|
||||||
|
|
||||||
@ -150,3 +151,5 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
TBaseServerApp& GetServerApp();
|
TBaseServerApp& GetServerApp();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
318
server/lurch.cpp
318
server/lurch.cpp
@ -3,56 +3,36 @@
|
|||||||
#include <wx/config.h>
|
#include <wx/config.h>
|
||||||
#include <wx/filename.h>
|
#include <wx/filename.h>
|
||||||
#include <wx/process.h>
|
#include <wx/process.h>
|
||||||
#ifdef WIN32
|
#include <wx/timer.h>
|
||||||
#include <wx/fileconf.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
|
||||||
// TProcess declaration
|
|
||||||
///////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
class TLurchServer; //segnaposto della TLurchServer che serve alla TProcess
|
|
||||||
|
|
||||||
class TProcess : public wxProcess
|
|
||||||
{
|
|
||||||
TLurchServer* m_pLurch;
|
|
||||||
wxString m_strApp;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void OnTerminate(int pid, int status);
|
|
||||||
|
|
||||||
public:
|
|
||||||
void ForcePid(int pid) { SetPid(pid); }
|
|
||||||
TProcess(TLurchServer* pLurch, const wxString& strApp) : m_pLurch(pLurch), m_strApp(strApp) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
// TLurchServer declaration
|
// TLurchServer declaration
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//classe TProcessHashMap derivata da wxHashMap (è una specie di assocarray!)
|
//classe TProcessHashMap derivata da wxHashMap (è l'equivalente di TAssoc_array)
|
||||||
WX_DECLARE_HASH_MAP( wxString, wxProcess*, wxStringHash, wxStringEqual, TProcessHashMap );
|
WX_DECLARE_HASH_MAP( wxString, wxProcess*, wxStringHash, wxStringEqual, TProcessHashMap );
|
||||||
|
|
||||||
|
|
||||||
class TLurchServer : public TBaseServerApp
|
class TLurchServer : public TBaseServerApp
|
||||||
{
|
{
|
||||||
TProcessHashMap m_ProcMap;
|
TProcessHashMap m_hmProcMap;
|
||||||
wxTimer m_Timer;
|
wxSemaphore m_Semaphore;
|
||||||
int m_nFreq;
|
wxTimer m_PingTimer;
|
||||||
|
wxArrayString m_aServers;
|
||||||
|
|
||||||
DECLARE_EVENT_TABLE();
|
DECLARE_EVENT_TABLE();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual const wxChar* GetAppName() const;
|
virtual const wxChar* GetAppName() const;
|
||||||
virtual bool Initialization();
|
virtual bool Initialization();
|
||||||
void OnTimer(wxTimerEvent& evt);
|
void OnTimer(wxTimerEvent& evt);
|
||||||
bool RestartTimer();
|
void OnEndProcess(wxProcessEvent& evt);
|
||||||
|
|
||||||
void AddMiniForm(TXmlItem& tr, const wxChar* action, const wxChar* app, const wxChar* prompt) const;
|
TXmlItem& AddMiniForm(TXmlItem& tr, const wxChar* action, const wxChar* app, const wxChar* prompt) const;
|
||||||
void EnumerateVariables(const wxString& strApp, wxArrayString& arr) const;
|
void EnumerateVariables(const wxString& strApp, wxArrayString& arr) const;
|
||||||
|
|
||||||
void CreateServersList(wxArrayString& arr) const;
|
const wxArrayString& GetServersList();
|
||||||
|
const TProcessHashMap& GetRunningServers() { return m_hmProcMap; }
|
||||||
|
|
||||||
bool PingProcess(const wxString& strApp);
|
bool PingProcess(const wxString& strApp);
|
||||||
void StopProcess(const wxString& strApp);
|
void StopProcess(const wxString& strApp);
|
||||||
wxString StartProcess(const wxString& strApp);
|
wxString StartProcess(const wxString& strApp);
|
||||||
@ -70,88 +50,119 @@ public:
|
|||||||
//metodi riguardanti l'interfaccia html
|
//metodi riguardanti l'interfaccia html
|
||||||
void ProcessFormStart(const THashTable& args, wxSocketBase& sock);
|
void ProcessFormStart(const THashTable& args, wxSocketBase& sock);
|
||||||
void ProcessFormStop(const THashTable& args, wxSocketBase& sock);
|
void ProcessFormStop(const THashTable& args, wxSocketBase& sock);
|
||||||
|
void ProcessFormRestart(const THashTable& args, wxSocketBase& sock);
|
||||||
void ProcessFormConfig(const THashTable& args, wxSocketBase& sock);
|
void ProcessFormConfig(const THashTable& args, wxSocketBase& sock);
|
||||||
void ProcessFormUpdate(THashTable& args, wxSocketBase& sock);
|
void ProcessFormUpdate(THashTable& args, wxSocketBase& sock);
|
||||||
void CallCgi(wxString& strFileName, wxSocketBase& sock);
|
void CallCgi(wxString& strFileName, wxSocketBase& sock);
|
||||||
|
|
||||||
|
TLurchServer();
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////
|
||||||
// TProcess implementation
|
|
||||||
///////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
void TProcess::OnTerminate(int pid, int WXUNUSED(status))
|
|
||||||
{
|
|
||||||
SetPid(pid);
|
|
||||||
m_pLurch->ForgetProcess(m_strApp);
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
|
||||||
// TLurchServer implementation
|
// TLurchServer implementation
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
|
|
||||||
BEGIN_EVENT_TABLE(TLurchServer, TBaseServerApp)
|
BEGIN_EVENT_TABLE(TLurchServer, TBaseServerApp)
|
||||||
EVT_TIMER(wxID_ANY, TLurchServer::OnTimer)
|
EVT_TIMER(wxID_ANY, TLurchServer::OnTimer)
|
||||||
|
EVT_END_PROCESS(wxID_ANY, TLurchServer::OnEndProcess)
|
||||||
END_EVENT_TABLE()
|
END_EVENT_TABLE()
|
||||||
|
|
||||||
|
#ifndef max
|
||||||
|
#define max(a,b) ((a)>(b) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
bool TLurchServer::PingProcess(const wxString& strApp)
|
bool TLurchServer::PingProcess(const wxString& strApp)
|
||||||
{
|
{
|
||||||
bool bPinged = false;
|
bool bPinged = false;
|
||||||
TProcess* pProcess = (TProcess*)m_ProcMap[strApp];
|
|
||||||
if (pProcess != NULL)
|
|
||||||
{
|
|
||||||
const wxString strPort = GetConfigString("Port", "", strApp);
|
const wxString strPort = GetConfigString("Port", "", strApp);
|
||||||
if (!strPort.IsEmpty())
|
if (!strPort.IsEmpty())
|
||||||
{
|
{
|
||||||
const int nTimeOut = m_nFreq > 3000 ? m_nFreq / 3000 : 1;
|
const int nInterval = m_PingTimer.GetInterval(); // msec
|
||||||
|
const int nTimeOut = max(nInterval/4, 250); // msec
|
||||||
wxIPV4address ipAddress;
|
wxIPV4address ipAddress;
|
||||||
ipAddress.LocalHost();
|
ipAddress.LocalHost();
|
||||||
ipAddress.Service(strPort);
|
ipAddress.Service(strPort);
|
||||||
wxSocketClient sSock(wxSOCKET_NOWAIT);
|
wxSocketClient sSock(wxSOCKET_NOWAIT);
|
||||||
sSock.Connect(ipAddress, false);
|
sSock.Connect(ipAddress, false);
|
||||||
if (sSock.WaitOnConnect(nTimeOut))
|
if (sSock.WaitOnConnect(0, nTimeOut))
|
||||||
{
|
{
|
||||||
sSock.Write("PING\n", 5);
|
sSock.Discard(); // Tralascia eventuali dati in arrivo non richiesti
|
||||||
if (sSock.WaitForWrite(nTimeOut))
|
const wxString strPing = wxT("PING\n");
|
||||||
|
sSock.Write(strPing, strPing.Len());
|
||||||
|
if (sSock.WaitForWrite(0, nTimeOut))
|
||||||
{
|
{
|
||||||
|
::wxMilliSleep(nTimeOut); // Triste necessita' :-( Aspetto qui ...
|
||||||
char buffer[8]; memset(buffer, 0, sizeof(buffer));
|
char buffer[8]; memset(buffer, 0, sizeof(buffer));
|
||||||
sSock.Read(buffer, 4);
|
sSock.Read(buffer, 4);
|
||||||
if (sSock.WaitForRead(nTimeOut))
|
if (sSock.WaitForRead(0, 1)) // ... ma poi non aspetto qua :-)
|
||||||
bPinged = wxStrcmp(buffer, "PONG") == 0;
|
bPinged = wxStrncmp(buffer, "PONG", 4) == 0;
|
||||||
}
|
sSock.Discard(); // Tralascia ulteriori dati in arrivo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return bPinged;
|
return bPinged;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TLurchServer::OnTimer(wxTimerEvent& WXUNUSED(evt))
|
void TLurchServer::OnTimer(wxTimerEvent& evt)
|
||||||
{
|
{
|
||||||
m_Timer.Stop();
|
if (m_Semaphore.TryWait() != wxSEMA_NO_ERROR)
|
||||||
const wxString strApp = "Authorization";
|
{
|
||||||
|
evt.Skip();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TProcessHashMap& hmServers = GetRunningServers();
|
||||||
|
const int nServers = hmServers.size();
|
||||||
|
if (nServers > 0) // Is anybody out there?
|
||||||
|
{
|
||||||
|
const int nRandomIndex = rand() % nServers;
|
||||||
|
wxString strApp; // Usually "Authorization"
|
||||||
|
TProcessHashMap::const_iterator it;
|
||||||
|
for (it = hmServers.begin(); it != hmServers.end(); ++it)
|
||||||
|
strApp = it->first;
|
||||||
|
|
||||||
if (!PingProcess(strApp))
|
if (!PingProcess(strApp))
|
||||||
{
|
{
|
||||||
TProcess* pProcess = (TProcess*)m_ProcMap[strApp];
|
wxProcess* pProcess = m_hmProcMap[strApp];
|
||||||
wxKillError ke = pProcess->Kill(pProcess->GetPid());
|
wxKillError ke = pProcess->Kill(pProcess->GetPid());
|
||||||
if (ke == wxKILL_OK)
|
if (ke == wxKILL_OK)
|
||||||
WriteLog(strApp + " killed!");
|
WriteLog(strApp + _(" killed!"));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
wxString strMsg;
|
wxString strMsg;
|
||||||
strMsg << "Error " << ke << " killing " << strApp;
|
strMsg << _("Error ") << ke << _(" killing ") << strApp;
|
||||||
WriteLog(strMsg);
|
WriteLog(strMsg);
|
||||||
}
|
}
|
||||||
wxSleep(2);
|
wxSleep(2);
|
||||||
StartProcess(strApp);
|
StartProcess(strApp);
|
||||||
}
|
}
|
||||||
RestartTimer();
|
}
|
||||||
|
|
||||||
|
m_Semaphore.Post();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TLurchServer::OnEndProcess(wxProcessEvent& evt)
|
||||||
|
{
|
||||||
|
TProcessHashMap::const_iterator it;
|
||||||
|
for (it = m_hmProcMap.begin(); it != m_hmProcMap.end(); ++it)
|
||||||
|
{
|
||||||
|
const wxProcess* p = it->second;
|
||||||
|
if (p->GetPid() == evt.GetPid())
|
||||||
|
{
|
||||||
|
ForgetProcess(it->first);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const wxChar* TLurchServer::GetAppName() const
|
const wxChar* TLurchServer::GetAppName() const
|
||||||
{
|
{ return wxT("Lurch"); }
|
||||||
return "Lurch";
|
|
||||||
}
|
|
||||||
|
|
||||||
void TLurchServer::CreateServersList(wxArrayString& arr) const
|
const wxArrayString& TLurchServer::GetServersList()
|
||||||
|
{
|
||||||
|
if (m_aServers.IsEmpty())
|
||||||
{
|
{
|
||||||
wxFileInputStream ini(GetConfigName());
|
wxFileInputStream ini(GetConfigName());
|
||||||
const size_t size = ini.GetSize();
|
const size_t size = ini.GetSize();
|
||||||
@ -166,20 +177,23 @@ void TLurchServer::CreateServersList(wxArrayString& arr) const
|
|||||||
{
|
{
|
||||||
*chiusa = '\0';
|
*chiusa = '\0';
|
||||||
wxString str = aperta+1;
|
wxString str = aperta+1;
|
||||||
arr.Add(str);
|
m_aServers.Add(str);
|
||||||
aperta = strchr(chiusa+1, '[');
|
aperta = strchr(chiusa+1, '[');
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
delete buff;
|
return m_aServers;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TLurchServer::AddMiniForm(TXmlItem& tr, const wxChar* action, const wxChar* app, const wxChar* prompt) const
|
TXmlItem& TLurchServer::AddMiniForm(TXmlItem& tr, const wxChar* action, const wxChar* app, const wxChar* prompt) const
|
||||||
{
|
{
|
||||||
TXmlItem& td = tr.AddChild("td").SetAttr("width", "15%");
|
TXmlItem& td = tr.AddChild("td").SetAttr("width", "10%");
|
||||||
TXmlItem& form = td.AddChild("center").AddChild("form");
|
td.SetAttr("align", "center");
|
||||||
|
td.SetAttr("valign", "center"); // Lo ignora ma insisto
|
||||||
|
|
||||||
|
TXmlItem& form = td.AddChild("form");
|
||||||
form.SetAttr("action", action);
|
form.SetAttr("action", action);
|
||||||
|
|
||||||
TXmlItem& name = form.AddChild("input");
|
TXmlItem& name = form.AddChild("input");
|
||||||
@ -189,6 +203,7 @@ void TLurchServer::AddMiniForm(TXmlItem& tr, const wxChar* action, const wxChar*
|
|||||||
TXmlItem& submit = form.AddChild("input");
|
TXmlItem& submit = form.AddChild("input");
|
||||||
submit.SetAttr("type", "submit");
|
submit.SetAttr("type", "submit");
|
||||||
submit.SetAttr("value", prompt);
|
submit.SetAttr("value", prompt);
|
||||||
|
return submit;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TLurchServer::GenerateFile(wxString& strFilename)
|
void TLurchServer::GenerateFile(wxString& strFilename)
|
||||||
@ -203,30 +218,21 @@ void TLurchServer::GenerateFile(wxString& strFilename)
|
|||||||
strFilename = GetTempFilename();
|
strFilename = GetTempFilename();
|
||||||
const wxString strLurchName = GetAppName();
|
const wxString strLurchName = GetAppName();
|
||||||
|
|
||||||
wxArrayString arr; CreateServersList(arr);
|
const wxArrayString& arr = GetServersList();
|
||||||
for (size_t i = 0; i < arr.GetCount(); i++)
|
for (size_t i = 0; i < arr.GetCount(); i++)
|
||||||
{
|
{
|
||||||
const bool bLurch = arr[i] == strLurchName;
|
const wxString& strApp = arr[i];
|
||||||
wxFileConfig ini("", "", GetConfigName(), "", wxCONFIG_USE_LOCAL_FILE | wxCONFIG_USE_RELATIVE_PATH);
|
const bool bLurch = strApp == strLurchName;
|
||||||
wxString str;
|
const wxString strHost = GetConfigString("Host", "127.0.0.1", strApp);
|
||||||
str << '/' << arr[i];
|
const int nPort = GetConfigInt("Port", 3883, strApp);
|
||||||
ini.SetPath(str);
|
const wxString strIcon = GetConfigString("Icon", "euro.gif", strApp);
|
||||||
|
|
||||||
wxString strHost;
|
const wxSingleInstanceChecker sic(strApp);
|
||||||
ini.Read("Host", &strHost, "127.0.0.1");
|
|
||||||
|
|
||||||
int nPort;
|
|
||||||
ini.Read("Port", &nPort, 3883);
|
|
||||||
|
|
||||||
wxString strIcon;
|
|
||||||
ini.Read("Icon", &strIcon, "euro.gif");
|
|
||||||
|
|
||||||
const wxSingleInstanceChecker sic(arr[i]);
|
|
||||||
const bool bRunning = sic.IsAnotherRunning();
|
const bool bRunning = sic.IsAnotherRunning();
|
||||||
|
|
||||||
TXmlItem& tr = table.AddChild("tr");
|
TXmlItem& tr = table.AddChild("tr");
|
||||||
TXmlItem& td0 = tr.AddChild("td");
|
TXmlItem& td0 = tr.AddChild("td");
|
||||||
td0.SetAttr("width", "15%"); td0.SetAttr("align", "center");
|
td0.SetAttr("width", "10%"); td0.SetAttr("align", "center");
|
||||||
TXmlItem& a = td0.AddChild("a");
|
TXmlItem& a = td0.AddChild("a");
|
||||||
if (!bLurch && bRunning)
|
if (!bLurch && bRunning)
|
||||||
{
|
{
|
||||||
@ -236,8 +242,17 @@ void TLurchServer::GenerateFile(wxString& strFilename)
|
|||||||
TXmlItem& img = a.AddChild("img");
|
TXmlItem& img = a.AddChild("img");
|
||||||
img.SetAttr("src", strIcon); img.SetAttr("border", 0L); img.SetAttr("alt", arr[i]);
|
img.SetAttr("src", strIcon); img.SetAttr("border", 0L); img.SetAttr("alt", arr[i]);
|
||||||
|
|
||||||
AddMiniForm(tr, (bRunning || bLurch) ? "kill.cgi" : "start.cgi", arr[i], (bRunning || bLurch) ? "Stop" : "Start");
|
TXmlItem& buttStart = AddMiniForm(tr, "start.cgi", arr[i], _("Start"));
|
||||||
AddMiniForm(tr, "config.cgi", arr[i], "Configure");
|
if (bRunning || bLurch)
|
||||||
|
buttStart.SetAttr(wxT("type"), wxT("hidden"));
|
||||||
|
|
||||||
|
TXmlItem& buttStop = AddMiniForm(tr, "kill.cgi", arr[i], _("Stop"));
|
||||||
|
if (!(bRunning || bLurch))
|
||||||
|
buttStop.SetAttr(wxT("type"), wxT("hidden"));
|
||||||
|
|
||||||
|
TXmlItem& buttRestart = AddMiniForm(tr, "restart.cgi", arr[i], _("Restart"));
|
||||||
|
if (!(bRunning && !bLurch))
|
||||||
|
buttRestart.SetAttr(wxT("type"), wxT("hidden"));
|
||||||
|
|
||||||
TXmlItem& a3 = tr.AddChild("td").AddChild("a");
|
TXmlItem& a3 = tr.AddChild("td").AddChild("a");
|
||||||
if (!bLurch && bRunning)
|
if (!bLurch && bRunning)
|
||||||
@ -264,7 +279,7 @@ void TLurchServer::GenerateFile(wxString& strFilename)
|
|||||||
|
|
||||||
TXmlItem& tr2 = panel.AddChild("tr");
|
TXmlItem& tr2 = panel.AddChild("tr");
|
||||||
tr2.AddChild("td").AddEnclosedText("Ping Frequency");
|
tr2.AddChild("td").AddEnclosedText("Ping Frequency");
|
||||||
wxString strFreq; strFreq << m_nFreq/1000;
|
wxString strFreq; strFreq << m_PingTimer.GetInterval()/1000;
|
||||||
tr2.AddChild("td").AddEnclosedText(strFreq);
|
tr2.AddChild("td").AddEnclosedText(strFreq);
|
||||||
|
|
||||||
html.Save(strFilename);
|
html.Save(strFilename);
|
||||||
@ -301,22 +316,6 @@ bool TLurchServer::IsCgiName(wxString strFilename) const
|
|||||||
return strExt == "cgi" || strExt == "exe";
|
return strExt == "cgi" || strExt == "exe";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TLurchServer::RestartTimer()
|
|
||||||
{
|
|
||||||
bool ok = true;
|
|
||||||
if (m_nFreq > 0)
|
|
||||||
{
|
|
||||||
ok = m_Timer.Start(m_nFreq) && m_Timer.IsRunning();
|
|
||||||
if (!ok)
|
|
||||||
{
|
|
||||||
wxString strMsg;
|
|
||||||
strMsg << "Error starting timer with " << m_nFreq << " ms frequency";
|
|
||||||
WriteLog(strMsg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
wxString TLurchServer::StartProcess(const wxString& strApp)
|
wxString TLurchServer::StartProcess(const wxString& strApp)
|
||||||
{
|
{
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
@ -337,28 +336,26 @@ wxString TLurchServer::StartProcess(const wxString& strApp)
|
|||||||
fnPath.SetPath(GetServerPath());
|
fnPath.SetPath(GetServerPath());
|
||||||
fnPath.SetFullName(strRun);
|
fnPath.SetFullName(strRun);
|
||||||
|
|
||||||
TProcess* pProcess = new TProcess(this, strApp);
|
wxProcess* pProcess = wxProcess::Open(fnPath.GetFullPath());
|
||||||
const long nProc = wxExecute(fnPath.GetFullPath(), wxEXEC_ASYNC, pProcess);
|
if (pProcess == NULL)
|
||||||
if (nProc == 0 || nProc == -1)
|
|
||||||
{
|
{
|
||||||
strMessage.Printf("Can't run %s executable (%s)", strApp.c_str(), strRun.c_str());
|
strMessage.Printf(_("Can't run %s executable (%s)"), strApp.c_str(), strRun.c_str());
|
||||||
delete pProcess;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pProcess->ForcePid(nProc);
|
m_hmProcMap[strApp] = pProcess; // memorizza il numero del processo che ha lanciato per poterlo usare in fase di controllo
|
||||||
m_ProcMap[strApp] = pProcess; //memorizza il numero del processo che ha lanciato per poterlo usare in fase di controllo
|
|
||||||
strMessage = wxEmptyString;
|
strMessage = wxEmptyString;
|
||||||
|
::wxSleep(1); // Lascia il tempo di inizializzarsi prima di compinciare a pingarlo!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
strMessage.Printf("Can't find %s executable (%s)", strApp.c_str(), strRun.c_str());
|
strMessage.Printf(_("Can't find %s executable (%s)"), strApp.c_str(), strRun.c_str());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
strMessage.Printf("%s il already running", strApp.c_str());
|
strMessage.Printf(_("%s il already running"), strApp.c_str());
|
||||||
|
|
||||||
if (strMessage.IsEmpty())
|
if (strMessage.IsEmpty())
|
||||||
WriteLog(strApp + " started.");
|
WriteLog(strApp + _(" started."));
|
||||||
else
|
else
|
||||||
WriteLog(strMessage);
|
WriteLog(strMessage);
|
||||||
|
|
||||||
@ -372,16 +369,16 @@ void TLurchServer::ProcessFormStart(const THashTable& args, wxSocketBase& sock)
|
|||||||
{
|
{
|
||||||
const wxString strMessage = StartProcess(strApp);
|
const wxString strMessage = StartProcess(strApp);
|
||||||
if (strMessage.IsEmpty())
|
if (strMessage.IsEmpty())
|
||||||
MessageBox("Server Started", strApp, sock);
|
MessageBox(_("Server Started"), strApp, sock);
|
||||||
else
|
else
|
||||||
MessageBox("ERROR", strMessage, sock);
|
MessageBox(_("ERROR"), strMessage, sock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TLurchServer::ForgetProcess(const wxString& strApp)
|
bool TLurchServer::ForgetProcess(const wxString& strApp)
|
||||||
{
|
{
|
||||||
WriteLog(strApp + " terminated.");
|
WriteLog(strApp + _(" terminated."));
|
||||||
return m_ProcMap.erase(strApp) != 0;
|
return m_hmProcMap.erase(strApp) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TLurchServer::StopProcess(const wxString& strApp)
|
void TLurchServer::StopProcess(const wxString& strApp)
|
||||||
@ -397,38 +394,71 @@ void TLurchServer::StopProcess(const wxString& strApp)
|
|||||||
wxSocketClient sock;
|
wxSocketClient sock;
|
||||||
if (sock.Connect(addr))
|
if (sock.Connect(addr))
|
||||||
{
|
{
|
||||||
|
// Prima provo con le buone inviando una richiesta di stop
|
||||||
const wxString str = "GET /stop.cgi HTTP/1.1\r\n\r\n";
|
const wxString str = "GET /stop.cgi HTTP/1.1\r\n\r\n";
|
||||||
sock.Write(str, str.Length());
|
sock.Write(str, str.Length());
|
||||||
if (strHost == "localhost")
|
if (addr.IsLocalHost())
|
||||||
{
|
{
|
||||||
const wxSingleInstanceChecker sic(strApp);
|
const wxSingleInstanceChecker sic(strApp);
|
||||||
for (int i = 0; i < 5 && sic.IsAnotherRunning(); i++)
|
int i;
|
||||||
|
for (i = 5; i >= 0 && sic.IsAnotherRunning(); i--)
|
||||||
wxSleep(1);
|
wxSleep(1);
|
||||||
|
// Se le buone non hanno funzionato ... passo alle cattive
|
||||||
|
if (i < 0)
|
||||||
|
{
|
||||||
|
wxProcess* p = m_hmProcMap[strApp];
|
||||||
|
if (p != NULL)
|
||||||
|
{
|
||||||
|
p->Kill(p->GetPid());
|
||||||
ForgetProcess(strApp);
|
ForgetProcess(strApp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TLurchServer::ProcessFormStop(const THashTable& args, wxSocketBase& sock)
|
void TLurchServer::ProcessFormStop(const THashTable& args, wxSocketBase& sock)
|
||||||
|
{
|
||||||
|
if (m_Semaphore.Wait() == wxSEMA_NO_ERROR)
|
||||||
{
|
{
|
||||||
const wxString strApp = args.Get("App");
|
const wxString strApp = args.Get("App");
|
||||||
if (strApp == GetAppName()) // Stop myself!
|
if (strApp == GetAppName() || strApp.IsEmpty()) // Stop myself!
|
||||||
{
|
{
|
||||||
wxArrayString app; CreateServersList(app);
|
m_PingTimer.Stop(); // Stop ping process!
|
||||||
for (size_t i = 0; i < app.GetCount(); i++)
|
// Fill a safe array of names before killing the processes stored in the hash map
|
||||||
{
|
const TProcessHashMap& hmServers = GetRunningServers(); // Hash map of the running processes
|
||||||
if (app[i] != GetAppName()) // Stop Children only!
|
wxArrayString aRunner; // Array of the names of the runners
|
||||||
{
|
TProcessHashMap::const_iterator it;
|
||||||
const wxSingleInstanceChecker sic(app[i]);
|
for (it = hmServers.begin(); it != hmServers.end(); ++it)
|
||||||
if (sic.IsAnotherRunning())
|
aRunner.Add(it->first);
|
||||||
StopProcess(app[i]);
|
for (size_t i = 0; i < aRunner.GetCount(); i++)
|
||||||
}
|
StopProcess(aRunner[i]);
|
||||||
}
|
ExitMainLoop();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
StopProcess(strApp);
|
StopProcess(strApp);
|
||||||
MessageBox("Server stopped", strApp, sock);
|
MessageBox("Server stopped", strApp, sock);
|
||||||
|
|
||||||
|
m_Semaphore.Post();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TLurchServer::ProcessFormRestart(const THashTable& args, wxSocketBase& sock)
|
||||||
|
{
|
||||||
|
const wxString strApp = args.Get("App");
|
||||||
|
if (!strApp.IsEmpty() && strApp != GetAppName())
|
||||||
|
{
|
||||||
|
if (m_Semaphore.Wait() == wxSEMA_NO_ERROR)
|
||||||
|
{
|
||||||
|
StopProcess(strApp);
|
||||||
|
::wxSleep(2);
|
||||||
|
ProcessFormStart(args, sock);
|
||||||
|
m_Semaphore.Post();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void TLurchServer::EnumerateVariables(const wxString& strApp, wxArrayString& arr) const
|
void TLurchServer::EnumerateVariables(const wxString& strApp, wxArrayString& arr) const
|
||||||
{
|
{
|
||||||
@ -542,10 +572,13 @@ void TLurchServer::CallCgi(wxString& strFileName, wxSocketBase& sock)
|
|||||||
|
|
||||||
if (strExt == "cgi")
|
if (strExt == "cgi")
|
||||||
{
|
{
|
||||||
|
strName.MakeLower();
|
||||||
if (strName == "start")
|
if (strName == "start")
|
||||||
ProcessFormStart(hashArgs, sock); else
|
ProcessFormStart(hashArgs, sock); else
|
||||||
if (strName == "kill")
|
if (strName == "kill")
|
||||||
ProcessFormStop(hashArgs, sock); else
|
ProcessFormStop(hashArgs, sock); else
|
||||||
|
if (strName == "restart")
|
||||||
|
ProcessFormRestart(hashArgs, sock); else
|
||||||
if (strName == "config")
|
if (strName == "config")
|
||||||
ProcessFormConfig(hashArgs, sock); else
|
ProcessFormConfig(hashArgs, sock); else
|
||||||
if (strName == "update")
|
if (strName == "update")
|
||||||
@ -593,19 +626,24 @@ void TLurchServer::ProcessHttpPost(wxString cmd, wxSocketBase& outs)
|
|||||||
|
|
||||||
bool TLurchServer::Initialization()
|
bool TLurchServer::Initialization()
|
||||||
{
|
{
|
||||||
m_nFreq = GetConfigInt("PingFreq") * 1000; // sec to msec
|
const wxArrayString& arr = GetServersList();
|
||||||
|
|
||||||
wxArrayString arr; CreateServersList(arr);
|
|
||||||
for (size_t i = 0; i < arr.GetCount(); i++)
|
for (size_t i = 0; i < arr.GetCount(); i++)
|
||||||
{
|
{
|
||||||
const wxString& strApp = arr[i];
|
const wxString& strApp = arr[i];
|
||||||
|
if (strApp != GetAppName())
|
||||||
|
{
|
||||||
const bool bAutorun = GetConfigBool("Autorun", false, strApp);
|
const bool bAutorun = GetConfigBool("Autorun", false, strApp);
|
||||||
if (bAutorun)
|
if (bAutorun)
|
||||||
StartProcess(strApp);
|
StartProcess(strApp);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RestartTimer();
|
const int nFreq = GetConfigInt("PingFreq");
|
||||||
|
if (nFreq > 0)
|
||||||
|
{
|
||||||
|
m_PingTimer.Start(nFreq * 1000); // sec to msec
|
||||||
|
m_Semaphore.Post(); // GREEN!
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -613,3 +651,7 @@ bool TLurchServer::Initialization()
|
|||||||
// Istanziare l'applicazione principale
|
// Istanziare l'applicazione principale
|
||||||
|
|
||||||
IMPLEMENT_APP(TLurchServer)
|
IMPLEMENT_APP(TLurchServer)
|
||||||
|
|
||||||
|
TLurchServer::TLurchServer()
|
||||||
|
: m_Semaphore(0 /* RED! */, 1 /* mutex like behaviour */)
|
||||||
|
{ }
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include <wx/wx.h>
|
#include <wx/wx.h>
|
||||||
|
|
||||||
#include "wx/mstream.h"
|
#include "wx/mstream.h"
|
||||||
#include <wx/wfstream.h>
|
#include <wx/wfstream.h>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user