mirror of
https://projects.vdr-developer.org/git/vdr-plugin-streamdev.git
synced 2023-10-10 19:16:51 +02:00
- added TS compatibility mode
This commit is contained in:
parent
3eec47314d
commit
450c8fd4a7
5
common.h
5
common.h
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: common.h,v 1.5 2005/02/11 16:44:14 lordjaxom Exp $
|
* $Id: common.h,v 1.6 2005/05/09 20:22:29 lordjaxom Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef VDR_STREAMDEV_COMMON_H
|
#ifndef VDR_STREAMDEV_COMMON_H
|
||||||
@ -50,9 +50,6 @@ const cChannel *ChannelFromString(const char *String, int *Apid = NULL);
|
|||||||
#define BUFOVERTIME 5000
|
#define BUFOVERTIME 5000
|
||||||
#define BUFOVERCOUNT 100
|
#define BUFOVERCOUNT 100
|
||||||
|
|
||||||
#define STREAMDEVHOSTS (const char*)AddDirectory(cPlugin::ConfigDirectory(), \
|
|
||||||
"streamdevhosts.conf")
|
|
||||||
|
|
||||||
#define POLLFAIL esyslog("Streamdev: Polling failed: %s", strerror(errno))
|
#define POLLFAIL esyslog("Streamdev: Polling failed: %s", strerror(errno))
|
||||||
#define WRITEFAIL esyslog("Streamdev: Writing failed: %s", strerror(errno))
|
#define WRITEFAIL esyslog("Streamdev: Writing failed: %s", strerror(errno))
|
||||||
#define READFAIL esyslog("Streamdev: Reading failed: %s", strerror(errno))
|
#define READFAIL esyslog("Streamdev: Reading failed: %s", strerror(errno))
|
||||||
|
@ -1,50 +1,48 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: component.c,v 1.2 2005/02/08 17:22:35 lordjaxom Exp $
|
* $Id: component.c,v 1.3 2005/05/09 20:22:29 lordjaxom Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "server/component.h"
|
#include "server/component.h"
|
||||||
#include "server/connection.h"
|
#include "server/connection.h"
|
||||||
|
|
||||||
#include <vdr/tools.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
cServerComponent::cServerComponent(const char *Protocol, const char *ListenIp,
|
cServerComponent::cServerComponent(const char *Protocol, const char *ListenIp,
|
||||||
uint ListenPort) {
|
uint ListenPort):
|
||||||
m_Protocol = Protocol;
|
m_Protocol(Protocol),
|
||||||
m_ListenIp = ListenIp;
|
m_ListenIp(ListenIp),
|
||||||
m_ListenPort = ListenPort;
|
m_ListenPort(ListenPort)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
cServerComponent::~cServerComponent() {
|
cServerComponent::~cServerComponent()
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cServerComponent::Init(void) {
|
bool cServerComponent::Initialize(void)
|
||||||
|
{
|
||||||
if (!m_Listen.Listen(m_ListenIp, m_ListenPort, 5)) {
|
if (!m_Listen.Listen(m_ListenIp, m_ListenPort, 5)) {
|
||||||
esyslog("Streamdev: Couldn't listen (%s) %s:%d: %s", m_Protocol, m_ListenIp,
|
esyslog("Streamdev: Couldn't listen (%s) %s:%d: %m",
|
||||||
m_ListenPort, strerror(errno));
|
m_Protocol, m_ListenIp, m_ListenPort);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
isyslog("Streamdev: Listening (%s) on port %d", m_Protocol, m_ListenPort);
|
isyslog("Streamdev: Listening (%s) on port %d", m_Protocol, m_ListenPort);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cServerComponent::Exit(void) {
|
void cServerComponent::Destruct(void)
|
||||||
|
{
|
||||||
m_Listen.Close();
|
m_Listen.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
cServerConnection *cServerComponent::CanAct(const cTBSelect &Select) {
|
cServerConnection *cServerComponent::Accept(void)
|
||||||
if (Select.CanRead(m_Listen)) {
|
{
|
||||||
cServerConnection *client = NewConnection();
|
cServerConnection *client = NewClient();
|
||||||
if (client->Accept(m_Listen)) {
|
if (client->Accept(m_Listen)) {
|
||||||
isyslog("Streamdev: Accepted new client (%s) %s:%d", m_Protocol,
|
isyslog("Streamdev: Accepted new client (%s) %s:%d", m_Protocol,
|
||||||
client->RemoteIp().c_str(), client->RemotePort());
|
client->RemoteIp().c_str(), client->RemotePort());
|
||||||
return client;
|
return client;
|
||||||
} else {
|
} else {
|
||||||
esyslog("Streamdev: Couldn't accept (%s): %s", m_Protocol,
|
esyslog("Streamdev: Couldn't accept (%s): %m", m_Protocol);
|
||||||
strerror(errno));
|
delete client;
|
||||||
delete client;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: component.h,v 1.1 2004/12/30 22:44:18 lordjaxom Exp $
|
* $Id: component.h,v 1.2 2005/05/09 20:22:29 lordjaxom Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef VDR_STREAMDEV_SERVERS_COMPONENT_H
|
#ifndef VDR_STREAMDEV_SERVERS_COMPONENT_H
|
||||||
@ -22,29 +22,30 @@ private:
|
|||||||
const char *m_ListenIp;
|
const char *m_ListenIp;
|
||||||
uint m_ListenPort;
|
uint m_ListenPort;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/* Returns a new connection object for Accept() */
|
||||||
|
virtual cServerConnection *NewClient(void) = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cServerComponent(const char *Protocol, const char *ListenIp, uint ListenPort);
|
cServerComponent(const char *Protocol, const char *ListenIp, uint ListenPort);
|
||||||
virtual ~cServerComponent();
|
virtual ~cServerComponent();
|
||||||
|
|
||||||
/* Starts listening on the specified Port, override if you want to do things
|
/* Starts listening on the specified Port, override if you want to do things
|
||||||
different */
|
different */
|
||||||
virtual bool Init(void);
|
virtual bool Initialize(void);
|
||||||
|
|
||||||
/* Stops listening, override if you want to do things different */
|
/* Stops listening, override if you want to do things different */
|
||||||
virtual void Exit(void);
|
virtual void Destruct(void);
|
||||||
|
|
||||||
|
/* Get the listening socket's file number */
|
||||||
|
virtual int Socket(void) const { return (int)m_Listen; }
|
||||||
|
|
||||||
/* Adds the listening socket to the Select object */
|
/* Adds the listening socket to the Select object */
|
||||||
virtual void AddSelect(cTBSelect &Select) const { Select.Add(m_Listen); }
|
virtual void Add(cTBSelect &Select) const { Select.Add(m_Listen); }
|
||||||
|
|
||||||
/* Accepts the connection on a NewConnection() object and calls the
|
/* Accepts the connection on a NewClient() object and calls the
|
||||||
Welcome() on it, override if you want to do things different */
|
Welcome() on it, override if you want to do things different */
|
||||||
virtual cServerConnection *CanAct(const cTBSelect &Select);
|
virtual cServerConnection *Accept(void);
|
||||||
|
|
||||||
/* Returns a new connection object for CanAct */
|
|
||||||
virtual cServerConnection *NewConnection(void) const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class cServerComponents: public cList<cServerComponent> {
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // VDR_STREAMDEV_SERVERS_COMPONENT_H
|
#endif // VDR_STREAMDEV_SERVERS_COMPONENT_H
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: componentHTTP.c,v 1.1 2004/12/30 22:44:19 lordjaxom Exp $
|
* $Id: componentHTTP.c,v 1.2 2005/05/09 20:22:29 lordjaxom Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "server/componentHTTP.h"
|
#include "server/componentHTTP.h"
|
||||||
@ -7,9 +7,12 @@
|
|||||||
#include "server/setup.h"
|
#include "server/setup.h"
|
||||||
|
|
||||||
cComponentHTTP::cComponentHTTP(void):
|
cComponentHTTP::cComponentHTTP(void):
|
||||||
cServerComponent("HTTP", StreamdevServerSetup.HTTPBindIP,
|
cServerComponent("HTTP", StreamdevServerSetup.HTTPBindIP,
|
||||||
StreamdevServerSetup.HTTPServerPort) {
|
StreamdevServerSetup.HTTPServerPort)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
cComponentHTTP::~cComponentHTTP() {
|
cServerConnection *cComponentHTTP::NewClient(void)
|
||||||
|
{
|
||||||
|
return new cConnectionHTTP;
|
||||||
}
|
}
|
||||||
|
@ -1,26 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: componentHTTP.h,v 1.1 2004/12/30 22:44:19 lordjaxom Exp $
|
* $Id: componentHTTP.h,v 1.2 2005/05/09 20:22:29 lordjaxom Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef VDR_STREAMDEV_HTTPSERVER_H
|
#ifndef VDR_STREAMDEV_HTTPSERVER_H
|
||||||
#define VDR_STREAMDEV_HTTPSERVER_H
|
#define VDR_STREAMDEV_HTTPSERVER_H
|
||||||
|
|
||||||
#include "server/component.h"
|
#include "server/component.h"
|
||||||
#include "server/connectionHTTP.h"
|
|
||||||
|
|
||||||
#include <tools/socket.h>
|
|
||||||
#include <tools/select.h>
|
|
||||||
|
|
||||||
class cComponentHTTP: public cServerComponent {
|
class cComponentHTTP: public cServerComponent {
|
||||||
|
protected:
|
||||||
|
virtual cServerConnection *NewClient(void);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cComponentHTTP(void);
|
cComponentHTTP(void);
|
||||||
~cComponentHTTP(void);
|
|
||||||
|
|
||||||
virtual cServerConnection *NewConnection(void) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline cServerConnection *cComponentHTTP::NewConnection(void) const {
|
|
||||||
return new cConnectionHTTP;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // VDR_STREAMDEV_HTTPSERVER_H
|
#endif // VDR_STREAMDEV_HTTPSERVER_H
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: componentVTP.c,v 1.1 2004/12/30 22:44:19 lordjaxom Exp $
|
* $Id: componentVTP.c,v 1.2 2005/05/09 20:22:29 lordjaxom Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "server/componentVTP.h"
|
#include "server/componentVTP.h"
|
||||||
@ -7,9 +7,12 @@
|
|||||||
#include "server/setup.h"
|
#include "server/setup.h"
|
||||||
|
|
||||||
cComponentVTP::cComponentVTP(void):
|
cComponentVTP::cComponentVTP(void):
|
||||||
cServerComponent("VTP", StreamdevServerSetup.VTPBindIP,
|
cServerComponent("VTP", StreamdevServerSetup.VTPBindIP,
|
||||||
StreamdevServerSetup.VTPServerPort) {
|
StreamdevServerSetup.VTPServerPort)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
cComponentVTP::~cComponentVTP() {
|
cServerConnection *cComponentVTP::NewClient(void)
|
||||||
|
{
|
||||||
|
return new cConnectionVTP;
|
||||||
}
|
}
|
||||||
|
@ -1,29 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: componentVTP.h,v 1.1 2004/12/30 22:44:19 lordjaxom Exp $
|
* $Id: componentVTP.h,v 1.2 2005/05/09 20:22:29 lordjaxom Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef VDR_STREAMDEV_SERVERS_SERVERVTP_H
|
#ifndef VDR_STREAMDEV_SERVERS_SERVERVTP_H
|
||||||
#define VDR_STREAMDEV_SERVERS_SERVERVTP_H
|
#define VDR_STREAMDEV_SERVERS_SERVERVTP_H
|
||||||
|
|
||||||
#include "server/component.h"
|
#include "server/component.h"
|
||||||
#include "server/connectionVTP.h"
|
|
||||||
|
|
||||||
#include <tools/socket.h>
|
|
||||||
#include <tools/select.h>
|
|
||||||
|
|
||||||
class cComponentVTP: public cServerComponent {
|
class cComponentVTP: public cServerComponent {
|
||||||
private:
|
protected:
|
||||||
cTBSocket m_Listen;
|
virtual cServerConnection *NewClient(void);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cComponentVTP(void);
|
cComponentVTP(void);
|
||||||
virtual ~cComponentVTP();
|
|
||||||
|
|
||||||
virtual cServerConnection *NewConnection(void) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline cServerConnection *cComponentVTP::NewConnection(void) const {
|
|
||||||
return new cConnectionVTP;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // VDR_STREAMDEV_SERVERS_SERVERVTP_H
|
#endif // VDR_STREAMDEV_SERVERS_SERVERVTP_H
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: connection.c,v 1.3 2005/03/24 21:31:38 lordjaxom Exp $
|
* $Id: connection.c,v 1.4 2005/05/09 20:22:29 lordjaxom Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "server/connection.h"
|
#include "server/connection.h"
|
||||||
@ -11,53 +11,79 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
cServerConnection::cServerConnection(const char *Protocol) {
|
cServerConnection::cServerConnection(const char *Protocol):
|
||||||
m_RdBytes = 0;
|
m_Protocol(Protocol),
|
||||||
m_WrBytes = 0;
|
m_DeferClose(false),
|
||||||
m_WrOffs = 0;
|
m_Pending(false),
|
||||||
m_DeferClose = false;
|
m_ReadBytes(0),
|
||||||
m_Protocol = Protocol;
|
m_WriteBytes(0),
|
||||||
|
m_WriteIndex(0)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
cServerConnection::~cServerConnection() {
|
cServerConnection::~cServerConnection()
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cServerConnection::CanAct(const cTBSelect &Select) {
|
bool cServerConnection::Read(void)
|
||||||
if (Select.CanRead(*this)) {
|
{
|
||||||
int b;
|
int b;
|
||||||
if ((b = Read(m_RdBuf + m_RdBytes, sizeof(m_RdBuf) - m_RdBytes - 1)) < 0) {
|
if ((b = cTBSocket::Read(m_ReadBuffer + m_ReadBytes,
|
||||||
esyslog("Streamdev: Read from client (%s) %s:%d failed: %s", m_Protocol,
|
sizeof(m_ReadBuffer) - m_ReadBytes - 1)) < 0) {
|
||||||
RemoteIp().c_str(), RemotePort(), strerror(errno));
|
esyslog("ERROR: read from client (%s) %s:%d failed: %m",
|
||||||
return false;
|
m_Protocol, RemoteIp().c_str(), RemotePort());
|
||||||
}
|
return false;
|
||||||
|
|
||||||
if (b == 0) {
|
|
||||||
isyslog("Streamdev: Client (%s) %s:%d closed connection", m_Protocol,
|
|
||||||
RemoteIp().c_str(), RemotePort());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_RdBytes += b;
|
|
||||||
m_RdBuf[m_RdBytes] = '\0';
|
|
||||||
return ParseBuffer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Select.CanWrite(*this)) {
|
if (b == 0) {
|
||||||
int b;
|
isyslog("client (%s) %s:%d has closed connection",
|
||||||
if ((b = Write(m_WrBuf + m_WrOffs, m_WrBytes - m_WrOffs)) < 0) {
|
m_Protocol, RemoteIp().c_str(), RemotePort());
|
||||||
esyslog("Streamdev: Write to client (%s) %s:%d failed: %s", m_Protocol,
|
return false;
|
||||||
RemoteIp().c_str(), RemotePort(), strerror(errno));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_WrOffs += b;
|
|
||||||
if (m_WrOffs == m_WrBytes) {
|
|
||||||
m_WrBytes = 0;
|
|
||||||
m_WrOffs = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_WrBytes == 0) {
|
m_ReadBytes += b;
|
||||||
|
m_ReadBuffer[m_ReadBytes] = '\0';
|
||||||
|
|
||||||
|
char *end;
|
||||||
|
bool result = true;
|
||||||
|
while ((end = strchr(m_ReadBuffer, '\012')) != NULL) {
|
||||||
|
*end = '\0';
|
||||||
|
if (end > m_ReadBuffer && *(end - 1) == '\015')
|
||||||
|
*(end - 1) = '\0';
|
||||||
|
|
||||||
|
if (!Command(m_ReadBuffer))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_ReadBytes -= ++end - m_ReadBuffer;
|
||||||
|
if (m_ReadBytes > 0)
|
||||||
|
memmove(m_ReadBuffer, end, m_ReadBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_ReadBytes == sizeof(m_ReadBuffer) - 1) {
|
||||||
|
esyslog("ERROR: streamdev: input buffer overflow (%s) for %s:%d",
|
||||||
|
m_Protocol, RemoteIp().c_str(), RemotePort());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cServerConnection::Write(void)
|
||||||
|
{
|
||||||
|
int b;
|
||||||
|
if ((b = cTBSocket::Write(m_WriteBuffer + m_WriteIndex,
|
||||||
|
m_WriteBytes - m_WriteIndex)) < 0) {
|
||||||
|
esyslog("ERROR: streamdev: write to client (%s) %s:%d failed: %m",
|
||||||
|
m_Protocol, RemoteIp().c_str(), RemotePort());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_WriteIndex += b;
|
||||||
|
if (m_WriteIndex == m_WriteBytes) {
|
||||||
|
m_WriteIndex = 0;
|
||||||
|
m_WriteBytes = 0;
|
||||||
|
if (m_Pending)
|
||||||
|
Command(NULL);
|
||||||
if (m_DeferClose)
|
if (m_DeferClose)
|
||||||
return false;
|
return false;
|
||||||
Flushed();
|
Flushed();
|
||||||
@ -65,42 +91,33 @@ bool cServerConnection::CanAct(const cTBSelect &Select) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cServerConnection::ParseBuffer(void) {
|
bool cServerConnection::Respond(const char *Message, bool Last, ...)
|
||||||
char *ep;
|
{
|
||||||
bool res;
|
char *buffer;
|
||||||
|
int length;
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, Last);
|
||||||
|
length = vasprintf(&buffer, Message, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
while ((ep = strchr(m_RdBuf, '\012')) != NULL) {
|
if (m_WriteBytes + length + 2 > sizeof(m_WriteBuffer)) {
|
||||||
*ep = '\0';
|
esyslog("ERROR: streamdev: output buffer overflow (%s) for %s:%d",
|
||||||
if (ep > m_RdBuf && *(ep-1) == '\015')
|
m_Protocol, RemoteIp().c_str(), RemotePort());
|
||||||
*(ep-1) = '\0';
|
|
||||||
|
|
||||||
Dprintf("IN: |%s|\n", m_RdBuf);
|
|
||||||
res = Command(m_RdBuf);
|
|
||||||
m_RdBytes -= ++ep - m_RdBuf;
|
|
||||||
if (m_RdBytes > 0)
|
|
||||||
memmove(m_RdBuf, ep, m_RdBytes);
|
|
||||||
if (res == false)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cServerConnection::Respond(const std::string &Message) {
|
|
||||||
if (m_WrBytes + Message.size() + 2 > sizeof(m_WrBuf)) {
|
|
||||||
esyslog("Streamdev: Output buffer overflow (%s) for %s:%d", m_Protocol,
|
|
||||||
RemoteIp().c_str(), RemotePort());
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Dprintf("OUT: |%s|\n", Message.c_str());
|
Dprintf("OUT: |%s|\n", buffer);
|
||||||
memcpy(m_WrBuf + m_WrBytes, Message.c_str(), Message.size());
|
memcpy(m_WriteBuffer + m_WriteBytes, buffer, length);
|
||||||
|
free(buffer);
|
||||||
|
|
||||||
m_WrBytes += Message.size();
|
m_WriteBytes += length;
|
||||||
m_WrBuf[m_WrBytes++] = '\015';
|
m_WriteBuffer[m_WriteBytes++] = '\015';
|
||||||
m_WrBuf[m_WrBytes++] = '\012';
|
m_WriteBuffer[m_WriteBytes++] = '\012';
|
||||||
|
m_Pending = !Last;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
cDevice *cServerConnection::GetDevice(const cChannel *Channel, int Priority) {
|
cDevice *cServerConnection::GetDevice(const cChannel *Channel, int Priority)
|
||||||
|
{
|
||||||
cDevice *device = NULL;
|
cDevice *device = NULL;
|
||||||
|
|
||||||
/*Dprintf("+ Statistics:\n");
|
/*Dprintf("+ Statistics:\n");
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: connection.h,v 1.2 2005/02/08 17:22:35 lordjaxom Exp $
|
* $Id: connection.h,v 1.3 2005/05/09 20:22:29 lordjaxom Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef VDR_STREAMDEV_SERVER_CONNECTION_H
|
#ifndef VDR_STREAMDEV_SERVER_CONNECTION_H
|
||||||
#define VDR_STREAMDEV_SERVER_CONNECTION_H
|
#define VDR_STREAMDEV_SERVER_CONNECTION_H
|
||||||
|
|
||||||
#include "tools/socket.h"
|
#include "tools/socket.h"
|
||||||
#include "tools/select.h"
|
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
class cChannel;
|
class cChannel;
|
||||||
@ -16,18 +14,32 @@ class cDevice;
|
|||||||
/* Basic capabilities of a straight text-based protocol, most functions
|
/* Basic capabilities of a straight text-based protocol, most functions
|
||||||
virtual to support more complicated protocols */
|
virtual to support more complicated protocols */
|
||||||
|
|
||||||
class cServerConnection: public cListObject, public cTBSocket {
|
class cServerConnection: public cListObject, public cTBSocket
|
||||||
|
{
|
||||||
private:
|
private:
|
||||||
char m_RdBuf[8192];
|
|
||||||
uint m_RdBytes;
|
|
||||||
|
|
||||||
char m_WrBuf[8192];
|
|
||||||
uint m_WrBytes;
|
|
||||||
uint m_WrOffs;
|
|
||||||
|
|
||||||
const char *m_Protocol;
|
const char *m_Protocol;
|
||||||
|
bool m_DeferClose;
|
||||||
|
bool m_Pending;
|
||||||
|
|
||||||
bool m_DeferClose;
|
char m_ReadBuffer[MAXPARSEBUFFER];
|
||||||
|
uint m_ReadBytes;
|
||||||
|
|
||||||
|
char m_WriteBuffer[MAXPARSEBUFFER];
|
||||||
|
uint m_WriteBytes;
|
||||||
|
uint m_WriteIndex;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/* Will be called when a command terminated by a newline has been
|
||||||
|
received */
|
||||||
|
virtual bool Command(char *Cmd) = 0;
|
||||||
|
|
||||||
|
/* Will put Message into the response queue, which will be sent in the next
|
||||||
|
server cycle. Note that Message will be line-terminated by Respond.
|
||||||
|
Only one line at a time may be sent. If there are lines to follow, set
|
||||||
|
Last to false. Command(NULL) will be called in the next cycle, so you can
|
||||||
|
post the next line. */
|
||||||
|
virtual bool Respond(const char *Message, bool Last = true, ...)
|
||||||
|
__attribute__ ((format (printf, 2, 4)));
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/* If you derive, specify a short string such as HTTP for Protocol, which
|
/* If you derive, specify a short string such as HTTP for Protocol, which
|
||||||
@ -41,24 +53,21 @@ public:
|
|||||||
/* Gets called if the client has been rejected by the core */
|
/* Gets called if the client has been rejected by the core */
|
||||||
virtual void Reject(void) { DeferClose(); }
|
virtual void Reject(void) { DeferClose(); }
|
||||||
|
|
||||||
/* Adds itself to the Select object, if data can be received or if data is
|
/* Get the client socket's file number */
|
||||||
to be sent. Override if necessary */
|
virtual int Socket(void) const { return (int)*this; }
|
||||||
virtual void AddSelect(cTBSelect &Select) const;
|
|
||||||
|
|
||||||
/* Receives incoming data and calls ParseBuffer on it. Also writes queued
|
/* Determine if there is data to send or any command pending */
|
||||||
output data if possible. Override if necessary */
|
virtual bool HasData(void) const;
|
||||||
virtual bool CanAct(const cTBSelect &Select);
|
|
||||||
|
|
||||||
/* Called by CanAct(), parses the input buffer for full lines (terminated
|
/* Gets called by server when the socket can accept more data. Writes
|
||||||
either by '\012' or '\015\012') and calls Command on them, if any */
|
the buffer filled up by Respond(). Calls Command(NULL) if there is a
|
||||||
virtual bool ParseBuffer(void);
|
command pending. Returns false in case of an error */
|
||||||
|
virtual bool Write(void);
|
||||||
|
|
||||||
/* Will be called when a command terminated by a newline has been received */
|
/* Gets called by server when there is incoming data to read. Calls
|
||||||
virtual bool Command(char *Cmd) = 0;
|
Command() for each line. Returns false in case of an error, or if
|
||||||
|
the connection shall be closed and removed by the server */
|
||||||
/* Will put Message into the response queue, which will be sent in the next
|
virtual bool Read(void);
|
||||||
server cycle. Note that Message will be line-terminated by Respond */
|
|
||||||
bool Respond(const std::string &Message);
|
|
||||||
|
|
||||||
/* Will make the socket close after sending all queued output data */
|
/* Will make the socket close after sending all queued output data */
|
||||||
void DeferClose(void) { m_DeferClose = true; }
|
void DeferClose(void) { m_DeferClose = true; }
|
||||||
@ -73,15 +82,9 @@ public:
|
|||||||
virtual void Attach(void) = 0;
|
virtual void Attach(void) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class cServerConnections: public cList<cServerConnection> {
|
inline bool cServerConnection::HasData(void) const
|
||||||
};
|
{
|
||||||
|
return m_WriteBytes > 0 || m_Pending || m_DeferClose;
|
||||||
inline void cServerConnection::AddSelect(cTBSelect &Select) const {
|
|
||||||
if (m_WrBytes > 0)
|
|
||||||
Select.Add(*this, true);
|
|
||||||
|
|
||||||
if (m_WrBytes == 0 && m_RdBytes < sizeof(m_RdBuf) - 1)
|
|
||||||
Select.Add(*this, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // VDR_STREAMDEV_SERVER_CONNECTION_H
|
#endif // VDR_STREAMDEV_SERVER_CONNECTION_H
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: connectionHTTP.c,v 1.8 2005/04/24 16:26:14 lordjaxom Exp $
|
* $Id: connectionHTTP.c,v 1.9 2005/05/09 20:22:29 lordjaxom Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@ -45,7 +45,8 @@ bool cConnectionHTTP::Command(char *Cmd)
|
|||||||
return false; // ??? shouldn't happen
|
return false; // ??? shouldn't happen
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cConnectionHTTP::ProcessRequest(void) {
|
bool cConnectionHTTP::ProcessRequest(void)
|
||||||
|
{
|
||||||
Dprintf("process\n");
|
Dprintf("process\n");
|
||||||
if (m_Request.substr(0, 4) == "GET " && CmdGET(m_Request.substr(4))) {
|
if (m_Request.substr(0, 4) == "GET " && CmdGET(m_Request.substr(4))) {
|
||||||
switch (m_Job) {
|
switch (m_Job) {
|
||||||
@ -71,7 +72,7 @@ bool cConnectionHTTP::ProcessRequest(void) {
|
|||||||
if (m_StreamType == stES && (m_Apid != 0 || ISRADIO(m_Channel))) {
|
if (m_StreamType == stES && (m_Apid != 0 || ISRADIO(m_Channel))) {
|
||||||
return Respond("HTTP/1.0 200 OK")
|
return Respond("HTTP/1.0 200 OK")
|
||||||
&& Respond("Content-Type: audio/mpeg")
|
&& Respond("Content-Type: audio/mpeg")
|
||||||
&& Respond((std::string)"icy-name: " + m_Channel->Name())
|
&& Respond("icy-name: %s", true, m_Channel->Name())
|
||||||
&& Respond("");
|
&& Respond("");
|
||||||
} else {
|
} else {
|
||||||
return Respond("HTTP/1.0 200 OK")
|
return Respond("HTTP/1.0 200 OK")
|
||||||
@ -90,7 +91,8 @@ bool cConnectionHTTP::ProcessRequest(void) {
|
|||||||
return Respond("HTTP/1.0 400 Bad Request");
|
return Respond("HTTP/1.0 400 Bad Request");
|
||||||
}
|
}
|
||||||
|
|
||||||
void cConnectionHTTP::Flushed(void) {
|
void cConnectionHTTP::Flushed(void)
|
||||||
|
{
|
||||||
std::string line;
|
std::string line;
|
||||||
|
|
||||||
if (m_Status != hsBody)
|
if (m_Status != hsBody)
|
||||||
@ -132,7 +134,7 @@ void cConnectionHTTP::Flushed(void) {
|
|||||||
}
|
}
|
||||||
line += "</li>";
|
line += "</li>";
|
||||||
}
|
}
|
||||||
if (!Respond(line))
|
if (!Respond(line.c_str()))
|
||||||
DeferClose();
|
DeferClose();
|
||||||
m_ListChannel = Channels.Next(m_ListChannel);
|
m_ListChannel = Channels.Next(m_ListChannel);
|
||||||
break;
|
break;
|
||||||
@ -145,7 +147,8 @@ void cConnectionHTTP::Flushed(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cConnectionHTTP::CmdGET(const std::string &Opts) {
|
bool cConnectionHTTP::CmdGET(const std::string &Opts)
|
||||||
|
{
|
||||||
const char *sp = Opts.c_str(), *ptr = sp, *ep;
|
const char *sp = Opts.c_str(), *ptr = sp, *ep;
|
||||||
const cChannel *chan;
|
const cChannel *chan;
|
||||||
int apid = 0, pos;
|
int apid = 0, pos;
|
||||||
@ -193,33 +196,3 @@ bool cConnectionHTTP::CmdGET(const std::string &Opts) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
bool cHTTPConnection::Listing(void) {
|
|
||||||
cChannel *chan;
|
|
||||||
cTBString line;
|
|
||||||
|
|
||||||
Respond(200, "OK");
|
|
||||||
Respond("Content-Type: text/html");
|
|
||||||
Respond("");
|
|
||||||
Respond("<html><head><title>VDR Channel Listing</title></head>");
|
|
||||||
Respond("<body><ul>");
|
|
||||||
|
|
||||||
for (chan = Channels.First(); chan != NULL; chan = Channels.Next(chan)) {
|
|
||||||
if (chan->GroupSep() && !*chan->Name())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (chan->GroupSep())
|
|
||||||
line.Format("<li>--- %s ---</li>", chan->Name());
|
|
||||||
else
|
|
||||||
line.Format("<li><a href=\"http://%s:%d/%s\">%s</a></li>",
|
|
||||||
(const char*)m_Socket.LocalIp(), StreamdevServerSetup.HTTPServerPort,
|
|
||||||
chan->GetChannelID().ToString(), chan->Name());
|
|
||||||
Respond(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
Respond("</ul></body></html>");
|
|
||||||
|
|
||||||
m_DeferClose = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -3,17 +3,31 @@
|
|||||||
|
|
||||||
#include "server/connection.h"
|
#include "server/connection.h"
|
||||||
|
|
||||||
class cDevice;
|
|
||||||
class cTBSocket;
|
class cTBSocket;
|
||||||
class cStreamdevLiveStreamer;
|
class cStreamdevLiveStreamer;
|
||||||
|
class cLSTEHandler;
|
||||||
|
class cLSTCHandler;
|
||||||
|
class cLSTTHandler;
|
||||||
|
|
||||||
class cConnectionVTP: public cServerConnection {
|
class cConnectionVTP: public cServerConnection {
|
||||||
|
friend class cLSTEHandler;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
cTBSocket *m_DataSockets[si_Count];
|
cTBSocket *m_LiveSocket;
|
||||||
cStreamdevLiveStreamer *m_LiveStreamer;
|
cStreamdevLiveStreamer *m_LiveStreamer;
|
||||||
|
|
||||||
// Members adopted from SVDRP
|
char *m_LastCommand;
|
||||||
|
bool m_NoTSPIDS;
|
||||||
|
|
||||||
|
// Members adopted for SVDRP
|
||||||
cRecordings Recordings;
|
cRecordings Recordings;
|
||||||
|
cLSTEHandler *m_LSTEHandler;
|
||||||
|
cLSTCHandler *m_LSTCHandler;
|
||||||
|
cLSTTHandler *m_LSTTHandler;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
template<class cHandler>
|
||||||
|
bool CmdLSTX(cHandler *&Handler, char *Option);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cConnectionVTP(void);
|
cConnectionVTP(void);
|
||||||
@ -25,7 +39,7 @@ public:
|
|||||||
virtual void Detach(void);
|
virtual void Detach(void);
|
||||||
virtual void Attach(void);
|
virtual void Attach(void);
|
||||||
|
|
||||||
bool Command(char *Cmd);
|
virtual bool Command(char *Cmd);
|
||||||
bool CmdCAPS(char *Opts);
|
bool CmdCAPS(char *Opts);
|
||||||
bool CmdPROV(char *Opts);
|
bool CmdPROV(char *Opts);
|
||||||
bool CmdPORT(char *Opts);
|
bool CmdPORT(char *Opts);
|
||||||
@ -38,17 +52,21 @@ public:
|
|||||||
bool CmdQUIT(char *Opts);
|
bool CmdQUIT(char *Opts);
|
||||||
bool CmdSUSP(char *Opts);
|
bool CmdSUSP(char *Opts);
|
||||||
|
|
||||||
// Commands adopted from SVDRP
|
// Thread-safe implementations of SVDRP commands
|
||||||
bool ReplyWrapper(int Code, const char *fmt, ...);
|
|
||||||
bool CmdLSTE(char *Opts);
|
bool CmdLSTE(char *Opts);
|
||||||
bool CmdLSTR(char *Opts);
|
bool CmdLSTC(char *Opts);
|
||||||
bool CmdDELR(char *Opts);
|
|
||||||
bool CmdLSTT(char *Opts);
|
bool CmdLSTT(char *Opts);
|
||||||
bool CmdMODT(char *Opts);
|
|
||||||
bool CmdNEWT(char *Opts);
|
|
||||||
bool CmdDELT(char *Opts);
|
|
||||||
|
|
||||||
bool Respond(int Code, const std::string &Message);
|
// Commands adopted from SVDRP
|
||||||
|
bool CmdMODT(const char *Option);
|
||||||
|
bool CmdNEWT(const char *Option);
|
||||||
|
bool CmdDELT(const char *Option);
|
||||||
|
|
||||||
|
//bool CmdLSTR(char *Opts);
|
||||||
|
//bool CmdDELR(char *Opts);
|
||||||
|
|
||||||
|
bool Respond(int Code, const char *Message, ...)
|
||||||
|
__attribute__ ((format (printf, 3, 4)));
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // VDR_STREAMDEV_SERVERS_CONNECTIONVTP_H
|
#endif // VDR_STREAMDEV_SERVERS_CONNECTIONVTP_H
|
||||||
|
133
server/server.c
133
server/server.c
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: server.c,v 1.2 2005/02/08 17:22:35 lordjaxom Exp $
|
* $Id: server.c,v 1.3 2005/05/09 20:22:29 lordjaxom Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "server/server.h"
|
#include "server/server.h"
|
||||||
@ -14,102 +14,101 @@
|
|||||||
|
|
||||||
cSVDRPhosts StreamdevHosts;
|
cSVDRPhosts StreamdevHosts;
|
||||||
|
|
||||||
cStreamdevServer *cStreamdevServer::m_Instance = NULL;
|
cStreamdevServer *cStreamdevServer::m_Instance = NULL;
|
||||||
|
cList<cServerComponent> cStreamdevServer::m_Servers;
|
||||||
|
cList<cServerConnection> cStreamdevServer::m_Clients;
|
||||||
|
|
||||||
cStreamdevServer::cStreamdevServer(void)
|
cStreamdevServer::cStreamdevServer(void):
|
||||||
#if VDRVERSNUM >= 10300
|
cThread("streamdev server"),
|
||||||
: cThread("Streamdev: server")
|
m_Active(false)
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
m_Active = false;
|
Start();
|
||||||
|
|
||||||
StreamdevHosts.Load(AddDirectory(cPlugin::ConfigDirectory(),
|
|
||||||
"streamdevhosts.conf"), true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cStreamdevServer::~cStreamdevServer() {
|
cStreamdevServer::~cStreamdevServer()
|
||||||
if (m_Active) Stop();
|
{
|
||||||
|
Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void cStreamdevServer::Init(void) {
|
void cStreamdevServer::Initialize(void)
|
||||||
|
{
|
||||||
if (m_Instance == NULL) {
|
if (m_Instance == NULL) {
|
||||||
|
if (StreamdevServerSetup.StartVTPServer) Register(new cComponentVTP);
|
||||||
|
if (StreamdevServerSetup.StartHTTPServer) Register(new cComponentHTTP);
|
||||||
|
|
||||||
m_Instance = new cStreamdevServer;
|
m_Instance = new cStreamdevServer;
|
||||||
if (StreamdevServerSetup.StartVTPServer)
|
|
||||||
m_Instance->Register(new cComponentVTP);
|
|
||||||
if (StreamdevServerSetup.StartHTTPServer)
|
|
||||||
m_Instance->Register(new cComponentHTTP);
|
|
||||||
m_Instance->Start();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cStreamdevServer::Exit(void) {
|
void cStreamdevServer::Destruct(void)
|
||||||
if (m_Instance != NULL) {
|
{
|
||||||
m_Instance->Stop();
|
DELETENULL(m_Instance);
|
||||||
DELETENULL(m_Instance);
|
}
|
||||||
|
|
||||||
|
void cStreamdevServer::Stop(void)
|
||||||
|
{
|
||||||
|
if (m_Active) {
|
||||||
|
m_Active = false;
|
||||||
|
Cancel(3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cStreamdevServer::Stop(void) {
|
void cStreamdevServer::Register(cServerComponent *Server)
|
||||||
m_Active = false;
|
{
|
||||||
Cancel(3);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cStreamdevServer::Register(cServerComponent *Server) {
|
|
||||||
m_Servers.Add(Server);
|
m_Servers.Add(Server);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cStreamdevServer::Action(void) {
|
void cStreamdevServer::Action(void)
|
||||||
cTBSelect select;
|
{
|
||||||
|
|
||||||
#if VDRVERSNUM < 10300
|
|
||||||
isyslog("Streamdev: Server thread started (pid=%d)", getpid());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
m_Active = true;
|
m_Active = true;
|
||||||
|
|
||||||
/* Initialize Server components, deleting those that failed */
|
/* Initialize Server components, deleting those that failed */
|
||||||
for (cServerComponent *c = m_Servers.First(); c;) {
|
for (cServerComponent *c = m_Servers.First(); c;) {
|
||||||
cServerComponent *next = m_Servers.Next(c);
|
cServerComponent *next = m_Servers.Next(c);
|
||||||
if (!c->Init())
|
if (!c->Initialize())
|
||||||
m_Servers.Del(c);
|
m_Servers.Del(c);
|
||||||
c = next;
|
c = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_Servers.Count()) {
|
if (m_Servers.Count() == 0) {
|
||||||
esyslog("Streamdev: No server components registered, exiting");
|
esyslog("ERROR: no streamdev server activated, exiting");
|
||||||
m_Active = false;
|
m_Active = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cTBSelect select;
|
||||||
while (m_Active) {
|
while (m_Active) {
|
||||||
select.Clear();
|
select.Clear();
|
||||||
|
|
||||||
/* Ask all Server components to register to the selector */
|
/* Ask all Server components to register to the selector */
|
||||||
for (cServerComponent *c = m_Servers.First(); c; c = m_Servers.Next(c))
|
for (cServerComponent *c = m_Servers.First(); c; c = m_Servers.Next(c))
|
||||||
c->AddSelect(select);
|
select.Add(c->Socket(), false);
|
||||||
|
|
||||||
/* Ask all Client connections to register to the selector */
|
/* Ask all Client connections to register to the selector */
|
||||||
for (cServerConnection *s = m_Clients.First(); s; s = m_Clients.Next(s))
|
for (cServerConnection *s = m_Clients.First(); s; s = m_Clients.Next(s))
|
||||||
s->AddSelect(select);
|
{
|
||||||
|
select.Add(s->Socket(), false);
|
||||||
|
if (s->HasData())
|
||||||
|
select.Add(s->Socket(), true);
|
||||||
|
}
|
||||||
|
|
||||||
if (select.Select(1000) < 0) {
|
if (select.Select() < 0) {
|
||||||
if (!m_Active) // Exit was requested while polling
|
if (m_Active) // no exit was requested while polling
|
||||||
continue;
|
esyslog("fatal error, server exiting: %m");
|
||||||
esyslog("Streamdev: Fatal error, server exiting: %s", strerror(errno));
|
break;
|
||||||
m_Active = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ask all Server components to act on signalled sockets */
|
/* Ask all Server components to act on signalled sockets */
|
||||||
for (cServerComponent *c = m_Servers.First(); c; c = m_Servers.Next(c)) {
|
for (cServerComponent *c = m_Servers.First(); c; c = m_Servers.Next(c)){
|
||||||
cServerConnection *client;
|
if (select.CanRead(c->Socket())) {
|
||||||
if ((client = c->CanAct(select)) != NULL) {
|
cServerConnection *client = c->Accept();
|
||||||
m_Clients.Add(client);
|
m_Clients.Add(client);
|
||||||
|
|
||||||
if (m_Clients.Count() > StreamdevServerSetup.MaxClients) {
|
if (m_Clients.Count() > StreamdevServerSetup.MaxClients) {
|
||||||
esyslog("Streamdev: Too many clients, rejecting %s:%d",
|
esyslog("streamdev: too many clients, rejecting %s:%d",
|
||||||
client->RemoteIp().c_str(), client->RemotePort());
|
client->RemoteIp().c_str(), client->RemotePort());
|
||||||
client->Reject();
|
client->Reject();
|
||||||
} else if (!StreamdevHosts.Acceptable(client->RemoteIpAddr())) {
|
} else if (!StreamdevHosts.Acceptable(client->RemoteIpAddr())) {
|
||||||
esyslog("Streamdev: Client from %s:%d not allowed to connect",
|
esyslog("streamdev: client %s:%d not allowed to connect",
|
||||||
client->RemoteIp().c_str(), client->RemotePort());
|
client->RemoteIp().c_str(), client->RemotePort());
|
||||||
client->Reject();
|
client->Reject();
|
||||||
} else
|
} else
|
||||||
@ -119,10 +118,18 @@ void cStreamdevServer::Action(void) {
|
|||||||
|
|
||||||
/* Ask all Client connections to act on signalled sockets */
|
/* Ask all Client connections to act on signalled sockets */
|
||||||
for (cServerConnection *s = m_Clients.First(); s;) {
|
for (cServerConnection *s = m_Clients.First(); s;) {
|
||||||
|
bool result = true;
|
||||||
|
|
||||||
|
if (select.CanWrite(s->Socket()))
|
||||||
|
result = s->Write();
|
||||||
|
|
||||||
|
if (result && select.CanRead(s->Socket()))
|
||||||
|
result = s->Read();
|
||||||
|
|
||||||
cServerConnection *next = m_Clients.Next(s);
|
cServerConnection *next = m_Clients.Next(s);
|
||||||
if (!s->CanAct(select)) {
|
if (!result) {
|
||||||
isyslog("Streamdev: Closing connection to %s:%d",
|
isyslog("streamdev: closing streamdev connection to %s:%d",
|
||||||
s->RemoteIp().c_str(), s->RemotePort());
|
s->RemoteIp().c_str(), s->RemotePort());
|
||||||
s->Close();
|
s->Close();
|
||||||
m_Clients.Del(s);
|
m_Clients.Del(s);
|
||||||
}
|
}
|
||||||
@ -130,19 +137,17 @@ void cStreamdevServer::Action(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (m_Clients.Count()) {
|
while (m_Clients.Count() > 0) {
|
||||||
cServerConnection *client = m_Clients.First();
|
cServerConnection *s = m_Clients.First();
|
||||||
client->Close();
|
s->Close();
|
||||||
m_Clients.Del(client);
|
m_Clients.Del(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (m_Servers.Count()) {
|
while (m_Servers.Count() > 0) {
|
||||||
cServerComponent *server = m_Servers.First();
|
cServerComponent *c = m_Servers.First();
|
||||||
server->Exit();
|
c->Destruct();
|
||||||
m_Servers.Del(server);
|
m_Servers.Del(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if VDRVERSNUM < 10300
|
m_Active = false;
|
||||||
isyslog("Streamdev: Server thread stopped");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: server.h,v 1.1 2004/12/30 22:44:21 lordjaxom Exp $
|
* $Id: server.h,v 1.2 2005/05/09 20:22:29 lordjaxom Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef VDR_STREAMDEV_SERVER_H
|
#ifndef VDR_STREAMDEV_SERVER_H
|
||||||
@ -10,33 +10,36 @@
|
|||||||
#include "server/component.h"
|
#include "server/component.h"
|
||||||
#include "server/connection.h"
|
#include "server/connection.h"
|
||||||
|
|
||||||
|
#define STREAMDEVHOSTSPATH (*AddDirectory(cPlugin::ConfigDirectory(), "streamdevhosts.conf"))
|
||||||
|
|
||||||
class cStreamdevServer: public cThread {
|
class cStreamdevServer: public cThread {
|
||||||
private:
|
private:
|
||||||
bool m_Active;
|
bool m_Active;
|
||||||
|
|
||||||
cServerComponents m_Servers;
|
static cStreamdevServer *m_Instance;
|
||||||
cServerConnections m_Clients;
|
static cList<cServerComponent> m_Servers;
|
||||||
|
static cList<cServerConnection> m_Clients;
|
||||||
static cStreamdevServer *m_Instance;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void Stop(void);
|
||||||
|
|
||||||
virtual void Action(void);
|
virtual void Action(void);
|
||||||
|
|
||||||
void Stop(void);
|
static void Register(cServerComponent *Server);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cStreamdevServer(void);
|
cStreamdevServer(void);
|
||||||
virtual ~cStreamdevServer();
|
virtual ~cStreamdevServer();
|
||||||
|
|
||||||
void Register(cServerComponent *Server);
|
static void Initialize(void);
|
||||||
|
static void Destruct(void);
|
||||||
static void Init(void);
|
|
||||||
static void Exit(void);
|
|
||||||
static bool Active(void);
|
static bool Active(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool cStreamdevServer::Active(void) {
|
inline bool cStreamdevServer::Active(void)
|
||||||
return m_Instance && m_Instance->m_Clients.Count() > 0;
|
{
|
||||||
|
return m_Instance != NULL
|
||||||
|
&& m_Instance->m_Clients.Count() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern cSVDRPhosts StreamdevHosts;
|
extern cSVDRPhosts StreamdevHosts;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: setup.c,v 1.1 2004/12/30 22:44:21 lordjaxom Exp $
|
* $Id: setup.c,v 1.2 2005/05/09 20:22:29 lordjaxom Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <vdr/menuitems.h>
|
#include <vdr/menuitems.h>
|
||||||
@ -72,7 +72,7 @@ void cStreamdevServerMenuSetupPage::Store(void) {
|
|||||||
|| m_NewSetup.HTTPServerPort != StreamdevServerSetup.HTTPServerPort
|
|| m_NewSetup.HTTPServerPort != StreamdevServerSetup.HTTPServerPort
|
||||||
|| strcmp(m_NewSetup.HTTPBindIP, StreamdevServerSetup.HTTPBindIP) != 0) {
|
|| strcmp(m_NewSetup.HTTPBindIP, StreamdevServerSetup.HTTPBindIP) != 0) {
|
||||||
restart = true;
|
restart = true;
|
||||||
cStreamdevServer::Exit();
|
cStreamdevServer::Destruct();
|
||||||
}
|
}
|
||||||
|
|
||||||
SetupStore("MaxClients", m_NewSetup.MaxClients);
|
SetupStore("MaxClients", m_NewSetup.MaxClients);
|
||||||
@ -89,6 +89,6 @@ void cStreamdevServerMenuSetupPage::Store(void) {
|
|||||||
StreamdevServerSetup = m_NewSetup;
|
StreamdevServerSetup = m_NewSetup;
|
||||||
|
|
||||||
if (restart)
|
if (restart)
|
||||||
cStreamdevServer::Init();
|
cStreamdevServer::Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: streamer.c,v 1.13 2005/04/30 19:41:08 lordjaxom Exp $
|
* $Id: streamer.c,v 1.14 2005/05/09 20:22:29 lordjaxom Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <vdr/ringbuffer.h>
|
#include <vdr/ringbuffer.h>
|
||||||
@ -16,7 +16,8 @@
|
|||||||
|
|
||||||
// --- cStreamdevWriter -------------------------------------------------------
|
// --- cStreamdevWriter -------------------------------------------------------
|
||||||
|
|
||||||
cStreamdevWriter::cStreamdevWriter(cTBSocket *Socket, cStreamdevStreamer *Streamer):
|
cStreamdevWriter::cStreamdevWriter(cTBSocket *Socket,
|
||||||
|
cStreamdevStreamer *Streamer):
|
||||||
cThread("streamdev-writer"),
|
cThread("streamdev-writer"),
|
||||||
m_Streamer(Streamer),
|
m_Streamer(Streamer),
|
||||||
m_Socket(Socket),
|
m_Socket(Socket),
|
||||||
@ -45,7 +46,7 @@ void cStreamdevWriter::Action(void)
|
|||||||
offset = 0;
|
offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (block) {
|
if (block != NULL) {
|
||||||
sel.Clear();
|
sel.Clear();
|
||||||
sel.Add(*m_Socket, true);
|
sel.Add(*m_Socket, true);
|
||||||
if (sel.Select(500) == -1) {
|
if (sel.Select(500) == -1) {
|
||||||
@ -130,8 +131,6 @@ void cStreamdevStreamer::Stop(void)
|
|||||||
|
|
||||||
void cStreamdevStreamer::Action(void)
|
void cStreamdevStreamer::Action(void)
|
||||||
{
|
{
|
||||||
int max = 0;
|
|
||||||
|
|
||||||
m_Active = true;
|
m_Active = true;
|
||||||
while (m_Active) {
|
while (m_Active) {
|
||||||
int got;
|
int got;
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* See the README file for copyright information and how to reach the author.
|
* See the README file for copyright information and how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: streamdev-server.c,v 1.1 2004/12/30 22:43:59 lordjaxom Exp $
|
* $Id: streamdev-server.c,v 1.2 2005/05/09 20:22:29 lordjaxom Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "streamdev-server.h"
|
#include "streamdev-server.h"
|
||||||
@ -14,59 +14,73 @@
|
|||||||
|
|
||||||
const char *cPluginStreamdevServer::DESCRIPTION = "VDR Streaming Server";
|
const char *cPluginStreamdevServer::DESCRIPTION = "VDR Streaming Server";
|
||||||
|
|
||||||
cPluginStreamdevServer::cPluginStreamdevServer(void) {
|
cPluginStreamdevServer::cPluginStreamdevServer(void)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
cPluginStreamdevServer::~cPluginStreamdevServer() {
|
cPluginStreamdevServer::~cPluginStreamdevServer()
|
||||||
cStreamdevServer::Exit();
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *cPluginStreamdevServer::Description(void) {
|
const char *cPluginStreamdevServer::Description(void)
|
||||||
|
{
|
||||||
return tr(DESCRIPTION);
|
return tr(DESCRIPTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cPluginStreamdevServer::Start(void) {
|
bool cPluginStreamdevServer::Start(void)
|
||||||
|
{
|
||||||
i18n_name = Name();
|
i18n_name = Name();
|
||||||
RegisterI18n(Phrases);
|
RegisterI18n(Phrases);
|
||||||
|
|
||||||
if (!StreamdevHosts.Load(STREAMDEVHOSTS, true, true)) {
|
if (!StreamdevHosts.Load(STREAMDEVHOSTSPATH, true, true)) {
|
||||||
esyslog("streamdev-server: error while loading %s", STREAMDEVHOSTS);
|
esyslog("streamdev-server: error while loading %s", STREAMDEVHOSTSPATH);
|
||||||
fprintf(stderr, "streamdev-server: error while loading %s\n");
|
fprintf(stderr, "streamdev-server: error while loading %s\n");
|
||||||
if (access(STREAMDEVHOSTS, F_OK) != 0)
|
if (access(STREAMDEVHOSTSPATH, F_OK) != 0) {
|
||||||
fprintf(stderr, " Please install streamdevhosts.conf into the path "
|
fprintf(stderr, " Please install streamdevhosts.conf into the path "
|
||||||
"printed above. Without it\n"
|
"printed above. Without it\n"
|
||||||
" no client will be able to access your streaming-"
|
" no client will be able to access your streaming-"
|
||||||
"server. An example can be\n"
|
"server. An example can be\n"
|
||||||
" found together with this plugin's sources.\n");
|
" found together with this plugin's sources.\n");
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
cStreamdevServer::Init();
|
cStreamdevServer::Initialize();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cPluginStreamdevServer::Active(void) {
|
void cPluginStreamdevServer::Stop(void)
|
||||||
|
{
|
||||||
|
cStreamdevServer::Destruct();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cPluginStreamdevServer::Active(void)
|
||||||
|
{
|
||||||
return cStreamdevServer::Active();
|
return cStreamdevServer::Active();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *cPluginStreamdevServer::MainMenuEntry(void) {
|
const char *cPluginStreamdevServer::MainMenuEntry(void)
|
||||||
|
{
|
||||||
if (StreamdevServerSetup.SuspendMode == smOffer && !cSuspendCtl::IsActive())
|
if (StreamdevServerSetup.SuspendMode == smOffer && !cSuspendCtl::IsActive())
|
||||||
return tr("Suspend Live TV");
|
return tr("Suspend Live TV");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
cOsdObject *cPluginStreamdevServer::MainMenuAction(void) {
|
cOsdObject *cPluginStreamdevServer::MainMenuAction(void)
|
||||||
|
{
|
||||||
cControl::Launch(new cSuspendCtl);
|
cControl::Launch(new cSuspendCtl);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
cMenuSetupPage *cPluginStreamdevServer::SetupMenu(void) {
|
cMenuSetupPage *cPluginStreamdevServer::SetupMenu(void)
|
||||||
return new cStreamdevServerMenuSetupPage;
|
{
|
||||||
|
return new cStreamdevServerMenuSetupPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cPluginStreamdevServer::SetupParse(const char *Name, const char *Value) {
|
bool cPluginStreamdevServer::SetupParse(const char *Name, const char *Value)
|
||||||
return StreamdevServerSetup.SetupParse(Name, Value);
|
{
|
||||||
|
return StreamdevServerSetup.SetupParse(Name, Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
VDRPLUGINCREATOR(cPluginStreamdevServer); // Don't touch this!
|
VDRPLUGINCREATOR(cPluginStreamdevServer); // Don't touch this!
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: streamdev-server.h,v 1.1 2004/12/30 22:43:59 lordjaxom Exp $
|
* $Id: streamdev-server.h,v 1.2 2005/05/09 20:22:29 lordjaxom Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef VDR_STREAMDEVSERVER_H
|
#ifndef VDR_STREAMDEVSERVER_H
|
||||||
@ -14,16 +14,18 @@ private:
|
|||||||
static const char *DESCRIPTION;
|
static const char *DESCRIPTION;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cPluginStreamdevServer(void);
|
cPluginStreamdevServer(void);
|
||||||
virtual ~cPluginStreamdevServer();
|
virtual ~cPluginStreamdevServer();
|
||||||
virtual const char *Version(void) { return VERSION; }
|
|
||||||
virtual const char *Description(void);
|
virtual const char *Version(void) { return VERSION; }
|
||||||
virtual bool Start(void);
|
virtual const char *Description(void);
|
||||||
|
virtual bool Start(void);
|
||||||
|
virtual void Stop(void);
|
||||||
virtual bool Active(void);
|
virtual bool Active(void);
|
||||||
virtual const char *MainMenuEntry(void);
|
virtual const char *MainMenuEntry(void);
|
||||||
virtual cOsdObject *MainMenuAction(void);
|
virtual cOsdObject *MainMenuAction(void);
|
||||||
virtual cMenuSetupPage *SetupMenu(void);
|
virtual cMenuSetupPage *SetupMenu(void);
|
||||||
virtual bool SetupParse(const char *Name, const char *Value);
|
virtual bool SetupParse(const char *Name, const char *Value);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // VDR_STREAMDEVSERVER_H
|
#endif // VDR_STREAMDEVSERVER_H
|
||||||
|
Loading…
Reference in New Issue
Block a user