mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
Initiating the client side of a peer-to-peer SVDRP connection is now done with the new SVDRP command CONN instead of using the UDP port with the server's address
This commit is contained in:
parent
a72806a0ba
commit
361d642660
6
HISTORY
6
HISTORY
@ -9162,7 +9162,7 @@ Video Disk Recorder Revision History
|
|||||||
a subdirectory.
|
a subdirectory.
|
||||||
- SVDRP peering can now be limited to the default SVDRP host (see MANUAL for details).
|
- SVDRP peering can now be limited to the default SVDRP host (see MANUAL for details).
|
||||||
|
|
||||||
2018-02-15: Version 2.3.9
|
2018-02-20: Version 2.3.9
|
||||||
|
|
||||||
- Updated the Italian OSD texts (thanks to Diego Pierotto).
|
- Updated the Italian OSD texts (thanks to Diego Pierotto).
|
||||||
- Updated the Finnish OSD texts (thanks to Rolf Ahrenberg).
|
- Updated the Finnish OSD texts (thanks to Rolf Ahrenberg).
|
||||||
@ -9279,3 +9279,7 @@ Video Disk Recorder Revision History
|
|||||||
improved logging and debug output.
|
improved logging and debug output.
|
||||||
- Fixed case inconsistency with SVDRPDefaultHost in config.c.
|
- Fixed case inconsistency with SVDRPDefaultHost in config.c.
|
||||||
- Added a section about the '.sort' file to vdr.5.
|
- Added a section about the '.sort' file to vdr.5.
|
||||||
|
- Initiating the client side of a peer-to-peer SVDRP connection is now done with the new
|
||||||
|
SVDRP command CONN instead of using the UDP port with the server's address.
|
||||||
|
This change requires that all VDRs that shall take part in a peer-to-peer network need
|
||||||
|
to be updated to this version.
|
||||||
|
295
svdrp.c
295
svdrp.c
@ -10,7 +10,7 @@
|
|||||||
* and interact with the Video Disk Recorder - or write a full featured
|
* and interact with the Video Disk Recorder - or write a full featured
|
||||||
* graphical interface that sits on top of an SVDRP connection.
|
* graphical interface that sits on top of an SVDRP connection.
|
||||||
*
|
*
|
||||||
* $Id: svdrp.c 4.26 2018/02/15 14:21:37 kls Exp $
|
* $Id: svdrp.c 4.27 2018/02/20 13:28:04 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "svdrp.h"
|
#include "svdrp.h"
|
||||||
@ -106,7 +106,7 @@ public:
|
|||||||
void Close(void);
|
void Close(void);
|
||||||
int Port(void) const { return port; }
|
int Port(void) const { return port; }
|
||||||
int Socket(void) const { return sock; }
|
int Socket(void) const { return sock; }
|
||||||
static bool SendDgram(const char *Dgram, int Port, const char *Address = NULL);
|
static bool SendDgram(const char *Dgram, int Port);
|
||||||
int Accept(void);
|
int Accept(void);
|
||||||
cString Discover(void);
|
cString Discover(void);
|
||||||
const cIpAddress *LastIpAddress(void) const { return &lastIpAddress; }
|
const cIpAddress *LastIpAddress(void) const { return &lastIpAddress; }
|
||||||
@ -210,13 +210,14 @@ bool cSocket::Connect(const char *Address)
|
|||||||
LOG_ERROR;
|
LOG_ERROR;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
dbgsvdrp("> %s:%d server connection established\n", Address, port);
|
||||||
isyslog("SVDRP %s > %s:%d server connection established", Setup.SVDRPHostName, Address, port);
|
isyslog("SVDRP %s > %s:%d server connection established", Setup.SVDRPHostName, Address, port);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cSocket::SendDgram(const char *Dgram, int Port, const char *Address)
|
bool cSocket::SendDgram(const char *Dgram, int Port)
|
||||||
{
|
{
|
||||||
// Create a socket:
|
// Create a socket:
|
||||||
int Socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
int Socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
@ -224,20 +225,18 @@ bool cSocket::SendDgram(const char *Dgram, int Port, const char *Address)
|
|||||||
LOG_ERROR;
|
LOG_ERROR;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!Address) {
|
// Enable broadcast:
|
||||||
// Enable broadcast:
|
int One = 1;
|
||||||
int One = 1;
|
if (setsockopt(Socket, SOL_SOCKET, SO_BROADCAST, &One, sizeof(One)) < 0) {
|
||||||
if (setsockopt(Socket, SOL_SOCKET, SO_BROADCAST, &One, sizeof(One)) < 0) {
|
LOG_ERROR;
|
||||||
LOG_ERROR;
|
close(Socket);
|
||||||
close(Socket);
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Configure port and ip:
|
// Configure port and ip:
|
||||||
sockaddr_in Addr;
|
sockaddr_in Addr;
|
||||||
memset(&Addr, 0, sizeof(Addr));
|
memset(&Addr, 0, sizeof(Addr));
|
||||||
Addr.sin_family = AF_INET;
|
Addr.sin_family = AF_INET;
|
||||||
Addr.sin_addr.s_addr = Address ? inet_addr(Address) : htonl(INADDR_BROADCAST);
|
Addr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
|
||||||
Addr.sin_port = htons(Port);
|
Addr.sin_port = htons(Port);
|
||||||
// Send datagram:
|
// Send datagram:
|
||||||
dbgsvdrp("> %s:%d %s\n", inet_ntoa(Addr.sin_addr), Port, Dgram);
|
dbgsvdrp("> %s:%d %s\n", inet_ntoa(Addr.sin_addr), Port, Dgram);
|
||||||
@ -310,23 +309,25 @@ cString cSocket::Discover(void)
|
|||||||
|
|
||||||
class cSVDRPClient {
|
class cSVDRPClient {
|
||||||
private:
|
private:
|
||||||
cIpAddress ipAddress;
|
cIpAddress serverIpAddress;
|
||||||
cSocket socket;
|
cSocket socket;
|
||||||
cString serverName;
|
cString serverName;
|
||||||
int timeout;
|
int timeout;
|
||||||
cTimeMs pingTime;
|
cTimeMs pingTime;
|
||||||
cFile file;
|
cFile file;
|
||||||
int fetchFlags;
|
int fetchFlags;
|
||||||
|
bool connected;
|
||||||
void Close(void);
|
void Close(void);
|
||||||
public:
|
public:
|
||||||
cSVDRPClient(const char *Address, int Port, const char *ServerName, int Timeout);
|
cSVDRPClient(const char *Address, int Port, const char *ServerName, int Timeout);
|
||||||
~cSVDRPClient();
|
~cSVDRPClient();
|
||||||
const char *ServerName(void) const { return serverName; }
|
const char *ServerName(void) const { return serverName; }
|
||||||
const char *Connection(void) const { return ipAddress.Connection(); }
|
const char *Connection(void) const { return serverIpAddress.Connection(); }
|
||||||
bool HasAddress(const char *Address, int Port) const;
|
bool HasAddress(const char *Address, int Port) const;
|
||||||
bool Send(const char *Command);
|
bool Send(const char *Command);
|
||||||
bool Process(cStringList *Response = NULL);
|
bool Process(cStringList *Response = NULL);
|
||||||
bool Execute(const char *Command, cStringList *Response = NULL);
|
bool Execute(const char *Command, cStringList *Response = NULL);
|
||||||
|
bool Connected(void) const { return connected; }
|
||||||
void SetFetchFlag(eSvdrpFetchFlags Flag);
|
void SetFetchFlag(eSvdrpFetchFlags Flag);
|
||||||
bool HasFetchFlag(eSvdrpFetchFlags Flag);
|
bool HasFetchFlag(eSvdrpFetchFlags Flag);
|
||||||
};
|
};
|
||||||
@ -334,27 +335,28 @@ public:
|
|||||||
static cPoller SVDRPClientPoller;
|
static cPoller SVDRPClientPoller;
|
||||||
|
|
||||||
cSVDRPClient::cSVDRPClient(const char *Address, int Port, const char *ServerName, int Timeout)
|
cSVDRPClient::cSVDRPClient(const char *Address, int Port, const char *ServerName, int Timeout)
|
||||||
:ipAddress(Address, Port)
|
:serverIpAddress(Address, Port)
|
||||||
,socket(Port, true)
|
,socket(Port, true)
|
||||||
{
|
{
|
||||||
serverName = ServerName;
|
serverName = ServerName;
|
||||||
timeout = Timeout * 1000 * 9 / 10; // ping after 90% of timeout
|
timeout = Timeout * 1000 * 9 / 10; // ping after 90% of timeout
|
||||||
pingTime.Set(timeout);
|
pingTime.Set(timeout);
|
||||||
fetchFlags = sffTimers;
|
fetchFlags = sffNone;
|
||||||
|
connected = false;
|
||||||
if (socket.Connect(Address)) {
|
if (socket.Connect(Address)) {
|
||||||
if (file.Open(socket.Socket())) {
|
if (file.Open(socket.Socket())) {
|
||||||
SVDRPClientPoller.Add(file, false);
|
SVDRPClientPoller.Add(file, false);
|
||||||
dsyslog("SVDRP %s > %s client created for '%s'", Setup.SVDRPHostName, ipAddress.Connection(), *serverName);
|
dsyslog("SVDRP %s > %s client created for '%s'", Setup.SVDRPHostName, serverIpAddress.Connection(), *serverName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
esyslog("SVDRP %s > %s ERROR: failed to create client for '%s'", Setup.SVDRPHostName, ipAddress.Connection(), *serverName);
|
esyslog("SVDRP %s > %s ERROR: failed to create client for '%s'", Setup.SVDRPHostName, serverIpAddress.Connection(), *serverName);
|
||||||
}
|
}
|
||||||
|
|
||||||
cSVDRPClient::~cSVDRPClient()
|
cSVDRPClient::~cSVDRPClient()
|
||||||
{
|
{
|
||||||
Close();
|
Close();
|
||||||
dsyslog("SVDRP %s > %s client destroyed for '%s'", Setup.SVDRPHostName, ipAddress.Connection(), *serverName);
|
dsyslog("SVDRP %s > %s client destroyed for '%s'", Setup.SVDRPHostName, serverIpAddress.Connection(), *serverName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSVDRPClient::Close(void)
|
void cSVDRPClient::Close(void)
|
||||||
@ -371,13 +373,13 @@ void cSVDRPClient::Close(void)
|
|||||||
|
|
||||||
bool cSVDRPClient::HasAddress(const char *Address, int Port) const
|
bool cSVDRPClient::HasAddress(const char *Address, int Port) const
|
||||||
{
|
{
|
||||||
return strcmp(ipAddress.Address(), Address) == 0 && ipAddress.Port() == Port;
|
return strcmp(serverIpAddress.Address(), Address) == 0 && serverIpAddress.Port() == Port;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cSVDRPClient::Send(const char *Command)
|
bool cSVDRPClient::Send(const char *Command)
|
||||||
{
|
{
|
||||||
pingTime.Set(timeout);
|
pingTime.Set(timeout);
|
||||||
dbgsvdrp("> %s: %s\n", *serverName, Command);
|
dbgsvdrp("> C %s: %s\n", *serverName, Command);
|
||||||
if (safe_write(file, Command, strlen(Command) + 1) < 0) {
|
if (safe_write(file, Command, strlen(Command) + 1) < 0) {
|
||||||
LOG_ERROR;
|
LOG_ERROR;
|
||||||
return false;
|
return false;
|
||||||
@ -403,7 +405,7 @@ bool cSVDRPClient::Process(cStringList *Response)
|
|||||||
input[--numChars] = 0;
|
input[--numChars] = 0;
|
||||||
// make sure the string is terminated:
|
// make sure the string is terminated:
|
||||||
input[numChars] = 0;
|
input[numChars] = 0;
|
||||||
dbgsvdrp("< %s: %s\n", *serverName, input);
|
dbgsvdrp("< C %s: %s\n", *serverName, input);
|
||||||
if (Response)
|
if (Response)
|
||||||
Response->Append(strdup(input));
|
Response->Append(strdup(input));
|
||||||
else {
|
else {
|
||||||
@ -414,12 +416,16 @@ bool cSVDRPClient::Process(cStringList *Response)
|
|||||||
*t = 0;
|
*t = 0;
|
||||||
if (strcmp(n, serverName) != 0) {
|
if (strcmp(n, serverName) != 0) {
|
||||||
serverName = n;
|
serverName = n;
|
||||||
dsyslog("SVDRP %s < %s remote server name is '%s'", Setup.SVDRPHostName, ipAddress.Connection(), *serverName);
|
dsyslog("SVDRP %s < %s remote server name is '%s'", Setup.SVDRPHostName, serverIpAddress.Connection(), *serverName);
|
||||||
}
|
}
|
||||||
|
Execute(cString::sprintf("CONN name:%s port:%d vdrversion:%d apiversion:%d timeout:%d", Setup.SVDRPHostName, SVDRPTcpPort, VDRVERSNUM, APIVERSNUM, Setup.SVDRPTimeout));
|
||||||
|
SetFetchFlag(sffTimers);
|
||||||
|
connected = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 221: dsyslog("SVDRP %s < %s remote server closed connection to '%s'", Setup.SVDRPHostName, ipAddress.Connection(), *serverName);
|
case 221: dsyslog("SVDRP %s < %s remote server closed connection to '%s'", Setup.SVDRPHostName, serverIpAddress.Connection(), *serverName);
|
||||||
|
connected = false;
|
||||||
Close();
|
Close();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -430,7 +436,7 @@ bool cSVDRPClient::Process(cStringList *Response)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (numChars >= int(sizeof(input))) {
|
if (numChars >= int(sizeof(input))) {
|
||||||
esyslog("SVDRP %s < %s ERROR: out of memory", Setup.SVDRPHostName, ipAddress.Connection());
|
esyslog("SVDRP %s < %s ERROR: out of memory", Setup.SVDRPHostName, serverIpAddress.Connection());
|
||||||
Close();
|
Close();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -440,13 +446,13 @@ bool cSVDRPClient::Process(cStringList *Response)
|
|||||||
Timeout.Set(SVDRPResonseTimeout);
|
Timeout.Set(SVDRPResonseTimeout);
|
||||||
}
|
}
|
||||||
else if (r <= 0) {
|
else if (r <= 0) {
|
||||||
isyslog("SVDRP %s < %s lost connection to remote server '%s'", Setup.SVDRPHostName, ipAddress.Connection(), *serverName);
|
isyslog("SVDRP %s < %s lost connection to remote server '%s'", Setup.SVDRPHostName, serverIpAddress.Connection(), *serverName);
|
||||||
Close();
|
Close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (Timeout.TimedOut()) {
|
else if (Timeout.TimedOut()) {
|
||||||
esyslog("SVDRP %s < %s timeout while waiting for response from '%s'", Setup.SVDRPHostName, ipAddress.Connection(), *serverName);
|
esyslog("SVDRP %s < %s timeout while waiting for response from '%s'", Setup.SVDRPHostName, serverIpAddress.Connection(), *serverName);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (!Response && numChars == 0)
|
else if (!Response && numChars == 0)
|
||||||
@ -477,6 +483,70 @@ bool cSVDRPClient::HasFetchFlag(eSvdrpFetchFlags Flag)
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- cSVDRPServerParams ----------------------------------------------------
|
||||||
|
|
||||||
|
class cSVDRPServerParams {
|
||||||
|
private:
|
||||||
|
cString name;
|
||||||
|
int port;
|
||||||
|
cString vdrversion;
|
||||||
|
cString apiversion;
|
||||||
|
int timeout;
|
||||||
|
cString host;
|
||||||
|
cString error;
|
||||||
|
public:
|
||||||
|
cSVDRPServerParams(const char *Params);
|
||||||
|
const char *Name(void) const { return name; }
|
||||||
|
const int Port(void) const { return port; }
|
||||||
|
const char *VdrVersion(void) const { return vdrversion; }
|
||||||
|
const char *ApiVersion(void) const { return apiversion; }
|
||||||
|
const int Timeout(void) const { return timeout; }
|
||||||
|
const char *Host(void) const { return host; }
|
||||||
|
bool Ok(void) const { return !*error; }
|
||||||
|
const char *Error(void) const { return error; }
|
||||||
|
};
|
||||||
|
|
||||||
|
cSVDRPServerParams::cSVDRPServerParams(const char *Params)
|
||||||
|
{
|
||||||
|
if (Params && *Params) {
|
||||||
|
name = strgetval(Params, "name", ':');
|
||||||
|
if (*name) {
|
||||||
|
cString p = strgetval(Params, "port", ':');
|
||||||
|
if (*p) {
|
||||||
|
port = atoi(p);
|
||||||
|
vdrversion = strgetval(Params, "vdrversion", ':');
|
||||||
|
if (*vdrversion) {
|
||||||
|
apiversion = strgetval(Params, "apiversion", ':');
|
||||||
|
if (*apiversion) {
|
||||||
|
cString t = strgetval(Params, "timeout", ':');
|
||||||
|
if (*t) {
|
||||||
|
timeout = atoi(t);
|
||||||
|
if (timeout > 10) { // don't let it get too small
|
||||||
|
host = strgetval(Params, "host", ':');
|
||||||
|
// no error if missing - this parameter is optional!
|
||||||
|
}
|
||||||
|
else
|
||||||
|
error = "invalid timeout";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
error = "missing server timeout";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
error = "missing server apiversion";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
error = "missing server vdrversion";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
error = "missing server port";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
error = "missing server name";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
error = "missing server parameters";
|
||||||
|
}
|
||||||
|
|
||||||
// --- cSVDRPClientHandler ---------------------------------------------------
|
// --- cSVDRPClientHandler ---------------------------------------------------
|
||||||
|
|
||||||
class cSVDRPClientHandler : public cThread {
|
class cSVDRPClientHandler : public cThread {
|
||||||
@ -487,16 +557,17 @@ private:
|
|||||||
cVector<cSVDRPClient *> clientConnections;
|
cVector<cSVDRPClient *> clientConnections;
|
||||||
void HandleClientConnection(void);
|
void HandleClientConnection(void);
|
||||||
void ProcessConnections(void);
|
void ProcessConnections(void);
|
||||||
cSVDRPClient *GetClientForServer(const char *ServerName);
|
|
||||||
protected:
|
protected:
|
||||||
virtual void Action(void);
|
virtual void Action(void);
|
||||||
public:
|
public:
|
||||||
cSVDRPClientHandler(int TcpPort, int UdpPort);
|
cSVDRPClientHandler(int TcpPort, int UdpPort);
|
||||||
virtual ~cSVDRPClientHandler();
|
virtual ~cSVDRPClientHandler();
|
||||||
void SendDiscover(const char *Address = NULL);
|
void SendDiscover(void);
|
||||||
|
void AddClient(cSVDRPServerParams &ServerParams, const char *IpAddress);
|
||||||
bool Execute(const char *ServerName, const char *Command, cStringList *Response = NULL);
|
bool Execute(const char *ServerName, const char *Command, cStringList *Response = NULL);
|
||||||
bool GetServerNames(cStringList *ServerNames, eSvdrpFetchFlags FetchFlags = sffNone);
|
bool GetServerNames(cStringList *ServerNames, eSvdrpFetchFlags FetchFlags = sffNone);
|
||||||
bool TriggerFetchingTimers(const char *ServerName);
|
bool TriggerFetchingTimers(const char *ServerName);
|
||||||
|
cSVDRPClient *GetClientForServer(const char *ServerName);
|
||||||
};
|
};
|
||||||
|
|
||||||
static cSVDRPClientHandler *SVDRPClientHandler = NULL;
|
static cSVDRPClientHandler *SVDRPClientHandler = NULL;
|
||||||
@ -517,6 +588,7 @@ cSVDRPClientHandler::~cSVDRPClientHandler()
|
|||||||
|
|
||||||
cSVDRPClient *cSVDRPClientHandler::GetClientForServer(const char *ServerName)
|
cSVDRPClient *cSVDRPClientHandler::GetClientForServer(const char *ServerName)
|
||||||
{
|
{
|
||||||
|
cMutexLock MutexLock(&mutex);
|
||||||
for (int i = 0; i < clientConnections.Size(); i++) {
|
for (int i = 0; i < clientConnections.Size(); i++) {
|
||||||
if (strcmp(clientConnections[i]->ServerName(), ServerName) == 0)
|
if (strcmp(clientConnections[i]->ServerName(), ServerName) == 0)
|
||||||
return clientConnections[i];
|
return clientConnections[i];
|
||||||
@ -524,11 +596,11 @@ cSVDRPClient *cSVDRPClientHandler::GetClientForServer(const char *ServerName)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSVDRPClientHandler::SendDiscover(const char *Address)
|
void cSVDRPClientHandler::SendDiscover(void)
|
||||||
{
|
{
|
||||||
cMutexLock MutexLock(&mutex);
|
cMutexLock MutexLock(&mutex);
|
||||||
cString Dgram = cString::sprintf("SVDRP:discover name:%s port:%d vdrversion:%d apiversion:%d timeout:%d%s", Setup.SVDRPHostName, tcpPort, VDRVERSNUM, APIVERSNUM, Setup.SVDRPTimeout, (Setup.SVDRPPeering == spmOnly && *Setup.SVDRPDefaultHost) ? *cString::sprintf(" host:%s", Setup.SVDRPDefaultHost) : "");
|
cString Dgram = cString::sprintf("SVDRP:discover name:%s port:%d vdrversion:%d apiversion:%d timeout:%d%s", Setup.SVDRPHostName, tcpPort, VDRVERSNUM, APIVERSNUM, Setup.SVDRPTimeout, (Setup.SVDRPPeering == spmOnly && *Setup.SVDRPDefaultHost) ? *cString::sprintf(" host:%s", Setup.SVDRPDefaultHost) : "");
|
||||||
udpSocket.SendDgram(Dgram, udpSocket.Port(), Address);
|
udpSocket.SendDgram(Dgram, udpSocket.Port());
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSVDRPClientHandler::ProcessConnections(void)
|
void cSVDRPClientHandler::ProcessConnections(void)
|
||||||
@ -543,45 +615,30 @@ void cSVDRPClientHandler::ProcessConnections(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cSVDRPClientHandler::AddClient(cSVDRPServerParams &ServerParams, const char *IpAddress)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < clientConnections.Size(); i++) {
|
||||||
|
if (clientConnections[i]->HasAddress(IpAddress, ServerParams.Port())) {
|
||||||
|
dsyslog("SVDRP %s < %s connection to '%s' already exists", Setup.SVDRPHostName, clientConnections[i]->Connection(), clientConnections[i]->ServerName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Setup.SVDRPPeering == spmOnly && strcmp(ServerParams.Name(), Setup.SVDRPDefaultHost) != 0)
|
||||||
|
return; // we only want to peer with the default host, but this isn't the default host
|
||||||
|
if (ServerParams.Host() && strcmp(ServerParams.Host(), Setup.SVDRPHostName) != 0)
|
||||||
|
return; // the remote VDR requests a specific host, but it's not us
|
||||||
|
clientConnections.Append(new cSVDRPClient(IpAddress, ServerParams.Port(), ServerParams.Name(), ServerParams.Timeout()));
|
||||||
|
}
|
||||||
|
|
||||||
void cSVDRPClientHandler::HandleClientConnection(void)
|
void cSVDRPClientHandler::HandleClientConnection(void)
|
||||||
{
|
{
|
||||||
cString NewDiscover = udpSocket.Discover();
|
cString NewDiscover = udpSocket.Discover();
|
||||||
if (*NewDiscover) {
|
if (*NewDiscover) {
|
||||||
cString p = strgetval(NewDiscover, "port", ':');
|
cSVDRPServerParams ServerParams(NewDiscover);
|
||||||
if (*p) {
|
if (ServerParams.Ok())
|
||||||
int Port = atoi(p);
|
AddClient(ServerParams, udpSocket.LastIpAddress()->Address());
|
||||||
for (int i = 0; i < clientConnections.Size(); i++) {
|
|
||||||
if (clientConnections[i]->HasAddress(udpSocket.LastIpAddress()->Address(), Port)) {
|
|
||||||
dsyslog("SVDRP %s < %s connection to '%s' confirmed", Setup.SVDRPHostName, clientConnections[i]->Connection(), clientConnections[i]->ServerName());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cString ServerName = strgetval(NewDiscover, "name", ':');
|
|
||||||
if (*ServerName) {
|
|
||||||
if (Setup.SVDRPPeering == spmOnly && strcmp(ServerName, Setup.SVDRPDefaultHost) != 0)
|
|
||||||
return; // we only want to peer with the default host, but this isn't the default host
|
|
||||||
cString HostName = strgetval(NewDiscover, "host", ':');
|
|
||||||
if (*HostName && strcmp(HostName, Setup.SVDRPHostName) != 0)
|
|
||||||
return; // the remote VDR requests a specific host, but it's not us
|
|
||||||
cString t = strgetval(NewDiscover, "timeout", ':');
|
|
||||||
if (*t) {
|
|
||||||
int Timeout = atoi(t);
|
|
||||||
if (Timeout > 10) { // don't let it get too small
|
|
||||||
const char *Address = udpSocket.LastIpAddress()->Address();
|
|
||||||
clientConnections.Append(new cSVDRPClient(Address, Port, ServerName, Timeout));
|
|
||||||
SendDiscover(Address);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
esyslog("SVDRP %s < %s ERROR: invalid timeout (%d)", Setup.SVDRPHostName, udpSocket.LastIpAddress()->Connection(), Timeout);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
esyslog("SVDRP %s < %s ERROR: missing timeout", Setup.SVDRPHostName, udpSocket.LastIpAddress()->Connection());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
esyslog("SVDRP %s < %s ERROR: missing server name", Setup.SVDRPHostName, udpSocket.LastIpAddress()->Connection());
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
esyslog("SVDRP %s < %s ERROR: missing port number", Setup.SVDRPHostName, udpSocket.LastIpAddress()->Connection());
|
esyslog("SVDRP %s < %s ERROR: %s", Setup.SVDRPHostName, udpSocket.LastIpAddress()->Connection(), ServerParams.Error());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -615,8 +672,10 @@ bool cSVDRPClientHandler::GetServerNames(cStringList *ServerNames, eSvdrpFetchFl
|
|||||||
ServerNames->Clear();
|
ServerNames->Clear();
|
||||||
for (int i = 0; i < clientConnections.Size(); i++) {
|
for (int i = 0; i < clientConnections.Size(); i++) {
|
||||||
cSVDRPClient *Client = clientConnections[i];
|
cSVDRPClient *Client = clientConnections[i];
|
||||||
if (FetchFlag == sffNone || Client->HasFetchFlag(FetchFlag))
|
if (Client->Connected()) {
|
||||||
ServerNames->Append(strdup(Client->ServerName()));
|
if (FetchFlag == sffNone || Client->HasFetchFlag(FetchFlag))
|
||||||
|
ServerNames->Append(strdup(Client->ServerName()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ServerNames->Size() > 0;
|
return ServerNames->Size() > 0;
|
||||||
}
|
}
|
||||||
@ -708,6 +767,10 @@ const char *HelpPages[] = {
|
|||||||
" After a CLRE command, no further EPG processing is done for 10\n"
|
" After a CLRE command, no further EPG processing is done for 10\n"
|
||||||
" seconds, so that data sent with subsequent PUTE commands doesn't\n"
|
" seconds, so that data sent with subsequent PUTE commands doesn't\n"
|
||||||
" interfere with data from the broadcasters.",
|
" interfere with data from the broadcasters.",
|
||||||
|
"CONN name:<name> port:<port> vdrversion:<vdrversion> apiversion:<apiversion> timeout:<timeout>\n"
|
||||||
|
" Used by peer-to-peer connections between VDRs to tell the other VDR\n"
|
||||||
|
" to establish a connection to this VDR. The name is the SVDRP host name\n"
|
||||||
|
" of this VDR, which may differ from its DNS name.",
|
||||||
"DELC <number>\n"
|
"DELC <number>\n"
|
||||||
" Delete channel.",
|
" Delete channel.",
|
||||||
"DELR <id>\n"
|
"DELR <id>\n"
|
||||||
@ -929,7 +992,8 @@ static cString grabImageDir;
|
|||||||
class cSVDRPServer {
|
class cSVDRPServer {
|
||||||
private:
|
private:
|
||||||
int socket;
|
int socket;
|
||||||
cString connection;
|
cIpAddress clientIpAddress;
|
||||||
|
cString clientName;
|
||||||
cFile file;
|
cFile file;
|
||||||
cPUTEhandler *PUTEhandler;
|
cPUTEhandler *PUTEhandler;
|
||||||
int numChars;
|
int numChars;
|
||||||
@ -942,6 +1006,7 @@ private:
|
|||||||
void PrintHelpTopics(const char **hp);
|
void PrintHelpTopics(const char **hp);
|
||||||
void CmdCHAN(const char *Option);
|
void CmdCHAN(const char *Option);
|
||||||
void CmdCLRE(const char *Option);
|
void CmdCLRE(const char *Option);
|
||||||
|
void CmdCONN(const char *Option);
|
||||||
void CmdDELC(const char *Option);
|
void CmdDELC(const char *Option);
|
||||||
void CmdDELR(const char *Option);
|
void CmdDELR(const char *Option);
|
||||||
void CmdDELT(const char *Option);
|
void CmdDELT(const char *Option);
|
||||||
@ -976,18 +1041,20 @@ private:
|
|||||||
void CmdVOLU(const char *Option);
|
void CmdVOLU(const char *Option);
|
||||||
void Execute(char *Cmd);
|
void Execute(char *Cmd);
|
||||||
public:
|
public:
|
||||||
cSVDRPServer(int Socket, const char *Connection);
|
cSVDRPServer(int Socket, const cIpAddress *ClientIpAddress);
|
||||||
~cSVDRPServer();
|
~cSVDRPServer();
|
||||||
|
const char *ClientName(void) const { return clientName; }
|
||||||
bool HasConnection(void) { return file.IsOpen(); }
|
bool HasConnection(void) { return file.IsOpen(); }
|
||||||
bool Process(void);
|
bool Process(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
static cPoller SVDRPServerPoller;
|
static cPoller SVDRPServerPoller;
|
||||||
|
|
||||||
cSVDRPServer::cSVDRPServer(int Socket, const char *Connection)
|
cSVDRPServer::cSVDRPServer(int Socket, const cIpAddress *ClientIpAddress)
|
||||||
{
|
{
|
||||||
socket = Socket;
|
socket = Socket;
|
||||||
connection = Connection;
|
clientIpAddress = *ClientIpAddress;
|
||||||
|
clientName = clientIpAddress.Connection(); // will be set to actual name by a CONN command
|
||||||
PUTEhandler = NULL;
|
PUTEhandler = NULL;
|
||||||
numChars = 0;
|
numChars = 0;
|
||||||
length = BUFSIZ;
|
length = BUFSIZ;
|
||||||
@ -998,14 +1065,14 @@ cSVDRPServer::cSVDRPServer(int Socket, const char *Connection)
|
|||||||
Reply(220, "%s SVDRP VideoDiskRecorder %s; %s; %s", Setup.SVDRPHostName, VDRVERSION, *TimeToString(now), cCharSetConv::SystemCharacterTable() ? cCharSetConv::SystemCharacterTable() : "UTF-8");
|
Reply(220, "%s SVDRP VideoDiskRecorder %s; %s; %s", Setup.SVDRPHostName, VDRVERSION, *TimeToString(now), cCharSetConv::SystemCharacterTable() ? cCharSetConv::SystemCharacterTable() : "UTF-8");
|
||||||
SVDRPServerPoller.Add(file, false);
|
SVDRPServerPoller.Add(file, false);
|
||||||
}
|
}
|
||||||
dsyslog("SVDRP %s < %s server created", Setup.SVDRPHostName, *connection);
|
dsyslog("SVDRP %s > %s server created", Setup.SVDRPHostName, *clientName);
|
||||||
}
|
}
|
||||||
|
|
||||||
cSVDRPServer::~cSVDRPServer()
|
cSVDRPServer::~cSVDRPServer()
|
||||||
{
|
{
|
||||||
Close(true);
|
Close(true);
|
||||||
free(cmdLine);
|
free(cmdLine);
|
||||||
dsyslog("SVDRP %s < %s server destroyed", Setup.SVDRPHostName, *connection);
|
dsyslog("SVDRP %s < %s server destroyed", Setup.SVDRPHostName, *clientName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSVDRPServer::Close(bool SendReply, bool Timeout)
|
void cSVDRPServer::Close(bool SendReply, bool Timeout)
|
||||||
@ -1014,7 +1081,7 @@ void cSVDRPServer::Close(bool SendReply, bool Timeout)
|
|||||||
if (SendReply) {
|
if (SendReply) {
|
||||||
Reply(221, "%s closing connection%s", Setup.SVDRPHostName, Timeout ? " (timeout)" : "");
|
Reply(221, "%s closing connection%s", Setup.SVDRPHostName, Timeout ? " (timeout)" : "");
|
||||||
}
|
}
|
||||||
isyslog("SVDRP %s < %s connection closed", Setup.SVDRPHostName, *connection);
|
isyslog("SVDRP %s < %s connection closed", Setup.SVDRPHostName, *clientName);
|
||||||
SVDRPServerPoller.Del(file, false);
|
SVDRPServerPoller.Del(file, false);
|
||||||
file.Close();
|
file.Close();
|
||||||
DELETENULL(PUTEhandler);
|
DELETENULL(PUTEhandler);
|
||||||
@ -1024,7 +1091,7 @@ void cSVDRPServer::Close(bool SendReply, bool Timeout)
|
|||||||
|
|
||||||
bool cSVDRPServer::Send(const char *s)
|
bool cSVDRPServer::Send(const char *s)
|
||||||
{
|
{
|
||||||
dbgsvdrp("> %s: %s", *connection, s); // terminating newline is already in the string!
|
dbgsvdrp("> S %s: %s", *clientName, s); // terminating newline is already in the string!
|
||||||
if (safe_write(file, s, strlen(s)) < 0) {
|
if (safe_write(file, s, strlen(s)) < 0) {
|
||||||
LOG_ERROR;
|
LOG_ERROR;
|
||||||
Close();
|
Close();
|
||||||
@ -1056,14 +1123,14 @@ void cSVDRPServer::Reply(int Code, const char *fmt, ...)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Reply(451, "Bad format - looks like a programming error!");
|
Reply(451, "Bad format - looks like a programming error!");
|
||||||
esyslog("SVDRP %s < %s bad format!", Setup.SVDRPHostName, *connection);
|
esyslog("SVDRP %s < %s bad format!", Setup.SVDRPHostName, *clientName);
|
||||||
}
|
}
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
free(buffer);
|
free(buffer);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Reply(451, "Zero return code - looks like a programming error!");
|
Reply(451, "Zero return code - looks like a programming error!");
|
||||||
esyslog("SVDRP %s < %s zero return code!", Setup.SVDRPHostName, *connection);
|
esyslog("SVDRP %s < %s zero return code!", Setup.SVDRPHostName, *clientName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1219,6 +1286,27 @@ void cSVDRPServer::CmdCLRE(const char *Option)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cSVDRPServer::CmdCONN(const char *Option)
|
||||||
|
{
|
||||||
|
if (*Option) {
|
||||||
|
if (SVDRPClientHandler) {
|
||||||
|
cSVDRPServerParams ServerParams(Option);
|
||||||
|
if (ServerParams.Ok()) {
|
||||||
|
clientName = ServerParams.Name();
|
||||||
|
Reply(250, "OK"); // must finish this transaction before creating the new client
|
||||||
|
if (!SVDRPClientHandler->GetClientForServer(ServerParams.Name()))
|
||||||
|
SVDRPClientHandler->AddClient(ServerParams, clientIpAddress.Address());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Reply(501, "Error in server parameters: %s", ServerParams.Error());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Reply(451, "No SVDRP client handler");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Reply(501, "Missing server parameters");
|
||||||
|
}
|
||||||
|
|
||||||
void cSVDRPServer::CmdDELC(const char *Option)
|
void cSVDRPServer::CmdDELC(const char *Option)
|
||||||
{
|
{
|
||||||
if (*Option) {
|
if (*Option) {
|
||||||
@ -1248,7 +1336,7 @@ void cSVDRPServer::CmdDELC(const char *Option)
|
|||||||
Channels->ReNumber();
|
Channels->ReNumber();
|
||||||
Channels->SetModifiedByUser();
|
Channels->SetModifiedByUser();
|
||||||
Channels->SetModified();
|
Channels->SetModified();
|
||||||
isyslog("SVDRP %s < %s deleted channel %s", Setup.SVDRPHostName, *connection, Option);
|
isyslog("SVDRP %s < %s deleted channel %s", Setup.SVDRPHostName, *clientName, Option);
|
||||||
if (CurrentChannel && CurrentChannel->Number() != CurrentChannelNr) {
|
if (CurrentChannel && CurrentChannel->Number() != CurrentChannelNr) {
|
||||||
if (!cDevice::PrimaryDevice()->Replaying() || cDevice::PrimaryDevice()->Transferring())
|
if (!cDevice::PrimaryDevice()->Replaying() || cDevice::PrimaryDevice()->Transferring())
|
||||||
Channels->SwitchTo(CurrentChannel->Number());
|
Channels->SwitchTo(CurrentChannel->Number());
|
||||||
@ -1296,7 +1384,7 @@ void cSVDRPServer::CmdDELR(const char *Option)
|
|||||||
if (Recording->Delete()) {
|
if (Recording->Delete()) {
|
||||||
Recordings->DelByName(Recording->FileName());
|
Recordings->DelByName(Recording->FileName());
|
||||||
Recordings->SetModified();
|
Recordings->SetModified();
|
||||||
isyslog("SVDRP %s < %s deleted recording %s", Setup.SVDRPHostName, *connection, Option);
|
isyslog("SVDRP %s < %s deleted recording %s", Setup.SVDRPHostName, *clientName, Option);
|
||||||
Reply(250, "Recording \"%s\" deleted", Option);
|
Reply(250, "Recording \"%s\" deleted", Option);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1326,7 +1414,7 @@ void cSVDRPServer::CmdDELT(const char *Option)
|
|||||||
}
|
}
|
||||||
Timers->Del(Timer);
|
Timers->Del(Timer);
|
||||||
Timers->SetModified();
|
Timers->SetModified();
|
||||||
isyslog("SVDRP %s < %s deleted timer %s", Setup.SVDRPHostName, *connection, *Timer->ToDescr());
|
isyslog("SVDRP %s < %s deleted timer %s", Setup.SVDRPHostName, *clientName, *Timer->ToDescr());
|
||||||
Reply(250, "Timer \"%s\" deleted", Option);
|
Reply(250, "Timer \"%s\" deleted", Option);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1472,7 +1560,7 @@ void cSVDRPServer::CmdGRAB(const char *Option)
|
|||||||
int fd = open(FileName, O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC, DEFFILEMODE);
|
int fd = open(FileName, O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC, DEFFILEMODE);
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
if (safe_write(fd, Image, ImageSize) == ImageSize) {
|
if (safe_write(fd, Image, ImageSize) == ImageSize) {
|
||||||
dsyslog("SVDRP %s < %s grabbed image to %s", Setup.SVDRPHostName, *connection, FileName);
|
dsyslog("SVDRP %s < %s grabbed image to %s", Setup.SVDRPHostName, *clientName, FileName);
|
||||||
Reply(250, "Grabbed image %s", Option);
|
Reply(250, "Grabbed image %s", Option);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -1826,7 +1914,7 @@ void cSVDRPServer::CmdLSTT(const char *Option)
|
|||||||
void cSVDRPServer::CmdMESG(const char *Option)
|
void cSVDRPServer::CmdMESG(const char *Option)
|
||||||
{
|
{
|
||||||
if (*Option) {
|
if (*Option) {
|
||||||
isyslog("SVDRP %s < %s message '%s'", Setup.SVDRPHostName, *connection, Option);
|
isyslog("SVDRP %s < %s message '%s'", Setup.SVDRPHostName, *clientName, Option);
|
||||||
Skins.QueueMessage(mtInfo, Option);
|
Skins.QueueMessage(mtInfo, Option);
|
||||||
Reply(250, "Message queued");
|
Reply(250, "Message queued");
|
||||||
}
|
}
|
||||||
@ -1851,7 +1939,7 @@ void cSVDRPServer::CmdMODC(const char *Option)
|
|||||||
Channels->ReNumber();
|
Channels->ReNumber();
|
||||||
Channels->SetModifiedByUser();
|
Channels->SetModifiedByUser();
|
||||||
Channels->SetModified();
|
Channels->SetModified();
|
||||||
isyslog("SVDRP %s < %s modifed channel %d %s", Setup.SVDRPHostName, *connection, Channel->Number(), *Channel->ToText());
|
isyslog("SVDRP %s < %s modifed channel %d %s", Setup.SVDRPHostName, *clientName, Channel->Number(), *Channel->ToText());
|
||||||
Reply(250, "%d %s", Channel->Number(), *Channel->ToText());
|
Reply(250, "%d %s", Channel->Number(), *Channel->ToText());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1891,7 +1979,7 @@ void cSVDRPServer::CmdMODT(const char *Option)
|
|||||||
}
|
}
|
||||||
*Timer = t;
|
*Timer = t;
|
||||||
Timers->SetModified();
|
Timers->SetModified();
|
||||||
isyslog("SVDRP %s < %s modified timer %s (%s)", Setup.SVDRPHostName, *connection, *Timer->ToDescr(), Timer->HasFlags(tfActive) ? "active" : "inactive");
|
isyslog("SVDRP %s < %s modified timer %s (%s)", Setup.SVDRPHostName, *clientName, *Timer->ToDescr(), Timer->HasFlags(tfActive) ? "active" : "inactive");
|
||||||
Reply(250, "%d %s", Timer->Id(), *Timer->ToText(true));
|
Reply(250, "%d %s", Timer->Id(), *Timer->ToText(true));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1935,7 +2023,7 @@ void cSVDRPServer::CmdMOVC(const char *Option)
|
|||||||
else
|
else
|
||||||
cDevice::SetCurrentChannel(CurrentChannel->Number());
|
cDevice::SetCurrentChannel(CurrentChannel->Number());
|
||||||
}
|
}
|
||||||
isyslog("SVDRP %s < %s moved channel %d to %d", Setup.SVDRPHostName, *connection, FromNumber, ToNumber);
|
isyslog("SVDRP %s < %s moved channel %d to %d", Setup.SVDRPHostName, *clientName, FromNumber, ToNumber);
|
||||||
Reply(250,"Channel \"%d\" moved to \"%d\"", From, To);
|
Reply(250,"Channel \"%d\" moved to \"%d\"", From, To);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -2015,7 +2103,7 @@ void cSVDRPServer::CmdNEWC(const char *Option)
|
|||||||
Channels->ReNumber();
|
Channels->ReNumber();
|
||||||
Channels->SetModifiedByUser();
|
Channels->SetModifiedByUser();
|
||||||
Channels->SetModified();
|
Channels->SetModified();
|
||||||
isyslog("SVDRP %s < %s new channel %d %s", Setup.SVDRPHostName, *connection, channel->Number(), *channel->ToText());
|
isyslog("SVDRP %s < %s new channel %d %s", Setup.SVDRPHostName, *clientName, channel->Number(), *channel->ToText());
|
||||||
Reply(250, "%d %s", channel->Number(), *channel->ToText());
|
Reply(250, "%d %s", channel->Number(), *channel->ToText());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -2036,7 +2124,7 @@ void cSVDRPServer::CmdNEWT(const char *Option)
|
|||||||
LOCK_TIMERS_WRITE;
|
LOCK_TIMERS_WRITE;
|
||||||
Timer->ClrFlags(tfRecording);
|
Timer->ClrFlags(tfRecording);
|
||||||
Timers->Add(Timer);
|
Timers->Add(Timer);
|
||||||
isyslog("SVDRP %s < %s added timer %s", Setup.SVDRPHostName, *connection, *Timer->ToDescr());
|
isyslog("SVDRP %s < %s added timer %s", Setup.SVDRPHostName, *clientName, *Timer->ToDescr());
|
||||||
Reply(250, "%d %s", Timer->Id(), *Timer->ToText(true));
|
Reply(250, "%d %s", Timer->Id(), *Timer->ToText(true));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2325,11 +2413,11 @@ void cSVDRPServer::CmdUPDT(const char *Option)
|
|||||||
t->Parse(Option);
|
t->Parse(Option);
|
||||||
delete Timer;
|
delete Timer;
|
||||||
Timer = t;
|
Timer = t;
|
||||||
isyslog("SVDRP %s < %s updated timer %s", Setup.SVDRPHostName, *connection, *Timer->ToDescr());
|
isyslog("SVDRP %s < %s updated timer %s", Setup.SVDRPHostName, *clientName, *Timer->ToDescr());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Timers->Add(Timer);
|
Timers->Add(Timer);
|
||||||
isyslog("SVDRP %s < %s added timer %s", Setup.SVDRPHostName, *connection, *Timer->ToDescr());
|
isyslog("SVDRP %s < %s added timer %s", Setup.SVDRPHostName, *clientName, *Timer->ToDescr());
|
||||||
}
|
}
|
||||||
Reply(250, "%d %s", Timer->Id(), *Timer->ToText(true));
|
Reply(250, "%d %s", Timer->Id(), *Timer->ToText(true));
|
||||||
return;
|
return;
|
||||||
@ -2395,6 +2483,7 @@ void cSVDRPServer::Execute(char *Cmd)
|
|||||||
s = skipspace(s);
|
s = skipspace(s);
|
||||||
if (CMD("CHAN")) CmdCHAN(s);
|
if (CMD("CHAN")) CmdCHAN(s);
|
||||||
else if (CMD("CLRE")) CmdCLRE(s);
|
else if (CMD("CLRE")) CmdCLRE(s);
|
||||||
|
else if (CMD("CONN")) CmdCONN(s);
|
||||||
else if (CMD("DELC")) CmdDELC(s);
|
else if (CMD("DELC")) CmdDELC(s);
|
||||||
else if (CMD("DELR")) CmdDELR(s);
|
else if (CMD("DELR")) CmdDELR(s);
|
||||||
else if (CMD("DELT")) CmdDELT(s);
|
else if (CMD("DELT")) CmdDELT(s);
|
||||||
@ -2445,7 +2534,7 @@ bool cSVDRPServer::Process(void)
|
|||||||
// make sure the string is terminated:
|
// make sure the string is terminated:
|
||||||
cmdLine[numChars] = 0;
|
cmdLine[numChars] = 0;
|
||||||
// showtime!
|
// showtime!
|
||||||
dbgsvdrp("< %s: %s\n", *connection, cmdLine);
|
dbgsvdrp("< S %s: %s\n", *clientName, cmdLine);
|
||||||
Execute(cmdLine);
|
Execute(cmdLine);
|
||||||
numChars = 0;
|
numChars = 0;
|
||||||
if (length > BUFSIZ) {
|
if (length > BUFSIZ) {
|
||||||
@ -2474,7 +2563,7 @@ bool cSVDRPServer::Process(void)
|
|||||||
cmdLine = NewBuffer;
|
cmdLine = NewBuffer;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
esyslog("SVDRP %s < %s ERROR: out of memory", Setup.SVDRPHostName, *connection);
|
esyslog("SVDRP %s < %s ERROR: out of memory", Setup.SVDRPHostName, *clientName);
|
||||||
Close();
|
Close();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2485,12 +2574,12 @@ bool cSVDRPServer::Process(void)
|
|||||||
lastActivity = time(NULL);
|
lastActivity = time(NULL);
|
||||||
}
|
}
|
||||||
else if (r <= 0) {
|
else if (r <= 0) {
|
||||||
isyslog("SVDRP %s < %s lost connection to client", Setup.SVDRPHostName, *connection);
|
isyslog("SVDRP %s < %s lost connection to client", Setup.SVDRPHostName, *clientName);
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Setup.SVDRPTimeout && time(NULL) - lastActivity > Setup.SVDRPTimeout) {
|
if (Setup.SVDRPTimeout && time(NULL) - lastActivity > Setup.SVDRPTimeout) {
|
||||||
isyslog("SVDRP %s < %s timeout on connection", Setup.SVDRPHostName, *connection);
|
isyslog("SVDRP %s < %s timeout on connection", Setup.SVDRPHostName, *clientName);
|
||||||
Close(true, true);
|
Close(true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2524,6 +2613,7 @@ public:
|
|||||||
cSVDRPServerHandler(int TcpPort);
|
cSVDRPServerHandler(int TcpPort);
|
||||||
virtual ~cSVDRPServerHandler();
|
virtual ~cSVDRPServerHandler();
|
||||||
void WaitUntilReady(void);
|
void WaitUntilReady(void);
|
||||||
|
cSVDRPServer *GetServerForClient(const char *ClientName);
|
||||||
};
|
};
|
||||||
|
|
||||||
static cSVDRPServerHandler *SVDRPServerHandler = NULL;
|
static cSVDRPServerHandler *SVDRPServerHandler = NULL;
|
||||||
@ -2565,7 +2655,7 @@ void cSVDRPServerHandler::HandleServerConnection(void)
|
|||||||
{
|
{
|
||||||
int NewSocket = tcpSocket.Accept();
|
int NewSocket = tcpSocket.Accept();
|
||||||
if (NewSocket >= 0)
|
if (NewSocket >= 0)
|
||||||
serverConnections.Append(new cSVDRPServer(NewSocket, tcpSocket.LastIpAddress()->Connection()));
|
serverConnections.Append(new cSVDRPServer(NewSocket, tcpSocket.LastIpAddress()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSVDRPServerHandler::Action(void)
|
void cSVDRPServerHandler::Action(void)
|
||||||
@ -2584,6 +2674,16 @@ void cSVDRPServerHandler::Action(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cSVDRPServer *cSVDRPServerHandler::GetServerForClient(const char *ClientName)
|
||||||
|
{
|
||||||
|
cMutexLock MutexLock(&mutex);
|
||||||
|
for (int i = 0; i < serverConnections.Size(); i++) {
|
||||||
|
if (serverConnections[i]->ClientName() && strcmp(serverConnections[i]->ClientName(), ClientName) == 0)
|
||||||
|
return serverConnections[i];
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// --- SVDRP Handler ---------------------------------------------------------
|
// --- SVDRP Handler ---------------------------------------------------------
|
||||||
|
|
||||||
static cMutex SVDRPHandlerMutex;
|
static cMutex SVDRPHandlerMutex;
|
||||||
@ -2621,13 +2721,6 @@ void StopSVDRPClientHandler(void)
|
|||||||
SVDRPClientHandler = NULL;
|
SVDRPClientHandler = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendSVDRPDiscover(const char *Address)
|
|
||||||
{
|
|
||||||
cMutexLock MutexLock(&SVDRPHandlerMutex);
|
|
||||||
if (SVDRPClientHandler)
|
|
||||||
SVDRPClientHandler->SendDiscover(Address);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GetSVDRPServerNames(cStringList *ServerNames, eSvdrpFetchFlags FetchFlag)
|
bool GetSVDRPServerNames(cStringList *ServerNames, eSvdrpFetchFlags FetchFlag)
|
||||||
{
|
{
|
||||||
cMutexLock MutexLock(&SVDRPHandlerMutex);
|
cMutexLock MutexLock(&SVDRPHandlerMutex);
|
||||||
|
3
svdrp.h
3
svdrp.h
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: svdrp.h 4.7 2017/06/30 09:49:39 kls Exp $
|
* $Id: svdrp.h 4.8 2018/02/19 12:36:35 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __SVDRP_H
|
#ifndef __SVDRP_H
|
||||||
@ -29,7 +29,6 @@ void StartSVDRPServerHandler(void);
|
|||||||
void StartSVDRPClientHandler(void);
|
void StartSVDRPClientHandler(void);
|
||||||
void StopSVDRPServerHandler(void);
|
void StopSVDRPServerHandler(void);
|
||||||
void StopSVDRPClientHandler(void);
|
void StopSVDRPClientHandler(void);
|
||||||
void SendSVDRPDiscover(const char *Address = NULL);
|
|
||||||
bool GetSVDRPServerNames(cStringList *ServerNames, eSvdrpFetchFlags FetchFlag = sffNone);
|
bool GetSVDRPServerNames(cStringList *ServerNames, eSvdrpFetchFlags FetchFlag = sffNone);
|
||||||
///< Gets a list of all available VDRs this VDR is connected to via SVDRP,
|
///< Gets a list of all available VDRs this VDR is connected to via SVDRP,
|
||||||
///< and stores it in the given ServerNames list. The list is cleared
|
///< and stores it in the given ServerNames list. The list is cleared
|
||||||
|
Loading…
x
Reference in New Issue
Block a user