diff --git a/README b/README index 49b0b38..1c3b610 100644 --- a/README +++ b/README @@ -56,6 +56,11 @@ vdr -P 'satip -s ||;...' vdr -P 'satip -s 192.168.0.1|DVBS2-2,DVBT2-2|Octo1' vdr -P 'satip -s 192.168.0.1|DVBS2-4|Octo1;192.168.0.2|DVBT2-4|Octo2' +The plugin accepts a "--portrange" (-p) command-line parameter, that can +be used to manually specify the RTP & RTCP port range and therefore +enables using the plugin through a NAT (e.g. Docker bridged network). +A minimum of 2 ports per device is required. + SAT>IP satellite positions (aka. signal sources) shall be defined via sources.conf. If the source description begins with a number, it's used as SAT>IP signal source selection parameter. A special number zero can diff --git a/config.c b/config.c index 050453c..2243aaa 100644 --- a/config.c +++ b/config.c @@ -17,6 +17,8 @@ cSatipConfig::cSatipConfig(void) ciExtensionM(0), eitScanM(1), useBytesM(1), + portRangeStartM(0), + portRangeStopM(0), detachedModeM(false), disableServerQuirksM(false), useSingleModelServersM(false) diff --git a/config.h b/config.h index b7745cf..b11b1d8 100644 --- a/config.h +++ b/config.h @@ -19,6 +19,8 @@ private: unsigned int ciExtensionM; unsigned int eitScanM; unsigned int useBytesM; + unsigned int portRangeStartM; + unsigned int portRangeStopM; bool detachedModeM; bool disableServerQuirksM; bool useSingleModelServersM; @@ -74,6 +76,8 @@ public: int GetDisabledSources(unsigned int indexP) const; unsigned int GetDisabledFiltersCount(void) const; int GetDisabledFilters(unsigned int indexP) const; + unsigned int GetPortRangeStart(void) const { return portRangeStartM; } + unsigned int GetPortRangeStop(void) const { return portRangeStopM; } void SetOperatingMode(unsigned int operatingModeP) { operatingModeM = operatingModeP; } void SetTraceMode(unsigned int modeP) { traceModeM = (modeP & eTraceModeMask); } @@ -86,6 +90,8 @@ public: void SetUseSingleModelServers(bool onOffP) { useSingleModelServersM = onOffP; } void SetDisabledSources(unsigned int indexP, int sourceP); void SetDisabledFilters(unsigned int indexP, int numberP); + void SetPortRangeStart(unsigned int rangeStartP) { portRangeStartM = rangeStartP; } + void SetPortRangeStop(unsigned int rangeStopP) { portRangeStopM = rangeStopP; } }; extern cSatipConfig SatipConfig; diff --git a/satip.c b/satip.c index 3453c48..35a92fe 100644 --- a/satip.c +++ b/satip.c @@ -35,6 +35,7 @@ private: unsigned int deviceCountM; cSatipDiscoverServers *serversM; void ParseServer(const char *paramP); + void ParsePortRange(const char *paramP); int ParseCicams(const char *valueP, int *cicamsP); int ParseSources(const char *valueP, int *sourcesP); int ParseFilters(const char *valueP, int *filtersP); @@ -87,7 +88,9 @@ const char *cPluginSatip::CommandLineHelp(void) " define hard-coded SAT>IP server(s)\n" " -D, --detach set the detached mode on\n" " -S, --single set the single model server mode on\n" - " -n, --noquirks disable all the server quirks\n"; + " -n, --noquirks disable all the server quirks\n" + " -p, --portrange=- set a range of ports used for the RT[C]P server\n" + " a minimum of 2 ports per device is required.\n"; } bool cPluginSatip::ProcessArgs(int argc, char *argv[]) @@ -98,6 +101,7 @@ bool cPluginSatip::ProcessArgs(int argc, char *argv[]) { "devices", required_argument, NULL, 'd' }, { "trace", required_argument, NULL, 't' }, { "server", required_argument, NULL, 's' }, + { "portrange",required_argument, NULL, 'p' }, { "detach", no_argument, NULL, 'D' }, { "single", no_argument, NULL, 'S' }, { "noquirks", no_argument, NULL, 'n' }, @@ -105,8 +109,9 @@ bool cPluginSatip::ProcessArgs(int argc, char *argv[]) }; cString server; + cString portrange; int c; - while ((c = getopt_long(argc, argv, "d:t:s:DSn", long_options, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "d:t:s:p:DSn", long_options, NULL)) != -1) { switch (c) { case 'd': deviceCountM = strtol(optarg, NULL, 0); @@ -126,10 +131,15 @@ bool cPluginSatip::ProcessArgs(int argc, char *argv[]) case 'n': SatipConfig.SetDisableServerQuirks(true); break; + case 'p': + portrange = optarg; + break; default: return false; } } + if (!isempty(*portrange)) + ParsePortRange(portrange); // this must be done after all parameters are parsed if (!isempty(*server)) ParseServer(*server); @@ -255,6 +265,32 @@ void cPluginSatip::ParseServer(const char *paramP) FREE_POINTER(p); } +void cPluginSatip::ParsePortRange(const char *paramP) +{ + char *s, *p = skipspace(paramP); + char *r = strtok_r(p, "-", &s); + unsigned int rangeStart = 0; + unsigned int rangeStop = 0; + if (r) { + rangeStart = strtol(r, NULL, 0); + r = strtok_r(NULL, "-", &s); + } + if (r) + rangeStop = strtol(r, NULL, 0); + else { + error("Port range argument not valid '%s'", paramP); + rangeStart = 0; + rangeStop = 0; + } + if (rangeStop - rangeStart + 1 < deviceCountM * 2) { + error("The given port range is to small: %d < %d!", rangeStop - rangeStart + 1, deviceCountM * 2); + rangeStart = 0; + rangeStop = 0; + } + SatipConfig.SetPortRangeStart(rangeStart); + SatipConfig.SetPortRangeStop(rangeStop); +} + int cPluginSatip::ParseCicams(const char *valueP, int *cicamsP) { debug1("%s (%s,)", __PRETTY_FUNCTION__, valueP); diff --git a/socket.c b/socket.c index 29c2602..35bc035 100644 --- a/socket.c +++ b/socket.c @@ -34,7 +34,7 @@ cSatipSocket::~cSatipSocket() Close(); } -bool cSatipSocket::Open(const int portP) +bool cSatipSocket::Open(const int portP, const bool reuseAddrP) { // Bind to the socket if it is not active already if (socketDescM < 0) { @@ -46,7 +46,7 @@ bool cSatipSocket::Open(const int portP) ERROR_IF_FUNC(fcntl(socketDescM, F_SETFL, O_NONBLOCK), "fcntl(O_NONBLOCK)", Close(), return false); // Allow multiple sockets to use the same PORT number - int yes = 1; + int yes = reuseAddrP; ERROR_IF_FUNC(setsockopt(socketDescM, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0, "setsockopt(SO_REUSEADDR)", Close(), return false); // Bind socket diff --git a/socket.h b/socket.h index f9a93d8..79bc991 100644 --- a/socket.h +++ b/socket.h @@ -19,7 +19,7 @@ private: public: cSatipSocket(); virtual ~cSatipSocket(); - bool Open(const int portP = 0); + bool Open(const int portP = 0, const bool reuseAddrP = false); virtual void Close(void); int Fd(void) { return socketDescM; } int Port(void) { return socketPortM; } diff --git a/tuner.c b/tuner.c index c12a19e..fc47b51 100644 --- a/tuner.c +++ b/tuner.c @@ -50,12 +50,15 @@ cSatipTuner::cSatipTuner(cSatipDeviceIf &deviceP, unsigned int packetLenP) debug1("%s (, %d) [device %d]", __PRETTY_FUNCTION__, packetLenP, deviceIdM); // Open sockets - int i = 100; + int i = SatipConfig.GetPortRangeStart() ? SatipConfig.GetPortRangeStop() - SatipConfig.GetPortRangeStart() - 1 : 100; + int port = SatipConfig.GetPortRangeStart(); while (i-- > 0) { - if (rtpM.Open(0) && rtcpM.Open(rtpM.Port() + 1)) + if (rtpM.Open(port) && rtcpM.Open(rtpM.Port() + 1)) break; rtpM.Close(); rtcpM.Close(); + if (SatipConfig.GetPortRangeStart()) + ++port; } if ((rtpM.Port() <= 0) || (rtcpM.Port() <= 0)) { error("Cannot open required RTP/RTCP ports [device %d]", deviceIdM);