summaryrefslogtreecommitdiff
path: root/plugins/streamdev/streamdev-cvs/server/server.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/streamdev/streamdev-cvs/server/server.c')
-rw-r--r--plugins/streamdev/streamdev-cvs/server/server.c173
1 files changed, 173 insertions, 0 deletions
diff --git a/plugins/streamdev/streamdev-cvs/server/server.c b/plugins/streamdev/streamdev-cvs/server/server.c
new file mode 100644
index 0000000..1bdb20a
--- /dev/null
+++ b/plugins/streamdev/streamdev-cvs/server/server.c
@@ -0,0 +1,173 @@
+/*
+ * $Id: server.c,v 1.10 2009/02/13 10:39:22 schmirl Exp $
+ */
+
+#include "server/server.h"
+#include "server/componentVTP.h"
+#include "server/componentHTTP.h"
+#include "server/componentIGMP.h"
+#include "server/setup.h"
+
+#include <vdr/tools.h>
+#include <tools/select.h>
+#include <string.h>
+#include <errno.h>
+
+cSVDRPhosts StreamdevHosts;
+char *opt_auth = NULL;
+char *opt_remux = NULL;
+
+cStreamdevServer *cStreamdevServer::m_Instance = NULL;
+cList<cServerComponent> cStreamdevServer::m_Servers;
+cList<cServerConnection> cStreamdevServer::m_Clients;
+
+cStreamdevServer::cStreamdevServer(void):
+ cThread("streamdev server")
+{
+ Start();
+}
+
+cStreamdevServer::~cStreamdevServer()
+{
+ Stop();
+}
+
+void cStreamdevServer::Initialize(void)
+{
+ if (m_Instance == NULL) {
+ if (StreamdevServerSetup.StartVTPServer) Register(new cComponentVTP);
+ if (StreamdevServerSetup.StartHTTPServer) Register(new cComponentHTTP);
+ if (StreamdevServerSetup.StartIGMPServer) {
+ if (strcmp(StreamdevServerSetup.IGMPBindIP, "0.0.0.0") == 0)
+ esyslog("streamdev-server: Not starting IGMP. IGMP must be bound to a local IP");
+ else
+ Register(new cComponentIGMP);
+ }
+
+ m_Instance = new cStreamdevServer;
+ }
+}
+
+void cStreamdevServer::Destruct(void)
+{
+ DELETENULL(m_Instance);
+}
+
+void cStreamdevServer::Stop(void)
+{
+ if (Running())
+ Cancel(3);
+}
+
+void cStreamdevServer::Register(cServerComponent *Server)
+{
+ m_Servers.Add(Server);
+}
+
+void cStreamdevServer::Action(void)
+{
+ /* Initialize Server components, deleting those that failed */
+ for (cServerComponent *c = m_Servers.First(); c;) {
+ cServerComponent *next = m_Servers.Next(c);
+ if (!c->Initialize())
+ m_Servers.Del(c);
+ c = next;
+ }
+
+ if (m_Servers.Count() == 0) {
+ esyslog("ERROR: no streamdev server activated, exiting");
+ Cancel(-1);
+ }
+
+ cTBSelect select;
+ while (Running()) {
+ select.Clear();
+
+ /* Ask all Server components to register to the selector */
+ for (cServerComponent *c = m_Servers.First(); c; c = m_Servers.Next(c))
+ select.Add(c->Socket(), false);
+
+ /* Ask all Client connections to register to the selector */
+ for (cServerConnection *s = m_Clients.First(); s; s = m_Clients.Next(s))
+ {
+ select.Add(s->Socket(), false);
+ if (s->HasData())
+ select.Add(s->Socket(), true);
+ }
+
+ 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 && Running());
+
+ if (!Running())
+ break;
+ if (sel < 0) {
+ esyslog("fatal error, server exiting: %m");
+ break;
+ }
+
+ /* Ask all Server components to act on signalled sockets */
+ for (cServerComponent *c = m_Servers.First(); c; c = m_Servers.Next(c)){
+ if (sel && select.CanRead(c->Socket())) {
+ cServerConnection *client = c->Accept();
+ if (!client)
+ continue;
+ m_Clients.Add(client);
+
+ if (m_Clients.Count() > StreamdevServerSetup.MaxClients) {
+ esyslog("streamdev: too many clients, rejecting %s:%d",
+ client->RemoteIp().c_str(), client->RemotePort());
+ client->Reject();
+ } else if (!client->CanAuthenticate() && !StreamdevHosts.Acceptable(client->RemoteIpAddr())) {
+ esyslog("streamdev: client %s:%d not allowed to connect",
+ client->RemoteIp().c_str(), client->RemotePort());
+ client->Reject();
+ } else
+ client->Welcome();
+ }
+ }
+
+ /* Ask all Client connections to act on signalled sockets */
+ for (cServerConnection *s = m_Clients.First(); s;) {
+ bool result = true;
+
+ if (sel && select.CanWrite(s->Socket()))
+ result = s->Write();
+
+ if (sel && result && select.CanRead(s->Socket()))
+ result = s->Read();
+
+ result &= !s->Abort();
+
+ cServerConnection *next = m_Clients.Next(s);
+ if (!result) {
+ isyslog("streamdev: closing streamdev connection to %s:%d",
+ s->RemoteIp().c_str(), s->RemotePort());
+ s->Close();
+ m_Clients.Del(s);
+ }
+ s = next;
+ }
+ }
+
+ while (m_Clients.Count() > 0) {
+ cServerConnection *s = m_Clients.First();
+ s->Close();
+ m_Clients.Del(s);
+ }
+
+ while (m_Servers.Count() > 0) {
+ cServerComponent *c = m_Servers.First();
+ c->Destruct();
+ m_Servers.Del(c);
+ }
+}