vdr-plugin-streamdev/server/server.c

170 lines
3.9 KiB
C
Raw Normal View History

2004-12-30 23:43:55 +01:00
/*
* $Id: server.c,v 1.5 2007/04/02 10:32:34 schmirl Exp $
2004-12-30 23:43:55 +01:00
*/
#include "server/server.h"
#include "server/componentVTP.h"
#include "server/componentHTTP.h"
#include "server/setup.h"
#include <vdr/tools.h>
#include <tools/select.h>
#include <string.h>
#include <errno.h>
cSVDRPhosts StreamdevHosts;
2005-05-09 22:22:29 +02:00
cStreamdevServer *cStreamdevServer::m_Instance = NULL;
cList<cServerComponent> cStreamdevServer::m_Servers;
cList<cServerConnection> cStreamdevServer::m_Clients;
2004-12-30 23:43:55 +01:00
2005-05-09 22:22:29 +02:00
cStreamdevServer::cStreamdevServer(void):
cThread("streamdev server"),
m_Active(false)
2004-12-30 23:43:55 +01:00
{
2005-05-09 22:22:29 +02:00
Start();
2004-12-30 23:43:55 +01:00
}
2005-05-09 22:22:29 +02:00
cStreamdevServer::~cStreamdevServer()
{
Stop();
2004-12-30 23:43:55 +01:00
}
2005-05-09 22:22:29 +02:00
void cStreamdevServer::Initialize(void)
{
2004-12-30 23:43:55 +01:00
if (m_Instance == NULL) {
2005-05-09 22:22:29 +02:00
if (StreamdevServerSetup.StartVTPServer) Register(new cComponentVTP);
if (StreamdevServerSetup.StartHTTPServer) Register(new cComponentHTTP);
2004-12-30 23:43:55 +01:00
m_Instance = new cStreamdevServer;
}
}
2005-05-09 22:22:29 +02:00
void cStreamdevServer::Destruct(void)
{
DELETENULL(m_Instance);
2004-12-30 23:43:55 +01:00
}
2005-05-09 22:22:29 +02:00
void cStreamdevServer::Stop(void)
{
if (m_Active) {
m_Active = false;
Cancel(3);
}
2004-12-30 23:43:55 +01:00
}
2005-05-09 22:22:29 +02:00
void cStreamdevServer::Register(cServerComponent *Server)
{
2004-12-30 23:43:55 +01:00
m_Servers.Add(Server);
}
2005-05-09 22:22:29 +02:00
void cStreamdevServer::Action(void)
{
2004-12-30 23:43:55 +01:00
m_Active = true;
/* Initialize Server components, deleting those that failed */
for (cServerComponent *c = m_Servers.First(); c;) {
cServerComponent *next = m_Servers.Next(c);
2005-05-09 22:22:29 +02:00
if (!c->Initialize())
2004-12-30 23:43:55 +01:00
m_Servers.Del(c);
c = next;
}
2005-05-09 22:22:29 +02:00
if (m_Servers.Count() == 0) {
esyslog("ERROR: no streamdev server activated, exiting");
2004-12-30 23:43:55 +01:00
m_Active = false;
}
2005-05-09 22:22:29 +02:00
cTBSelect select;
2004-12-30 23:43:55 +01:00
while (m_Active) {
select.Clear();
/* Ask all Server components to register to the selector */
for (cServerComponent *c = m_Servers.First(); c; c = m_Servers.Next(c))
2005-05-09 22:22:29 +02:00
select.Add(c->Socket(), false);
2004-12-30 23:43:55 +01:00
/* Ask all Client connections to register to the selector */
for (cServerConnection *s = m_Clients.First(); s; s = m_Clients.Next(s))
2005-05-09 22:22:29 +02:00
{
select.Add(s->Socket(), false);
if (s->HasData())
select.Add(s->Socket(), true);
}
2004-12-30 23:43:55 +01:00
int sel;
do
{
sel = select.Select(400);
if (sel < 0 && errno == ETIMEDOUT) {
// check for aborted clients
for (cServerConnection *s = m_Clients.First(); s; s = m_Clients.Next(s)) {
if (s->Abort())
sel = 0;
}
}
} while (sel < 0 && errno == ETIMEDOUT && m_Active);
if (!m_Active)
break;
if (sel < 0) {
esyslog("fatal error, server exiting: %m");
2005-05-09 22:22:29 +02:00
break;
2004-12-30 23:43:55 +01:00
}
/* Ask all Server components to act on signalled sockets */
2005-05-09 22:22:29 +02:00
for (cServerComponent *c = m_Servers.First(); c; c = m_Servers.Next(c)){
if (sel && select.CanRead(c->Socket())) {
2005-05-09 22:22:29 +02:00
cServerConnection *client = c->Accept();
2004-12-30 23:43:55 +01:00
m_Clients.Add(client);
if (m_Clients.Count() > StreamdevServerSetup.MaxClients) {
2005-05-09 22:22:29 +02:00
esyslog("streamdev: too many clients, rejecting %s:%d",
2005-02-08 18:22:35 +01:00
client->RemoteIp().c_str(), client->RemotePort());
2004-12-30 23:43:55 +01:00
client->Reject();
} else if (!StreamdevHosts.Acceptable(client->RemoteIpAddr())) {
2005-05-09 22:22:29 +02:00
esyslog("streamdev: client %s:%d not allowed to connect",
2005-02-08 18:22:35 +01:00
client->RemoteIp().c_str(), client->RemotePort());
2004-12-30 23:43:55 +01:00
client->Reject();
} else
client->Welcome();
}
}
/* Ask all Client connections to act on signalled sockets */
for (cServerConnection *s = m_Clients.First(); s;) {
2005-05-09 22:22:29 +02:00
bool result = true;
if (sel && select.CanWrite(s->Socket()))
2005-05-09 22:22:29 +02:00
result = s->Write();
if (sel && result && select.CanRead(s->Socket()))
2005-05-09 22:22:29 +02:00
result = s->Read();
result &= !s->Abort();
2005-05-09 22:22:29 +02:00
2004-12-30 23:43:55 +01:00
cServerConnection *next = m_Clients.Next(s);
2005-05-09 22:22:29 +02:00
if (!result) {
isyslog("streamdev: closing streamdev connection to %s:%d",
s->RemoteIp().c_str(), s->RemotePort());
2004-12-30 23:43:55 +01:00
s->Close();
m_Clients.Del(s);
}
s = next;
}
}
2005-05-09 22:22:29 +02:00
while (m_Clients.Count() > 0) {
cServerConnection *s = m_Clients.First();
s->Close();
m_Clients.Del(s);
2004-12-30 23:43:55 +01:00
}
2005-05-09 22:22:29 +02:00
while (m_Servers.Count() > 0) {
cServerComponent *c = m_Servers.First();
c->Destruct();
m_Servers.Del(c);
2004-12-30 23:43:55 +01:00
}
2005-05-09 22:22:29 +02:00
m_Active = false;
2004-12-30 23:43:55 +01:00
}