2004-12-30 23:43:55 +01:00
|
|
|
/*
|
2007-04-02 12:32:34 +02: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
|
|
|
|
2007-04-02 12:32:34 +02: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);
|
2006-11-10 12:52:41 +01:00
|
|
|
|
2007-04-02 12:32:34 +02:00
|
|
|
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)){
|
2007-04-02 12:32:34 +02:00
|
|
|
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;
|
|
|
|
|
2007-04-02 12:32:34 +02:00
|
|
|
if (sel && select.CanWrite(s->Socket()))
|
2005-05-09 22:22:29 +02:00
|
|
|
result = s->Write();
|
|
|
|
|
2007-04-02 12:32:34 +02:00
|
|
|
if (sel && result && select.CanRead(s->Socket()))
|
2005-05-09 22:22:29 +02:00
|
|
|
result = s->Read();
|
2007-04-02 12:32:34 +02:00
|
|
|
|
|
|
|
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
|
|
|
}
|