📄 httpsvc.cxx
字号:
PHTTPServiceProcess::~PHTTPServiceProcess()
{
ShutdownListener();
}
PHTTPServiceProcess & PHTTPServiceProcess::Current()
{
PHTTPServiceProcess & process = (PHTTPServiceProcess &)PProcess::Current();
PAssert(PIsDescendant(&process, PHTTPServiceProcess), "Not a HTTP service!");
return process;
}
BOOL PHTTPServiceProcess::OnStart()
{
if (!Initialise("Started"))
return FALSE;
OnConfigChanged();
return TRUE;
}
void PHTTPServiceProcess::OnStop()
{
ShutdownListener();
PSYSTEMLOG(Warning, GetName() << " stopped.");
PServiceProcess::OnStop();
}
BOOL PHTTPServiceProcess::OnPause()
{
OnConfigChanged();
return TRUE;
}
void PHTTPServiceProcess::OnContinue()
{
if (Initialise("Restarted"))
return;
OnStop();
Terminate();
}
#ifdef _WIN32
const char * PHTTPServiceProcess::GetServiceDependencies() const
{
return "EventLog\0Tcpip\0";
}
#endif
BOOL PHTTPServiceProcess::ListenForHTTP(WORD port,
PSocket::Reusability reuse,
PINDEX stackSize)
{
if (httpListeningSocket != NULL &&
httpListeningSocket->GetPort() == port &&
httpListeningSocket->IsOpen())
return TRUE;
return ListenForHTTP(new PTCPSocket(port), reuse, stackSize);
}
BOOL PHTTPServiceProcess::ListenForHTTP(PSocket * listener,
PSocket::Reusability reuse,
PINDEX stackSize)
{
if (httpListeningSocket != NULL)
ShutdownListener();
httpListeningSocket = PAssertNULL(listener);
if (!httpListeningSocket->Listen(5, 0, reuse)) {
PSYSTEMLOG(Debug, "HTTPSVC\tListen on port " << httpListeningSocket->GetPort()
<< " failed: " << httpListeningSocket->GetErrorText());
return FALSE;
}
if (stackSize > 1000)
new PHTTPServiceThread(stackSize, *this);
return TRUE;
}
void PHTTPServiceProcess::ShutdownListener()
{
if (httpListeningSocket == NULL)
return;
if (!httpListeningSocket->IsOpen())
return;
PSYSTEMLOG(Debug, "HTTPSVC\tClosing listener socket on port "
<< httpListeningSocket->GetPort());
httpListeningSocket->Close();
httpThreadsMutex.Wait();
for (PINDEX i = 0; i < httpThreads.GetSize(); i++)
httpThreads[i].Close();
while (httpThreads.GetSize() > 0) {
httpThreadsMutex.Signal();
Sleep(1);
httpThreadsMutex.Wait();
}
httpThreadsMutex.Signal();
delete httpListeningSocket;
httpListeningSocket = NULL;
}
PString PHTTPServiceProcess::GetCopyrightText()
{
PHTML html(PHTML::InBody);
html << "Copyright ©"
<< compilationDate.AsString("yyyy") << " by "
<< PHTML::HotLink(copyrightHomePage)
<< copyrightHolder
<< PHTML::HotLink()
<< ", "
<< PHTML::HotLink("mailto:" + copyrightEmail)
<< copyrightEmail
<< PHTML::HotLink();
return html;
}
PString PHTTPServiceProcess::GetPageGraphic()
{
PFile header;
if (header.Open("header.html", PFile::ReadOnly))
return header.ReadString(header.GetLength());
PHTML html(PHTML::InBody);
html << PHTML::TableStart()
<< PHTML::TableRow()
<< PHTML::TableData();
if (gifHTML.IsEmpty())
html << PHTML::Heading(1) << productNameHTML << " " << PHTML::Heading(1);
else
html << gifHTML;
html << PHTML::TableData()
<< PHTML::Bold() << GetName() << PHTML::Bold() << PHTML::BreakLine()
<< GetOSClass() << ' ' << GetOSName()
<< " Version " << GetVersion(TRUE) << PHTML::BreakLine()
<< ' ' << GetCompilationDate().AsString("d MMMM yyyy")
<< PHTML::BreakLine()
<< "By "
<< PHTML::HotLink(manufacturersHomePage) << GetManufacturer() << PHTML::HotLink()
<< ", "
<< PHTML::HotLink("mailto:" + manufacturersEmail) << manufacturersEmail << PHTML::HotLink()
<< PHTML::TableEnd()
<< PHTML::HRule();
return html;
}
void PHTTPServiceProcess::GetPageHeader(PHTML & html)
{
GetPageHeader(html, GetName());
}
void PHTTPServiceProcess::GetPageHeader(PHTML & html, const PString & title)
{
html << PHTML::Title(title)
<< PHTML::Body()
<< GetPageGraphic();
}
PTCPSocket * PHTTPServiceProcess::AcceptHTTP()
{
if (httpListeningSocket == NULL)
return NULL;
if (!httpListeningSocket->IsOpen())
return NULL;
// get a socket when a client connects
PTCPSocket * socket = new PTCPSocket;
if (socket->Accept(*httpListeningSocket))
return socket;
if (socket->GetErrorCode() != PChannel::Interrupted)
PSYSTEMLOG(Error, "Accept failed for HTTP: " << socket->GetErrorText());
if (httpListeningSocket != NULL && httpListeningSocket->IsOpen())
return socket;
delete socket;
return NULL;
}
BOOL PHTTPServiceProcess::ProcessHTTP(PTCPSocket & socket)
{
if (!socket.IsOpen())
return TRUE;
PHTTPServer * server = CreateHTTPServer(socket);
if (server == NULL) {
PSYSTEMLOG(Error, "HTTP server creation/open failed.");
return TRUE;
}
// process requests
while (server->ProcessCommand())
;
// always close after the response has been sent
delete server;
// if a restart was requested, then do it, but only if we are not shutting down
if (httpListeningSocket->IsOpen())
CompleteRestartSystem();
return TRUE;
}
void PHTTPServiceProcess::BeginRestartSystem()
{
if (restartThread == NULL) {
restartThread = PThread::Current();
OnConfigChanged();
}
}
void PHTTPServiceProcess::CompleteRestartSystem()
{
if (restartThread == NULL)
return;
if (restartThread != PThread::Current())
return;
httpNameSpace.StartWrite();
if (Initialise("Restart\tInitialisation"))
restartThread = NULL;
httpNameSpace.EndWrite();
if (restartThread != NULL)
Terminate();
}
void PHTTPServiceProcess::AddRegisteredText(PHTML &)
{
}
void PHTTPServiceProcess::AddUnregisteredText(PHTML &)
{
}
BOOL PHTTPServiceProcess::SubstituteEquivalSequence(PHTTPRequest &, const PString &, PString &)
{
return FALSE;
}
PHTTPServer * PHTTPServiceProcess::CreateHTTPServer(PTCPSocket & socket)
{
#ifdef SO_LINGER
const linger ling = { 1, 5 };
socket.SetOption(SO_LINGER, &ling, sizeof(ling));
#endif
PHTTPServer * server = OnCreateHTTPServer(httpNameSpace);
if (server->Open(socket))
return server;
delete server;
return NULL;
}
PHTTPServer * PHTTPServiceProcess::OnCreateHTTPServer(const PHTTPSpace & httpNameSpace)
{
return new PHTTPServer(httpNameSpace);
}
//////////////////////////////////////////////////////////////
PHTTPServiceThread::PHTTPServiceThread(PINDEX stackSize,
PHTTPServiceProcess & app)
: PThread(stackSize, AutoDeleteThread, NormalPriority, "HTTP Service:%x"),
process(app)
{
process.httpThreadsMutex.Wait();
process.httpThreads.Append(this);
process.httpThreadsMutex.Signal();
myStackSize = stackSize;
socket = NULL;
Resume();
}
PHTTPServiceThread::~PHTTPServiceThread()
{
process.httpThreadsMutex.Wait();
process.httpThreads.Remove(this);
process.httpThreadsMutex.Signal();
delete socket;
}
void PHTTPServiceThread::Close()
{
if (socket != NULL)
socket->Close();
}
void PHTTPServiceThread::Main()
{
PTCPSocket * socket = process.AcceptHTTP();
if (socket != NULL) {
new PHTTPServiceThread(myStackSize, process);
process.ProcessHTTP(*socket);
}
}
//////////////////////////////////////////////////////////////
PConfigPage::PConfigPage(PHTTPServiceProcess & app,
const PString & title,
const PString & section,
const PHTTPAuthority & auth)
: PHTTPConfig(title, section, auth),
process(app)
{
}
PConfigPage::PConfigPage(PHTTPServiceProcess & app,
const PString & section,
const PHTTPAuthority & auth)
: PHTTPConfig(section.ToLower() + ".html", section, auth),
process(app)
{
}
void PConfigPage::OnLoadedText(PHTTPRequest & request, PString & text)
{
PServiceHTML::ProcessMacros(request, text,
GetURL().AsString(PURL::PathOnly).Mid(1),
PServiceHTML::LoadFromFile);
PHTTPConfig::OnLoadedText(request, text);
PServiceHTML::ProcessMacros(request, text, "", PServiceHTML::NoOptions);
}
BOOL PConfigPage::OnPOST(PHTTPServer & server,
const PURL & url,
const PMIMEInfo & info,
const PStringToString & data,
const PHTTPConnectionInfo & connectInfo)
{
PHTTPConfig::OnPOST(server, url, info, data, connectInfo);
return FALSE; // Make sure we break any persistent connections
}
BOOL PConfigPage::Post(PHTTPRequest & request,
const PStringToString & data,
PHTML & reply)
{
PSYSTEMLOG(Debug3, "Post to " << request.url << '\n' << data);
BOOL retval = PHTTPConfig::Post(request, data, reply);
if (request.code == PHTTP::RequestOK)
process.BeginRestartSystem();
PServiceHTML::ProcessMacros(request, reply,
GetURL().AsString(PURL::PathOnly).Mid(1),
PServiceHTML::LoadFromFile);
OnLoadedText(request, reply);
return retval;
}
BOOL PConfigPage::GetExpirationDate(PTime & when)
{
// Well and truly before now....
when = ImmediateExpiryTime;
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -