mirror of
				https://projects.vdr-developer.org/git/vdr-plugin-streamdev.git
				synced 2023-10-10 17:16:51 +00:00 
			
		
		
		
	- replaced the last usleep by cCondWait thanks to Rolf Ahrenberg (#383) Modified Files: Tag: v0_4 CONTRIBUTORS HISTORY server/server.c server/server.h server/streamer.c server/streamer.h server/suspend.c server/suspend.h
		
			
				
	
	
		
			169 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			169 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 *  $Id: server.c,v 1.5.2.3 2008/10/22 11:59:37 schmirl Exp $
 | 
						|
 */
 | 
						|
 | 
						|
#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;
 | 
						|
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);
 | 
						|
 | 
						|
		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");
 | 
						|
#if VDRVERSNUM > 10403
 | 
						|
		Cancel(-1);
 | 
						|
#else
 | 
						|
		return;
 | 
						|
#endif
 | 
						|
	}
 | 
						|
 | 
						|
	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();
 | 
						|
				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);
 | 
						|
	}
 | 
						|
}
 |