/**
* ======================== legal notice ======================
*
* File: HTTPServer.cc
* Created: 4. Juli 2012, 12
* Author: Geronimo
* Project: libnetworking: classes for tcp/ip sockets and http-protocol handling
*
* CMP - compound media player
*
* is a client/server mediaplayer intended to play any media from any workstation
* without the need to export or mount shares. cmps is an easy to use backend
* with a (ready to use) HTML-interface. Additionally the backend supports
* authentication via HTTP-digest authorization.
* cmpc is a client with vdr-like osd-menues.
*
* Copyright (c) 2012 Reinhard Mantey, some rights reserved!
* published under Creative Commons by-sa
* For details see http://creativecommons.org/licenses/by-sa/3.0/
*
* The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp
*
* --------------------------------------------------------------
*/
#include
#include
#include
#include
#include
#include
#include
#include
static volatile bool running = true;
cHTTPServer::cHTTPServer(cServerConfig &Config)
: config(Config)
#ifdef LIVE_CLEANUP
, cleaner(NULL)
#endif
{
threads = new std::vector();
#ifdef LIVE_CLEANUP
cleaner = new cThread(cleanerThread, NULL, "cleanup thread stubs");
#endif
}
cHTTPServer::~cHTTPServer()
{
#ifdef LIVE_CLEANUP
cleaner->Cancel(0);
delete cleaner;
#else
Cleanup();
#endif
delete threads;
}
void cHTTPServer::Action()
{
#ifdef LIVE_CLEANUP
if (cleaner) {
fprintf(stderr, "check size of thread pool ...\n");
if (!threads->empty()) fprintf(stderr, "thread pool has size of %lu\n", threads->size());
fprintf(stderr, "start cleaner thread\n");
cleaner->Start();
}
#endif
fprintf(stderr, "startup server now\n");
ServerSocket().Open();
while (Running()) {
cConnectionPoint *cp = ServerSocket().Accept();
if (cp) {
// this has to come after accept, as the hostnames can not be determined before an established connection.
if (!cHTTPResponse::ServerID()) {
char *id;
asprintf(&id, "HTTPServer %s:%d", ServerSocket().ThisSide()->RealName(), ServerSocket().Port());
cHTTPResponse::SetServerID(id);
}
cConnectionHandler *ch = new cConnectionHandler(*cp, config);
ch->Start();
#ifdef LIVE_CLEANUP
cMutexLock poolSync(&poolMutex);
#endif
threads->push_back(ch);
}
}
}
bool cHTTPServer::Running()
{
return ServerSocket().Active();
}
#ifdef LIVE_CLEANUP
int cHTTPServer::cleanerThread(void *opaque, cThread *ThreadContext)
{
cHTTPServer *server = (cHTTPServer *)opaque;
server->Cleanup(ThreadContext);
return 0;
}
void cHTTPServer::Cleanup(cThread *ThreadContext)
{
if (!ThreadContext) return;
cThread *p;
fprintf(stderr, "cleanup-Thread - gonna start loop ...\n");
while (ThreadContext->Running()) {
fprintf(stderr, "check list of possible threads ...\n");
if (!threads->empty()) {
fprintf(stderr, "thread pool is not empty ...\n");
for (size_t i=0; i < threads->size(); ++i) {
fprintf(stderr, "ok, got first entry to check ...\n");
p = (*threads)[i];
if (p->Active()) continue;
fprintf(stderr, "thread %lu looks dead ...\n", i);
isyslog("thread %lu is not active, so just clean it up", i);
p->Cancel();
delete p;
cMutexLock poolSync(&poolMutex);
threads->erase(threads->begin() + i);
break;
}
}
cCondWait::SleepMs(200);
}
ThreadContext->Cancel();
}
#else
void cHTTPServer::Cleanup()
{
cThread *t;
for (size_t i=0; i < threads->size(); ++i) {
t = (*threads)[i];
t->Cancel();
delete t;
}
}
#endif
bool cHTTPServer::Start()
{
Action();
return true;
}
void cHTTPServer::Stop()
{
ServerSocket().SetActive(false);
}