From 4e3325b7f7e30d1013798d74b8e7e0b8471813b1 Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Tue, 8 Sep 2015 11:08:06 +0200 Subject: [PATCH] Implemented setup options for SVDRP peering --- HISTORY | 6 ++++- MANUAL | 9 ++++++++ config.c | 10 ++++++++- config.h | 5 ++++- menu.c | 49 +++++++++++++++++++++++++++++++++++++++- menuitems.c | 22 +++++++++++++++++- menuitems.h | 14 +++++++++++- svdrp.c | 65 ++++++++++++++++++++++++++++++----------------------- svdrp.h | 10 +++++---- timers.c | 6 ++--- tools.c | 16 ++++++++++++- tools.h | 4 +++- vdr.c | 10 ++++++--- 13 files changed, 180 insertions(+), 46 deletions(-) diff --git a/HISTORY b/HISTORY index b662cf0f..aa13be2c 100644 --- a/HISTORY +++ b/HISTORY @@ -8596,7 +8596,7 @@ Video Disk Recorder Revision History - Bumped all version numbers to 2.2.0. - Official release. -2015-09-06: Version 2.3.1 +2015-09-08: Version 2.3.1 - The new function cOsd::MaxPixmapSize() can be called to determine the maximum size a cPixmap may have on the current OSD. The 'osddemo' example has been modified @@ -8791,3 +8791,7 @@ Video Disk Recorder Revision History gaps in the sequence, in case timers have been deleted. - The Timers menu now displays the name of the remote VDR in front of the timer's file name, if this is a remote timer. +- The new options "Setup/Miscellaneous/SVDRP peering", ".../SVDRP host name" and + ".../SVDRP default host" can be used to configure automatic peering between VDRs + in the same network. Peering is disabled by default and can be enabled by setting + "SVDRP peering" to "yes". diff --git a/MANUAL b/MANUAL index 5a3e7fcb..e956c29e 100644 --- a/MANUAL +++ b/MANUAL @@ -1071,6 +1071,15 @@ Version 2.2 connection after which the connection is automatically closed. Default is 300, a value of 0 means no timeout. + SVDRP peering = no Activates automatic connections between VDRs in the same + network. + + SVDRP host name The name of this VDR, which is used when connecting VDRs + via SVDRP. By default, the machine's host name is used. + + SVDRP default host The name of the VDR to be used by default when creating a + new timer. + Zap timeout = 3 The time (in seconds) until a channel counts as "previous" for switching with '0' diff --git a/config.c b/config.c index cfeda521..902775bb 100644 --- a/config.c +++ b/config.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: config.c 4.1 2015/04/18 13:09:31 kls Exp $ + * $Id: config.c 4.2 2015/09/06 13:17:19 kls Exp $ */ #include "config.h" @@ -412,6 +412,9 @@ cSetup::cSetup(void) EPGBugfixLevel = 3; EPGLinger = 0; SVDRPTimeout = 300; + SVDRPPeering = 0; + strn0cpy(SVDRPHostName, GetHostName(), sizeof(SVDRPHostName)); + strcpy(SVDRPDefaultHost, ""); ZapTimeout = 3; ChannelEntryTimeout = 1000; RcRepeatDelay = 300; @@ -635,6 +638,9 @@ bool cSetup::Parse(const char *Name, const char *Value) else if (!strcasecmp(Name, "EPGBugfixLevel")) EPGBugfixLevel = atoi(Value); else if (!strcasecmp(Name, "EPGLinger")) EPGLinger = atoi(Value); else if (!strcasecmp(Name, "SVDRPTimeout")) SVDRPTimeout = atoi(Value); + else if (!strcasecmp(Name, "SVDRPPeering")) SVDRPPeering = atoi(Value); + else if (!strcasecmp(Name, "SVDRPHostName")) strn0cpy(SVDRPHostName, Value, sizeof(SVDRPHostName)); + else if (!strcasecmp(Name, "SVDRPdefaultHost")) strn0cpy(SVDRPDefaultHost, Value, sizeof(SVDRPDefaultHost)); else if (!strcasecmp(Name, "ZapTimeout")) ZapTimeout = atoi(Value); else if (!strcasecmp(Name, "ChannelEntryTimeout")) ChannelEntryTimeout= atoi(Value); else if (!strcasecmp(Name, "RcRepeatDelay")) RcRepeatDelay = atoi(Value); @@ -762,6 +768,8 @@ bool cSetup::Save(void) Store("EPGBugfixLevel", EPGBugfixLevel); Store("EPGLinger", EPGLinger); Store("SVDRPTimeout", SVDRPTimeout); + Store("SVDRPPeering", SVDRPPeering); + Store("SVDRPDefaultHost", SVDRPDefaultHost); Store("ZapTimeout", ZapTimeout); Store("ChannelEntryTimeout",ChannelEntryTimeout); Store("RcRepeatDelay", RcRepeatDelay); diff --git a/config.h b/config.h index 2978d7d6..299f6aba 100644 --- a/config.h +++ b/config.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: config.h 4.3 2015/08/09 09:17:46 kls Exp $ + * $Id: config.h 4.4 2015/09/06 09:50:13 kls Exp $ */ #ifndef __CONFIG_H @@ -288,6 +288,9 @@ public: int EPGBugfixLevel; int EPGLinger; int SVDRPTimeout; + int SVDRPPeering; + char SVDRPHostName[HOST_NAME_MAX]; + char SVDRPDefaultHost[HOST_NAME_MAX]; int ZapTimeout; int ChannelEntryTimeout; int RcRepeatDelay; diff --git a/menu.c b/menu.c index 999144ec..eb49c665 100644 --- a/menu.c +++ b/menu.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: menu.c 4.4 2015/09/06 09:28:24 kls Exp $ + * $Id: menu.c 4.5 2015/09/08 11:02:52 kls Exp $ */ #include "menu.h" @@ -27,6 +27,7 @@ #include "sourceparams.h" #include "sources.h" #include "status.h" +#include "svdrp.h" #include "themes.h" #include "timers.h" #include "transfer.h" @@ -3897,17 +3898,36 @@ void cMenuSetupReplay::Store(void) // --- cMenuSetupMisc -------------------------------------------------------- class cMenuSetupMisc : public cMenuSetupBase { +private: + cStringList svdrpServerNames; + void Set(void); public: cMenuSetupMisc(void); + virtual eOSState ProcessKey(eKeys Key); }; cMenuSetupMisc::cMenuSetupMisc(void) { SetMenuCategory(mcSetupMisc); SetSection(tr("Miscellaneous")); + Set(); +} + +void cMenuSetupMisc::Set(void) +{ + int current = Current(); + Clear(); Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$Min. event timeout (min)"), &data.MinEventTimeout)); Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$Min. user inactivity (min)"), &data.MinUserInactivity)); Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$SVDRP timeout (s)"), &data.SVDRPTimeout)); + Add(new cMenuEditBoolItem(tr("Setup.Miscellaneous$SVDRP peering"), &data.SVDRPPeering)); + if (data.SVDRPPeering) { + Add(new cMenuEditStrItem( tr("Setup.Miscellaneous$SVDRP host name"), data.SVDRPHostName, sizeof(data.SVDRPHostName))); + if (GetSVDRPServerNames(&svdrpServerNames)) { + svdrpServerNames.Sort(true); + Add(new cMenuEditStrlItem(tr("Setup.Miscellaneous$SVDRP default host"), data.SVDRPDefaultHost, sizeof(data.SVDRPDefaultHost), &svdrpServerNames)); + } + } Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$Zap timeout (s)"), &data.ZapTimeout)); Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$Channel entry timeout (ms)"), &data.ChannelEntryTimeout, 0)); Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$Remote control repeat delay (ms)"), &data.RcRepeatDelay, 0)); @@ -3919,6 +3939,33 @@ cMenuSetupMisc::cMenuSetupMisc(void) Add(new cMenuEditBoolItem(tr("Setup.Miscellaneous$Channels wrap"), &data.ChannelsWrap)); Add(new cMenuEditBoolItem(tr("Setup.Miscellaneous$Show channel names with source"), &data.ShowChannelNamesWithSource)); Add(new cMenuEditBoolItem(tr("Setup.Miscellaneous$Emergency exit"), &data.EmergencyExit)); + SetCurrent(Get(current)); + Display(); +} + +eOSState cMenuSetupMisc::ProcessKey(eKeys Key) +{ + bool OldSVDRPPeering = data.SVDRPPeering; + bool ModifiedSVDRPSettings = false; + if (Key == kOk) + ModifiedSVDRPSettings = data.SVDRPPeering != Setup.SVDRPPeering | strcmp(data.SVDRPHostName, Setup.SVDRPHostName); + eOSState state = cMenuSetupBase::ProcessKey(Key); + if (data.SVDRPPeering != OldSVDRPPeering) + Set(); + if (ModifiedSVDRPSettings) { + StopSVDRPClientHandler(); + StopSVDRPServerHandler(); + StartSVDRPServerHandler(); + if (data.SVDRPPeering) + StartSVDRPClientHandler(); + else { + LOCK_TIMERS_WRITE; + Timers->SetExplicitModify(); + if (Timers->DelRemoteTimers()) + Timers->SetModified(); + } + } + return state; } // --- cMenuSetupPluginItem -------------------------------------------------- diff --git a/menuitems.c b/menuitems.c index c07ad2a7..659c1a58 100644 --- a/menuitems.c +++ b/menuitems.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: menuitems.c 4.1 2015/07/18 10:38:31 kls Exp $ + * $Id: menuitems.c 4.2 2015/09/08 10:25:23 kls Exp $ */ #include "menuitems.h" @@ -774,6 +774,26 @@ void cMenuEditStraItem::Set(void) SetValue(strings[*value]); } +// --- cMenuEditStrlItem ----------------------------------------------------- + +cMenuEditStrlItem::cMenuEditStrlItem(const char *Name, char *Value, int Length, const cStringList *Strings) +:cMenuEditIntItem(Name, &index, 0, Strings->Size() - 1) +{ + strings = Strings; + value = Value; + length = Length; + index = strings->Find(value); + if (index < 0) + index = 0; + Set(); +} + +void cMenuEditStrlItem::Set(void) +{ + strn0cpy(value, strings->At(index), length); + SetValue(value); +} + // --- cMenuEditChanItem ----------------------------------------------------- cMenuEditChanItem::cMenuEditChanItem(const char *Name, int *Value, const char *NoneString) diff --git a/menuitems.h b/menuitems.h index 2a30b465..44f6fec5 100644 --- a/menuitems.h +++ b/menuitems.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: menuitems.h 3.1 2013/05/24 10:19:55 kls Exp $ + * $Id: menuitems.h 4.1 2015/09/06 10:38:37 kls Exp $ */ #ifndef __MENUITEMS_H @@ -146,6 +146,18 @@ public: cMenuEditStraItem(const char *Name, int *Value, int NumStrings, const char * const *Strings); }; +class cMenuEditStrlItem : public cMenuEditIntItem { +private: + const cStringList *strings; + int index; + char *value; + int length; +protected: + virtual void Set(void); +public: + cMenuEditStrlItem(const char *Name, char *Value, int Length, const cStringList *Strings); + }; + class cMenuEditChanItem : public cMenuEditIntItem { protected: const char *noneString; diff --git a/svdrp.c b/svdrp.c index 4e23f978..65be32ad 100644 --- a/svdrp.c +++ b/svdrp.c @@ -10,7 +10,7 @@ * and interact with the Video Disk Recorder - or write a full featured * graphical interface that sits on top of an SVDRP connection. * - * $Id: svdrp.c 4.5 2015/09/06 09:25:16 kls Exp $ + * $Id: svdrp.c 4.6 2015/09/08 11:08:06 kls Exp $ */ #include "svdrp.h" @@ -45,17 +45,8 @@ static bool DumpSVDRPDataTransfer = false; #define dbgsvdrp(a...) if (DumpSVDRPDataTransfer) fprintf(stderr, a) -const char *SVDRPHostName(void) -{ - static char buffer[HOST_NAME_MAX] = ""; - if (!*buffer) { - if (gethostname(buffer, sizeof(buffer)) < 0) { - LOG_ERROR; - strcpy(buffer, "vdr"); - } - } - return buffer; -} +static int SVDRPTcpPort = 0; +static int SVDRPUdpPort = 0; // --- cIpAddress ------------------------------------------------------------ @@ -375,7 +366,6 @@ cSVDRPClient::cSVDRPClient(const char *Address, int Port, const char *ServerName if (file.Open(socket.Socket())) { SVDRPClientPoller.Add(file, false); dsyslog("SVDRP > %s client created for '%s'", ipAddress.Connection(), *serverName); - SendSVDRPDiscover(Address); return; } } @@ -510,8 +500,8 @@ bool cSVDRPClient::HasFetchFlag(eSvdrpFetchFlags Flag) class cSVDRPClientHandler : public cThread { private: cMutex mutex; - cSocket udpSocket; int tcpPort; + cSocket udpSocket; cVector clientConnections; void HandleClientConnection(void); void ProcessConnections(void); @@ -519,7 +509,7 @@ private: protected: virtual void Action(void); public: - cSVDRPClientHandler(int UdpPort, int TcpPort); + cSVDRPClientHandler(int TcpPort, int UdpPort); virtual ~cSVDRPClientHandler(); void SendDiscover(const char *Address = NULL); bool Execute(const char *ServerName, const char *Command, cStringList *Response); @@ -529,7 +519,7 @@ public: static cSVDRPClientHandler *SVDRPClientHandler = NULL; -cSVDRPClientHandler::cSVDRPClientHandler(int UdpPort, int TcpPort) +cSVDRPClientHandler::cSVDRPClientHandler(int TcpPort, int UdpPort) :cThread("SVDRP client handler", true) ,udpSocket(UdpPort, false) { @@ -555,7 +545,7 @@ cSVDRPClient *cSVDRPClientHandler::GetClientForServer(const char *ServerName) void cSVDRPClientHandler::SendDiscover(const char *Address) { cMutexLock MutexLock(&mutex); - cString Dgram = cString::sprintf("SVDRP:discover name:%s port:%d vdrversion:%d apiversion:%d timeout:%d", SVDRPHostName(), tcpPort, VDRVERSNUM, APIVERSNUM, Setup.SVDRPTimeout); + cString Dgram = cString::sprintf("SVDRP:discover name:%s port:%d vdrversion:%d apiversion:%d timeout:%d", Setup.SVDRPHostName, tcpPort, VDRVERSNUM, APIVERSNUM, Setup.SVDRPTimeout); udpSocket.SendDgram(Dgram, udpSocket.Port(), Address); } @@ -589,8 +579,11 @@ void cSVDRPClientHandler::HandleClientConnection(void) cString t = strgetval(NewDiscover, "timeout", ':'); if (*t) { int Timeout = atoi(t); - if (Timeout > 10) // don't let it get too small - clientConnections.Append(new cSVDRPClient(udpSocket.LastIpAddress()->Address(), Port, ServerName, Timeout)); + 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 ERROR: invalid timeout (%d)", udpSocket.LastIpAddress()->Connection(), Timeout); } @@ -999,7 +992,7 @@ cSVDRPServer::cSVDRPServer(int Socket, const char *Connection) lastActivity = time(NULL); if (file.Open(socket)) { time_t now = time(NULL); - Reply(220, "%s SVDRP VideoDiskRecorder %s; %s; %s", 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); } dsyslog("SVDRP < %s server created", *connection); @@ -1016,7 +1009,7 @@ void cSVDRPServer::Close(bool SendReply, bool Timeout) { if (file.IsOpen()) { if (SendReply) { - Reply(221, "%s closing connection%s", SVDRPHostName(), Timeout ? " (timeout)" : ""); + Reply(221, "%s closing connection%s", Setup.SVDRPHostName, Timeout ? " (timeout)" : ""); } isyslog("SVDRP < %s connection closed", *connection); SVDRPServerPoller.Del(file, false); @@ -2044,7 +2037,7 @@ void cSVDRPServer::CmdNEXT(const char *Option) void cSVDRPServer::CmdPING(const char *Option) { - Reply(250, "%s is alive", SVDRPHostName()); + Reply(250, "%s is alive", Setup.SVDRPHostName); } void cSVDRPServer::CmdPLAY(const char *Option) @@ -2434,6 +2427,12 @@ bool cSVDRPServer::Process(void) return file.IsOpen(); } +void SetSVDRPPorts(int TcpPort, int UdpPort) +{ + SVDRPTcpPort = TcpPort; + SVDRPUdpPort = UdpPort; +} + void SetSVDRPGrabImageDir(const char *GrabImageDir) { grabImageDir = GrabImageDir; @@ -2519,25 +2518,35 @@ void cSVDRPServerHandler::Action(void) static cMutex SVDRPHandlerMutex; -void StartSVDRPHandler(int TcpPort, int UdpPort) +void StartSVDRPServerHandler(void) { cMutexLock MutexLock(&SVDRPHandlerMutex); - if (TcpPort && !SVDRPServerHandler) { - SVDRPServerHandler = new cSVDRPServerHandler(TcpPort); + if (SVDRPTcpPort && !SVDRPServerHandler) { + SVDRPServerHandler = new cSVDRPServerHandler(SVDRPTcpPort); SVDRPServerHandler->Start(); SVDRPServerHandler->WaitUntilReady(); } - if (UdpPort && !SVDRPClientHandler) { - SVDRPClientHandler = new cSVDRPClientHandler(UdpPort, TcpPort); +} + +void StartSVDRPClientHandler(void) +{ + cMutexLock MutexLock(&SVDRPHandlerMutex); + if (SVDRPTcpPort && SVDRPUdpPort && !SVDRPClientHandler) { + SVDRPClientHandler = new cSVDRPClientHandler(SVDRPTcpPort, SVDRPUdpPort); SVDRPClientHandler->Start(); } } -void StopSVDRPHandler(void) +void StopSVDRPServerHandler(void) { cMutexLock MutexLock(&SVDRPHandlerMutex); delete SVDRPServerHandler; SVDRPServerHandler = NULL; +} + +void StopSVDRPClientHandler(void) +{ + cMutexLock MutexLock(&SVDRPHandlerMutex); delete SVDRPClientHandler; SVDRPClientHandler = NULL; } diff --git a/svdrp.h b/svdrp.h index fd9d5fb5..10c0c053 100644 --- a/svdrp.h +++ b/svdrp.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: svdrp.h 4.3 2015/09/01 10:34:09 kls Exp $ + * $Id: svdrp.h 4.4 2015/09/06 12:39:24 kls Exp $ */ #ifndef __SVDRP_H @@ -57,10 +57,12 @@ enum eSvdrpFetchFlags { sffTimers = 0b0001, }; -const char *SVDRPHostName(void); +void SetSVDRPPorts(int TcpPort, int UdpPort); void SetSVDRPGrabImageDir(const char *GrabImageDir); -void StartSVDRPHandler(int TcpPort, int UdpPort); -void StopSVDRPHandler(void); +void StartSVDRPServerHandler(void); +void StartSVDRPClientHandler(void); +void StopSVDRPServerHandler(void); +void StopSVDRPClientHandler(void); void SendSVDRPDiscover(const char *Address = NULL); bool GetSVDRPServerNames(cStringList *ServerNames, eSvdrpFetchFlags FetchFlag = sffNone); ///< Gets a list of all available VDRs this VDR is connected to via SVDRP, diff --git a/timers.c b/timers.c index 0e5075fc..77e9096d 100644 --- a/timers.c +++ b/timers.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: timers.c 4.2 2015/09/05 14:42:50 kls Exp $ + * $Id: timers.c 4.3 2015/09/08 10:01:02 kls Exp $ */ #include "timers.h" @@ -939,9 +939,9 @@ bool cTimers::DelRemoteTimers(const char *ServerName) void cTimers::TriggerRemoteTimerPoll(const char *ServerName) { if (ServerName) { - cSVDRPCommand Cmd(ServerName, cString::sprintf("POLL %s TIMERS", SVDRPHostName())); + cSVDRPCommand Cmd(ServerName, cString::sprintf("POLL %s TIMERS", Setup.SVDRPHostName)); if (!Cmd.Execute()) - esyslog("ERROR: can't send 'POLL %s TIMERS' to '%s'", SVDRPHostName(), ServerName); + esyslog("ERROR: can't send 'POLL %s TIMERS' to '%s'", Setup.SVDRPHostName, ServerName); } else { cStringList ServerNames; diff --git a/tools.c b/tools.c index 005e4027..2d5ff5e2 100644 --- a/tools.c +++ b/tools.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: tools.c 4.2 2015/08/29 12:11:20 kls Exp $ + * $Id: tools.c 4.3 2015/09/06 10:47:05 kls Exp $ */ #include "tools.h" @@ -1322,6 +1322,20 @@ uchar *RgbToJpeg(uchar *Mem, int Width, int Height, int &Size, int Quality) return jcd.mem; } +// --- GetHostName ----------------------------------------------------------- + +const char *GetHostName(void) +{ + static char buffer[HOST_NAME_MAX] = ""; + if (!*buffer) { + if (gethostname(buffer, sizeof(buffer)) < 0) { + LOG_ERROR; + strcpy(buffer, "vdr"); + } + } + return buffer; +} + // --- cBase64Encoder -------------------------------------------------------- const char *cBase64Encoder::b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; diff --git a/tools.h b/tools.h index a4de535b..1563db92 100644 --- a/tools.h +++ b/tools.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: tools.h 4.2 2015/08/29 11:45:51 kls Exp $ + * $Id: tools.h 4.3 2015/09/06 10:45:54 kls Exp $ */ #ifndef __TOOLS_H @@ -293,6 +293,8 @@ uchar *RgbToJpeg(uchar *Mem, int Width, int Height, int &Size, int Quality = 100 ///< resulting image, where 100 is "best". The caller takes ownership of ///< the result and has to delete it once it is no longer needed. ///< The result may be NULL in case of an error. +const char *GetHostName(void); + ///< Gets the host name of this machine. class cBase64Encoder { private: diff --git a/vdr.c b/vdr.c index a09ec086..68c8a9e1 100644 --- a/vdr.c +++ b/vdr.c @@ -22,7 +22,7 @@ * * The project's page is at http://www.tvdr.de * - * $Id: vdr.c 4.5 2015/09/01 10:33:04 kls Exp $ + * $Id: vdr.c 4.6 2015/09/08 10:00:46 kls Exp $ */ #include @@ -919,7 +919,10 @@ int main(int argc, char *argv[]) // SVDRP: - StartSVDRPHandler(SVDRPport, DEFAULTSVDRPPORT); + SetSVDRPPorts(SVDRPport, DEFAULTSVDRPPORT); + StartSVDRPServerHandler(); + if (Setup.SVDRPPeering) + StartSVDRPClientHandler(); // Main program loop: @@ -1524,7 +1527,8 @@ Exit: signal(SIGPIPE, SIG_DFL); signal(SIGALRM, SIG_DFL); - StopSVDRPHandler(); + StopSVDRPClientHandler(); + StopSVDRPServerHandler(); PluginManager.StopPlugins(); cRecordControls::Shutdown(); RecordingsHandler.DelAll();