campo-sirio/server/baseserv.cpp
guy 4dc843a0a2 Allineamento file modificati durante la transizione da cvs a svn
git-svn-id: svn://10.65.10.50/branches/R_10_00@22612 c028cbd2-c16b-5b4b-a496-9718f37d4682
2012-03-20 13:37:23 +00:00

974 lines
26 KiB
C++
Executable File

/////////////////////////////////////////////////////////////////////////////
// Name: BaseServ.cpp
// Purpose: Simple base Server
// Author: Guy
// Modified by:
// Created: 21/08/2002
// Copyright: (c) 2002 Guy
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ==========================================================================
// declarations
// ==========================================================================
// --------------------------------------------------------------------------
// headers
// --------------------------------------------------------------------------
#include <wx/wx.h>
#include "baseserv.h"
#include <wx/config.h>
#include <wx/filename.h>
#include <wx/image.h>
#include <wx/mimetype.h>
#include <wx/mstream.h>
#include <wx/sckstrm.h>
#include <wx/tokenzr.h>
#ifndef __WXMSW__
#include <wx/fileconf.h>
#endif
///////////////////////////////////////////////////////////
// Utilities
///////////////////////////////////////////////////////////
IMPLEMENT_ABSTRACT_CLASS(TBaseServerApp, wxApp)
TBaseServerApp& GetServerApp()
{ return *wxStaticCast(wxTheApp, TBaseServerApp); }
wxString Date2String(const wxDateTime& date)
{ return date.Format("%d-%m-%Y"); }
wxDateTime String2Date(const wxString& str)
{
int d, m, y;
sscanf(str, "%d-%d-%d", &d, &m, &y);
wxDateTime date(d, wxDateTime::Month(m-1), y);
return date;
}
wxSocketBase& operator<<(wxSocketBase& outf, const wxChar* str)
{
if (str && *str)
outf.Write(str, (wxUint32)wxStrlen(str));
return outf;
}
wxSocketBase& operator<<(wxSocketBase& outf, wxString str)
{
if (!str.IsEmpty())
outf.Write(str, (wxUint32)str.Length());
return outf;
}
wxSocketBase& operator<<(wxSocketBase& outf, size_t num)
{ return outf << wxString::Format("%u", num); }
// --------------------------------------------------------------------------
// classes
// --------------------------------------------------------------------------
///////////////////////////////////////////////////////////
// THashTable
///////////////////////////////////////////////////////////
void THashTable::Put(const wxString& key, const wxString& value)
{
THashString* entry = new THashString(value);
m_Hash.Put(key, entry);
}
wxString THashTable::Get(const wxChar* key) const
{
wxString strValue;
THashString* str = (THashString*)m_Hash.Get(key);
if (str != NULL)
strValue = str->m_str;
return strValue;
}
THashTable::THashTable(size_t size) : m_Hash(wxKEY_STRING, size)
{
m_Hash.DeleteContents(true);
}
#ifdef wxHAS_TASK_BAR_ICON
///////////////////////////////////////////////////////////
// TTaskbarIcon
///////////////////////////////////////////////////////////
BEGIN_EVENT_TABLE(TTaskBarIcon, wxTaskBarIcon)
EVT_TASKBAR_LEFT_DOWN(TTaskBarIcon::OnTaskBarClick)
END_EVENT_TABLE()
void TTaskBarIcon::OnTaskBarClick(wxTaskBarIconEvent& WXUNUSED(e))
{
wxString strURL;
// wxIPV4address addr; addr.AnyAddress();
// addr.Service(GetServerApp().GetDefaultPort());
// url << addr.Hostname() << ":" << addr.Service();
strURL << "http://127.0.0.1:" << GetServerApp().GetDefaultPort();
wxLaunchDefaultBrowser(strURL);
}
void TTaskBarIcon::Init()
{
const TBaseServerApp& a = GetServerApp();
wxIcon icon;
const wxString strIcon = a.GetConfigString("Icon");
if (wxFileExists(strIcon))
{
wxInitAllImageHandlers();
wxImage img(strIcon);
img.Rescale(32,32/*,wxIMAGE_QUALITY_HIGH*/);
const wxBitmap bmp(img);
icon.CopyFromBitmap(bmp);
}
else
icon.LoadFile("soap", wxBITMAP_TYPE_ICO_RESOURCE);
SetIcon(icon, a.GetAppName());
}
#endif
///////////////////////////////////////////////////////////
// TBaseServerApp
///////////////////////////////////////////////////////////
enum
{
SERVER_ID = 1001,
SOCKET_ID = 1002,
DATAGRAM_ID = 1003,
};
BEGIN_EVENT_TABLE(TBaseServerApp, wxApp)
EVT_SOCKET(SERVER_ID, TBaseServerApp::OnServerEvent)
EVT_SOCKET(SOCKET_ID, TBaseServerApp::OnSocketEvent)
EVT_SOCKET(DATAGRAM_ID, TBaseServerApp::OnDatagramEvent)
EVT_IDLE(TBaseServerApp::OnIdle)
END_EVENT_TABLE()
void TBaseServerApp::WriteLog(const wxChar* str, int nPriority) const
{
const bool doit = (m_log != NULL) && (m_bLogVerbose || nPriority > 0);
if (doit)
{
//raccatta data ed ora
const wxString strNow = wxNow();
*m_log << strNow << " " << str << endl;
}
}
wxString TBaseServerApp::GetTempFilename(const wxChar * ext)
{
wxString strTmp;
if (m_strTempDir.IsEmpty())
{
const wxString strPrefix = "Srv";
::wxGetTempFileName(strPrefix, strTmp);
::wxRemoveFile(strTmp);
(wxString&)m_strTempDir << ::wxPathOnly(strTmp) << "/";
}
strTmp = m_strTempDir;
strTmp += wxString::Format("%s_%d.%s", GetAppName(), m_nTmpCounter, ext);
m_nTmpCounter++;
if (m_nTmpCounter >= 32)
m_nTmpCounter = 0;
return strTmp;
}
TXmlItem& TBaseServerApp::AddLogo(TXmlItem& tr) const
{
TXmlItem& td = tr.AddChild("td");
td.SetAttr("width", "15%");
td.SetAttr("align", "center");
TXmlItem& a = td.AddChild("a");
a.SetAttr("href", "/index.htm");
const wxString gif = GetConfigString("Icon", "euro.gif");
TXmlItem& img = a.AddChild("img");
img.SetAttr("src", gif);
img.SetAttr("border", "0");
img.SetAttr("alt", "Return to Home Page");
return td;
}
TXmlItem& TBaseServerApp::CreatePageBody(TXmlItem& html, wxString header) const
{
if (header.IsEmpty())
header << GetAppName() << " Server";
html.SetTag("html");
TXmlItem& head = html.AddChild("head");
TXmlItem& meta1 = head.AddChild("meta");
meta1.SetAttr("name", "GENERATOR");
meta1.SetAttr("content", GetAppName());
TXmlItem& meta2 = head.AddChild("meta");
meta2.SetAttr("HTTP-EQUIV", "Content-Type");
meta2.SetAttr("content", "text/html; charset=iso-8859-1");
head.AddChild("title") << header;
TXmlItem& body = html.AddChild("body");
body.SetAttr("bgcolor", "#EFCEAD");
if (IsRunning())
body.SetAttr("background", "back.gif");
TXmlItem& title = body.AddChild("table");
title.SetAttr("border", "5"); title.SetAttr("width", "100%");
TXmlItem& title_tr = title.AddChild("tr");
if (IsRunning())
AddLogo(title_tr);
TXmlItem& td1 = title_tr.AddChild("td");
td1.AddChild("h1").AddChild("center") << header;
if (IsRunning())
AddLogo(title_tr);
body.AddChild("br");
return body;
}
TXmlItem& TBaseServerApp::AddLinkButton(TXmlItem& body, const wxChar* strCaption, const wxChar* strHref) const
{
/*
TXmlItem& table = body.AddChild("table");
table.SetAttr("border", "2"); table.SetAttr("bgcolor", "#C0C0C0");
TXmlItem& td = table.AddChild("tr").AddChild("td");
td.SetAttr("align", "center");
td.AddChild("a").SetAttr("href", strHref) << strCaption;
return table;
*/
TXmlItem& b = body.AddChild("button");
b.SetAttr("type", "button");
wxString strScript;
strScript += "window.open('";
strScript += strHref;
strScript += "', '_self')";
b.SetAttr("onClick", strScript);
b << strCaption;
return b;
}
void TBaseServerApp::MessageBox(const wxChar* caption, const wxChar* msg, wxSocketBase& outs)
{
TXmlItem html;
TXmlItem& body = CreatePageBody(html);
TXmlItem& table = body.AddChild("center").AddChild("table");
table.SetAttr("width", "70%"); table.SetAttr("border", "2");
table.AddChild("caption").AddChild("h2") << caption;
TXmlItem& td0 = table.AddChild("tr").AddChild("td");
td0.SetAttr("align", "justify");
td0.AddChild("h3") << msg;
if (m_bRunning) // Aggiungi il bottone di ritorno solo se il server non si sta spegnendo
{
TXmlItem& td1 = table.AddChild("tr").AddChild("td");
td1.SetAttr("align", "center");
AddLinkButton(td1, _("Return to main page"), "index.htm");
}
const wxString strTmp = GetTempFilename();
html.Save(strTmp);
SendFile(strTmp, outs);
}
bool TBaseServerApp::CanProcessCommand(wxString& cmd, wxSocketBase& outs)
{
if (cmd.Find("stop.cgi") >= 0)
{
m_bRunning = false; // Disable gif on title
if (outs.IsOk())
MessageBox("Warning!", "Server Stopped", outs);
ExitMainLoop();
return false;
}
return true;
}
void TBaseServerApp::SendContent(wxFileInputStream& inf, wxSocketBase& sock)
{
const size_t nSize = inf.GetSize();
WriteLog(wxString::Format("Sending %lu bytes", nSize), 0);
const size_t BUF_TEMP_SIZE = 1024*1024; // was 1024*16
char* buf = new char[BUF_TEMP_SIZE];
size_t bytes = BUF_TEMP_SIZE;
size_t nTotalWritten = 0;
while (bytes == BUF_TEMP_SIZE)
{
bytes = inf.Read(buf, bytes).LastRead();
size_t nWritten = sock.Write(buf, wxUint32(bytes)).LastCount();
nTotalWritten += nWritten;
}
delete buf;
if (nTotalWritten < nSize)
WriteLog(wxString::Format("I sent %lu of %lu bytes only.", nTotalWritten, nSize), 1);
}
void TBaseServerApp::SendFile(wxString strFilename, wxSocketBase& sock)
{
const bool bFound = wxFileExists(strFilename);
if (!bFound)
{
const wxString strTmp = GetTempFilename();
if (!strTmp.IsEmpty())
{
TXmlItem html;
TXmlItem& body = CreatePageBody(html);
body.AddChild("h1") << "Sorry: File not found!";
body.AddChild("br");
body.AddChild("h2") << strFilename;
html.Save(strTmp);
}
strFilename = strTmp;
}
wxString strType;
wxSplitPath(strFilename, NULL, NULL, &strType);
wxFileType* type = wxTheMimeTypesManager->GetFileTypeFromExtension(strType);
if (type != NULL)
type->GetMimeType(&strType);
else
strType = "text/plain";
const wxDateTime date = ::wxFileModificationTime(strFilename);
wxFileInputStream inf(strFilename);
const size_t nSize = inf.GetSize();
if (bFound)
sock << "HTTP/1.1 200 OK\n";
else
sock << "HTTP/1.1 401 Not found\n";
sock << "Server: " << GetAppName() << "\n";
sock << "Host: " << wxGetFullHostName() << "\n";
if (bFound && m_bRunning)
sock << "Connection: keep-alive\n";
else
sock << "Connection: close\n";
sock << "Content-Type: " << strType << "\n";
sock << "Content-Length: " << nSize << "\n";
sock << "Date: " << date.Format("%#c") << "\n";
wxDateTime dtFraUnPo = wxDateTime::Now();
const wxTimeSpan minuto(0, 1, 0); // Zero ore, Un minuto, Zero secondi
dtFraUnPo += minuto;
sock << "Expires: " << dtFraUnPo.Format("%#c") << "\n";
sock << "\n";
SendContent(inf, sock);
}
void TBaseServerApp::SoapProcessMethod(const TXmlItem& WXUNUSED(xmlMethod), TXmlItem& WXUNUSED(xmlAnswer))
{
}
void TBaseServerApp::ProcessSoapCommand(wxString cmd, wxSocketBase& sock)
{
TXmlItem xmlEnvelope;
xmlEnvelope.SetTag("SOAP-ENV:Envelope");
TXmlItem& xmlBody = xmlEnvelope.AddChild("SOAP-ENV:Body");
const int soapstart = cmd.Find("<SOAP-ENV:");
if (soapstart > 0)
{
const size_t soaplen = cmd.length() - soapstart;
const char* buff = (const char*)cmd;
buff += soapstart;
wxMemoryInputStream input(buff, soaplen);
TXmlItem query;
if (query.Read(input))
{
const TXmlItem* pxmlBody = query.FindFirst("SOAP-ENV:Body");
if (pxmlBody != NULL) for (int m = 0; ; m++)
{
const TXmlItem* pxmlMethod = pxmlBody->GetChild(m);
if (pxmlMethod == NULL)
break;
if (pxmlMethod->GetTag().StartsWith("m:"))
{
wxString str = pxmlMethod->GetTag(); str += "Result";
TXmlItem& xmlAnswer = xmlBody.AddChild(str);
SoapProcessMethod(*pxmlMethod, xmlAnswer);
}
}
}
}
const wxString strResult = xmlEnvelope.AsString();
sock << "HTTP/1.1 200 OK" << endl;
sock << "Connection: keep-alive" << endl;
sock << "Content-Length: " << strResult.Length() << endl;
sock << "Content-Type: text/xml; charset=utf-8" << endl;
sock << "Date: " << wxDateTime::Now().Format("%#c") << endl;
sock << "Server: " << GetAppName() << endl;
sock << "Host: " << wxGetFullHostName() << endl;
sock << endl;
sock << strResult;
}
void TBaseServerApp::ProcessHttpGet(wxString cmd, wxSocketBase& sock)
{
const int stop = cmd.Find(" HTTP");
wxString str = cmd.Mid(4, stop-4).Trim();
if (str == "/")
str += "index.htm";
wxString strFilename = GetDocumentRoot() + str;
SendFile(strFilename, sock);
}
void TBaseServerApp::ProcessFormCommand(wxString WXUNUSED(cmd),
wxSocketBase& WXUNUSED(sock))
{ }
void TBaseServerApp::SendNotModifiedFile(wxSocketBase& sock)
{
sock << "HTTP/1.1 304 Not Modified\n";
sock << "Date: " << wxDateTime::Now().Format("%#c") << "\n";
sock << "Server: " << GetAppName() << "\n";
sock << "Connection: close\n";
}
const wxChar* TBaseServerApp::GetAppName() const
{
// Pure virtual function
return "Server";
}
bool TBaseServerApp::ProcessCommand(wxString cmd, wxSocketBase& outs)
{
WriteLog(cmd, 0);
bool bProcessed = true;
if (cmd.StartsWith("POST "))
{
if (cmd.Find("SOAPAction") > 0)
ProcessSoapCommand(cmd, outs);
else
ProcessFormCommand(cmd, outs);
} else
if (cmd.StartsWith("GET "))
ProcessHttpGet(cmd, outs); else
if (cmd.StartsWith("PING"))
outs << "PONG\n";
else
bProcessed = false;
return bProcessed;
}
void TBaseServerApp::OnServerEvent(wxSocketEvent& e)
{
// Accept new connection if there is one in the pending
// connections queue, else exit. We use Accept(FALSE) for
// non-blocking accept (although if we got here, there
// should ALWAYS be a pending connection).
switch(e.GetSocketEvent())
{
case wxSOCKET_CONNECTION:
{
wxSocketBase* sock = m_server->Accept(false);
if (sock != NULL)
{
sock->SetEventHandler(*this, SOCKET_ID);
sock->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG);
sock->Notify(true);
WriteLog(_("Connection accepted."));
}
else
WriteLog(_("Connection REFUSED!"), 1);
}
break;
default:
WriteLog(_("Unhandled server event!"), 1);
break;
}
}
struct TCommand : public wxObject
{
wxSocketBase* m_Sock;
wxString m_Command;
};
void TBaseServerApp::OnSocketEvent(wxSocketEvent& e)
{
wxSocketBase* sock = e.GetSocket();
switch(e.GetSocketEvent())
{
case wxSOCKET_INPUT:
if (sock != NULL && sock->IsOk())
{
// We disable input events, so that the test doesn't trigger wxSocketEvent again.
sock->SetNotify(wxSOCKET_LOST_FLAG);
TCommand* message = new TCommand;
message->m_Sock = sock;
// Read the data
const size_t BUFSIZE = 1024;
wxChar buf[BUFSIZE + 16];
memset(buf, 0, sizeof(buf));
while (sock->Read(buf, BUFSIZE).LastCount() == BUFSIZE)
{
message->m_Command << buf;
memset(buf, 0, sizeof(buf));
}
message->m_Command << buf;
m_Sockets.Add(message);
// Enable input events again.
sock->SetNotify(wxSOCKET_LOST_FLAG | wxSOCKET_INPUT_FLAG);
}
break;
case wxSOCKET_LOST:
WriteLog(_("--- Socket lost."), 0);
if (sock != NULL)
{
for (int i = m_Sockets.GetCount()-1; i >= 0; i--)
{
TCommand& cmd = *(TCommand*)m_Sockets[i];
if (cmd.m_Sock == sock)
m_Sockets.RemoveAt(i);
}
if (sock->IsOk())
sock->Destroy();
}
break;
default:
break;
}
}
void TBaseServerApp::OnDatagramEvent(wxSocketEvent& WXUNUSED(e))
{
}
void TBaseServerApp::OnIdle(wxIdleEvent& evt)
{
if (m_Sockets.GetCount() > 0)
{
TCommand& cmd = *(TCommand*)m_Sockets[0];
wxSocketBase& sock = *cmd.m_Sock;
const bool valid_socket = sock.IsOk();
if (valid_socket)
sock.SetNotify(wxSOCKET_LOST_FLAG);
wxString& str = cmd.m_Command;
if (CanProcessCommand(str, sock))
{
if (valid_socket)
{
const wxSocketFlags flags = sock.GetFlags();
sock.SetFlags(wxSOCKET_WAITALL);
ProcessCommand(str, sock);
sock.SetFlags(flags);
}
else
ProcessCommand(str, sock); // Comandi come "UserLogout" vanno processati anche per socket non validi
}
// Enable input events again.
if (valid_socket)
{
sock.SetNotify(wxSOCKET_LOST_FLAG | wxSOCKET_INPUT_FLAG);
sock.Notify(true);
}
if (m_Sockets.GetCount() > 0)
m_Sockets.RemoveAt(0, 1);
evt.RequestMore(); // FONDAMENTALE per gestire richieste multiple!
}
wxApp::OnIdle(evt);
}
const wxString& TBaseServerApp::GetConfigName() const
{
if (m_strIni.IsEmpty())
{
wxFileName name(argv[0]); // Prendo il persorso completo del server in esecuzione
name.SetName("servers"); // Trasformo il nome in servers ...
name.SetExt("ini"); // ... e l'esetensione in .ini
name.MakeAbsolute();
(wxString&)m_strIni = name.GetFullPath();
}
return m_strIni;
}
wxString TBaseServerApp::GetConfigFileString(const wxChar* file, const wxChar* paragraph, const wxChar* key, const wxChar* def) const
{
wxString str;
if (file == NULL || *file <= ' ')
file = GetConfigName();
if (paragraph == NULL || *paragraph <= ' ')
paragraph = GetAppName();
#ifdef __WXMSW__
wxChar value[512]; memset(value, 0, sizeof(value));
const int len = ::GetPrivateProfileString(paragraph, key, def, value, sizeof(value)-1, file);
str = len <= 0 ? def : value;
#else
wxFileConfig ini("", "", file, "", wxCONFIG_USE_LOCAL_FILE | wxCONFIG_USE_RELATIVE_PATH);
str << '/' << paragraph;
ini.SetPath(str);
ini.Read(key, &str, def);
#endif
return str;
}
long TBaseServerApp::GetConfigFileInt(const wxChar* file, const wxChar* paragraph, const wxChar* key, long val) const
{
const wxString str = GetConfigFileString(file, paragraph, key, "*");
if (str != "*")
str.ToLong(&val);
return val;
}
void TBaseServerApp::SetConfigFileString(const wxChar* file, const wxChar* paragraph, const wxChar* key, const wxChar* val) const
{
if (file == NULL || *file <= ' ')
file = GetConfigName();
if (paragraph == NULL || *paragraph <= ' ')
paragraph = GetAppName();
#ifdef __WXMSW__
::WritePrivateProfileString(paragraph, key, val, file);
#else
wxFileConfig ini("", "", file, "", wxCONFIG_USE_LOCAL_FILE | wxCONFIG_USE_RELATIVE_PATH);
wxString str;
str << '/' << paragraph;
ini.SetPath(str);
ini.Write(key, val);
#endif
}
void TBaseServerApp::SetConfigString(const wxChar* key, const wxChar* val, const wxChar* app) const
{
return SetConfigFileString(NULL, app, key, val);
}
void TBaseServerApp::SetConfigInt(const wxChar* key, int val, const wxChar* app) const
{
wxString str; str.Printf("%d", val);
SetConfigString(key, str, app);
}
wxString TBaseServerApp::GetConfigString(const wxChar* key, const wxChar* def, const wxChar* app) const
{
return GetConfigFileString(NULL, app, key, def);
}
int TBaseServerApp::GetConfigInt(const wxChar* key, int def, const wxChar* app) const
{
return GetConfigFileInt(NULL, app, key, def);
}
bool TBaseServerApp::GetConfigBool(const wxChar* key, bool def, const wxChar* app) const
{
bool val = def;
const wxString str = GetConfigString(key, "*", app);
if (str != "*")
val = (str[0u] == '1') || (str[0u] == 'T') || (str[0u] == 'X') || (str[0u] == 'Y') || (str.CmpNoCase("On") == 0);
return val;
}
int TBaseServerApp::GetDefaultPort() const
{ return GetConfigInt("Port", 3883); }
int TBaseServerApp::GetUDPPort() const
{ return GetConfigInt("PortUDP", 0); }
#define OEM_INI wxT("../setup/oem.ini")
int TBaseServerApp::GetOemInt(const wxChar* key, int def) const
{
static int _oem = GetConfigFileInt(OEM_INI, "MAIN", "OEM", -1);
if (_oem >= 0)
{
if (wxStrcmp(key, wxT("OEM")) != 0)
{
wxString str; str.Printf(wxT("OEM_%d"), _oem);
def = GetConfigFileInt(OEM_INI, str, key, def);
}
else
def = _oem;
}
return def;
}
wxString TBaseServerApp::GetOemString(const wxChar* key, const wxChar* def) const
{
const int oem = GetOemInt("OEM", -1);
wxString str = def;
if (oem >= 0)
{
if (wxStrcmp(key, "OEM") != 0)
{
str.Printf("OEM_%d", oem);
str = GetConfigFileString(OEM_INI, str, key, def);
}
else
str.Printf("%d", oem);
}
return str;
}
wxString TBaseServerApp::GetInstallString(const wxChar* key, const wxChar* module) const
{
if (module == NULL || *module <= ' ')
module = wxT("sr");
return GetConfigFileString(wxT("../install.ini"), module, key, wxEmptyString);
}
bool TBaseServerApp::IsAdvanced() const
{
const int nOEM = GetOemInt(wxT("OEM"), -1);
return nOEM==0;
}
wxString TBaseServerApp::GetLogFileName() const
{ return GetConfigString("LogFile"); }
wxString TBaseServerApp::GetDocumentRoot() const
{ return GetConfigString("DocumentRoot", m_strPath); }
bool TBaseServerApp::IsRunning() const
{ return m_bRunning && IsMainLoopRunning() && Ok(); }
bool TBaseServerApp::OnInit()
{
m_server = NULL;
m_datagram = NULL;
m_log = NULL;
m_bRunning = false;
m_SingleInstance = new wxSingleInstanceChecker(GetAppName());
if (m_SingleInstance->IsAnotherRunning())
{
wxMessageBox(_("Another instance is already running"), GetAppName(), wxICON_HAND);
delete m_SingleInstance;
m_SingleInstance = NULL;
return false;
}
wxFileName::SplitPath(argv[0], &m_strPath, NULL, NULL);
if (!m_strPath.IsEmpty())
{
wxSetWorkingDirectory(m_strPath);
if (!wxEndsWithPathSeparator(m_strPath))
m_strPath += wxFILE_SEP_PATH;
}
// Create the address - defaults to localhost:0 initially
wxIPV4address addr;
addr.AnyAddress(); // I docs affermano che AnyAddress sia meglio di LocalHost
const int nTCPPort = GetDefaultPort();
addr.Service(nTCPPort);
// Create the TCP socket
m_server = new wxSocketServer(addr);
// Create the Log file
//Prima di creare il nuovo log file (vuoto) salva quello vecchio aggiungendo al nome data e ora di ripartenza..
//..Serve per monitorare i defungimenti dei server
const wxString strLog = GetLogFileName();
if (!strLog.IsEmpty())
{
wxFileName fnLogFileName(strLog);
if (fnLogFileName.FileExists())
{
const wxDateTime dtNow = wxDateTime::Now();
wxString strWorkString;
strWorkString.Printf("%04d%02d%02d_%02d%02d_",
dtNow.GetYear(), dtNow.GetMonth() + 1, dtNow.GetDay(),
dtNow.GetHour(), dtNow.GetMinute());
strWorkString << fnLogFileName.GetName();
fnLogFileName.SetName(strWorkString);
wxCopyFile(strLog, fnLogFileName.GetFullPath());
}
m_log = new wxFileOutputStream(strLog);
m_bLogVerbose = GetConfigBool("LogVerbose");
}
else
{
m_log = NULL;
m_bLogVerbose = false;
}
m_nTmpCounter = 0;
// We use Ok() here to see if the server is really listening
if (m_server->Ok())
{
// Setup the event handler and subscribe to connection events
m_server->SetEventHandler(*this, SERVER_ID);
m_server->SetNotify(wxSOCKET_CONNECTION_FLAG);
m_server->Notify(true);
wxString str;
str << GetAppName() << _(" listening at ") << addr.Hostname() << wxT(":") << addr.Service();
WriteLog(str);
m_bRunning = Initialization();
}
else
{
wxString str;
str << GetAppName() << _(" could not listen to port ") << addr.Service();
WriteLog(str);
}
#ifdef wxHAS_TASK_BAR_ICON
m_Tray = NULL;
if (m_bRunning)
{
m_Tray = new TTaskBarIcon;
m_Tray->Init();
}
#endif
/*
// Create the UDP socket
const int nUDPPort = GetUDPPort();
if (m_bRunning && nUDPPort > nTCPPort)
{
wxIPV4address udp_addr;
udp_addr.AnyAddress(); // I docs affermano che AnyAddress sia meglio di LocalHost
udp_addr.Service(nUDPPort);
m_datagram = new wxDatagramSocket(udp_addr);
// Setup the event handler and subscribe to connection events
m_datagram->SetEventHandler(*this, DATAGRAM_ID);
m_datagram->Notify(true);
}
*/
return m_bRunning;
}
int TBaseServerApp::OnExit()
{
if (m_server != NULL)
{
m_bRunning = false;
Deinitialization();
delete m_SingleInstance;
m_SingleInstance = NULL;
delete m_server;
m_server = NULL;
}
if (m_log != NULL)
{
wxString str;
str << GetAppName() << " shutting down.";
WriteLog(str);
delete m_log;
m_log = NULL;
}
#ifdef wxHAS_TASK_BAR_ICON
if (m_Tray != NULL)
{
m_Tray->RemoveIcon();
delete m_Tray;
m_Tray = NULL;
}
#endif
return wxApp::OnExit();
}
wxString TBaseServerApp::UnformatString(const wxString& strFormString) const
{
wxString strResult;
for (int i = 0; strFormString[i]; i++)
{
switch(strFormString[i])
{
case '+':
strResult += ' '; break;
case '%':
{
const wxChar c = hex2int(strFormString.Mid(i+1, 2));
strResult += c;
i += 2;
}
break;
default:
strResult += strFormString[i]; break;
}
}
return strResult;
}
size_t TBaseServerApp::ParseArguments(wxString args, THashTable& hashArgs) const
{
int uguale = args.Find('=');
while (uguale > 0)
{
wxString name = args.Left(uguale);
name.Trim(false); name.Trim(true);
wxString value;
const int acapo = args.Find('&');
if (acapo > uguale)
value = args.Mid(uguale+1, acapo-uguale-1);
else
value = args.Mid(uguale+1);
value.Trim(false); value.Trim(true);
hashArgs.Put(name, UnformatString(value));
if (acapo > 0)
{
args = args.Mid(acapo+1);
uguale = args.Find('=');
}
else
uguale = -1;
}
return hashArgs.GetCount();
}
bool TBaseServerApp::GetVersionInfo(int& year, int& release, int& tag, int& patch) const
{
const char* const VERSIONANDPATCH = "Don't cry for me Argentina.2091.10.00.0000.2101";
wxStringTokenizer tok(VERSIONANDPATCH, wxT("."));
tok.GetNextToken(); // Ignore string
year = wxAtoi(tok.GetNextToken());
release = wxAtoi(tok.GetNextToken());
tag = wxAtoi(tok.GetNextToken());
patch = wxAtoi(tok.GetNextToken());
int checksum = wxAtoi(tok.GetNextToken());
bool valid = year >= 2091 && release > 0 && tag >= 0 && patch >= 0 &&
checksum == (year + release + tag + patch);
return valid;
}